[FFmpeg-devel,v2] lavf/mxfenc: support creating s436m data tracks

Submitted by Baptiste Coudurier on July 4, 2018, 10:06 p.m.

Details

Message ID 20180704220654.75605-1-baptiste.coudurier@gmail.com
State New
Headers show

Commit Message

Baptiste Coudurier July 4, 2018, 10:06 p.m.
---
 libavformat/mxf.c    |  1 +
 libavformat/mxfdec.c |  2 ++
 libavformat/mxfenc.c | 41 +++++++++++++++++++++++++++++++++++++----
 libavformat/utils.c  |  6 +++++-
 4 files changed, 45 insertions(+), 5 deletions(-)

Comments

Marton Balint July 4, 2018, 10:54 p.m.
On Wed, 4 Jul 2018, Baptiste Coudurier wrote:

> ---
> libavformat/mxf.c    |  1 +
> libavformat/mxfdec.c |  2 ++
> libavformat/mxfenc.c | 41 +++++++++++++++++++++++++++++++++++++----
> libavformat/utils.c  |  6 +++++-
> 4 files changed, 45 insertions(+), 5 deletions(-)
>
> diff --git a/libavformat/mxf.c b/libavformat/mxf.c
> index 8376a2b9bf..451cbcfb2c 100644
> --- a/libavformat/mxf.c
> +++ b/libavformat/mxf.c
> @@ -28,6 +28,7 @@
> const MXFCodecUL ff_mxf_data_definition_uls[] = {
>     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x02,0x01,0x00,0x00,0x00 }, 13, AVMEDIA_TYPE_VIDEO },
>     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x02,0x02,0x00,0x00,0x00 }, 13, AVMEDIA_TYPE_AUDIO },
> +    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x02,0x03,0x00,0x00,0x00 }, 13, AVMEDIA_TYPE_DATA },
>     { { 0x80,0x7D,0x00,0x60,0x08,0x14,0x3E,0x6F,0x6F,0x3C,0x8C,0xE1,0x6C,0xEF,0x11,0xD2 }, 16, AVMEDIA_TYPE_VIDEO }, /* LegacyPicture Avid Media Composer MXF */
>     { { 0x80,0x7D,0x00,0x60,0x08,0x14,0x3E,0x6F,0x78,0xE1,0xEB,0xE1,0x6C,0xEF,0x11,0xD2 }, 16, AVMEDIA_TYPE_AUDIO }, /* LegacySound Avid Media Composer MXF */
>     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0,  AVMEDIA_TYPE_DATA },
> diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
> index b76beb962f..575126d639 100644
> --- a/libavformat/mxfdec.c
> +++ b/libavformat/mxfdec.c
> @@ -3299,6 +3299,8 @@ static int mxf_set_pts(MXFContext *mxf, AVStream *st, AVPacket *pkt)
>             return ret;
>     } else if (track) {
>         track->sample_count++;
> +        pkt->dts = pkt->pts = track->sample_count;
> +        pkt->duration = 1;

You probably need to set pts before increasing sample_count.

Regards,
Marton
Baptiste Coudurier July 19, 2018, 3:36 p.m.
Hi Marton,

Yes, changed.
Michael, are you OK with the utils.c changes ? To be able to remux data
tracks.

Thanks!
Michael Niedermayer July 19, 2018, 9:31 p.m.
On Wed, Jul 04, 2018 at 03:06:54PM -0700, Baptiste Coudurier wrote:
> ---
>  libavformat/mxf.c    |  1 +
>  libavformat/mxfdec.c |  2 ++
>  libavformat/mxfenc.c | 41 +++++++++++++++++++++++++++++++++++++----
>  libavformat/utils.c  |  6 +++++-
>  4 files changed, 45 insertions(+), 5 deletions(-)
[...]
> diff --git a/libavformat/utils.c b/libavformat/utils.c
> index c9cdd2b470..36a32ad9c2 100644
> --- a/libavformat/utils.c
> +++ b/libavformat/utils.c
> @@ -1003,6 +1003,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
>          *pnum = frame_size;
>          *pden = sample_rate;
>          break;
> +    case AVMEDIA_TYPE_DATA:
> +        *pnum = st->time_base.num;
> +        *pden = st->time_base.den;
> +        break;
>      default:
>          break;
>      }
> @@ -1405,7 +1409,7 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
>              presentation_delayed, delay, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts));
>  
>      /* update flags */
> -    if (is_intra_only(st->codecpar->codec_id))
> +    if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA || is_intra_only(st->codecpar->codec_id))
>          pkt->flags |= AV_PKT_FLAG_KEY;
>  #if FF_API_CONVERGENCE_DURATION
>  FF_DISABLE_DEPRECATION_WARNINGS

