1 # Camera组件<a name="ZH-CN_TOPIC_0000001101564782"></a>
2 
3 - [Camera组件<a name="ZH-CN_TOPIC_0000001101564782"></a>](#camera组件)
4   - [简介<a name="section11660541593"></a>](#简介)
5     - [基本概念<a name="sectionbasicconcepts"></a>](#基本概念)
6   - [目录<a name="section176641621345"></a>](#目录)
7   - [使用说明<a name="section45377346241"></a>](#使用说明)
8     - [拍照<a name="section2071191842718"></a>](#拍照)
9     - [开始和停止预览<a name="section2094314213271"></a>](#开始和停止预览)
10     - [视频录像<a name="section1983913118271"></a>](#视频录像)
11     - [切换多个照相机设备<a name="sectionswitchcamera"></a>](#切换多个照相机设备)
12     - [设置闪光灯<a name="sectionsetflash"></a>](#设置闪光灯)
13   - [相关仓<a name="section16511040154318"></a>](#相关仓)
14 
15 ## 简介<a name="section11660541593"></a>
16 
17 相机组件支持相机业务的开发,开发者可以通过已开放的接口实现相机硬件的访问、操作和新功能开发,最常见的操作如:预览、拍照和录像等。
18 
19 ### 基本概念<a name="sectionbasicconcepts"></a>
20 
21 -   拍照
22 
23     此功能用于拍摄采集照片。
24 
25 -   预览
26 
27     此功能用于在开启相机后,在缓冲区内重复采集摄像帧,支持在拍照或录像前进行摄像帧预览显示。
28 
29 -   录像
30 
31     此功能用于在开始录像后和结束录像前的时间段内,在缓冲区内重复采集摄像帧,支持视频录制。
32 
33 **图 1**  相机组件架构图<a name="fig310889397"></a>
34 
35 ![](figures/camera-architecture-zh.png "camera-architecture-zh")
36 
37 ## 目录<a name="section176641621345"></a>
38 
39 仓目录结构如下:
40 
41 ```
42 /foundation/multimedia/camera_framework   # 相机组件业务代码
43 ├── frameworks                           # 框架代码
44 │   ├── native                           # 内部接口实现
45 │   │   ├── camera                       # 相机框架实现
46 │   │   └── metadata                     # 元数据实现
47 │   └── js                               # 外部接口实现
48 │       └── camera_napi                  # 相机NAPI实现
49 ├── interfaces                           # 接口代码
50 │   ├── inner_api                        # 内部接口
51 │   └── kits                             # 外部接口
52 ├── LICENSE                              # 许可证文件
53 ├── ohos.build                           # 构建文件
54 ├── sa_profile                           # 服务配置文件
55 └── services                             # 服务代码
56     ├── camera_service                   # 相机服务实现
57     └── etc                              # 相机服务配置
58 ```
59 
60 ## 使用说明<a name="section45377346241"></a>
61 
62 ### 拍照<a name="section2071191842718"></a>
63 
64 拍照的步骤:
65 
66 1.  创建缓冲区消费者端监听器(CaptureSurfaceListener)以保存图像。
67     ```
68     class CaptureSurfaceListener : public IBufferConsumerListener {
69     public:
70         int32_t mode_;
71         sptr<Surface> surface_;
72 
73         void OnBufferAvailable() override
74         {
75             int32_t flushFence = 0;
76             int64_t timestamp = 0;
77             OHOS::Rect damage; // initialize the damage
78 
79             OHOS::sptr<OHOS::SurfaceBuffer> buffer = nullptr;
80             surface_->AcquireBuffer(buffer, flushFence, timestamp, damage);
81             if (buffer != nullptr) {
82                 void* addr = buffer->GetVirAddr();
83                 int32_t size = buffer->GetSize();
84 
85                 // Save the buffer(addr) to a file.
86 
87                 surface_->ReleaseBuffer(buffer, -1);
88             }
89         }
90     };
91     ```
92 
93 2.  获取相机管理器实例并获取相机对象列表。
94 
95     ```
96     sptr<CameraManager> camManagerObj = CameraManager::GetInstance();
97     std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras();
98     ```
99 
100 3.  使用相机对象创建相机输入来打开相机。
101 
102     ```
103     sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]);
104     ```
105 
106 4.  创建采集会话。
107 
108     ```
109     sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession();
110     ```
111 
112 5.  开始配置采集会话。
113 
114     ```
115     int32_t result = captureSession->BeginConfig();
116     ```
117 
118 6.  将相机输入添加到采集会话。
119 
120     ```
121     result = captureSession->AddInput(cameraInput);
122     ```
123 
124 7.  创建消费者 Surface 并注册监听器以监听缓冲区更新。拍照的宽和高可以配置为所支持的 1280x960 分辨率。
125 
126     ```
127     sptr<Surface> photoSurface = Surface::CreateSurfaceAsConsumer();
128     int32_t photoWidth = 1280;
129     int32_t photoHeight = 960;
130     photoSurface->SetDefaultWidthAndHeight(photoWidth, photoHeight);
131     photoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_JPEG));
132     sptr<CaptureSurfaceListener> capturelistener = new(std::nothrow) CaptureSurfaceListener();
133     capturelistener->mode_ = MODE_PHOTO;
134     capturelistener->surface_ = photoSurface;
135     photoSurface->RegisterConsumerListener((sptr<IBufferConsumerListener> &)capturelistener);
136     ```
137 
138 8.  使用上面创建的 Surface 创建拍照输出。
139 
140     ```
141     sptr<CaptureOutput> photoOutput = camManagerObj->CreatePhotoOutput(photoSurface);
142     ```
143 
144 9.  将拍照输出添加到采集会话。
145 
146     ```
147     result = captureSession->AddOutput(photoOutput);
148     ```
149 
150 10. 将配置提交到采集会话。
151 
152     ```
153     result = captureSession->CommitConfig();
154     ```
155 
156 11. 拍摄照片。
157 
158     ```
159     result = ((sptr<PhotoOutput> &)photoOutput)->Capture();
160     ```
161 
162 12. 释放采集会话资源。
163 
164     ```
165     captureSession->Release();
166     ```
167 
168 13. 释放相机输入关闭相机。
169 
170     ```
171     cameraInput->Release();
172     ```
173 
174 ### 开始和停止预览<a name="section2094314213271"></a>
175 
176 开始和停止预览的步骤:
177 
178 1.  获取相机管理器实例并获取相机对象列表。
179 
180     ```
181     sptr<CameraManager> camManagerObj = CameraManager::GetInstance();
182     std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras();
183     ```
184 
185 2.  使用相机对象创建相机输入来打开相机。
186 
187     ```
188     sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]);
189     ```
190 
191 3.  创建采集会话。
192 
193     ```
194     sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession();
195     ```
196 
197 4.  开始配置采集会话。
198 
199     ```
200     int32_t result = captureSession->BeginConfig();
201     ```
202 
203 5.  将相机输入添加到采集会话。
204 
205     ```
206     result = captureSession->AddInput(cameraInput);
207     ```
208 
209 6.  使用从窗口管理器获得的 Surface 创建预览输出用以在显示上渲染。预览的宽和高可以配置为所支持的 640x480 或 832x480 分辨率,如果想保存到文件,可以按照拍照流程提到步骤,创建 Surface,注册监听器以监听缓冲区更新。
210 
211     ```
212     int32_t previewWidth = 640;
213     int32_t previewHeight = 480;
214     previewSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_YCRCB_420_SP));
215     sptr<CaptureOutput> previewOutput = camManagerObj->CreateCustomPreviewOutput(previewSurface, previewWidth, previewHeight);
216     ```
217 
218 7.  将预览输出添加到采集会话。
219 
220     ```
221     result = captureSession->AddOutput(previewOutput);
222     ```
223 
224 8.  将配置提交到采集会话。
225 
226     ```
227     result = captureSession->CommitConfig();
228     ```
229 
230 9.  开始预览。
231 
232     ```
233     result = captureSession->Start();
234     ```
235 
236 10. 需要时停止预览。
237 
238     ```
239     result = captureSession->Stop();
240     ```
241 
242 11. 释放采集会话资源。
243 
244     ```
245     captureSession->Release();
246     ```
247 
248 12. 释放相机输入关闭相机。
249 
250     ```
251     cameraInput->Release();
252     ```
253 
254 ### 视频录像<a name="section1983913118271"></a>
255 
256 视频录像的步骤:
257 
258 1.  获取相机管理器实例并获取相机对象列表。
259 
260     ```
261     sptr<CameraManager> camManagerObj = CameraManager::GetInstance();
262     std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras();
263     ```
264 
265 2.  使用相机对象创建相机输入来打开相机。
266 
267     ```
268     sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]);
269     ```
270 
271 3.  创建采集会话。
272 
273     ```
274     sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession();
275     ```
276 
277 4.  开始配置采集会话。
278 
279     ```
280     int32_t result = captureSession->BeginConfig();
281     ```
282 
283 5.  将相机输入添加到采集会话。
284 
285     ```
286     result = captureSession->AddInput(cameraInput);
287     ```
288 
289 6.  通过 Surface 创建一个视频输出,来与音频合成并保存到文件,Surface 通过 Recoder 获取。如果想仅保存视频缓冲数据到文件里,可以按照拍照流程提到步骤,创建 Surface,注册监听器以监听缓冲区更新。录像的分辨率可以在录制器内配置为所支持的 1280x720 或 640x360 分辨率。
290 
291     ```
292     videoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_YCRCB_420_SP));
293     sptr<CaptureOutput> videoOutput = camManagerObj->CreateVideoOutput(videoSurface);
294     ```
295 
296 7.  将视频输出添加到采集会话。
297 
298     ```
299     result = captureSession->AddOutput(videoOutput);
300     ```
301 
302 8.  将配置提交到采集会话。
303 
304     ```
305     result = captureSession->CommitConfig();
306     ```
307 
308 9.  开始视频录制。
309 
310     ```
311     result = ((sptr<VideoOutput> &)videoOutput)->Start();
312     ```
313 
314 10. 需要时停止录制。
315 
316     ```
317     result = ((sptr<VideoOutput> &)videoOutput)->Stop();
318     ```
319 
320 11. 释放采集会话的资源。
321 
322     ```
323     captureSession->Release();
324     ```
325 
326 12. 释放相机输入关闭相机。
327 
328     ```
329     cameraInput->Release();
330     ```
331 
332 ### 切换多个照相机设备<a name="sectionswitchcamera"></a>
333 
334 以下演示如何切换多个照相机设备。最初在采集会话中有一个视频输出(video output)。如果用户想要切换其他 照相机,现存的相机输入和输出需要先移除并加入新的相机输入和输出(示例中使用的是photo output)。
335 
336 1.  获取相机管理器实例并获取相机对象列表。
337 
338     ```
339     sptr<CameraManager> camManagerObj = CameraManager::GetInstance();
340     std::vector<sptr<CameraInfo>> cameraObjList = camManagerObj->GetCameras();
341     ```
342 
343 2.  使用相机对象创建相机输入来打开相机。
344 
345     ```
346     sptr<CaptureInput> cameraInput = camManagerObj->CreateCameraInput(cameraObjList[0]);
347     ```
348 
349 3.  创建采集会话。
350 
351     ```
352     sptr<CaptureSession> captureSession = camManagerObj->CreateCaptureSession();
353     ```
354 
355 4.  开始配置采集会话。
356 
357     ```
358     int32_t result = captureSession->BeginConfig()
359     ```
360 
361 5.  将相机输入添加到采集会话。
362 
363     ```
364     result = captureSession->AddInput(cameraInput);
365     ```
366 
367 6.  通过Surface创建一个视频输出。
368 
369     ```
370     sptr<CaptureOutput> videoOutput = camManagerObj->CreateVideoOutput(videoSurface);
371     ```
372 
373 7.  将视频输出添加到采集会话。
374 
375     ```
376     result = captureSession->AddOutput(videoOutput);
377     ```
378 
379 8.  将配置提交到采集会话。
380 
381     ```
382     result = captureSession->CommitConfig();
383     ```
384 
385 9.  开始录制视频。
386 
387     ```
388     result = ((sptr<VideoOutput> &)videoOutput)->Start();
389     ```
390 
391 10. 需要时停止录制。
392 
393     ```
394     result = ((sptr<VideoOutput> &)videoOutput)->Stop();
395     ```
396 
397 11. 重新配置会话并移除相机输入和输出。
398 
399     ```
400     int32_t result = captureSession->BeginConfig();
401     ```
402 
403 12. 在新的会话配置中移除相机输入。
404 
405     ```
406     int32_t result = captureSession->RemoveInput(cameraInput);
407     ```
408 
409 13. 同样移除相机输出。
410 
411     ```
412     int32_t result = captureSession->RemoveOutut(videoOutput);
413     ```
414 
415 14. 创建新的相机输入,并把它添加到采集会话。
416 
417     ```
418     sptr<CaptureInput> cameraInput2 = camManagerObj->CreateCameraInput(cameraObjList[1]);
419     result = captureSession->AddInput(cameraInput2);
420     ```
421 
422 15. 创建拍照输出,成功创建后将拍照输出添加到采集会话。创建消费者 Surface 并注册监听器以监听新的拍照输出缓冲区更新。这个 Surface 用于新创建的拍照输出。
423 
424     ```
425     // Get the surface
426     sptr<Surface> photoSurface = Surface::CreateSurfaceAsConsumer();
427     int32_t photoWidth = 1280;
428     int32_t photoHeight = 960;
429     photoSurface->SetDefaultWidthAndHeight(photoWidth, photoHeight);
430     photoSurface->SetUserData(CameraManager::surfaceFormat, std::to_string(OHOS_CAMERA_FORMAT_JPEG));
431     sptr<CaptureSurfaceListener> capturelistener = new(std::nothrow) CaptureSurfaceListener();
432     capturelistener->mode_ = MODE_PHOTO;
433     capturelistener->surface_ = photoSurface;
434     photoSurface->RegisterConsumerListener((sptr<IBufferConsumerListener> &)capturelistener);
435 
436     // Create the Photo Output
437     sptr<CaptureOutput> photoOutput = camManagerObj->CreatePhotoOutput(photoSurface);
438 
439     // Add the output to the capture session
440     result = captureSession->AddOutput(photoOutput);
441     ```
442 
443 16. 将配置提交到采集会话。
444 
445     ```
446     result = captureSession->CommitConfig();
447     ```
448 
449 17. 释放被移出会话的相机输入。
450 
451     ```
452     cameraInput->Release();
453     ```
454 
455 18. 拍摄照片。
456 
457     ```
458     result = ((sptr<PhotoOutput> &)photoOutput)->Capture();
459     ```
460 
461 19. 释放采集会话资源。
462 
463     ```
464     captureSession->Release();
465     ```
466 
467 20. 释放相机输入关闭相机。
468 
469     ```
470     cameraInput2->Release();
471     ```
472 
473 ### 设置闪光灯<a name="sectionsetflash"></a>
474 
475 拍照和录像前可以在相机输入里设置闪光灯。
476 
477 1.  在照相中设置闪光灯。
478 
479     ```
480     cameraInput->LockForControl();
481     cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_OPEN);
482     cameraInput->UnlockForControl();
483     ```
484 
485 2.  在录像中设置闪光灯。
486 
487     ```
488     cameraInput->LockForControl();
489     cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_ALWAYS_OPEN);
490     cameraInput->UnlockForControl();
491     ```
492 
493 3.  关闭闪光灯。
494 
495     ```
496     cameraInput->LockForControl();
497     cameraInput->SetFlashMode(OHOS_CAMERA_FLASH_MODE_CLOSE);
498     cameraInput->UnlockForControl();
499     ```
500 
501 ## 相关仓<a name="section16511040154318"></a>
502 
503 [multimedia\_camera\_framework](https://gitee.com/openharmony/multimedia_camera_framework)
504 
505