YUV拍照(C/C++)
============

从API version 23开始，相机框架提供YUV格式图片拍照能力。与普通拍照相比，YUV拍照获取到的是未经过编码的图像数据，完整保留了传感器捕获的原始亮度和色度信息，适用于视频编码或专业处理。同时，拍摄过程会产生更高的能耗开销，保存会占用更多的存储空间。

#### 开发步骤

详细的相机功能API说明请参考Camera模块描述[OH\_Camera](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-oh-camera)。

1.  导入NDK接口，接口中提供了相机相关的属性和方法，导入方法如下。
    
    // 导入NDK接口头文件。
    #include <cstdint>
    #include <cstdlib>
    #include <cstring>
    #include <string.h>
    #include <new>
    #include "hilog/log.h"
    #include "multimedia/image\_framework/image/image\_source\_native.h"
    #include "multimedia/image\_framework/image/image\_packer\_native.h"
    #include "multimedia/media\_library/media\_access\_helper\_capi.h"
    #include "multimedia/media\_library/media\_asset\_base\_capi.h"
    #include "multimedia/media\_library/media\_asset\_capi.h"
    #include "multimedia/media\_library/media\_asset\_change\_request\_capi.h"
    #include "multimedia/media\_library/media\_asset\_manager\_capi.h"
    #include "ohcamera/camera.h"
    #include "ohcamera/camera\_input.h"
    #include "ohcamera/camera\_manager.h"
    #include "ohcamera/capture\_session.h"
    #include "ohcamera/photo\_native.h"
    #include "ohcamera/photo\_output.h"
    #include "ohcamera/preview\_output.h"
    #include "ohcamera/video\_output.h"
    
2.  在CMake脚本中链接相关动态库。
    
    target\_link\_libraries(entry PUBLIC
        libace\_napi.z.so
        libhilog\_ndk.z.so
        libnative\_buffer.so
        libohcamera.so
        libohimage.so
        libohfileuri.so
        libmedia\_asset\_manager.so
        libimage\_source.so
        libpixelmap.so
        libimage\_packer.so
        libpicture.so
    )
    
3.  创建并打开相机设备，参考[设备输入(C/C++)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/native-camera-device-input)中的步骤3-4。
    
