diff --git a/ffplay.c b/ffplay.c index d9f751ca5a..ca4f3c2c93 100644 --- a/ffplay.c +++ b/ffplay.c @@ -87,11 +87,18 @@ const int program_birth_year = 2003; static int sws_flags = SWS_BICUBIC; +typedef struct MyAVPacketList { + AVPacket pkt; + struct MyAVPacketList *next; + int serial; +} MyAVPacketList; + typedef struct PacketQueue { - AVPacketList *first_pkt, *last_pkt; + MyAVPacketList *first_pkt, *last_pkt; int nb_packets; int size; int abort_request; + int serial; SDL_mutex *mutex; SDL_cond *cond; } PacketQueue; @@ -108,6 +115,7 @@ typedef struct VideoPicture { AVRational sample_aspect_ratio; int allocated; int reallocate; + int serial; #if CONFIG_AVFILTER AVFilterBufferRef *picref; @@ -174,6 +182,7 @@ typedef struct VideoState { int audio_write_buf_size; AVPacket audio_pkt_temp; AVPacket audio_pkt; + int audio_pkt_temp_serial; struct AudioParams audio_src; struct AudioParams audio_tgt; struct SwrContext *swr_ctx; @@ -305,16 +314,19 @@ static int packet_queue_put(PacketQueue *q, AVPacket *pkt); static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt) { - AVPacketList *pkt1; + MyAVPacketList *pkt1; if (q->abort_request) return -1; - pkt1 = av_malloc(sizeof(AVPacketList)); + pkt1 = av_malloc(sizeof(MyAVPacketList)); if (!pkt1) return -1; pkt1->pkt = *pkt; pkt1->next = NULL; + if (pkt == &flush_pkt) + q->serial++; + pkt1->serial = q->serial; if (!q->last_pkt) q->first_pkt = pkt1; @@ -357,7 +369,7 @@ static void packet_queue_init(PacketQueue *q) static void packet_queue_flush(PacketQueue *q) { - AVPacketList *pkt, *pkt1; + MyAVPacketList *pkt, *pkt1; SDL_LockMutex(q->mutex); for (pkt = q->first_pkt; pkt != NULL; pkt = pkt1) { @@ -399,9 +411,9 @@ static void packet_queue_start(PacketQueue *q) } /* return < 0 if aborted, 0 if no packet and > 0 if packet. */ -static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) +static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial) { - AVPacketList *pkt1; + MyAVPacketList *pkt1; int ret; SDL_LockMutex(q->mutex); @@ -420,6 +432,8 @@ static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block) q->nb_packets--; q->size -= pkt1->pkt.size + sizeof(*pkt1); *pkt = pkt1->pkt; + if (serial) + *serial = pkt1->serial; av_free(pkt1); ret = 1; break; @@ -1169,7 +1183,7 @@ static void pictq_prev_picture(VideoState *is) { } } -static void update_video_pts(VideoState *is, double pts, int64_t pos) { +static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial) { double time = av_gettime() / 1000000.0; /* update current video pts */ is->video_current_pts = pts; @@ -1195,7 +1209,7 @@ retry: if (is->pictq_size == 0) { SDL_LockMutex(is->pictq_mutex); if (is->frame_last_dropped_pts != AV_NOPTS_VALUE && is->frame_last_dropped_pts > is->frame_last_pts) { - update_video_pts(is, is->frame_last_dropped_pts, is->frame_last_dropped_pos); + update_video_pts(is, is->frame_last_dropped_pts, is->frame_last_dropped_pos, 0); is->frame_last_dropped_pts = AV_NOPTS_VALUE; } SDL_UnlockMutex(is->pictq_mutex); @@ -1229,7 +1243,7 @@ retry: is->frame_timer += delay * FFMAX(1, floor((time-is->frame_timer) / delay)); SDL_LockMutex(is->pictq_mutex); - update_video_pts(is, vp->pts, vp->pos); + update_video_pts(is, vp->pts, vp->pos, vp->serial); SDL_UnlockMutex(is->pictq_mutex); if (is->pictq_size > 1) { @@ -1374,7 +1388,7 @@ static void alloc_picture(VideoState *is) SDL_UnlockMutex(is->pictq_mutex); } -static int queue_picture(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos) +static int queue_picture(VideoState *is, AVFrame *src_frame, double pts1, int64_t pos, int serial) { VideoPicture *vp; double frame_delay, pts = pts1; @@ -1495,6 +1509,7 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts1, int64_ vp->pts = pts; vp->pos = pos; vp->skip = 0; + vp->serial = serial; /* now we can update the picture count */ if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE) @@ -1506,11 +1521,11 @@ static int queue_picture(VideoState *is, AVFrame *src_frame, double pts1, int64_ return 0; } -static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt) +static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacket *pkt, int *serial) { int got_picture, i; - if (packet_queue_get(&is->videoq, pkt, 1) < 0) + if (packet_queue_get(&is->videoq, pkt, 1, serial) < 0) return -1; if (pkt->data == flush_pkt.data) { @@ -1682,6 +1697,7 @@ static int video_thread(void *arg) int64_t pts_int = AV_NOPTS_VALUE, pos = -1; double pts; int ret; + int serial = 0; #if CONFIG_AVFILTER AVCodecContext *codec = is->video_st->codec; @@ -1710,7 +1726,7 @@ static int video_thread(void *arg) avcodec_get_frame_defaults(frame); av_free_packet(&pkt); - ret = get_video_frame(is, frame, &pts_int, &pkt); + ret = get_video_frame(is, frame, &pts_int, &pkt, &serial); if (ret < 0) goto the_end; @@ -1791,11 +1807,11 @@ static int video_thread(void *arg) is->video_st->time_base.num, is->video_st->time_base.den, pts_int); } pts = pts_int * av_q2d(is->video_st->time_base); - ret = queue_picture(is, frame, pts, pos); + ret = queue_picture(is, frame, pts, pos, serial); } #else pts = pts_int * av_q2d(is->video_st->time_base); - ret = queue_picture(is, frame, pts, pkt.pos); + ret = queue_picture(is, frame, pts, pkt.pos, serial); #endif if (ret < 0) @@ -1828,7 +1844,7 @@ static int subtitle_thread(void *arg) while (is->paused && !is->subtitleq.abort_request) { SDL_Delay(10); } - if (packet_queue_get(&is->subtitleq, pkt, 1) < 0) + if (packet_queue_get(&is->subtitleq, pkt, 1, NULL) < 0) break; if (pkt->data == flush_pkt.data) { @@ -2079,7 +2095,7 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) SDL_CondSignal(is->continue_read_thread); /* read next packet */ - if ((new_packet = packet_queue_get(&is->audioq, pkt, 1)) < 0) + if ((new_packet = packet_queue_get(&is->audioq, pkt, 1, &is->audio_pkt_temp_serial)) < 0) return -1; if (pkt->data == flush_pkt.data) {