if (s->next_pts != AV_NOPTS_VALUE)
s->next_pts += nb_samples;
- return ff_filter_samples(outlink, out_buf);
+ return ff_filter_frame(outlink, out_buf);
}
/**
return output_frame(outlink, available_samples);
}
-static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
{
AVFilterContext *ctx = inlink->dst;
MixContext *s = ctx->priv;
snprintf(name, sizeof(name), "input%d", i);
pad.type = AVMEDIA_TYPE_AUDIO;
pad.name = av_strdup(name);
- pad.filter_samples = filter_samples;
+ pad.filter_frame = filter_frame;
ff_insert_inpad(ctx, i, &pad);
}
#include "audio.h"
#include "avfilter.h"
+#include "internal.h"
typedef struct AShowInfoContext {
/**
av_freep(&s->plane_checksums);
}
-static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
{
AVFilterContext *ctx = inlink->dst;
AShowInfoContext *s = ctx->priv;
av_log(ctx, AV_LOG_INFO, "]\n");
s->frame++;
- return ff_filter_samples(inlink->dst->outputs[0], buf);
+ return ff_filter_frame(inlink->dst->outputs[0], buf);
}
static const AVFilterPad inputs[] = {
.type = AVMEDIA_TYPE_AUDIO,
.get_audio_buffer = ff_null_get_audio_buffer,
.config_props = config_input,
- .filter_samples = filter_samples,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ,
},
{ NULL },
float min_delta_sec;
int max_comp;
- /* set by filter_samples() to signal an output frame to request_frame() */
+ /* set by filter_frame() to signal an output frame to request_frame() */
int got_output;
} ASyncContext;
}
buf->pts = s->pts;
- return ff_filter_samples(link, buf);
+ return ff_filter_frame(link, buf);
}
return ret;
return avresample_available(s->avr) + avresample_get_delay(s->avr);
}
-static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
{
AVFilterContext *ctx = inlink->dst;
ASyncContext *s = ctx->priv;
av_samples_set_silence(buf_out->extended_data, out_size - delta,
delta, nb_channels, buf->format);
}
- ret = ff_filter_samples(outlink, buf_out);
+ ret = ff_filter_frame(outlink, buf_out);
if (ret < 0)
goto fail;
s->got_output = 1;
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
- .filter_samples = filter_samples
+ .filter_frame = filter_frame,
},
{ NULL }
};
return 0;
}
-static int channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
+static int channelmap_filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
{
AVFilterContext *ctx = inlink->dst;
AVFilterLink *outlink = ctx->outputs[0];
memcpy(buf->data, buf->extended_data,
FFMIN(FF_ARRAY_ELEMS(buf->data), nch_out) * sizeof(buf->data[0]));
- return ff_filter_samples(outlink, buf);
+ return ff_filter_frame(outlink, buf);
}
static int channelmap_config_input(AVFilterLink *inlink)
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
- .filter_samples = channelmap_filter_samples,
+ .filter_frame = channelmap_filter_frame,
.config_props = channelmap_config_input
},
{ NULL }
return 0;
}
-static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
{
AVFilterContext *ctx = inlink->dst;
int i, ret = 0;
buf_out->audio->channel_layout =
av_channel_layout_extract_channel(buf->audio->channel_layout, i);
- ret = ff_filter_samples(ctx->outputs[i], buf_out);
+ ret = ff_filter_frame(ctx->outputs[i], buf_out);
if (ret < 0)
break;
}
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
- .filter_samples = filter_samples,
+ .filter_frame = filter_frame,
},
{ NULL }
};
.version = LIBAVUTIL_VERSION_INT,
};
-static int filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *buf)
{
AVFilterContext *ctx = link->dst;
JoinContext *s = ctx->priv;
snprintf(name, sizeof(name), "input%d", i);
pad.type = AVMEDIA_TYPE_AUDIO;
pad.name = av_strdup(name);
- pad.filter_samples = filter_samples;
+ pad.filter_frame = filter_frame;
pad.needs_fifo = 1;
priv->nb_in_buffers = ctx->nb_inputs;
buf->buf->priv = priv;
- ret = ff_filter_samples(outlink, buf);
+ ret = ff_filter_frame(outlink, buf);
memset(s->input_frames, 0, sizeof(*s->input_frames) * ctx->nb_inputs);
int64_t next_pts;
- /* set by filter_samples() to signal an output frame to request_frame() */
+ /* set by filter_frame() to signal an output frame to request_frame() */
int got_output;
} ResampleContext;
}
buf->pts = s->next_pts;
- return ff_filter_samples(outlink, buf);
+ return ff_filter_frame(outlink, buf);
}
return ret;
}
-static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
{
AVFilterContext *ctx = inlink->dst;
ResampleContext *s = ctx->priv;
s->next_pts = buf_out->pts + buf_out->audio->nb_samples;
- ret = ff_filter_samples(outlink, buf_out);
+ ret = ff_filter_frame(outlink, buf_out);
s->got_output = 1;
}
avfilter_unref_buffer(buf);
} else {
buf->format = outlink->format;
- ret = ff_filter_samples(outlink, buf);
+ ret = ff_filter_frame(outlink, buf);
s->got_output = 1;
}
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
- .filter_samples = filter_samples,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ
},
{ NULL }
#include "avfilter.h"
#include "internal.h"
-static int null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
+static int null_filter_frame(AVFilterLink *link, AVFilterBufferRef *samplesref)
{
avfilter_unref_bufferp(&samplesref);
return 0;
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
- .filter_samples = null_filter_samples,
+ .filter_frame = null_filter_frame,
},
{ NULL },
};
av_freep(&samples);
return NULL;
}
-
-static int default_filter_samples(AVFilterLink *link,
- AVFilterBufferRef *samplesref)
-{
- return ff_filter_samples(link->dst->outputs[0], samplesref);
-}
-
-int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
-{
- int (*filter_samples)(AVFilterLink *, AVFilterBufferRef *);
- AVFilterPad *dst = link->dstpad;
- AVFilterBufferRef *buf_out;
-
- FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1);
-
- if (!(filter_samples = dst->filter_samples))
- filter_samples = default_filter_samples;
-
- /* prepare to copy the samples if the buffer has insufficient permissions */
- if ((dst->min_perms & samplesref->perms) != dst->min_perms ||
- dst->rej_perms & samplesref->perms) {
- av_log(link->dst, AV_LOG_DEBUG,
- "Copying audio data in avfilter (have perms %x, need %x, reject %x)\n",
- samplesref->perms, link->dstpad->min_perms, link->dstpad->rej_perms);
-
- buf_out = ff_default_get_audio_buffer(link, dst->min_perms,
- samplesref->audio->nb_samples);
- if (!buf_out) {
- avfilter_unref_buffer(samplesref);
- return AVERROR(ENOMEM);
- }
- buf_out->pts = samplesref->pts;
- buf_out->audio->sample_rate = samplesref->audio->sample_rate;
-
- /* Copy actual data into new samples buffer */
- av_samples_copy(buf_out->extended_data, samplesref->extended_data,
- 0, 0, samplesref->audio->nb_samples,
- av_get_channel_layout_nb_channels(link->channel_layout),
- link->format);
-
- avfilter_unref_buffer(samplesref);
- } else
- buf_out = samplesref;
-
- return filter_samples(link, buf_out);
-}
-
AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms,
int nb_samples);
-/**
- * Send a buffer of audio samples to the next filter.
- *
- * @param link the output link over which the audio samples are being sent
- * @param samplesref a reference to the buffer of audio samples being sent. The
- * receiving filter will free this reference when it no longer
- * needs it or pass it on to the next filter.
- *
- * @return >= 0 on success, a negative AVERROR on error. The receiving filter
- * is responsible for unreferencing samplesref in case of error.
- */
-int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
-
#endif /* AVFILTER_AUDIO_H */
#include "libavutil/channel_layout.h"
#include "libavutil/common.h"
+#include "libavutil/imgutils.h"
#include "libavutil/pixdesc.h"
#include "libavutil/rational.h"
+#include "libavutil/samplefmt.h"
+#include "audio.h"
#include "avfilter.h"
#include "formats.h"
#include "internal.h"
+#include "video.h"
unsigned avfilter_version(void) {
return LIBAVFILTER_VERSION_INT;
{
return pads[pad_idx].type;
}
+
+static int default_filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
+{
+ return ff_filter_frame(link->dst->outputs[0], frame);
+}
+
+int ff_filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
+{
+ int (*filter_frame)(AVFilterLink *, AVFilterBufferRef *);
+ AVFilterPad *dst = link->dstpad;
+ AVFilterBufferRef *out;
+ int perms = frame->perms;
+
+ FF_DPRINTF_START(NULL, filter_frame);
+ ff_dlog_link(NULL, link, 1);
+
+ if (!(filter_frame = dst->filter_frame))
+ filter_frame = default_filter_frame;
+
+ if (frame->linesize[0] < 0)
+ perms |= AV_PERM_NEG_LINESIZES;
+ /* prepare to copy the frame if the buffer has insufficient permissions */
+ if ((dst->min_perms & perms) != dst->min_perms ||
+ dst->rej_perms & perms) {
+ av_log(link->dst, AV_LOG_DEBUG,
+ "Copying data in avfilter (have perms %x, need %x, reject %x)\n",
+ perms, link->dstpad->min_perms, link->dstpad->rej_perms);
+
+ switch (link->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ out = ff_get_video_buffer(link, dst->min_perms,
+ link->w, link->h);
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ out = ff_get_audio_buffer(link, dst->min_perms,
+ frame->audio->nb_samples);
+ break;
+ default: return AVERROR(EINVAL);
+ }
+ if (!out) {
+ avfilter_unref_buffer(frame);
+ return AVERROR(ENOMEM);
+ }
+ avfilter_copy_buffer_ref_props(out, frame);
+
+ switch (link->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ av_image_copy(out->data, out->linesize, frame->data, frame->linesize,
+ frame->format, frame->video->w, frame->video->h);
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ av_samples_copy(out->extended_data, frame->extended_data,
+ 0, 0, frame->audio->nb_samples,
+ av_get_channel_layout_nb_channels(frame->audio->channel_layout),
+ frame->format);
+ break;
+ default: return AVERROR(EINVAL);
+ }
+
+ avfilter_unref_buffer(frame);
+ } else
+ out = frame;
+
+ return filter_frame(link, out);
+}
int rej_perms;
/**
- * Callback called before passing the first slice of a new frame. If
- * NULL, the filter layer will default to storing a reference to the
- * picture inside the link structure.
- *
- * Input video pads only.
- *
- * @return >= 0 on success, a negative AVERROR on error. picref will be
- * unreferenced by the caller in case of error.
+ * @deprecated unused
*/
int (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref);
int nb_samples);
/**
- * Callback called after the slices of a frame are completely sent. If
- * NULL, the filter layer will default to releasing the reference stored
- * in the link structure during start_frame().
- *
- * Input video pads only.
- *
- * @return >= 0 on success, a negative AVERROR on error.
+ * @deprecated unused
*/
int (*end_frame)(AVFilterLink *link);
/**
- * Slice drawing callback. This is where a filter receives video data
- * and should do its processing.
- *
- * Input video pads only.
- *
- * @return >= 0 on success, a negative AVERROR on error.
+ * @deprecated unused
*/
int (*draw_slice)(AVFilterLink *link, int y, int height, int slice_dir);
/**
- * Samples filtering callback. This is where a filter receives audio data
- * and should do its processing.
+ * Filtering callback. This is where a filter receives a frame with
+ * audio/video data and should do its processing.
*
- * Input audio pads only.
+ * Input pads only.
*
* @return >= 0 on success, a negative AVERROR on error. This function
* must ensure that samplesref is properly unreferenced on error if it
* hasn't been passed on to another filter.
*/
- int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref);
+ int (*filter_frame)(AVFilterLink *link, AVFilterBufferRef *frame);
/**
* Frame poll callback. This returns the number of immediately available
AVLINK_STARTINIT, ///< started, but incomplete
AVLINK_INIT ///< complete
} init_state;
-
- /**
- * The buffer reference currently being sent across the link by the source
- * filter. This is used internally by the filter system to allow
- * automatic copying of buffers which do not have sufficient permissions
- * for the destination. This should not be accessed directly by the
- * filters.
- */
- AVFilterBufferRef *src_buf;
-
- AVFilterBufferRef *cur_buf;
- AVFilterBufferRef *out_buf;
};
/**
av_audio_fifo_free(sink->audio_fifo);
}
-static int start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *buf)
{
BufferSinkContext *s = link->dst->priv;
av_assert0(!s->cur_buf);
s->cur_buf = buf;
- link->cur_buf = NULL;
return 0;
}
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .start_frame = start_frame,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ,
.needs_fifo = 1
},
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
- .filter_samples = start_frame,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ,
.needs_fifo = 1
},
}
av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL);
- switch (link->type) {
- case AVMEDIA_TYPE_VIDEO:
- if ((ret = ff_start_frame(link, buf)) < 0 ||
- (ret = ff_draw_slice(link, 0, link->h, 1)) < 0 ||
- (ret = ff_end_frame(link)) < 0)
- return ret;
- break;
- case AVMEDIA_TYPE_AUDIO:
- ret = ff_filter_samples(link, buf);
- break;
- default:
- avfilter_unref_bufferp(&buf);
- return AVERROR(EINVAL);
- }
+ ff_filter_frame(link, buf);
return ret;
}
{
FifoContext *fifo = inlink->dst->priv;
- inlink->cur_buf = NULL;
fifo->last->next = av_mallocz(sizeof(Buf));
if (!fifo->last->next) {
avfilter_unref_buffer(buf);
s->root.next = tmp;
}
-static int end_frame(AVFilterLink *inlink)
-{
- return 0;
-}
-
-static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
-{
- return 0;
-}
-
/**
* Move data pointers and pts offset samples forward.
*/
buf_out = s->buf_out;
s->buf_out = NULL;
}
- return ff_filter_samples(link, buf_out);
+ return ff_filter_frame(link, buf_out);
}
static int request_frame(AVFilterLink *outlink)
return ret;
}
- /* by doing this, we give ownership of the reference to the next filter,
- * so we don't have to worry about dereferencing it ourselves. */
- switch (outlink->type) {
- case AVMEDIA_TYPE_VIDEO:
- if ((ret = ff_start_frame(outlink, fifo->root.next->buf)) < 0 ||
- (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0)
- return ret;
-
+ if (outlink->request_samples) {
+ return return_audio_frame(outlink->src);
+ } else {
+ ret = ff_filter_frame(outlink, fifo->root.next->buf);
queue_pop(fifo);
- break;
- case AVMEDIA_TYPE_AUDIO:
- if (outlink->request_samples) {
- return return_audio_frame(outlink->src);
- } else {
- ret = ff_filter_samples(outlink, fifo->root.next->buf);
- queue_pop(fifo);
- }
- break;
- default:
- return AVERROR(EINVAL);
}
return ret;
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = add_to_queue,
- .draw_slice = draw_slice,
- .end_frame = end_frame,
+ .filter_frame = add_to_queue,
.rej_perms = AV_PERM_REUSE2,
},
{ NULL }
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
.get_audio_buffer = ff_null_get_audio_buffer,
- .filter_samples = add_to_queue,
+ .filter_frame = add_to_queue,
.rej_perms = AV_PERM_REUSE2,
},
{ NULL }
*/
int rej_perms;
- /**
- * Callback called before passing the first slice of a new frame. If
- * NULL, the filter layer will default to storing a reference to the
- * picture inside the link structure.
- *
- * Input video pads only.
- *
- * @return >= 0 on success, a negative AVERROR on error. picref will be
- * unreferenced by the caller in case of error.
- */
- void (*start_frame)(AVFilterLink *link, AVFilterBufferRef *picref);
-
/**
* Callback function to get a video buffer. If NULL, the filter system will
* use avfilter_default_get_video_buffer().
int nb_samples);
/**
- * Callback called after the slices of a frame are completely sent. If
- * NULL, the filter layer will default to releasing the reference stored
- * in the link structure during start_frame().
+ * Filtering callback. This is where a filter receives a frame with
+ * audio/video data and should do its processing.
*
- * Input video pads only.
- *
- * @return >= 0 on success, a negative AVERROR on error.
- */
- int (*end_frame)(AVFilterLink *link);
-
- /**
- * Slice drawing callback. This is where a filter receives video data
- * and should do its processing.
- *
- * Input video pads only.
- *
- * @return >= 0 on success, a negative AVERROR on error.
- */
- int (*draw_slice)(AVFilterLink *link, int y, int height, int slice_dir);
-
- /**
- * Samples filtering callback. This is where a filter receives audio data
- * and should do its processing.
- *
- * Input audio pads only.
+ * Input pads only.
*
* @return >= 0 on success, a negative AVERROR on error. This function
* must ensure that samplesref is properly unreferenced on error if it
* hasn't been passed on to another filter.
*/
- int (*filter_samples)(AVFilterLink *link, AVFilterBufferRef *samplesref);
+ int (*filter_frame)(AVFilterLink *link, AVFilterBufferRef *frame);
/**
* Frame poll callback. This returns the number of immediately available
*/
int ff_request_frame(AVFilterLink *link);
+/**
+ * Send a frame of data to the next filter.
+ *
+ * @param link the output link over which the data is being sent
+ * @param frame a reference to the buffer of data being sent. The
+ * receiving filter will free this reference when it no longer
+ * needs it or pass it on to the next filter.
+ *
+ * @return >= 0 on success, a negative AVERROR on error. The receiving filter
+ * is responsible for unreferencing frame in case of error.
+ */
+int ff_filter_frame(AVFilterLink *link, AVFilterBufferRef *frame);
+
#endif /* AVFILTER_INTERNAL_H */
av_freep(&ctx->output_pads[i].name);
}
-static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
AVFilterContext *ctx = inlink->dst;
int i, ret = 0;
for (i = 0; i < ctx->nb_outputs; i++) {
- AVFilterBufferRef *buf_out = avfilter_ref_buffer(picref, ~AV_PERM_WRITE);
- if (!buf_out)
- return AVERROR(ENOMEM);
-
- ret = ff_start_frame(ctx->outputs[i], buf_out);
- if (ret < 0)
- break;
- }
- return ret;
-}
-
-static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
-{
- AVFilterContext *ctx = inlink->dst;
- int i, ret = 0;
-
- for (i = 0; i < ctx->nb_outputs; i++) {
- ret = ff_draw_slice(ctx->outputs[i], y, h, slice_dir);
- if (ret < 0)
+ AVFilterBufferRef *buf_out = avfilter_ref_buffer(frame, ~AV_PERM_WRITE);
+ if (!buf_out) {
+ ret = AVERROR(ENOMEM);
break;
- }
- return ret;
-}
-
-static int end_frame(AVFilterLink *inlink)
-{
- AVFilterContext *ctx = inlink->dst;
- int i, ret = 0;
+ }
- for (i = 0; i < ctx->nb_outputs; i++) {
- ret = ff_end_frame(ctx->outputs[i]);
+ ret = ff_filter_frame(ctx->outputs[i], buf_out);
if (ret < 0)
break;
}
+ avfilter_unref_bufferp(&frame);
return ret;
}
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = start_frame,
- .draw_slice = draw_slice,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
},
{ NULL }
};
.outputs = NULL,
};
-static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
-{
- AVFilterContext *ctx = inlink->dst;
- int i, ret = 0;
-
- for (i = 0; i < ctx->nb_outputs; i++) {
- AVFilterBufferRef *buf_out = avfilter_ref_buffer(samplesref,
- ~AV_PERM_WRITE);
- if (!buf_out) {
- ret = AVERROR(ENOMEM);
- break;
- }
-
- ret = ff_filter_samples(inlink->dst->outputs[i], buf_out);
- if (ret < 0)
- break;
- }
- avfilter_unref_buffer(samplesref);
- return ret;
-}
-
static const AVFilterPad avfilter_af_asplit_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_AUDIO,
.get_audio_buffer = ff_null_get_audio_buffer,
- .filter_samples = filter_samples
+ .filter_frame = filter_frame,
},
{ NULL }
};
return 0;
}
-static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
{
AspectContext *aspect = link->dst->priv;
- picref->video->pixel_aspect = aspect->aspect;
- link->cur_buf = NULL;
- return ff_start_frame(link->dst->outputs[0], picref);
+ frame->video->pixel_aspect = aspect->aspect;
+ return ff_filter_frame(link->dst->outputs[0], frame);
}
#if CONFIG_SETDAR_FILTER
.type = AVMEDIA_TYPE_VIDEO,
.config_props = setdar_config_props,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = start_frame,
- .end_frame = ff_null_end_frame
+ .filter_frame = filter_frame,
},
{ NULL }
};
.type = AVMEDIA_TYPE_VIDEO,
.config_props = setsar_config_props,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = start_frame,
- .end_frame = ff_null_end_frame
+ .filter_frame = filter_frame,
},
{ NULL }
};
return 0;
}
-static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
AVFilterContext *ctx = inlink->dst;
BlackFrameContext *blackframe = ctx->priv;
- AVFilterBufferRef *picref = inlink->cur_buf;
int x, i;
- uint8_t *p = picref->data[0] + y * picref->linesize[0];
+ int pblack = 0;
+ uint8_t *p = frame->data[0];
- for (i = 0; i < h; i++) {
+ for (i = 0; i < frame->video->h; i++) {
for (x = 0; x < inlink->w; x++)
blackframe->nblack += p[x] < blackframe->bthresh;
- p += picref->linesize[0];
+ p += frame->linesize[0];
}
- return ff_draw_slice(ctx->outputs[0], y, h, slice_dir);
-}
-
-static int end_frame(AVFilterLink *inlink)
-{
- AVFilterContext *ctx = inlink->dst;
- BlackFrameContext *blackframe = ctx->priv;
- AVFilterBufferRef *picref = inlink->cur_buf;
- int pblack = 0;
-
pblack = blackframe->nblack * 100 / (inlink->w * inlink->h);
if (pblack >= blackframe->bamount)
av_log(ctx, AV_LOG_INFO, "frame:%u pblack:%u pos:%"PRId64" pts:%"PRId64" t:%f\n",
- blackframe->frame, pblack, picref->pos, picref->pts,
- picref->pts == AV_NOPTS_VALUE ? -1 : picref->pts * av_q2d(inlink->time_base));
+ blackframe->frame, pblack, frame->pos, frame->pts,
+ frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base));
blackframe->frame++;
blackframe->nblack = 0;
- return ff_end_frame(inlink->dst->outputs[0]);
+ return ff_filter_frame(inlink->dst->outputs[0], frame);
}
static const AVFilterPad avfilter_vf_blackframe_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .draw_slice = draw_slice,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = ff_null_start_frame,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
},
{ NULL }
};
h, radius, power, temp);
}
-static int draw_slice(AVFilterLink *inlink, int y0, int h0, int slice_dir)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
{
AVFilterContext *ctx = inlink->dst;
BoxBlurContext *boxblur = ctx->priv;
AVFilterLink *outlink = inlink->dst->outputs[0];
- AVFilterBufferRef *inpicref = inlink ->cur_buf;
- AVFilterBufferRef *outpicref = outlink->out_buf;
+ AVFilterBufferRef *out;
int plane;
- int cw = inlink->w >> boxblur->hsub, ch = h0 >> boxblur->vsub;
+ int cw = inlink->w >> boxblur->hsub, ch = in->video->h >> boxblur->vsub;
int w[4] = { inlink->w, cw, cw, inlink->w };
- int h[4] = { h0, ch, ch, h0 };
+ int h[4] = { in->video->h, ch, ch, in->video->h };
- for (plane = 0; inpicref->data[plane] && plane < 4; plane++)
- hblur(outpicref->data[plane], outpicref->linesize[plane],
- inpicref ->data[plane], inpicref ->linesize[plane],
+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+ if (!out) {
+ avfilter_unref_bufferp(&in);
+ return AVERROR(ENOMEM);
+ }
+ avfilter_copy_buffer_ref_props(out, in);
+
+ for (plane = 0; in->data[plane] && plane < 4; plane++)
+ hblur(out->data[plane], out->linesize[plane],
+ in ->data[plane], in ->linesize[plane],
w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane],
boxblur->temp);
- for (plane = 0; inpicref->data[plane] && plane < 4; plane++)
- vblur(outpicref->data[plane], outpicref->linesize[plane],
- outpicref->data[plane], outpicref->linesize[plane],
+ for (plane = 0; in->data[plane] && plane < 4; plane++)
+ vblur(out->data[plane], out->linesize[plane],
+ out->data[plane], out->linesize[plane],
w[plane], h[plane], boxblur->radius[plane], boxblur->power[plane],
boxblur->temp);
- return ff_draw_slice(outlink, y0, h0, slice_dir);
+ avfilter_unref_bufferp(&in);
+
+ return ff_filter_frame(outlink, out);
}
static const AVFilterPad avfilter_vf_boxblur_inputs[] = {
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_input,
- .draw_slice = draw_slice,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ
},
{ NULL }
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = ff_null_start_frame,
- .end_frame = ff_null_end_frame,
.rej_perms = ~0
},
{ NULL }
return 0;
}
-static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
{
AVFilterContext *ctx = link->dst;
CropContext *crop = ctx->priv;
- AVFilterBufferRef *ref2;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
int i;
- ref2 = avfilter_ref_buffer(picref, ~0);
- if (!ref2)
- return AVERROR(ENOMEM);
+ frame->video->w = crop->w;
+ frame->video->h = crop->h;
- ref2->video->w = crop->w;
- ref2->video->h = crop->h;
-
- crop->var_values[VAR_T] = picref->pts == AV_NOPTS_VALUE ?
- NAN : picref->pts * av_q2d(link->time_base);
- crop->var_values[VAR_POS] = picref->pos == -1 ? NAN : picref->pos;
+ crop->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
+ NAN : frame->pts * av_q2d(link->time_base);
+ crop->var_values[VAR_POS] = frame->pos == -1 ? NAN : frame->pos;
crop->var_values[VAR_X] = av_expr_eval(crop->x_pexpr, crop->var_values, NULL);
crop->var_values[VAR_Y] = av_expr_eval(crop->y_pexpr, crop->var_values, NULL);
crop->var_values[VAR_X] = av_expr_eval(crop->x_pexpr, crop->var_values, NULL);
(int)crop->var_values[VAR_N], crop->var_values[VAR_T], crop->x,
crop->y, crop->x+crop->w, crop->y+crop->h);
- ref2->data[0] += crop->y * ref2->linesize[0];
- ref2->data[0] += crop->x * crop->max_step[0];
+ frame->data[0] += crop->y * frame->linesize[0];
+ frame->data[0] += crop->x * crop->max_step[0];
if (!(desc->flags & PIX_FMT_PAL || desc->flags & PIX_FMT_PSEUDOPAL)) {
for (i = 1; i < 3; i ++) {
- if (ref2->data[i]) {
- ref2->data[i] += (crop->y >> crop->vsub) * ref2->linesize[i];
- ref2->data[i] += (crop->x * crop->max_step[i]) >> crop->hsub;
+ if (frame->data[i]) {
+ frame->data[i] += (crop->y >> crop->vsub) * frame->linesize[i];
+ frame->data[i] += (crop->x * crop->max_step[i]) >> crop->hsub;
}
}
}
/* alpha plane */
- if (ref2->data[3]) {
- ref2->data[3] += crop->y * ref2->linesize[3];
- ref2->data[3] += crop->x * crop->max_step[3];
+ if (frame->data[3]) {
+ frame->data[3] += crop->y * frame->linesize[3];
+ frame->data[3] += crop->x * crop->max_step[3];
}
- return ff_start_frame(link->dst->outputs[0], ref2);
-}
-
-static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- AVFilterContext *ctx = link->dst;
- CropContext *crop = ctx->priv;
-
- if (y >= crop->y + crop->h || y + h <= crop->y)
- return 0;
-
- if (y < crop->y) {
- h -= crop->y - y;
- y = crop->y;
- }
- if (y + h > crop->y + crop->h)
- h = crop->y + crop->h - y;
-
- return ff_draw_slice(ctx->outputs[0], y - crop->y, h, slice_dir);
-}
-
-static int end_frame(AVFilterLink *link)
-{
- CropContext *crop = link->dst->priv;
-
crop->var_values[VAR_N] += 1.0;
- return ff_end_frame(link->dst->outputs[0]);
+
+ return ff_filter_frame(link->dst->outputs[0], frame);
}
static const AVFilterPad avfilter_vf_crop_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .start_frame = start_frame,
- .draw_slice = draw_slice,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
.get_video_buffer = ff_null_get_video_buffer,
.config_props = config_input,
},
return 0;
}
-static int end_frame(AVFilterLink *inlink)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
AVFilterContext *ctx = inlink->dst;
CropDetectContext *cd = ctx->priv;
- AVFilterBufferRef *picref = inlink->cur_buf;
int bpp = cd->max_pixsteps[0];
int w, h, x, y, shrink_by;
if (++cd->frame_nb > 0) {
// Reset the crop area every reset_count frames, if reset_count is > 0
if (cd->reset_count > 0 && cd->frame_nb > cd->reset_count) {
- cd->x1 = picref->video->w-1;
- cd->y1 = picref->video->h-1;
+ cd->x1 = frame->video->w-1;
+ cd->y1 = frame->video->h-1;
cd->x2 = 0;
cd->y2 = 0;
cd->frame_nb = 1;
}
for (y = 0; y < cd->y1; y++) {
- if (checkline(ctx, picref->data[0] + picref->linesize[0] * y, bpp, picref->video->w, bpp) > cd->limit) {
+ if (checkline(ctx, frame->data[0] + frame->linesize[0] * y, bpp, frame->video->w, bpp) > cd->limit) {
cd->y1 = y;
break;
}
}
- for (y = picref->video->h-1; y > cd->y2; y--) {
- if (checkline(ctx, picref->data[0] + picref->linesize[0] * y, bpp, picref->video->w, bpp) > cd->limit) {
+ for (y = frame->video->h-1; y > cd->y2; y--) {
+ if (checkline(ctx, frame->data[0] + frame->linesize[0] * y, bpp, frame->video->w, bpp) > cd->limit) {
cd->y2 = y;
break;
}
}
for (y = 0; y < cd->x1; y++) {
- if (checkline(ctx, picref->data[0] + bpp*y, picref->linesize[0], picref->video->h, bpp) > cd->limit) {
+ if (checkline(ctx, frame->data[0] + bpp*y, frame->linesize[0], frame->video->h, bpp) > cd->limit) {
cd->x1 = y;
break;
}
}
- for (y = picref->video->w-1; y > cd->x2; y--) {
- if (checkline(ctx, picref->data[0] + bpp*y, picref->linesize[0], picref->video->h, bpp) > cd->limit) {
+ for (y = frame->video->w-1; y > cd->x2; y--) {
+ if (checkline(ctx, frame->data[0] + bpp*y, frame->linesize[0], frame->video->h, bpp) > cd->limit) {
cd->x2 = y;
break;
}
av_log(ctx, AV_LOG_INFO,
"x1:%d x2:%d y1:%d y2:%d w:%d h:%d x:%d y:%d pos:%"PRId64" pts:%"PRId64" t:%f crop=%d:%d:%d:%d\n",
- cd->x1, cd->x2, cd->y1, cd->y2, w, h, x, y, picref->pos, picref->pts,
- picref->pts == AV_NOPTS_VALUE ? -1 : picref->pts * av_q2d(inlink->time_base),
+ cd->x1, cd->x2, cd->y1, cd->y2, w, h, x, y, frame->pos, frame->pts,
+ frame->pts == AV_NOPTS_VALUE ? -1 : frame->pts * av_q2d(inlink->time_base),
w, h, x, y);
}
- return ff_end_frame(inlink->dst->outputs[0]);
+ return ff_filter_frame(inlink->dst->outputs[0], frame);
}
static const AVFilterPad avfilter_vf_cropdetect_inputs[] = {
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_input,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = ff_null_start_frame,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
},
{ NULL }
};
return 0;
}
-static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- return 0;
-}
-
-static int end_frame(AVFilterLink *inlink)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
{
DelogoContext *delogo = inlink->dst->priv;
AVFilterLink *outlink = inlink->dst->outputs[0];
- AVFilterBufferRef *inpicref = inlink ->cur_buf;
- AVFilterBufferRef *outpicref = outlink->out_buf;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
- int direct = inpicref->buf == outpicref->buf;
+ AVFilterBufferRef *out;
int hsub0 = desc->log2_chroma_w;
int vsub0 = desc->log2_chroma_h;
+ int direct;
int plane;
- int ret;
- for (plane = 0; plane < 4 && inpicref->data[plane]; plane++) {
+ if ((in->perms & AV_PERM_WRITE) && !(in->perms & AV_PERM_PRESERVE)) {
+ direct = 1;
+ out = in;
+ } else {
+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+ if (!out) {
+ avfilter_unref_bufferp(&in);
+ return AVERROR(ENOMEM);
+ }
+
+ avfilter_copy_buffer_ref_props(out, in);
+ out->video->w = outlink->w;
+ out->video->h = outlink->h;
+ }
+
+ for (plane = 0; plane < 4 && in->data[plane]; plane++) {
int hsub = plane == 1 || plane == 2 ? hsub0 : 0;
int vsub = plane == 1 || plane == 2 ? vsub0 : 0;
- apply_delogo(outpicref->data[plane], outpicref->linesize[plane],
- inpicref ->data[plane], inpicref ->linesize[plane],
+ apply_delogo(out->data[plane], out->linesize[plane],
+ in ->data[plane], in ->linesize[plane],
inlink->w>>hsub, inlink->h>>vsub,
delogo->x>>hsub, delogo->y>>vsub,
delogo->w>>hsub, delogo->h>>vsub,
delogo->show, direct);
}
- if ((ret = ff_draw_slice(outlink, 0, inlink->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0)
- return ret;
- return 0;
+ if (!direct)
+ avfilter_unref_bufferp(&in);
+
+ return ff_filter_frame(outlink, out);
}
static const AVFilterPad avfilter_vf_delogo_inputs[] = {
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = ff_inplace_start_frame,
- .draw_slice = null_draw_slice,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_WRITE | AV_PERM_READ,
.rej_perms = AV_PERM_PRESERVE
},
return 0;
}
-static int draw_slice(AVFilterLink *inlink, int y0, int h, int slice_dir)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
DrawBoxContext *drawbox = inlink->dst->priv;
int plane, x, y, xb = drawbox->x, yb = drawbox->y;
unsigned char *row[4];
- AVFilterBufferRef *picref = inlink->cur_buf;
- for (y = FFMAX(yb, y0); y < (y0 + h) && y < (yb + drawbox->h); y++) {
- row[0] = picref->data[0] + y * picref->linesize[0];
+ for (y = FFMAX(yb, 0); y < frame->video->h && y < (yb + drawbox->h); y++) {
+ row[0] = frame->data[0] + y * frame->linesize[0];
for (plane = 1; plane < 3; plane++)
- row[plane] = picref->data[plane] +
- picref->linesize[plane] * (y >> drawbox->vsub);
+ row[plane] = frame->data[plane] +
+ frame->linesize[plane] * (y >> drawbox->vsub);
- for (x = FFMAX(xb, 0); x < (xb + drawbox->w) && x < picref->video->w; x++) {
+ for (x = FFMAX(xb, 0); x < (xb + drawbox->w) && x < frame->video->w; x++) {
double alpha = (double)drawbox->yuv_color[A] / 255;
if ((y - yb < 3) || (yb + drawbox->h - y < 4) ||
}
}
- return ff_draw_slice(inlink->dst->outputs[0], y0, h, 1);
+ return ff_filter_frame(inlink->dst->outputs[0], frame);
}
static const AVFilterPad avfilter_vf_drawbox_inputs[] = {
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_input,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = ff_null_start_frame,
- .draw_slice = draw_slice,
- .end_frame = ff_null_end_frame,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_WRITE | AV_PERM_READ,
.rej_perms = AV_PERM_PRESERVE
},
return 0;
}
-static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- return 0;
-}
-
static inline int normalize_double(int *n, double d)
{
int ret = 0;
return ret;
}
-static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
AVFilterContext *ctx = inlink->dst;
DrawTextContext *dtext = ctx->priv;
- AVFilterBufferRef *buf_out;
int ret = 0;
if ((ret = dtext_prepare_text(ctx)) < 0) {
av_log(ctx, AV_LOG_ERROR, "Can't draw text\n");
+ avfilter_unref_bufferp(&frame);
return ret;
}
- dtext->var_values[VAR_T] = inpicref->pts == AV_NOPTS_VALUE ?
- NAN : inpicref->pts * av_q2d(inlink->time_base);
+ dtext->var_values[VAR_T] = frame->pts == AV_NOPTS_VALUE ?
+ NAN : frame->pts * av_q2d(inlink->time_base);
dtext->var_values[VAR_X] =
av_expr_eval(dtext->x_pexpr, dtext->var_values, &dtext->prng);
dtext->var_values[VAR_Y] =
(int)dtext->var_values[VAR_N], dtext->var_values[VAR_T],
dtext->x, dtext->y, dtext->x+dtext->w, dtext->y+dtext->h);
- buf_out = avfilter_ref_buffer(inpicref, ~0);
- if (!buf_out)
- return AVERROR(ENOMEM);
-
- return ff_start_frame(inlink->dst->outputs[0], buf_out);
-}
-
-static int end_frame(AVFilterLink *inlink)
-{
- AVFilterLink *outlink = inlink->dst->outputs[0];
- AVFilterBufferRef *picref = inlink->cur_buf;
- DrawTextContext *dtext = inlink->dst->priv;
- int ret;
-
if (dtext->draw)
- draw_text(inlink->dst, picref, picref->video->w, picref->video->h);
+ draw_text(inlink->dst, frame, frame->video->w, frame->video->h);
dtext->var_values[VAR_N] += 1.0;
- if ((ret = ff_draw_slice(outlink, 0, picref->video->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0)
- return ret;
- return 0;
+ return ff_filter_frame(inlink->dst->outputs[0], frame);
}
static const AVFilterPad avfilter_vf_drawtext_inputs[] = {
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = start_frame,
- .draw_slice = null_draw_slice,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
.config_props = config_input,
.min_perms = AV_PERM_WRITE |
AV_PERM_READ,
return 0;
}
-static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
FadeContext *fade = inlink->dst->priv;
- AVFilterBufferRef *outpic = inlink->cur_buf;
uint8_t *p;
int i, j, plane;
if (fade->factor < UINT16_MAX) {
/* luma or rgb plane */
- for (i = 0; i < h; i++) {
- p = outpic->data[0] + (y+i) * outpic->linesize[0];
+ for (i = 0; i < frame->video->h; i++) {
+ p = frame->data[0] + i * frame->linesize[0];
for (j = 0; j < inlink->w * fade->bpp; j++) {
/* fade->factor is using 16 lower-order bits for decimal
* places. 32768 = 1 << 15, it is an integer representation
}
}
- if (outpic->data[1] && outpic->data[2]) {
+ if (frame->data[1] && frame->data[2]) {
/* chroma planes */
for (plane = 1; plane < 3; plane++) {
- for (i = 0; i < h; i++) {
- p = outpic->data[plane] + ((y+i) >> fade->vsub) * outpic->linesize[plane];
+ for (i = 0; i < frame->video->h; i++) {
+ p = frame->data[plane] + (i >> fade->vsub) * frame->linesize[plane];
for (j = 0; j < inlink->w >> fade->hsub; j++) {
/* 8421367 = ((128 << 1) + 1) << 15. It is an integer
* representation of 128.5. The .5 is for rounding
}
}
- return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir);
-}
-
-static int end_frame(AVFilterLink *inlink)
-{
- FadeContext *fade = inlink->dst->priv;
- int ret;
-
- ret = ff_end_frame(inlink->dst->outputs[0]);
-
if (fade->frame_index >= fade->start_frame &&
fade->frame_index <= fade->stop_frame)
fade->factor += fade->fade_per_frame;
fade->factor = av_clip_uint16(fade->factor);
fade->frame_index++;
- return ret;
+ return ff_filter_frame(inlink->dst->outputs[0], frame);
}
static const AVFilterPad avfilter_vf_fade_inputs[] = {
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_props,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = ff_null_start_frame,
- .draw_slice = draw_slice,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ | AV_PERM_WRITE,
.rej_perms = AV_PERM_PRESERVE,
},
return ff_get_video_buffer(outlink, perms, w, h);
}
-static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
- AVFilterContext *ctx = inlink->dst;
- AVFilterLink *outlink = ctx->outputs[0];
-
- AVFilterBufferRef *outpicref, *for_next_filter;
- int ret = 0;
-
- outpicref = avfilter_ref_buffer(inpicref, ~0);
- if (!outpicref)
- return AVERROR(ENOMEM);
-
- for_next_filter = avfilter_ref_buffer(outpicref, ~0);
- if (!for_next_filter) {
- avfilter_unref_bufferp(&outpicref);
- return AVERROR(ENOMEM);
- }
-
- ret = ff_start_frame(outlink, for_next_filter);
- if (ret < 0) {
- avfilter_unref_bufferp(&outpicref);
- return ret;
- }
-
- outlink->out_buf = outpicref;
- return 0;
-}
-
-static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
-{
- AVFilterContext *ctx = inlink->dst;
- FieldOrderContext *fieldorder = ctx->priv;
- AVFilterLink *outlink = ctx->outputs[0];
-
- AVFilterBufferRef *inpicref = inlink->cur_buf;
+ AVFilterContext *ctx = inlink->dst;
+ FieldOrderContext *s = ctx->priv;
+ AVFilterLink *outlink = ctx->outputs[0];
+ int h, plane, line_step, line_size, line;
+ uint8_t *data;
- /** can only currently do slices if this filter is doing nothing
- * because this filter is moving picture content, the output
- * slice will contain different video lines than the input slice
- * and that complexity will be added later */
- if ( !inpicref->video->interlaced
- || inpicref->video->top_field_first == fieldorder->dst_tff) {
- return ff_draw_slice(outlink, y, h, slice_dir);
- }
- return 0;
-}
+ if (!frame->video->interlaced ||
+ frame->video->top_field_first == s->dst_tff)
+ return ff_filter_frame(outlink, frame);
-static int end_frame(AVFilterLink *inlink)
-{
- AVFilterContext *ctx = inlink->dst;
- FieldOrderContext *fieldorder = ctx->priv;
- AVFilterLink *outlink = ctx->outputs[0];
-
- AVFilterBufferRef *inpicref = inlink->cur_buf;
- AVFilterBufferRef *outpicref = outlink->out_buf;
-
- int h, plane, line_step, line_size, line;
- uint8_t *cpy_src, *cpy_dst;
-
- if ( inpicref->video->interlaced
- && inpicref->video->top_field_first != fieldorder->dst_tff) {
av_dlog(ctx,
"picture will move %s one line\n",
- fieldorder->dst_tff ? "up" : "down");
- h = inpicref->video->h;
- for (plane = 0; plane < 4 && inpicref->data[plane]; plane++) {
- line_step = inpicref->linesize[plane];
- line_size = fieldorder->line_size[plane];
- cpy_src = inpicref->data[plane];
- cpy_dst = outpicref->data[plane];
- if (fieldorder->dst_tff) {
+ s->dst_tff ? "up" : "down");
+ h = frame->video->h;
+ for (plane = 0; plane < 4 && frame->data[plane]; plane++) {
+ line_step = frame->linesize[plane];
+ line_size = s->line_size[plane];
+ data = frame->data[plane];
+ if (s->dst_tff) {
/** Move every line up one line, working from
* the top to the bottom of the frame.
* The original top line is lost.
* The new last line is created as a copy of the
* penultimate line from that field. */
for (line = 0; line < h; line++) {
- if (1 + line < outpicref->video->h) {
- memcpy(cpy_dst, cpy_src + line_step, line_size);
+ if (1 + line < frame->video->h) {
+ memcpy(data, data + line_step, line_size);
} else {
- memcpy(cpy_dst, cpy_src - line_step - line_step, line_size);
+ memcpy(data, data - line_step - line_step, line_size);
}
- cpy_src += line_step;
- cpy_dst += line_step;
+ data += line_step;
}
} else {
/** Move every line down one line, working from
* The original bottom line is lost.
* The new first line is created as a copy of the
* second line from that field. */
- cpy_src += (h - 1) * line_step;
- cpy_dst += (h - 1) * line_step;
+ data += (h - 1) * line_step;
for (line = h - 1; line >= 0 ; line--) {
if (line > 0) {
- memcpy(cpy_dst, cpy_src - line_step, line_size);
+ memcpy(data, data - line_step, line_size);
} else {
- memcpy(cpy_dst, cpy_src + line_step + line_step, line_size);
+ memcpy(data, data + line_step + line_step, line_size);
}
- cpy_src -= line_step;
- cpy_dst -= line_step;
+ data -= line_step;
}
}
}
- outpicref->video->top_field_first = fieldorder->dst_tff;
- ff_draw_slice(outlink, 0, h, 1);
- } else {
- av_dlog(ctx,
- "not interlaced or field order already correct\n");
- }
+ frame->video->top_field_first = s->dst_tff;
- return ff_end_frame(outlink);
+ return ff_filter_frame(outlink, frame);
}
static const AVFilterPad avfilter_vf_fieldorder_inputs[] = {
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_input,
- .start_frame = start_frame,
.get_video_buffer = get_video_buffer,
- .draw_slice = draw_slice,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ,
.rej_perms = AV_PERM_REUSE2 | AV_PERM_PRESERVE,
},
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = ff_null_start_frame,
- .draw_slice = ff_null_draw_slice,
- .end_frame = ff_null_end_frame,
},
{ NULL }
};
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = ff_null_start_frame,
- .draw_slice = ff_null_draw_slice,
- .end_frame = ff_null_end_frame,
},
{ NULL }
};
buf->pts = av_rescale_q(s->first_pts, ctx->inputs[0]->time_base,
outlink->time_base) + s->frames_out;
- if ((ret = ff_start_frame(outlink, buf)) < 0 ||
- (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0)
+ if ((ret = ff_filter_frame(outlink, buf)) < 0)
return ret;
s->frames_out++;
return 0;
}
-static int end_frame(AVFilterLink *inlink)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
{
AVFilterContext *ctx = inlink->dst;
FPSContext *s = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0];
- AVFilterBufferRef *buf = inlink->cur_buf;
int64_t delta;
int i, ret;
- inlink->cur_buf = NULL;
s->frames_in++;
/* discard frames until we get the first timestamp */
if (s->pts == AV_NOPTS_VALUE) {
buf_out->pts = av_rescale_q(s->first_pts, inlink->time_base,
outlink->time_base) + s->frames_out;
- if ((ret = ff_start_frame(outlink, buf_out)) < 0 ||
- (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0) {
+ if ((ret = ff_filter_frame(outlink, buf_out)) < 0) {
avfilter_unref_bufferp(&buf);
return ret;
}
return ret;
}
-static int null_start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
-{
- return 0;
-}
-
-static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- return 0;
-}
-
static const AVFilterPad avfilter_vf_fps_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .start_frame = null_start_frame,
- .draw_slice = null_draw_slice,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
},
{ NULL }
};
return 0;
}
-static int null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
-{
- return 0;
-}
-
-static int end_frame(AVFilterLink *inlink)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
{
Frei0rContext *frei0r = inlink->dst->priv;
AVFilterLink *outlink = inlink->dst->outputs[0];
- AVFilterBufferRef *inpicref = inlink->cur_buf;
- AVFilterBufferRef *outpicref = outlink->out_buf;
- int ret;
-
- frei0r->update(frei0r->instance, inpicref->pts * av_q2d(inlink->time_base) * 1000,
- (const uint32_t *)inpicref->data[0],
- (uint32_t *)outpicref->data[0]);
- if ((ret = ff_draw_slice(outlink, 0, outlink->h, 1)) ||
- (ret = ff_end_frame(outlink)) < 0)
- return ret;
- return 0;
+ AVFilterBufferRef *out;
+
+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+ if (!out) {
+ avfilter_unref_bufferp(&in);
+ return AVERROR(ENOMEM);
+ }
+ avfilter_copy_buffer_ref_props(out, in);
+
+ frei0r->update(frei0r->instance, in->pts * av_q2d(inlink->time_base) * 1000,
+ (const uint32_t *)in->data[0],
+ (uint32_t *)out->data[0]);
+
+ avfilter_unref_bufferp(&in);
+
+ return ff_filter_frame(outlink, out);
}
static const AVFilterPad avfilter_vf_frei0r_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .draw_slice = null_draw_slice,
.config_props = config_input_props,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ
},
{ NULL }
{
Frei0rContext *frei0r = outlink->src->priv;
AVFilterBufferRef *picref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
- AVFilterBufferRef *buf_out;
- int ret;
if (!picref)
return AVERROR(ENOMEM);
picref->pts = frei0r->pts++;
picref->pos = -1;
- buf_out = avfilter_ref_buffer(picref, ~0);
- if (!buf_out) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- ret = ff_start_frame(outlink, buf_out);
- if (ret < 0)
- goto fail;
-
frei0r->update(frei0r->instance, av_rescale_q(picref->pts, frei0r->time_base, (AVRational){1,1000}),
NULL, (uint32_t *)picref->data[0]);
- ret = ff_draw_slice(outlink, 0, outlink->h, 1);
- if (ret < 0)
- goto fail;
-
- ret = ff_end_frame(outlink);
-
-fail:
- avfilter_unref_buffer(picref);
- return ret;
+ return ff_filter_frame(outlink, picref);
}
static const AVFilterPad avfilter_vsrc_frei0r_src_outputs[] = {
return 0;
}
-static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- return 0;
-}
-
-static int end_frame(AVFilterLink *inlink)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
{
GradFunContext *gf = inlink->dst->priv;
- AVFilterBufferRef *inpic = inlink->cur_buf;
AVFilterLink *outlink = inlink->dst->outputs[0];
- AVFilterBufferRef *outpic = outlink->out_buf;
- int p, ret;
+ AVFilterBufferRef *out;
+ int p, direct;
+
+ if ((in->perms & AV_PERM_WRITE) && !(in->perms & AV_PERM_PRESERVE)) {
+ direct = 1;
+ out = in;
+ } else {
+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+ if (!out) {
+ avfilter_unref_bufferp(&in);
+ return AVERROR(ENOMEM);
+ }
+
+ avfilter_copy_buffer_ref_props(out, in);
+ out->video->w = outlink->w;
+ out->video->h = outlink->h;
+ }
- for (p = 0; p < 4 && inpic->data[p]; p++) {
+ for (p = 0; p < 4 && in->data[p]; p++) {
int w = inlink->w;
int h = inlink->h;
int r = gf->radius;
}
if (FFMIN(w, h) > 2 * r)
- filter(gf, outpic->data[p], inpic->data[p], w, h, outpic->linesize[p], inpic->linesize[p], r);
- else if (outpic->data[p] != inpic->data[p])
- av_image_copy_plane(outpic->data[p], outpic->linesize[p], inpic->data[p], inpic->linesize[p], w, h);
+ filter(gf, out->data[p], in->data[p], w, h, out->linesize[p], in->linesize[p], r);
+ else if (out->data[p] != in->data[p])
+ av_image_copy_plane(out->data[p], out->linesize[p], in->data[p], in->linesize[p], w, h);
}
- if ((ret = ff_draw_slice(outlink, 0, inlink->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0)
- return ret;
- return 0;
+ if (!direct)
+ avfilter_unref_bufferp(&in);
+
+ return ff_filter_frame(outlink, out);
}
static const AVFilterPad avfilter_vf_gradfun_inputs[] = {
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_input,
- .start_frame = ff_inplace_start_frame,
- .draw_slice = null_draw_slice,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ,
},
{ NULL }
return 0;
}
-static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
{
- FlipContext *flip = inlink->dst->priv;
- AVFilterBufferRef *inpic = inlink->cur_buf;
- AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf;
+ AVFilterContext *ctx = inlink->dst;
+ FlipContext *flip = ctx->priv;
+ AVFilterLink *outlink = ctx->outputs[0];
+ AVFilterBufferRef *out;
uint8_t *inrow, *outrow;
int i, j, plane, step, hsub, vsub;
- for (plane = 0; plane < 4 && inpic->data[plane]; plane++) {
+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+ if (!out) {
+ avfilter_unref_bufferp(&in);
+ return AVERROR(ENOMEM);
+ }
+ avfilter_copy_buffer_ref_props(out, in);
+
+ for (plane = 0; plane < 4 && in->data[plane]; plane++) {
step = flip->max_step[plane];
hsub = (plane == 1 || plane == 2) ? flip->hsub : 0;
vsub = (plane == 1 || plane == 2) ? flip->vsub : 0;
- outrow = outpic->data[plane] + (y>>vsub) * outpic->linesize[plane];
- inrow = inpic ->data[plane] + (y>>vsub) * inpic ->linesize[plane] + ((inlink->w >> hsub) - 1) * step;
- for (i = 0; i < h>>vsub; i++) {
+ outrow = out->data[plane];
+ inrow = in ->data[plane] + ((inlink->w >> hsub) - 1) * step;
+ for (i = 0; i < in->video->h >> vsub; i++) {
switch (step) {
case 1:
for (j = 0; j < (inlink->w >> hsub); j++)
memcpy(outrow + j*step, inrow - j*step, step);
}
- inrow += inpic ->linesize[plane];
- outrow += outpic->linesize[plane];
+ inrow += in ->linesize[plane];
+ outrow += out->linesize[plane];
}
}
- return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir);
+ avfilter_unref_bufferp(&in);
+ return ff_filter_frame(outlink, out);
}
static const AVFilterPad avfilter_vf_hflip_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .draw_slice = draw_slice,
+ .filter_frame = filter_frame,
.config_props = config_props,
.min_perms = AV_PERM_READ,
},
return 0;
}
-static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- return 0;
-}
-
-static int end_frame(AVFilterLink *inlink)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
{
HQDN3DContext *hqdn3d = inlink->dst->priv;
AVFilterLink *outlink = inlink->dst->outputs[0];
- AVFilterBufferRef *inpic = inlink ->cur_buf;
- AVFilterBufferRef *outpic = outlink->out_buf;
- int ret, c;
+ AVFilterBufferRef *out;
+ int direct, c;
+
+ if ((in->perms & AV_PERM_WRITE) && !(in->perms & AV_PERM_PRESERVE)) {
+ direct = 1;
+ out = in;
+ } else {
+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+ if (!out) {
+ avfilter_unref_bufferp(&in);
+ return AVERROR(ENOMEM);
+ }
+
+ avfilter_copy_buffer_ref_props(out, in);
+ out->video->w = outlink->w;
+ out->video->h = outlink->h;
+ }
for (c = 0; c < 3; c++) {
- denoise(hqdn3d, inpic->data[c], outpic->data[c],
+ denoise(hqdn3d, in->data[c], out->data[c],
hqdn3d->line, &hqdn3d->frame_prev[c],
- inpic->video->w >> (!!c * hqdn3d->hsub),
- inpic->video->h >> (!!c * hqdn3d->vsub),
- inpic->linesize[c], outpic->linesize[c],
+ in->video->w >> (!!c * hqdn3d->hsub),
+ in->video->h >> (!!c * hqdn3d->vsub),
+ in->linesize[c], out->linesize[c],
hqdn3d->coefs[c?2:0], hqdn3d->coefs[c?3:1]);
}
- if ((ret = ff_draw_slice(outlink, 0, inpic->video->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0)
- return ret;
- return 0;
+ if (!direct)
+ avfilter_unref_bufferp(&in);
+
+ return ff_filter_frame(outlink, out);
}
static const AVFilterPad avfilter_vf_hqdn3d_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .start_frame = ff_inplace_start_frame,
- .draw_slice = null_draw_slice,
.config_props = config_input,
- .end_frame = end_frame
+ .filter_frame = filter_frame,
},
{ NULL }
};
#include "libavutil/file.h"
#include "avfilter.h"
#include "formats.h"
+#include "internal.h"
#include "video.h"
static void fill_iplimage_from_picref(IplImage *img, const AVFilterBufferRef *picref, enum AVPixelFormat pixfmt)
return 0;
}
-static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- return 0;
-}
-
typedef struct {
const char *name;
int (*init)(AVFilterContext *ctx, const char *args);
memset(ocv, 0, sizeof(*ocv));
}
-static int end_frame(AVFilterLink *inlink)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
{
AVFilterContext *ctx = inlink->dst;
OCVContext *ocv = ctx->priv;
AVFilterLink *outlink= inlink->dst->outputs[0];
- AVFilterBufferRef *inpicref = inlink ->cur_buf;
- AVFilterBufferRef *outpicref = outlink->out_buf;
+ AVFilterBufferRef *out;
IplImage inimg, outimg;
- int ret;
- fill_iplimage_from_picref(&inimg , inpicref , inlink->format);
- fill_iplimage_from_picref(&outimg, outpicref, inlink->format);
+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+ if (!out) {
+ avfilter_unref_bufferp(&in);
+ return AVERROR(ENOMEM);
+ }
+ avfilter_copy_buffer_ref_props(out, in);
+
+ fill_iplimage_from_picref(&inimg , in , inlink->format);
+ fill_iplimage_from_picref(&outimg, out, inlink->format);
ocv->end_frame_filter(ctx, &inimg, &outimg);
- fill_picref_from_iplimage(outpicref, &outimg, inlink->format);
+ fill_picref_from_iplimage(out, &outimg, inlink->format);
- if ((ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0)
- return ret;
- return 0;
+ avfilter_unref_bufferp(&in);
+
+ return ff_filter_frame(outlink, out);
}
static const AVFilterPad avfilter_vf_ocv_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .draw_slice = null_draw_slice,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ
},
{ NULL }
return 0;
}
-static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
{
AVFilterContext *ctx = inlink->dst;
LutContext *lut = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0];
- AVFilterBufferRef *inpic = inlink ->cur_buf;
- AVFilterBufferRef *outpic = outlink->out_buf;
+ AVFilterBufferRef *out;
uint8_t *inrow, *outrow, *inrow0, *outrow0;
int i, j, k, plane;
+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+ if (!out) {
+ avfilter_unref_bufferp(&in);
+ return AVERROR(ENOMEM);
+ }
+ avfilter_copy_buffer_ref_props(out, in);
+
if (lut->is_rgb) {
/* packed */
- inrow0 = inpic ->data[0] + y * inpic ->linesize[0];
- outrow0 = outpic->data[0] + y * outpic->linesize[0];
+ inrow0 = in ->data[0];
+ outrow0 = out->data[0];
- for (i = 0; i < h; i ++) {
+ for (i = 0; i < in->video->h; i ++) {
inrow = inrow0;
outrow = outrow0;
for (j = 0; j < inlink->w; j++) {
outrow += lut->step;
inrow += lut->step;
}
- inrow0 += inpic ->linesize[0];
- outrow0 += outpic->linesize[0];
+ inrow0 += in ->linesize[0];
+ outrow0 += out->linesize[0];
}
} else {
/* planar */
- for (plane = 0; plane < 4 && inpic->data[plane]; plane++) {
+ for (plane = 0; plane < 4 && in->data[plane]; plane++) {
int vsub = plane == 1 || plane == 2 ? lut->vsub : 0;
int hsub = plane == 1 || plane == 2 ? lut->hsub : 0;
- inrow = inpic ->data[plane] + (y>>vsub) * inpic ->linesize[plane];
- outrow = outpic->data[plane] + (y>>vsub) * outpic->linesize[plane];
+ inrow = in ->data[plane];
+ outrow = out->data[plane];
- for (i = 0; i < h>>vsub; i ++) {
+ for (i = 0; i < in->video->h >> vsub; i ++) {
for (j = 0; j < inlink->w>>hsub; j++)
outrow[j] = lut->lut[plane][inrow[j]];
- inrow += inpic ->linesize[plane];
- outrow += outpic->linesize[plane];
+ inrow += in ->linesize[plane];
+ outrow += out->linesize[plane];
}
}
}
- return ff_draw_slice(outlink, y, h, slice_dir);
+ avfilter_unref_bufferp(&in);
+ return ff_filter_frame(outlink, out);
}
static const AVFilterPad inputs[] = {
{ .name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .draw_slice = draw_slice,
+ .filter_frame = filter_frame,
.config_props = config_props,
.min_perms = AV_PERM_READ, },
{ .name = NULL}
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = ff_null_start_frame,
- .end_frame = ff_null_end_frame
},
{ NULL }
};
}
}
-static int null_start_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
-{
- return 0;
-}
-
-static int null_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
-{
- return 0;
-}
-
-static int end_frame_main(AVFilterLink *inlink)
+static int filter_frame_main(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
OverlayContext *s = inlink->dst->priv;
av_assert0(!s->main);
- s->main = inlink->cur_buf;
- inlink->cur_buf = NULL;
+ s->main = frame;
return 0;
}
-static int end_frame_overlay(AVFilterLink *inlink)
+static int filter_frame_overlay(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
OverlayContext *s = inlink->dst->priv;
av_assert0(!s->over_next);
- s->over_next = inlink->cur_buf;
- inlink->cur_buf = NULL;
+ s->over_next = frame;
return 0;
}
{
OverlayContext *s = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0];
- int ret = ff_start_frame(outlink, s->main);
- if (ret >= 0)
- ret = ff_draw_slice(outlink, 0, outlink->h, 1);
- if (ret >= 0)
- ret = ff_end_frame(outlink);
+ int ret = ff_filter_frame(outlink, s->main);
s->main = NULL;
return ret;
{
.name = "main",
.type = AVMEDIA_TYPE_VIDEO,
- .start_frame = null_start_frame,
.config_props = config_input_main,
- .draw_slice = null_draw_slice,
- .end_frame = end_frame_main,
+ .filter_frame = filter_frame_main,
.min_perms = AV_PERM_READ,
.rej_perms = AV_PERM_REUSE2 | AV_PERM_PRESERVE,
.needs_fifo = 1,
{
.name = "overlay",
.type = AVMEDIA_TYPE_VIDEO,
- .start_frame = null_start_frame,
.config_props = config_input_overlay,
- .draw_slice = null_draw_slice,
- .end_frame = end_frame_overlay,
+ .filter_frame = filter_frame_overlay,
.min_perms = AV_PERM_READ,
.rej_perms = AV_PERM_REUSE2,
.needs_fifo = 1,
uint8_t *line[4];
int line_step[4];
int hsub, vsub; ///< chroma subsampling values
- int needs_copy;
} PadContext;
static av_cold int init(AVFilterContext *ctx, const char *args)
return 0;
}
-static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
{
PadContext *pad = inlink->dst->priv;
- AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
- AVFilterBufferRef *for_next_filter;
- int plane, ret = 0;
+ AVFilterBufferRef *out = avfilter_ref_buffer(in, ~0);
+ int plane, needs_copy;
- if (!outpicref)
+ if (!out) {
+ avfilter_unref_bufferp(&in);
return AVERROR(ENOMEM);
+ }
- for (plane = 0; plane < 4 && outpicref->data[plane]; plane++) {
+ for (plane = 0; plane < 4 && out->data[plane]; plane++) {
int hsub = (plane == 1 || plane == 2) ? pad->hsub : 0;
int vsub = (plane == 1 || plane == 2) ? pad->vsub : 0;
- av_assert0(outpicref->buf->w>0 && outpicref->buf->h>0);
+ av_assert0(out->buf->w > 0 && out->buf->h > 0);
- if(outpicref->format != outpicref->buf->format) //unsupported currently
+ if (out->format != out->buf->format) //unsupported currently
break;
- outpicref->data[plane] -= (pad->x >> hsub) * pad ->line_step[plane]
- + (pad->y >> vsub) * outpicref->linesize [plane];
+ out->data[plane] -= (pad->x >> hsub) * pad->line_step[plane] +
+ (pad->y >> vsub) * out->linesize [plane];
- if( does_clip(pad, outpicref, plane, hsub, vsub, 0, 0)
- || does_clip(pad, outpicref, plane, hsub, vsub, 0, pad->h-1)
- || does_clip(pad, outpicref, plane, hsub, vsub, pad->w-1, 0)
- || does_clip(pad, outpicref, plane, hsub, vsub, pad->w-1, pad->h-1)
- )
+ if (does_clip(pad, out, plane, hsub, vsub, 0, 0) ||
+ does_clip(pad, out, plane, hsub, vsub, 0, pad->h - 1) ||
+ does_clip(pad, out, plane, hsub, vsub, pad->w - 1, 0) ||
+ does_clip(pad, out, plane, hsub, vsub, pad->w - 1, pad->h - 1))
break;
}
- pad->needs_copy= plane < 4 && outpicref->data[plane];
- if(pad->needs_copy){
+ needs_copy = plane < 4 && out->data[plane];
+ if (needs_copy) {
av_log(inlink->dst, AV_LOG_DEBUG, "Direct padding impossible allocating new frame\n");
- avfilter_unref_buffer(outpicref);
- outpicref = ff_get_video_buffer(inlink->dst->outputs[0], AV_PERM_WRITE | AV_PERM_NEG_LINESIZES,
- FFMAX(inlink->w, pad->w),
- FFMAX(inlink->h, pad->h));
- if (!outpicref)
+ avfilter_unref_buffer(out);
+ out = ff_get_video_buffer(inlink->dst->outputs[0], AV_PERM_WRITE | AV_PERM_NEG_LINESIZES,
+ FFMAX(inlink->w, pad->w),
+ FFMAX(inlink->h, pad->h));
+ if (!out) {
+ avfilter_unref_bufferp(&in);
return AVERROR(ENOMEM);
+ }
- avfilter_copy_buffer_ref_props(outpicref, inpicref);
- }
-
- outpicref->video->w = pad->w;
- outpicref->video->h = pad->h;
-
- for_next_filter = avfilter_ref_buffer(outpicref, ~0);
- if (!for_next_filter) {
- ret = AVERROR(ENOMEM);
- goto fail;
+ avfilter_copy_buffer_ref_props(out, in);
}
- ret = ff_start_frame(inlink->dst->outputs[0], for_next_filter);
- if (ret < 0)
- goto fail;
-
- inlink->dst->outputs[0]->out_buf = outpicref;
- return 0;
-
-fail:
- avfilter_unref_bufferp(&outpicref);
- return ret;
-}
-
-static int end_frame(AVFilterLink *link)
-{
- return ff_end_frame(link->dst->outputs[0]);
-}
+ out->video->w = pad->w;
+ out->video->h = pad->h;
-static int draw_send_bar_slice(AVFilterLink *link, int y, int h, int slice_dir, int before_slice)
-{
- PadContext *pad = link->dst->priv;
- int bar_y, bar_h = 0, ret = 0;
-
- if (slice_dir * before_slice == 1 && y == pad->y) {
- /* top bar */
- bar_y = 0;
- bar_h = pad->y;
- } else if (slice_dir * before_slice == -1 && (y + h) == (pad->y + pad->in_h)) {
- /* bottom bar */
- bar_y = pad->y + pad->in_h;
- bar_h = pad->h - pad->in_h - pad->y;
+ /* top bar */
+ if (pad->y) {
+ ff_draw_rectangle(out->data, out->linesize,
+ pad->line, pad->line_step, pad->hsub, pad->vsub,
+ 0, 0, pad->w, pad->y);
}
- if (bar_h) {
- ff_draw_rectangle(link->dst->outputs[0]->out_buf->data,
- link->dst->outputs[0]->out_buf->linesize,
+ /* bottom bar */
+ if (pad->h > pad->y + pad->in_h) {
+ ff_draw_rectangle(out->data, out->linesize,
pad->line, pad->line_step, pad->hsub, pad->vsub,
- 0, bar_y, pad->w, bar_h);
- ret = ff_draw_slice(link->dst->outputs[0], bar_y, bar_h, slice_dir);
+ 0, pad->y + pad->in_h, pad->w, pad->h - pad->y - pad->in_h);
}
- return ret;
-}
-
-static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- PadContext *pad = link->dst->priv;
- AVFilterBufferRef *outpic = link->dst->outputs[0]->out_buf;
- AVFilterBufferRef *inpic = link->cur_buf;
- int ret;
-
- y += pad->y;
-
- y &= ~((1 << pad->vsub) - 1);
- h &= ~((1 << pad->vsub) - 1);
-
- if (!h)
- return 0;
- draw_send_bar_slice(link, y, h, slice_dir, 1);
/* left border */
- ff_draw_rectangle(outpic->data, outpic->linesize, pad->line, pad->line_step,
- pad->hsub, pad->vsub, 0, y, pad->x, h);
-
- if(pad->needs_copy){
- ff_copy_rectangle(outpic->data, outpic->linesize,
- inpic->data, inpic->linesize, pad->line_step,
- pad->hsub, pad->vsub,
- pad->x, y, y-pad->y, inpic->video->w, h);
+ ff_draw_rectangle(out->data, out->linesize, pad->line, pad->line_step,
+ pad->hsub, pad->vsub, 0, pad->y, pad->x, in->video->h);
+
+ if (needs_copy) {
+ ff_copy_rectangle(out->data, out->linesize, in->data, in->linesize,
+ pad->line_step, pad->hsub, pad->vsub,
+ pad->x, pad->y, 0, in->video->w, in->video->h);
}
/* right border */
- ff_draw_rectangle(outpic->data, outpic->linesize,
+ ff_draw_rectangle(out->data, out->linesize,
pad->line, pad->line_step, pad->hsub, pad->vsub,
- pad->x + pad->in_w, y, pad->w - pad->x - pad->in_w, h);
- ret = ff_draw_slice(link->dst->outputs[0], y, h, slice_dir);
- if (ret < 0)
- return ret;
+ pad->x + pad->in_w, pad->y, pad->w - pad->x - pad->in_w,
+ in->video->h);
- return draw_send_bar_slice(link, y, h, slice_dir, -1);
+ avfilter_unref_bufferp(&in);
+ return ff_filter_frame(inlink->dst->outputs[0], out);
}
static const AVFilterPad avfilter_vf_pad_inputs[] = {
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_input,
.get_video_buffer = get_video_buffer,
- .start_frame = start_frame,
- .draw_slice = draw_slice,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
},
{ NULL }
};
return 0;
}
-static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
{
PixdescTestContext *priv = inlink->dst->priv;
AVFilterLink *outlink = inlink->dst->outputs[0];
- AVFilterBufferRef *outpicref, *for_next_filter;
- int i, ret = 0;
+ AVFilterBufferRef *out;
+ int i, c, w = inlink->w, h = inlink->h;
- outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE,
- outlink->w, outlink->h);
- if (!outpicref)
+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE,
+ outlink->w, outlink->h);
+ if (!out) {
+ avfilter_unref_bufferp(&in);
return AVERROR(ENOMEM);
+ }
- avfilter_copy_buffer_ref_props(outpicref, picref);
+ avfilter_copy_buffer_ref_props(out, in);
for (i = 0; i < 4; i++) {
int h = outlink->h;
h = i == 1 || i == 2 ? h>>priv->pix_desc->log2_chroma_h : h;
- if (outpicref->data[i]) {
- uint8_t *data = outpicref->data[i] +
- (outpicref->linesize[i] > 0 ? 0 : outpicref->linesize[i] * (h-1));
- memset(data, 0, FFABS(outpicref->linesize[i]) * h);
+ if (out->data[i]) {
+ uint8_t *data = out->data[i] +
+ (out->linesize[i] > 0 ? 0 : out->linesize[i] * (h-1));
+ memset(data, 0, FFABS(out->linesize[i]) * h);
}
}
/* copy palette */
if (priv->pix_desc->flags & PIX_FMT_PAL ||
priv->pix_desc->flags & PIX_FMT_PSEUDOPAL)
- memcpy(outpicref->data[1], outpicref->data[1], 256*4);
-
- for_next_filter = avfilter_ref_buffer(outpicref, ~0);
- if (for_next_filter)
- ret = ff_start_frame(outlink, for_next_filter);
- else
- ret = AVERROR(ENOMEM);
-
- if (ret < 0) {
- avfilter_unref_bufferp(&outpicref);
- return ret;
- }
-
- outlink->out_buf = outpicref;
- return 0;
-}
-
-static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
-{
- PixdescTestContext *priv = inlink->dst->priv;
- AVFilterBufferRef *inpic = inlink->cur_buf;
- AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf;
- int i, c, w = inlink->w;
+ memcpy(out->data[1], in->data[1], 256*4);
for (c = 0; c < priv->pix_desc->nb_components; c++) {
int w1 = c == 1 || c == 2 ? w>>priv->pix_desc->log2_chroma_w : w;
int h1 = c == 1 || c == 2 ? h>>priv->pix_desc->log2_chroma_h : h;
- int y1 = c == 1 || c == 2 ? y>>priv->pix_desc->log2_chroma_h : y;
- for (i = y1; i < y1 + h1; i++) {
+ for (i = 0; i < h1; i++) {
av_read_image_line(priv->line,
- inpic->data,
- inpic->linesize,
+ in->data,
+ in->linesize,
priv->pix_desc,
0, i, c, w1, 0);
av_write_image_line(priv->line,
- outpic->data,
- outpic->linesize,
+ out->data,
+ out->linesize,
priv->pix_desc,
0, i, c, w1);
}
}
- return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir);
+ avfilter_unref_bufferp(&in);
+ return ff_filter_frame(outlink, out);
}
static const AVFilterPad avfilter_vf_pixdesctest_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .start_frame = start_frame,
- .draw_slice = draw_slice,
+ .filter_frame = filter_frame,
.config_props = config_props,
.min_perms = AV_PERM_READ,
},
return ret;
}
-static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *in)
{
ScaleContext *scale = link->dst->priv;
AVFilterLink *outlink = link->dst->outputs[0];
- AVFilterBufferRef *outpicref, *for_next_filter;
+ AVFilterBufferRef *out;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
- int ret = 0;
- if (!scale->sws) {
- outpicref = avfilter_ref_buffer(picref, ~0);
- if (!outpicref)
- return AVERROR(ENOMEM);
- return ff_start_frame(outlink, outpicref);
- }
+ if (!scale->sws)
+ return ff_filter_frame(outlink, in);
scale->hsub = desc->log2_chroma_w;
scale->vsub = desc->log2_chroma_h;
- outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
- if (!outpicref)
+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+ if (!out) {
+ avfilter_unref_bufferp(&in);
return AVERROR(ENOMEM);
-
- avfilter_copy_buffer_ref_props(outpicref, picref);
- outpicref->video->w = outlink->w;
- outpicref->video->h = outlink->h;
-
-
- av_reduce(&outpicref->video->pixel_aspect.num, &outpicref->video->pixel_aspect.den,
- (int64_t)picref->video->pixel_aspect.num * outlink->h * link->w,
- (int64_t)picref->video->pixel_aspect.den * outlink->w * link->h,
- INT_MAX);
-
- scale->slice_y = 0;
- for_next_filter = avfilter_ref_buffer(outpicref, ~0);
- if (for_next_filter)
- ret = ff_start_frame(outlink, for_next_filter);
- else
- ret = AVERROR(ENOMEM);
-
- if (ret < 0) {
- avfilter_unref_bufferp(&outpicref);
- return ret;
}
- outlink->out_buf = outpicref;
- return 0;
-}
+ avfilter_copy_buffer_ref_props(out, in);
+ out->video->w = outlink->w;
+ out->video->h = outlink->h;
-static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- ScaleContext *scale = link->dst->priv;
- int out_h, ret;
- AVFilterBufferRef *cur_pic = link->cur_buf;
- const uint8_t *data[4];
+ av_reduce(&out->video->pixel_aspect.num, &out->video->pixel_aspect.den,
+ (int64_t)in->video->pixel_aspect.num * outlink->h * link->w,
+ (int64_t)in->video->pixel_aspect.den * outlink->w * link->h,
+ INT_MAX);
- if (!scale->sws) {
- return ff_draw_slice(link->dst->outputs[0], y, h, slice_dir);
- }
+ sws_scale(scale->sws, in->data, in->linesize, 0, in->video->h,
+ out->data, out->linesize);
- if (scale->slice_y == 0 && slice_dir == -1)
- scale->slice_y = link->dst->outputs[0]->h;
-
- data[0] = cur_pic->data[0] + y * cur_pic->linesize[0];
- data[1] = scale->input_is_pal ?
- cur_pic->data[1] :
- cur_pic->data[1] + (y>>scale->vsub) * cur_pic->linesize[1];
- data[2] = cur_pic->data[2] + (y>>scale->vsub) * cur_pic->linesize[2];
- data[3] = cur_pic->data[3] + y * cur_pic->linesize[3];
-
- out_h = sws_scale(scale->sws, data, cur_pic->linesize, y, h,
- link->dst->outputs[0]->out_buf->data,
- link->dst->outputs[0]->out_buf->linesize);
-
- if (slice_dir == -1)
- scale->slice_y -= out_h;
- ret = ff_draw_slice(link->dst->outputs[0], scale->slice_y, out_h, slice_dir);
- if (slice_dir == 1)
- scale->slice_y += out_h;
- return ret;
+ avfilter_unref_bufferp(&in);
+ return ff_filter_frame(outlink, out);
}
static const AVFilterPad avfilter_vf_scale_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .start_frame = start_frame,
- .draw_slice = draw_slice,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ,
},
{ NULL }
return res;
}
-static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
SelectContext *select = inlink->dst->priv;
- select->select = select_frame(inlink->dst, picref);
+ select->select = select_frame(inlink->dst, frame);
if (select->select) {
- AVFilterBufferRef *buf_out;
/* frame was requested through poll_frame */
if (select->cache_frames) {
- if (!av_fifo_space(select->pending_frames))
+ if (!av_fifo_space(select->pending_frames)) {
av_log(inlink->dst, AV_LOG_ERROR,
"Buffering limit reached, cannot cache more frames\n");
- else
- av_fifo_generic_write(select->pending_frames, &picref,
- sizeof(picref), NULL);
+ avfilter_unref_bufferp(&frame);
+ } else
+ av_fifo_generic_write(select->pending_frames, &frame,
+ sizeof(frame), NULL);
return 0;
}
- buf_out = avfilter_ref_buffer(picref, ~0);
- if (!buf_out)
- return AVERROR(ENOMEM);
- return ff_start_frame(inlink->dst->outputs[0], buf_out);
+ return ff_filter_frame(inlink->dst->outputs[0], frame);
}
- return 0;
-}
-
-static int draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
-{
- SelectContext *select = inlink->dst->priv;
-
- if (select->select && !select->cache_frames)
- return ff_draw_slice(inlink->dst->outputs[0], y, h, slice_dir);
- return 0;
-}
-
-static int end_frame(AVFilterLink *inlink)
-{
- SelectContext *select = inlink->dst->priv;
-
- if (select->select) {
- if (select->cache_frames)
- return 0;
- return ff_end_frame(inlink->dst->outputs[0]);
- }
+ avfilter_unref_bufferp(&frame);
return 0;
}
if (av_fifo_size(select->pending_frames)) {
AVFilterBufferRef *picref;
- int ret;
av_fifo_generic_read(select->pending_frames, &picref, sizeof(picref), NULL);
- if ((ret = ff_start_frame(outlink, picref)) < 0 ||
- (ret = ff_draw_slice(outlink, 0, outlink->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0);
-
- return ret;
+ return ff_filter_frame(outlink, picref);
}
while (!select->select) {
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = ff_null_get_video_buffer,
.config_props = config_input,
- .start_frame = start_frame,
- .draw_slice = draw_slice,
- .end_frame = end_frame
+ .filter_frame = filter_frame,
},
{ NULL }
};
#define D2TS(d) (isnan(d) ? AV_NOPTS_VALUE : (int64_t)(d))
#define TS2D(ts) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts))
-static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
SetPTSContext *setpts = inlink->dst->priv;
+ int64_t in_pts = frame->pts;
double d;
- AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
-
- if (!outpicref)
- return AVERROR(ENOMEM);
if (isnan(setpts->var_values[VAR_STARTPTS]))
- setpts->var_values[VAR_STARTPTS] = TS2D(inpicref->pts);
+ setpts->var_values[VAR_STARTPTS] = TS2D(frame->pts);
- setpts->var_values[VAR_INTERLACED] = inpicref->video->interlaced;
- setpts->var_values[VAR_PTS ] = TS2D(inpicref->pts);
- setpts->var_values[VAR_POS ] = inpicref->pos == -1 ? NAN : inpicref->pos;
+ setpts->var_values[VAR_INTERLACED] = frame->video->interlaced;
+ setpts->var_values[VAR_PTS ] = TS2D(frame->pts);
+ setpts->var_values[VAR_POS ] = frame->pos == -1 ? NAN : frame->pos;
d = av_expr_eval(setpts->expr, setpts->var_values, NULL);
- outpicref->pts = D2TS(d);
+ frame->pts = D2TS(d);
#ifdef DEBUG
av_log(inlink->dst, AV_LOG_DEBUG,
"n:%"PRId64" interlaced:%d pos:%"PRId64" pts:%"PRId64" t:%f -> pts:%"PRId64" t:%f\n",
(int64_t)setpts->var_values[VAR_N],
(int)setpts->var_values[VAR_INTERLACED],
- inpicref ->pos,
- inpicref ->pts, inpicref ->pts * av_q2d(inlink->time_base),
- outpicref->pts, outpicref->pts * av_q2d(inlink->time_base));
+ frame->pos, in_pts, in_pts * av_q2d(inlink->time_base),
+ frame->pts, frame->pts * av_q2d(inlink->time_base));
#endif
+
setpts->var_values[VAR_N] += 1.0;
- setpts->var_values[VAR_PREV_INPTS ] = TS2D(inpicref ->pts);
- setpts->var_values[VAR_PREV_OUTPTS] = TS2D(outpicref->pts);
- return ff_start_frame(inlink->dst->outputs[0], outpicref);
+ setpts->var_values[VAR_PREV_INPTS ] = TS2D(in_pts);
+ setpts->var_values[VAR_PREV_OUTPTS] = TS2D(frame->pts);
+ return ff_filter_frame(inlink->dst->outputs[0], frame);
}
static av_cold void uninit(AVFilterContext *ctx)
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = ff_null_get_video_buffer,
.config_props = config_input,
- .start_frame = start_frame,
+ .filter_frame = filter_frame,
},
{ NULL }
};
return 0;
}
-static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
AVFilterContext *ctx = inlink->dst;
AVFilterLink *outlink = ctx->outputs[0];
if (av_cmp_q(inlink->time_base, outlink->time_base)) {
- int64_t orig_pts = picref->pts;
- picref->pts = av_rescale_q(picref->pts, inlink->time_base, outlink->time_base);
+ int64_t orig_pts = frame->pts;
+ frame->pts = av_rescale_q(frame->pts, inlink->time_base, outlink->time_base);
av_log(ctx, AV_LOG_DEBUG, "tb:%d/%d pts:%"PRId64" -> tb:%d/%d pts:%"PRId64"\n",
inlink ->time_base.num, inlink ->time_base.den, orig_pts,
- outlink->time_base.num, outlink->time_base.den, picref->pts);
+ outlink->time_base.num, outlink->time_base.den, frame->pts);
}
- inlink->cur_buf = NULL;
- return ff_start_frame(outlink, picref);
+ return ff_filter_frame(outlink, frame);
}
static const AVFilterPad avfilter_vf_settb_inputs[] = {
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = start_frame,
- .end_frame = ff_null_end_frame
+ .filter_frame = filter_frame,
},
{ NULL }
};
return 0;
}
-static int end_frame(AVFilterLink *inlink)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *frame)
{
AVFilterContext *ctx = inlink->dst;
ShowInfoContext *showinfo = ctx->priv;
- AVFilterBufferRef *picref = inlink->cur_buf;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
uint32_t plane_checksum[4] = {0}, checksum = 0;
int i, plane, vsub = desc->log2_chroma_h;
- for (plane = 0; picref->data[plane] && plane < 4; plane++) {
- size_t linesize = av_image_get_linesize(picref->format, picref->video->w, plane);
- uint8_t *data = picref->data[plane];
+ for (plane = 0; frame->data[plane] && plane < 4; plane++) {
+ size_t linesize = av_image_get_linesize(frame->format, frame->video->w, plane);
+ uint8_t *data = frame->data[plane];
int h = plane == 1 || plane == 2 ? inlink->h >> vsub : inlink->h;
for (i = 0; i < h; i++) {
plane_checksum[plane] = av_adler32_update(plane_checksum[plane], data, linesize);
checksum = av_adler32_update(checksum, data, linesize);
- data += picref->linesize[plane];
+ data += frame->linesize[plane];
}
}
"fmt:%s sar:%d/%d s:%dx%d i:%c iskey:%d type:%c "
"checksum:%u plane_checksum:[%u %u %u %u]\n",
showinfo->frame,
- picref->pts, picref->pts * av_q2d(inlink->time_base), picref->pos,
+ frame->pts, frame->pts * av_q2d(inlink->time_base), frame->pos,
desc->name,
- picref->video->pixel_aspect.num, picref->video->pixel_aspect.den,
- picref->video->w, picref->video->h,
- !picref->video->interlaced ? 'P' : /* Progressive */
- picref->video->top_field_first ? 'T' : 'B', /* Top / Bottom */
- picref->video->key_frame,
- av_get_picture_type_char(picref->video->pict_type),
+ frame->video->pixel_aspect.num, frame->video->pixel_aspect.den,
+ frame->video->w, frame->video->h,
+ !frame->video->interlaced ? 'P' : /* Progressive */
+ frame->video->top_field_first ? 'T' : 'B', /* Top / Bottom */
+ frame->video->key_frame,
+ av_get_picture_type_char(frame->video->pict_type),
checksum, plane_checksum[0], plane_checksum[1], plane_checksum[2], plane_checksum[3]);
showinfo->frame++;
- return ff_end_frame(inlink->dst->outputs[0]);
+ return ff_filter_frame(inlink->dst->outputs[0], frame);
}
static const AVFilterPad avfilter_vf_showinfo_inputs[] = {
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = ff_null_get_video_buffer,
- .start_frame = ff_null_start_frame,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ,
},
{ NULL }
return 0;
}
-static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
+static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *in)
{
AVFilterLink *outlink = inlink->dst->outputs[0];
- AVFilterBufferRef *buf_out;
+ TransContext *trans = inlink->dst->priv;
+ AVFilterBufferRef *out;
+ int plane;
- outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE,
- outlink->w, outlink->h);
- if (!outlink->out_buf)
+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+ if (!out) {
+ avfilter_unref_bufferp(&in);
return AVERROR(ENOMEM);
+ }
- outlink->out_buf->pts = picref->pts;
+ out->pts = in->pts;
- if (picref->video->pixel_aspect.num == 0) {
- outlink->out_buf->video->pixel_aspect = picref->video->pixel_aspect;
+ if (in->video->pixel_aspect.num == 0) {
+ out->video->pixel_aspect = in->video->pixel_aspect;
} else {
- outlink->out_buf->video->pixel_aspect.num = picref->video->pixel_aspect.den;
- outlink->out_buf->video->pixel_aspect.den = picref->video->pixel_aspect.num;
+ out->video->pixel_aspect.num = in->video->pixel_aspect.den;
+ out->video->pixel_aspect.den = in->video->pixel_aspect.num;
}
- buf_out = avfilter_ref_buffer(outlink->out_buf, ~0);
- if (!buf_out)
- return AVERROR(ENOMEM);
- return ff_start_frame(outlink, buf_out);
-}
-
-static int end_frame(AVFilterLink *inlink)
-{
- TransContext *trans = inlink->dst->priv;
- AVFilterBufferRef *inpic = inlink->cur_buf;
- AVFilterBufferRef *outpic = inlink->dst->outputs[0]->out_buf;
- AVFilterLink *outlink = inlink->dst->outputs[0];
- int plane, ret;
-
- for (plane = 0; outpic->data[plane]; plane++) {
+ for (plane = 0; out->data[plane]; plane++) {
int hsub = plane == 1 || plane == 2 ? trans->hsub : 0;
int vsub = plane == 1 || plane == 2 ? trans->vsub : 0;
int pixstep = trans->pixsteps[plane];
- int inh = inpic->video->h>>vsub;
- int outw = outpic->video->w>>hsub;
- int outh = outpic->video->h>>vsub;
- uint8_t *out, *in;
- int outlinesize, inlinesize;
+ int inh = in->video->h>>vsub;
+ int outw = out->video->w>>hsub;
+ int outh = out->video->h>>vsub;
+ uint8_t *dst, *src;
+ int dstlinesize, srclinesize;
int x, y;
- out = outpic->data[plane]; outlinesize = outpic->linesize[plane];
- in = inpic ->data[plane]; inlinesize = inpic ->linesize[plane];
+ dst = out->data[plane];
+ dstlinesize = out->linesize[plane];
+ src = in->data[plane];
+ srclinesize = in->linesize[plane];
if (trans->dir&1) {
- in += inpic->linesize[plane] * (inh-1);
- inlinesize *= -1;
+ src += in->linesize[plane] * (inh-1);
+ srclinesize *= -1;
}
if (trans->dir&2) {
- out += outpic->linesize[plane] * (outh-1);
- outlinesize *= -1;
+ dst += out->linesize[plane] * (outh-1);
+ dstlinesize *= -1;
}
for (y = 0; y < outh; y++) {
switch (pixstep) {
case 1:
for (x = 0; x < outw; x++)
- out[x] = in[x*inlinesize + y];
+ dst[x] = src[x*srclinesize + y];
break;
case 2:
for (x = 0; x < outw; x++)
- *((uint16_t *)(out + 2*x)) = *((uint16_t *)(in + x*inlinesize + y*2));
+ *((uint16_t *)(dst + 2*x)) = *((uint16_t *)(src + x*srclinesize + y*2));
break;
case 3:
for (x = 0; x < outw; x++) {
- int32_t v = AV_RB24(in + x*inlinesize + y*3);
- AV_WB24(out + 3*x, v);
+ int32_t v = AV_RB24(src + x*srclinesize + y*3);
+ AV_WB24(dst + 3*x, v);
}
break;
case 4:
for (x = 0; x < outw; x++)
- *((uint32_t *)(out + 4*x)) = *((uint32_t *)(in + x*inlinesize + y*4));
+ *((uint32_t *)(dst + 4*x)) = *((uint32_t *)(src + x*srclinesize + y*4));
break;
}
- out += outlinesize;
+ dst += dstlinesize;
}
}
- if ((ret = ff_draw_slice(outlink, 0, outpic->video->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0)
- return ret;
- return 0;
+ avfilter_unref_bufferp(&in);
+ return ff_filter_frame(outlink, out);
}
static const AVFilterPad avfilter_vf_transpose_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .start_frame = start_frame,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
.min_perms = AV_PERM_READ,
},
{ NULL }
free_filter_param(&unsharp->chroma);
}
-static int end_frame(AVFilterLink *link)
+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *in)
{
UnsharpContext *unsharp = link->dst->priv;
- AVFilterBufferRef *in = link->cur_buf;
- AVFilterBufferRef *out = link->dst->outputs[0]->out_buf;
+ AVFilterLink *outlink = link->dst->outputs[0];
+ AVFilterBufferRef *out;
int cw = SHIFTUP(link->w, unsharp->hsub);
int ch = SHIFTUP(link->h, unsharp->vsub);
- int ret;
+
+ out = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+ if (!out) {
+ avfilter_unref_bufferp(&in);
+ return AVERROR(ENOMEM);
+ }
+ avfilter_copy_buffer_ref_props(out, in);
apply_unsharp(out->data[0], out->linesize[0], in->data[0], in->linesize[0], link->w, link->h, &unsharp->luma);
apply_unsharp(out->data[1], out->linesize[1], in->data[1], in->linesize[1], cw, ch, &unsharp->chroma);
apply_unsharp(out->data[2], out->linesize[2], in->data[2], in->linesize[2], cw, ch, &unsharp->chroma);
- if ((ret = ff_draw_slice(link->dst->outputs[0], 0, link->h, 1)) < 0 ||
- (ret = ff_end_frame(link->dst->outputs[0])) < 0)
- return ret;
- return 0;
-}
-
-static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- return 0;
+ avfilter_unref_bufferp(&in);
+ return ff_filter_frame(outlink, out);
}
static const AVFilterPad avfilter_vf_unsharp_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .draw_slice = draw_slice,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
.config_props = config_props,
.min_perms = AV_PERM_READ,
},
return picref;
}
-static int start_frame(AVFilterLink *link, AVFilterBufferRef *inpicref)
+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
{
FlipContext *flip = link->dst->priv;
- AVFilterBufferRef *outpicref = avfilter_ref_buffer(inpicref, ~0);
int i;
- if (!outpicref)
- return AVERROR(ENOMEM);
-
for (i = 0; i < 4; i ++) {
int vsub = i == 1 || i == 2 ? flip->vsub : 0;
- if (outpicref->data[i]) {
- outpicref->data[i] += ((link->h >> vsub)-1) * outpicref->linesize[i];
- outpicref->linesize[i] = -outpicref->linesize[i];
+ if (frame->data[i]) {
+ frame->data[i] += ((link->h >> vsub)-1) * frame->linesize[i];
+ frame->linesize[i] = -frame->linesize[i];
}
}
- return ff_start_frame(link->dst->outputs[0], outpicref);
-}
-
-static int draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- AVFilterContext *ctx = link->dst;
-
- return ff_draw_slice(ctx->outputs[0], link->h - (y+h), h, -1 * slice_dir);
+ return ff_filter_frame(link->dst->outputs[0], frame);
}
-
static const AVFilterPad avfilter_vf_vflip_inputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.get_video_buffer = get_video_buffer,
- .start_frame = start_frame,
- .draw_slice = draw_slice,
+ .filter_frame = filter_frame,
.config_props = config_input,
},
{ NULL }
} else {
yadif->out->pts = AV_NOPTS_VALUE;
}
- ret = ff_start_frame(ctx->outputs[0], yadif->out);
- if (ret < 0)
- return ret;
}
- if ((ret = ff_draw_slice(ctx->outputs[0], 0, link->h, 1)) < 0 ||
- (ret = ff_end_frame(ctx->outputs[0])) < 0)
- return ret;
+ ret = ff_filter_frame(ctx->outputs[0], yadif->out);
yadif->frame_pending = (yadif->mode&1) && !is_second;
- return 0;
+ return ret;
}
-static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *picref)
{
AVFilterContext *ctx = link->dst;
YADIFContext *yadif = ctx->priv;
yadif->prev = yadif->cur;
yadif->cur = yadif->next;
yadif->next = picref;
- link->cur_buf = NULL;
if (!yadif->cur)
return 0;
avfilter_unref_bufferp(&yadif->prev);
if (yadif->out->pts != AV_NOPTS_VALUE)
yadif->out->pts *= 2;
- return ff_start_frame(ctx->outputs[0], yadif->out);
+ return ff_filter_frame(ctx->outputs[0], yadif->out);
}
if (!yadif->prev &&
if (yadif->out->pts != AV_NOPTS_VALUE)
yadif->out->pts *= 2;
- return ff_start_frame(ctx->outputs[0], yadif->out);
-}
-
-static int end_frame(AVFilterLink *link)
-{
- AVFilterContext *ctx = link->dst;
- YADIFContext *yadif = ctx->priv;
-
- if (!yadif->out)
- return 0;
-
- if (yadif->auto_enable && !yadif->cur->video->interlaced) {
- int ret = ff_draw_slice(ctx->outputs[0], 0, link->h, 1);
- if (ret >= 0)
- ret = ff_end_frame(ctx->outputs[0]);
- return ret;
- }
-
- return_frame(ctx, 0);
- return 0;
+ return return_frame(ctx, 0);
}
static int request_frame(AVFilterLink *link)
next->pts = yadif->next->pts * 2 - yadif->cur->pts;
- start_frame(link->src->inputs[0], next);
- end_frame(link->src->inputs[0]);
+ filter_frame(link->src->inputs[0], next);
yadif->eof = 1;
} else if (ret < 0) {
return ret;
return 0;
}
-static int null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- return 0;
-}
-
static int config_props(AVFilterLink *link)
{
link->time_base.num = link->src->inputs[0]->time_base.num;
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .start_frame = start_frame,
.get_video_buffer = get_video_buffer,
- .draw_slice = null_draw_slice,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
},
{ NULL }
};
return ret;
}
-
-int ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
-{
- AVFilterBufferRef *buf_out = avfilter_ref_buffer(picref, ~0);
- if (!buf_out)
- return AVERROR(ENOMEM);
- return ff_start_frame(link->dst->outputs[0], buf_out);
-}
-
-// for filters that support (but don't require) outpic==inpic
-int ff_inplace_start_frame(AVFilterLink *inlink, AVFilterBufferRef *inpicref)
-{
- AVFilterLink *outlink = inlink->dst->outputs[0];
- AVFilterBufferRef *outpicref = NULL, *for_next_filter;
- int ret = 0;
-
- if ((inpicref->perms & AV_PERM_WRITE) && !(inpicref->perms & AV_PERM_PRESERVE)) {
- outpicref = avfilter_ref_buffer(inpicref, ~0);
- if (!outpicref)
- return AVERROR(ENOMEM);
- } else {
- outpicref = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
- if (!outpicref)
- return AVERROR(ENOMEM);
-
- avfilter_copy_buffer_ref_props(outpicref, inpicref);
- outpicref->video->w = outlink->w;
- outpicref->video->h = outlink->h;
- }
-
- for_next_filter = avfilter_ref_buffer(outpicref, ~0);
- if (for_next_filter)
- ret = ff_start_frame(outlink, for_next_filter);
- else
- ret = AVERROR(ENOMEM);
-
- if (ret < 0) {
- avfilter_unref_bufferp(&outpicref);
- return ret;
- }
-
- outlink->out_buf = outpicref;
- return 0;
-}
-
-static int default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
-{
- AVFilterLink *outlink = NULL;
-
- if (inlink->dst->nb_outputs)
- outlink = inlink->dst->outputs[0];
-
- if (outlink) {
- AVFilterBufferRef *buf_out;
- outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
- if (!outlink->out_buf)
- return AVERROR(ENOMEM);
-
- avfilter_copy_buffer_ref_props(outlink->out_buf, picref);
- buf_out = avfilter_ref_buffer(outlink->out_buf, ~0);
- if (!buf_out)
- return AVERROR(ENOMEM);
-
- return ff_start_frame(outlink, buf_out);
- }
- return 0;
-}
-
-static void clear_link(AVFilterLink *link)
-{
- avfilter_unref_bufferp(&link->cur_buf);
- avfilter_unref_bufferp(&link->src_buf);
- avfilter_unref_bufferp(&link->out_buf);
-}
-
-/* XXX: should we do the duplicating of the picture ref here, instead of
- * forcing the source filter to do it? */
-int ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
-{
- int (*start_frame)(AVFilterLink *, AVFilterBufferRef *);
- AVFilterPad *dst = link->dstpad;
- int ret, perms = picref->perms;
-
- FF_DPRINTF_START(NULL, start_frame); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " "); ff_dlog_ref(NULL, picref, 1);
-
- if (!(start_frame = dst->start_frame))
- start_frame = default_start_frame;
-
- if (picref->linesize[0] < 0)
- perms |= AV_PERM_NEG_LINESIZES;
- /* prepare to copy the picture if it has insufficient permissions */
- if ((dst->min_perms & perms) != dst->min_perms || dst->rej_perms & perms) {
- av_log(link->dst, AV_LOG_DEBUG,
- "frame copy needed (have perms %x, need %x, reject %x)\n",
- picref->perms,
- link->dstpad->min_perms, link->dstpad->rej_perms);
-
- link->cur_buf = ff_get_video_buffer(link, dst->min_perms, link->w, link->h);
- if (!link->cur_buf) {
- avfilter_unref_bufferp(&picref);
- return AVERROR(ENOMEM);
- }
-
- link->src_buf = picref;
- avfilter_copy_buffer_ref_props(link->cur_buf, link->src_buf);
- }
- else
- link->cur_buf = picref;
-
- ret = start_frame(link, link->cur_buf);
- if (ret < 0)
- clear_link(link);
-
- return ret;
-}
-
-int ff_null_end_frame(AVFilterLink *link)
-{
- return ff_end_frame(link->dst->outputs[0]);
-}
-
-static int default_end_frame(AVFilterLink *inlink)
-{
- AVFilterLink *outlink = NULL;
-
- if (inlink->dst->nb_outputs)
- outlink = inlink->dst->outputs[0];
-
- if (outlink) {
- return ff_end_frame(outlink);
- }
- return 0;
-}
-
-int ff_end_frame(AVFilterLink *link)
-{
- int (*end_frame)(AVFilterLink *);
- int ret;
-
- if (!(end_frame = link->dstpad->end_frame))
- end_frame = default_end_frame;
-
- ret = end_frame(link);
-
- clear_link(link);
-
- return ret;
-}
-
-int ff_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- return ff_draw_slice(link->dst->outputs[0], y, h, slice_dir);
-}
-
-static int default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
-{
- AVFilterLink *outlink = NULL;
-
- if (inlink->dst->nb_outputs)
- outlink = inlink->dst->outputs[0];
-
- if (outlink)
- return ff_draw_slice(outlink, y, h, slice_dir);
- return 0;
-}
-
-int ff_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- uint8_t *src[4], *dst[4];
- int i, j, vsub, ret;
- int (*draw_slice)(AVFilterLink *, int, int, int);
-
- FF_DPRINTF_START(NULL, draw_slice); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " y:%d h:%d dir:%d\n", y, h, slice_dir);
-
- /* copy the slice if needed for permission reasons */
- if (link->src_buf) {
- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(link->format);
- vsub = desc->log2_chroma_h;
-
- for (i = 0; i < 4; i++) {
- if (link->src_buf->data[i]) {
- src[i] = link->src_buf-> data[i] +
- (y >> (i==1 || i==2 ? vsub : 0)) * link->src_buf-> linesize[i];
- dst[i] = link->cur_buf->data[i] +
- (y >> (i==1 || i==2 ? vsub : 0)) * link->cur_buf->linesize[i];
- } else
- src[i] = dst[i] = NULL;
- }
-
- for (i = 0; i < 4; i++) {
- int planew =
- av_image_get_linesize(link->format, link->cur_buf->video->w, i);
-
- if (!src[i]) continue;
-
- for (j = 0; j < h >> (i==1 || i==2 ? vsub : 0); j++) {
- memcpy(dst[i], src[i], planew);
- src[i] += link->src_buf->linesize[i];
- dst[i] += link->cur_buf->linesize[i];
- }
- }
- }
-
- if (!(draw_slice = link->dstpad->draw_slice))
- draw_slice = default_draw_slice;
- ret = draw_slice(link, y, h, slice_dir);
- if (ret < 0)
- clear_link(link);
- return ret;
-}
AVFilterBufferRef *ff_get_video_buffer(AVFilterLink *link, int perms,
int w, int h);
-int ff_inplace_start_frame(AVFilterLink *link, AVFilterBufferRef *picref);
-int ff_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref);
-int ff_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir);
-int ff_null_end_frame(AVFilterLink *link);
-
-/**
- * Notify the next filter of the start of a frame.
- *
- * @param link the output link the frame will be sent over
- * @param picref A reference to the frame about to be sent. The data for this
- * frame need only be valid once draw_slice() is called for that
- * portion. The receiving filter will free this reference when
- * it no longer needs it.
- *
- * @return >= 0 on success, a negative AVERROR on error. This function will
- * unreference picref in case of error.
- */
-int ff_start_frame(AVFilterLink *link, AVFilterBufferRef *picref);
-
-/**
- * Notify the next filter that the current frame has finished.
- *
- * @param link the output link the frame was sent over
- *
- * @return >= 0 on success, a negative AVERROR on error
- */
-int ff_end_frame(AVFilterLink *link);
-
-/**
- * Send a slice to the next filter.
- *
- * Slices have to be provided in sequential order, either in
- * top-bottom or bottom-top order. If slices are provided in
- * non-sequential order the behavior of the function is undefined.
- *
- * @param link the output link over which the frame is being sent
- * @param y offset in pixels from the top of the image for this slice
- * @param h height of this slice in pixels
- * @param slice_dir the assumed direction for sending slices,
- * from the top slice to the bottom slice if the value is 1,
- * from the bottom slice to the top slice if the value is -1,
- * for other values the behavior of the function is undefined.
- *
- * @return >= 0 on success, a negative AVERROR on error.
- */
-int ff_draw_slice(AVFilterLink *link, int y, int h, int slice_dir);
-
#endif /* AVFILTER_VIDEO_H */
#include "internal.h"
#include "libavutil/internal.h"
-static int start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
-{
- return 0;
-}
-
-static int end_frame(AVFilterLink *link)
+static int filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
{
+ avfilter_unref_bufferp(&frame);
return 0;
}
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
- .start_frame = start_frame,
- .end_frame = end_frame,
+ .filter_frame = filter_frame,
},
{ NULL },
};
{
ColorContext *color = link->src->priv;
AVFilterBufferRef *picref = ff_get_video_buffer(link, AV_PERM_WRITE, color->w, color->h);
- AVFilterBufferRef *buf_out;
- int ret;
if (!picref)
return AVERROR(ENOMEM);
picref->pts = color->pts++;
picref->pos = -1;
- buf_out = avfilter_ref_buffer(picref, ~0);
- if (!buf_out) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- ret = ff_start_frame(link, buf_out);
- if (ret < 0)
- goto fail;
-
ff_draw_rectangle(picref->data, picref->linesize,
color->line, color->line_step, color->hsub, color->vsub,
0, 0, color->w, color->h);
- ret = ff_draw_slice(link, 0, color->h, 1);
- if (ret < 0)
- goto fail;
-
- ret = ff_end_frame(link);
-
-fail:
- avfilter_unref_buffer(picref);
-
- return ret;
+ return ff_filter_frame(link, picref);
}
static const AVFilterPad avfilter_vsrc_color_outputs[] = {
static int request_frame(AVFilterLink *outlink)
{
- AVFilterBufferRef *outpicref;
MovieContext *movie = outlink->src->priv;
int ret;
if ((ret = movie_get_frame(outlink)) < 0)
return ret;
- outpicref = avfilter_ref_buffer(movie->picref, ~0);
- if (!outpicref) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- ret = ff_start_frame(outlink, outpicref);
- if (ret < 0)
- goto fail;
-
- ret = ff_draw_slice(outlink, 0, outlink->h, 1);
- if (ret < 0)
- goto fail;
-
- ret = ff_end_frame(outlink);
-fail:
- avfilter_unref_bufferp(&movie->picref);
+ ret = ff_filter_frame(outlink, movie->picref);
+ movie->picref = NULL;
return ret;
}
{
TestSourceContext *test = outlink->src->priv;
AVFilterBufferRef *picref;
- int ret;
if (test->max_pts >= 0 && test->pts > test->max_pts)
return AVERROR_EOF;
test->nb_frame++;
test->fill_picture_fn(outlink->src, picref);
- if ((ret = ff_start_frame(outlink, picref)) < 0 ||
- (ret = ff_draw_slice(outlink, 0, test->h, 1)) < 0 ||
- (ret = ff_end_frame(outlink)) < 0)
- return ret;
-
- return 0;
+ return ff_filter_frame(outlink, picref);
}
#if CONFIG_TESTSRC_FILTER