[FFmpeg-soc] [Patch]Mxf muxer 0.0.1

Michael Niedermayer michaelni at gmx.at
Thu Aug 14 20:18:20 CEST 2008


On Fri, Aug 15, 2008 at 01:03:52AM +0800, zhentan feng wrote:
> Hi
> 
> 2008/8/14 Michael Niedermayer <michaelni at gmx.at>
> 
> > On Thu, Aug 14, 2008 at 11:41:01AM +0800, zhentan feng wrote:
[...]
> > >
> > >
> > > >
> > > > [...]
> > > > > +static const MXFCodecUL mxf_essence_container_uls[] = {
> > > > > +    // picture essence container
> > > > > +    { {
> > > >
> > 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01
> > > > }, 14, CODEC_ID_MPEG2VIDEO }, /* MPEG-ES Frame wrapped */
> > > > > +//    { {
> > > >
> > 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x41,0x01
> > > > }, 14,    CODEC_ID_DVVIDEO }, /* DV 625 25mbps */
> > > > > +    // audio essence conatiner uls
> > > > > +    { {
> > > >
> > 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x06,0x01,0x00
> > > > }, 14, CODEC_ID_PCM_S16LE }, /* BWF Frame wrapped */
> > > > > +//    { {
> > > >
> > 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x40,0x01
> > > > }, 14,       CODEC_ID_MP2 }, /* MPEG-ES Frame wrapped, 0x40 ??? stream
> > id */
> > > > > +//    { {
> > > >
> > 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x01,0x01,0x01
> > > > }, 14, CODEC_ID_PCM_S16LE }, /* D-10 Mapping 50Mbps PAL Extended
> > Template */
> > > > > +    { {
> > > >
> > 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
> > > > },  0,      CODEC_ID_NONE },
> > > > > +};
> > > >
> > > > duplicate
> > > >
> > >
> > > I tried to extract this code ,however, we muxing by CodecID type to get
> > UL,
> > > but one CodecID have different ULs, such as CODEC_ID_PCM_S16LE.
> > >
> > > so when checking each item in mxf_essence_container_uls for streams to
> > build
> > > essence container references, we can not decide which ul to use only by
> > > CodecID type.
> > > But we actually know which type we should mux, so just write what will be
> > > muxed type in the table.
> >
> > no reason not the share the tables, either CODEC_ID_PCM_S16LE must be
> > special
> > handled or the UL used for muxing can be the first CODEC_ID_PCM_S16LE in
> > the
> > table.
> >
> 
> hmm, to get the ul when muxing, i think it is not enough only by CodecID
> type.
> Is it necessary to add some flag in the table( or get information from some
> api in FFmpeg) to distinguish one CodecID type having different uls?

Either
A. MXF supports generic 16bit PCM, in which case it has one (or more)
   identifers for it and any of them can be used at will
or
B. MXF does not support generic 16bit PCM but supports just 16bit PCM with
   a finite set of fixed samplerates/ channels in which case a different
   identifer might need to be choosen for each sample rate or channel count.
   in that case a simple
   if(codec_id == CODEC_ID_PCM_S16LE && sample_rate==123) write(aaaa); can
   be used.

I do not see a problem with sharing the table


