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 }, /* [EMAIL PROTECTED] 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 }, /* [EMAIL PROTECTED] Long GoP */ + { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x04,0x02,0x00 }, 14, CODEC_ID_MPEG2VIDEO }, /* [EMAIL PROTECTED] 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; _______________________________________________ FFmpeg-soc mailing list FFmpeg-soc@mplayerhq.hu https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc