很多细节还是没有研究透

1、源码ffplay.c迁移qt编译

首先尝试了再vs下是要msvc进行编译发现报错误

: “unistd.h”: No such file or directory

百度解决方案意思是再linux下开发的C程序都需要头文件unistd.h,但VC中没有个头文件,
所以用VC编译总是报错。但是根据网上的方法,自己定义,h文件发现汇报其他错误
在这里插入图片描述
参考链接:https://www.cnblogs.com/ManMonth/archive/2010/02/01/1661142.html [转]VC报错 ‘unistd.h’: No such file or directory

则改到qt中新建工程引入ffplay.c
效果图
在这里插入图片描述
注意点:
1)编译环境&参数传入在这里插入图片描述
2)运行时所需要的动态库和文件需要放过去
在这里插入图片描述

2、源代码解析

2.1、函数流程分析

参考公众号:txb玩linux中相关文章
在这里插入图片描述
入口函数main

main
	init_dynload;win32设置动态库当前路径警告
	av_log_set_flags
	parse_loglevel
	avdevice_register_all
	parse_options
	SDL_Init
	SDL_CreateWindow
	SDL_CreateRenderer
	stream_open
		frame_queue_init;创建循环帧队列,视频音频字幕
		packet_queue_init;创建循环包队列,视频音频字幕
		SDL_CreateCond;
		init_clock ;初始化时钟 视频音频字幕
		SDL_CreateThread(read_thread)
	event_loop

read_thread线程主要完成解封装,读取多媒体包数据放入包缓冲队列中,

read_thread
	//解封装
	avformat_alloc_context;创建上下文结构体
	interrupt_callback.callback = decode_interrupt_cb;设置中断回调函数
	avformat_open_input;打开文件
	avformat_find_stream_info;探测媒体类型,
	avformat_seek_file;需要指定起始位置
	is_realtime;是否为实时流媒体
	av_find_best_stream;将为流的编解码器找到默认的解码器,视频音频字幕
	av_guess_sample_aspect_ratio
	set_default_window_size
	stream_component_open;相应解码器,并创建相应的解码线程;视频、音频解码器字幕
		avcodec_alloc_context3;编解码器上下文结构体
		avcodec_parameters_to_context;将码流中的编解码器信息拷贝到新分配的编解码器上下文结构体
		avcodec_find_decoder;codec_id查找解码器
		音频
			audio_open
				SDL_Init
				SDL_getenv
				wanted_spec.callback = sdl_audio_callback;
			decoder_init
			decoder_start
				SDL_CreateThread(audio_thread)//创建音频解码线程
		视频
			decoder_init
			decoder_start
				SDL_CreateThread(video_thread)//创建视频解码线程
		字幕
			decoder_init
			decoder_start
				SDL_CreateThread(subtitle_thread)
	//读取多媒体包数据放入对应的包缓冲队列中
	for (;;)
		是否有seek请求
		缓存队列有足够的包,不需要继续读取数据
		av_read_frame;读取媒体数据、对应视频音频字幕
		packet_queue_put;音视频数据分别送入相应的queue、对应视频音频字幕

event_loop 线程主要完成视频sdl显示及sdl的一些事件处理

//视频输出
event_loop	
	for (;;)
		refresh_loop_wait_event
			 while (!SDL_PeepEvents)
				av_usleep;remaining_time就是用来进行音视频同步的。
				video_refresh;显示每一帧
					frame_queue_peek
					video_display
						video_open;设置宽高,sdlwindows设置
						SDL_SetRenderDrawColor
						SDL_RenderClear
						video_audio_display;播放声音
						video_image_display;渲染视频
						SDL_RenderPresent
		sdl事件监听	

sdl_audio_callback线程,主要完成声音的输出

//声音输出
sdl_audio_callback
	while
		audio_decode_frame
			frame_queue_next
			音频相关操作
		update_sample_display
		memcpy(stream, (uint8_t *)is->audio_buf

audio_thread线程主要完成从音频包缓冲队列中拿包解码将解码后的帧数据放入帧缓冲队列中

//音频解码
audio_thread
	while
		decoder_decode_frame
			for (;;)
				avcodec_receive_frame;从解码器中收到解码出的帧
			while
				packet_queue_get;从包缓冲队列中获取包
			avcodec_send_packet;发生包到解码器中
		frame_queue_push;将解码出来的帧放到帧队列中

video_thread线程主要是从视频包缓冲队列中拿包解码将解码后的帧数据放入帧缓冲队列中

//视频解码
video_thread
	for (;;)
		get_video_frame;获取解码后的视频帧
			decoder_decode_frame
				for (;;)
					avcodec_receive_frame;从解码器中收到解码出的帧
				while
					packet_queue_get;从包缓冲队列中获取包
				avcodec_send_packet;发生包到解码器中
		queue_picture;将解码后的视频帧插入队列
			frame_queue_peek_writable;检测队列是否有空间
			set_default_window_size
			frame_queue_push

2.2、如何做到音视频同步的

理论:在ffplay中 音视频同步有三种方式

以视频为基准,同步音频到视频
	音频慢了就加快音频的播放速度,或者直接丢掉一部分音频帧
	音频快了就放慢音频的播放速度
以音频为基准,同步视频到音频
	视频慢了则加快播放或丢掉部分视频帧
	视频快了则延迟播放
以外部时钟为准,同步音频和视频到外部时钟
	根据外部时钟改版音频和视频的播放速度

2.2.1、以视频为基准,同步音频到视频

视频同步到音频是ffplay的默认同步方式。在视频播放线程中实现。视频播放函数video_refresh()实现了视频显示(包含同步控制)。
视频同步到音频的基本方法是:如果视频超前音频,则不进行播放,以等待音频;如果视频落后音频,则丢弃当前帧直接播放下一帧,以追赶音频。

2.2.2、音频同步到视频

音频同步到视频的方式,在音频播放线程中,实现代码在audio_decode_frame()及synchronize_audio()中。

2.2.3、以外部标准时钟为标准

具体细节之后研究
在之前双录写文件都是以标准时钟进行写入的

参考博客:
https://www.cnblogs.com/leisure_chn/p/10307089.html

3、seek步骤

参考:https://www.cnblogs.com/leisure_chn/p/10316225.html

参考博客:
https://www.cnblogs.com/leisure_chn/p/10301831.html

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