4.  获取相机设备完整输出能力。
    
    通过[OH\_CameraManager\_GetSupportedFullCameraOutputCapabilityWithSceneMode()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-camera-manager-h#oh_cameramanager_getsupportedfullcameraoutputcapabilitywithscenemode)方法，获取当前设备支持的所有输出流的能力，包含预览流、拍照流、录像流等。输出流在CameraOutputCapability中的各个profile字段中，其中拍照流支持YUV格式。根据相机设备指定模式[Camera\_SceneMode](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-camera-h#camera_scenemode)的不同，需要添加不同类型的输出流。
    
    Camera\_OutputCapability\* GetSupportedFullCameraOutputCapability(Camera\_Manager\* cameraManager, Camera\_Device &camera)
    {
         Camera\_OutputCapability\* cameraOutputCapability = nullptr;
         // 获取相机设备支持的输出流能力。
         const Camera\_Profile\* previewProfile = nullptr;
         const Camera\_Profile\* photoProfile = nullptr;
         Camera\_ErrorCode ret = OH\_CameraManager\_GetSupportedFullCameraOutputCapabilityWithSceneMode(cameraManager, &camera,
             Camera\_SceneMode::NORMAL\_PHOTO, &cameraOutputCapability);
         if (cameraOutputCapability == nullptr || ret != CAMERA\_OK) {
             OH\_LOG\_ERROR(LOG\_APP, "OH\_CameraManager\_GetSupportedCameraOutputCapability failed.");
             return nullptr;
         }
         return cameraOutputCapability;
    }
    
5.  选择设备支持的输出流能力，创建拍照输出流。
    
    通过[OH\_CameraManager\_CreatePhotoOutputWithoutSurface()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-camera-manager-h#oh_cameramanager_createphotooutputwithoutsurface)方法创建拍照输出流。
    
    可以通过[OH\_CameraManager\_GetSupportedFullCameraOutputCapabilityWithSceneMode()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-camera-manager-h#oh_cameramanager_getsupportedfullcameraoutputcapabilitywithscenemode)获取相机在指定模式下支持的完整输出能力cameraOutputCapability，参考步骤2。在cameraOutputCapability的photoProfiles中选择支持YUV格式的profile，作为创建拍照输出流的参数photoProfile。
    
    Camera\_PhotoOutput\* CreatePhotoOutput(Camera\_Manager\* cameraManager, const Camera\_Profile\* photoProfile)
    {
        Camera\_PhotoOutput\* photoOutput = nullptr;
        // 无需传入surfaceId，直接创建拍照流。
        Camera\_ErrorCode ret = OH\_CameraManager\_CreatePhotoOutputWithoutSurface(cameraManager, photoProfile, &photoOutput);
        if (photoOutput == nullptr || ret != CAMERA\_OK) {
            OH\_LOG\_ERROR(LOG\_APP, "OH\_CameraManager\_CreatePhotoOutputWithoutSurface failed.");
        }
        return photoOutput;
    }
    
6.  注册单段式(PhotoAvailable)或分段式(PhotoAssetAvailable)拍照回调，若应用希望快速得到回图，推荐使用[分段式拍照(PhotoAssetAvailable)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/native-camera-deferred-capture)回调。
    
    ![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/8e/v3/IO9xWlwvQFKbNnLSnf62SA/caution_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260612T073516Z&HW-CC-Expire=86400&HW-CC-Sign=38A910ACBF3248C7BB95AAA92F108BC56F87AF05B07B18CC11B980A49F2D75F0)
    
    如果已经注册了PhotoAssetAvailable回调，并且在Session开始之后又注册了PhotoAvailable回调，PhotoAssetAvailable和PhotoAvailable同时注册会导致流被重启，仅PhotoAssetAvailable生效。
    
    *   **单段式拍照（PhotoAvailable）开发流程**：
        
        *   在会话[OH\_CaptureSession\_CommitConfig](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-capture-session-h#oh_capturesession_commitconfig)前注册单段式拍照回调。
        *   在单段式拍照回调函数中获取图片信息，解析出pixelMap数据，做自定义业务处理。
        *   将处理完的pixelMap通过回调传给ArkTS侧，做图片显示或通过安全控件写文件保存图片。
        *   使用完后解注册单段式拍照回调函数。
        
        // 单段式拍照回调函数。
        void OnPhotoAvailable(Camera\_PhotoOutput\* photoOutput, OH\_PhotoNative\* photo)
        {
            OH\_LOG\_INFO(LOG\_APP, "OnPhotoAvailable start!");
            OH\_PictureNative\* picture;
            Camera\_ErrorCode errCode = OH\_PhotoNative\_GetUncompressedImage(photo, &picture);
            if (errCode != CAMERA\_OK || picture == nullptr) {
                OH\_LOG\_ERROR(LOG\_APP, "OH\_PhotoNative\_GetUncompressedImage call failed, errorCode: %{public}d", errCode);
                return;
            }
            OH\_LOG\_INFO(LOG\_APP, "OnPhotoAvailable errCode:%{public}d picture:%{public}p", errCode, picture);
            // 读取OH\_PictureNative中的主图mainPixelMap。
            OH\_PixelmapNative\* mainPixelmap;
            Image\_ErrorCode imageErr = OH\_PictureNative\_GetMainPixelmap(picture, &mainPixelmap);
            if (imageErr != IMAGE\_SUCCESS || mainPixelmap == nullptr) {
                OH\_LOG\_ERROR(LOG\_APP, "OH\_ImageNative\_GetImageSize call failed, errorCode: %{public}d", imageErr);
                return;
            }
            OH\_LOG\_INFO(LOG\_APP, "OH\_PictureNative\_GetMainPixelmap success");
            // 获取主图Pixelmap中所有像素所占用的总字节数。
            uint32\_t byteCount = 0;
            imageErr = OH\_PixelmapNative\_GetByteCount(mainPixelmap, &byteCount);
            OH\_LOG\_INFO(LOG\_APP, "OH\_PixelmapNative\_GetByteCount count:%{public}u", byteCount);
            // 获取主图的图像像素信息。
            OH\_Pixelmap\_ImageInfo\* imageInfo;
            imageErr = OH\_PixelmapNative\_GetImageInfo(mainPixelmap, imageInfo);
            OH\_LOG\_INFO(LOG\_APP, "OH\_PixelmapNative\_GetImageInfo errorCode:%{public}d", imageErr);
        
            uint32\_t width = 0;
            uint32\_t height = 0;
            uint32\_t rowStride = 0;
            int32\_t pixelFormat = PIXEL\_FORMAT::PIXEL\_FORMAT\_UNKNOWN;
            int32\_t alphaMode = PIXELMAP\_ALPHA\_TYPE::PIXELMAP\_ALPHA\_TYPE\_UNKNOWN;
            int32\_t alphaType = PIXELMAP\_ALPHA\_TYPE::PIXELMAP\_ALPHA\_TYPE\_UNKNOWN;
            // 获取主图图像像素信息中的宽度。
            OH\_PixelmapImageInfo\_GetWidth(imageInfo, &width);
            // 获取主图图像像素信息中的高度。
            OH\_PixelmapImageInfo\_GetHeight(imageInfo, &height);
            // 获取主图图像像素信息中的行跨距。
            OH\_PixelmapImageInfo\_GetRowStride(imageInfo, &rowStride);
            // 获取主图图像像素信息中的像素格式。
            OH\_PixelmapImageInfo\_GetPixelFormat(imageInfo, &pixelFormat);
            // 获取主图图像像素信息中的透明通道类型。
            OH\_PixelmapImageInfo\_GetAlphaMode(imageInfo, &alphaMode);
            // 获取主图图像像素信息中的默认的透明通道类型。
            OH\_PixelmapImageInfo\_GetAlphaType(imageInfo, &alphaType);
            OH\_LOG\_INFO(LOG\_APP, "OH\_PixelmapNative\_GetImageInfo width:%{public}u height:%{public}u rowStride:%{public}u pixelFormat:%{public}d alphaMode:%{public}d alphaType:%{public}d", width, height, rowStride, pixelFormat, alphaMode, alphaType);
           // 释放资源。
            OH\_PixelmapNative\_Release(mainPixelmap);
            OH\_PictureNative\_Release(picture);
        }
        
        // 注册单段式拍照回调。
        Camera\_ErrorCode PhotoOutputRegisterPhotoAvailableCallback(Camera\_PhotoOutput\* photoOutput)
        {
            OH\_LOG\_INFO(LOG\_APP, "PhotoOutputRegisterPhotoAvailableCallback start!");
            Camera\_ErrorCode ret = OH\_PhotoOutput\_RegisterPhotoAvailableCallback(photoOutput, OnPhotoAvailable);
            if (ret != CAMERA\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "PhotoOutputRegisterPhotoAvailableCallback failed.");
            }
            OH\_LOG\_INFO(LOG\_APP, "PhotoOutputRegisterPhotoAvailableCallback return with ret code: %{public}d!", ret);
            return ret;
        }
        
        // 解注册单段式拍照回调。
        Camera\_ErrorCode PhotoOutputUnRegisterPhotoAvailableCallback(Camera\_PhotoOutput\* photoOutput)
        {
            OH\_LOG\_INFO(LOG\_APP, "PhotoOutputUnRegisterPhotoAvailableCallback start!");
            Camera\_ErrorCode ret = OH\_PhotoOutput\_UnregisterPhotoAvailableCallback(photoOutput, OnPhotoAvailable);
            if (ret != CAMERA\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "PhotoOutputUnRegisterPhotoAvailableCallback failed.");
            }
            OH\_LOG\_INFO(LOG\_APP, "PhotoOutputUnRegisterPhotoAvailableCallback return with ret code: %{public}d!", ret);
            return ret;
        }
        
    *   **分段式拍照（PhotoAvailable）开发流程**：
        
        *   在会话[OH\_CaptureSession\_CommitConfig](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-capture-session-h#oh_capturesession_commitconfig)前注册分段式拍照回调。
        *   在分段式拍照回调函数中获取图片信息，解析出pixelMap数据，做自定义业务处理。
        *   将处理完的pixelMap通过回调传给ArkTS侧，做图片显示或通过安全控件写文件保存图片。
        *   调用[OH\_PhotoOutput\_Capture](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-photo-output-h#oh_photooutput_capture)拍照后，需要及时调用[OH\_MediaAssetChangeRequest\_SaveCameraPhoto](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-media-asset-change-request-capi-h#oh_mediaassetchangerequest_savecameraphoto)保存图片或[OH\_MediaAssetChangeRequest\_DiscardCameraPhoto](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-media-asset-change-request-capi-h#oh_mediaassetchangerequest_discardcameraphoto)取消保存图片，否则会影响后续图片的拍摄。
        *   使用完后解注册分段式拍照回调函数。
        
        // 声明快速返图回调。
        void OnRequestQuickImageDataPreparedWithDetails(MediaLibrary\_ErrorCode result, MediaLibrary\_RequestId requestId, MediaLibrary\_MediaQuality mediaQuality, MediaLibrary\_MediaContentType type, OH\_ImageSourceNative\* imageSourceNative, OH\_PictureNative\* pictureNative)
        {
            OH\_LOG\_INFO(LOG\_APP, "OnRequestQuickImageDataPreparedWithDetails start!");
            if (!pictureNative && !imageSourceNative) {
                OH\_LOG\_ERROR(LOG\_APP, "OnRequestQuickImageDataPreparedWithDetails, pictureNative and imageSourceNative are null.");
                return;
            } else if (!pictureNative && imageSourceNative) {
                OH\_LOG\_ERROR(LOG\_APP, "OnRequestQuickImageDataPreparedWithDetails, pictureNative is null.");
            } else if (pictureNative && !imageSourceNative) {
                OH\_LOG\_ERROR(LOG\_APP, "OnRequestQuickImageDataPreparedWithDetails, imageSourceNative is null.");
            } else {
                OH\_LOG\_INFO(LOG\_APP, "OnRequestQuickImageDataPreparedWithDetails, pictureNative and imageSourceNative are not null.");
            }
        }
        
        // 分段式拍照回调函数。
        void OnPhotoAssetAvailable(Camera\_PhotoOutput\* photoOutput, OH\_MediaAsset\* mediaAsset)
        {
            OH\_LOG\_INFO(LOG\_APP, "OnPhotoAssetAvailable start!");
            if (mediaAsset == nullptr) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable invalid error, mediaAsset is null.");
                return;
            }
            // 尝试获取mediaAsset中的uri信息。
            const char\* uri = nullptr;
            MediaLibrary\_ErrorCode result = OH\_MediaAsset\_GetUri(mediaAsset, &uri);
            if (uri == nullptr || result != MEDIA\_LIBRARY\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable failed to get uri.");
            }
            // 尝试获取mediaAsset中的displayName信息。
            const char\* displayName = nullptr;
            result = OH\_MediaAsset\_GetDisplayName(mediaAsset, &displayName);
            if (displayName == nullptr || result != MEDIA\_LIBRARY\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable failed to get displayName.");
            }
            // 尝试获取mediaAsset中的size信息。
            uint32\_t mediaAssetSize = 0;
            result = OH\_MediaAsset\_GetSize(mediaAsset, &mediaAssetSize);
            if (result != MEDIA\_LIBRARY\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable failed to get size.");
            }
            // 尝试获取mediaAsset中的修改时间信息。
            uint32\_t modifiedMs = 0;
            result = OH\_MediaAsset\_GetDateModifiedMs(mediaAsset, &modifiedMs);
            if (result != MEDIA\_LIBRARY\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable failed to get modifiedMs.");
            }
            // 尝试获取mediaAsset中的图片宽度信息。
            uint32\_t width = 0;
            result = OH\_MediaAsset\_GetWidth(mediaAsset, &width);
            if (result != MEDIA\_LIBRARY\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable failed to get width.");
            }
            // 尝试获取mediaAsset中的图片高度信息。
            uint32\_t height = 0;
            result = OH\_MediaAsset\_GetHeight(mediaAsset, &height);
            if (result != MEDIA\_LIBRARY\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable failed to get height.");
            }
            // 尝试获取mediaAsset中的图片方向信息。
            uint32\_t orientation = 0;
            result = OH\_MediaAsset\_GetOrientation(mediaAsset, &orientation);
            if (result != MEDIA\_LIBRARY\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable failed to get orientation.");
            }
            // 创建媒体资产管理对象。
            OH\_MediaAssetManager\* mediaAssetManager = OH\_MediaAssetManager\_Create();
            if (mediaAssetManager == nullptr) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable failed to create mediaAssetManager.");
                return;
            }
        
            // 创建媒体资产变更请求。
            OH\_MediaAssetChangeRequest\* changeRequest = OH\_MediaAssetChangeRequest\_Create(mediaAsset);
            if (changeRequest == nullptr) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable failed to create changeRequest.");
            }
            // 注册媒体资产快速请求回调。
            MediaLibrary\_RequestOptions requestOptions;
            requestOptions.deliveryMode = MEDIA\_LIBRARY\_BALANCED\_MODE;
            MediaLibrary\_RequestId requestId;
            result = OH\_MediaAssetManager\_QuickRequestImage(mediaAssetManager, mediaAsset, requestOptions, &requestId, OnRequestQuickImageDataPreparedWithDetails);
            if (result != MEDIA\_LIBRARY\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable failed to quick image.");
            }
            // 创建媒体资产保存变更请求。
            result = OH\_MediaAssetChangeRequest\_SaveCameraPhoto(changeRequest, MediaLibrary\_ImageFileType::MEDIA\_LIBRARY\_IMAGE\_JPEG);
            if (result != MEDIA\_LIBRARY\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable failed to save camera photo.");
            }
            result = OH\_MediaAccessHelper\_ApplyChanges(changeRequest);
            if (result != MEDIA\_LIBRARY\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "OnPhotoAssetAvailable failed to apply changes.");
            }
        }
        
        // 注册分段式拍照回调函数。
        Camera\_ErrorCode RegisterPhotoAssetAvailable(Camera\_PhotoOutput\* photoOutput)
        {
            Camera\_ErrorCode ret = OH\_PhotoOutput\_RegisterPhotoAssetAvailableCallback(photoOutput, OnPhotoAssetAvailable);
            if (ret != CAMERA\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "RegisterPhotoAssetAvailable failed. %d ", ret);
            }
            return ret;
        }
        // 解注册分段式拍照回调函数。
        Camera\_ErrorCode UnregisterPhotoAssetAvailable(Camera\_PhotoOutput\* photoOutput)
        {
            Camera\_ErrorCode ret = OH\_PhotoOutput\_UnregisterPhotoAssetAvailableCallback(photoOutput, OnPhotoAssetAvailable);
            if (ret != CAMERA\_OK) {
                OH\_LOG\_ERROR(LOG\_APP, "UnregisterPhotoAssetAvailable failed. %d ", ret);
            }
            return ret;
        }
        
