summaryrefslogtreecommitdiff
path: root/ffplay.c
diff options
context:
space:
mode:
authorMarton Balint <cus@passwd.hu>2011-08-14 20:21:25 +0200
committerMichael Niedermayer <michaelni@gmx.at>2011-08-15 03:49:07 +0200
commit10b7b4a6a1585a7c46487b00594798cdd92eed37 (patch)
treef076ab577eb3db06ef0acfff2e789cb730231f61 /ffplay.c
parentabf6b0d1ea231cc52008e9eaa1d2902442e1cbba (diff)
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>
Diffstat (limited to 'ffplay.c')
-rw-r--r--ffplay.c34
1 files changed, 15 insertions, 19 deletions
diff --git a/ffplay.c b/ffplay.c
index 6f3130e57e..61f4bc086c 100644
--- a/ffplay.c
+++ b/ffplay.c
@@ -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 */