int ff_request_frame(AVFilterLink *link) { int ret = -1; FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1); if (link->closed) return AVERROR_EOF; av_assert0(!link->frame_requested); link->frame_requested = 1; while (link->frame_requested) { if (link->srcpad->request_frame) ret = link->srcpad->request_frame(link); else if (link->src->inputs[0]) ret = ff_request_frame(link->src->inputs[0]); if (ret == AVERROR_EOF && link->partial_buf) { AVFrame *pbuf = link->partial_buf; link->partial_buf = NULL; ret = ff_filter_frame_framed(link, pbuf); } if (ret < 0) { link->frame_requested = 0; if (ret == AVERROR_EOF) link->closed = 1; } else { av_assert0(!link->frame_requested || link->flags & FF_LINK_FLAG_REQUEST_LOOP); } } return ret; }
int ff_filter_frame(AVFilterLink *link, AVFrame *frame) { FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); ff_tlog_ref(NULL, frame, 1); /* Consistency checks */ if (link->type == AVMEDIA_TYPE_VIDEO) { if (strcmp(link->dst->filter->name, "scale") && strcmp(link->dst->filter->name, "idet")) { av_assert1(frame->format == link->format); av_assert1(frame->width == link->w); av_assert1(frame->height == link->h); } } else { av_assert1(frame->format == link->format); av_assert1(av_frame_get_channels(frame) == link->channels); av_assert1(frame->channel_layout == link->channel_layout); av_assert1(frame->sample_rate == link->sample_rate); } /* Go directly to actual filtering if possible */ if (link->type == AVMEDIA_TYPE_AUDIO && link->min_samples && (link->partial_buf || frame->nb_samples < link->min_samples || frame->nb_samples > link->max_samples)) { return ff_filter_frame_needs_framing(link, frame); } else { return ff_filter_frame_framed(link, frame); } }
int ff_filter_frame_to_filter(AVFilterLink *link) { AVFrame *frame; AVFilterContext *dst = link->dst; int ret; av_assert1(ff_framequeue_queued_frames(&link->fifo)); if (link->min_samples) { int min = link->min_samples; if (link->status_in) min = FFMIN(min, ff_framequeue_queued_samples(&link->fifo)); ret = take_samples(link, min, link->max_samples, &frame); if (ret < 0) return ret; } else { frame = ff_framequeue_take(&link->fifo); } /* The filter will soon have received a new frame, that may allow it to produce one or more: unblock its outputs. */ filter_unblock(dst); ret = ff_filter_frame_framed(link, frame); if (ret < 0 && ret != link->status_out) { ff_avfilter_link_set_out_status(link, ret, AV_NOPTS_VALUE); } else { /* Run once again, to see if several frames were available, or if the input status has also changed, or any other reason. */ ff_filter_set_ready(dst, 300); } return ret; }
int ff_filter_frame(AVFilterLink *link, AVFrame *frame) { FF_TPRINTF_START(NULL, filter_frame); ff_tlog_link(NULL, link, 1); ff_tlog(NULL, " "); ff_tlog_ref(NULL, frame, 1); /* Consistency checks */ if (link->type == AVMEDIA_TYPE_VIDEO) { if (strcmp(link->dst->filter->name, "buffersink") && strcmp(link->dst->filter->name, "format") && strcmp(link->dst->filter->name, "idet") && strcmp(link->dst->filter->name, "null") && strcmp(link->dst->filter->name, "scale")) { av_assert1(frame->format == link->format); av_assert1(frame->width == link->w); av_assert1(frame->height == link->h); } } else { if (frame->format != link->format) { av_log(link->dst, AV_LOG_ERROR, "Format change is not supported\n"); goto error; } if (av_frame_get_channels(frame) != link->channels) { av_log(link->dst, AV_LOG_ERROR, "Channel count change is not supported\n"); goto error; } if (frame->channel_layout != link->channel_layout) { av_log(link->dst, AV_LOG_ERROR, "Channel layout change is not supported\n"); goto error; } if (frame->sample_rate != link->sample_rate) { av_log(link->dst, AV_LOG_ERROR, "Sample rate change is not supported\n"); goto error; } } /* Go directly to actual filtering if possible */ if (link->type == AVMEDIA_TYPE_AUDIO && link->min_samples && (link->partial_buf || frame->nb_samples < link->min_samples || frame->nb_samples > link->max_samples)) { return ff_filter_frame_needs_framing(link, frame); } else { return ff_filter_frame_framed(link, frame); } error: av_frame_free(&frame); return AVERROR_PATCHWELCOME; }
static int ff_filter_frame_needs_framing(AVFilterLink *link, AVFrame *frame) { int insamples = frame->nb_samples, inpos = 0, nb_samples; AVFrame *pbuf = link->partial_buf; int nb_channels = av_frame_get_channels(frame); int ret = 0; link->flags |= FF_LINK_FLAG_REQUEST_LOOP; /* Handle framing (min_samples, max_samples) */ while (insamples) { if (!pbuf) { AVRational samples_tb = { 1, link->sample_rate }; pbuf = ff_get_audio_buffer(link, link->partial_buf_size); if (!pbuf) { av_log(link->dst, AV_LOG_WARNING, "Samples dropped due to memory allocation failure.\n"); return 0; } av_frame_copy_props(pbuf, frame); pbuf->pts = frame->pts; if (pbuf->pts != AV_NOPTS_VALUE) pbuf->pts += av_rescale_q(inpos, samples_tb, link->time_base); pbuf->nb_samples = 0; } nb_samples = FFMIN(insamples, link->partial_buf_size - pbuf->nb_samples); av_samples_copy(pbuf->extended_data, frame->extended_data, pbuf->nb_samples, inpos, nb_samples, nb_channels, link->format); inpos += nb_samples; insamples -= nb_samples; pbuf->nb_samples += nb_samples; if (pbuf->nb_samples >= link->min_samples) { ret = ff_filter_frame_framed(link, pbuf); pbuf = NULL; } } av_frame_free(&frame); link->partial_buf = pbuf; return ret; }
int ff_request_frame(AVFilterLink *link) { int ret = -1; FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1); if (link->closed) return AVERROR_EOF; if (link->srcpad->request_frame) ret = link->srcpad->request_frame(link); else if (link->src->inputs[0]) ret = ff_request_frame(link->src->inputs[0]); if (ret == AVERROR_EOF && link->partial_buf) { AVFrame *pbuf = link->partial_buf; link->partial_buf = NULL; ret = ff_filter_frame_framed(link, pbuf); } if (ret < 0) { if (ret == AVERROR_EOF) link->closed = 1; } return ret; }