Also deprecate adding a NULL frame to mark EOF. TODO APIchanges entry, version bump.
Signed-off-by: Nicolas George <geo...@nsup.org> --- libavfilter/buffersrc.c | 40 ++++++++++++++++++++++++++++++---------- libavfilter/buffersrc.h | 15 +++++++++++++++ 2 files changed, 45 insertions(+), 10 deletions(-) Note: relying on the frame duration for the end timestamp would be fragile (no filters update it), and technically an API break. diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c index 27d3db0..6d71587 100644 --- a/libavfilter/buffersrc.c +++ b/libavfilter/buffersrc.c @@ -63,6 +63,7 @@ typedef struct BufferSourceContext { char *channel_layout_str; int eof; + int64_t eof_pts; } BufferSourceContext; #define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format)\ @@ -77,6 +78,27 @@ typedef struct BufferSourceContext { return AVERROR(EINVAL);\ } +static int push_if_flag(AVFilterContext *ctx, int flags) +{ + return (flags & AV_BUFFERSRC_FLAG_PUSH) ? + ctx->output_pads[0].request_frame(ctx->outputs[0]) : 0; +} + +int av_buffersrc_close(AVFilterContext *ctx, int64_t pts, int flags) +{ + BufferSourceContext *s = ctx->priv; + + if (pts == AV_NOPTS_VALUE) { + av_log(ctx, AV_LOG_WARNING, "No EOF timestamp\n"); + /* FIXME use duration for audio */ + pts = av_rescale_q(ctx->outputs[0]->current_pts, + AV_TIME_BASE_Q, ctx->outputs[0]->time_base) + 1; + } + s->eof_pts = pts; + s->eof = 1; + return push_if_flag(ctx, flags); +} + int attribute_align_arg av_buffersrc_write_frame(AVFilterContext *ctx, const AVFrame *frame) { return av_buffersrc_add_frame_flags(ctx, (AVFrame *)frame, @@ -125,8 +147,7 @@ static int av_buffersrc_add_frame_internal(AVFilterContext *ctx, s->nb_failed_requests = 0; if (!frame) { - s->eof = 1; - return 0; + return av_buffersrc_close(ctx, AV_NOPTS_VALUE, flags); } else if (s->eof) return AVERROR(EINVAL); @@ -177,11 +198,7 @@ static int av_buffersrc_add_frame_internal(AVFilterContext *ctx, return ret; } - if ((flags & AV_BUFFERSRC_FLAG_PUSH)) - if ((ret = ctx->output_pads[0].request_frame(ctx->outputs[0])) < 0) - return ret; - - return 0; + return push_if_flag(ctx, flags); } #if FF_API_AVFILTERBUFFER @@ -211,8 +228,7 @@ int av_buffersrc_add_ref(AVFilterContext *ctx, AVFilterBufferRef *buf, int ret = 0, planes, i; if (!buf) { - s->eof = 1; - return 0; + return av_buffersrc_close(ctx, AV_NOPTS_VALUE, flags); } else if (s->eof) return AVERROR(EINVAL); @@ -487,10 +503,14 @@ static int request_frame(AVFilterLink *link) { BufferSourceContext *c = link->src->priv; AVFrame *frame; + int ret; if (!av_fifo_size(c->fifo)) { - if (c->eof) + if (c->eof) { + if ((ret = ff_filter_link_close(link, c->eof_pts)) < 0) + return ret; return AVERROR_EOF; + } c->nb_failed_requests++; return AVERROR(EAGAIN); } diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h index ea34c04..28ca545 100644 --- a/libavfilter/buffersrc.h +++ b/libavfilter/buffersrc.h @@ -145,6 +145,8 @@ int av_buffersrc_add_frame(AVFilterContext *ctx, AVFrame *frame); * * @param buffer_src pointer to a buffer source context * @param frame a frame, or NULL to mark EOF + * (Using NULL to mark EOF is deprecated, use + * av_buffersrc_close() instead.) * @param flags a combination of AV_BUFFERSRC_FLAG_* * @return >= 0 in case of success, a negative AVERROR code * in case of failure @@ -154,6 +156,19 @@ int av_buffersrc_add_frame_flags(AVFilterContext *buffer_src, /** + * Close a buffer source. + * + * This cause EOF to be propagated along the filter graph. + * + * @param buffer_src pointer to a buffer source context + * @param pts the timestamp of the end of stream + * @param flags a combination of AV_BUFFERSRC_FLAG_* + * @return >= 0 in case of success, a negative AVERROR code + * in case of failure + */ +int av_buffersrc_close(AVFilterContext *buffer_src, int64_t pts, int flags); + +/** * @} */ -- 2.0.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel