[FFmpeg-devel] [PATCH] Implemented arrange feature to convert from low timebase formats to high timebase

Roman Arutyunyan arutyunyan.roman at gmail.com
Thu Oct 18 07:47:21 CEST 2012


2012/10/18 Roman Arutyunyan <arutyunyan.roman at gmail.com>

> 2012/10/18 Michael Niedermayer <michaelni at gmx.at>
>
>> On Wed, Oct 17, 2012 at 07:14:07PM +0400, Roman Arutyunyan wrote:
>> > 2012/10/17 Michael Niedermayer <michaelni at gmx.at>
>> >
>> > > On Wed, Oct 17, 2012 at 11:34:58AM +0400, Roman Arutyunyan wrote:
>> > > [...]
>> > > >  AVRational av_codec_get_pkt_timebase         (const AVCodecContext
>> > > *avctx);
>> > > > diff --git a/libavformat/utils.c b/libavformat/utils.c
>> > > > index 05c4b7f..0b59eeb 100644
>> > > > --- a/libavformat/utils.c
>> > > > +++ b/libavformat/utils.c
>> > > > @@ -3498,6 +3498,14 @@ static int
>> compute_pkt_fields2(AVFormatContext
>> > > *s, AVStream *st, AVPacket *pkt){
>> > > >      if(pkt->pts == AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE &&
>> > > delay==0)
>> > > >          pkt->pts= pkt->dts;
>> > > >
>> > > > +    if (st->codec->arrange_threshold && pkt->dts != AV_NOPTS_VALUE
>> &&
>> > > st->pts.val != AV_NOPTS_VALUE){
>> > > > +        int64_t diff = pkt->dts - st->pts.val;
>> > > > +        int64_t maxdiff = av_rescale(st->codec->arrange_threshold,
>> > > st->time_base.den, AV_TIME_BASE * (int64_t)st->time_base.num);
>> > > > +        av_dlog(s, "Arrange dts=%"PRId64" cur_dts=%"PRId64"
>> > > diff=%"PRId64" maxdiff=%"PRId64"\n", pkt->dts, st->pts.val, diff,
>> maxdiff);
>> > > > +        if (diff > -maxdiff && diff < maxdiff)
>> > > > +            pkt->dts = pkt->pts = AV_NOPTS_VALUE;
>> > > > +    }
>> > >
>> > > this doesnt look correct. The correction should be done where the
>> > > problem is currently introduced. As done here , ffmpeg.c would send
>> > > some timestamps to the muxer but the muxer would use different
>> > > timestamps. its ffmpeg*.c or a common utility function used by
>> > > ffmpeg*.c where the correction should be done.
>> > >
>> > > Currently timestamps are rounded toward "nearest", what should
>> > > instead be done, is to round toward the exact duration + last_time
>> > > see av_get_audio_frame_duration() to find the exact frame duration.
>> > >
>> >
>> > I'm absolutely agree with you. The reason why I've done that way is
>> there's
>> > nothing
>> > that looks like last_time on earlier stages of frame processing
>> (ffmpeg.c).
>>
>> if at the location where the issue is introduced there really is no
>> last timestamp variable then its quite easy to add one.
>>
>>
> I looked into write_frame in ffmpeg.c. It operates with ost->st->...
> fields a lot.
> So what do you think about moving the code from where it
> is now to write_frame with accessing the same data (ost->st->pts.val) from
> there.
> because ost->st->pts.val is exactly what we need (last_time).
>
> Michael, is that a good solution to reset the timestamps (pkt->dts =
> pkt->pts = AV_NOPTS_VALUE)
> to make them receive auto-generated values? The code which assign the
> auto-generated
> values is marked with "FIXME this is a temporary hack until all encoders
> output pts"
>
dated back to 2004. A long-living hack :)
>

