媒体子系统

简介

该仓主要用于存放媒体子系统的源码信息,旨在为多媒体应用开发者开发者提供统一的开发接口,使得开发者可以专注于应用业务的开发,轻松使用多媒体的资源。

本次开源基于本仓代码信息将相关设备配置文件放入到test\lite\devini内,用户使用时将配置文件放入到开发板/data目录,通过该配置文件可以方便去适配sensor及分辨率帧率等能力。

多媒体子系统框架

媒体子系统 - 图1

多媒体子系统系统业务流程图

媒体子系统 - 图2

如上图,多媒体包括camera,recorder和player,camera提供yuv/rgb,jpeg以及H264,H265数据到共享内存surface中,recorder模块将surface中h264/h265数据和音频aac数据打包成mp4文件,player模块把mp4文件解复用成音频和视频数据,分别送入对应编码器解码,然后进行播放。

目录

表 1 轻量级多媒体子系统源代码目录结构

名称

描述

foundation\multimedia\frameworks

北向接口内部框架实现,包括audio,camera,player.recorder

foundation\multimedia\interfaces\kits

北向接口对外头文件

foundation\multimedia\services\media_lite

北向接口底层服务实现

foundation\multimedia\utils\lite

北向接口通用模块实现

foundation\multimedia\test\lite

北向接口测试代码。

约束

  • C++11版本或以上
  • 目前支持3516dv300、3518ev300开发板,其中仅3516dv300支持播放功能

安装

  • 请提前加载内核及相关驱动,参考内核及驱动子系统readme。
  • 配置合适的配置文件,可以参考test/devini下配置文件,说明参见《配置文件说明文档》,当前仅支持imx335和imx327sensor,如果适配其他sensor可在开源社区中求助。
  • 北向接口调用参见test下demo实现。

使用

开发者使用多媒体接口用于录像、预览和播放音视频等资源,使用这些资源前先创建camerakit组件对象,注册各种事件回调,这些事件回调是用户实现用来响应多媒体模块中事件响应的,之后调用创建camera就可以创建一个操作camera资源的对象,使用这个对象可以启动预览、录像或抓拍取流,及设置取流的相关参数。

