[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