2021-01-27 09:41:59
0
接上篇继续分析 鸿蒙系统媒体子系统的Recorder部分。
再来分析类 RecorderImpl 的另一个成员,一个数组:
SourceManager sourceManager_[RECORDER_SOURCE_MAX_CNT];
且看结构体 SourceManager:
struct SourceManager {
RecorderVideoSource *videoSource; // 视频缓冲区管理
bool videoSourceStarted; // 视频启动状态
bool videoSourcePaused; // 视频暂停状态
int32_t videoTrackId;
std::thread videoProcessThread; // 视频处理线程
RecorderAudioSource *audioSource; // 音频缓冲区管理
bool audioSourceStarted; // 音频启动状态
bool audioSourcePaused; //音频暂停状态
int32_t audioTrackId;
std::thread audioProcessThread; // 音频处理线程
RecorderVideoSourceConfig videoSourceConfig;
RecorderAudioSourceConfig audioSourceConfig;
};
SourceManager 中包含 RecorderVideoSource 和 RecorderAudioSource,来完成视频和音频的相关的操作,并记录其Recorder状态。
类 RecorderImpl 的成员 sourceManager_ 数组在上层调用以下系列接口时被逐步的初始化:
int32_t Recorder::RecorderImpl::SetVideoSource(VideoSourceType source, int32_t &sourceId);
int32_t Recorder::RecorderImpl::SetVideoEncoder(int32_t sourceId, VideoCodecFormat encoder);
int32_t Recorder::RecorderImpl::SetAudioSource(AudioSourceType source, int32_t &sourceId);
...
以视频Video为例,在设置 video 相关参数时,可以看到对 sourceManager_ 数组的操作:
可以看到赋值语句:
sourceManager_[sourceId].videoSource = new RecorderVideoSource();
在类 RecorderVideoSource 中,主要完成一些共享内存 Surface,缓冲区查询、请求、释放等操作。
回到 applications/sample/camera/media/camera_sample.cpp 文件的 StartRecord() 函数中,其调用的 recorder_->Prepare() 和 recorder_->Start() 均可对应到 类 RecorderImpl 中:
在 Prepare() 中,分别 prepare 了 recorderSink_、VideoSource、AudioSource,
在此仍以 video 为例追踪,可以看到其完成 video source 相关工作。
在 Start() 中,分别启动了 recorderSink_、VideoSource、AudioSource,
在此仍以 video 为例追踪,
调用 recorderSink_->Start() 即前文提到的 将数据格式化后输出至录像文件中保存。
调用 StartVideoSource(),在其中:
首先调用 sourceManager_.videoSource->Start() 对数组中对应的 RecorderVideoSource 实例作启动(内部实际仅改变其状态);
接着通过
sourceManager_.videoProcessThread = std::thread(VideoSourceProcess, &sourceManager_, recorderSink_);
创建一个视频源处理线程,则接下来的工作有该线程去完成。
在线程的执行体函数 VideoSourceProcess 的 while 循环中,
调用
videoSourceManager->videoSource->AcquireBuffer(buffer, true);
实现请求 buffer(即调用类 RecorderVideoSource 中的函数);
调用
videoSourceManager->videoSource->AcquireBuffer(buffer, true);
实现写入格式后的数据到录像文件(即调用类 RecorderSink 中的 WriteData()函数)。
至此,Recorder 的底层框架及调用流程已然明了。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。
侵权投诉