例:下面是用户重写事件类的实例

  1. /*
  2. * Copyright (c) 2020 Huawei Device Co., Ltd.
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include "camera_kit.h"
  16. #include "recorder.h"
  17. #include <sys/time.h>
  18. #include <algorithm>
  19. #include <fstream>
  20. #include <iostream>
  21. #include <sstream>
  22. using namespace std;
  23. using namespace OHOS;
  24. using namespace OHOS::Media;
  25. static void SampleSaveCapture(const char *p, uint32_t size)
  26. {
  27. cout << "Start saving picture" << endl;
  28. struct timeval tv;
  29. gettimeofday(&tv, NULL);
  30. struct tm *ltm = localtime(&tv.tv_sec);
  31. if (ltm != nullptr) {
  32. ostringstream ss("Capture_");
  33. ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg";
  34. ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc);
  35. cout << "write " << size << " bytes" << endl;
  36. pic.write(p, size);
  37. cout << "Saving picture end" << endl;
  38. }
  39. }
  40. Recorder *SampleCreateRecorder()
  41. {
  42. int ret = 0;
  43. int32_t sampleRate = 48000;
  44. int32_t channelCount = 1;
  45. AudioCodecFormat audioFormat = AAC_LC;
  46. AudioSourceType inputSource = AUDIO_MIC;
  47. int32_t audioEncodingBitRate = sampleRate;
  48. VideoSourceType source = VIDEO_SOURCE_SURFACE_ES;
  49. int32_t frameRate = 30;
  50. float fps = 30;
  51. int32_t rate = 4096;
  52. int32_t sourceId = 0;
  53. int32_t audioSourceId = 0;
  54. int32_t width = 1920;
  55. int32_t height = 1080;
  56. VideoCodecFormat encoder;
  57. encoder = HEVC;
  58. width = 1920;
  59. height = 1080;
  60. Recorder *recorder = new Recorder();
  61. if ((ret = recorder->SetVideoSource(source, sourceId)) != SUCCESS) {
  62. cout << "SetVideoSource failed." << ret << endl;
  63. delete recorder;
  64. return nullptr;
  65. }
  66. if ((ret = recorder->SetVideoEncoder(sourceId, encoder)) != SUCCESS) {
  67. cout << "SetVideoEncoder failed." << ret << endl;
  68. delete recorder;
  69. return nullptr;
  70. }
  71. if ((ret = recorder->SetVideoSize(sourceId, width, height)) != SUCCESS) {
  72. cout << "SetVideoSize failed." << ret << endl;
  73. delete recorder;
  74. return nullptr;
  75. }
  76. if ((ret = recorder->SetVideoFrameRate(sourceId, frameRate)) != SUCCESS) {
  77. cout << "SetVideoFrameRate failed." << ret << endl;
  78. delete recorder;
  79. return nullptr;
  80. }
  81. if ((ret = recorder->SetVideoEncodingBitRate(sourceId, rate)) != SUCCESS) {
  82. cout << "SetVideoEncodingBitRate failed." << ret << endl;
  83. delete recorder;
  84. return nullptr;
  85. }
  86. if ((ret = recorder->SetCaptureRate(sourceId, frameRate)) != SUCCESS) {
  87. cout << "SetCaptureRate failed." << ret << endl;
  88. delete recorder;
  89. return nullptr;
  90. }
  91. if ((ret = recorder->SetAudioSource(inputSource, audioSourceId)) != SUCCESS) {
  92. cout << "SetAudioSource failed." << ret << endl;
  93. delete recorder;
  94. return nullptr;
  95. }
  96. if ((ret = recorder->SetAudioEncoder(audioSourceId, audioFormat)) != SUCCESS) {
  97. cout << "SetAudioEncoder failed." << ret << endl;
  98. delete recorder;
  99. return nullptr;
  100. }
  101. if ((ret = recorder->SetAudioSampleRate(audioSourceId, sampleRate)) != SUCCESS) {
  102. cout << "SetAudioSampleRate failed." << ret << endl;
  103. delete recorder;
  104. return nullptr;
  105. }
  106. if ((ret = recorder->SetAudioChannels(audioSourceId, channelCount)) != SUCCESS) {
  107. cout << "SetAudioChannels failed." << ret << endl;
  108. delete recorder;
  109. return nullptr;
  110. }
  111. if ((ret = recorder->SetAudioEncodingBitRate(audioSourceId, audioEncodingBitRate)) != SUCCESS) {
  112. cout << "SetAudioEncodingBitRate failed." << ret << endl;
  113. delete recorder;
  114. return nullptr;
  115. }
  116. return recorder;
  117. }
  118. class SampleFrameStateCallback : public FrameStateCallback {
  119. void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override
  120. {
  121. cout << "Receive frame complete inform." << endl;
  122. if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) {
  123. cout << "Capture frame received." << endl;
  124. list<Surface *> surfaceList = fc.GetSurfaces();
  125. for (Surface *surface : surfaceList) {
  126. SurfaceBuffer *buffer = surface->AcquireBuffer();
  127. if (buffer != nullptr) {
  128. char *virtAddr = static_cast<char *>(buffer->GetVirAddr());
  129. if (virtAddr != nullptr) {
  130. SampleSaveCapture(virtAddr, buffer->GetSize());
  131. }
  132. surface->ReleaseBuffer(buffer);
  133. }
  134. delete surface;
  135. }
  136. delete &fc;
  137. }
  138. }
  139. };
  140. class SampleCameraStateMng : public CameraStateCallback {
  141. public:
  142. SampleCameraStateMng() = delete;
  143. SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {}
  144. ~SampleCameraStateMng()
  145. {
  146. if (recorder_ != nullptr) {
  147. recorder_->Release();
  148. delete recorder_;
  149. }
  150. }
  151. void OnCreated(Camera &c) override
  152. {
  153. cout << "Sample recv OnCreate camera." << endl;
  154. auto config = CameraConfig::CreateCameraConfig();
  155. config->SetFrameStateCallback(&fsCb_, &eventHdlr_);
  156. c.Configure(*config);
  157. cam_ = &c;
  158. }
  159. void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {}
  160. void OnReleased(Camera &c) override {}
  161. void StartRecord()
  162. {
  163. int ret;
  164. if (isRecording_) {
  165. cout << "Camera is already recording." << endl;
  166. return;
  167. }
  168. if (recorder_ == nullptr) {
  169. recorder_ = SampleCreateRecorder();
  170. }
  171. if (recorder_ == nullptr) {
  172. cout << "Recorder not available" << endl;
  173. return;
  174. }
  175. string path = "/sdcard";
  176. ret = recorder_->SetOutputPath(path);
  177. if (ret != SUCCESS) {
  178. cout << "SetOutputPath fialed :" << ret << std::endl;
  179. return;
  180. }
  181. ret = recorder_->Prepare();
  182. if (ret != SUCCESS) {
  183. cout << "Prepare failed.=" << ret << endl;
  184. return;
  185. }
  186. Surface *surface = (recorder_->GetSurface(0)).get();
  187. surface->SetWidthAndHeight(1920, 1080);
  188. surface->SetQueueSize(3);
  189. surface->SetSize(1024 * 1024);
  190. FrameConfig *fc = new FrameConfig(FRAME_CONFIG_RECORD);
  191. fc->AddSurface(*surface);
  192. ret = recorder_->Start();
  193. if (ret != SUCCESS) {
  194. delete fc;
  195. cout << "recorder start failed. ret=" << ret << endl;
  196. return;
  197. }
  198. ret = cam_->TriggerLoopingCapture(*fc);
  199. if (ret != 0) {
  200. delete fc;
  201. cout << "camera start recording failed. ret=" << ret << endl;
  202. return;
  203. }
  204. isRecording_ = true;
  205. cout << "camera start recording succeed." << endl;
  206. }
  207. void StartPreview()
  208. {
  209. if (isPreviewing_) {
  210. cout << "Camera is already previewing." << endl;
  211. return;
  212. }
  213. FrameConfig *fc = new FrameConfig(FRAME_CONFIG_PREVIEW);
  214. Surface *surface = Surface::CreateSurface();
  215. if (surface == nullptr) {
  216. delete fc;
  217. cout << "CreateSurface failed" << endl;
  218. return;
  219. }
  220. surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */
  221. surface->SetUserData("region_position_x", "0");
  222. surface->SetUserData("region_position_y", "0");
  223. surface->SetUserData("region_width", "480");
  224. surface->SetUserData("region_height", "480");
  225. fc->AddSurface(*surface);
  226. int32_t ret = cam_->TriggerLoopingCapture(*fc);
  227. if (ret != 0) {
  228. delete fc;
  229. cout << "camera start preview failed. ret=" << ret << endl;
  230. return;
  231. }
  232. delete surface;
  233. isPreviewing_ = true;
  234. cout << "camera start preview succeed." << endl;
  235. }
  236. void Capture()
  237. {
  238. if (cam_ == nullptr) {
  239. cout << "Camera is not ready." << endl;
  240. return;
  241. }
  242. FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE);
  243. Surface *surface = Surface::CreateSurface();
  244. if (surface == nullptr) {
  245. delete fc;
  246. cout << "CreateSurface failed" << endl;
  247. return;
  248. }
  249. surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */
  250. fc->AddSurface(*surface);
  251. cam_->TriggerSingleCapture(*fc);
  252. }
  253. void Stop()
  254. {
  255. if (cam_ == nullptr) {
  256. cout << "Camera is not ready." << endl;
  257. return;
  258. }
  259. if (recorder_ != nullptr) {
  260. recorder_->Stop(false);
  261. }
  262. cam_->StopLoopingCapture();
  263. isPreviewing_ = false;
  264. isRecording_ = false;
  265. }
  266. private:
  267. bool isPreviewing_ = false;
  268. bool isRecording_ = false;
  269. EventHandler &eventHdlr_;
  270. Camera *cam_ = nullptr;
  271. Recorder *recorder_ = nullptr;
  272. SampleFrameStateCallback fsCb_;
  273. };
  274. class SampleCameraDeviceCallback : public CameraDeviceCallback {};
  275. void SampleHelp()
  276. {
  277. cout << "*******************************************" << endl;
  278. cout << "Select the behavior of avrecorder." << endl;
  279. cout << "1: Capture" << endl;
  280. cout << "2: Record(Press s or S to stop)" << endl;
  281. cout << "3: Preview(Press s or S to stop)" << endl;
  282. cout << "q: quit the sample." << endl;
  283. cout << "*******************************************" << endl;
  284. }
  285. int main()
  286. {
  287. cout << "Camera sample begin." << endl;
  288. SampleHelp();
  289. CameraKit *camKit = CameraKit::GetInstance();
  290. if (camKit == nullptr) {
  291. cout << "Can not get CameraKit instance" << endl;
  292. return 0;
  293. }
  294. list<string> camList = camKit->GetCameraIds();
  295. string camId;
  296. for (auto &cam : camList) {
  297. cout << "camera name:" << cam << endl;
  298. const CameraAbility *ability = camKit->GetCameraAbility(cam);
  299. /* find camera which fits user's ability */
  300. list<CameraPicSize> sizeList = ability->GetSupportedSizes(0);
  301. if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) {
  302. camId = cam;
  303. break;
  304. }
  305. }
  306. if (camId.empty()) {
  307. cout << "No available camera.(1080p wanted)" << endl;
  308. return 0;
  309. }
  310. EventHandler eventHdlr; // Create a thread to handle callback events
  311. SampleCameraStateMng CamStateMng(eventHdlr);
  312. camKit->CreateCamera(camId, CamStateMng, eventHdlr);
  313. char input;
  314. while (cin >> input) {
  315. switch (input) {
  316. case '1':
  317. CamStateMng.Capture();
  318. break;
  319. case '2':
  320. CamStateMng.StartRecord();
  321. break;
  322. case '3':
  323. CamStateMng.StartPreview();
  324. break;
  325. case 's':
  326. CamStateMng.Stop();
  327. break;
  328. case 'q':
  329. CamStateMng.Stop();
  330. goto EXIT;
  331. default:
  332. SampleHelp();
  333. break;
  334. }
  335. }
  336. EXIT:
  337. cout << "Camera sample end." << endl;
  338. return 0;
  339. }

涉及仓

multimedia_frameworks_camera_lite

multimedia_frameworks_audio_lite

multimedia_frameworks_player_lite

multimedia_frameworks_recorder_lite

multimedia_hals_camera_lite

multimedia_interfaces_kits_recorder_lite

multimedia_interfaces_kits_audio_lite

multimedia_interfaces_kits_camera_lite

multimedia_interfaces_kits_player_lite

multimedia_services_media_lite

multimedia_utils_lite