• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 预览流二次处理(C/C++)
2
3通过ImageReceiver创建预览输出,获取预览流实时数据,以供后续进行图像二次处理,比如应用可以对其添加滤镜算法等。
4
5## 开发步骤
6
7详细的API说明请参考[Camera API参考](../../reference/apis-camera-kit/_o_h___camera.md)。
8
91. 导入NDK接口,接口中提供了相机相关的属性和方法,导入方法如下。
10
11   ```c++
12    // 导入NDK接口头文件
13   #include <cstdlib>
14   #include <hilog/log.h>
15   #include <memory>
16   #include <multimedia/image_framework/image/image_native.h>
17   #include <multimedia/image_framework/image/image_receiver_native.h>
18   #include "ohcamera/camera.h"
19   #include "ohcamera/camera_input.h"
20   #include "ohcamera/capture_session.h"
21   #include "ohcamera/preview_output.h"
22   #include "ohcamera/camera_manager.h"
23   ```
24
252. 在CMake脚本中链接相关动态库。
26
27   ```txt
28   target_link_libraries(entry PUBLIC
29       libace_napi.z.so
30       libhilog_ndk.z.so
31       libohimage.so
32       libimage_receiver.so
33       libnative_image.so
34       libohcamera.so
35   )
36   ```
37
383. 初始化图片接收器[ImageReceiver](../image/image-receiver-c.md)实例,获取SurfaceId。
39
40   通过image的OH_ImageReceiverNative_Create方法创建OH_ImageReceiverNative实例,再通过实例的OH_ImageReceiverNative_GetReceivingSurfaceId方法获取SurfaceId。
41
42   ```c++
43   void InitImageReceiver() {
44       OH_ImageReceiverOptions *options = nullptr;
45       // 注意捕获错误码处理异常及对象判空,当前示例仅展示调用流程
46       // 设置图片参数
47       Image_ErrorCode errCode = OH_ImageReceiverOptions_Create(&options);
48       Image_Size imgSize;
49       imgSize.width = 1080; // 创建预览流的宽
50       imgSize.height = 1080; // 创建预览流的高
51       int32_t capacity = 8; // BufferQueue里最大Image数量,推荐填写8
52       errCode = OH_ImageReceiverOptions_SetSize(options, imgSize);
53       errCode = OH_ImageReceiverOptions_SetCapacity(options, capacity);
54       // 创建OH_ImageReceiverNative对象
55       OH_ImageReceiverNative *receiver = nullptr;
56       errCode = OH_ImageReceiverNative_Create(options, &receiver);
57       // 获取OH_ImageReceiverNative对象的SurfaceId
58       uint64_t receiverSurfaceID = 0;
59       errCode = OH_ImageReceiverNative_GetReceivingSurfaceId(receiver, &receiverSurfaceID);
60       OH_LOG_INFO(LOG_APP, "receiver surfaceID:%{public}%llu", receiverSurfaceID);
61   }
62   ```
63
644. 通过上一步获取到的SurfaceId创建预览流,参考[预览(C/C++)](./native-camera-preview.md)步骤4。
65
665. 创建会话,使能会话,参考[会话管理(C/C++)](./native-camera-session-management.md)。
67
686. 注册ImageReceiver图片接收器的回调,监听获取每帧上报图像内容。
69
70   ```c++
71   OH_ImageReceiverNative *receiver; // 步骤3创建的实例
72
73   // 图像回调函数,参考媒体/Image Kit(图片处理服务)
74   static void OnCallback(OH_ImageReceiverNative *receiver) {
75       OH_LOG_INFO(LOG_APP, "ImageReceiverNativeCTest buffer available.");
76       // 注意捕获错误码处理异常及对象判空,当前示例仅展示调用流程
77       OH_ImageNative *image = nullptr;
78       // 从bufferQueue中获取图像
79       Image_ErrorCode errCode = OH_ImageReceiverNative_ReadNextImage(receiver, &image);
80       // 读取图像宽高
81       Image_Size size;
82       errCode = OH_ImageNative_GetImageSize(image, &size);
83       OH_LOG_INFO(LOG_APP, "OH_ImageNative_GetImageSize errCode:%{public}d width:%{public}d height:%{public}d", errCode,
84           size.width, size.height);
85
86       // 获取图像ComponentType
87       size_t typeSize = 0;
88       OH_ImageNative_GetComponentTypes(image, nullptr, &typeSize);
89       uint32_t* types = new uint32_t[typeSize];
90       OH_ImageNative_GetComponentTypes(image, &types, &typeSize);
91       uint32_t component = types[0];
92       // 获取图像buffer
93       OH_NativeBuffer *imageBuffer = nullptr;
94       errCode = OH_ImageNative_GetByteBuffer(image, component, &imageBuffer);
95       size_t bufferSize = 0;
96       errCode = OH_ImageNative_GetBufferSize(image, component, &bufferSize);
97       OH_LOG_INFO(LOG_APP, "ImageReceiverNativeCTest buffer component: %{public}d size:%{public}zu", component, bufferSize);
98       // 获取图像行距
99       int32_t stride = 0;
100       errCode = OH_ImageNative_GetRowStride(image, component, &stride);
101       OH_LOG_INFO(LOG_APP, "ImageReceiverNativeCTest buffer stride:%{public}d.", stride);
102       void* srcVir = nullptr;
103       OH_NativeBuffer_Map(imageBuffer, &srcVir);
104       uint8_t* srcBuffer = static_cast<uint8_t*>(srcVir);
105       // 判断行距与预览流宽是否一致,如不一致,需要考虑stride对读取buffer的影响
106       if (stride == size.width) {
107           // 传给其他不需要stride的接口处理
108       } else {
109           // 传给其他支持stride的接口处理,或去除stride数据
110           // 去除stride数据示例:将byteBuffer中的数据去除stride,拷贝得到新的dstBuffer数据
111           size_t dstBufferSize = size.width * size.height * 1.5; // 相机预览流返回NV21格式
112           std::unique_ptr<uint8_t[]> dstBuffer = std::make_unique<uint8_t[]>(dstBufferSize);
113           uint8_t *dstPtr = dstBuffer.get();
114           for (int j = 0; j < size.height * 1.5; j++) {
115               memcpy(dstPtr, srcBuffer, size.width);
116               dstPtr += size.width;
117               srcBuffer += stride;
118           }
119           // 传给其他不需要stride的接口处理
120       }
121       // 释放buffer,保证bufferQueue正常轮转
122       OH_NativeBuffer_Unmap(imageBuffer);
123       errCode = OH_ImageNative_Release(image);
124   }
125
126   void OnImageReceiver() {
127       // 注册图像回调事件,监听每帧上报的图像
128       Image_ErrorCode errCode = OH_ImageReceiverNative_On(receiver, OnCallback);
129   }
130   ```