[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