ffplay: ensure the decoder is flushed before exiting or looping

Also make sure that we only exit or restart the video if it is not paused and
if the picture queue is empty.

There is still room for improvement (filters may also buffer some frames), but
the patch fixes the most common use cases and ticket #2783 as well.

Signed-off-by: Marton Balint <cus@passwd.hu>
This commit is contained in:
Marton Balint 2013-07-16 03:04:22 +02:00
parent 608989f6bf
commit e84ca8d38a
1 changed files with 17 additions and 8 deletions

View File

@ -177,6 +177,8 @@ typedef struct VideoState {
int read_pause_return; int read_pause_return;
AVFormatContext *ic; AVFormatContext *ic;
int realtime; int realtime;
int audio_finished;
int video_finished;
Clock audclk; Clock audclk;
Clock vidclk; Clock vidclk;
@ -1673,6 +1675,9 @@ static int get_video_frame(VideoState *is, AVFrame *frame, AVPacket *pkt, int *s
if(avcodec_decode_video2(is->video_st->codec, frame, &got_picture, pkt) < 0) if(avcodec_decode_video2(is->video_st->codec, frame, &got_picture, pkt) < 0)
return 0; return 0;
if (!got_picture && !pkt->data)
is->video_finished = *serial;
if (got_picture) { if (got_picture) {
int ret = 1; int ret = 1;
double dpts = NAN; double dpts = NAN;
@ -2170,6 +2175,8 @@ static int audio_decode_frame(VideoState *is)
pkt_temp->size -= len1; pkt_temp->size -= len1;
if (pkt_temp->data && pkt_temp->size <= 0 || !pkt_temp->data && !got_frame) if (pkt_temp->data && pkt_temp->size <= 0 || !pkt_temp->data && !got_frame)
pkt_temp->stream_index = -1; pkt_temp->stream_index = -1;
if (!pkt_temp->data && !got_frame)
is->audio_finished = is->audio_pkt_temp_serial;
if (!got_frame) if (!got_frame)
continue; continue;
@ -2899,6 +2906,16 @@ static int read_thread(void *arg)
SDL_UnlockMutex(wait_mutex); SDL_UnlockMutex(wait_mutex);
continue; continue;
} }
if (!is->paused &&
(!is->audio_st || is->audio_finished == is->audioq.serial) &&
(!is->video_st || (is->video_finished == is->videoq.serial && is->pictq_size == 0))) {
if (loop != 1 && (!loop || --loop)) {
stream_seek(is, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
} else if (autoexit) {
ret = AVERROR_EOF;
goto fail;
}
}
if (eof) { if (eof) {
if (is->video_stream >= 0) { if (is->video_stream >= 0) {
av_init_packet(pkt); av_init_packet(pkt);
@ -2915,14 +2932,6 @@ static int read_thread(void *arg)
packet_queue_put(&is->audioq, pkt); packet_queue_put(&is->audioq, pkt);
} }
SDL_Delay(10); SDL_Delay(10);
if (is->audioq.size + is->videoq.size + is->subtitleq.size == 0) {
if (loop != 1 && (!loop || --loop)) {
stream_seek(is, start_time != AV_NOPTS_VALUE ? start_time : 0, 0, 0);
} else if (autoexit) {
ret = AVERROR_EOF;
goto fail;
}
}
eof=0; eof=0;
continue; continue;
} }