7.  创建拍照类型会话（参考[会话管理(C/C++)](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/native-camera-session-management)），开启会话，准备拍照。
    
8.  触发拍照。
    
    通过[OH\_PhotoOutput\_Capture()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-photo-output-h#oh_photooutput_capture)方法，执行拍照任务。
    
    Camera\_ErrorCode Capture(Camera\_PhotoOutput\* photoOutput)
    {
        Camera\_ErrorCode ret = OH\_PhotoOutput\_Capture(photoOutput);
        if (ret == CAMERA\_OK) {
            OH\_LOG\_INFO(LOG\_APP, "OH\_PhotoOutput\_Capture success ");
        } else {
            OH\_LOG\_ERROR(LOG\_APP, "OH\_PhotoOutput\_Capture failed. %d ", ret);
        }
        return ret;
    }
    

#### 状态监听

在相机应用开发过程中，可以随时监听拍照输出流状态，包括拍照流开始、拍照帧的开始与结束、拍摄下一张图片是否就绪、拍照输出流的错误。

*   通过注册固定的onFrameStart回调函数获取监听拍照开始结果，当photoOutput创建成功时，即可监听。拍照第一次曝光时触发。
    
    void PhotoOutputOnFrameStart(Camera\_PhotoOutput\* photoOutput)
    {
        OH\_LOG\_INFO(LOG\_APP, "PhotoOutputOnFrameStart");
    }
    void PhotoOutputOnFrameShutter(Camera\_PhotoOutput\* photoOutput, Camera\_FrameShutterInfo\* info)
    {
        OH\_LOG\_INFO(LOG\_APP, "PhotoOutputOnFrameShutter");
    }
    
*   通过注册固定的onFrameEnd回调函数监听拍照结束结果，当photoOutput创建成功时，即可监听。
    
    void PhotoOutputOnFrameEnd(Camera\_PhotoOutput\* photoOutput, int32\_t frameCount)
    {
        OH\_LOG\_INFO(LOG\_APP, "PhotoOutput frameCount = %{public}d", frameCount);
    }
    
*   通过注册固定的captureReady回调函数监听能否继续拍摄下一张的结果，当photoOutput创建成功时，即可监听。当下一张可拍时触发，该事件返回结果为下一张可拍的相关信息。
    
    static bool g\_captureReadyFlag = false;
    void CaptureReadyCb(Camera\_PhotoOutput\* photoOutput) {
      g\_captureReadyFlag = true;
      OH\_LOG\_INFO(LOG\_APP, "PhotoOutputOnCaptureReady captureReadyFlag = %{public}d", g\_captureReadyFlag);
    }
    
    void OnPhotoOutputOnCaptureReady(Camera\_PhotoOutput\* photoOutput)
    {
        OH\_LOG\_INFO(LOG\_APP, "PhotoOutputOnCaptureReady");
        Camera\_ErrorCode ret = OH\_PhotoOutput\_RegisterCaptureReadyCallback(photoOutput, CaptureReadyCb);
    }
    
*   通过注册固定的onError回调函数获取监听拍照输出流的错误结果。callback返回拍照输出接口使用错误时的对应错误码，错误码类型参见[Camera\_ErrorCode](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/capi-camera-h#camera_errorcode)。
    
    void PhotoOutputOnError(Camera\_PhotoOutput\* photoOutput, Camera\_ErrorCode errorCode)
    {
        OH\_LOG\_INFO(LOG\_APP, "PhotoOutput errorCode = %{public}d", errorCode);
    }
    
    PhotoOutput\_Callbacks\* GetPhotoOutputListener()
    {
        static PhotoOutput\_Callbacks photoOutputListener = {
            .onFrameStart = PhotoOutputOnFrameStart,
            .onFrameShutter = PhotoOutputOnFrameShutter,
            .onFrameEnd = PhotoOutputOnFrameEnd,
            .onError = PhotoOutputOnError
        };
        return &photoOutputListener;
    }
    Camera\_ErrorCode RegisterPhotoOutputCallback(Camera\_PhotoOutput\* photoOutput)
    {
        Camera\_ErrorCode ret = OH\_PhotoOutput\_RegisterCallback(photoOutput, GetPhotoOutputListener());
        if (ret != CAMERA\_OK) {
            OH\_LOG\_ERROR(LOG\_APP, "OH\_PhotoOutput\_RegisterCallback failed.");
        }
        return ret;
    }