ffplay中音频参考时钟的获取

 /* prepare a new audio buffer */
static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) {
	VideoState *is = opaque;
	int audio_size, len1;
	int bytes_per_sec;
	int frame_size = av_samples_get_buffer_size(NULL, is->audio_tgt_channels, 1,
			is->audio_tgt_fmt, 1);
	double pts;

	audio_callback_time = av_gettime();//当前正在播放的声音的系统时间
	LOGV("audio_buffer:audio_callback_time=%03f,len=%d\n",audio_callback_time/1000000.0,len);
	while (len > 0) {
		if (is->audio_buf_index >= is->audio_buf_size) {
			audio_size = audio_decode_frame(is, &pts);
			if (audio_size < 0) {
				/* if error, just output silence */
				is->audio_buf = is->silence_buf;
				is->audio_buf_size = sizeof(is->silence_buf) / frame_size
						* frame_size;
			} else {
				if (is->show_mode != SHOW_MODE_VIDEO)
					update_sample_display(is, (int16_t *) is->audio_buf,
							audio_size);
				is->audio_buf_size = audio_size;
			}
			is->audio_buf_index = 0;
		}
		len1 = is->audio_buf_size - is->audio_buf_index;
		if (len1 > len)
			len1 = len;
		memcpy(stream, (uint8_t *) is->audio_buf + is->audio_buf_index, len1);
		len -= len1;
		stream += len1;
		is->audio_buf_index += len1;
	}
	bytes_per_sec = is->audio_tgt_freq * is->audio_tgt_channels
			* av_get_bytes_per_sample(is->audio_tgt_fmt);
	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. */
//从当前播放的声音开始到播放完两个stream buffer和上次未传递完的音频帧字节(当stream buffer为自定义buffer的1.5倍时,每次未
//传完的大小为0.5自定义buffer)才能到当前解码后的音频帧	,所以以下可以获取到当前播放声音的pts
 is->audio_current_pts = is->audio_clock
			- (double) (2 * is->audio_hw_buf_size + is->audio_write_buf_size)
					/ bytes_per_sec;
	LOGV("audio_buffer: is->audio_hw_buf_size  =%d,audio_size=%d,delay=%03fis->audio_current_pts = %03f   is->audio_write_buf_size=%d\n",is->audio_hw_buf_size,audio_size,(av_gettime()-audio_callback_time)/1000000.0,
			                                 is->audio_current_pts, is->audio_write_buf_size);
//现在已经获取到当前播放声音对应的系统时间 audio_callback_time 和audio_current_pts,它们之差对应的应该是个固定的偏移值,
//否则说明声音播放过快或者过慢(不要被drift迷惑,可能是以前版本的遗留症)
	is->audio_current_pts_drift = is->audio_current_pts
			- audio_callback_time / 1000000.0;
}



static double get_audio_clock(VideoState *is) {
	if (is->paused) {
		return is->audio_current_pts;
	} else {
  //因为从sdl_audio_callback回调开始时播放的声音已经持续了一段时间,用当时的pts+播放持续的时间得到声音的参考时钟此刻
//的值, is->audio_current_pts +(av_gettime() / 1000000.0-audio_callback_time / 1000000.0)
		return is->audio_current_pts_drift + av_gettime() / 1000000.0;
	}
}
以上是我对ffplay.c中以音频为参考时钟的个人理解,不足之处希望大家相互指点。

你可能感兴趣的:(视频多媒体)