[FFmpeg-soc] [Patch]MXF muxer version 0.0.3
Michael Niedermayer
michaelni at gmx.at
Tue Aug 19 13:31:19 CEST 2008
On Tue, Aug 19, 2008 at 09:57:23AM +0800, zhentan feng wrote:
> Hi
>
> 2008/8/19 Michael Niedermayer <michaelni at gmx.at>
>
> > On Tue, Aug 19, 2008 at 12:31:09AM +0800, zhentan feng wrote:
> > > Hi,
> > >
> > > I have fixed bugs and improved the code into new version patch accordingt
> > to
> > > MXF muxer version 0.0.2 reviews from Michael.
> > > However, it seems that the ok'ed parts are not commited into FFmpeg repo
> > in
> > > MXF muxer version 0.0.2 patch.
> >
> > Ive just commited them, please resubmit what is left.
> >
>
> thanks.
> here is the patch.
>
> --
> Best wishes~
> Index: mxfenc.c
> ===================================================================
> --- mxfenc.c (revision 14829)
> +++ mxfenc.c (working copy)
> @@ -38,6 +38,23 @@
> UID uid;
> } MXFLocalTagPair;
>
> +typedef struct {
> + UID track_essence_element_key;
> +} MXFStreamContext;
> +
> +typedef struct MXFContext {
> + int64_t header_byte_count;
> + int64_t header_byte_count_offset;
> + int64_t header_footer_partition_offset;
> + int essence_container_count;
> +} MXFContext;
ok
[...]
> @@ -56,6 +148,18 @@
> put_be16(pb, value);
> }
>
> +static void mxf_write_umid(ByteIOContext *pb, enum CodecID type, int value)
> +{
> + put_buffer(pb, umid_base, 16);
> + mxf_write_uuid(pb, type, value);
> +}
ok
[...]
> @@ -114,9 +218,14 @@
> put_be16(pb, value_size);
> }
>
> +static void mxf_write_metadata_key(ByteIOContext *pb, unsigned int value)
> +{
> + put_buffer(pb, header_metadata_key, 13);
> + put_be24(pb, value);
> +}
> +
> static void mxf_free(AVFormatContext *s)
> {
> - MXFContext *mxf = s->priv_data;
> AVStream *st;
> int i;
>
> @@ -124,7 +233,6 @@
> st = s->streams[i];
> av_freep(&st->priv_data);
> }
> - av_freep(&mxf->essence_container_uls);
> }
>
> static const MXFDataDefinitionUL *mxf_get_data_definition_ul(enum CodecType type)
ok
> @@ -138,6 +246,630 @@
> return uls;
> }
>
> +static int mxf_write_essence_container_refs(AVFormatContext *s)
static int mxf_write_essence_container_refs(AVFormatContext *s, int write)
> +{
> + MXFContext *mxf = s->priv_data;
> + ByteIOContext *pb = s->pb;
> + AVStream *st;
> + int i, count = 0, j = 0;
> + int essence_container_ul_sign[32] = { 0 };
> + const MXFCodecUL *codec_ul = NULL;
useless initialization
> +
> + for (codec_ul = ff_mxf_essence_container_uls; codec_ul->id; codec_ul++) {
> + for (i = 0; i < s->nb_streams; i++) {
> + st = s->streams[i];
> + if (st->codec->codec_id == codec_ul->id) {
> + essence_container_ul_sign[count] = j;
if(write)
put_buffer()
> + count++;
> + break;
> + }
> + }
> + j++;
> + // considering WAV/AES3 frame wrapped, when get the first CODEC_ID_PCM_S16LE, break;
> + // this is a temporary method, when we can get more information, modofy this.
> + if (codec_ul->id == CODEC_ID_PCM_S16LE)
> + break;
> + }
> + // set the count of essence container for caculating the size of the references in other metadata sets
> + if (!mxf->essence_container_count)
> + mxf->essence_container_count = count;
> + else {
> + mxf_write_refs_count(pb, count);
> + for (i = 0; i < count; i++) {
> + put_buffer(pb, ff_mxf_essence_container_uls[essence_container_ul_sign[i]].uid, 16);
> + }
> +#ifdef DEBUG
> + av_log(s,AV_LOG_DEBUG, "essence container count:%d\n", count);
> + for (i = 0; i < count; i++)
> + PRINT_KEY(s, "essence container ul:\n", ff_mxf_essence_container_uls[essence_container_ul_sign[i]].uid);
> +#endif
> + }
> +
> + return 0;
return mxf->essence_container_count
> +}
> +
> +static int mxf_write_preface(AVFormatContext *s)
> +{
> + MXFContext *mxf = s->priv_data;
> + ByteIOContext *pb = s->pb;
> +
> + mxf_write_metadata_key(pb, 0x012f00);
> +#ifdef DEBUG
> + PRINT_KEY(s, "preface key", pb->buf_ptr - 16);
> +#endif
PRINT_KEY can be #defined to nothing when DEBUG is not, this would avoid
the #ifdef lines all over the code
[...]
> +static int mxf_write_track(AVFormatContext *s, int stream_index, enum MXFMetadataSetType type, int *track_number_sign)
> +{
> + ByteIOContext *pb = s->pb;
> + AVStream *st;
> + MXFStreamContext *sc;
> + const MXFCodecUL *element;
> + int i = 0;
> +
> + mxf_write_metadata_key(pb, 0x013b00);
> +#ifdef DEBUG
> + PRINT_KEY(s, "track key", pb->buf_ptr - 16);
> +#endif
> + klv_encode_ber_length(pb, 80);
> +
> + st = s->streams[stream_index];
> + sc = st->priv_data;
> +
> + // write track uid
> + mxf_write_local_tag(pb, 16, 0x3C0A);
> + mxf_write_uuid(pb, Track * type, stream_index);
> +#ifdef DEBUG
> + PRINT_KEY(s, "track uid", pb->buf_ptr - 16);
> +#endif
> + // write track id
> + mxf_write_local_tag(pb, 4, 0x4801);
> + put_be32(pb, stream_index);
> +
> + mxf_write_local_tag(pb, 4, 0x4804);
> + if (type != MaterialPackage) {
> + for (element = mxf_essence_element_key; element->id != CODEC_ID_NONE; element++) {
> + if (st->codec->codec_id== element->id) {
> + // write track number
> + put_buffer(pb, element->uid + 12, 3);
> + put_byte(pb, element->uid[15] + track_number_sign[i]);
> + track_number_sign[i] ++;
> +
> + // set essence_element key
> + memcpy(sc->track_essence_element_key, element->uid, 16);
shouldnt [15] of track_essence_element_key be set to track_number_sign[i] as
well?
> + break;
> + }
> + i++;
> + }
> + } else {
> + put_be32(pb, 0); // track number of material package is 0
> + }
> +
> + mxf_write_local_tag(pb, 8, 0x4B01);
> + put_be32(pb, st->time_base.den);
> + put_be32(pb, st->time_base.num);
> +
> + // write origin
> + mxf_write_local_tag(pb, 8, 0x4B02);
> + put_be64(pb, 0);
> +
> + // write sequence refs
> + mxf_write_local_tag(pb, 16, 0x4803);
> + mxf_write_uuid(pb, Sequence * Track * type, stream_index);
Is it intended to multiply the values of 2 enums with the type ?
[...]
> +static int mxf_write_sequence(AVFormatContext *s, int stream_index, enum MXFMetadataSetType type)
> +{
> + ByteIOContext *pb = s->pb;
> + AVStream *st;
> + const MXFDataDefinitionUL * data_def_ul;
> +
> + mxf_write_metadata_key(pb, 0x010f00);
> +#ifdef DEBUG
> + PRINT_KEY(s, "sequence key", pb->buf_ptr - 16);
> +#endif
> + klv_encode_ber_length(pb, 80);
> +
> + st = s->streams[stream_index];
> +
> + mxf_write_local_tag(pb, 16, 0x3C0A);
> + mxf_write_uuid(pb, Sequence * Track * type, stream_index);
> +
> +#ifdef DEBUG
> + PRINT_KEY(s, "sequence uid", pb->buf_ptr - 16);
> +#endif
> + // find data define uls
> + data_def_ul = mxf_get_data_definition_ul(st->codec->codec_type);
> + mxf_write_local_tag(pb, 16, 0x0201);
> + put_buffer(pb, data_def_ul->uid, 16);
[...]
> +
> +static int mxf_write_structural_component(AVFormatContext *s, int stream_index, enum MXFMetadataSetType type)
> +{
> + ByteIOContext *pb = s->pb;
> + AVStream *st;
> + const MXFDataDefinitionUL * data_def_ul;
> + int i;
> +
> + mxf_write_metadata_key(pb, 0x011100);
> +#ifdef DEBUG
> + PRINT_KEY(s, "sturctural component key", pb->buf_ptr - 16);
> +#endif
> + klv_encode_ber_length(pb, 108);
> +
> + st = s->streams[stream_index];
> +
> + // write uid
> + mxf_write_local_tag(pb, 16, 0x3C0A);
> + mxf_write_uuid(pb, SourceClip * Track * type, stream_index);
> +
> +#ifdef DEBUG
> + PRINT_KEY(s, "structural component uid", pb->buf_ptr - 16);
> +#endif
> + data_def_ul = mxf_get_data_definition_ul(st->codec->codec_type);
> + mxf_write_local_tag(pb, 16, 0x0201);
> + put_buffer(pb, data_def_ul->uid, 16);
> +
duplicate
[...]
> +static void mxf_write_essence_container_ul(ByteIOContext *pb, enum CodecID type)
> +{
> + const MXFCodecUL *codec_ul;
> + codec_ul = mxf_get_essence_container_ul(type);
> + mxf_write_local_tag(pb, 16, 0x3004);
> + put_buffer(pb, codec_ul->uid, 16);
> +}
this function is used just once so the code could just be put there instead
of the function call
[...]
> +static int mxf_write_header_metadata_sets(AVFormatContext *s)
> +{
> + AVStream *st;
> + MXFStreamContext *sc = NULL;
> + int i;
> + if (mxf_write_preface(s) < 0)
> + return -1;
> +
> + if (mxf_write_identification(s) < 0)
> + return -1;
> +
> + if (mxf_write_content_storage(s) < 0)
> + return -1;
> +
> + for (i = 0; i < s->nb_streams; i++) {
> + st = s->streams[i];
> + sc = av_mallocz(sizeof(MXFStreamContext));
> + if (!sc)
> + return AVERROR(ENOMEM);
> + st->priv_data = sc;
> + // set pts information
> + if (st->codec->codec_type == CODEC_TYPE_VIDEO) {
> + av_set_pts_info(st, 64, 1, st->codec->time_base.den);
> + } else if (st->codec->codec_type == CODEC_TYPE_AUDIO) {
> + av_set_pts_info(st, 64, 1, st->codec->sample_rate);
> + }
> + }
> +
> + if (mxf_build_structural_metadata(s, MaterialPackage) < 0)
> + return -1;
> +
> + if (mxf_build_structural_metadata(s, SourcePackage) < 0)
> + return -1;
> + return 0;
> +}
ok
[...]
> +static int mux_write_header(AVFormatContext *s)
> +{
> + MXFContext *mxf = s->priv_data;
> + ByteIOContext *pb = s->pb;
> + int64_t header_metadata_start, offset_now;
> +
> + mxf_write_partition(s, 0, 1, header_partition_key);
> +
> + // mark the start of the headermetadata and calculate metadata size
> + header_metadata_start = url_ftell(s->pb);
> + mxf_write_primer_pack(s);
> + if (mxf_write_header_metadata_sets(s) < 0)
> + goto fail;
> + offset_now = url_ftell(s->pb);
> + mxf->header_byte_count = offset_now - header_metadata_start;
> +
> + // if streamed file, update header_byte_count field here, before put_flush_packet()
> + if (url_is_streamed(s->pb)) {
> + url_fseek(pb, mxf->header_byte_count_offset, SEEK_SET);
> + put_be64(pb, mxf->header_byte_count);
> + url_fseek(pb, offset_now, SEEK_SET);
> + }
actually, this could be done unconditional, it does no harm
[...]
> @@ -152,6 +884,39 @@
> return 0;
> }
>
> +static int mxf_update_header_partition(AVFormatContext *s, int64_t footer_partition_offset)
> +{
> + MXFContext *mxf = s->priv_data;
> + ByteIOContext *pb = s->pb;
> +
> + url_fseek(pb, mxf->header_byte_count_offset, SEEK_SET);
> + put_be64(pb, mxf->header_byte_count);
> + put_flush_packet(pb);
> +
> + url_fseek(pb, mxf->header_footer_partition_offset, SEEK_SET);
> + put_be64(pb, footer_partition_offset);
> + put_flush_packet(pb);
> + return 0;
> +}
ok
> +
> +
> +static int mux_write_footer(AVFormatContext *s)
> +{
> + ByteIOContext *pb = s->pb;
> +
> + int64_t byte_position= url_ftell(pb);
> + if (url_is_streamed(s->pb))
> + goto end;
> + mxf_write_partition(s, byte_position, 0, footer_partition_key);
> +
> + put_flush_packet(pb);
> +
> + mxf_update_header_partition(s, byte_position);
> +end:
if(!url_is_streamed(s->pb))){
...
}
is simpler
[...]
> Index: mxf.c
> ===================================================================
> --- mxf.c (revision 14829)
> +++ mxf.c (working copy)
> @@ -1,6 +1,6 @@
> /*
> * MXF
> - * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>.
> + * Copyright (c) 2008 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>
> *
> * This file is part of FFmpeg.
> *
[...]
> Index: mxf.h
> ===================================================================
> --- mxf.h (revision 14829)
> +++ mxf.h (working copy)
> @@ -1,6 +1,6 @@
> /*
> * MXF
> - * Copyright (c) 2006 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>.
> + * Copyright (c) 2008 SmartJog S.A., Baptiste Coudurier <baptiste dot coudurier at smartjog dot com>
> *
> * This file is part of FFmpeg.
> *
The code in the demuxer from where this was copied had 2006 so i think
2006 is correct.
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
The misfortune of the wise is better than the prosperity of the fool.
-- Epicurus
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-soc/attachments/20080819/e5160b4b/attachment.pgp>
More information about the FFmpeg-soc
mailing list