| 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 }}, |
| 97 | {AV_PIX_FMT_GRAY8, {'A', 8 }}, |
| 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 | } |