[FFmpeg-soc] [soc]: r2858 - mxf/mxfenc.c

spyfeng subversion at mplayerhq.hu
Sun Jul 27 19:23:55 CEST 2008


Author: spyfeng
Date: Sun Jul 27 19:23:54 2008
New Revision: 2858

Log:
add descriptor for each track. implement this as three steps:
1) add multiple descriptor in sourcepackage
2) add sub descriptor references in mutiple discriptors
3) set descriptor for each track
4) add local tag in primer pack


Modified:
   mxf/mxfenc.c

Modified: mxf/mxfenc.c
==============================================================================
--- mxf/mxfenc.c	(original)
+++ mxf/mxfenc.c	Sun Jul 27 19:23:54 2008
@@ -77,6 +77,8 @@ typedef struct {
     UID **track;
     UID **sequence;
     UID **structural_component;
+    UID *mul_desc;
+    UID **sub_desc;
 } MXFReferenceContext;
 
 typedef struct MXFContext {
@@ -93,6 +95,12 @@ typedef struct MXFContext {
     UID *essence_container_uls;
 } MXFContext;
 
+typedef struct {
+    const UID key;
+    int (*write)();
+    enum CodecType type;
+} MXFDescriptorWriteTableEntry;
+
 static const uint8_t umid_base[] = {0x06, 0x0a, 0x2b, 0x34, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0f, 0x00, 0x13, 0x00, 0x00, 0x00};
 
 /* complete key */
@@ -118,6 +126,28 @@ static const MXFDataDefinitionUL mxf_dat
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  CODEC_TYPE_DATA },
 };
 
+static const MXFCodecUL mxf_codec_uls[] = {
+    /* PictureEssenceCoding */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, 14, CODEC_ID_MPEG2VIDEO }, /* MP at ML Long GoP */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x01,0x02,0x01,0x01 }, 14, CODEC_ID_MPEG2VIDEO }, /* D-10 50Mbps PAL */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x03,0x03,0x00 }, 14, CODEC_ID_MPEG2VIDEO }, /* MP at HL Long GoP */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, 14, CODEC_ID_MPEG2VIDEO }, /* 422P at HL I-Frame */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x20,0x02,0x03 }, 14,      CODEC_ID_MPEG4 }, /* XDCAM proxy_pal030926.mxf */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x01,0x02,0x00 }, 13,    CODEC_ID_DVVIDEO }, /* DV25 IEC PAL */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x01,0x02,0x02,0x03,0x01,0x01,0x00 }, 14,   CODEC_ID_JPEG2000 }, /* JPEG2000 Codestream */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13,   CODEC_ID_RAWVIDEO }, /* Uncompressed */
+    /* SoundEssenceCompression */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 }, 13,  CODEC_ID_PCM_S16LE }, /* Uncompressed */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x7F,0x00,0x00,0x00 }, 13,  CODEC_ID_PCM_S16LE },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x07,0x04,0x02,0x02,0x01,0x7E,0x00,0x00,0x00 }, 13,  CODEC_ID_PCM_S16BE }, /* From Omneon MXF file */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x04,0x04,0x02,0x02,0x02,0x03,0x01,0x01,0x00 }, 15,   CODEC_ID_PCM_ALAW }, /* XDCAM Proxy C0023S01.mxf */
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x01,0x00 }, 15,        CODEC_ID_AC3 },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x05,0x00 }, 15,        CODEC_ID_MP2 }, /* MP2 or MP3 */
+  //{ { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x02,0x03,0x02,0x1C,0x00 }, 15,    CODEC_ID_DOLBY_E }, /* Dolby-E */
+    { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0,       CODEC_ID_NONE },
+};
+
+static const uint8_t multiple_desc_ul[]           = { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x0D,0x01,0x03,0x01,0x02,0x7F,0x01,0x00 };
 
 static const MXFCodecUL mxf_picture_essence_container_uls[] = {
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 }, 14, CODEC_ID_MPEG2VIDEO }, /* MPEG-ES Frame wrapped */
@@ -160,6 +190,7 @@ static const MXFLocalTagPair mxf_local_t
     { 0x4405, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x10,0x01,0x03,0x00,0x00}}, /* Package Creation Date */
     { 0x4404, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x10,0x02,0x05,0x00,0x00}}, /* Package Modified Date */
     { 0x4403, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x06,0x05,0x00,0x00}}, /* Tracks Strong reference array */
