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