[FFmpeg-devel] [PATCH 4/4] mxfenc: support smpte dv codecs

Matthieu Bouron matthieu.bouron at gmail.com
Tue May 29 12:23:26 CEST 2012


On Sun, May 27, 2012 at 02:21:42PM +0200, Matthieu Bouron wrote:
> ---
> Hi,
> 
> This patch introduces support for smpte dv codecs in mxf container.
> Field dominance flag is not set since the dv encoder does not output correct
> ff/fs value in vsc pack (maybe i'm missing something here).
> 
> Regards,
> Matthieu
> ---
>  libavformat/mxfenc.c |  120 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 119 insertions(+), 1 deletion(-)
> 
> diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
> index fce8446..0c39acb 100644
> --- a/libavformat/mxfenc.c
> +++ b/libavformat/mxfenc.c
> @@ -93,6 +93,7 @@ static const struct {
>      { CODEC_ID_MPEG2VIDEO, 0 },
>      { CODEC_ID_PCM_S24LE,  1 },
>      { CODEC_ID_PCM_S16LE,  1 },
> +    { CODEC_ID_DVVIDEO,   15 },
>      { CODEC_ID_NONE }
>  };
>  
> @@ -169,6 +170,51 @@ static const MXFContainerEssenceEntry mxf_essence_container_uls[] = {
>        { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x06,0x01,0x10,0x00 },
>        { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x02,0x02,0x01,0x00,0x00,0x00,0x00 },
>        mxf_write_generic_sound_desc },
> +    // DV Unknwon 15
> +    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x7F,0x01 },
> +      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
> +      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x00,0x00,0x00 },
> +      mxf_write_cdci_desc },
> +    // DV25 525/60
> +    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x40,0x01 },
> +      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
> +      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x01,0x00 },
> +      mxf_write_cdci_desc },
> +    // DV25 625/50
> +    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x41,0x01 },
> +      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
> +      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x02,0x00 },
> +      mxf_write_cdci_desc },
> +    // DV50 525/60
> +    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x50,0x01 },
> +      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
> +      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x03,0x00 },
> +      mxf_write_cdci_desc },
> +    // DV50 625/50
> +    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x51,0x01 },
> +      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
> +      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x04,0x00 },
> +      mxf_write_cdci_desc },
> +    // DV100 1080/60
> +    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x60,0x01 },
> +      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
> +      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x05,0x00 },
> +      mxf_write_cdci_desc },
> +    // DV100 1080/50
> +    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x61,0x01 },
> +      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
> +      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x06,0x00 },
> +      mxf_write_cdci_desc },
> +    // DV100 720/60
> +    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x62,0x01 },
> +      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
> +      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x07,0x00 },
> +      mxf_write_cdci_desc },
> +    // DV100 720/50
> +    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x0D,0x01,0x03,0x01,0x02,0x02,0x63,0x01 },
> +      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x18,0x01,0x01,0x00 },
> +      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x04,0x01,0x02,0x02,0x02,0x02,0x08,0x00 },
> +      mxf_write_cdci_desc },
>      { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
>        { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
>        { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
> @@ -1292,6 +1338,70 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid,
>      avio_flush(pb);
>  }
>  
> +static int mxf_parse_dv_frame(AVFormatContext *s, AVStream *st, AVPacket *pkt)
> +{
> +    MXFContext *mxf = s->priv_data;
> +    MXFStreamContext *sc = st->priv_data;
> +    uint8_t *vs_pack = pkt->data + 80*5 + 48;
> +    uint8_t *vsc_pack = pkt->data + 80*5 + 53;
> +    int stype = vs_pack[3] & 0x1f;
> +    int pal = (vs_pack[3] >> 5) & 0x1;
> +    int i, ul_index, frame_size;
> +
> +    if (mxf->header_written)
> +        return 1;
> +
> +    if ((vs_pack[2] & 0x07) == 0x02)
> +        sc->aspect_ratio = (AVRational){ 16, 9 };
> +    else
> +        sc->aspect_ratio = (AVRational){ 4, 3 };
> +
> +    sc->interlaced = (vsc_pack[3] >> 4) & 0x01;
> +    // TODO: fix dv encoder to set proper FF/FS value in VSC pack
> +    // and set field dominance accordingly
> +    // av_log(s, AV_LOG_DEBUG, "DV vsc pack ff/ss = %x\n", vsc_pack[2] >> 6);
> +
> +    switch (stype) {
> +    case 0x18: // DV100 720p
> +        ul_index = 6 + pal;
> +        frame_size = pal ? 288000 : 240000;
> +        if (sc->interlaced) {
> +            av_log(s, AV_LOG_ERROR, "source marked as interlaced but codec profile is progressive");
> +            sc->interlaced = 0;
> +        }
> +        break;
> +    case 0x14: // DV100 1080i
> +        ul_index = 4 + pal;
> +        frame_size = pal ? 576000 : 480000;
> +        break;
> +    case 0x04: // DV50
> +        ul_index = 2 + pal;
> +        frame_size = pal ? 288000 : 240000;
> +        break;
> +    default: // DV25
> +        ul_index = 0 + pal;
> +        frame_size = pal ? 144000 : 120000;
> +    }
> +
> +    sc->index = ul_index + 16;
> +    sc->codec_ul =  &mxf_essence_container_uls[sc->index].codec_ul;
> +
> +    mxf->edit_unit_byte_count = KAG_SIZE;
> +    for (i = 0; i < s->nb_streams; i++) {
> +        AVStream *st = s->streams[i];
> +        MXFStreamContext *sc = st->priv_data;
> +        if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
> +            mxf->edit_unit_byte_count += 16 + 4 + sc->aic.samples[0]*sc->aic.sample_size;
> +            mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
> +        } else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
> +            mxf->edit_unit_byte_count += 16 + 4 + frame_size;
> +            mxf->edit_unit_byte_count += klv_fill_size(mxf->edit_unit_byte_count);
> +        }
> +    }
> +
> +    return 1;
> +}
> +
>  static const UID mxf_mpeg2_codec_uls[] = {
>      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x10,0x00 }, // MP-ML I-Frame
>      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x03,0x04,0x01,0x02,0x02,0x01,0x01,0x11,0x00 }, // MP-ML Long GOP
> @@ -1536,7 +1646,10 @@ static int mxf_write_header(AVFormatContext *s)
>          MXFStreamContext *sc = s->streams[i]->priv_data;
>          // update element count
>          sc->track_essence_element_key[13] = present[sc->index];
> -        sc->order = AV_RB32(sc->track_essence_element_key+12);
> +        if (sc->track_essence_element_key[12] == 0x18) // DV
> +            sc->order = (0x15 << 24) | AV_RB32(sc->track_essence_element_key+13);
> +        else
> +            sc->order = AV_RB32(sc->track_essence_element_key+12);
>      }
>  
>      if (t = av_dict_get(s->metadata, "creation_time", NULL, 0))
> @@ -1690,6 +1803,11 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt)
>              av_log(s, AV_LOG_ERROR, "could not get mpeg2 profile and level\n");
>              return -1;
>          }
> +    } else if (st->codec->codec_id == CODEC_ID_DVVIDEO) {
> +        if (!mxf_parse_dv_frame(s, st, pkt)) {
> +            av_log(s, AV_LOG_ERROR, "could not get dv profile\n");
> +            return -1;
> +        }
>      }
>  
>      if (!mxf->header_written) {
> -- 
> 1.7.10
> 

Patch updated, I forgot to adjust the first active lines according to SMPTE S314M:
  - 285 for DV 525/60,
  - 335 for DV 625/50.

Regards,
Matthieu
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0004-mxfenc-support-smpte-dv-codecs.patch
Type: text/x-diff
Size: 8495 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20120529/915724f6/attachment.bin>


More information about the ffmpeg-devel mailing list