With this we can mix filters using filter_frame OR start/draw_slice/end Signed-off-by: Michael Niedermayer <michaelni@gmx.at>tags/n1.1
| @@ -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, | |||||
| AVFilterBufferRef *samplesref); | |||||
| int ff_filter_samples_framed(AVFilterLink *link, | |||||
| 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; | ||||
| } | } | ||||