[FFmpeg-devel] lavfi noise generator
Stefano Sabatini
stefano.sabatini-lala
Sun Jan 11 18:01:47 CET 2009
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.
What currently request_frame() does:
1) return a negative number if unready/error, update the filter
context, eventually create a picref and set its PTS, notify the
destination pad with avfilter_start_frame()
2) fill the frame or a single slice, and send it using
avfilter_draw_slice(), we need access to the picref here
3) notify the destination pad with avfilter_end_frame(), eventually
unref the picref
What about to split the request_frame() like this:
* AVFilterPicRef *push_frame_start(AVFilterLink *link)
will return a picref if successfull, a NULL pointer otherwise, and
notify the receiving pad with avfilter_start_frame()
* void push_frame_slice(AVFilterPicRef *picref, AVFilterLink *link, int y, int height)
this will fill the picref slice and will call avfilter_draw_slice()
* void push_frame_end(AVFilterPicRef *picref, AVFilterLink *link)
this will call avfilter_end_frame() and unref the picref
So the avfilter_request_frame() may look like this:
int avfilter_request_frame(AVFilterLink *link)
AVFilterPad *src_pad = link_spad(link);
AVFilterPicRef *picref;
if(src_pad.push_frame_start) {
if (!(picref = src_pad.push_frame_start(link)))
return -1;
}
else if(link->src->inputs[0])
return avfilter_request_frame(link->src->inputs[0]);
else return -1;
if (src_pad.push_frame_slice) {
int y;
for (y=0; y < link->h; y += SLICE_SIZE)
src_pad.push_frame_slice(picref, link, y, FFMIN(SLICE_SIZE, link->h - y));
}
if (src_pad.push_frame_end)
src_pad.push_frame_end(picref, link);
return 0;
}
Or maybe we could call the various
avfilter_start_frame/draw_slice/end_frame explicitely in
avfilter_request_frame().
Regards.
--
FFmpeg = Fiendish & Forgiving Majestic Ponderous Extravagant Guru
More information about the ffmpeg-devel
mailing list