aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Robertson <steven@strobe.cc>2012-07-06 22:41:28 -0700
committerStefano Sabatini <stefasab@gmail.com>2012-07-10 01:37:18 +0200
commitac726a4f0cd2fb8619b478af51312a4282215f0e (patch)
treec26a3bdd63d7ad1012b1dc00d2f4e7257dc9cda2
parenta5382b50f23a2d840298216211126c397122b4ea (diff)
downloadffmpeg-ac726a4f0cd2fb8619b478af51312a4282215f0e.tar.gz
lavfi/movie: flush decoder frames on EOF
movie currently forwards EOF (or begins looping) immediately upon reaching the last packet in the input stream, which can leave frames in the decoder. This change first tries to read any remaining packets from the decoder before forwarding EOF. Signed-off-by: Steven Robertson <steven@strobe.cc> Signed-off-by: Stefano Sabatini <stefasab@gmail.com>
-rw-r--r--libavfilter/src_movie.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c
index b0c9b086da..95ea2fc6bf 100644
--- a/libavfilter/src_movie.c
+++ b/libavfilter/src_movie.c
@@ -42,6 +42,12 @@
#include "internal.h"
#include "video.h"
+typedef enum {
+ STATE_DECODING,
+ STATE_FLUSHING,
+ STATE_DONE,
+} MovieState;
+
typedef struct {
/* common A/V fields */
const AVClass *class;
@@ -54,7 +60,7 @@ typedef struct {
AVFormatContext *format_ctx;
AVCodecContext *codec_ctx;
- int is_done;
+ MovieState state;
AVFrame *frame; ///< video frame to store the decoded images in
/* video-only fields */
@@ -236,13 +242,14 @@ static int movie_get_frame(AVFilterLink *outlink)
{
MovieContext *movie = outlink->src->priv;
AVPacket pkt;
- int ret, frame_decoded;
+ int ret = 0, frame_decoded;
AVStream *st = movie->format_ctx->streams[movie->stream_index];
- if (movie->is_done == 1)
+ if (movie->state == STATE_DONE)
return 0;
while (1) {
+ if (movie->state == STATE_DECODING) {
ret = av_read_frame(movie->format_ctx, &pkt);
if (ret == AVERROR_EOF) {
int64_t timestamp;
@@ -251,20 +258,19 @@ static int movie_get_frame(AVFilterLink *outlink)
if (movie->format_ctx->start_time != AV_NOPTS_VALUE)
timestamp += movie->format_ctx->start_time;
if (av_seek_frame(movie->format_ctx, -1, timestamp, AVSEEK_FLAG_BACKWARD) < 0) {
- movie->is_done = 1;
- break;
+ movie->state = STATE_FLUSHING;
} else if (movie->loop_count>1)
movie->loop_count--;
continue;
} else {
- movie->is_done = 1;
- break;
+ movie->state = STATE_FLUSHING;
}
} else if (ret < 0)
break;
+ }
// Is this a packet from the video stream?
- if (pkt.stream_index == movie->stream_index) {
+ if (pkt.stream_index == movie->stream_index || movie->state == STATE_FLUSHING) {
avcodec_decode_video2(movie->codec_ctx, movie->frame, &frame_decoded, &pkt);
if (frame_decoded) {
@@ -295,6 +301,10 @@ static int movie_get_frame(AVFilterLink *outlink)
av_free_packet(&pkt);
return 0;
+ } else if (movie->state == STATE_FLUSHING) {
+ movie->state = STATE_DONE;
+ av_free_packet(&pkt);
+ return AVERROR_EOF;
}
}
// Free the packet that was allocated by av_read_frame
@@ -310,7 +320,7 @@ static int movie_request_frame(AVFilterLink *outlink)
MovieContext *movie = outlink->src->priv;
int ret;
- if (movie->is_done)
+ if (movie->state == STATE_DONE)
return AVERROR_EOF;
if ((ret = movie_get_frame(outlink)) < 0)
return ret;
@@ -391,7 +401,7 @@ static int amovie_get_samples(AVFilterLink *outlink)
AVPacket pkt;
int ret, got_frame = 0;
- if (!movie->pkt.size && movie->is_done == 1)
+ if (!movie->pkt.size && movie->state == STATE_DONE)
return AVERROR_EOF;
/* check for another frame, in case the previous one was completely consumed */
@@ -408,7 +418,7 @@ static int amovie_get_samples(AVFilterLink *outlink)
}
if (ret == AVERROR_EOF) {
- movie->is_done = 1;
+ movie->state = STATE_DONE;
return ret;
}
}
@@ -451,7 +461,7 @@ static int amovie_request_frame(AVFilterLink *outlink)
MovieContext *movie = outlink->src->priv;
int ret;
- if (movie->is_done)
+ if (movie->state == STATE_DONE)
return AVERROR_EOF;
do {
if ((ret = amovie_get_samples(outlink)) < 0)