> 
> 
> >
> >
> > >
> > > on the other side, demuxer can get the correct CodecID type by uls, uls
> > are
> > > unique.
> > >
> > >
> > > >
> > > >
> > > > > +
> > > > > +/**
> > > > > + * SMPTE RP210 http://www.smpte-ra.org/mdd/index.html
> > > > > + */
> > > > > +static const MXFLocalTagPair mxf_local_tag_batch[] = {
> > > > > +    // preface set
> > > > > +    { 0x3C0A,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x15,0x02,0x00,0x00,0x00,0x00}},
> > > > /* Instance UID */
> > > > > +    { 0x3B02,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x10,0x02,0x04,0x00,0x00}},
> > > > /* Last Modified Date */
> > > > > +    { 0x3B05,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x03,0x01,0x02,0x01,0x05,0x00,0x00,0x00}},
> > > > /* Version */
> > > > > +    { 0x3B06,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x06,0x04,0x00,0x00}},
> > > > /* Identifications reference */
> > > > > +    { 0x3B03,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x02,0x01,0x00,0x00}},
> > > > /* Content Storage reference */
> > > > > +    { 0x3B09,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x02,0x02,0x03,0x00,0x00,0x00,0x00}},
> > > > /* Operational Pattern UL */
> > > > > +    { 0x3B0A,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x02,0x02,0x10,0x02,0x01,0x00,0x00}},
> > > > /* Essence Containers UL batch */
> > > > > +    { 0x3B0B,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x05,0x01,0x02,0x02,0x10,0x02,0x02,0x00,0x00}},
> > > > /* DM Schemes UL batch */
> > > > > +    // Identification
> > > > > +    { 0x3C09,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x01,0x00,0x00,0x00}},
> > > > /* This Generation UID */
> > > > > +    { 0x3C01,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x02,0x01,0x00,0x00}},
> > > > /* Company Name */
> > > > > +    { 0x3C02,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x03,0x01,0x00,0x00}},
> > > > /* Product Name */
> > > > > +    { 0x3C04,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x04,0x00,0x00,0x00}},
> > > > /* Version String */
> > > > > +    { 0x3C05,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x20,0x07,0x01,0x07,0x00,0x00,0x00}},
> > > > /* Product ID */
> > > > > +    { 0x3C06,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x10,0x02,0x03,0x00,0x00}},
> > > > /* Modification Date */
> > > > > +    // Content Storage
> > > > > +    { 0x1901,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x05,0x01,0x00,0x00}},
> > > > /* Package strong reference batch */
> > > > > +    // Essence Container Data
> > > > > +    { 0x2701,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x06,0x01,0x00,0x00,0x00}},
> > > > /* Linked Package UID */
> > > > > +    { 0x3F07,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x04,0x01,0x03,0x04,0x04,0x00,0x00,0x00,0x00}},
> > > > /* BodySID */
> > > > > +    // Package
> > > > > +    { 0x4401,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x01,0x01,0x15,0x10,0x00,0x00,0x00,0x00}},
> > > > /* Package UID */
> > > > > +    { 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 */
> > > > > +    { 0x4B01,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x05,0x30,0x04,0x05,0x00,0x00,0x00,0x00}},
> > > > /* Edit Rate */
> > > > > +    { 0x4B02,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x01,0x03,0x01,0x03,0x00,0x00}},
> > > > /* Origin */
> > > > > +    { 0x4803,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x02,0x04,0x00,0x00}},
> > > > /* Sequence reference */
> > > > > +    // Sequence
> > > > > +    { 0x0201,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x07,0x01,0x00,0x00,0x00,0x00,0x00}},
> > > > /* Data Definition UL */
> > > > > +    { 0x0202,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x07,0x02,0x02,0x01,0x01,0x03,0x00,0x00}},
> > > > /* Duration */
> > > > > +    { 0x1001,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x06,0x01,0x01,0x04,0x06,0x09,0x00,0x00}},
> > > > /* Structural Components reference array */
> > > > > +    // Source Clip
> > > > > +    { 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 */
> > > > > +    { 0x3001,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x01,0x04,0x06,0x01,0x01,0x00,0x00,0x00,0x00}},
> > > > /* SampleRate */
> > > > > +    { 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*/
> > > >
> > > > i dont know mxf but what do these mean?
> > > > the aspect ratio is not stored anywhere ...
> >
> > ping?
> >
> I made a mistake in mxfenc.c, i restored time_base, this is obviously wrong.
> 
> I meaned to store aspect ratio of the video.
> Is AVCodecContext->sample_aspect_ratio correct?

yes ,but it is the sample aspect ratio not the display aspect ratio!


> 
> 
> 
> >
> >
> >
> > > >
> > > >
> > > > > +    { 0x3201,
> > > >
> > {0x06,0x0E,0x2B,0x34,0x01,0x01,0x01,0x02,0x04,0x01,0x06,0x01,0x00,0x00,0x00,0x00}},
> > > > /* picture essence coding*/
> > > > > +    // generic 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 */
> > > > > +};
> > > >
> > > > > +
> > > > > +static void mxf_generate_uuid(AVFormatContext *s, UID uuid)
> > > > > +{
> > > > > +    MXFContext *mxf = s->priv_data;
> > > > > +    int i;
> > > > > +
> > > > > +    for (i = 0; i < 16; i++) {
> > > > > +        mxf->random_state= mxf->random_state*1664525+10139042;
> > > > > +        uuid[i]= mxf->random_state>>24;
> > > > > +    }
> > > > > +    // the 7th byte is version according to ISO 11578
> > > > > +    uuid[6] &= 0x0f;
> > > > > +    uuid[6] |= 0x40;
> > > > > +
> > > > > +    // the 8th byte is variant for current use according to ISO
> > 11578
> > > > > +    uuid[8] &= 0x3f;
> > > > > +    uuid[8] |= 0x80;
> > > > > +}
> > > > > +
> > > > > +static void mxf_generate_umid(AVFormatContext *s, UMID umid)
> > > > > +{
> > > > > +    memcpy(umid, umid_base, 16);
> > > > > +    mxf_generate_uuid(s, umid + 16);
> > > > > +}
> > > > > +
> > > > > +static int mxf_generate_reference(AVFormatContext *s, UID **refs,
> > int
> > > > ref_count)
> > > > > +{
> > > > > +    int i;
> > > > > +    UID *p;
> > > > > +    *refs = av_mallocz(ref_count * sizeof(UID));
> > > > > +    if (!*refs)
> > > > > +        return AVERROR(ENOMEM);
> > > > > +    p = *refs;
> > > > > +    for (i = 0; i < ref_count; i++) {
> > > > > +        mxf_generate_uuid(s, *p);
> > > > > +        p ++;
> > > > > +    }
> > > > > +    return 0;
> > > > > +}
> > > > > +
> > > >
> > > > I think uid values should be made systeatically so they do not need to
> > be
> > > > stored. Currently weakly random UIDs are generated, stored in the
> > context
> > > > and then used, it would be simpler to just store systematic ones like
> > > > constant or constant + stream_number.
> > > >
> > >
> > > there are many references and the number of references are also different
> > in
> > > metadata sets, IMHO this is more clear than writing them into context.
> > > though it is a little waste of memory, unacceptable?
> >
> > write_uid(stream_num or codec_id or ...)
> > ...
> > write_uid(stream_num or codec_id or ...)
> >
> > vs.
> > context->variable_UID= av_malloc(sizeof(UID*));
> > for(i=0; i<stream_num; i++)
> >    context->variable_UID[i]= av_malloc(sizeof(UID));
> > for(i=0; i<stream_num; i++)
> >    context->variable_UID[i]= generate_random_uid()
> > put_buffer(context->variable_UID);
> > ...
> > put_buffer(context->variable_UID);
> >
> >
> > My suggstion looks distinctly simpler
> >

> I am a little confused about your suggstion :(

yes i realize but i am not sure how to clarify it :(


> 
> you know this is a reference chain,
> for example, once  have generatee refs for tracks in package set,
> when writing track set, it just read the uid by
> MXFReferenceContext->track[i].
> 
> at this situation, we should generate the refs for tracks while wrting
> package set, becasue some fields of package set are the value of the
> references, so it can not be put into " for (i=0; i<stream_num; i++)" to
> generate.
> 
> on the other hand, stream_num is equal to the number of track sets, so we
> generate references for sequence set and structual componet set in "for
> (i=0; i<stream_num)" while writing track set and sequence set.
> 
> MXFReferenceContext have all the references pointer.
> MXFStreamContext all common value for each stream including the references
> pointer.

what iam suggesting is that instead of
* generating refs
* storing them in the contexts
* writing them where they are needed

We could (and i belive this is simpler)
* generate refs as we write them

a more concrete example with C code:

static void mxf_write_uuid(ByteIOContext *pb, int type, int value)
{
    put_buffer(pb, constant_uuid, 12);
    put_be16(pb, type);
    put_be16(pb, value);
}

for(i=0, i<stream_num; i++){
    mxf_write_uuid(pb, 0, i)
    ...
}
...
for(i=0, i<track_num; i++){
    mxf_write_uuid(pb, 1, i)
    ...
}

that way
mxf_write_uuid(pb, x, y)
will always generate the same uid for the same x and y parameter and thus
it becomes unneccesary to store it in the context.

Do you understand? or should i try to explain it differently?


[...]
> > >
> > >
> > > >
> > > >
> > > > > +    put_be64(pb, this_partition); // footerPartition,update later
> > > > > +
> > > > > +    // set offset
> > > > > +    if (!this_partition)
> > > > > +        mxf->header_byte_count_offset = url_ftell(pb);
> > > > > +    put_be64(pb, 0); // headerByteCount, update later
> > > > > +
> > > >
> > > > > +    // no indexTable
> > > > > +    put_be64(pb, 0); // indexByteCount
> > > > > +    put_be32(pb, 0); // indexSID
> > > > > +    put_be64(pb, 0); // bodyOffset
> > > >
> > > > why? Isnt an index required for seeking?
> > >
> > >
> > > we generate mxf file use op1a, and index table is optional for op1a.
> >
> > That is not what i was asking. They surely are optional, but they are
> > required to be able to seek in non cbr files. The spec also says:
> >
> > "Index Tables should be implemented wherever possible. They can be used to
> > satisfy a number of the User
> >  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> >  Requirements, particularly those to do with the handling of partial files
> > (for example reading part of a large file
> >  from the middle of a data tape, indexed by the timeline). When Index
> > Tables are used, they shall conform to this
> >  specification.
> > "
> >
> well, now the mxf file doesn't contain indext table, so it can not be
> seeked.
> however, mxfdec.c seems not read any values of index table, and
> mxf_read_seek() doesn't use any information about of index table.

> Sholud i must add index table?

you do not have to, but it would be nice, it would make the files more
usefull once mxfdec supports using the index.


[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

In a rich man's house there is no place to spit but his face.
-- Diogenes of Sinope
-------------- 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/20080814/9755809c/attachment.pgp>


More information about the FFmpeg-soc mailing list