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_request_frame(AVFilterLink *link) { FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1); if (link->srcpad->request_frame) return link->srcpad->request_frame(link); else if (link->src->inputs[0]) return ff_request_frame(link->src->inputs[0]); else return -1; }
int ff_filter_samples_framed(AVFilterLink *link, AVFilterBufferRef *samplesref) { int (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); AVFilterPad *src = link->srcpad; AVFilterPad *dst = link->dstpad; int64_t pts; AVFilterBufferRef *buf_out; int ret; FF_TPRINTF_START(NULL, filter_samples); ff_tlog_link(NULL, link, 1); if (link->closed) { avfilter_unref_buffer(samplesref); return AVERROR_EOF; } if (!(filter_samples = dst->filter_samples)) filter_samples = default_filter_samples; av_assert1((samplesref->perms & src->min_perms) == src->min_perms); samplesref->perms &= ~ src->rej_perms; /* 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; link->cur_buf = buf_out; pts = buf_out->pts; ret = filter_samples(link, buf_out); ff_update_link_current_pts(link, pts); return ret; }
int ff_filter_frame(AVFilterLink *link, AVFrame *frame) { int ret; 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; } } link->frame_blocked_in = link->frame_wanted_out = 0; link->frame_count_in++; filter_unblock(link->dst); ret = ff_framequeue_add(&link->fifo, frame); if (ret < 0) { av_frame_free(&frame); return ret; } ff_filter_set_ready(link->dst, 300); return 0; error: av_frame_free(&frame); return AVERROR_PATCHWELCOME; }
AVFrame *ff_get_video_buffer(AVFilterLink *link, int w, int h) { AVFrame *ret = NULL; FF_TPRINTF_START(NULL, get_video_buffer); ff_tlog_link(NULL, link, 0); if (link->dstpad->get_video_buffer) ret = link->dstpad->get_video_buffer(link, w, h); if (!ret) ret = ff_default_get_video_buffer(link, w, h); 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; }
void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) { void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); AVFilterPad *dst = link->dstpad; int64_t pts; FF_TPRINTF_START(NULL, filter_samples); ff_tlog_link(NULL, link, 1); if (!(filter_samples = dst->filter_samples)) filter_samples = ff_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) { int i, size, planar = av_sample_fmt_is_planar(samplesref->format); int planes = !planar ? 1: av_get_channel_layout_nb_channels(samplesref->audio->channel_layout); 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); link->cur_buf = ff_default_get_audio_buffer(link, dst->min_perms, samplesref->audio->nb_samples); link->cur_buf->pts = samplesref->pts; link->cur_buf->audio->sample_rate = samplesref->audio->sample_rate; /* Copy actual data into new samples buffer */ /* src can be larger than dst if it was allocated larger than necessary. dst can be slightly larger due to extra alignment padding. */ size = FFMIN(samplesref->linesize[0], link->cur_buf->linesize[0]); for (i = 0; samplesref->data[i] && i < 8; i++) memcpy(link->cur_buf->data[i], samplesref->data[i], size); for (i = 0; i < planes; i++) memcpy(link->cur_buf->extended_data[i], samplesref->extended_data[i], size); avfilter_unref_buffer(samplesref); } else link->cur_buf = samplesref; pts = link->cur_buf->pts; filter_samples(link, link->cur_buf); ff_update_link_current_pts(link, pts); }
int ff_request_frame_to_filter(AVFilterLink *link) { int ret = -1; FF_TPRINTF_START(NULL, request_frame_to_filter); ff_tlog_link(NULL, link, 1); /* Assume the filter is blocked, let the method clear it if not */ link->frame_blocked_in = 1; 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 < 0) { if (ret != AVERROR(EAGAIN) && ret != link->status_in) ff_avfilter_link_set_in_status(link, ret, AV_NOPTS_VALUE); if (ret == AVERROR_EOF) ret = 0; } return ret; }
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); } }
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) { AVFilterBufferRef *pbuf = link->partial_buf; link->partial_buf = NULL; ff_filter_samples_framed(link, pbuf); return 0; } if (ret == AVERROR_EOF) link->closed = 1; return ret; }
int ff_request_frame(AVFilterLink *link) { FF_TPRINTF_START(NULL, request_frame); ff_tlog_link(NULL, link, 1); if (link->status_out) return link->status_out; if (link->status_in) { if (ff_framequeue_queued_frames(&link->fifo)) { av_assert1(!link->frame_wanted_out); av_assert1(link->dst->ready >= 300); return 0; } else { /* Acknowledge status change. Filters using ff_request_frame() will handle the change automatically. Filters can also check the status directly but none do yet. */ ff_avfilter_link_set_out_status(link, link->status_in, link->status_in_pts); return link->status_out; } } link->frame_wanted_out = 1; ff_filter_set_ready(link->src, 100); return 0; }