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: Marton Balint <cus@passwd.hu>
This commit is contained in:
Marton Balint 2013-02-16 23:36:07 +01:00
parent 38f649662c
commit 26c208cf0f
1 changed files with 16 additions and 4 deletions

View File

@ -176,6 +176,7 @@ typedef struct VideoState {
double external_clock_speed; ///< speed of the external clock
double audio_clock;
int audio_clock_serial;
double audio_diff_cum; /* used for AV difference average computation */
double audio_diff_avg_coef;
double audio_diff_threshold;
@ -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
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
int video_clock_serial;
VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
int pictq_size, pictq_rindex, pictq_windex;
SDL_mutex *pictq_mutex;
@ -1079,6 +1081,8 @@ static void video_display(VideoState *is)
/* get the current audio clock value */
static double get_audio_clock(VideoState *is)
{
if (is->audio_clock_serial != is->audioq.serial)
return NAN;
if (is->paused) {
return is->audio_current_pts;
} else {
@ -1089,6 +1093,8 @@ static double get_audio_clock(VideoState *is)
/* get the current video clock value */
static double get_video_clock(VideoState *is)
{
if (is->video_clock_serial != is->videoq.serial)
return NAN;
if (is->paused) {
return is->video_current_pts;
} else {
@ -1230,7 +1236,7 @@ static double compute_target_delay(double delay, VideoState *is)
delay to compute the threshold. I still don't know
if it is the best guess */
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)
delay = 0;
else if (diff >= sync_threshold)
@ -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_pos = pos;
is->frame_last_pts = pts;
is->video_clock_serial = serial;
if (is->videoq.serial == serial)
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
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 &&
if (!isnan(clockdiff) && fabs(clockdiff) < AV_NOSYNC_THRESHOLD &&
ptsdiff > 0 && ptsdiff < AV_NOSYNC_THRESHOLD &&
clockdiff + ptsdiff - is->frame_last_filter_delay < 0) {
is->frame_last_dropped_pos = pkt->pos;
@ -2038,7 +2045,7 @@ static int synchronize_audio(VideoState *is, int nb_samples)
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;
if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) {
/* not enough measures to have a correct estimate */
@ -2224,6 +2231,7 @@ static int audio_decode_frame(VideoState *is)
/* if update the audio clock with the pts */
if (pkt->pts != AV_NOPTS_VALUE) {
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)
/* 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_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);
}
@ -2851,6 +2859,8 @@ static VideoState *stream_open(const char *filename, AVInputFormat *iformat)
update_external_clock_speed(is, 1.0);
is->audio_current_pts_drift = -av_gettime() / 1000000.0;
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->read_tid = SDL_CreateThread(read_thread, is);
if (!is->read_tid) {
@ -3033,6 +3043,8 @@ static void event_loop(VideoState *cur_stream)
stream_seek(cur_stream, pos, incr, 1);
} else {
pos = get_master_clock(cur_stream);
if (isnan(pos))
pos = (double)cur_stream->seek_pos / AV_TIME_BASE;
pos += incr;
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;