电子产业一站式赋能平台

PCB联盟网

搜索
查看: 1332|回复: 0
收起左侧

【HarmonyOS HiSpark AI Camera试用连载】鸿蒙系统之媒体子系统Record

[复制链接]

2607

主题

2607

帖子

7472

积分

高级会员

Rank: 5Rank: 5

积分
7472
发表于 2021-1-26 17:56:29 | 显示全部楼层 |阅读模式
【HarmonyOS HiSpark AI Camera试用连载】鸿蒙系统之媒体子系统Record, 之前分析了媒体子系统的主要框架,另外其中涉及的几个辅助类,这些类调用了一些封装的底层接口以帮助应用层开发者快速开发。

在应用层,applications/sample/camera/media/camera_sample.cpp 文件的 main() 函数中,我们以Record为例对其主线进行分析。



001.jpg (109.7 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传



  • int main()
      
  • {
      
  •     cout << “Camera sample begin.“ << endl;
      
  •     SampleHelp();
      
  •     CameraKit *camKit = CameraKit::GetInstance();
      
  •     if (camKit == nullptr) {
      
  •         cout << “Can not get CameraKit instance“ << endl;
      
  •         return 0;
      
  •     }
      
  •     list<string> camList = camKit->GetCameraIds();
      
  •     string camId;
      
  •     for (auto &cam : camList) {
      
  •         cout << “camera name:“ << cam << endl;
      
  •         const CameraAbility *ability = camKit->GetCameraAbility(cam);
      
  •         /* find camera which fits user\“s ability */
      
  •         list<CameraPicSize> sizeList = ability->GetSupportedSizes(0);
      
  •         if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) {
      
  •             camId = cam;
      
  • <!--StartFragment-->            <!--EndFragment--> break;

复制代码

首先看调用 StartRecord(),



002.jpg (156.87 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传

在 StartRecord() 中可以看到其所做的工作如下:

1、调用 PrepareRecorder() 即做一些准备工作:其中包括:创建 真正的(狭义的)Recorder,创建录像文件;

2、调用 recorder_->SetOutputFile() 设置(传递)录像文件的文件描述符;

3、调用 recorder_->Prepare() 以完成其内部准备工作;

4、调用 recorder_->Start() 启动录像;

5、初始化共享内存、分辨率等,以实现预览;



PrepareRecorder() 中仅调用 SampleCreateRecorder() 和 SampleGetRecordFd(),

002-2.jpg (90.64 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传

其中 SampleGetRecordFd() 所作工作相对简单:创建录像文件以备存储压缩编码后数据流;

重心在 SampleCreateRecorder() 上,



003.jpg (187.27 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传

004.jpg (193.09 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传

其内部首先 new 一个 Recorder 实例,然后对该实例进行一系列的设置,所调用这些设置接口实际上是由类Recorder 的内部实现类 RecorderImpl 来实现,而稍后所调用实例recorder_的一系列函数,其内均出自RecorderImpl,接下来详细分析该类。



005.jpg (196.24 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传

由图中代码可知,类Recorder 的实现类 RecorderImpl 完成了所有工作,该类内部持有两个重要成员:

     SourceManager sourceManager_[RECORDER_SOURCE_MAX_CNT];

     RecorderSink *recorderSink_;

先看类 RecorderSink:



006.jpg (122.63 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传

007.jpg (168.28 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传

008.jpg (170 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传

类 RecorderSink 完成 底层 muxer 的一系列操作,并将数据混合后输出至录像文件中保存。



再看 结构体 SourceManager:



010.jpg (77.57 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传

SourceManager 中包含 RecorderVideoSource 和 RecorderaudioSource,来完成视频和音频的相关的操作,并记录其Recorder状态。以视频Video为例,在设置 video 相关参数时,可以看到对 sourceManager_ 数组的操作:



011.jpg (232.63 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传



回到 applications/sample/camera/media/camera_sample.cpp 文件的 StartRecord() 函数中,其调用的 recorder_->Prepare() 和 recorder_->Start() 对应到 类 RecorderImpl 中:

在 Prepare() 中,分别 prepare 了 recorderSink_、VideoSource、AudioSource,在此仍以 video 为例追踪,   



012.jpg (107.83 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传



013.jpg (152.28 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传

在 Start() 中,分别启动了 recorderSink_、VideoSource、AudioSource,在此仍以 video 为例追踪,



014.jpg (146.24 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传



015.jpg (105.41 KB, 下载次数: 0)

下载附件  保存到相册  

1 小时前 上传

在 StartVideoSource 中,启动视频源并通过std::thread()创建一个视频源处理线程。



最后可以看到,在创建的线程 VideoSourceProcess 中,通过 while () 循环不断的写入格式后的数据到录像文件。

至此,Record 的底层框架及调用流程已然明了。
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


联系客服 关注微信 下载APP 返回顶部 返回列表