Commit 26c208cf authored by Marton Balint's avatar Marton Balint

ffplay: if audio or video clock is invalid return NAN

This helps us not to make bad decision (frame dropping, audio compensation)
right after seeking when we do not know yet the recent audio or video clock.
Signed-off-by: 's avatarMarton Balint <cus@passwd.hu>
parent 38f64966
...@@ -176,6 +176,7 @@ typedef struct VideoState { ...@@ -176,6 +176,7 @@ typedef struct VideoState {
double external_clock_speed; ///< speed of the external clock double external_clock_speed; ///< speed of the external clock
double audio_clock; double audio_clock;
int audio_clock_serial;
double audio_diff_cum; /* used for AV difference average computation */ double audio_diff_cum; /* used for AV difference average computation */
double audio_diff_avg_coef; double audio_diff_avg_coef;
double audio_diff_threshold; double audio_diff_threshold;
...@@ -238,6 +239,7 @@ typedef struct VideoState { ...@@ -238,6 +239,7 @@ typedef struct VideoState {
double video_current_pts_drift; // video_current_pts - time (av_gettime) at which we updated video_current_pts - used to have running video pts double video_current_pts_drift; // video_current_pts - time (av_gettime) at which we updated video_current_pts - used to have running video pts
int64_t video_current_pos; // current displayed file pos int64_t video_current_pos; // current displayed file pos
double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity
int video_clock_serial;
VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE]; VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
int pictq_size, pictq_rindex, pictq_windex; int pictq_size, pictq_rindex, pictq_windex;
SDL_mutex *pictq_mutex; SDL_mutex *pictq_mutex;
...@@ -1079,6 +1081,8 @@ static void video_display(VideoState *is) ...@@ -1079,6 +1081,8 @@ static void video_display(VideoState *is)
/* get the current audio clock value */ /* get the current audio clock value */
static double get_audio_clock(VideoState *is) static double get_audio_clock(VideoState *is)
{ {
if (is->audio_clock_serial != is->audioq.serial)
return NAN;
if (is->paused) { if (is->paused) {
return is->audio_current_pts; return is->audio_current_pts;
} else { } else {
...@@ -1089,6 +1093,8 @@ static double get_audio_clock(VideoState *is) ...@@ -1089,6 +1093,8 @@ static double get_audio_clock(VideoState *is)
/* get the current video clock value */ /* get the current video clock value */
static double get_video_clock(VideoState *is) static double get_video_clock(VideoState *is)
{ {
if (is->video_clock_serial != is->videoq.serial)
return NAN;
if (is->paused) { if (is->paused) {
return is->video_current_pts; return is->video_current_pts;
} else { } else {
...@@ -1230,7 +1236,7 @@ static double compute_target_delay(double delay, VideoState *is) ...@@ -1230,7 +1236,7 @@ static double compute_target_delay(double delay, VideoState *is)
delay to compute the threshold. I still don't know delay to compute the threshold. I still don't know
if it is the best guess */ if it is the best guess */
sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay); sync_threshold = FFMAX(AV_SYNC_THRESHOLD, delay);
if (fabs(diff) < AV_NOSYNC_THRESHOLD) { if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) {
if (diff <= -sync_threshold) if (diff <= -sync_threshold)
delay = 0; delay = 0;
else if (diff >= sync_threshold) else if (diff >= sync_threshold)
...@@ -1281,6 +1287,7 @@ static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial ...@@ -1281,6 +1287,7 @@ static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial
is->video_current_pts_drift = is->video_current_pts - time; is->video_current_pts_drift = is->video_current_pts - time;
is->video_current_pos = pos; is->video_current_pos = pos;
is->frame_last_pts = pts; is->frame_last_pts = pts;
is->video_clock_serial = serial;
if (is->videoq.serial == serial) if (is->videoq.serial == serial)
check_external_clock_sync(is, is->video_current_pts); check_external_clock_sync(is, is->video_current_pts);
} }
...@@ -1677,7 +1684,7 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke ...@@ -1677,7 +1684,7 @@ static int get_video_frame(VideoState *is, AVFrame *frame, int64_t *pts, AVPacke
double clockdiff = get_video_clock(is) - get_master_clock(is); double clockdiff = get_video_clock(is) - get_master_clock(is);
double dpts = av_q2d(is->video_st->time_base) * *pts; double dpts = av_q2d(is->video_st->time_base) * *pts;
double ptsdiff = dpts - is->frame_last_pts; double ptsdiff = dpts - is->frame_last_pts;
if (fabs(clockdiff) < AV_NOSYNC_THRESHOLD && if (!isnan(clockdiff) && fabs(clockdiff) < AV_NOSYNC_THRESHOLD &&
ptsdiff > 0 && ptsdiff < AV_NOSYNC_THRESHOLD && ptsdiff > 0 && ptsdiff < AV_NOSYNC_THRESHOLD &&
clockdiff + ptsdiff - is->frame_last_filter_delay < 0) { clockdiff + ptsdiff - is->frame_last_filter_delay < 0) {
is->frame_last_dropped_pos = pkt->pos; is->frame_last_dropped_pos = pkt->pos;
...@@ -2038,7 +2045,7 @@ static int synchronize_audio(VideoState *is, int nb_samples) ...@@ -2038,7 +2045,7 @@ static int synchronize_audio(VideoState *is, int nb_samples)
diff = get_audio_clock(is) - get_master_clock(is); diff = get_audio_clock(is) - get_master_clock(is);
if (fabs(diff) < AV_NOSYNC_THRESHOLD) { if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) {
is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum; is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum;
if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) { if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
/* not enough measures to have a correct estimate */ /* not enough measures to have a correct estimate */
...@@ -2224,6 +2231,7 @@ static int audio_decode_frame(VideoState *is) ...@@ -2224,6 +2231,7 @@ static int audio_decode_frame(VideoState *is)
/* if update the audio clock with the pts */ /* if update the audio clock with the pts */
if (pkt->pts != AV_NOPTS_VALUE) { if (pkt->pts != AV_NOPTS_VALUE) {
is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts; is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;
is->audio_clock_serial = is->audio_pkt_temp_serial;
} }
} }
} }
...@@ -2265,7 +2273,7 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) ...@@ -2265,7 +2273,7 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
/* Let's assume the audio driver that is used by SDL has two periods. */ /* Let's assume the audio driver that is used by SDL has two periods. */
is->audio_current_pts = is->audio_clock - (double)(2 * is->audio_hw_buf_size + is->audio_write_buf_size) / bytes_per_sec; is->audio_current_pts = is->audio_clock - (double)(2 * is->audio_hw_buf_size + is->audio_write_buf_size) / bytes_per_sec;
is->audio_current_pts_drift = is->audio_current_pts - audio_callback_time / 1000000.0; is->audio_current_pts_drift = is->audio_current_pts - audio_callback_time / 1000000.0;
if (is->audioq.serial == is->audio_pkt_temp_serial) if (is->audioq.serial == is->audio_clock_serial)
check_external_clock_sync(is, is->audio_current_pts); check_external_clock_sync(is, is->audio_current_pts);
} }
...@@ -2851,6 +2859,8 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat) ...@@ -2851,6 +2859,8 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
update_external_clock_speed(is, 1.0); update_external_clock_speed(is, 1.0);
is->audio_current_pts_drift = -av_gettime() / 1000000.0; is->audio_current_pts_drift = -av_gettime() / 1000000.0;
is->video_current_pts_drift = is->audio_current_pts_drift; is->video_current_pts_drift = is->audio_current_pts_drift;
is->audio_clock_serial = -1;
is->video_clock_serial = -1;
is->av_sync_type = av_sync_type; is->av_sync_type = av_sync_type;
is->read_tid = SDL_CreateThread(read_thread, is); is->read_tid = SDL_CreateThread(read_thread, is);
if (!is->read_tid) { if (!is->read_tid) {
...@@ -3033,6 +3043,8 @@ static void event_loop(VideoState *cur_stream) ...@@ -3033,6 +3043,8 @@ static void event_loop(VideoState *cur_stream)
stream_seek(cur_stream, pos, incr, 1); stream_seek(cur_stream, pos, incr, 1);
} else { } else {
pos = get_master_clock(cur_stream); pos = get_master_clock(cur_stream);
if (isnan(pos))
pos = (double)cur_stream->seek_pos / AV_TIME_BASE;
pos += incr; pos += incr;
if (cur_stream->ic->start_time != AV_NOPTS_VALUE && pos < cur_stream->ic->start_time / (double)AV_TIME_BASE) if (cur_stream->ic->start_time != AV_NOPTS_VALUE && pos < cur_stream->ic->start_time / (double)AV_TIME_BASE)
pos = cur_stream->ic->start_time / (double)AV_TIME_BASE; pos = cur_stream->ic->start_time / (double)AV_TIME_BASE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment