• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "avmetadatahelper_impl.h"
17 
18 #include <sys/stat.h>
19 #include <unistd.h>
20 
21 #include "v1_0/hdr_static_metadata.h"
22 #include "v1_0/buffer_handle_meta_key_type.h"
23 
24 #include "securec.h"
25 #include "image_source.h"
26 #include "i_media_service.h"
27 #include "media_log.h"
28 #include "media_errors.h"
29 #include "scope_guard.h"
30 #include "hisysevent.h"
31 #include "image_type.h"
32 #include "param_wrapper.h"
33 #include "hdr_type.h"
34 #include "metadata_convertor.h"
35 
36 namespace {
37 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_METADATA, "AVMetadatahelperImpl" };
38 constexpr int32_t SCENE_CODE_EFFECTIVE_DURATION_MS = 20000;
39 static constexpr char PERFORMANCE_STATS[] = "PERFORMANCE";
40 static std::atomic<uint32_t> concurrentWorkCount_ = 0;
41 static constexpr uint8_t HIGH_CONCRENT_WORK_NUM = 4;
42 static constexpr int32_t PLANE_Y = 0;
43 static constexpr int32_t PLANE_U = 1;
44 static constexpr uint8_t HDR_PIXEL_SIZE = 2;
45 static constexpr uint8_t SDR_PIXEL_SIZE = 1;
46 constexpr int32_t NUM_180 = 180;
47 static const std::string FILE_DIR_IN_THE_SANDBOX = "/data/storage/el2/base/files/";
48 const std::string DUMP_FILE_NAME_AVBUFFER = "_avbuffer.dat";
49 const std::string DUMP_FILE_NAME_PIXEMAP = "_pixelMap.dat";
50 const std::string DUMP_FILE_NAME_AFTER_SCLAE = "_afterScale.dat";
51 const std::string DUMP_FILE_NAME_AFTER_ROTATE = "_afterRotate.dat";
52 
53 constexpr uint8_t COLORPRIMARIES_OFFSET = 0;
54 constexpr uint8_t TRANSFUNC_OFFSET = 8;
55 constexpr uint8_t MATRIX_OFFSET = 16;
56 constexpr uint8_t RANGE_OFFSET = 21;
57 }
58 
59 namespace OHOS {
60 namespace Media {
61 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
62 static constexpr uint8_t PIXEL_SIZE_HDR_YUV = 3;
63 static std::map<Scene, long> SCENE_CODE_MAP = { { Scene::AV_META_SCENE_CLONE, 1 },
64                                                 { Scene::AV_META_SCENE_BATCH_HANDLE, 2 } };
65 static std::map<Scene, int64_t> SCENE_TIMESTAMP_MAP = { { Scene::AV_META_SCENE_CLONE, 0 },
66                                                         { Scene::AV_META_SCENE_BATCH_HANDLE, 0 } };
67 /*
68  * CM_ColorSpaceType from
69  * {@link ${system_general}/drivers/interface/display/graphic/common/v1_0/CMColorSpace.idl}
70  *
71  * ColorManager::ColorSpaceName from
72  * {@link ${system_general}/foundation/graphic/graphic_2d/utils/color_manager/export/color_space.h}
73  *
74  * maps with #IsHdr()
75  * {@link ${system_general}/foundation/multimedia/image_framework/frameworks/innerkitsimpl/common/src/pixel_map.cpp}
76  */
77 static const std::unordered_map<unsigned int, ColorManager::ColorSpaceName> SDR_COLORSPACE_MAP = {
78     { CM_BT601_EBU_FULL, ColorManager::ColorSpaceName::BT601_EBU },
79     { CM_BT601_EBU_LIMIT, ColorManager::ColorSpaceName::BT601_EBU_LIMIT },
80     { CM_BT601_SMPTE_C_FULL, ColorManager::ColorSpaceName::BT601_SMPTE_C },
81     { CM_BT601_SMPTE_C_LIMIT, ColorManager::ColorSpaceName::BT601_SMPTE_C_LIMIT },
82     { CM_BT709_FULL, ColorManager::ColorSpaceName::BT709 },
83     { CM_BT709_LIMIT, ColorManager::ColorSpaceName::BT709_LIMIT },
84     { CM_SRGB_FULL, ColorManager::ColorSpaceName::SRGB },
85     { CM_SRGB_LIMIT, ColorManager::ColorSpaceName::SRGB_LIMIT },
86     { CM_P3_FULL, ColorManager::ColorSpaceName::DISPLAY_P3 },
87     { CM_P3_LIMIT, ColorManager::ColorSpaceName::DISPLAY_P3_LIMIT },
88     { CM_P3_HLG_FULL, ColorManager::ColorSpaceName::P3_HLG },
89     { CM_P3_HLG_LIMIT, ColorManager::ColorSpaceName::P3_HLG_LIMIT },
90     { CM_P3_PQ_FULL, ColorManager::ColorSpaceName::P3_PQ_LIMIT },
91     { CM_P3_PQ_LIMIT, ColorManager::ColorSpaceName::P3_PQ_LIMIT },
92     { CM_ADOBERGB_FULL, ColorManager::ColorSpaceName::ADOBE_RGB },
93     { CM_ADOBERGB_LIMIT, ColorManager::ColorSpaceName::ADOBE_RGB_LIMIT },
94     { CM_LINEAR_SRGB, ColorManager::ColorSpaceName::LINEAR_SRGB },
95     { CM_LINEAR_BT709, ColorManager::ColorSpaceName::LINEAR_BT709 },
96     { CM_LINEAR_P3, ColorManager::ColorSpaceName::LINEAR_P3 },
97     { CM_LINEAR_BT2020, ColorManager::ColorSpaceName::LINEAR_BT2020 },
98 
99     // sdr pixelMap can use BT2020 color space, but hdr can't use color space except BT2020
100     { CM_BT2020_HLG_FULL, ColorManager::ColorSpaceName::BT2020_HLG },
101     { CM_BT2020_PQ_FULL, ColorManager::ColorSpaceName::BT2020_PQ },
102     { CM_BT2020_HLG_LIMIT, ColorManager::ColorSpaceName::BT2020_HLG_LIMIT },
103     { CM_BT2020_PQ_LIMIT, ColorManager::ColorSpaceName::BT2020_PQ_LIMIT },
104 };
105 
106 static const std::unordered_map<unsigned int, ColorManager::ColorSpaceName> HDR_COLORSPACE_MAP = {
107     { CM_BT2020_HLG_FULL, ColorManager::ColorSpaceName::BT2020_HLG },
108     { CM_BT2020_PQ_FULL, ColorManager::ColorSpaceName::BT2020_PQ },
109     { CM_BT2020_HLG_LIMIT, ColorManager::ColorSpaceName::BT2020_HLG_LIMIT },
110     { CM_BT2020_PQ_LIMIT, ColorManager::ColorSpaceName::BT2020_PQ_LIMIT },
111 };
112 
113 static const std::unordered_map<int32_t, std::pair<bool, bool>> VIDEOORIENTATIONTYPE_FLIP_MAP = {
114     { Plugins::VideoOrientationType::FLIP_H, {true, false} },
115     { Plugins::VideoOrientationType::FLIP_V, {false, true} },
116     { Plugins::VideoOrientationType::FLIP_H_ROT90, {true, false} },
117     { Plugins::VideoOrientationType::FLIP_V_ROT90, {false, true} },
118 };
119 
120 static const std::unordered_map<int32_t, int32_t> VIDEOORIENTATIONTYPE_ROTATION_MAP = {
121     { Plugins::VideoOrientationType::FLIP_H, 0 },
122     { Plugins::VideoOrientationType::FLIP_V, 0 },
123     { Plugins::VideoOrientationType::FLIP_H_ROT90, 270 },
124     { Plugins::VideoOrientationType::FLIP_V_ROT90, 270 },
125 };
126 
127 struct PixelMapMemHolder {
128     bool isShmem;
129     std::shared_ptr<AVSharedMemory> shmem;
130     uint8_t *heap;
131 };
132 
133 struct AVBufferHolder {
134     std::shared_ptr<AVBuffer> buffer;
135 };
136 
FreePixelMapData(void * addr,void * context,uint32_t size)137 static void FreePixelMapData(void *addr, void *context, uint32_t size)
138 {
139     (void)size;
140 
141     MEDIA_LOGD("free pixel map data");
142 
143     CHECK_AND_RETURN_LOG(context != nullptr, "context is nullptr");
144     PixelMapMemHolder *holder = reinterpret_cast<PixelMapMemHolder *>(context);
145     if (holder->isShmem) {
146         if (holder->shmem == nullptr) {
147             MEDIA_LOGE("shmem is nullptr");
148         }
149         holder->shmem = nullptr;
150         holder->heap = nullptr;
151     } else {
152         if (holder->heap == nullptr || holder->heap != addr) {
153             MEDIA_LOGE("heap is invalid");
154         } else {
155             delete [] holder->heap;
156             holder->heap = nullptr;
157         }
158     }
159     delete holder;
160 }
161 
FreeAvBufferData(void * addr,void * context,uint32_t size)162 static void FreeAvBufferData(void *addr, void *context, uint32_t size)
163 {
164     (void)addr;
165     (void)size;
166     CHECK_AND_RETURN_LOG(context != nullptr, "context is nullptr");
167     AVBufferHolder *holder = reinterpret_cast<AVBufferHolder *>(context);
168     delete holder;
169 }
170 
FreeSurfaceBuffer(void * addr,void * context,uint32_t size)171 static void FreeSurfaceBuffer(void *addr, void *context, uint32_t size)
172 {
173     (void)addr;
174     (void)size;
175     CHECK_AND_RETURN_LOG(context != nullptr, "context is nullptr");
176     void* nativeBuffer = context;
177     RefBase *ref = reinterpret_cast<RefBase *>(nativeBuffer);
178     ref->DecStrongRef(ref);
179 }
180 
CreatePixelMapData(const std::shared_ptr<AVSharedMemory> & mem,const OutputFrame & frame)181 static PixelMapMemHolder *CreatePixelMapData(const std::shared_ptr<AVSharedMemory> &mem, const OutputFrame &frame)
182 {
183     PixelMapMemHolder *holder = new (std::nothrow) PixelMapMemHolder;
184     CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "alloc pixelmap mem holder failed");
185 
186     ON_SCOPE_EXIT(0) {
187         delete holder;
188     };
189 
190     int32_t minStride = frame.width_ * frame.bytesPerPixel_;
191     CHECK_AND_RETURN_RET_LOG(minStride <= frame.stride_, nullptr, "stride info wrong");
192 
193     if (frame.stride_ == minStride) {
194         CANCEL_SCOPE_EXIT_GUARD(0);
195         holder->isShmem = true;
196         holder->shmem = mem;
197         holder->heap = frame.GetFlattenedData();
198         return holder;
199     }
200 
201     static constexpr int64_t maxAllowedSize = 100 * 1024 * 1024;
202     int64_t memSize = static_cast<int64_t>(minStride) * frame.height_;
203     CHECK_AND_RETURN_RET_LOG(memSize <= maxAllowedSize, nullptr, "alloc heap size too large");
204 
205     uint8_t *heap = new (std::nothrow) uint8_t[memSize];
206     CHECK_AND_RETURN_RET_LOG(heap != nullptr, nullptr, "alloc heap failed");
207 
208     ON_SCOPE_EXIT(1) {
209         delete [] heap;
210     };
211 
212     uint8_t *currDstPos = heap;
213     uint8_t *currSrcPos = frame.GetFlattenedData();
214     for (int32_t row = 0; row < frame.height_; ++row) {
215         errno_t rc = memcpy_s(currDstPos, static_cast<size_t>(memSize), currSrcPos, static_cast<size_t>(minStride));
216         CHECK_AND_RETURN_RET_LOG(rc == EOK, nullptr, "memcpy_s failed");
217 
218         currDstPos += minStride;
219         currSrcPos += frame.stride_;
220         memSize -= minStride;
221     }
222 
223     holder->isShmem = false;
224     holder->heap = heap;
225 
226     CANCEL_SCOPE_EXIT_GUARD(0);
227     CANCEL_SCOPE_EXIT_GUARD(1);
228     return holder;
229 }
230 
CreateAVBufferHolder(const std::shared_ptr<AVBuffer> & avBuffer)231 static AVBufferHolder *CreateAVBufferHolder(const std::shared_ptr<AVBuffer> &avBuffer)
232 {
233     CHECK_AND_RETURN_RET(avBuffer != nullptr && avBuffer->memory_ != nullptr, nullptr);
234     AVBufferHolder *holder = new (std::nothrow) AVBufferHolder;
235     CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "alloc avBuffer holder failed");
236     holder->buffer = avBuffer;
237     return holder;
238 }
239 
CreatePixelMap(const std::shared_ptr<AVSharedMemory> & mem,PixelFormat color,int32_t & rotation)240 static std::shared_ptr<PixelMap> CreatePixelMap(const std::shared_ptr<AVSharedMemory> &mem, PixelFormat color,
241     int32_t &rotation)
242 {
243     CHECK_AND_RETURN_RET_LOG(mem != nullptr, nullptr, "Fetch frame failed");
244     CHECK_AND_RETURN_RET_LOG(mem->GetBase() != nullptr, nullptr, "Addr is nullptr");
245     CHECK_AND_RETURN_RET_LOG(mem->GetSize() > 0, nullptr, "size is incorrect");
246     CHECK_AND_RETURN_RET_LOG(static_cast<uint32_t>(mem->GetSize()) >= sizeof(OutputFrame),
247                              nullptr, "size is incorrect");
248 
249     OutputFrame *frame = reinterpret_cast<OutputFrame *>(mem->GetBase());
250     MEDIA_LOGD("width: %{public}d, stride : %{public}d, height: %{public}d, size: %{public}d, format: %{public}d",
251         frame->width_, frame->stride_, frame->height_, frame->size_, color);
252 
253     rotation = frame->rotation_;
254     InitializationOptions opts;
255     opts.size.width = frame->width_;
256     opts.size.height = frame->height_;
257     opts.pixelFormat = color;
258     opts.editable = true;
259     std::shared_ptr<PixelMap> pixelMap = PixelMap::Create(opts);
260 
261     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "pixelMap create failed");
262     CHECK_AND_RETURN_RET_LOG(pixelMap->GetByteCount() <= frame->size_, nullptr, "Size inconsistent !");
263 
264     PixelMapMemHolder *holder = CreatePixelMapData(mem, *frame);
265     CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "create pixel map data failed");
266 
267     pixelMap->SetPixelsAddr(holder->heap, holder, static_cast<uint32_t>(pixelMap->GetByteCount()),
268         AllocatorType::CUSTOM_ALLOC, FreePixelMapData);
269     return pixelMap;
270 }
271 
SaveDataToFile(const std::string & fileName,const char * data,const size_t & totalSize)272 int32_t AVMetadataHelperImpl::SaveDataToFile(const std::string &fileName, const char *data, const size_t &totalSize)
273 {
274     CHECK_AND_RETURN_RET_LOG(data != nullptr, MSERR_INVALID_VAL, "data is nullptr");
275     auto rootPath = FILE_DIR_IN_THE_SANDBOX;
276     auto fullPath = rootPath + fileName;
277     char realPath[PATH_MAX] = { 0x00 };
278     CHECK_AND_RETURN_RET((fullPath.length() < PATH_MAX) && (realpath(rootPath.c_str(), realPath) != nullptr),
279                          MSERR_INVALID_VAL);
280     std::string verifiedPath(realPath);
281     std::ofstream outFile(verifiedPath.append("/" + fileName), std::ofstream::out);
282     if (!outFile.is_open()) {
283         MEDIA_LOGI("SaveDataToFile write error, path=%{public}s", verifiedPath.c_str());
284         return MSERR_UNKNOWN;
285     }
286 
287     outFile.write(data, totalSize);
288     return MSERR_OK;
289 }
290 
InitDumpFlag()291 void AVMetadataHelperImpl::InitDumpFlag()
292 {
293     const std::string dumpTag = "sys.media.avmetadatahelper.dump.enable";
294     std::string dumpEnable;
295     int32_t dumpRes = OHOS::system::GetStringParameter(dumpTag, dumpEnable, "false");
296     isDump_ = (dumpEnable == "true");
297     MEDIA_LOGI("get dump flag, dumpRes: %{public}d, isDump_: %{public}d", dumpRes, isDump_);
298 }
299 
DumpPixelMap(bool isDump,std::shared_ptr<PixelMap> pixelMap,const std::string & fileNameSuffix)300 int32_t AVMetadataHelperImpl::DumpPixelMap(bool isDump, std::shared_ptr<PixelMap> pixelMap,
301                                            const std::string &fileNameSuffix)
302 {
303     if (!isDump) {
304         return MSERR_INVALID_VAL;
305     }
306     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, MSERR_INVALID_VAL, "invalid pixelMap");
307     std::string width = std::to_string(pixelMap->GetWidth());
308     std::string height = std::to_string(pixelMap->GetHeight());
309     std::string pixelFormat = pixelFormatToString(pixelMap->GetPixelFormat());
310     auto fileName = GetLocalTime() + "_" + width + "_" + height + "_" + pixelFormat + fileNameSuffix;
311     if (pixelMap->GetAllocatorType() == AllocatorType::DMA_ALLOC) {
312         auto surfaceBuffer = static_cast<SurfaceBuffer*>(pixelMap->GetFd());
313         CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, MSERR_INVALID_VAL, "invalid surface buffer");
314         return SaveDataToFile(fileName,
315                               reinterpret_cast<const char *>(surfaceBuffer->GetVirAddr()),
316                               surfaceBuffer->GetSize());
317     }
318     return SaveDataToFile(fileName,
319                           reinterpret_cast<const char *>(pixelMap->GetPixels()),
320                           pixelMap->GetByteCount());
321 }
322 
DumpAVBuffer(bool isDump,const std::shared_ptr<AVBuffer> & frameBuffer,const std::string & fileNameSuffix)323 int32_t AVMetadataHelperImpl::DumpAVBuffer(bool isDump, const std::shared_ptr<AVBuffer> &frameBuffer,
324                                            const std::string &fileNameSuffix)
325 {
326     if (!isDump) {
327         return MSERR_INVALID_VAL;
328     }
329     bool isValid = frameBuffer != nullptr && frameBuffer->meta_ != nullptr && frameBuffer->memory_ != nullptr;
330     CHECK_AND_RETURN_RET_LOG(isValid, MSERR_INVALID_VAL, "invalid frame buffer");
331     auto bufferMeta = frameBuffer->meta_;
332     int32_t width = 0;
333     int32_t height = 0;
334     bool isHdr = false;
335     bufferMeta->Get<Tag::VIDEO_WIDTH>(width);
336     bufferMeta->Get<Tag::VIDEO_HEIGHT>(height);
337     bufferMeta->Get<Tag::VIDEO_IS_HDR_VIVID>(isHdr);
338     std::string widthStr = std::to_string(width);
339     std::string heightStr = std::to_string(height);
340     std::string pixelFormat = isHdr ? pixelFormatToString(PixelFormat::YCBCR_P010):
341                               pixelFormatToString(PixelFormat::NV12);
342     auto fileName = GetLocalTime() + "_" + widthStr + "_" + heightStr + "_" + pixelFormat + fileNameSuffix;
343     auto surfaceBuffer = frameBuffer->memory_->GetSurfaceBuffer();
344     if (surfaceBuffer == nullptr) {
345         return SaveDataToFile(fileName,
346                               reinterpret_cast<const char *>(frameBuffer->memory_->GetAddr()),
347                               frameBuffer->memory_->GetSize());
348     }
349     return SaveDataToFile(fileName,
350                           reinterpret_cast<const char *>(surfaceBuffer->GetVirAddr()),
351                           surfaceBuffer->GetSize());
352 }
353 
pixelFormatToString(PixelFormat pixelFormat)354 std::string AVMetadataHelperImpl::pixelFormatToString(PixelFormat pixelFormat)
355 {
356     switch (pixelFormat) {
357         case PixelFormat::RGB_565:
358             return "RGB_565";
359         case PixelFormat::RGBA_8888:
360             return "RGBA_8888";
361         case PixelFormat::RGB_888:
362             return "RGB_888";
363         case PixelFormat::NV12:
364             return "NV12";
365         case PixelFormat::YCBCR_P010:
366             return "YCBCR_P010";
367         default:
368             return "UNKNOWN";
369     }
370 }
371 
CreatePixelMapYuv(const std::shared_ptr<AVBuffer> & frameBuffer,PixelMapInfo & pixelMapInfo)372 std::shared_ptr<PixelMap> AVMetadataHelperImpl::CreatePixelMapYuv(const std::shared_ptr<AVBuffer> &frameBuffer,
373                                                                   PixelMapInfo &pixelMapInfo)
374 {
375     bool isValid = frameBuffer != nullptr && frameBuffer->meta_ != nullptr && frameBuffer->memory_ != nullptr;
376     CHECK_AND_RETURN_RET_LOG(isValid, nullptr, "invalid frame buffer");
377     auto bufferMeta = frameBuffer->meta_;
378 
379     int32_t width = 0;
380     auto hasProperty = bufferMeta->Get<Tag::VIDEO_WIDTH>(width);
381     CHECK_AND_RETURN_RET_LOG(hasProperty, nullptr, "invalid width");
382     int32_t height = 0;
383     hasProperty = bufferMeta->Get<Tag::VIDEO_HEIGHT>(height);
384     CHECK_AND_RETURN_RET_LOG(hasProperty, nullptr, "invalid height");
385 
386     Plugins::VideoRotation rotation = Plugins::VideoRotation::VIDEO_ROTATION_0;
387     bufferMeta->Get<Tag::VIDEO_ROTATION>(rotation);
388     pixelMapInfo.rotation = static_cast<int32_t>(rotation);
389 
390     Plugins::VideoOrientationType orientation = Plugins::VideoOrientationType::ROTATE_NONE;
391     bufferMeta->Get<Tag::VIDEO_ORIENTATION_TYPE>(orientation);
392     pixelMapInfo.orientation = static_cast<int32_t>(orientation);
393 
394     bufferMeta->Get<Tag::VIDEO_IS_HDR_VIVID>(pixelMapInfo.isHdr);
395 
396     if (pixelMapInfo.pixelFormat == PixelFormat::UNKNOWN) {
397         pixelMapInfo.pixelFormat = pixelMapInfo.isHdr ? PixelFormat::YCBCR_P010 : PixelFormat::NV12;
398     }
399 
400     if (frameBuffer->memory_->GetSize() != 0 && frameBuffer->memory_->GetSurfaceBuffer() == nullptr) {
401         InitializationOptions options = { .size = { .width = width, .height = height },
402                                           .pixelFormat = PixelFormat::NV12 };
403         return CreatePixelMapFromAVShareMemory(frameBuffer, pixelMapInfo, options);
404     }
405 
406     auto surfaceBuffer = frameBuffer->memory_->GetSurfaceBuffer();
407     CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, nullptr, "srcSurfaceBuffer is nullptr");
408 
409     pixelMapInfo.width = width;
410     pixelMapInfo.height = height;
411     int32_t outputHeight = height;
412     bufferMeta->Get<Tag::VIDEO_SLICE_HEIGHT>(outputHeight);
413     pixelMapInfo.outputHeight = outputHeight;
414     MEDIA_LOGD("pixelMapInfo.outputHeight = %{public}d", pixelMapInfo.outputHeight);
415 
416     return CreatePixelMapFromSurfaceBuffer(surfaceBuffer, pixelMapInfo);
417 }
418 
CreatePixelMapFromAVShareMemory(const std::shared_ptr<AVBuffer> & frameBuffer,PixelMapInfo & pixelMapInfo,InitializationOptions & options)419 std::shared_ptr<PixelMap> AVMetadataHelperImpl::CreatePixelMapFromAVShareMemory(const std::shared_ptr<AVBuffer>
420                                                                                 &frameBuffer,
421                                                                                 PixelMapInfo &pixelMapInfo,
422                                                                                 InitializationOptions &options)
423 {
424     bool isValid = frameBuffer != nullptr && frameBuffer->memory_ != nullptr;
425     CHECK_AND_RETURN_RET_LOG(isValid, nullptr, "invalid frame buffer");
426     std::shared_ptr<PixelMap> pixelMap = PixelMap::Create(options);
427     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Create pixelMap failed");
428     AVBufferHolder *holder = CreateAVBufferHolder(frameBuffer);
429     CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "Create buffer holder failed");
430     uint8_t *pixelAddr = frameBuffer->memory_->GetAddr();
431     pixelMap->SetPixelsAddr(pixelAddr, holder, pixelMap->GetByteCount(),
432                             AllocatorType::CUSTOM_ALLOC, FreeAvBufferData);
433     const InitializationOptions opts = { .size = { .width = pixelMap->GetWidth(),
434                                                    .height = pixelMap->GetHeight() },
435                                          .srcPixelFormat = PixelFormat::NV12,
436                                          .pixelFormat = pixelMapInfo.pixelFormat };
437     pixelMap = PixelMap::Create(reinterpret_cast<const uint32_t *>(pixelMap->GetPixels()),
438                                 pixelMap->GetByteCount(), opts);
439     sptr<SurfaceBuffer> surfaceBuffer = nullptr;
440     SetPixelMapYuvInfo(surfaceBuffer, pixelMap, pixelMapInfo, false);
441     return pixelMap;
442 }
443 
FormatColorSpaceInfo(CM_ColorSpaceInfo & colorSpaceInfo)444 void AVMetadataHelperImpl::FormatColorSpaceInfo(CM_ColorSpaceInfo &colorSpaceInfo)
445 {
446     switch (colorSpaceInfo.primaries) {
447         case CM_ColorPrimaries::COLORPRIMARIES_P3_D65:
448             if (colorSpaceInfo.matrix == CM_Matrix::MATRIX_BT601_P) {
449                 colorSpaceInfo.matrix = CM_Matrix::MATRIX_P3; // MATRIX_P3 equals MATRIX_BT601_P and MATRIX_BT601_N
450             }
451             break;
452         case CM_ColorPrimaries::COLORPRIMARIES_BT601_P:
453             if (colorSpaceInfo.matrix == CM_Matrix::MATRIX_BT601_N || colorSpaceInfo.matrix == CM_Matrix::MATRIX_P3) {
454                 colorSpaceInfo.matrix = CM_Matrix::MATRIX_BT601_P; // MATRIX_P3 equals MATRIX_BT601_P and MATRIX_BT601_N
455             }
456             break;
457         default:
458             break;
459     }
460 }
461 
GetColorSpace(sptr<SurfaceBuffer> & surfaceBuffer,PixelMapInfo & pixelMapInfo)462 Status AVMetadataHelperImpl::GetColorSpace(sptr<SurfaceBuffer> &surfaceBuffer, PixelMapInfo &pixelMapInfo)
463 {
464     std::vector<uint8_t> colorSpaceInfoVec;
465     if (surfaceBuffer->GetMetadata(ATTRKEY_COLORSPACE_INFO, colorSpaceInfoVec) != GSERROR_OK) {
466         MEDIA_LOGW("cant find colorSpace");
467         return Status::ERROR_UNKNOWN;
468     }
469     CHECK_AND_RETURN_RET_LOG(!colorSpaceInfoVec.empty(), Status::ERROR_UNKNOWN, "colorSpaceInfoVec is empty");
470     auto outColor = reinterpret_cast<CM_ColorSpaceInfo *>(colorSpaceInfoVec.data());
471     CHECK_AND_RETURN_RET_LOG(outColor != nullptr, Status::ERROR_UNKNOWN, "colorSpaceInfoVec init failed");
472     auto colorSpaceInfo = outColor[0];
473     FormatColorSpaceInfo(colorSpaceInfo);
474     pixelMapInfo.srcRange = colorSpaceInfo.range == CM_Range::RANGE_FULL ? 1 : 0;
475     auto type = ((static_cast<unsigned int>(colorSpaceInfo.primaries) << COLORPRIMARIES_OFFSET) +
476                  (static_cast<unsigned int>(colorSpaceInfo.transfunc) << TRANSFUNC_OFFSET) +
477                  (static_cast<unsigned int>(colorSpaceInfo.matrix) << MATRIX_OFFSET) +
478                  (static_cast<unsigned int>(colorSpaceInfo.range) << RANGE_OFFSET));
479     pixelMapInfo.primaries = colorSpaceInfo.primaries;
480     MEDIA_LOGI("colorSpaceType is %{public}u", type);
481     if (pixelMapInfo.isHdr) {
482         auto it = HDR_COLORSPACE_MAP.find(type);
483         CHECK_AND_RETURN_RET_LOG(it != HDR_COLORSPACE_MAP.end(), Status::ERROR_UNKNOWN,
484             "can't find mapped colorSpace name in hdr map");
485         pixelMapInfo.colorSpaceName = it->second;
486         return Status::OK;
487     }
488     auto it = SDR_COLORSPACE_MAP.find(type);
489     CHECK_AND_RETURN_RET_LOG(it != SDR_COLORSPACE_MAP.end(), Status::ERROR_UNKNOWN,
490         "can't find mapped colorSpace name in sdr map");
491     pixelMapInfo.colorSpaceName = it->second;
492     return Status::OK;
493 }
494 
CreatePixelMapFromSurfaceBuffer(sptr<SurfaceBuffer> & surfaceBuffer,PixelMapInfo & pixelMapInfo)495 std::shared_ptr<PixelMap> AVMetadataHelperImpl::CreatePixelMapFromSurfaceBuffer(sptr<SurfaceBuffer> &surfaceBuffer,
496                                                                                 PixelMapInfo &pixelMapInfo)
497 {
498     CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, nullptr, "surfaceBuffer is nullptr");
499     auto getColorSpaceInfoRes = GetColorSpace(surfaceBuffer, pixelMapInfo);
500     InitializationOptions options = { .size = { .width = pixelMapInfo.width,
501                                                 .height = pixelMapInfo.height } };
502     bool isHdr = pixelMapInfo.isHdr;
503     options.srcPixelFormat = isHdr ? PixelFormat::YCBCR_P010 : PixelFormat::NV12;
504     options.pixelFormat = isHdr ? PixelFormat::YCBCR_P010 : PixelFormat::NV12;
505     options.useDMA = isHdr;
506     bool needModifyStride = false;
507     options.convertColorSpace.srcRange = pixelMapInfo.srcRange;
508     int32_t colorLength = pixelMapInfo.width * pixelMapInfo.height * PIXEL_SIZE_HDR_YUV;
509     colorLength = isHdr ? colorLength : colorLength / HDR_PIXEL_SIZE;
510     std::shared_ptr<PixelMap> pixelMap;
511 
512     if (!options.useDMA) {
513         pixelMap = PixelMap::Create(options);
514         CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Create pixelMap failed");
515         auto ret = CopySurfaceBufferToPixelMap(surfaceBuffer, pixelMap, pixelMapInfo);
516         CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "CopySurfaceBufferToPixelMap failed");
517         options.pixelFormat = pixelMapInfo.pixelFormat;
518         int32_t primaries = pixelMapInfo.primaries;
519         options.convertColorSpace.srcYuvConversion = primaries == CM_ColorPrimaries::COLORPRIMARIES_BT709 ?
520             YuvConversion::BT709 : YuvConversion::BT601;
521         options.convertColorSpace.dstYuvConversion = primaries == CM_ColorPrimaries::COLORPRIMARIES_BT709 ?
522             YuvConversion::BT709 : YuvConversion::BT601;
523         MEDIA_LOGD("conversion: %{public}d", options.convertColorSpace.srcYuvConversion);
524         pixelMap = PixelMap::Create(reinterpret_cast<const uint32_t *>(pixelMap->GetPixels()),
525                                     pixelMap->GetByteCount(), options);
526         CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Create non-DMA pixelMap failed");
527         pixelMap->InnerSetColorSpace(OHOS::ColorManager::ColorSpace(
528             getColorSpaceInfoRes == Status::OK ? pixelMapInfo.colorSpaceName : ColorManager::SRGB));
529     } else {
530         pixelMap = PixelMap::Create(reinterpret_cast<const uint32_t *>(surfaceBuffer->GetVirAddr()),
531                                     static_cast<uint32_t>(colorLength), options);
532         CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Create DMA pixelMap failed");
533         void* nativeBuffer = surfaceBuffer.GetRefPtr();
534         RefBase *ref = reinterpret_cast<RefBase *>(nativeBuffer);
535         ref->IncStrongRef(ref);
536         if (isHdr) {
537             pixelMap->SetHdrType(ImageHdrType::HDR_VIVID_SINGLE);
538             pixelMap->InnerSetColorSpace(OHOS::ColorManager::ColorSpace(
539                 getColorSpaceInfoRes == Status::OK ? pixelMapInfo.colorSpaceName : ColorManager::BT2020_HLG));
540         }
541         pixelMap->SetPixelsAddr(surfaceBuffer->GetVirAddr(), surfaceBuffer.GetRefPtr(), surfaceBuffer->GetSize(),
542                                 AllocatorType::DMA_ALLOC, FreeSurfaceBuffer);
543         needModifyStride = true;
544     }
545 
546     SetPixelMapYuvInfo(surfaceBuffer, pixelMap, pixelMapInfo, needModifyStride);
547 
548     return pixelMap;
549 }
550 
CopySurfaceBufferToPixelMap(sptr<SurfaceBuffer> & surfaceBuffer,std::shared_ptr<PixelMap> pixelMap,PixelMapInfo & pixelMapInfo)551 int32_t AVMetadataHelperImpl::CopySurfaceBufferToPixelMap(sptr<SurfaceBuffer> &surfaceBuffer,
552                                                           std::shared_ptr<PixelMap> pixelMap,
553                                                           PixelMapInfo &pixelMapInfo)
554 {
555     CHECK_AND_RETURN_RET(surfaceBuffer != nullptr && pixelMap != nullptr, MSERR_INVALID_VAL);
556     int32_t width = surfaceBuffer->GetWidth();
557     int32_t height = surfaceBuffer->GetHeight();
558     int32_t stride = surfaceBuffer->GetStride();
559 
560     CHECK_AND_RETURN_RET(width > 0 && height > 0 && stride > 0, MSERR_INVALID_VAL);
561 
562     static int32_t uvDivBase = 2;
563     CHECK_AND_RETURN_RET(INT64_MAX - (static_cast<int64_t>(stride) * pixelMapInfo.outputHeight)
564         >= static_cast<int64_t>(stride) * height / uvDivBase, MSERR_INVALID_VAL);
565     int64_t copySrcSize = std::max(static_cast<int64_t>(stride) * height,
566         static_cast<int64_t>(stride) * pixelMapInfo.outputHeight + static_cast<int64_t>(stride) * height / uvDivBase);
567     CHECK_AND_RETURN_RET(static_cast<int64_t>(surfaceBuffer->GetSize()) >= copySrcSize, MSERR_INVALID_VAL);
568 
569     CHECK_AND_RETURN_RET(INT64_MAX - (static_cast<int64_t>(width) * height) >=
570         static_cast<int64_t>(width) * height / uvDivBase, MSERR_INVALID_VAL);
571     int64_t copyDstSize = static_cast<int64_t>(width) * height + static_cast<int64_t>(width) * height / uvDivBase;
572     CHECK_AND_RETURN_RET(static_cast<int64_t>(pixelMap->GetCapacity()) >= copyDstSize, MSERR_INVALID_VAL);
573 
574     uint8_t *srcPtr = static_cast<uint8_t *>(surfaceBuffer->GetVirAddr());
575     uint8_t *dstPtr = const_cast<uint8_t *>(pixelMap->GetPixels());
576         // copy src Y component to dst
577     int32_t lineByteCount = width;
578     for (int32_t y = 0; y < height; y++) {
579         auto ret = memcpy_s(dstPtr, lineByteCount, srcPtr, lineByteCount);
580         TRUE_LOG(ret != EOK, MEDIA_LOGW, "Memcpy Y component failed.");
581         srcPtr += stride;
582         dstPtr += lineByteCount;
583     }
584 
585     srcPtr = static_cast<uint8_t *>(surfaceBuffer->GetVirAddr()) + stride * pixelMapInfo.outputHeight;
586 
587     // copy src UV component to dst, height(UV) = height(Y) / 2
588     for (int32_t uv = 0; uv < height / 2; uv++) {
589         auto ret = memcpy_s(dstPtr, lineByteCount, srcPtr, lineByteCount);
590         TRUE_LOG(ret != EOK, MEDIA_LOGW, "Memcpy UV component failed.");
591         srcPtr += stride;
592         dstPtr += lineByteCount;
593     }
594     return MSERR_OK;
595 }
596 
SetPixelMapYuvInfo(sptr<SurfaceBuffer> & surfaceBuffer,std::shared_ptr<PixelMap> pixelMap,PixelMapInfo & pixelMapInfo,bool needModifyStride)597 void AVMetadataHelperImpl::SetPixelMapYuvInfo(sptr<SurfaceBuffer> &surfaceBuffer, std::shared_ptr<PixelMap> pixelMap,
598                                               PixelMapInfo &pixelMapInfo, bool needModifyStride)
599 {
600     CHECK_AND_RETURN_LOG(pixelMap != nullptr, "invalid pixelMap");
601     uint8_t ratio = pixelMapInfo.isHdr ? HDR_PIXEL_SIZE : SDR_PIXEL_SIZE;
602     int32_t srcWidth = pixelMap->GetWidth();
603     int32_t srcHeight = pixelMap->GetHeight();
604     YUVDataInfo yuvDataInfo = { .yWidth = srcWidth,
605                                 .yHeight = srcHeight,
606                                 .uvWidth = srcWidth / 2,
607                                 .uvHeight = srcHeight / 2,
608                                 .yStride = srcWidth,
609                                 .uvStride = srcWidth,
610                                 .uvOffset = srcWidth * srcHeight};
611 
612     if (surfaceBuffer == nullptr || !needModifyStride) {
613         pixelMap->SetImageYUVInfo(yuvDataInfo);
614         return;
615     }
616     OH_NativeBuffer_Planes *planes = nullptr;
617     GSError retVal = surfaceBuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
618     if (retVal != OHOS::GSERROR_OK || planes == nullptr) {
619         pixelMap->SetImageYUVInfo(yuvDataInfo);
620         return;
621     }
622 
623     yuvDataInfo.yStride = planes->planes[PLANE_Y].columnStride / ratio;
624     yuvDataInfo.uvStride = planes->planes[PLANE_U].columnStride / ratio;
625     yuvDataInfo.yOffset = planes->planes[PLANE_Y].offset / ratio;
626     yuvDataInfo.uvOffset = planes->planes[PLANE_U].offset / ratio;
627 
628     pixelMap->SetImageYUVInfo(yuvDataInfo);
629 }
630 
CreateAVMetadataHelper()631 std::shared_ptr<AVMetadataHelper> AVMetadataHelperFactory::CreateAVMetadataHelper()
632 {
633     std::shared_ptr<AVMetadataHelperImpl> impl = std::make_shared<AVMetadataHelperImpl>();
634     CHECK_AND_RETURN_RET_LOG(impl != nullptr, nullptr, "failed to new AVMetadataHelperImpl");
635 
636     int32_t ret = impl->Init();
637     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "failed to init AVMetadataHelperImpl");
638 
639     return impl;
640 }
641 
Init()642 int32_t AVMetadataHelperImpl::Init()
643 {
644     avMetadataHelperService_ = MediaServiceFactory::GetInstance().CreateAVMetadataHelperService();
645     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
646         "failed to create avmetadatahelper service");
647     InitDumpFlag();
648     return MSERR_OK;
649 }
650 
AVMetadataHelperImpl()651 AVMetadataHelperImpl::AVMetadataHelperImpl()
652 {
653     MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
654 }
655 
~AVMetadataHelperImpl()656 AVMetadataHelperImpl::~AVMetadataHelperImpl()
657 {
658     if (avMetadataHelperService_ != nullptr) {
659         (void)MediaServiceFactory::GetInstance().DestroyAVMetadataHelperService(avMetadataHelperService_);
660         avMetadataHelperService_ = nullptr;
661     }
662     MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
663 }
664 
SetHelperCallback(const std::shared_ptr<HelperCallback> & callback)665 int32_t AVMetadataHelperImpl::SetHelperCallback(const std::shared_ptr<HelperCallback> &callback)
666 {
667     MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " SetHelperCallback in", FAKE_POINTER(this));
668     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_SERVICE_DIED,
669         "metadata helper service does not exist..");
670     CHECK_AND_RETURN_RET_LOG(callback != nullptr, MSERR_INVALID_VAL, "callback is nullptr");
671     return avMetadataHelperService_->SetHelperCallback(callback);
672 }
673 
SetScene(Scene scene)674 void AVMetadataHelperImpl::SetScene(Scene scene)
675 {
676     ReportSceneCode(scene);
677 }
678 
ReportSceneCode(Scene scene)679 void AVMetadataHelperImpl::ReportSceneCode(Scene scene)
680 {
681     if (scene != Scene::AV_META_SCENE_CLONE && scene != Scene::AV_META_SCENE_BATCH_HANDLE) {
682         return;
683     }
684     if (scene == Scene::AV_META_SCENE_BATCH_HANDLE && concurrentWorkCount_ < HIGH_CONCRENT_WORK_NUM) {
685         return;
686     }
687     auto sceneCode = SCENE_CODE_MAP[scene];
688     auto lastTsp = SCENE_TIMESTAMP_MAP[scene];
689     auto now =
690         std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
691     auto duration = now - std::chrono::milliseconds(lastTsp);
692     if (duration < std::chrono::milliseconds(SCENE_CODE_EFFECTIVE_DURATION_MS)) {
693         return;
694     }
695     SCENE_TIMESTAMP_MAP[scene] = now.count();
696     MEDIA_LOGI("Report scene code %{public}ld", sceneCode);
697     int32_t ret = HiSysEventWrite(
698         PERFORMANCE_STATS, "CPU_SCENE_ENTRY", OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "PACKAGE_NAME",
699         "media_service", "SCENE_ID", std::to_string(sceneCode).c_str(), "HAPPEN_TIME", now.count());
700     if (ret != MSERR_OK) {
701         MEDIA_LOGW("report error");
702     }
703 }
704 
SetSource(const std::string & uri,int32_t usage)705 int32_t AVMetadataHelperImpl::SetSource(const std::string &uri, int32_t usage)
706 {
707     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
708         "avmetadatahelper service does not exist..");
709     CHECK_AND_RETURN_RET_LOG(!uri.empty(), MSERR_INVALID_VAL, "uri is empty.");
710 
711     concurrentWorkCount_++;
712     ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
713     auto res = avMetadataHelperService_->SetSource(uri, usage);
714     concurrentWorkCount_--;
715     return res;
716 }
717 
SetAVMetadataCaller(AVMetadataCaller caller)718 int32_t AVMetadataHelperImpl::SetAVMetadataCaller(AVMetadataCaller caller)
719 {
720     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
721         "avmetadatahelper service does not exist..");
722     return avMetadataHelperService_->SetAVMetadataCaller(caller);
723 }
724 
SetUrlSource(const std::string & uri,const std::map<std::string,std::string> & header)725 int32_t AVMetadataHelperImpl::SetUrlSource(const std::string &uri, const std::map<std::string, std::string> &header)
726 {
727     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
728         "avmetadatahelper service does not exist..");
729     CHECK_AND_RETURN_RET_LOG(!uri.empty(), MSERR_INVALID_VAL, "uri is empty.");
730     CHECK_AND_RETURN_RET_LOG((uri.find("http://") == 0 || uri.find("https://") == 0),
731         MSERR_INVALID_VAL, "uri is error.");
732     concurrentWorkCount_++;
733     ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
734     auto res = avMetadataHelperService_->SetUrlSource(uri, header);
735     concurrentWorkCount_--;
736     return res;
737 }
738 
SetSource(int32_t fd,int64_t offset,int64_t size,int32_t usage)739 int32_t AVMetadataHelperImpl::SetSource(int32_t fd, int64_t offset, int64_t size, int32_t usage)
740 {
741     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
742         "avmetadatahelper service does not exist..");
743     MEDIA_LOGI("Set file source fd: %{public}d, offset: %{public}" PRIu64 ", size: %{public}" PRIu64,
744         fd, offset, size);
745     CHECK_AND_RETURN_RET_LOG(fd > 0 && offset >= 0 && size >= -1, MSERR_INVALID_VAL,
746         "invalid param");
747 
748     concurrentWorkCount_++;
749     ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
750     auto res = avMetadataHelperService_->SetSource(fd, offset, size, usage);
751     concurrentWorkCount_--;
752     return res;
753 }
754 
SetSource(const std::shared_ptr<IMediaDataSource> & dataSrc)755 int32_t AVMetadataHelperImpl::SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)
756 {
757     MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " SetSource in(dataSrc)", FAKE_POINTER(this));
758     CHECK_AND_RETURN_RET_LOG(dataSrc != nullptr, MSERR_INVALID_VAL, "failed to create data source");
759 
760     concurrentWorkCount_++;
761     ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
762     auto res = avMetadataHelperService_->SetSource(dataSrc);
763     concurrentWorkCount_--;
764     return res;
765 }
766 
ResolveMetadata(int32_t key)767 std::string AVMetadataHelperImpl::ResolveMetadata(int32_t key)
768 {
769     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, "",
770         "avmetadatahelper service does not exist.");
771     concurrentWorkCount_++;
772     auto res = avMetadataHelperService_->ResolveMetadata(key);
773     concurrentWorkCount_--;
774     return res;
775 }
776 
ResolveMetadata()777 std::unordered_map<int32_t, std::string> AVMetadataHelperImpl::ResolveMetadata()
778 {
779     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, {},
780         "avmetadatahelper service does not exist.");
781     concurrentWorkCount_++;
782     auto res = avMetadataHelperService_->ResolveMetadata();
783     concurrentWorkCount_--;
784     return res;
785 }
786 
GetAVMetadata()787 std::shared_ptr<Meta> AVMetadataHelperImpl::GetAVMetadata()
788 {
789     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
790         "avmetadatahelper service does not exist.");
791     concurrentWorkCount_++;
792     auto res = avMetadataHelperService_->GetAVMetadata();
793     concurrentWorkCount_--;
794     return res;
795 }
796 
FetchArtPicture()797 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchArtPicture()
798 {
799     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
800         "avmetadatahelper service does not exist.");
801     concurrentWorkCount_++;
802     auto res = avMetadataHelperService_->FetchArtPicture();
803     concurrentWorkCount_--;
804     return res;
805 }
806 
FetchFrameAtTime(int64_t timeUs,int32_t option,const PixelMapParams & param)807 std::shared_ptr<PixelMap> AVMetadataHelperImpl::FetchFrameAtTime(
808     int64_t timeUs, int32_t option, const PixelMapParams &param)
809 {
810     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
811         "avmetadatahelper service does not exist.");
812 
813     concurrentWorkCount_++;
814     ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
815 
816     OutputConfiguration config;
817     config.colorFormat = param.colorFormat;
818     config.dstHeight = param.dstHeight;
819     config.dstWidth = param.dstWidth;
820 
821     auto mem = avMetadataHelperService_->FetchFrameAtTime(timeUs, option, config);
822     auto pixelMap = CreatePixelMap(mem, PixelFormat::NV12, rotation_);
823 
824     concurrentWorkCount_--;
825 
826     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "pixelMap does not exist.");
827 
828     const InitializationOptions opts = { .size = { .width = pixelMap->GetWidth(), .height = pixelMap->GetHeight() },
829                                          .srcPixelFormat = PixelFormat::NV12 };
830     pixelMap =
831         PixelMap::Create(reinterpret_cast<const uint32_t *>(pixelMap->GetPixels()), pixelMap->GetByteCount(), opts);
832     if (pixelMap == nullptr) {
833         return nullptr;
834     }
835     if (rotation_ > 0) {
836         pixelMap->rotate(rotation_);
837     }
838     int32_t srcWidth = pixelMap->GetWidth();
839     int32_t srcHeight = pixelMap->GetHeight();
840     bool needScale = (param.dstWidth > 0 && param.dstHeight > 0) &&
841                      (param.dstWidth <= srcWidth && param.dstHeight <= srcHeight) &&
842                      (param.dstWidth < srcWidth || param.dstHeight < srcHeight) && srcWidth > 0 && srcHeight > 0;
843     if (needScale) {
844         pixelMap->scale((1.0f * param.dstWidth) / srcWidth, (1.0f * param.dstHeight) / srcHeight);
845     }
846     return pixelMap;
847 }
848 
ScalePixelMapWithEqualRatio(std::shared_ptr<PixelMap> & pixelMap,PixelMapInfo & info,const PixelMapParams & param)849 void AVMetadataHelperImpl::ScalePixelMapWithEqualRatio(
850     std::shared_ptr<PixelMap> &pixelMap, PixelMapInfo &info, const PixelMapParams &param)
851 {
852     CHECK_AND_RETURN_LOG(pixelMap != nullptr, "pixelMap is nullptr");
853     int32_t srcWidth = pixelMap->GetWidth();
854     int32_t srcHeight = pixelMap->GetHeight();
855     int32_t dstWidth = info.rotation % NUM_180 == 0 ? param.dstWidth : param.dstHeight;
856     int32_t dstHeight = info.rotation % NUM_180 == 0 ? param.dstHeight : param.dstWidth;
857 
858     bool needScale = (dstWidth > 0 || dstHeight > 0) && (srcWidth > 0 && srcHeight > 0) &&
859         (dstWidth <= srcWidth && dstHeight <= srcHeight) && (dstWidth < srcWidth || dstHeight < srcHeight);
860     CHECK_AND_RETURN(needScale);
861 
862     float widthFactor = dstWidth > 0 ? (1.0f * dstWidth) / srcWidth : 1.0f;
863     float heightFactor = dstHeight > 0 ? (1.0f * dstHeight) / srcHeight : 1.0f;
864 
865     if (dstWidth == 0) {
866         widthFactor = heightFactor;
867     } else if (dstHeight == 0) {
868         heightFactor = widthFactor;
869     }
870     pixelMap->scale(widthFactor, heightFactor, AntiAliasingOption::LOW);
871     MEDIA_LOGI("srcWidth: %{public}d, srcHeight : %{public}d, dstWidth: %{public}d, dstHeight: %{public}d,"
872         "widthFactor: %{public}f, HeightFactor: %{public}f, finalWidth: %{public}d, finalHeight : %{public}d",
873         srcWidth, srcHeight, dstWidth, dstHeight, widthFactor, heightFactor,
874         pixelMap->GetWidth(), pixelMap->GetHeight());
875 }
876 
ScalePixelMap(std::shared_ptr<PixelMap> & pixelMap,PixelMapInfo & info,const PixelMapParams & param)877 void AVMetadataHelperImpl::ScalePixelMap(
878     std::shared_ptr<PixelMap> &pixelMap, PixelMapInfo &info, const PixelMapParams &param)
879 {
880     int32_t srcWidth = pixelMap->GetWidth();
881     int32_t srcHeight = pixelMap->GetHeight();
882     int32_t dstWidth = info.rotation % NUM_180 == 0 ? param.dstWidth : param.dstHeight;
883     int32_t dstHeight = info.rotation % NUM_180 == 0 ? param.dstHeight : param.dstWidth;
884     bool needScale = (dstWidth > 0 && dstHeight > 0) &&
885                      (dstWidth <= srcWidth && dstHeight <= srcHeight) &&
886                      (dstWidth < srcWidth || dstHeight < srcHeight) && srcWidth > 0 && srcHeight > 0;
887     CHECK_AND_RETURN(needScale);
888     pixelMap->scale((1.0f * dstWidth) / srcWidth, (1.0f * dstHeight) / srcHeight, AntiAliasingOption::LOW);
889 }
890 
FetchFrameYuv(int64_t timeUs,int32_t option,const PixelMapParams & param)891 std::shared_ptr<PixelMap> AVMetadataHelperImpl::FetchFrameYuv(int64_t timeUs, int32_t option,
892                                                               const PixelMapParams &param)
893 {
894     return FetchFrameBase(timeUs, option, param, FrameScaleMode::NORMAL_RATIO);
895 }
896 
FetchScaledFrameYuv(int64_t timeUs,int32_t option,const PixelMapParams & param)897 std::shared_ptr<PixelMap> AVMetadataHelperImpl::FetchScaledFrameYuv(int64_t timeUs, int32_t option,
898                                                                     const PixelMapParams &param)
899 {
900     return FetchFrameBase(timeUs, option, param, FrameScaleMode::ASPECT_RATIO);
901 }
902 
FetchFrameBase(int64_t timeUs,int32_t option,const PixelMapParams & param,int32_t scaleMode)903 std::shared_ptr<PixelMap> AVMetadataHelperImpl::FetchFrameBase(int64_t timeUs, int32_t option,
904                                                                const PixelMapParams &param, int32_t scaleMode)
905 {
906     std::shared_ptr<IAVMetadataHelperService> avMetadataHelperService = avMetadataHelperService_;
907     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService != nullptr, nullptr, "avmetadatahelper service does not exist.");
908 
909     concurrentWorkCount_++;
910     ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
911     OutputConfiguration config = { .dstWidth = param.dstWidth,
912                                    .dstHeight = param.dstHeight,
913                                    .colorFormat = param.colorFormat };
914     auto frameBuffer = avMetadataHelperService->FetchFrameYuv(timeUs, option, config);
915     CHECK_AND_RETURN_RET(frameBuffer != nullptr && frameBuffer->memory_ != nullptr, nullptr);
916     concurrentWorkCount_--;
917 
918     DumpAVBuffer(isDump_, frameBuffer, DUMP_FILE_NAME_AVBUFFER);
919 
920     PixelMapInfo pixelMapInfo = { .pixelFormat = param.colorFormat };
921     auto pixelMap = CreatePixelMapYuv(frameBuffer, pixelMapInfo);
922     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "convert to pixelMap failed");
923 
924     DumpPixelMap(isDump_, pixelMap, DUMP_FILE_NAME_PIXEMAP);
925 
926     ScalePixelMapByMode(pixelMap, pixelMapInfo, param, scaleMode);
927 
928     DumpPixelMap(isDump_, pixelMap, DUMP_FILE_NAME_AFTER_SCLAE);
929 
930     MEDIA_LOGI("Rotation is %{public}d, orientation is %{public}d", pixelMapInfo.rotation, pixelMapInfo.orientation);
931     if (param.isSupportFlip && VIDEOORIENTATIONTYPE_ROTATION_MAP.count(pixelMapInfo.orientation) > 0) {
932         MEDIA_LOGI("Support flip");
933         auto itFlip = VIDEOORIENTATIONTYPE_FLIP_MAP.find(pixelMapInfo.orientation);
934         CHECK_AND_RETURN_RET_LOG(itFlip != VIDEOORIENTATIONTYPE_FLIP_MAP.end(), nullptr,
935             "can't find mapped orientation name in VIDEOORIENTATIONTYPE_FLIP_MAP");
936         pixelMap->flip(itFlip->second.first, itFlip->second.second);
937         auto itRotate = VIDEOORIENTATIONTYPE_ROTATION_MAP.find(pixelMapInfo.orientation);
938         CHECK_AND_RETURN_RET_LOG(itRotate != VIDEOORIENTATIONTYPE_ROTATION_MAP.end(), nullptr,
939             "can't find mapped orientation name in VIDEOORIENTATIONTYPE_ROTATION_MAP");
940         pixelMap->rotate(itRotate->second);
941     } else if (pixelMapInfo.rotation > 0) {
942         MEDIA_LOGI("Not support flip");
943         pixelMap->rotate(pixelMapInfo.rotation);
944     }
945 
946     MEDIA_LOGI("final colorSpace %{public}u", pixelMap->InnerGetGrColorSpace().GetColorSpaceName());
947 
948     DumpPixelMap(isDump_, pixelMap, DUMP_FILE_NAME_AFTER_ROTATE);
949     return pixelMap;
950 }
951 
ScalePixelMapByMode(std::shared_ptr<PixelMap> & pixelMap,PixelMapInfo & info,const PixelMapParams & param,int32_t scaleMode)952 void AVMetadataHelperImpl::ScalePixelMapByMode(std::shared_ptr<PixelMap> &pixelMap, PixelMapInfo &info,
953                                                const PixelMapParams &param, int32_t scaleMode)
954 {
955     CHECK_AND_RETURN_LOG(pixelMap != nullptr, "pixelMap is nullptr");
956     switch (scaleMode) {
957         case FrameScaleMode::NORMAL_RATIO:
958             ScalePixelMap(pixelMap, info, param);
959             break;
960         case FrameScaleMode::ASPECT_RATIO:
961             ScalePixelMapWithEqualRatio(pixelMap, info, param);
962             break;
963         default:
964             break;
965     }
966 }
967 
GetTimeByFrameIndex(uint32_t index,uint64_t & time)968 int32_t AVMetadataHelperImpl::GetTimeByFrameIndex(uint32_t index, uint64_t &time)
969 {
970     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, 0, "avmetadatahelper service does not exist.");
971     concurrentWorkCount_++;
972     auto res = avMetadataHelperService_->GetTimeByFrameIndex(index, time);
973     concurrentWorkCount_--;
974     return res;
975 }
976 
GetFrameIndexByTime(uint64_t time,uint32_t & index)977 int32_t AVMetadataHelperImpl::GetFrameIndexByTime(uint64_t time, uint32_t &index)
978 {
979     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, 0, "avmetadatahelper service does not exist.");
980     concurrentWorkCount_++;
981     auto res = avMetadataHelperService_->GetFrameIndexByTime(time, index);
982     concurrentWorkCount_--;
983     return res;
984 }
985 
Release()986 void AVMetadataHelperImpl::Release()
987 {
988     std::lock_guard<std::mutex> lock(releaseMutex_);
989     MEDIA_LOGI("0x%{public}06" PRIXPTR " Release", FAKE_POINTER(this));
990     CHECK_AND_RETURN_LOG(avMetadataHelperService_ != nullptr, "avmetadatahelper service does not exist.");
991     avMetadataHelperService_->Release();
992     (void)MediaServiceFactory::GetInstance().DestroyAVMetadataHelperService(avMetadataHelperService_);
993     avMetadataHelperService_ = nullptr;
994     MEDIA_LOGI("0x%{public}06" PRIXPTR " Release out", FAKE_POINTER(this));
995 }
996 } // namespace Media
997 } // namespace OHOS
998