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

Stefano Sabatini stefano.sabatini-lala
Fri Oct 1 11:38:59 CEST 2010


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.

A possible solution would be to av_reduce tb1 and tb2 with
max=INT32_MAX, and only then reduce again
tb1.num*tb2.num/(tb2.den*tb2.den):

    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,
                       tb1.num * tb2.num, tb1.den * tb2.den, INT64_MAX);

Is this acceptable?

Regards.
-- 
FFmpeg = Fascinating and Fancy Mythic Problematic Ecstatic Governor



More information about the ffmpeg-devel mailing list