I mean this (not tested this version, just an example).
btw I've named the feature "align_aframes"
---
 ffmpeg.c     |   10 ++++++++++
 ffmpeg.h     |    4 ++++
 ffmpeg_opt.c |    4 ++++
 3 files changed, 18 insertions(+)

diff --git a/ffmpeg.c b/ffmpeg.c
index 2763db6..63c8817 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -507,6 +507,16 @@ static void write_frame(AVFormatContext *s, AVPacket
*pkt, OutputStream *ost)
         (avctx->codec_type == AVMEDIA_TYPE_AUDIO && audio_sync_method < 0))
         pkt->pts = pkt->dts = AV_NOPTS_VALUE;

+    if (avctx->codec_type == AVMEDIA_TYPE_AUDIO &&
ost->align_aframes_threshold &&
+        pkt->pts != AV_NOPTS_VALUE && ost->st->pts.val != AV_NOPTS_VALUE) {
+        int64_t diff = pkt->pts - ost->st->pts.val;
+        int64_t maxdiff = av_rescale(ost->align_aframes_threshold,
ost->st->time_base.den, AV_TIME_BASE * (int64_t)ost->st->time_base.num);
+        if (diff > -maxdiff && diff < maxdiff) {
+            av_dlog(s, "st:%d frame-sync breakup %"PRId64" > %"PRId64"\n",
pkt->stream_index, diff, maxdiff);
+            pkt->dts = pkt->pts = AV_NOPTS_VALUE;
+        }
+    }
+
     if ((avctx->codec_type == AVMEDIA_TYPE_AUDIO || avctx->codec_type ==
AVMEDIA_TYPE_VIDEO) && pkt->dts != AV_NOPTS_VALUE) {
         int64_t max = ost->st->cur_dts + !(s->oformat->flags &
AVFMT_TS_NONSTRICT);
         if (ost->st->cur_dts && ost->st->cur_dts != AV_NOPTS_VALUE &&  max
> pkt->dts) {
diff --git a/ffmpeg.h b/ffmpeg.h
index cd849c9..9ebaa53 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -165,6 +165,8 @@ typedef struct OptionsContext {
     int        nb_pass;
     SpecifierOpt *passlogfiles;
     int        nb_passlogfiles;
+    SpecifierOpt *align_audio_frames;
+    int        nb_align_audio_frames;
 } OptionsContext;

 typedef struct InputFilter {
@@ -312,6 +314,8 @@ typedef struct OutputStream {
     int audio_channels_map[SWR_CH_MAX];  /* list of the channels id to
pick from the source stream */
     int audio_channels_mapped;           /* number of channels in
audio_channels_map */

+    int64_t align_aframes_threshold;
+
     char *logfile_prefix;
     FILE *logfile;

diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
index f337a91..c309503 100644
--- a/ffmpeg_opt.c
+++ b/ffmpeg_opt.c
@@ -981,6 +981,8 @@ static OutputStream *new_output_stream(OptionsContext
*o, AVFormatContext *oc, e
         st->codec->global_quality = FF_QP2LAMBDA * qscale;
     }

+    MATCH_PER_STREAM_OPT(align_audio_frames, i64,
ost->align_aframes_threshold, oc, st);
+
     if (oc->oformat->flags & AVFMT_GLOBALHEADER)
         st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;

@@ -2427,6 +2429,8 @@ const OptionDef options[] = {
         "set channel layout", "layout" },
     { "af",             OPT_AUDIO | HAS_ARG  | OPT_PERFILE,
         { .func_arg = opt_audio_filters },
         "audio filters", "filter list" },
+    { "align_aframes",  OPT_AUDIO | HAS_ARG  | OPT_INT64 | OPT_SPEC,
        { .off = OFFSET(align_audio_frames) },
+        "align closely spaced audio frames" },

     /* subtitle options */
     { "sn",     OPT_SUBTITLE | OPT_BOOL | OPT_OFFSET, { .off =
OFFSET(subtitle_disable) },
-- 
1.7.10.4


More information about the ffmpeg-devel mailing list