This should be a seperate patch.
Also i think forcing duration=1 is not correct for all AVMEDIA_TYPE_DATA
for example there are ID3 and fonts. These would i guess if they have a
timebase set apply to more than 1 "unit"

[...]
Baptiste Coudurier Sept. 24, 2018, 8:55 p.m.
On Thu, Jul 19, 2018 at 2:32 PM Michael Niedermayer <michael@niedermayer.cc>
wrote:

> On Wed, Jul 04, 2018 at 03:06:54PM -0700, Baptiste Coudurier wrote:
> > ---
> >  libavformat/mxf.c    |  1 +
> >  libavformat/mxfdec.c |  2 ++
> >  libavformat/mxfenc.c | 41 +++++++++++++++++++++++++++++++++++++----
> >  libavformat/utils.c  |  6 +++++-
> >  4 files changed, 45 insertions(+), 5 deletions(-)
> [...]
> > diff --git a/libavformat/utils.c b/libavformat/utils.c
> > index c9cdd2b470..36a32ad9c2 100644
> > --- a/libavformat/utils.c
> > +++ b/libavformat/utils.c
> > @@ -1003,6 +1003,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
> >          *pnum = frame_size;
> >          *pden = sample_rate;
> >          break;
> > +    case AVMEDIA_TYPE_DATA:
> > +        *pnum = st->time_base.num;
> > +        *pden = st->time_base.den;
> > +        break;
> >      default:
> >          break;
> >      }
> > @@ -1405,7 +1409,7 @@ static void compute_pkt_fields(AVFormatContext *s,
> AVStream *st,
> >              presentation_delayed, delay, av_ts2str(pkt->pts),
> av_ts2str(pkt->dts), av_ts2str(st->cur_dts));
> >
> >      /* update flags */
> > -    if (is_intra_only(st->codecpar->codec_id))
> > +    if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
> is_intra_only(st->codecpar->codec_id))
> >          pkt->flags |= AV_PKT_FLAG_KEY;
> >  #if FF_API_CONVERGENCE_DURATION
> >  FF_DISABLE_DEPRECATION_WARNINGS
>
> This should be a seperate patch.
> Also i think forcing duration=1 is not correct for all AVMEDIA_TYPE_DATA
> for example there are ID3 and fonts. These would i guess if they have a
> timebase set apply to more than 1 "unit"
>

I applied the separate patch.
Will apply this patch shortly, addressing Marton comment.

Thanks!
Baptiste Coudurier Oct. 12, 2018, 7:34 p.m.
On Mon, Sep 24, 2018 at 1:55 PM Baptiste Coudurier <
baptiste.coudurier@gmail.com> wrote:

> On Thu, Jul 19, 2018 at 2:32 PM Michael Niedermayer <michael@niedermayer.cc>
> wrote:
>
>> On Wed, Jul 04, 2018 at 03:06:54PM -0700, Baptiste Coudurier wrote:
>> > ---
>> >  libavformat/mxf.c    |  1 +
>> >  libavformat/mxfdec.c |  2 ++
>> >  libavformat/mxfenc.c | 41 +++++++++++++++++++++++++++++++++++++----
>> >  libavformat/utils.c  |  6 +++++-
>> >  4 files changed, 45 insertions(+), 5 deletions(-)
>> [...]
>> > diff --git a/libavformat/utils.c b/libavformat/utils.c
>> > index c9cdd2b470..36a32ad9c2 100644
>> > --- a/libavformat/utils.c
>> > +++ b/libavformat/utils.c
>> > @@ -1003,6 +1003,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
>> >          *pnum = frame_size;
>> >          *pden = sample_rate;
>> >          break;
>> > +    case AVMEDIA_TYPE_DATA:
>> > +        *pnum = st->time_base.num;
>> > +        *pden = st->time_base.den;
>> > +        break;
>> >      default:
>> >          break;
>> >      }
>> > @@ -1405,7 +1409,7 @@ static void compute_pkt_fields(AVFormatContext
>> *s, AVStream *st,
>> >              presentation_delayed, delay, av_ts2str(pkt->pts),
>> av_ts2str(pkt->dts), av_ts2str(st->cur_dts));
>> >
>> >      /* update flags */
>> > -    if (is_intra_only(st->codecpar->codec_id))
>> > +    if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA ||
>> is_intra_only(st->codecpar->codec_id))
>> >          pkt->flags |= AV_PKT_FLAG_KEY;
>> >  #if FF_API_CONVERGENCE_DURATION
>> >  FF_DISABLE_DEPRECATION_WARNINGS
>>
>> This should be a seperate patch.
>> Also i think forcing duration=1 is not correct for all AVMEDIA_TYPE_DATA
>> for example there are ID3 and fonts. These would i guess if they have a
>> timebase set apply to more than 1 "unit"
>>
>
> I applied the separate patch.
> Will apply this patch shortly, addressing Marton comment.
>
> Thanks!
>

