yading@11: /* yading@11: * MXF yading@11: * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier yading@11: * yading@11: * This file is part of FFmpeg. yading@11: * yading@11: * FFmpeg is free software; you can redistribute it and/or yading@11: * modify it under the terms of the GNU Lesser General Public yading@11: * License as published by the Free Software Foundation; either yading@11: * version 2.1 of the License, or (at your option) any later version. yading@11: * yading@11: * FFmpeg is distributed in the hope that it will be useful, yading@11: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@11: * Lesser General Public License for more details. yading@11: * yading@11: * You should have received a copy of the GNU Lesser General Public yading@11: * License along with FFmpeg; if not, write to the Free Software yading@11: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@11: */ yading@11: yading@11: #include "libavutil/common.h" yading@11: #include "mxf.h" yading@11: yading@11: /** yading@11: * SMPTE RP224 http://www.smpte-ra.org/mdd/index.html yading@11: */ yading@11: const MXFCodecUL ff_mxf_data_definition_uls[] = { yading@11: { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x02,0x01,0x00,0x00,0x00 }, 13, AVMEDIA_TYPE_VIDEO }, yading@11: { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x02,0x02,0x00,0x00,0x00 }, 13, AVMEDIA_TYPE_AUDIO }, yading@11: { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AVMEDIA_TYPE_DATA }, yading@11: }; yading@11: yading@11: const MXFCodecUL ff_mxf_codec_uls[] = { yading@11: /* PictureEssenceCoding */ yading@11: { { 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 */ yading@11: { { 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 */ yading@11: { { 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 */ yading@11: { { 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 */ yading@11: { { 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 */ yading@11: { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x02,0x00 }, 13, AV_CODEC_ID_DVVIDEO }, /* DV25 IEC PAL */ yading@11: { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14, AV_CODEC_ID_JPEG2000 }, /* JPEG2000 Codestream */ yading@11: { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13, AV_CODEC_ID_RAWVIDEO }, /* Uncompressed */ yading@11: { { 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 */ yading@11: { { 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 */ yading@11: { { 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 */ yading@11: { { 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 */ yading@11: { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x02,0x01 }, 16, AV_CODEC_ID_V210 }, /* V210 */ yading@11: /* SoundEssenceCompression */ yading@11: { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, 13, AV_CODEC_ID_PCM_S16LE }, /* Uncompressed */ yading@11: { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13, AV_CODEC_ID_PCM_S16LE }, yading@11: { { 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 */ yading@11: { { 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 */ yading@11: { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x01,0x00 }, 15, AV_CODEC_ID_AC3 }, yading@11: { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x05,0x00 }, 15, AV_CODEC_ID_MP2 }, /* MP2 or MP3 */ yading@11: //{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x1C,0x00 }, 15, AV_CODEC_ID_DOLBY_E }, /* Dolby-E */ yading@11: { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_CODEC_ID_NONE }, yading@11: }; yading@11: yading@11: const MXFCodecUL ff_mxf_pixel_format_uls[] = { yading@11: { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x01 }, 16, AV_PIX_FMT_UYVY422 }, yading@11: { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0A,0x04,0x01,0x02,0x01,0x01,0x02,0x01,0x02 }, 16, AV_PIX_FMT_YUYV422 }, yading@11: { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 0, AV_PIX_FMT_NONE }, yading@11: }; yading@11: yading@11: static const struct { yading@11: enum AVPixelFormat pix_fmt; yading@11: const char data[16]; yading@11: } ff_mxf_pixel_layouts[] = { yading@11: /** yading@11: * See SMPTE 377M E.2.46 yading@11: * yading@11: * Note: Only RGB, palette based and "abnormal" YUV pixel formats like 4:2:2:4 go here. yading@11: * For regular YUV, use CDCIPictureEssenceDescriptor. yading@11: * yading@11: * Note: Do not use these for encoding descriptors for little-endian formats until we yading@11: * get samples or official word from SMPTE on how/if those can be encoded. yading@11: */ yading@11: {AV_PIX_FMT_ABGR, {'A', 8, 'B', 8, 'G', 8, 'R', 8 }}, yading@11: {AV_PIX_FMT_ARGB, {'A', 8, 'R', 8, 'G', 8, 'B', 8 }}, yading@11: {AV_PIX_FMT_BGR24, {'B', 8, 'G', 8, 'R', 8 }}, yading@11: {AV_PIX_FMT_BGRA, {'B', 8, 'G', 8, 'R', 8, 'A', 8 }}, yading@11: {AV_PIX_FMT_RGB24, {'R', 8, 'G', 8, 'B', 8 }}, yading@11: {AV_PIX_FMT_RGB444BE,{'F', 4, 'R', 4, 'G', 4, 'B', 4 }}, yading@11: {AV_PIX_FMT_RGB48BE, {'R', 8, 'r', 8, 'G', 8, 'g', 8, 'B', 8, 'b', 8 }}, yading@11: {AV_PIX_FMT_RGB48BE, {'R', 16, 'G', 16, 'B', 16 }}, yading@11: {AV_PIX_FMT_RGB48LE, {'r', 8, 'R', 8, 'g', 8, 'G', 8, 'b', 8, 'B', 8 }}, yading@11: {AV_PIX_FMT_RGB555BE,{'F', 1, 'R', 5, 'G', 5, 'B', 5 }}, yading@11: {AV_PIX_FMT_RGB565BE,{'R', 5, 'G', 6, 'B', 5 }}, yading@11: {AV_PIX_FMT_RGBA, {'R', 8, 'G', 8, 'B', 8, 'A', 8 }}, yading@11: {AV_PIX_FMT_PAL8, {'P', 8 }}, yading@11: }; yading@11: yading@11: static const int num_pixel_layouts = FF_ARRAY_ELEMS(ff_mxf_pixel_layouts); yading@11: yading@11: int ff_mxf_decode_pixel_layout(const char pixel_layout[16], enum AVPixelFormat *pix_fmt) yading@11: { yading@11: int x; yading@11: yading@11: for(x = 0; x < num_pixel_layouts; x++) { yading@11: if (!memcmp(pixel_layout, ff_mxf_pixel_layouts[x].data, 16)) { yading@11: *pix_fmt = ff_mxf_pixel_layouts[x].pix_fmt; yading@11: return 0; yading@11: } yading@11: } yading@11: yading@11: return -1; yading@11: } yading@11: yading@11: static const MXFSamplesPerFrame mxf_samples_per_frames[] = { yading@11: { { 1001, 24000 }, { 2002, 0, 0, 0, 0, 0 } }, // FILM 23.976 yading@11: { { 1, 24}, { 2000, 0, 0, 0, 0, 0 } }, // FILM 24 yading@11: { { 1001, 30000 }, { 1602, 1601, 1602, 1601, 1602, 0 } }, // NTSC 29.97 yading@11: { { 1001, 60000 }, { 801, 801, 801, 801, 800, 0 } }, // NTSC 59.94 yading@11: { { 1, 25 }, { 1920, 0, 0, 0, 0, 0 } }, // PAL 25 yading@11: { { 1, 50 }, { 960, 0, 0, 0, 0, 0 } }, // PAL 50 yading@11: }; yading@11: yading@11: const MXFSamplesPerFrame *ff_mxf_get_samples_per_frame(AVFormatContext *s, AVRational time_base) yading@11: { yading@11: int i; yading@11: for (i = 0; i < FF_ARRAY_ELEMS(mxf_samples_per_frames); i++) { yading@11: if (!av_cmp_q(mxf_samples_per_frames[i].time_base, time_base)) yading@11: return &mxf_samples_per_frames[i]; yading@11: } yading@11: yading@11: // Find closest container time base for approximative codec time base like 1/29.97, 1/30, ... yading@11: for (i = 0; i < FF_ARRAY_ELEMS(mxf_samples_per_frames); i++) { yading@11: if (fabs(av_q2d(mxf_samples_per_frames[i].time_base) - av_q2d(time_base)) < 0.0001) { yading@11: av_log(s, AV_LOG_WARNING, "%d/%d input time base matched %d/%d container time base\n", yading@11: time_base.num, time_base.den, yading@11: mxf_samples_per_frames[i].time_base.num, mxf_samples_per_frames[i].time_base.den); yading@11: return &mxf_samples_per_frames[i]; yading@11: } yading@11: } yading@11: return NULL; yading@11: }