lavfi: replace link.closed by link.status.

The status field can carry any error code instead of just EOF.
Also only update it through a wrapper function and provide a timestamp.
Update the few filters that used it directly.
This commit is contained in:
Nicolas George 2015-09-24 10:07:42 +02:00
parent 39a09e995d
commit 108b4de552
8 changed files with 49 additions and 21 deletions

View File

@ -178,9 +178,20 @@ int avfilter_link_get_channels(AVFilterLink *link)
return link->channels;
}
void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts)
{
ff_avfilter_link_set_out_status(link, status, pts);
}
void ff_avfilter_link_set_out_status(AVFilterLink *link, int status, int64_t pts)
{
link->status = status;
ff_update_link_current_pts(link, pts);
}
void avfilter_link_set_closed(AVFilterLink *link, int closed)
{
link->closed = closed;
ff_avfilter_link_set_out_status(link, closed ? AVERROR_EOF : 0, AV_NOPTS_VALUE);
}
int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,
@ -346,8 +357,8 @@ 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->status)
return link->status;
if (link->srcpad->request_frame)
ret = link->srcpad->request_frame(link);
else if (link->src->inputs[0])
@ -358,8 +369,8 @@ int ff_request_frame(AVFilterLink *link)
ret = ff_filter_frame_framed(link, pbuf);
}
if (ret < 0) {
if (ret == AVERROR_EOF)
link->closed = 1;
if (ret != AVERROR(EAGAIN) && ret != link->status)
ff_avfilter_link_set_in_status(link, ret, AV_NOPTS_VALUE);
}
return ret;
}
@ -1005,9 +1016,9 @@ static int ff_filter_frame_framed(AVFilterLink *link, AVFrame *frame)
AVFilterCommand *cmd= link->dst->command_queue;
int64_t pts;
if (link->closed) {
if (link->status) {
av_frame_free(&frame);
return AVERROR_EOF;
return link->status;
}
if (!(filter_frame = dst->filter_frame))

View File

@ -490,16 +490,16 @@ struct AVFilterLink {
int max_samples;
/**
* True if the link is closed.
* If set, all attempts of start_frame, filter_frame or request_frame
* will fail with AVERROR_EOF, and if necessary the reference will be
* destroyed.
* If request_frame returns AVERROR_EOF, this flag is set on the
* Link status.
* If not zero, all attempts of start_frame, filter_frame or request_frame
* will fail with the corresponding code, and if necessary the reference
* will be destroyed.
* If request_frame returns an error, the status is set on the
* corresponding link.
* It can be set also be set by either the source or the destination
* filter.
*/
int closed;
int status;
/**
* Number of channels.

View File

@ -134,8 +134,8 @@ int attribute_align_arg av_buffersink_get_frame_flags(AVFilterContext *ctx, AVFr
/* no picref available, fetch it from the filterchain */
while (!av_fifo_size(buf->fifo)) {
if (inlink->closed)
return AVERROR_EOF;
if (inlink->status)
return inlink->status;
if (flags & AV_BUFFERSINK_FLAG_NO_REQUEST)
return AVERROR(EAGAIN);
if ((ret = ff_request_frame(inlink)) < 0)

View File

@ -59,7 +59,7 @@ inline static int push_frame(AVFilterContext *ctx)
for (i = 0; i < ctx->nb_inputs; i++) {
struct FFBufQueue *q = &s->queues[i];
if (!q->available && !ctx->inputs[i]->closed)
if (!q->available && !ctx->inputs[i]->status)
return 0;
if (q->available) {
frame = ff_bufqueue_peek(q, 0);
@ -190,7 +190,7 @@ static int request_frame(AVFilterLink *outlink)
int i, ret;
for (i = 0; i < ctx->nb_inputs; i++) {
if (!s->queues[i].available && !ctx->inputs[i]->closed) {
if (!s->queues[i].available && !ctx->inputs[i]->status) {
ret = ff_request_frame(ctx->inputs[i]);
if (ret != AVERROR_EOF)
return ret;

View File

@ -226,6 +226,21 @@ int ff_parse_channel_layout(int64_t *ret, int *nret, const char *arg,
void ff_update_link_current_pts(AVFilterLink *link, int64_t pts);
/**
* Set the status field of a link from the source filter.
* The pts should reflect the timestamp of the status change,
* in link time base and relative to the frames timeline.
* In particular, for AVERROR_EOF, it should reflect the
* end time of the last frame.
*/
void ff_avfilter_link_set_in_status(AVFilterLink *link, int status, int64_t pts);
/**
* Set the status field of a link from the destination filter.
* The pts should probably be left unset (AV_NOPTS_VALUE).
*/
void ff_avfilter_link_set_out_status(AVFilterLink *link, int status, int64_t pts);
void ff_command_queue_pop(AVFilterContext *filter);
/* misc trace functions */

View File

@ -77,7 +77,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
for (i = 0; i < ctx->nb_outputs; i++) {
AVFrame *buf_out;
if (ctx->outputs[i]->closed)
if (ctx->outputs[i]->status)
continue;
buf_out = av_frame_clone(frame);
if (!buf_out) {

View File

@ -174,7 +174,8 @@ static int trim_filter_frame(AVFilterLink *inlink, AVFrame *frame)
drop = 0;
if (drop) {
s->eof = inlink->closed = 1;
s->eof = 1;
ff_avfilter_link_set_out_status(inlink, AVERROR_EOF, AV_NOPTS_VALUE);
goto drop;
}
}
@ -305,7 +306,8 @@ static int atrim_filter_frame(AVFilterLink *inlink, AVFrame *frame)
}
if (drop) {
s->eof = inlink->closed = 1;
s->eof = 1;
ff_avfilter_link_set_out_status(inlink, AVERROR_EOF, AV_NOPTS_VALUE);
goto drop;
}
}

View File

@ -219,7 +219,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
const int idx = s->map[i];
AVFrame *out;
if (outlink->closed)
if (outlink->status)
continue;
out = ff_get_video_buffer(outlink, outlink->w, outlink->h);