|
【HarmonyOS HiSpark AI Camera試用連載】鴻蒙系統(tǒng)之媒體子系統(tǒng)Record, 之前分析了媒體子系統(tǒng)的主要框架,另外其中涉及的幾個(gè)輔助類,這些類調(diào)用了一些封裝的底層接口以幫助應(yīng)用層開發(fā)者快速開發(fā)。
在應(yīng)用層,applications/sample/camera/media/camera_sample.cpp 文件的 main() 函數(shù)中,我們以Record為例對(duì)其主線進(jìn)行分析。
001.jpg (109.7 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
- 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;
復(fù)制代碼
首先看調(diào)用 StartRecord(),
002.jpg (156.87 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
在 StartRecord() 中可以看到其所做的工作如下:
1、調(diào)用 PrepareRecorder() 即做一些準(zhǔn)備工作:其中包括:創(chuàng)建 真正的(狹義的)Recorder,創(chuàng)建錄像文件;
2、調(diào)用 recorder_->SetOutputFile() 設(shè)置(傳遞)錄像文件的文件描述符;
3、調(diào)用 recorder_->Prepare() 以完成其內(nèi)部準(zhǔn)備工作;
4、調(diào)用 recorder_->Start() 啟動(dòng)錄像;
5、初始化共享內(nèi)存、分辨率等,以實(shí)現(xiàn)預(yù)覽;
PrepareRecorder() 中僅調(diào)用 SampleCreateRecorder() 和 SampleGetRecordFd(),
002-2.jpg (90.64 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
其中 SampleGetRecordFd() 所作工作相對(duì)簡單:創(chuàng)建錄像文件以備存儲(chǔ)壓縮編碼后數(shù)據(jù)流;
重心在 SampleCreateRecorder() 上,
003.jpg (187.27 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
004.jpg (193.09 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
其內(nèi)部首先 new 一個(gè) Recorder 實(shí)例,然后對(duì)該實(shí)例進(jìn)行一系列的設(shè)置,所調(diào)用這些設(shè)置接口實(shí)際上是由類Recorder 的內(nèi)部實(shí)現(xiàn)類 RecorderImpl 來實(shí)現(xiàn),而稍后所調(diào)用實(shí)例recorder_的一系列函數(shù),其內(nèi)均出自RecorderImpl,接下來詳細(xì)分析該類。
005.jpg (196.24 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
由圖中代碼可知,類Recorder 的實(shí)現(xiàn)類 RecorderImpl 完成了所有工作,該類內(nèi)部持有兩個(gè)重要成員:
SourceManager sourceManager_[RECORDER_SOURCE_MAX_CNT];
RecorderSink *recorderSink_;
先看類 RecorderSink:
006.jpg (122.63 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
007.jpg (168.28 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
008.jpg (170 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
類 RecorderSink 完成 底層 muxer 的一系列操作,并將數(shù)據(jù)混合后輸出至錄像文件中保存。
再看 結(jié)構(gòu)體 SourceManager:
010.jpg (77.57 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
SourceManager 中包含 RecorderVideoSource 和 RecorderaudioSource,來完成視頻和音頻的相關(guān)的操作,并記錄其Recorder狀態(tài)。以視頻Video為例,在設(shè)置 video 相關(guān)參數(shù)時(shí),可以看到對(duì) sourceManager_ 數(shù)組的操作:
011.jpg (232.63 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
回到 applications/sample/camera/media/camera_sample.cpp 文件的 StartRecord() 函數(shù)中,其調(diào)用的 recorder_->Prepare() 和 recorder_->Start() 對(duì)應(yīng)到 類 RecorderImpl 中:
在 Prepare() 中,分別 prepare 了 recorderSink_、VideoSource、AudioSource,在此仍以 video 為例追蹤,
012.jpg (107.83 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
013.jpg (152.28 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
在 Start() 中,分別啟動(dòng)了 recorderSink_、VideoSource、AudioSource,在此仍以 video 為例追蹤,
014.jpg (146.24 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
015.jpg (105.41 KB, 下載次數(shù): 0)
下載附件 保存到相冊(cè)
1 小時(shí)前 上傳
在 StartVideoSource 中,啟動(dòng)視頻源并通過std::thread()創(chuàng)建一個(gè)視頻源處理線程。
最后可以看到,在創(chuàng)建的線程 VideoSourceProcess 中,通過 while () 循環(huán)不斷的寫入格式后的數(shù)據(jù)到錄像文件。
至此,Record 的底層框架及調(diào)用流程已然明了。 |
|