diff options
author | Marton Balint <cus@passwd.hu> | 2011-08-14 20:21:25 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-08-15 03:49:07 +0200 |
commit | 10b7b4a6a1585a7c46487b00594798cdd92eed37 (patch) | |
tree | f076ab577eb3db06ef0acfff2e789cb730231f61 | |
parent | abf6b0d1ea231cc52008e9eaa1d2902442e1cbba (diff) | |
download | ffmpeg-10b7b4a6a1585a7c46487b00594798cdd92eed37.tar.gz |
ffplay: more precise audio clock based on current time
Since SDL has no audio buffer fullness info, one can get a much precise audio
clock based on the last time of the audio callback and the elapsed time since.
To achieve this I introduced the audio_current_pts and audio_current_pts_drift
variables (similar to video_current_pts and video_current_pts_drift) and
calculate them in the end of the audio callback, when VideoState->audio_clock
is already updated. The reference time I use is from the start of the audio
callback, because this way the amount of time used for audio decoding is not
interfereing with calculation.
I also replaced the audio_write_get_buf_size function with a calculated
variable because when the audio frame decoding is in progress audio_buf_size
and audio_buf_index are not stable, so using them from other threads are not a
good idea.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | ffplay.c | 34 |
1 files changed, 15 insertions, 19 deletions
@@ -158,10 +158,13 @@ typedef struct VideoState { uint8_t *audio_buf; unsigned int audio_buf_size; /* in bytes */ int audio_buf_index; /* in bytes */ + int audio_write_buf_size; AVPacket audio_pkt_temp; AVPacket audio_pkt; enum AVSampleFormat audio_src_fmt; AVAudioConvert *reformat_ctx; + double audio_current_pts; + double audio_current_pts_drift; enum ShowMode { SHOW_MODE_NONE = -1, SHOW_MODE_VIDEO = 0, SHOW_MODE_WAVES, SHOW_MODE_RDFT, SHOW_MODE_NB @@ -706,13 +709,6 @@ static void video_image_display(VideoState *is) } } -/* get the current audio output buffer size, in samples. With SDL, we - cannot have a precise information */ -static int audio_write_get_buf_size(VideoState *is) -{ - return is->audio_buf_size - is->audio_buf_index; -} - static inline int compute_mod(int a, int b) { return a < 0 ? a%b + b : a%b; @@ -735,7 +731,7 @@ static void video_audio_display(VideoState *s) if (!s->paused) { int data_used= s->show_mode == SHOW_MODE_WAVES ? s->width : (2*nb_freq); n = 2 * channels; - delay = audio_write_get_buf_size(s); + delay = s->audio_write_buf_size; delay /= n; /* to be more precise, we take into account the time spent since @@ -989,18 +985,11 @@ static int refresh_thread(void *opaque) /* get the current audio clock value */ static double get_audio_clock(VideoState *is) { - double pts; - int hw_buf_size, bytes_per_sec; - pts = is->audio_clock; - hw_buf_size = audio_write_get_buf_size(is); - bytes_per_sec = 0; - if (is->audio_st) { - bytes_per_sec = is->audio_st->codec->sample_rate * - 2 * is->audio_st->codec->channels; + if (is->paused) { + return is->audio_current_pts; + } else { + return is->audio_current_pts_drift + av_gettime() / 1000000.0; } - if (bytes_per_sec) - pts -= (double)hw_buf_size / bytes_per_sec; - return pts; } /* get the current video clock value */ @@ -2074,6 +2063,7 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) { VideoState *is = opaque; int audio_size, len1; + int bytes_per_sec; double pts; audio_callback_time = av_gettime(); @@ -2103,6 +2093,12 @@ static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) stream += len1; is->audio_buf_index += len1; } + bytes_per_sec = is->audio_st->codec->sample_rate * + 2 * is->audio_st->codec->channels; + is->audio_write_buf_size = is->audio_buf_size - is->audio_buf_index; + /* 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; } /* open a given stream. Return 0 if OK */ |