[FFmpeg-devel] lavfi noise generator

Stefano Sabatini stefano.sabatini-lala
Sun Jan 11 20:52:45 CET 2009


On date Sunday 2009-01-11 19:23:54 +0100, Michael Niedermayer encoded:
> On Sun, Jan 11, 2009 at 06:01:47PM +0100, Stefano Sabatini wrote:
> > On date Sunday 2009-01-11 11:19:18 +0100, Michael Niedermayer encoded:
> > > On Fri, Jan 02, 2009 at 03:26:17AM +0100, Stefano Sabatini wrote:
> > > > On date Tuesday 2008-12-30 19:14:37 +0100, Stefano Sabatini encoded:
> > > > > On date Monday 2008-12-29 16:27:04 +0100, Vitor Sessak encoded:
> > > > > > Stefano Sabatini wrote:
> > > > [...]
> > > > > >> Hi Vitor, vsrc_noise.c is a *source* rather than a filter, so I don't
> > > > > >> think it is possible to use the the draw_slice() API.
> > > > > >
> > > > > > Indeed, it should not be possible, at least not with the current svn  
> > > > > > code. See my attached patch.
> > > > > >
> > > > > >> What I'm currently doing is:
> > > > > >>
> > > > > >> static int request_frame(AVFilterLink *link)
> > > > > >> {
> > > > > >>     NoiseContext *ctx = link->src->priv;
> > > > > >>     AVFilterPicRef *picref = avfilter_get_video_buffer(link, AV_PERM_WRITE);
> > > > > >>
> > > > > >>     fill_picture(ctx, picref);
> > > > > >>     picref->pts = av_rescale_q(ctx->pts++, (AVRational){ ctx->frame_rate.den, ctx->frame_rate.num }, AV_TIME_BASE_Q);
> > > > > >>
> > > > > >>     avfilter_start_frame(link, avfilter_ref_pic(picref, ~0));
> > > > > >>     avfilter_draw_slice(link, 0, picref->h);
> > > > > >>     avfilter_end_frame(link);
> > > > > >>
> > > > > >>     avfilter_unref_pic(picref);
> > > > > >>
> > > > > >>     return 0;
> > > > > >> }
> > > > > >
> > > > > > Could something like the following work?
> > > > > >
> > > > > > #define SLICE_SIZE 32
> > > > > >
> > > > > > static int request_frame(AVFilterLink *link)
> > > > > > {
> > > > > >     NoiseContext *ctx = link->src->priv;
> > > > > >     AVFilterPicRef *picref = avfilter_get_video_buffer(link,  
> > > > > > AV_PERM_WRITE);
> > > > > >     int h;
> > > > > >
> > > > > >     picref->pts = av_rescale_q(ctx->pts++, (AVRational) {  
> > > > > > ctx->frame_rate.den, ctx->frame_rate.num }, AV_TIME_BASE_Q);
> > > > > >
> > > > > >     avfilter_start_frame(link, avfilter_ref_pic(picref, ~0));
> > > > > >     for(h=0; h < ctx->h; h += SLICE_SIZE) {
> > > > > >        fill_picture(ctx, picref, h, FFMIN(h+SLICE_SIZE, ctx->h));
> > > > > >        avfilter_draw_slice(link, h, FFMIN(h+SLICE_SIZE, ctx->h));
> > > > > >     }
> > > > > >     avfilter_end_frame(link);
> > > > > >
> > > > > >     avfilter_unref_pic(picref);
> > > > > >
> > > > > >     return 0;
> > > > > > }
> > > > > 
> > > > > It should work, the only thing I don't like is that in this way the
> > > > > code *needs* to know about the picture structure (it needs to know how
> > > > > to access the slice), while before I was simply filling the whole
> > > > > buffer, and this consideration leads to this (maybe silly)
> > > > > question:
> > > > > what's the advantage of per-slice filling in this case?
> > > > > 
> > > > > > But maybe an even cleaner solution would be to use draw_slice() and  
> > > > > > change the function avfilter_request_frame() as in the completely  
> > > > > > untested attached patch.
> > > > > 
> > > > > [...]
> > > > > 
> > > > > > Index: libavfilter/avfilter.c
> > > > > > ===================================================================
> > > > > > --- libavfilter/avfilter.c	(revision 16243)
> > > > > > +++ libavfilter/avfilter.c	(working copy)
> > > > > > @@ -179,7 +179,18 @@
> > > > > >          return link_spad(link).request_frame(link);
> > > > > >      else if(link->src->inputs[0])
> > > > > >          return avfilter_request_frame(link->src->inputs[0]);
> > > > > > +    else if (link_spad(link).draw_slice) {
> > > > > > +        int h;
> > > > > > +        for (h=0; h < link->h; h += SLICE_SIZE) {
> > > > > > +            AVFilterPicRef *picref = avfilter_get_video_buffer(link, AV_PERM_WRITE);
> > > > > > +            avfilter_start_frame(link, avfilter_ref_pic(picref, ~0));
> > > > > > +            link_spad(link).draw_slice(link, h, FFMIN(h+SLICE_SIZE, link->h));
> > > > > > +        }
> > > > > > +        avfilter_end_frame(link);
> > > > > > +        avfilter_unref_pic(picref);
> > > > > > +    }
> > > > > >      else return -1;
> > > > > > +    return 0;
> > > > > >  }
> > > > > >  
> > > > > >  int avfilter_poll_frame(AVFilterLink *link)
> > > > 
> > > > What if we need to change the context before/after to send the picture data?
> > > > 
> > > > And what if we need to set the PTS (as indeed would be needed by most
> > > > sources? (yes we could set PTS for each slice but this would be rater
> > > > ugly.)
> > > 
> > > my_request_frame(){
> > >     pts= 123;
> > >     context->blah=456;
> > >     return avfilter_request_frame();
> > > }
> > 
> > This can't work, since avfilter_request_frame() calls the
> > request_frame() callback, so we'll have a loop.
>
> then this should be fixed.
> Overriden functions should be able to call the default function.

AFAIK in lavfi we call an avfilter_* function from a callback passing
a different link, for example when we call avfilter_draw_slice() in a
draw_slice() callback we use the output link as argument.

In this case we could easily define a default callback (check the
patch), but this won't address the problem we have here.

The problem we have if we want a source to define a draw_slice()
callback, is that this callback will need to access a picref (where
you also set the pts), and after the draw_slice() will be done we
would also need to unref it.

My previous post proposed a possible solution, which extend the
current API.

Regards.
-- 
FFmpeg = Funny Faboulous MultiPurpose Elastic Guide
-------------- next part --------------
A non-text attachment was scrubbed...
Name: implement-default-request-callback.patch
Type: text/x-diff
Size: 2288 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090111/5fb5fb07/attachment.patch>



More information about the ffmpeg-devel mailing list