[FFmpeg-devel] [PATCH 2/2] mxfdec: set audio packets pts

Matthieu Bouron matthieu.bouron at gmail.com
Thu Nov 8 22:12:34 CET 2012


On Thu, Nov 08, 2012 at 05:00:31PM +0100, Tomas Härdin wrote:
> 
> > From 466d6e5f641469e620a8e46b45a8e5e6e256edd1 Mon Sep 17 00:00:00 2001
> > From: Matthieu Bouron <matthieu.bouron at gmail.com>
> > Date: Thu, 13 Sep 2012 21:15:48 +0200
> > Subject: [PATCH] mxfdec: set audio packets pts
> > 
> > Also fix playback of ntsc files.
> > ---
> >  libavformat/mxfdec.c        | 82 +++++++++++++++++++++++++++++++++++++++++++--
> >  tests/ref/fate/mxf-demux    |  6 ++--
> >  tests/ref/lavf/mxf          |  2 +-
> >  tests/ref/seek/lavf_mxf     | 18 +++++-----
> >  tests/ref/seek/lavf_mxf_d10 | 30 ++++++++---------
> >  5 files changed, 107 insertions(+), 31 deletions(-)
> > 
> > diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
> > index b7c0826..b3f6165 100644
> > --- a/libavformat/mxfdec.c
> > +++ b/libavformat/mxfdec.c
> > @@ -46,6 +46,7 @@
> >  //#define DEBUG
> >  
> >  #include "libavutil/aes.h"
> > +#include "libavutil/avassert.h"
> >  #include "libavutil/mathematics.h"
> >  #include "libavcodec/bytestream.h"
> >  #include "libavutil/timecode.h"
> > @@ -132,6 +133,8 @@ typedef struct {
> >      uint8_t track_number[4];
> >      AVRational edit_rate;
> >      int intra_only;
> > +    AVRational time_base;
> 
> Please avoid having multiple points of truth. Also see further down.
> 
> > +static int mxf_compute_sample_count(MXFContext *mxf, int stream_index, uint64_t *sample_count)
> > +{
> > +    int i, total = 0, size = 0;
> > +    AVStream *st = mxf->fc->streams[stream_index];
> > +    MXFTrack *track = st->priv_data;
> > +    AVRational time_base = track->time_base;
> > +    AVRational sample_rate = st->time_base;
> > +    const MXFSamplesPerFrame *spf = NULL;
> > +
> > +    if (av_q2d(sample_rate) == 48000)
> > +        spf = ff_mxf_get_samples_per_frame(mxf->fc, time_base);
> > +    if (!spf) {
> > +        int remainder = (sample_rate.num * time_base.den) % (time_base.num * sample_rate.den);
> > +        *sample_count = mxf->current_edit_unit * (av_q2d(sample_rate) / av_q2d(time_base));
> 
> Inaccurate. Try something like:
> 
>     *sample_count = av_mul_q((AVRational){mxf->current_edit_unit,1},
>                              av_mul_q(sample_rate, track->edit_rate));
> 
> since track->time_base is 1/edit_rate here.

Updated in new patch.

> 
> > +static int mxf_set_audio_pts(MXFContext *mxf, AVCodecContext *codec, AVPacket *pkt)
> > +{
> > +    MXFTrack *track = mxf->fc->streams[pkt->stream_index]->priv_data;
> > +    pkt->pts = track->sample_count;
> > +    track->sample_count += pkt->size / (codec->channels * av_get_bits_per_sample(codec->codec_id) / 8);
> 
> pkt->duration gets set by lavf later, right?

This needs to be checked.

In this third patch, all audio track sample counts are updated in case of
seeking.

Note: audio ptses are broken in case of seeking if the mxf has no index
table; the current_edit_unit is not computed in that case in the
mxf_read_seek function.

Matthieu

[...]
-------------- next part --------------
>From e5305335a528683d673dc679887002f676c4f5fe Mon Sep 17 00:00:00 2001
From: Matthieu Bouron <matthieu.bouron at gmail.com>
Date: Thu, 13 Sep 2012 21:15:48 +0200
Subject: [PATCH] mxfdec: set audio packets pts

Also fix playback of ntsc files.
---
 libavformat/mxfdec.c        | 86 ++++++++++++++++++++++++++++++++++++++++++---
 tests/ref/fate/mxf-demux    |  6 ++--
 tests/ref/lavf/mxf          |  2 +-
 tests/ref/seek/lavf_mxf     | 18 +++++-----
 tests/ref/seek/lavf_mxf_d10 | 30 ++++++++--------
 5 files changed, 110 insertions(+), 32 deletions(-)

diff --git a/libavformat/mxfdec.c b/libavformat/mxfdec.c
index b7c0826..da2eb1f 100644
--- a/libavformat/mxfdec.c
+++ b/libavformat/mxfdec.c
@@ -46,6 +46,7 @@
 //#define DEBUG
 
 #include "libavutil/aes.h"
+#include "libavutil/avassert.h"
 #include "libavutil/mathematics.h"
 #include "libavcodec/bytestream.h"
 #include "libavutil/timecode.h"
@@ -132,6 +133,7 @@ typedef struct {
     uint8_t track_number[4];
     AVRational edit_rate;
     int intra_only;
+    uint64_t sample_count;
 } MXFTrack;
 
 typedef struct {
@@ -1545,8 +1547,14 @@ static int mxf_parse_structural_metadata(MXFContext *mxf)
             st->codec->channels = descriptor->channels;
             st->codec->bits_per_coded_sample = descriptor->bits_per_sample;
 
-            if (descriptor->sample_rate.den > 0)
+            if (descriptor->sample_rate.den > 0) {
+                avpriv_set_pts_info(st, 64, descriptor->sample_rate.den, descriptor->sample_rate.num);
                 st->codec->sample_rate = descriptor->sample_rate.num / descriptor->sample_rate.den;
+            } else {
+                av_log(mxf->fc, AV_LOG_WARNING, "invalid sample rate (%d/%d) found for stream #%d, time base forced to 1/48000\n",
+                       descriptor->sample_rate.num, descriptor->sample_rate.den, st->index);
+                avpriv_set_pts_info(st, 64, 1, 48000);
+            }
 
             /* TODO: implement AV_CODEC_ID_RAWAUDIO */
             if (st->codec->codec_id == AV_CODEC_ID_PCM_S16LE) {
@@ -1986,6 +1994,51 @@ static int64_t mxf_set_current_edit_unit(MXFContext *mxf, int64_t current_offset
     return next_ofs;
 }
 
+static int mxf_compute_sample_count(MXFContext *mxf, int stream_index, uint64_t *sample_count)
+{
+    int i, total = 0, size = 0;
+    AVStream *st = mxf->fc->streams[stream_index];
+    MXFTrack *track = st->priv_data;
+    AVRational time_base = av_inv_q(track->edit_rate);
+    AVRational sample_rate = av_inv_q(st->time_base);
+    const MXFSamplesPerFrame *spf = NULL;
+
+    if (av_q2d(sample_rate) == 48000)
+        spf = ff_mxf_get_samples_per_frame(mxf->fc, time_base);
+    if (!spf) {
+        int remainder = (sample_rate.num * time_base.num) % (time_base.den * sample_rate.den);
+        *sample_count = av_q2d(av_mul_q((AVRational){mxf->current_edit_unit, 1},
+                                        av_mul_q(sample_rate, time_base)));
+        if (remainder)
+            av_log(mxf->fc, AV_LOG_WARNING,
+                   "seeking detected on stream #%d with time base (%d/%d) and sample rate (%d/%d), audio pts won't be accurate.\n",
+                   stream_index, time_base.num, time_base.den, sample_rate.num, sample_rate.den);
+        return 0;
+    }
+
+    while (spf->samples_per_frame[size]) {
+        total += spf->samples_per_frame[size];
+        size++;
+    }
+
+    av_assert2(size);
+
+    *sample_count = (mxf->current_edit_unit / size) * total;
+    for (i = 0; i < mxf->current_edit_unit % size; i++) {
+        *sample_count += spf->samples_per_frame[i];
+    }
+
+    return 0;
+}
+
+static int mxf_set_audio_pts(MXFContext *mxf, AVCodecContext *codec, AVPacket *pkt)
+{
+    MXFTrack *track = mxf->fc->streams[pkt->stream_index]->priv_data;
+    pkt->pts = track->sample_count;
+    track->sample_count += pkt->size / (codec->channels * av_get_bits_per_sample(codec->codec_id) / 8);
+    return 0;
+}
+
 static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
 {
     KLVPacket klv;
@@ -2011,6 +2064,7 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
             int64_t next_ofs, next_klv;
             AVStream *st;
             MXFTrack *track;
+            AVCodecContext *codec;
 
             if (index < 0) {
                 av_log(s, AV_LOG_ERROR, "error getting stream index %d\n", AV_RB32(klv.key+12));
@@ -2049,7 +2103,8 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
             pkt->stream_index = index;
             pkt->pos = klv.offset;
 
-            if (s->streams[index]->codec->codec_type == AVMEDIA_TYPE_VIDEO && next_ofs >= 0) {
+            codec = s->streams[index]->codec;
+            if (codec->codec_type == AVMEDIA_TYPE_VIDEO && next_ofs >= 0) {
                 /* mxf->current_edit_unit good - see if we have an index table to derive timestamps from */
                 MXFIndexTable *t = &mxf->index_tables[0];
 
@@ -2061,6 +2116,10 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt)
                      * let utils.c figure out DTS since it can be < PTS if low_delay = 0 (Sony IMX30) */
                     pkt->pts = mxf->current_edit_unit;
                 }
+            } else if (codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+                int ret = mxf_set_audio_pts(mxf, codec, pkt);
+                if (ret < 0)
+                    return ret;
             }
 
             /* seek for truncated packets */
@@ -2118,13 +2177,18 @@ static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt)
     if ((size = av_get_packet(s->pb, pkt, size)) < 0)
         return size;
 
+    pkt->stream_index = 0;
+
     if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && t->ptses &&
         mxf->current_edit_unit >= 0 && mxf->current_edit_unit < t->nb_ptses) {
         pkt->dts = mxf->current_edit_unit + t->first_dts;
         pkt->pts = t->ptses[mxf->current_edit_unit];
+    } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+        int ret = mxf_set_audio_pts(mxf, st->codec, pkt);
+        if (ret < 0)
+            return ret;
     }
 
-    pkt->stream_index = 0;
     mxf->current_edit_unit += edit_units;
 
     return 0;
@@ -2203,7 +2267,7 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
     int64_t seconds;
     MXFContext* mxf = s->priv_data;
     int64_t seekpos;
-    int ret;
+    int i, ret;
     MXFIndexTable *t;
 
     if (mxf->nb_index_tables <= 0) {
@@ -2240,6 +2304,20 @@ static int mxf_read_seek(AVFormatContext *s, int stream_index, int64_t sample_ti
         mxf->current_edit_unit = sample_time;
         avio_seek(s->pb, seekpos, SEEK_SET);
     }
+
+    // Update all tracks sample count
+    for (i = 0; i < s->nb_streams; i++) {
+        AVStream *cur_st = s->streams[i];
+        MXFTrack *cur_track = cur_st->priv_data;
+        uint64_t current_sample_count = 0;
+        if (cur_st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
+            ret = mxf_compute_sample_count(mxf, i, &current_sample_count);
+            if (ret < 0)
+                return ret;
+
+            cur_track->sample_count = current_sample_count;
+        }
+    }
     return 0;
 }
 
diff --git a/tests/ref/fate/mxf-demux b/tests/ref/fate/mxf-demux
index c67c4ab..454722e 100644
--- a/tests/ref/fate/mxf-demux
+++ b/tests/ref/fate/mxf-demux
@@ -1,7 +1,7 @@
 #tb 0: 1/25
-#tb 1: 1/25
+#tb 1: 1/8000
 0,          0, -9223372036854775808,        1,     8468, 0xc0855553
-1,          0,          0,       50,    32000, 0x479155e6
+1,          0,          0,    16000,    32000, 0x479155e6
 0,          1, -9223372036854775808,        1,     3814, 0xa10783b4, F=0x0
 0,          2, -9223372036854775808,        1,     3747, 0xb7bf6973, F=0x0
 0,          3, -9223372036854775808,        1,     3705, 0x5462a600, F=0x0
@@ -52,7 +52,7 @@
 0,         48, -9223372036854775808,        1,     3688, 0x1db45852, F=0x0
 0,         49, -9223372036854775808,        1,    38412, 0x2ee26a63, F=0x0
 0,         50, -9223372036854775808,        1,     8385, 0x0bc20a27
-1,         50,         50,       50,    32000, 0x8f7e5009
+1,      16000,      16000,    16000,    32000, 0x8f7e5009
 0,         51, -9223372036854775808,        1,     3733, 0xa3e2a9a0, F=0x0
 0,         52, -9223372036854775808,        1,     3773, 0x27769caa, F=0x0
 0,         53, -9223372036854775808,        1,     3670, 0xc8335e98, F=0x0
diff --git a/tests/ref/lavf/mxf b/tests/ref/lavf/mxf
index d8aeb4a..e1473cc 100644
--- a/tests/ref/lavf/mxf
+++ b/tests/ref/lavf/mxf
@@ -3,7 +3,7 @@
 ./tests/data/lavf/lavf.mxf CRC=0x17ce1069
 830a8b9ee58781bf654c55905067cdae *./tests/data/lavf/lavf.mxf
 554553 ./tests/data/lavf/lavf.mxf
-./tests/data/lavf/lavf.mxf CRC=0xa3c0dbc4
+./tests/data/lavf/lavf.mxf CRC=0x468cdbc4
 10c6ae1bd97c851728c9abad9dddfa2e *./tests/data/lavf/lavf.mxf
 525369 ./tests/data/lavf/lavf.mxf
 ./tests/data/lavf/lavf.mxf CRC=0x17ce1069
diff --git a/tests/ref/seek/lavf_mxf b/tests/ref/seek/lavf_mxf
index f7d1f67..34dddc3 100644
--- a/tests/ref/seek/lavf_mxf
+++ b/tests/ref/seek/lavf_mxf
@@ -7,8 +7,8 @@ ret: 0         st: 0 flags:0  ts: 0.800000
 ret: 0         st: 0 flags:1 dts: 0.840000 pts: 0.960000 pos: 460288 size: 24711
 ret: 0         st: 0 flags:1  ts:-0.320000
 ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   6144 size: 24801
-ret:-1         st: 1 flags:0  ts: 2.560000
-ret: 0         st: 1 flags:1  ts: 1.480000
+ret:-1         st: 1 flags:0  ts: 2.576667
+ret: 0         st: 1 flags:1  ts: 1.470833
 ret: 0         st: 0 flags:1 dts: 0.840000 pts: 0.960000 pos: 460288 size: 24711
 ret: 0         st:-1 flags:0  ts: 0.365002
 ret: 0         st: 0 flags:1 dts: 0.360000 pts: 0.480000 pos: 211456 size: 24786
@@ -17,9 +17,9 @@ ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   6144 size: 24801
 ret:-1         st: 0 flags:0  ts: 2.160000
 ret: 0         st: 0 flags:1  ts: 1.040000
 ret: 0         st: 0 flags:1 dts: 0.840000 pts: 0.960000 pos: 460288 size: 24711
-ret: 0         st: 1 flags:0  ts:-0.040000
+ret: 0         st: 1 flags:0  ts:-0.058333
 ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   6144 size: 24801
-ret: 0         st: 1 flags:1  ts: 2.840000
+ret: 0         st: 1 flags:1  ts: 2.835833
 ret: 0         st: 0 flags:1 dts: 0.840000 pts: 0.960000 pos: 460288 size: 24711
 ret:-1         st:-1 flags:0  ts: 1.730004
 ret: 0         st:-1 flags:1  ts: 0.624171
@@ -28,9 +28,9 @@ ret: 0         st: 0 flags:0  ts:-0.480000
 ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   6144 size: 24801
 ret: 0         st: 0 flags:1  ts: 2.400000
 ret: 0         st: 0 flags:1 dts: 0.840000 pts: 0.960000 pos: 460288 size: 24711
-ret:-1         st: 1 flags:0  ts: 1.320000
-ret: 0         st: 1 flags:1  ts: 0.200000
-ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   6144 size: 24801
+ret:-1         st: 1 flags:0  ts: 1.306667
+ret: 0         st: 1 flags:1  ts: 0.200833
+ret: 0         st: 0 flags:1 dts: 0.840000 pts: 0.960000 pos: 460288 size: 24711
 ret: 0         st:-1 flags:0  ts:-0.904994
 ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   6144 size: 24801
 ret: 0         st:-1 flags:1  ts: 1.989173
@@ -39,8 +39,8 @@ ret: 0         st: 0 flags:0  ts: 0.880000
 ret: 0         st: 0 flags:1 dts: 0.840000 pts: 0.960000 pos: 460288 size: 24711
 ret: 0         st: 0 flags:1  ts:-0.240000
 ret: 0         st: 0 flags:1 dts:-0.040000 pts: 0.000000 pos:   6144 size: 24801
-ret:-1         st: 1 flags:0  ts: 2.680000
-ret: 0         st: 1 flags:1  ts: 1.560000
+ret:-1         st: 1 flags:0  ts: 2.671667
+ret: 0         st: 1 flags:1  ts: 1.565833
 ret: 0         st: 0 flags:1 dts: 0.840000 pts: 0.960000 pos: 460288 size: 24711
 ret: 0         st:-1 flags:0  ts: 0.460008
 ret: 0         st: 0 flags:1 dts: 0.840000 pts: 0.960000 pos: 460288 size: 24711
diff --git a/tests/ref/seek/lavf_mxf_d10 b/tests/ref/seek/lavf_mxf_d10
index 4cfe595..e091c77 100644
--- a/tests/ref/seek/lavf_mxf_d10
+++ b/tests/ref/seek/lavf_mxf_d10
@@ -7,10 +7,10 @@ ret: 0         st: 0 flags:0  ts: 0.800000
 ret: 0         st: 0 flags:1 dts: 0.800000 pts: 0.800000 pos:4265984 size:150000
 ret: 0         st: 0 flags:1  ts:-0.320000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   6144 size:150000
-ret: 0         st: 1 flags:0  ts: 2.560000
-ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000
-ret: 0         st: 1 flags:1  ts: 1.480000
-ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000
+ret: 0         st: 1 flags:0  ts: 2.576667
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000
+ret: 0         st: 1 flags:1  ts: 1.470833
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000
 ret: 0         st:-1 flags:0  ts: 0.365002
 ret: 0         st: 0 flags:1 dts: 0.360000 pts: 0.360000 pos:1923072 size:150000
 ret: 0         st:-1 flags:1  ts:-0.740831
@@ -19,10 +19,10 @@ ret: 0         st: 0 flags:0  ts: 2.160000
 ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000
 ret: 0         st: 0 flags:1  ts: 1.040000
 ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000
-ret: 0         st: 1 flags:0  ts:-0.040000
+ret: 0         st: 1 flags:0  ts:-0.058333
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   6144 size:150000
-ret: 0         st: 1 flags:1  ts: 2.840000
-ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000
+ret: 0         st: 1 flags:1  ts: 2.835833
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000
 ret: 0         st:-1 flags:0  ts: 1.730004
 ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000
 ret: 0         st:-1 flags:1  ts: 0.624171
@@ -31,10 +31,10 @@ ret: 0         st: 0 flags:0  ts:-0.480000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   6144 size:150000
 ret: 0         st: 0 flags:1  ts: 2.400000
 ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000
-ret: 0         st: 1 flags:0  ts: 1.320000
-ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000
-ret: 0         st: 1 flags:1  ts: 0.200000
-ret: 0         st: 0 flags:1 dts: 0.200000 pts: 0.200000 pos:1071104 size:150000
+ret: 0         st: 1 flags:0  ts: 1.306667
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000
+ret: 0         st: 1 flags:1  ts: 0.200833
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000
 ret: 0         st:-1 flags:0  ts:-0.904994
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   6144 size:150000
 ret: 0         st:-1 flags:1  ts: 1.989173
@@ -43,10 +43,10 @@ ret: 0         st: 0 flags:0  ts: 0.880000
 ret: 0         st: 0 flags:1 dts: 0.880000 pts: 0.880000 pos:4691968 size:150000
 ret: 0         st: 0 flags:1  ts:-0.240000
 ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:   6144 size:150000
-ret: 0         st: 1 flags:0  ts: 2.680000
-ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000
-ret: 0         st: 1 flags:1  ts: 1.560000
-ret: 0         st: 0 flags:1 dts: 0.960000 pts: 0.960000 pos:5117952 size:150000
+ret: 0         st: 1 flags:0  ts: 2.671667
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000
+ret: 0         st: 1 flags:1  ts: 1.565833
+ret: 0         st: 0 flags:1 dts: 0.000000 pts: 0.000000 pos:5117952 size:150000
 ret: 0         st:-1 flags:0  ts: 0.460008
 ret: 0         st: 0 flags:1 dts: 0.480000 pts: 0.480000 pos:2562048 size:150000
 ret: 0         st:-1 flags:1  ts:-0.645825
-- 
1.8.0



More information about the ffmpeg-devel mailing list