+    { 0x4701, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x02,0x03,0x00,0x00}}, /* Descriptor */
     // Track
     { 0x4801, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x01,0x07,0x01,0x01,0x00,0x00,0x00,0x00}}, /* Track ID */
     { 0x4804, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x01,0x03,0x00,0x00}}, /* Track Numberr */
@@ -174,6 +205,20 @@ static const MXFLocalTagPair mxf_local_t
     { 0x1201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x07,0x02,0x01,0x03,0x01,0x0A,0x00,0x00}}, /* Start position */
     { 0x1101, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x03,0x01,0x00,0x00,0x00}}, /* SourcePackageID */
     { 0x1102, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x03,0x02,0x00,0x00,0x00}}, /* SourceTrackID */
+    // file descriptor
+    { 0x3F01, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x06,0x01,0x01,0x04,0x06,0x0B,0x00,0x00}}, /* sub descriptor uid*/
+    { 0x3006, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x06,0x01,0x01,0x03,0x05,0x00,0x00,0x00}}, /* Linked Track ID */
+    { 0x3004, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x01,0x02,0x00,0x00}}, /* essence container ul */
+    // generic picture eseence descriptor
+    { 0x3203, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x02,0x02,0x00,0x00,0x00}}, /* stored width */
+    { 0x3202, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x05,0x02,0x01,0x00,0x00,0x00}}, /* stored heigth */
+    { 0x320E, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x01,0x01,0x01,0x01,0x00,0x00,0x00}}, /* aspect ratio*/
+    { 0x3201, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x06,0x01,0x00,0x00,0x00,0x00}}, /* picture essence coding*/
+    // generic picture sound essence descriptor
+    { 0x3D03, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x03,0x01,0x01,0x01,0x00,0x00}}, /* audio sampling rate */
+    { 0x3D07, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x04,0x02,0x01,0x01,0x04,0x00,0x00,0x00}}, /* channel count */
+    { 0x3D01, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x04,0x02,0x03,0x03,0x04,0x00,0x00,0x00}}, /* quantization bits */
+    { 0x3D06, {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x06,0x01,0x00,0x00,0x00,0x00}}, /* sound essence compression */
 };
 
 #define PRINT_KEY(pc, s, x) dprintf(pc, "%s %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\n", s, \
@@ -258,6 +303,16 @@ static int klv_encode_ber_length(ByteIOC
     return 0;
 }
 
