[FFmpeg-devel] [PATCH] Add a time_base field to AVFilterPad.

Stefano Sabatini stefano.sabatini-lala
Sun Oct 3 23:23:49 CEST 2010


On date Sunday 2010-10-03 21:07:55 +0200, Michael Niedermayer encoded:
> On Fri, Oct 01, 2010 at 11:38:59AM +0200, Stefano Sabatini wrote:
> > On date Friday 2010-10-01 11:12:44 +0200, Stefano Sabatini encoded:
> > > On date Friday 2010-10-01 01:27:36 +0200, Michael Niedermayer encoded:
> > > > On Thu, Sep 30, 2010 at 10:35:41PM +0200, Stefano Sabatini wrote:
> > > > > On date Tuesday 2010-09-28 20:29:48 +0200, Michael Niedermayer encoded:
> > > > > > On Tue, Sep 28, 2010 at 02:34:05AM +0200, Stefano Sabatini wrote:
> > > [...]
> > > > > > > So we have this scenario:
> > > > > > > 
> > > > > > > buffer [TB1] <-> [X] filter [Y] <-> [Z] ffmpeg_output
> > > > > > > 
> > > > > > > Z can be set using the TB provided in the output video stream, so we
> > > > > > > have:
> > > > > > > 
> > > > > > > buffer [TB1] <-> [X] filter [Y] <-> [TB2] ffmpeg_output
> > > > > > 
> > > > > > X=TB1
> > > > > > Y=X unless filter wants something else
> > > > > > Z=Y
> > > > > > ffmpeg has to configure itself to use Z or rescale, there never is a timebase
> > > > > > moving backward in the graph
> > > > > > 
> > > > > > or in other words i fail to see where the problem you seem to have comes from
> > > > > > but i might be missing something of course
> > > > > 
> > > > > Updated patch implements this logic.
> > > > > Example:
> > > > > 
> > > > > $ echo "color,null,null,settb=23:35,null,settb=365:234,null,null,nullsink" | tools/graph2dot
> > > > > digraph G {
> > > > > node [shape=box]
> > > > > rankdir=LR
> > > > > "Filter 0 color (color)" -> "Filter 1 null (null)" [ label= "[1/1000000] fmt:argb w:320 h:240 [1/1000000]"];
> > > > > "Filter 1 null (null)" -> "Filter 2 null (null)" [ label= "[1/1000000] fmt:argb w:320 h:240 [1/1000000]"];
> > > > > "Filter 2 null (null)" -> "Filter 3 settb (settb)" [ label= "[1/1000000] fmt:argb w:320 h:240 [23/35]"];
> > > > > "Filter 3 settb (settb)" -> "Filter 4 null (null)" [ label= "[23/35] fmt:argb w:320 h:240 [23/35]"];
> > > > > "Filter 4 null (null)" -> "Filter 5 settb (settb)" [ label= "[23/35] fmt:argb w:320 h:240 [365/234]"];
> > > > > "Filter 5 settb (settb)" -> "Filter 6 null (null)" [ label= "[365/234] fmt:argb w:320 h:240 [365/234]"];
> > > > > "Filter 6 null (null)" -> "Filter 7 null (null)" [ label= "[365/234] fmt:argb w:320 h:240 [365/234]"];
> > > > > "Filter 7 null (null)" -> "Filter 8 nullsink (nullsink)" [ label= "[365/234] fmt:argb w:320 h:240 [365/234]"];
> > > > > }
> > > > > 
> > > > > It is not yet clear to me how to interpret this sentence from you:
> > > > > 
> > > > > |by default the output tb should be choose so that all input timestamps can be
> > > > > |exactly represented or if this timebase exceeds 32/32bit then AVTB
> > > > 
> > > > a filter  that has 2 inputs has 2 input timebases ...
> > > > ill review your patch once you confirm that its supposed to work in such cases
> > > 
> > > Still it's not clear what you mean by "exceeds 32/32bit". Check how
> > > I'm managing pts conversion in this variant of the overlay filter,
> > > in particular the config_output() function.
> > > 
> > > $ echo "nullsrc=300:300:75/23 [in], nullsrc=128:246:29/37 [over]; [in][over] overlay, nullsink" | tools/graph2dot | dot -Tpng -o out.png; display out.png
> > > [nullsrc @ 0xa38b150] w:300 h:300
> > > [nullsrc @ 0xa38b390] w:128 h:246
> > > [overlay @ 0xa38b650] main w:300 h:300 fmt:yuv420p overlay x:0 y:0 w:128 h:246 fmt:yuva420p
> > > [overlay @ 0xa38b650] main_tb:23/75 overlay_tb:37/29 -> tb:851/2175 exact:1
> > > 
> > > Regards.
> > 
> > [...]
> > > +static int config_output(AVFilterLink *outlink)
> > > +{
> > > +    AVFilterContext *ctx = outlink->src;
> > > +
> > > +    /* choose the output timebase */
> > > +    AVRational tb1 = ctx->input_pads[MAIN   ].time_base;
> > > +    AVRational tb2 = ctx->input_pads[OVERLAY].time_base;
> > > +    AVRational tb;
> > 
> > > +    int exact = av_reduce(&tb.num, &tb.den,
> > > +                          tb1.num * tb2.num, tb1.den * tb2.den, INT_MAX);
> > 
> > And soon I realized this may overflow.
> 
> you are missing int64_t casts

Ok so the overlay config_output would be:

static int config_output(AVFilterLink *outlink)
{
    AVFilterContext *ctx = outlink->src;

    /* choose the output timebase */
    AVRational tb1 = ctx->input_pads[MAIN   ].time_base;
    AVRational tb2 = ctx->input_pads[OVERLAY].time_base;
    AVRational tb;
    int exact = 1;

    exact *= av_reduce(&tb1.num, &tb1.den, tb1.num, tb1.den, INT32_MAX);
    exact *= av_reduce(&tb2.num, &tb2.den, tb2.num, tb2.den, INT32_MAX);
    exact *= av_reduce(&tb.num, &tb.den,
                       (int64_t)tb1.num * tb2.num, (int64_t)tb1.den * tb2.den, INT_MAX);
    ctx->input_pads[MAIN].time_base = ctx->input_pads[OVERLAY].time_base = tb;

    av_log(ctx, AV_LOG_INFO,
           "main_tb:%d/%d overlay_tb:%d/%d -> tb:%d/%d exact:%d\n",
           tb1.num, tb1.den, tb2.num, tb2.den, tb.num, tb.den, exact);
    if (!exact)
        av_log(ctx, AV_LOG_WARNING,
               "Timestamp conversion inexact, timestamp information loss may occurr\n");

    outlink->w = ctx->inputs[MAIN]->w;
    outlink->h = ctx->inputs[MAIN]->h;

    return 0;
}

> > > > a filter  that has 2 inputs has 2 input timebases ...
> > > > ill review your patch once you confirm that its supposed to work in such cases

Is this enough to show that this can work with two different input
timebases?

Regards.
-- 
FFmpeg = Formidable & Funny Meaningless Prodigious Erroneous Guru



More information about the ffmpeg-devel mailing list