Commit | Line | Data |
---|---|---|
2ba45a60 DM |
1 | /* |
2 | * MXF | |
3 | * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com> | |
4 | * | |
5 | * This file is part of FFmpeg. | |
6 | * | |
7 | * FFmpeg is free software; you can redistribute it and/or | |
8 | * modify it under the terms of the GNU Lesser General Public | |
9 | * License as published by the Free Software Foundation; either | |
10 | * version 2.1 of the License, or (at your option) any later version. | |
11 | * | |
12 | * FFmpeg is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * Lesser General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU Lesser General Public | |
18 | * License along with FFmpeg; if not, write to the Free Software | |
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
20 | */ | |
21 | ||
22 | #include "libavutil/common.h" | |
23 | #include "mxf.h" | |
24 | ||
25 | /** | |
26 | * SMPTE RP224 http://www.smpte-ra.org/mdd/index.html | |
27 | */ | |
28 | const MXFCodecUL ff_mxf_data_definition_uls[] = { | |
29 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x02,0x01,0x00,0x00,0x00 }, 13, AVMEDIA_TYPE_VIDEO }, | |
30 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x02,0x02,0x00,0x00,0x00 }, 13, AVMEDIA_TYPE_AUDIO }, | |
31 | { { 0x80,0x7D,0x00,0x60,0x08,0x14,0x3E,0x6F,0x6F,0x3C,0x8C,0xE1,0x6C,0xEF,0x11,0xD2 }, 16, AVMEDIA_TYPE_VIDEO }, /* LegacyPicture Avid Media Composer MXF */ | |
32 | { { 0x80,0x7D,0x00,0x60,0x08,0x14,0x3E,0x6F,0x78,0xE1,0xEB,0xE1,0x6C,0xEF,0x11,0xD2 }, 16, AVMEDIA_TYPE_AUDIO }, /* LegacySound Avid Media Composer MXF */ | |
33 | { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AVMEDIA_TYPE_DATA }, | |
34 | }; | |
35 | ||
36 | const MXFCodecUL ff_mxf_codec_uls[] = { | |
37 | /* PictureEssenceCoding */ | |
38 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MP@ML Long GoP */ | |
39 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x01 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* D-10 50Mbps PAL */ | |
40 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x03,0x03,0x00 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* MP@HL Long GoP */ | |
41 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, 14, AV_CODEC_ID_MPEG2VIDEO }, /* 422P@HL I-Frame */ | |
42 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x20,0x02,0x03 }, 14, AV_CODEC_ID_MPEG4 }, /* XDCAM proxy_pal030926.mxf */ | |
43 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x02,0x00 }, 13, AV_CODEC_ID_DVVIDEO }, /* DV25 IEC PAL */ | |
44 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14, AV_CODEC_ID_JPEG2000 }, /* JPEG2000 Codestream */ | |
45 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13, AV_CODEC_ID_RAWVIDEO }, /* Uncompressed */ | |
46 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x00 }, 15, AV_CODEC_ID_RAWVIDEO }, /* Uncompressed 422 8-bit */ | |
47 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x71,0x00,0x00,0x00 }, 13, AV_CODEC_ID_DNXHD }, /* SMPTE VC-3/DNxHD */ | |
48 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x03,0x02,0x00,0x00 }, 14, AV_CODEC_ID_DNXHD }, /* SMPTE VC-3/DNxHD */ | |
49 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0E,0x04,0x02,0x01,0x02,0x04,0x01,0x00 }, 16, AV_CODEC_ID_DNXHD }, /* SMPTE VC-3/DNxHD Legacy Avid Media Composer MXF */ | |
50 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x32,0x00,0x00 }, 14, AV_CODEC_ID_H264 }, /* H.264/MPEG-4 AVC Intra */ | |
51 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x02,0x01,0x31,0x11,0x01 }, 14, AV_CODEC_ID_H264 }, /* H.264/MPEG-4 AVC SPS/PPS in-band */ | |
52 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x02,0x01 }, 16, AV_CODEC_ID_V210 }, /* V210 */ | |
53 | /* SoundEssenceCompression */ | |
54 | { { 0x06,0x0e,0x2b,0x34,0x04,0x01,0x01,0x03,0x04,0x02,0x02,0x02,0x03,0x03,0x01,0x00 }, 14, AV_CODEC_ID_AAC }, /* MPEG2 AAC ADTS (legacy) */ | |
55 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, 13, AV_CODEC_ID_PCM_S16LE }, /* Uncompressed */ | |
56 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13, AV_CODEC_ID_PCM_S16LE }, | |
57 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x02,0x02,0x01,0x7E,0x00,0x00,0x00 }, 13, AV_CODEC_ID_PCM_S16BE }, /* From Omneon MXF file */ | |
58 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x04,0x04,0x02,0x02,0x02,0x03,0x01,0x01,0x00 }, 15, AV_CODEC_ID_PCM_ALAW }, /* XDCAM Proxy C0023S01.mxf */ | |
59 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x01,0x00 }, 15, AV_CODEC_ID_AC3 }, | |
60 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x05,0x00 }, 15, AV_CODEC_ID_MP2 }, /* MP2 or MP3 */ | |
61 | //{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x1C,0x00 }, 15, AV_CODEC_ID_DOLBY_E }, /* Dolby-E */ | |
62 | { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, | |
63 | }; | |
64 | ||
65 | const MXFCodecUL ff_mxf_pixel_format_uls[] = { | |
66 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x01 }, 16, AV_PIX_FMT_UYVY422 }, | |
67 | { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x02 }, 16, AV_PIX_FMT_YUYV422 }, | |
68 | { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_PIX_FMT_NONE }, | |
69 | }; | |
70 | ||
71 | static const struct { | |
72 | enum AVPixelFormat pix_fmt; | |
73 | const char data[16]; | |
74 | } ff_mxf_pixel_layouts[] = { | |
75 | /** | |
76 | * See SMPTE 377M E.2.46 | |
77 | * | |
78 | * Note: Only RGB, palette based and "abnormal" YUV pixel formats like 4:2:2:4 go here. | |
79 | * For regular YUV, use CDCIPictureEssenceDescriptor. | |
80 | * | |
81 | * Note: Do not use these for encoding descriptors for little-endian formats until we | |
82 | * get samples or official word from SMPTE on how/if those can be encoded. | |
83 | */ | |
84 | {AV_PIX_FMT_ABGR, {'A', 8, 'B', 8, 'G', 8, 'R', 8 }}, | |
85 | {AV_PIX_FMT_ARGB, {'A', 8, 'R', 8, 'G', 8, 'B', 8 }}, | |
86 | {AV_PIX_FMT_BGR24, {'B', 8, 'G', 8, 'R', 8 }}, | |
87 | {AV_PIX_FMT_BGRA, {'B', 8, 'G', 8, 'R', 8, 'A', 8 }}, | |
88 | {AV_PIX_FMT_RGB24, {'R', 8, 'G', 8, 'B', 8 }}, | |
89 | {AV_PIX_FMT_RGB444BE,{'F', 4, 'R', 4, 'G', 4, 'B', 4 }}, | |
90 | {AV_PIX_FMT_RGB48BE, {'R', 8, 'r', 8, 'G', 8, 'g', 8, 'B', 8, 'b', 8 }}, | |
91 | {AV_PIX_FMT_RGB48BE, {'R', 16, 'G', 16, 'B', 16 }}, | |
92 | {AV_PIX_FMT_RGB48LE, {'r', 8, 'R', 8, 'g', 8, 'G', 8, 'b', 8, 'B', 8 }}, | |
93 | {AV_PIX_FMT_RGB555BE,{'F', 1, 'R', 5, 'G', 5, 'B', 5 }}, | |
94 | {AV_PIX_FMT_RGB565BE,{'R', 5, 'G', 6, 'B', 5 }}, | |
95 | {AV_PIX_FMT_RGBA, {'R', 8, 'G', 8, 'B', 8, 'A', 8 }}, | |
96 | {AV_PIX_FMT_PAL8, {'P', 8 }}, | |
f6fa7814 | 97 | {AV_PIX_FMT_GRAY8, {'A', 8 }}, |
2ba45a60 DM |
98 | }; |
99 | ||
100 | static const int num_pixel_layouts = FF_ARRAY_ELEMS(ff_mxf_pixel_layouts); | |
101 | ||
102 | int ff_mxf_decode_pixel_layout(const char pixel_layout[16], enum AVPixelFormat *pix_fmt) | |
103 | { | |
104 | int x; | |
105 | ||
106 | for(x = 0; x < num_pixel_layouts; x++) { | |
107 | if (!memcmp(pixel_layout, ff_mxf_pixel_layouts[x].data, 16)) { | |
108 | *pix_fmt = ff_mxf_pixel_layouts[x].pix_fmt; | |
109 | return 0; | |
110 | } | |
111 | } | |
112 | ||
113 | return -1; | |
114 | } | |
115 | ||
116 | static const MXFSamplesPerFrame mxf_spf[] = { | |
117 | { { 1001, 24000 }, { 2002, 0, 0, 0, 0, 0 } }, // FILM 23.976 | |
118 | { { 1, 24}, { 2000, 0, 0, 0, 0, 0 } }, // FILM 24 | |
119 | { { 1001, 30000 }, { 1602, 1601, 1602, 1601, 1602, 0 } }, // NTSC 29.97 | |
120 | { { 1001, 60000 }, { 801, 801, 801, 801, 800, 0 } }, // NTSC 59.94 | |
121 | { { 1, 25 }, { 1920, 0, 0, 0, 0, 0 } }, // PAL 25 | |
122 | { { 1, 50 }, { 960, 0, 0, 0, 0, 0 } }, // PAL 50 | |
123 | }; | |
124 | ||
125 | static const AVRational mxf_time_base[] = { | |
126 | { 1001, 24000 }, | |
127 | { 1, 24}, | |
128 | { 1001, 30000 }, | |
129 | { 1001, 60000 }, | |
130 | { 1, 25 }, | |
131 | { 1, 50 }, | |
132 | { 0, 0} | |
133 | }; | |
134 | ||
135 | const MXFSamplesPerFrame *ff_mxf_get_samples_per_frame(AVFormatContext *s, | |
136 | AVRational time_base) | |
137 | { | |
138 | int idx = av_find_nearest_q_idx(time_base, mxf_time_base); | |
139 | AVRational diff = av_sub_q(time_base, mxf_time_base[idx]); | |
140 | ||
141 | diff.num = abs(diff.num); | |
142 | ||
143 | if (av_cmp_q(diff, (AVRational){1, 1000}) >= 0) | |
144 | return NULL; | |
145 | ||
146 | if (av_cmp_q(time_base, mxf_time_base[idx])) | |
147 | av_log(s, AV_LOG_WARNING, | |
148 | "%d/%d input time base matched %d/%d container time base\n", | |
149 | time_base.num, time_base.den, | |
150 | mxf_spf[idx].time_base.num, | |
151 | mxf_spf[idx].time_base.den); | |
152 | ||
153 | return &mxf_spf[idx]; | |
154 | } |