summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ffplay.c54
1 files changed, 45 insertions, 9 deletions
diff --git a/ffplay.c b/ffplay.c
index c998b5d446..81ded546c8 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -197,6 +197,8 @@ typedef struct VideoState {
double frame_timer;
double frame_last_pts;
double frame_last_duration;
+ double frame_last_dropped_pts;
+ int64_t frame_last_dropped_pos;
double video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame
int video_stream;
AVStream *video_st;
@@ -1102,20 +1104,35 @@ static void pictq_next_picture(VideoState *is) {
SDL_UnlockMutex(is->pictq_mutex);
}
+static void update_video_pts(VideoState *is, double pts, int64_t pos) {
+ double time = av_gettime() / 1000000.0;
+ /* update current video pts */
+ is->video_current_pts = pts;
+ is->video_current_pts_drift = is->video_current_pts - time;
+ is->video_current_pos = pos;
+ is->frame_last_pts = pts;
+}
+
/* called to display each frame */
static void video_refresh(void *opaque)
{
VideoState *is = opaque;
VideoPicture *vp;
+ double time;
SubPicture *sp, *sp2;
if (is->video_st) {
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);
+ is->frame_last_dropped_pts = AV_NOPTS_VALUE;
+ }
+ SDL_UnlockMutex(is->pictq_mutex);
//nothing to do, no picture to display in the que
} else {
- double time= av_gettime()/1000000.0;
double last_duration, duration, delay;
/* dequeue the picture */
vp = &is->pictq[is->pictq_rindex];
@@ -1133,17 +1150,16 @@ retry:
}
delay = compute_target_delay(is->frame_last_duration, is);
+ time= av_gettime()/1000000.0;
if(time < is->frame_timer + delay)
return;
- is->frame_last_pts = vp->pts;
if (delay > 0)
is->frame_timer += delay * FFMAX(1, floor((time-is->frame_timer) / delay));
- /* update current video pts */
- is->video_current_pts = vp->pts;
- is->video_current_pts_drift = is->video_current_pts - time;
- is->video_current_pos = vp->pos;
+ SDL_LockMutex(is->pictq_mutex);
+ update_video_pts(is, vp->pts, vp->pos);
+ SDL_UnlockMutex(is->pictq_mutex);
if(is->pictq_size > 1) {
VideoPicture *nextvp= &is->pictq[(is->pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE];
@@ -1448,17 +1464,20 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke
SDL_CondWait(is->pictq_cond, is->pictq_mutex);
}
is->video_current_pos = -1;
- SDL_UnlockMutex(is->pictq_mutex);
-
is->frame_last_pts = AV_NOPTS_VALUE;
is->frame_last_duration = 0;
is->frame_timer = (double)av_gettime() / 1000000.0;
+ is->frame_last_dropped_pts = AV_NOPTS_VALUE;
+ SDL_UnlockMutex(is->pictq_mutex);
+
return 0;
}
avcodec_decode_video2(is->video_st->codec, frame, &got_picture, pkt);
if (got_picture) {
+ int ret = 1;
+
if (decoder_reorder_pts == -1) {
*pts = frame->best_effort_timestamp;
} else if (decoder_reorder_pts) {
@@ -1471,8 +1490,25 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke
*pts = 0;
}
- return 1;
+ if (((is->av_sync_type == AV_SYNC_AUDIO_MASTER && is->audio_st) || is->av_sync_type == AV_SYNC_EXTERNAL_CLOCK) &&
+ (framedrop>0 || (framedrop && is->audio_st))) {
+ SDL_LockMutex(is->pictq_mutex);
+ if (is->frame_last_pts != AV_NOPTS_VALUE && *pts) {
+ double clockdiff = get_video_clock(is) - get_master_clock(is);
+ double dpts = av_q2d(is->video_st->time_base) * *pts;
+ double ptsdiff = dpts - is->frame_last_pts;
+ if (fabs(clockdiff) < AV_NOSYNC_THRESHOLD &&
+ ptsdiff > 0 && ptsdiff < AV_NOSYNC_THRESHOLD &&
+ clockdiff + ptsdiff < 0) { //TODO: Substract approxiamte time of filter
+ is->frame_last_dropped_pos = pkt->pos;
+ is->frame_last_dropped_pts = dpts;
+ ret = 0;
+ }
+ }
+ SDL_UnlockMutex(is->pictq_mutex);
+ }
+ return ret;
}
return 0;
}