文档管理中心

分段式拍照(C/C++)

本文导读

分段式拍照是相机的最重要功能之一,相机输出低质量图用作快速显示,提升用户感知拍照速度,同时使用高质量图保证最后的成图质量达到系统相机的水平,既满足了后处理算法的需求,又不阻塞前台的拍照速度,构筑相机性能竞争力,提升了用户的体验。

  • 在第一阶段,系统快速上报轻量处理的图片,轻量处理的图片比全质量图低,出图速度快。应用通过回调会收到一个PhotoAsset对象,通过该对象可调用媒体库接口,读取图片或落盘图片。
  • 在第二阶段,相机框架会根据应用的请求图片诉求或者在系统闲时,进行图像增强处理得到全质量图,将处理好的图片传回给媒体库,替换轻量处理的图片。

开发步骤

详细的API说明请参考OH_Camera

  1. 导入NDK接口,接口中提供了相机相关的属性和方法,导入方法如下。

    收起
    自动换行
    深色代码主题
    复制
    1. #include <cstdint>
    2. #include <unistd.h>
    3. #include <string>
    4. #include <thread>
    5. #include <cstdio>
    6. #include <fcntl.h>
    7. #include <map>
    8. #include <string>
    9. #include <vector>
    10. #include <native_buffer/native_buffer.h>
    11. #include "iostream"
    12. #include "mutex"
    13. #include "hilog/log.h"
    14. #include "ohcamera/camera.h"
    15. #include "ohcamera/camera_input.h"
    16. #include "ohcamera/capture_session.h"
    17. #include "ohcamera/photo_output.h"
    18. #include "ohcamera/preview_output.h"
    19. #include "ohcamera/video_output.h"
    20. #include "napi/native_api.h"
    21. #include "ohcamera/camera_manager.h"
    22. #include "common/log_common.h"
    23. #include "multimedia/image_framework/image/image_native.h"
    24. #include "multimedia/image_framework/image/image_source_native.h"
    25. #include "multimedia/image_framework/image/image_packer_native.h"
    26. #include "multimedia/media_library/media_access_helper_capi.h"
    27. #include "multimedia/media_library/media_asset_base_capi.h"
    28. #include "multimedia/media_library/media_asset_capi.h"
    29. #include "multimedia/media_library/media_asset_change_request_capi.h"
    30. #include "multimedia/media_library/media_asset_manager_capi.h"
    31. #include "multimedia/media_library/moving_photo_capi.h"
    32. #include "ohcamera/photo_native.h"
    33. #include <window_manager/oh_display_info.h>
    34. #include <window_manager/oh_display_manager.h>
  2. 在CMake脚本中链接相关动态库。

    收起
    自动换行
    深色代码主题
    复制
    1. target_link_libraries(entry PUBLIC
    2. libace_napi.z.so
    3. libhilog_ndk.z.so
    4. libohcamera.so
    5. libimage_source.so
    6. libmedia_asset_manager.so
    7. libimage_packer.so
    8. )
  3. 相机初始化及拍照触发参考拍照(C/C++)

  4. 注册分段式(PhotoAssetAvailable)拍照回调,对比单段式拍照,仅注册的拍照回调接口不同。

    注意

    如果已经注册了PhotoAssetAvailable回调,并且在Session开始之后又注册了PhotoAvailable回调,PhotoAssetAvailable和PhotoAvailable同时注册,会导致流被重启,仅PhotoAssetAvailable生效。

    不建议开发者同时注册PhotoAssetAvailable和PhotoAvailable。

    注册PhotoAssetAvailableCallback回调,接收分段式拍照回图示例:

    分段式拍照开发流程(PhotoAssetAvailableCallback)

    • 在会话commitConfig前注册分段式拍照回调。
    • 通过分段式拍照回调,获取媒体库资源mediaAsset。
    • 通过mediaAsset直接落盘图片或者通过mediaAsset配置策略模式请求图像资源,业务处理后通过buffer保存图片,或显示图片(参考拍照(C/C++)步骤5)。
    • 使用完后解注册分段式拍照回调函数。
    收起
    自动换行
    深色代码主题
    复制
    1. // 分段式拍照回调函数。
    2. void onPhotoAssetAvailable(Camera_PhotoOutput *photoOutput, OH_MediaAsset *mediaAsset)
    3. {
    4. if (mediaAsset == nullptr) {
    5. DRAWING_LOGI("onPhotoAssetAvailable mediaAsset is nullptr !");
    6. return;
    7. }
    8. DRAWING_LOGD("onPhotoAssetAvailable start!");
    9. NDKCamera::MediaAssetRelease();
    10. g_mediaAsset = mediaAsset;
    11. NDKCamera::MediaAssetGetUri(mediaAsset);
    12. NDKCamera::MediaAssetGetDisplayName(mediaAsset);
    13. NDKCamera::MediaAssetGetSize(mediaAsset);
    14. NDKCamera::MediaAssetGetDateModifiedMs(mediaAsset);
    15. NDKCamera::MediaAssetGetWidth(mediaAsset);
    16. NDKCamera::MediaAssetGetHeight(mediaAsset);
    17. NDKCamera::MediaAssetGetOrientation(mediaAsset);
    18. NDKCamera::MediaAssetManagerCreate();
    19. NDKCamera::MediaAssetChangeRequest(mediaAsset);
    20. DRAWING_LOGD("onPhotoAssetAvailable finish!");
    21. return;
    22. }
    23. // 注册分段式拍照回调。
    24. Camera_ErrorCode NDKCamera::PhotoOutputRegisterPhotoAssetAvailableCallback(void)
    25. {
    26. DRAWING_LOGD("NDKCamera::PhotoOutputRegisterPhotoAssetAvailableCallback start!");
    27. MediaAssetManagerCreate();
    28. ret_ = OH_PhotoOutput_RegisterPhotoAssetAvailableCallback(photoOutput_, onPhotoAssetAvailable);
    29. if (ret_ != CAMERA_OK) {
    30. DRAWING_LOGD("NDKCamera::PhotoOutputRegisterPhotoAssetAvailableCallback failed.");
    31. }
    32. DRAWING_LOGD(
    33. "NDKCamera::PhotoOutputRegisterPhotoAssetAvailableCallback return with ret code: %{public}d!",
    34. ret_);
    35. return ret_;
    36. }
    37. MediaLibrary_ErrorCode NDKCamera::MediaAssetChangeRequest(OH_MediaAsset *mediaAsset)
    38. {
    39. DRAWING_LOGD("NDKCamera::MediaAssetChangeRequest start!");
    40. MediaAssetChangeRequestCreate(mediaAsset);
    41. MediaAssetManagerRequestImage(mediaAsset);
    42. DRAWING_LOGD("NDKCamera::MediaAssetChangeRequest finish!");
    43. return MEDIA_LIBRARY_OK;
    44. }
    45. MediaLibrary_ErrorCode NDKCamera::MediaAssetChangeRequestCreate(OH_MediaAsset *mediaAsset)
    46. {
    47. DRAWING_LOGD("NDKCamera::MediaAssetChangeRequestCreate start!");
    48. g_changeRequest = OH_MediaAssetChangeRequest_Create(mediaAsset);
    49. if (g_changeRequest == nullptr) {
    50. DRAWING_LOGD("NDKCamera::MediaAssetChangeRequestCreate failed.");
    51. }
    52. return MEDIA_LIBRARY_OK;
    53. }
    54. MediaLibrary_ErrorCode NDKCamera::MediaAssetManagerCreate(void)
    55. {
    56. DRAWING_LOGD("NDKCamera::MediaAssetManagerCreate start!");
    57. mediaAssetManager = OH_MediaAssetManager_Create();
    58. if (mediaAssetManager == nullptr) {
    59. DRAWING_LOGD("NDKCamera::MediaAssetManagerCreate failed.");
    60. }
    61. return MEDIA_LIBRARY_OK;
    62. }
    63. void OnRequestImageDataPreparedWithDetails(MediaLibrary_ErrorCode result, MediaLibrary_RequestId requestId,
    64. MediaLibrary_MediaQuality mediaQuality, MediaLibrary_MediaContentType type, OH_ImageSourceNative *imageSourceNative)
    65. {
    66. auto cb = (void (*)(char *))(g_requestImageCallback);
    67. auto qCb = (void (*)(char *))(g_requestImageQualityCallback);
    68. DRAWING_LOGD("OnRequestImageDataPreparedWithDetails start!");
    69. if (mediaQuality == MediaLibrary_MediaQuality::MEDIA_LIBRARY_QUALITY_FAST) {
    70. DRAWING_LOGD("OnRequestImageDataPreparedWithDetails into fast quality mode!");
    71. g_mediaQualityCb = "fast";
    72. qCb(g_mediaQualityCb);
    73. } else {
    74. DRAWING_LOGD("OnRequestImageDataPreparedWithDetails into high quality mode!");
    75. g_mediaQualityCb = "high";
    76. qCb(g_mediaQualityCb);
    77. }
    78. DRAWING_LOGD("OnRequestImageDataPreparedWithDetails GetUri uri_ = %{public}s", URI);
    79. cb(const_cast<char *>(URI));
    80. NDKCamera::ChangeRequestAddResourceWithBuffer(imageSourceNative);
    81. return;
    82. }
    83. // 请求图片数据:deliveryMode/quality等通过requestOptions控制,完成后进回调OnRequestImageDataPreparedWithDetails。
    84. MediaLibrary_ErrorCode NDKCamera::MediaAssetManagerRequestImage(OH_MediaAsset *mediaAsset)
    85. {
    86. DRAWING_LOGD("NDKCamera::MediaAssetManagerRequestImage start! g_deliveryMode = %{public}d",
    87. g_deliveryMode);
    88. requestOptions.deliveryMode = g_deliveryMode;
    89. result = OH_MediaAssetManager_RequestImage(mediaAssetManager, mediaAsset, requestOptions, &g_requestId,
    90. OnRequestImageDataPreparedWithDetails);
    91. if (result != MEDIA_LIBRARY_OK) {
    92. DRAWING_LOGD("NDKCamera::MediaAssetManagerRequestImage failed.");
    93. }
    94. DRAWING_LOGD("NDKCamera::MediaAssetManagerRequestImage return with ret code: %{public}d!", result);
    95. return result;
    96. }
    97. MediaLibrary_ErrorCode NDKCamera::ChangeRequestAddResourceWithBuffer(OH_ImageSourceNative *imageSourceNative)
    98. {
    99. DRAWING_LOGD("NDKCamera::ChangeRequestAddResourceWithBuffer start!");
    100. size_t bufferSize = BUFFER_SIZE;
    101. char buffer[BUFFER_SIZE];
    102. int fd = open("/data/storage/el2/base/haps/test.jpg", O_RDONLY);
    103. int fr = read(fd, buffer, bufferSize);
    104. if (fr == -1) {
    105. DRAWING_LOGD("NDKCamera::ChangeRequestAddResourceWithBuffer read failed.");
    106. return MEDIA_LIBRARY_OK;
    107. }
    108. if (fr == BUFFER_SIZE) {
    109. DRAWING_LOGD("NDKCamera::ChangeRequestAddResourceWithBuffer read not complete.");
    110. return MEDIA_LIBRARY_OK;
    111. }
    112. result = OH_MediaAssetChangeRequest_AddResourceWithBuffer(g_changeRequest,
    113. MediaLibrary_ResourceType::MEDIA_LIBRARY_IMAGE_RESOURCE, (uint8_t *)buffer, (uint32_t)bufferSize);
    114. if (result != MEDIA_LIBRARY_OK) {
    115. DRAWING_LOGD("NDKCamera::ChangeRequestAddResourceWithBuffer failed.");
    116. DRAWING_LOGD("NDKCamera::ChangeRequestAddResourceWithBuffer failed %{public}d.", result);
    117. return MEDIA_LIBRARY_OK;
    118. }
    119. result = OH_MediaAccessHelper_ApplyChanges(g_changeRequest);
    120. if (result != MEDIA_LIBRARY_OK) {
    121. DRAWING_LOGD(
    122. "NDKCamera::ChangeRequestAddResourceWithBuffer OH_MediaAccessHelper_ApplyChanges failed.");
    123. return MEDIA_LIBRARY_OK;
    124. }
    125. DRAWING_LOGD("NDKCamera::ChangeRequestAddResourceWithBuffer OH_MediaAccessHelper_ApplyChanges return "
    126. "with ret code: %{public}d!",
    127. result);
    128. return result;
    129. }
    130. MediaLibrary_ErrorCode NDKCamera::ChangeRequestSaveCameraPhoto(void)
    131. {
    132. DRAWING_LOGD("NDKCamera::ChangeRequestSaveCameraPhoto start!");
    133. result = OH_MediaAssetChangeRequest_SaveCameraPhoto(g_changeRequest,
    134. MediaLibrary_ImageFileType::MEDIA_LIBRARY_IMAGE_JPEG);
    135. if (result != MEDIA_LIBRARY_OK) {
    136. DRAWING_LOGD(
    137. "NDKCamera::ChangeRequestSaveCameraPhoto OH_MediaAssetChangeRequest_SaveCameraPhoto failed.");
    138. }
    139. DRAWING_LOGD("NDKCamera::ChangeRequestSaveCameraPhoto OH_MediaAssetChangeRequest_SaveCameraPhoto "
    140. "return with ret code: %{public}d!",
    141. result);
    142. result = OH_MediaAccessHelper_ApplyChanges(g_changeRequest);
    143. if (result != MEDIA_LIBRARY_OK) {
    144. DRAWING_LOGD("NDKCamera::ChangeRequestSaveCameraPhoto OH_MediaAccessHelper_ApplyChanges failed.");
    145. }
    146. DRAWING_LOGD("NDKCamera::ChangeRequestSaveCameraPhoto OH_MediaAccessHelper_ApplyChanges return with "
    147. "ret code: %{public}d!",
    148. result);
    149. return result;
    150. }
    151. MediaLibrary_ErrorCode NDKCamera::ChangeRequestDiscardCameraPhoto(void)
    152. {
    153. DRAWING_LOGD("NDKCamera::ChangeRequestDiscardCameraPhoto start!");
    154. result = OH_MediaAssetChangeRequest_DiscardCameraPhoto(g_changeRequest);
    155. if (result != MEDIA_LIBRARY_OK) {
    156. DRAWING_LOGD("NDKCamera::ChangeRequestDiscardCameraPhoto "
    157. "OH_MediaAssetChangeRequest_DiscardCameraPhoto failed.");
    158. }
    159. DRAWING_LOGD("NDKCamera::ChangeRequestDiscardCameraPhoto OH_MediaAssetChangeRequest_DiscardCameraPhoto "
    160. "return with ret code: %{public}d!",
    161. result);
    162. result = OH_MediaAccessHelper_ApplyChanges(g_changeRequest);
    163. if (result != MEDIA_LIBRARY_OK) {
    164. DRAWING_LOGD(
    165. "NDKCamera::ChangeRequestDiscardCameraPhoto OH_MediaAccessHelper_ApplyChanges failed.");
    166. }
    167. DRAWING_LOGD("NDKCamera::ChangeRequestDiscardCameraPhoto OH_MediaAccessHelper_ApplyChanges return with "
    168. "ret code: %{public}d!",
    169. result);
    170. return result;
    171. }
    172. MediaLibrary_ErrorCode NDKCamera::ChangeRequestRelease(void)
    173. {
    174. DRAWING_LOGD("NDKCamera::ChangeRequestRelease start!");
    175. result = OH_MediaAssetChangeRequest_Release(g_changeRequest);
    176. if (result != MEDIA_LIBRARY_OK) {
    177. DRAWING_LOGD("NDKCamera::ChangeRequestRelease failed.");
    178. }
    179. g_changeRequest = nullptr;
    180. DRAWING_LOGD("NDKCamera::ChangeRequestRelease return with ret code: %{public}d!", result);
    181. return result;
    182. }
在 指南 中进行搜索
请输入您想要搜索的关键词