Applied.

Patch hide | download patch | download mbox

diff --git a/libavformat/mxf.c b/libavformat/mxf.c
index 8376a2b9bf..451cbcfb2c 100644
--- a/libavformat/mxf.c
+++ b/libavformat/mxf.c
@@ -28,6 +28,7 @@ 
 const MXFCodecUL ff_mxf_data_definition_uls[] = {
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x02,0x01,0x00,0x00,0x00 }, 13, AVMEDIA_TYPE_VIDEO },
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x02,0x02,0x00,0x00,0x00 }, 13, AVMEDIA_TYPE_AUDIO },
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x01,0x01,0x03,0x02,0x02,0x03,0x00,0x00,0x00 }, 13, AVMEDIA_TYPE_DATA },
     { { 0x80,0x7D,0x00,0x60,0x08,0x14,0x3E,0x6F,0x6F,0x3C,0x8C,0xE1,0x6C,0xEF,0x11,0xD2 }, 16, AVMEDIA_TYPE_VIDEO }, /* LegacyPicture Avid Media Composer MXF */
     { { 0x80,0x7D,0x00,0x60,0x08,0x14,0x3E,0x6F,0x78,0xE1,0xEB,0xE1,0x6C,0xEF,0x11,0xD2 }, 16, AVMEDIA_TYPE_AUDIO }, /* LegacySound Avid Media Composer MXF */
     { { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },  0,  AVMEDIA_TYPE_DATA },
diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index b76beb962f..575126d639 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -3299,6 +3299,8 @@  static int mxf_set_pts(MXFContext *mxf, AVStream *st, AVPacket *pkt)
             return ret;
     } else if (track) {
         track->sample_count++;
+        pkt->dts = pkt->pts = track->sample_count;
+        pkt->duration = 1;
     }
     return 0;
 }
diff --git a/libavformat/mxfenc.c b/libavformat/mxfenc.c
index 036adce011..6da27bf4f5 100644
--- a/libavformat/mxfenc.c
+++ b/libavformat/mxfenc.c
@@ -175,6 +175,7 @@  static void mxf_write_aes3_desc(AVFormatContext *s, AVStream *st);
 static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st);
 static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st);
 static void mxf_write_generic_sound_desc(AVFormatContext *s, AVStream *st);
+static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st);
 
 static const MXFContainerEssenceEntry mxf_essence_container_uls[] = {
     { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x02,0x0D,0x01,0x03,0x01,0x02,0x04,0x60,0x01 },
@@ -361,6 +362,11 @@  static const MXFContainerEssenceEntry mxf_essence_container_uls[] = {
       { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x15,0x01,0x05,0x00 },
       { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x00,0x00,0x00 },
       mxf_write_mpegvideo_desc },
+    // S436M ANC
+    { { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x0D,0x01,0x03,0x01,0x02,0x0e,0x00,0x00 },
+      { 0x06,0x0E,0x2B,0x34,0x01,0x02,0x01,0x01,0x0D,0x01,0x03,0x01,0x17,0x01,0x02,0x00 },
+      { 0x06,0x0E,0x2B,0x34,0x04,0x01,0x01,0x0a,0x04,0x01,0x02,0x02,0x01,0x01,0x5C,0x00 },
+      mxf_write_s436m_anc_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 },
@@ -695,9 +701,14 @@  static void mxf_write_essence_container_refs(AVFormatContext *s)
 
     mxf_write_refs_count(pb, DESCRIPTOR_COUNT(c->essence_container_count));
     av_log(s,AV_LOG_DEBUG, "essence container count:%d\n", c->essence_container_count);
-    for (i = 0; i < c->essence_container_count; i++) {
+    for (i = 0; i < s->nb_streams; i++) {
         MXFStreamContext *sc = s->streams[i]->priv_data;
+        // check first track of essence container type and only write it once
+        if (sc->track_essence_element_key[15] != 0)
+            continue;
         avio_write(pb, mxf_essence_container_uls[sc->index].container_ul, 16);
+        if (c->essence_container_count == 1)
+            break;
     }
 
     if (c->essence_container_count > 1)
@@ -1154,6 +1165,7 @@  static int64_t mxf_write_generic_desc(AVFormatContext *s, AVStream *st, const UI
     return pos;
 }
 
+static const UID mxf_s436m_anc_descriptor_key = { 0x06,0x0e,0x2b,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x5c,0x00 };
 static const UID mxf_mpegvideo_descriptor_key = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x51,0x00 };
 static const UID mxf_wav_descriptor_key       = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x48,0x00 };
 static const UID mxf_aes3_descriptor_key      = { 0x06,0x0E,0x2B,0x34,0x02,0x53,0x01,0x01,0x0d,0x01,0x01,0x01,0x01,0x01,0x47,0x00 };
