You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-11-23 21:54:53 +02:00
libavfilter: Support using filter_frame for video
With this we can mix filters using filter_frame OR start/draw_slice/end Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
@@ -162,7 +162,7 @@ static int default_filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
|
|||||||
return ff_filter_frame(link->dst->outputs[0], frame);
|
return ff_filter_frame(link->dst->outputs[0], frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_filter_frame_framed(AVFilterLink *link, AVFilterBufferRef *samplesref)
|
int ff_filter_samples_framed(AVFilterLink *link, AVFilterBufferRef *samplesref)
|
||||||
{
|
{
|
||||||
int (*filter_frame)(AVFilterLink *, AVFilterBufferRef *);
|
int (*filter_frame)(AVFilterLink *, AVFilterBufferRef *);
|
||||||
AVFilterPad *src = link->srcpad;
|
AVFilterPad *src = link->srcpad;
|
||||||
@@ -217,7 +217,7 @@ int ff_filter_frame_framed(AVFilterLink *link, AVFilterBufferRef *samplesref)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_filter_frame(AVFilterLink *link, AVFilterBufferRef *samplesref)
|
int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
|
||||||
{
|
{
|
||||||
int insamples = samplesref->audio->nb_samples, inpos = 0, nb_samples;
|
int insamples = samplesref->audio->nb_samples, inpos = 0, nb_samples;
|
||||||
AVFilterBufferRef *pbuf = link->partial_buf;
|
AVFilterBufferRef *pbuf = link->partial_buf;
|
||||||
@@ -231,7 +231,7 @@ int ff_filter_frame(AVFilterLink *link, AVFilterBufferRef *samplesref)
|
|||||||
if (!link->min_samples ||
|
if (!link->min_samples ||
|
||||||
(!pbuf &&
|
(!pbuf &&
|
||||||
insamples >= link->min_samples && insamples <= link->max_samples)) {
|
insamples >= link->min_samples && insamples <= link->max_samples)) {
|
||||||
return ff_filter_frame_framed(link, samplesref);
|
return ff_filter_samples_framed(link, samplesref);
|
||||||
}
|
}
|
||||||
/* Handle framing (min_samples, max_samples) */
|
/* Handle framing (min_samples, max_samples) */
|
||||||
while (insamples) {
|
while (insamples) {
|
||||||
@@ -258,7 +258,7 @@ int ff_filter_frame(AVFilterLink *link, AVFilterBufferRef *samplesref)
|
|||||||
insamples -= nb_samples;
|
insamples -= nb_samples;
|
||||||
pbuf->audio->nb_samples += nb_samples;
|
pbuf->audio->nb_samples += nb_samples;
|
||||||
if (pbuf->audio->nb_samples >= link->min_samples) {
|
if (pbuf->audio->nb_samples >= link->min_samples) {
|
||||||
ret = ff_filter_frame_framed(link, pbuf);
|
ret = ff_filter_samples_framed(link, pbuf);
|
||||||
pbuf = NULL;
|
pbuf = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#define AVFILTER_AUDIO_H
|
#define AVFILTER_AUDIO_H
|
||||||
|
|
||||||
#include "avfilter.h"
|
#include "avfilter.h"
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
static const enum AVSampleFormat ff_packed_sample_fmts_array[] = {
|
static const enum AVSampleFormat ff_packed_sample_fmts_array[] = {
|
||||||
AV_SAMPLE_FMT_U8,
|
AV_SAMPLE_FMT_U8,
|
||||||
@@ -74,13 +75,13 @@ AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms,
|
|||||||
* @return >= 0 on success, a negative AVERROR on error. The receiving filter
|
* @return >= 0 on success, a negative AVERROR on error. The receiving filter
|
||||||
* is responsible for unreferencing samplesref in case of error.
|
* is responsible for unreferencing samplesref in case of error.
|
||||||
*/
|
*/
|
||||||
int ff_filter_frame(AVFilterLink *link, AVFilterBufferRef *samplesref);
|
int ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a buffer of audio samples to the next link, without checking
|
* Send a buffer of audio samples to the next link, without checking
|
||||||
* min_samples.
|
* min_samples.
|
||||||
*/
|
*/
|
||||||
int ff_filter_frame_framed(AVFilterLink *link,
|
int ff_filter_samples_framed(AVFilterLink *link,
|
||||||
AVFilterBufferRef *samplesref);
|
AVFilterBufferRef *samplesref);
|
||||||
|
|
||||||
#endif /* AVFILTER_AUDIO_H */
|
#endif /* AVFILTER_AUDIO_H */
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ int ff_request_frame(AVFilterLink *link)
|
|||||||
if (ret == AVERROR_EOF && link->partial_buf) {
|
if (ret == AVERROR_EOF && link->partial_buf) {
|
||||||
AVFilterBufferRef *pbuf = link->partial_buf;
|
AVFilterBufferRef *pbuf = link->partial_buf;
|
||||||
link->partial_buf = NULL;
|
link->partial_buf = NULL;
|
||||||
ff_filter_frame_framed(link, pbuf);
|
ff_filter_samples_framed(link, pbuf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (ret == AVERROR_EOF)
|
if (ret == AVERROR_EOF)
|
||||||
@@ -631,3 +631,23 @@ enum AVMediaType avfilter_pad_get_type(AVFilterPad *pads, int pad_idx)
|
|||||||
{
|
{
|
||||||
return pads[pad_idx].type;
|
return pads[pad_idx].type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ff_filter_frame(AVFilterLink *link, AVFilterBufferRef *frame)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); ff_tlog_ref(NULL, frame, 1);
|
||||||
|
|
||||||
|
switch (link->type) {
|
||||||
|
case AVMEDIA_TYPE_VIDEO:
|
||||||
|
if((ret = ff_start_frame(link, frame)) < 0)
|
||||||
|
return ret;
|
||||||
|
if((ret = ff_draw_slice(link, 0, frame->video->h, 1)) < 0)
|
||||||
|
return ret;
|
||||||
|
if((ret = ff_end_frame(link)) < 0)
|
||||||
|
return ret;
|
||||||
|
return ret;
|
||||||
|
case AVMEDIA_TYPE_AUDIO:
|
||||||
|
return ff_filter_samples(link, frame);
|
||||||
|
default: return AVERROR(EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -368,5 +368,17 @@ AVFilterBufferRef *ff_copy_buffer_ref(AVFilterLink *outlink,
|
|||||||
int ff_buffersink_read_compat(AVFilterContext *ctx, AVFilterBufferRef **buf);
|
int ff_buffersink_read_compat(AVFilterContext *ctx, AVFilterBufferRef **buf);
|
||||||
int ff_buffersink_read_samples_compat(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
|
int ff_buffersink_read_samples_compat(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
|
||||||
int nb_samples);
|
int nb_samples);
|
||||||
|
/**
|
||||||
|
* 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 */
|
#endif /* AVFILTER_INTERNAL_H */
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ static int default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
|
|||||||
if (inlink->dst->nb_outputs)
|
if (inlink->dst->nb_outputs)
|
||||||
outlink = inlink->dst->outputs[0];
|
outlink = inlink->dst->outputs[0];
|
||||||
|
|
||||||
if (outlink) {
|
if (outlink && !inlink->dstpad->filter_frame) {
|
||||||
AVFilterBufferRef *buf_out;
|
AVFilterBufferRef *buf_out;
|
||||||
outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
|
outlink->out_buf = ff_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
|
||||||
if (!outlink->out_buf)
|
if (!outlink->out_buf)
|
||||||
@@ -328,7 +328,13 @@ static int default_end_frame(AVFilterLink *inlink)
|
|||||||
outlink = inlink->dst->outputs[0];
|
outlink = inlink->dst->outputs[0];
|
||||||
|
|
||||||
if (outlink) {
|
if (outlink) {
|
||||||
return ff_end_frame(outlink);
|
if (inlink->dstpad->filter_frame) {
|
||||||
|
int ret = inlink->dstpad->filter_frame(inlink, inlink->cur_buf);
|
||||||
|
inlink->cur_buf = NULL;
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
return ff_end_frame(outlink);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -360,7 +366,7 @@ static int default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
|
|||||||
if (inlink->dst->nb_outputs)
|
if (inlink->dst->nb_outputs)
|
||||||
outlink = inlink->dst->outputs[0];
|
outlink = inlink->dst->outputs[0];
|
||||||
|
|
||||||
if (outlink)
|
if (outlink && !inlink->dstpad->filter_frame)
|
||||||
return ff_draw_slice(outlink, y, h, slice_dir);
|
return ff_draw_slice(outlink, y, h, slice_dir);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user