前言
在read_thread线程中有三个地方调用了stream_component_open函数,分别对应音频流、视频流和字幕流,由于字幕流的索引值st_index[AVMEDIA_TYPE_SUBTITLE]小于0,实际执行时,只有前两个地方生效。在stream_component_open函数内部,又产生了两个线程audio_thread和video_thread,分别用于解码音频和视频,并把解码后的数据保存到对应的FrameQueue中。
一、打开解码器
1、寻找解码器
对于音频和视频,前面的操作都是一致的,分配解码器上下文AVCodecContext,并把媒体流的参数信息填充到新分配的解码器上下文avctx中,接下来根据解码器ID,从已经注册的解码器中,寻找对应的解码器。

以mp4为例,对于音频格式,一般是AAC,对于视频格式,一般是h264。
2、强制指定解码器
接下来有个forced_codec_name变量,这个变量是在switch语句中赋值的
audio_codec_name和video_codec_name,是main函数设置参数时用到的,如果运行ffplay时,参数中没有强制指定解码器,那么audio_codec_name和video_codec_name的值为NULL,对应forced_codec_name的值也为NULL。
if (forced_codec_name)
codec = avcodec_find_decoder_by_name(forced_codec_name);
如果指定了解码器名称,则需要调用avcodec_find_decoder_by_name函数查找解码器。
3、解析参数
初步阶段只是添加了mp4文件作为参数,解析参数相关的功能,先忽略。
opts = filter_codec_opts(codec_opts, avctx->codec_id, ic, ic->streams[stream_index], codec);
4、打开解码器
然后用avcodec_open2()函数打开对应的解码器。
if ((ret = avcodec_open2(avctx, codec, &opts)) < 0) {
goto fail;
}
接下来有个switch语句,对音频和视频单独处理,处理音频的功能相对复杂一些。
二、开启音频解码线程
这一部分涉及到SDL的功能,有几个重要的函数SDL_OpenAudioDevice和SDL_PauseAudioDevice,以及音频回调函数sdl_audio_callback,还有一个结构体SDL_AudioSpec都比较重要。
1、audio_open函数
首先定义了两个数组next_nb_channels和数组next_sample_rates,这两个数组是打开音频设备失败时用到的,实际运行时一般都可以找到音频设备,暂不分析。


最低0.47元/天 解锁文章
1731

被折叠的 条评论
为什么被折叠?