@@ -1369,6 +1381,12 @@  static void mxf_write_cdci_desc(AVFormatContext *s, AVStream *st)
     mxf_update_klv_size(s->pb, pos);
 }
 
+static void mxf_write_s436m_anc_desc(AVFormatContext *s, AVStream *st)
+{
+    int64_t pos = mxf_write_generic_desc(s, st, mxf_s436m_anc_descriptor_key);
+    mxf_update_klv_size(s->pb, pos);
+}
+
 static void mxf_write_mpegvideo_desc(AVFormatContext *s, AVStream *st)
 {
     AVIOContext *pb = s->pb;
@@ -1723,6 +1741,7 @@  static void mxf_write_index_table_segment(AVFormatContext *s)
     int i, j, temporal_reordering = 0;
     int key_index = mxf->last_key_index;
     int prev_non_b_picture = 0;
+    int audio_frame_size = 0;
     int64_t pos;
 
     av_log(s, AV_LOG_DEBUG, "edit units count %d\n", mxf->edit_units_count);
@@ -1792,9 +1811,11 @@  static void mxf_write_index_table_segment(AVFormatContext *s)
         } else if (i == 0) { // video track
             avio_w8(pb, 0); // slice number
             avio_wb32(pb, KAG_SIZE); // system item size including klv fill
-        } else { // audio track
-            unsigned audio_frame_size = sc->aic.samples[0]*sc->aic.sample_size;
-            audio_frame_size += klv_fill_size(audio_frame_size);
+        } else { // audio or data track
+            if (!audio_frame_size) {
+                audio_frame_size = sc->aic.samples[0]*sc->aic.sample_size;
+                audio_frame_size += klv_fill_size(audio_frame_size);
+            }
             avio_w8(pb, 1);
             avio_wb32(pb, (i-1)*audio_frame_size); // element delta
         }
@@ -2505,6 +2526,18 @@  static int mxf_write_header(AVFormatContext *s)
                 sc->frame_size = (st->codecpar->channels * spf[0].samples_per_frame[0] *
                                   av_get_bits_per_sample(st->codecpar->codec_id)) / 8;
             }
+        } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) {
+            AVDictionaryEntry *e = av_dict_get(st->metadata, "data_type", NULL, 0);
+            if (e && !strcmp(e->value, "vbi_vanc_smpte_436M")) {
+                sc->index = 38;
+            } else {
+                av_log(s, AV_LOG_ERROR, "track %d: unsupported data type\n", i);
+                return -1;
+            }
+            if (st->index != s->nb_streams - 1) {
+                av_log(s, AV_LOG_ERROR, "data track must be placed last\n");
+                return -1;
+            }
         }
 
         if (!sc->index) {
diff --git a/libavformat/utils.c b/libavformat/utils.c
index c9cdd2b470..36a32ad9c2 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -1003,6 +1003,10 @@  FF_ENABLE_DEPRECATION_WARNINGS
         *pnum = frame_size;
         *pden = sample_rate;
         break;
+    case AVMEDIA_TYPE_DATA:
+        *pnum = st->time_base.num;
+        *pden = st->time_base.den;
+        break;
     default:
         break;
     }
@@ -1405,7 +1409,7 @@  static void compute_pkt_fields(AVFormatContext *s, AVStream *st,
             presentation_delayed, delay, av_ts2str(pkt->pts), av_ts2str(pkt->dts), av_ts2str(st->cur_dts));
 
     /* update flags */
-    if (is_intra_only(st->codecpar->codec_id))
+    if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA || is_intra_only(st->codecpar->codec_id))
         pkt->flags |= AV_PKT_FLAG_KEY;
 #if FF_API_CONVERGENCE_DURATION
 FF_DISABLE_DEPRECATION_WARNINGS