[FFmpeg-soc] [soc]: r918 - in libavfilter: avfilter.c avfilter.h defaults.c vf_crop.c vf_fps.c vf_overlay.c vf_passthrough.c vf_slicify.c vf_vflip.c vsrc_dummy.c vsrc_ppm.c
koorogi
subversion at mplayerhq.hu
Fri Aug 17 20:21:07 CEST 2007
Author: koorogi
Date: Fri Aug 17 20:21:07 2007
New Revision: 918
Log:
Track the permissions that have been given out to each picture.
This should make it easier to know what can be done to a buffer once
it's been passed to your filter without falling back to copying it "just
to be safe".
Modified:
libavfilter/avfilter.c
libavfilter/avfilter.h
libavfilter/defaults.c
libavfilter/vf_crop.c
libavfilter/vf_fps.c
libavfilter/vf_overlay.c
libavfilter/vf_passthrough.c
libavfilter/vf_slicify.c
libavfilter/vf_vflip.c
libavfilter/vsrc_dummy.c
libavfilter/vsrc_ppm.c
Modified: libavfilter/avfilter.c
==============================================================================
--- libavfilter/avfilter.c (original)
+++ libavfilter/avfilter.c Fri Aug 17 20:21:07 2007
@@ -35,19 +35,67 @@ static AVFilter **filters = NULL;
#define link_dpad(link) link->dst-> input_pads[link->dstpad]
#define link_spad(link) link->src->output_pads[link->srcpad]
-AVFilterPicRef *avfilter_ref_pic(AVFilterPicRef *ref, int pmask)
+/**
+ * helper function to get a pointer to the structure telling the permissions
+ * the filter has on the given picture, or to create the structure if it
+ * does not yet exist.
+ */
+static AVFilterPicPerms *get_perms(AVFilterPic *pic, AVFilterContext *filter)
+{
+ AVFilterPicPerms *ret;
+
+ for(ret = pic->perms; ret; ret = ret->next)
+ if(ret->filter == filter)
+ return ret;
+
+ ret = av_malloc(sizeof(AVFilterPicPerms));
+ ret->filter = filter;
+ ret->perms = 0;
+ ret->next = pic->perms;
+ pic->perms = ret;
+
+ return ret;
+}
+
+int avfilter_get_pic_perms(AVFilterPicRef *pic, AVFilterContext *filter)
+{
+ return get_perms(pic->pic, filter)->perms;
+}
+
+void avfilter_add_pic_perms(AVFilterPicRef *pic, AVFilterContext *filter,
+ int perms)
{
+ get_perms(pic->pic, filter)->perms |= perms;
+}
+
+AVFilterPicRef *avfilter_ref_pic(AVFilterPicRef *ref, AVFilterContext *filter,
+ int pmask)
+{
+ AVFilterPicPerms *pic_perms;
AVFilterPicRef *ret = av_malloc(sizeof(AVFilterPicRef));
memcpy(ret, ref, sizeof(AVFilterPicRef));
ret->perms &= pmask;
ret->pic->refcount ++;
+
+ if(filter) {
+ pic_perms = get_perms(ref->pic, filter);
+ pic_perms->perms |= ret->perms;
+ }
+
return ret;
}
void avfilter_unref_pic(AVFilterPicRef *ref)
{
- if(-- ref->pic->refcount == 0)
+ AVFilterPicPerms *perms;
+
+ if(-- ref->pic->refcount == 0) {
+ for(; ref->pic->perms; ref->pic->perms = perms) {
+ perms = ref->pic->perms->next;
+ av_free(ref->pic->perms);
+ }
ref->pic->free(ref->pic);
+ }
av_free(ref);
}
@@ -160,6 +208,7 @@ int avfilter_request_frame(AVFilterLink
* forcing the source filter to do it? */
void avfilter_start_frame(AVFilterLink *link, AVFilterPicRef *picref)
{
+ int perms = get_perms(picref->pic, link->dst)->perms;
void (*start_frame)(AVFilterLink *, AVFilterPicRef *);
start_frame = link_dpad(link).start_frame;
@@ -167,11 +216,11 @@ void avfilter_start_frame(AVFilterLink *
start_frame = avfilter_default_start_frame;
/* prepare to copy the picture if it has insufficient permissions */
- if((link_dpad(link).min_perms & picref->perms) != link_dpad(link).min_perms ||
- link_dpad(link).rej_perms & picref->perms) {
+ if((link_dpad(link).min_perms & perms) != link_dpad(link).min_perms ||
+ link_dpad(link).rej_perms & perms) {
av_log(link->dst, AV_LOG_INFO,
"frame copy needed (have perms %x, need %x, reject %x)\n",
- picref->perms,
+ perms,
link_dpad(link).min_perms, link_dpad(link).rej_perms);
link->cur_pic = avfilter_default_get_video_buffer(link, link_dpad(link).min_perms);
Modified: libavfilter/avfilter.h
==============================================================================
--- libavfilter/avfilter.h (original)
+++ libavfilter/avfilter.h Fri Aug 17 20:21:07 2007
@@ -29,6 +29,29 @@ typedef struct AVFilterContext AVFilterC
typedef struct AVFilterLink AVFilterLink;
typedef struct AVFilterPad AVFilterPad;
+/**
+ * A linked list of filters which reference this picture and the permissions
+ * they each have. This is needed for the case that filter A requests a buffer
+ * from filter B. Filter B gives it a buffer to use with the permissions it
+ * requested, while reserving more permissions for itself to use when filter A
+ * eventually passes the buffer to filter B. However, filter A does not know
+ * what these permissions are to reinsert them in the reference passed to B,
+ * filter B can't assume that any picture it is passed is one that it allocated.
+ *
+ * Rather than have each filter implement their own code to check for this
+ * case, we store all the permissions here in the picture structure.
+ *
+ * Because the number of filters holding references to any one picture should
+ * be rather low, this should not be a major source of performance problems.
+ */
+typedef struct AVFilterPicPerms
+{
+ AVFilterContext *filter; ///< the filter
+ int perms; ///< the permissions that filter has
+
+ struct AVFilterPicPerms *next;
+} AVFilterPicPerms;
+
/* TODO: look for other flags which may be useful in this structure (interlace
* flags, etc)
*/
@@ -44,6 +67,7 @@ typedef struct AVFilterPic
enum PixelFormat format; ///< colorspace
unsigned refcount; ///< number of references to this image
+ AVFilterPicPerms *perms; ///< list of permissions held by filters
/** private data to be used by a custom free function */
void *priv;
@@ -81,15 +105,25 @@ typedef struct AVFilterPicRef
#define AV_PERM_REUSE 0x08 ///< can output the buffer multiple times
} AVFilterPicRef;
+/** Get the permissions the filter has to access the picture. */
+int avfilter_get_pic_perms(AVFilterPicRef *pic, AVFilterContext *filter);
+
+/** Give the filter more permissions to access the picture */
+void avfilter_add_pic_perms(AVFilterPicRef *pic, AVFilterContext *filter,
+ int perms);
+
/**
* Add a new reference to a picture.
* @param ref An existing reference to the picture
+ * @param ref If non-NULL, a pointer to the filter to which the permissions
+ * to the picture are to be given
* @param pmask A bitmask containing the allowable permissions in the new
* reference
* @return A new reference to the picture with the same properties as the
* old, excluding any permissions denied by pmask
*/
-AVFilterPicRef *avfilter_ref_pic(AVFilterPicRef *ref, int pmask);
+AVFilterPicRef *avfilter_ref_pic(AVFilterPicRef *ref, AVFilterContext *filter,
+ int pmask);
/**
* Remove a reference to a picture. If this is the last reference to the
@@ -222,6 +256,8 @@ int *avfilter_default_query_output_forma
AVFilterPicRef *avfilter_default_get_video_buffer(AVFilterLink *link,
int perms);
+/** handler for get_video_buffer() which forwards the request down the chain */
+AVFilterPicRef *avfilter_next_get_video_buffer(AVFilterLink *link, int perms);
/**
* Filter definition. This defines the pads a filter contains, and all the
* callback functions used to interact with the filter.
Modified: libavfilter/defaults.c
==============================================================================
--- libavfilter/defaults.c (original)
+++ libavfilter/defaults.c Fri Aug 17 20:21:07 2007
@@ -28,6 +28,13 @@ void avfilter_default_free_video_buffer(
av_free(pic);
}
+AVFilterPicRef *avfilter_next_get_video_buffer(AVFilterLink *link, int perms)
+{
+ if(!link->dst->outputs[0])
+ return NULL;
+ return avfilter_get_video_buffer(link->dst->outputs[0], perms);
+}
+
/* TODO: set the buffer's priv member to a context structure for the whole
* filter chain. This will allow for a buffer pool instead of the constant
* alloc & free cycle currently implemented. */
@@ -41,6 +48,9 @@ AVFilterPicRef *avfilter_default_get_vid
ref->h = link->h;
ref->perms = perms;
+ /* we always give the destination filter read access by default */
+ avfilter_add_pic_perms(ref, link->dst, AV_PERM_READ);
+
pic->refcount = 1;
pic->format = link->format;
pic->free = avfilter_default_free_video_buffer;
@@ -62,7 +72,7 @@ void avfilter_default_start_frame(AVFilt
if(out) {
out->outpic = avfilter_get_video_buffer(out, AV_PERM_WRITE);
out->outpic->pts = picref->pts;
- avfilter_start_frame(out, avfilter_ref_pic(out->outpic, ~0));
+ avfilter_start_frame(out, avfilter_ref_pic(out->outpic, out->dst, ~0));
}
}
Modified: libavfilter/vf_crop.c
==============================================================================
--- libavfilter/vf_crop.c (original)
+++ libavfilter/vf_crop.c Fri Aug 17 20:21:07 2007
@@ -122,7 +122,9 @@ static int config_output(AVFilterLink *l
static void start_frame(AVFilterLink *link, AVFilterPicRef *picref)
{
CropContext *crop = link->dst->priv;
- AVFilterPicRef *ref2 = avfilter_ref_pic(picref, ~0);
+ AVFilterPicRef *ref2 = avfilter_ref_pic(picref,
+ link->dst->outputs[0]->dst,
+ ~0);
int i;
ref2->w = crop->cw;
@@ -172,7 +174,8 @@ AVFilter vf_crop =
.start_frame = start_frame,
.draw_slice = draw_slice,
.query_formats = query_in_formats,
- .config_props = config_input, },
+ .config_props = config_input,
+ .get_video_buffer= avfilter_next_get_video_buffer, },
{ .name = NULL}},
.outputs = (AVFilterPad[]) {{ .name = "default",
.type = AV_PAD_VIDEO,
Modified: libavfilter/vf_fps.c
==============================================================================
--- libavfilter/vf_fps.c (original)
+++ libavfilter/vf_fps.c Fri Aug 17 20:21:07 2007
@@ -94,7 +94,9 @@ static int request_frame(AVFilterLink *l
if(avfilter_request_frame(link->src->inputs[0]))
return -1;
- avfilter_start_frame(link, avfilter_ref_pic(fps->pic, ~AV_PERM_WRITE));
+ avfilter_start_frame(link, avfilter_ref_pic(fps->pic,
+ link->dst->outputs[0]->dst,
+ ~AV_PERM_WRITE));
avfilter_draw_slice (link, 0, fps->pic->h);
avfilter_end_frame (link);
@@ -118,7 +120,8 @@ AVFilter vf_fps =
.start_frame = start_frame,
.draw_slice = draw_slice,
.query_formats = query_formats,
- .end_frame = end_frame, },
+ .end_frame = end_frame,
+ .get_video_buffer= avfilter_next_get_video_buffer, },
{ .name = NULL}},
.outputs = (AVFilterPad[]) {{ .name = "default",
.type = AV_PAD_VIDEO,
Modified: libavfilter/vf_overlay.c
==============================================================================
--- libavfilter/vf_overlay.c (original)
+++ libavfilter/vf_overlay.c Fri Aug 17 20:21:07 2007
@@ -207,7 +207,9 @@ static int request_frame(AVFilterLink *l
pic->pts = over->pics[!lower_timestamp(over)][0]->pts;
/* and send it to the next filter */
- avfilter_start_frame(link, avfilter_ref_pic(pic, ~0));
+ avfilter_start_frame(link, avfilter_ref_pic(pic,
+ link->dst->outputs[0]->dst,
+ ~0));
avfilter_draw_slice (link, 0, pic->h);
avfilter_end_frame (link);
avfilter_unref_pic(pic);
Modified: libavfilter/vf_passthrough.c
==============================================================================
--- libavfilter/vf_passthrough.c (original)
+++ libavfilter/vf_passthrough.c Fri Aug 17 20:21:07 2007
@@ -68,7 +68,8 @@ AVFilter vf_passthrough =
.start_frame = start_frame,
.draw_slice = draw_slice,
.query_formats = query_formats,
- .end_frame = end_frame, },
+ .end_frame = end_frame,
+ .get_video_buffer= avfilter_next_get_video_buffer, },
{ .name = NULL}},
.outputs = (AVFilterPad[]) {{ .name = "default",
.type = AV_PAD_VIDEO },
Modified: libavfilter/vf_slicify.c
==============================================================================
--- libavfilter/vf_slicify.c (original)
+++ libavfilter/vf_slicify.c Fri Aug 17 20:21:07 2007
@@ -62,8 +62,12 @@ static int config_props(AVFilterLink *li
static void start_frame(AVFilterLink *link, AVFilterPicRef *picref)
{
+ AVFilterPicRef *ref2 = avfilter_ref_pic(picref,
+ link->dst->outputs[0]->dst,
+ ~0);
+
avfilter_default_start_frame(link, picref);
- avfilter_start_frame(link->dst->outputs[0], avfilter_ref_pic(picref, ~0));
+ avfilter_start_frame(link->dst->outputs[0], ref2);
}
static void end_frame(AVFilterLink *link)
@@ -98,7 +102,8 @@ AVFilter vf_slicify =
.draw_slice = draw_slice,
.query_formats = query_formats,
.config_props = config_props,
- .end_frame = end_frame, },
+ .end_frame = end_frame,
+ .get_video_buffer= avfilter_next_get_video_buffer, },
{ .name = NULL}},
.outputs = (AVFilterPad[]) {{ .name = "default",
.type = AV_PAD_VIDEO, },
Modified: libavfilter/vf_vflip.c
==============================================================================
--- libavfilter/vf_vflip.c (original)
+++ libavfilter/vf_vflip.c Fri Aug 17 20:21:07 2007
@@ -61,7 +61,9 @@ static int config_input(AVFilterLink *li
static void start_frame(AVFilterLink *link, AVFilterPicRef *picref)
{
FlipContext *flip = link->dst->priv;
- AVFilterPicRef *ref2 = avfilter_ref_pic(picref, ~0);
+ AVFilterPicRef *ref2 = avfilter_ref_pic(picref,
+ link->dst->outputs[0]->dst,
+ ~0);
int i;
ref2->data[0] += (ref2->h-1) * ref2->linesize[0];
@@ -95,7 +97,8 @@ AVFilter vf_vflip =
.start_frame = start_frame,
.draw_slice = draw_slice,
.query_formats = query_in_formats,
- .config_props = config_input, },
+ .config_props = config_input,
+ .get_video_buffer= avfilter_next_get_video_buffer, },
{ .name = NULL}},
.outputs = (AVFilterPad[]) {{ .name = "default",
.type = AV_PAD_VIDEO, },
Modified: libavfilter/vsrc_dummy.c
==============================================================================
--- libavfilter/vsrc_dummy.c (original)
+++ libavfilter/vsrc_dummy.c Fri Aug 17 20:21:07 2007
@@ -55,7 +55,9 @@ static int request_frame(AVFilterLink *l
pic = avfilter_get_video_buffer(link, AV_PERM_WRITE);
pic->pts =
ctx->pts += 30;
- avfilter_start_frame(link, avfilter_ref_pic(pic, ~0));
+ avfilter_start_frame(link, avfilter_ref_pic(pic,
+ link->dst->outputs[0]->dst,
+ ~0));
row = pic->data[0];
for(y = 0; y < pic->h; y ++) {
Modified: libavfilter/vsrc_ppm.c
==============================================================================
--- libavfilter/vsrc_ppm.c (original)
+++ libavfilter/vsrc_ppm.c Fri Aug 17 20:21:07 2007
@@ -87,7 +87,8 @@ static int request_frame(AVFilterLink *l
ppm->in = NULL;
} else ppm->pic->pts += 30;
- out = avfilter_ref_pic(ppm->pic, ~AV_PERM_WRITE);
+ out = avfilter_ref_pic(ppm->pic, link->dst->outputs[0]->dst,
+ ~AV_PERM_WRITE);
avfilter_start_frame(link, out);
avfilter_draw_slice(link, 0, out->h);
avfilter_end_frame(link);
More information about the FFmpeg-soc
mailing list