+static const MXFCodecUL *mxf_get_essence_container_ul(const MXFCodecUL *uls, enum CodecID type)
+{
+    while (uls->id != CODEC_ID_NONE) {
+        if (uls->id == type)
+            break;
+        uls++;
+    }
+    return uls;
+}
+
 static int mxf_write_primer_pack(AVFormatContext *s)
 {
     ByteIOContext *pb = s->pb;
@@ -320,6 +375,8 @@ static void mxf_free(AVFormatContext *s)
     av_freep(&mxf->reference->sequence);
     av_freep(&mxf->reference->structural_component);
     av_freep(&mxf->reference->track);
+    av_freep(&mxf->reference->sub_desc);
+    av_freep(&mxf->reference->mul_desc);
     av_freep(&mxf->reference->package);
     av_freep(&mxf->reference);
     av_freep(&mxf->track_essence_element_key);
@@ -491,7 +548,10 @@ static int mxf_write_package(AVFormatCon
     klv->key[15] = 0x00;
 
     put_buffer(pb, klv->key, 16);
-    klv_encode_ber_length(pb, 92 + 16 * s->nb_streams);
+    if (type == MaterialPackage)
+        klv_encode_ber_length(pb, 92 + 16 * s->nb_streams);
+    else
+        klv_encode_ber_length(pb, 112 + 16 * s->nb_streams); // 20 bytes length for descriptor reference
 
     // write uid
     i = type == MaterialPackage ? 0 : 1;
@@ -544,6 +604,11 @@ static int mxf_write_package(AVFormatCon
         mxf->track_number_sign = av_mallocz(sizeof(mxf_essence_element_key)/sizeof(MXFEssenceElementKey));
         if (!mxf->track_number_sign)
             return -1;
+        // write multiple descriptor reference
+        if (mxf_generate_reference(s, &refs->mul_desc, 1) < 0)
+            return -1;
+        mxf_write_local_tag(pb, 16, 0x4701);
+        put_buffer(pb, *refs->mul_desc, 16);
     }
 
     // malloc memory for essence element key of each track
@@ -587,7 +652,7 @@ static int mxf_write_track(AVFormatConte
 #endif
     // write track id
     mxf_write_local_tag(pb, 4, 0x4801);
-    put_be32(pb, stream_index + 1);
+    put_be32(pb, stream_index);
 
     mxf_write_local_tag(pb, 4, 0x4804);
     if (type != MaterialPackage) {
@@ -716,17 +781,152 @@ static int mxf_write_structural_componen
         put_buffer(pb, mxf->top_src_package_uid, 32);
 
         mxf_write_local_tag(pb, 4, 0x1102);
-        put_be32(pb, stream_index + 1);
+        put_be32(pb, stream_index);
     }
     return 0;
 }
 
+static int mxf_write_multi_descriptor(AVFormatContext *s, KLVPacket *klv)
+{
+    MXFContext *mxf = s->priv_data;
+    MXFReferenceContext *refs = mxf->reference;
+    ByteIOContext *pb = s->pb;
+
+    klv->key[13] = 0x01;
+    klv->key[14] = 0x44;
+    klv->key[15] = 0x00;
+
+    put_buffer(pb, klv->key, 16);
+    klv_encode_ber_length(pb, 64 + 16 * s->nb_streams);
+
+    mxf_write_local_tag(pb, 16, 0x3C0A);
+    put_buffer(pb, *refs->mul_desc, 16);
+#ifdef DEBUG
+    PRINT_KEY(s, "multi_desc uid", *refs->mul_desc);
+#endif
+    // write sample rate
+    // SMPTE377M D.1 says this field is necessary,
+    // but mxf.c actually do not read the field,so we set 0 as default.
+    mxf_write_local_tag(pb, 8, 0x3001);
+    put_be64(pb, 0);
+
+    // write essence container ul
+    mxf_write_local_tag(pb, 16, 0x3004);
+    put_buffer(pb, multiple_desc_ul, 16);
+
+    // write sub descriptor refs
+    refs->sub_desc= av_mallocz(s->nb_streams * sizeof(*refs->sub_desc));
+    if (!refs->sub_desc)
+        return -1;
+    if (mxf_generate_reference(s, refs->sub_desc, s->nb_streams) < 0)
+        return -1;
+    mxf_write_local_tag(pb, s->nb_streams * 16 + 8, 0x3F01);
+    mxf_write_reference(pb, s->nb_streams, *refs->sub_desc);
+    return 0;
+}
+
+static int mxf_write_mpeg_video_desc(AVFormatContext *s, const MXFDescriptorWriteTableEntry *desc_tbl, int stream_index)
+{
+    MXFContext *mxf = s->priv_data;
+    MXFReferenceContext *refs = mxf->reference;
+    ByteIOContext *pb = s->pb;
+    AVStream *st;
+    const MXFCodecUL *codec_ul = NULL;
+
+    st = s->streams[stream_index];
+
+    put_buffer(pb, desc_tbl->key, 16);
+    klv_encode_ber_length(pb, 96);
+
+    mxf_write_local_tag(pb, 16, 0x3C0A);
+    put_buffer(pb, (*refs->sub_desc)[stream_index], 16);
+
+    mxf_write_local_tag(pb, 4, 0x3006);
+    put_be32(pb, stream_index);
+#ifdef DEBUG
+    PRINT_KEY(s, "mpeg2video uid", (*refs->track)[stream_index]);
+    av_log(s, AV_LOG_DEBUG, "linked track ID:%d\n", stream_index);
+#endif
+
+    codec_ul = mxf_get_essence_container_ul(mxf_picture_essence_container_uls, st->codec->codec_id);
+    mxf_write_local_tag(pb, 16, 0x3004);
+    put_buffer(pb, codec_ul->uid, 16);
+
+    mxf_write_local_tag(pb, 4, 0x3203);
+    put_be32(pb, st->codec->width);
+
+    mxf_write_local_tag(pb, 4, 0x3202);
+    put_be32(pb, st->codec->height);
+
+    mxf_write_local_tag(pb, 8, 0x320E);
+    put_be32(pb, st->time_base.den);
+    put_be32(pb, st->time_base.num);
+
+    // tmp write, will modified later
+    mxf_write_local_tag(pb, 16, 0x3201);
+    put_buffer(pb, mxf_codec_uls->uid, 16);
+    return 0;
+}
+
+static int mxf_write_wav_desc(AVFormatContext *s, const MXFDescriptorWriteTableEntry *desc_tbl, int stream_index)
+{
+    MXFContext *mxf = s->priv_data;
+    MXFReferenceContext *refs = mxf->reference;
+    ByteIOContext *pb = s->pb;
+    AVStream *st;
+    const MXFCodecUL *codec_ul = NULL;
+
+    st = s->streams[stream_index];
+
+    put_buffer(pb, desc_tbl->key, 16);
+    klv_encode_ber_length(pb, 96);
+
+    mxf_write_local_tag(pb, 16, 0x3C0A);
+    put_buffer(pb, (*refs->sub_desc)[stream_index], 16);
+
+    mxf_write_local_tag(pb, 4, 0x3006);
+    put_be32(pb, stream_index);
+#ifdef DEBUG
+    PRINT_KEY(s, "wav desc uid", (*refs->track)[stream_index]);
+#endif
+    codec_ul = mxf_get_essence_container_ul(mxf_sound_essence_container_uls, st->codec->codec_id);
+    mxf_write_local_tag(pb, 16, 0x3004);
+    put_buffer(pb, codec_ul->uid, 16);
+
+    // write audio sampling rate
+    mxf_write_local_tag(pb, 8, 0x3D03);
+    put_be32(pb, 48000);
+    put_be32(pb, 1);
+
+    mxf_write_local_tag(pb, 4, 0x3D07);
+    put_be32(pb, st->codec->channels);
+
+    mxf_write_local_tag(pb, 4, 0x3D01);
+    put_be32(pb, st->codec->bits_per_sample);
+
+    // tmp write, will modified later
+    mxf_write_local_tag(pb, 16, 0x3201);
+    put_buffer(pb, (mxf_codec_uls + 8) ->uid, 16);
+    return 0;
+}
+
+static const MXFDescriptorWriteTableEntry mxf_descriptor_read_table[] = {
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x51,0x00 }, mxf_write_mpeg_video_desc, CODEC_ID_MPEG2VIDEO},
+    { { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 }, mxf_write_wav_desc, CODEC_ID_PCM_S16LE},
+    { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, NULL, CODEC_ID_NONE},
+};
+
 static int mxf_build_structural_metadata(AVFormatContext *s, KLVPacket* klv, enum MXFMetadataSetType type)
 {
     int i;
+    const MXFDescriptorWriteTableEntry *desc = NULL;
 
     if (mxf_write_package(s, klv, type) < 0)
         return -1;
+    if (type == SourcePackage) {
+        if (mxf_write_multi_descriptor(s, klv) < 0)
+            return -1;
+    }
 
     for (i = 0;i < s->nb_streams; i++) {
         if (mxf_write_track(s, klv, i, type) < 0)
@@ -737,6 +937,19 @@ static int mxf_build_structural_metadata
 
         if (mxf_write_structural_component(s, klv, i, type) < 0)
             return -1;
+
+        if (type == SourcePackage) {
+            for (desc = mxf_descriptor_read_table; desc->write; desc++) {
+                if(s->streams[i]->codec->codec_id == desc->type) {
+                    int (*write)() = desc->write;
+                    if (write(s, desc, i) < 0) {
+                        av_log(s, AV_LOG_ERROR, "error writing descriptor\n");
+                        return -1;
+                    }
+                    break;
+                }
+            }
+        }
     }
     return 0;
 }
@@ -762,16 +975,6 @@ static int mxf_write_header_metadata_set
     return 0;
 }
 
-static const MXFCodecUL *mxf_get_essence_container_ul(const MXFCodecUL *uls, enum CodecID type)
-{
-    while (uls->id != CODEC_ID_NONE) {
-        if (uls->id == type)
-            break;
-        uls++;
-    }
-    return uls;
-}
-
 static int mxf_add_essence_container_ul(MXFContext *mxf, const MXFCodecUL *codec_ul)
 {
     int i;



More information about the FFmpeg-soc mailing list