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/cm_color_space.h"
22 #include "v1_0/hdr_static_metadata.h"
23 #include "v1_0/buffer_handle_meta_key_type.h"
24 
25 #include "securec.h"
26 #include "image_source.h"
27 #include "i_media_service.h"
28 #include "media_log.h"
29 #include "media_errors.h"
30 #include "scope_guard.h"
31 #include "hisysevent.h"
32 #include "color_space.h"
33 #include "image_type.h"
34 #include "hdr_type.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 constexpr int32_t NUM_180 = 180;
43 static constexpr int32_t PLANE_Y = 0;
44 static constexpr int32_t PLANE_U = 1;
45 static constexpr uint8_t NUM_2 = 2;
46 }
47 
48 namespace OHOS {
49 namespace Media {
50 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
51 static constexpr uint8_t PIXEL_SIZE_HDR_YUV = 3;
52 static std::map<Scene, long> SCENE_CODE_MAP = { { Scene::AV_META_SCENE_CLONE, 1 },
53                                                 { Scene::AV_META_SCENE_BATCH_HANDLE, 2 } };
54 static std::map<Scene, int64_t> SCENE_TIMESTAMP_MAP = { { Scene::AV_META_SCENE_CLONE, 0 },
55                                                         { Scene::AV_META_SCENE_BATCH_HANDLE, 0 } };
56 
57 struct PixelMapMemHolder {
58     bool isShmem;
59     std::shared_ptr<AVSharedMemory> shmem;
60     uint8_t *heap;
61 };
62 
63 struct AVBufferHolder {
64     std::shared_ptr<AVBuffer> buffer;
65 };
66 
FreePixelMapData(void * addr,void * context,uint32_t size)67 static void FreePixelMapData(void *addr, void *context, uint32_t size)
68 {
69     (void)size;
70 
71     MEDIA_LOGD("free pixel map data");
72 
73     CHECK_AND_RETURN_LOG(context != nullptr, "context is nullptr");
74     PixelMapMemHolder *holder = reinterpret_cast<PixelMapMemHolder *>(context);
75     if (holder->isShmem) {
76         if (holder->shmem == nullptr) {
77             MEDIA_LOGE("shmem is nullptr");
78         }
79         holder->shmem = nullptr;
80         holder->heap = nullptr;
81     } else {
82         if (holder->heap == nullptr || holder->heap != addr) {
83             MEDIA_LOGE("heap is invalid");
84         } else {
85             delete [] holder->heap;
86             holder->heap = nullptr;
87         }
88     }
89     delete holder;
90 }
91 
FreeAvBufferData(void * addr,void * context,uint32_t size)92 static void FreeAvBufferData(void *addr, void *context, uint32_t size)
93 {
94     (void)addr;
95     (void)size;
96     CHECK_AND_RETURN_LOG(context != nullptr, "context is nullptr");
97     AVBufferHolder *holder = reinterpret_cast<AVBufferHolder *>(context);
98     delete holder;
99 }
100 
FreeSurfaceBuffer(void * addr,void * context,uint32_t size)101 static void FreeSurfaceBuffer(void *addr, void *context, uint32_t size)
102 {
103     (void)addr;
104     (void)size;
105     CHECK_AND_RETURN_LOG(context != nullptr, "context is nullptr");
106     void* nativeBuffer = context;
107     RefBase *ref = reinterpret_cast<RefBase *>(nativeBuffer);
108     ref->DecStrongRef(ref);
109 }
110 
CreatePixelMapData(const std::shared_ptr<AVSharedMemory> & mem,const OutputFrame & frame)111 static PixelMapMemHolder *CreatePixelMapData(const std::shared_ptr<AVSharedMemory> &mem, const OutputFrame &frame)
112 {
113     PixelMapMemHolder *holder = new (std::nothrow) PixelMapMemHolder;
114     CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "alloc pixelmap mem holder failed");
115 
116     ON_SCOPE_EXIT(0) {
117         delete holder;
118     };
119 
120     int32_t minStride = frame.width_ * frame.bytesPerPixel_;
121     CHECK_AND_RETURN_RET_LOG(minStride <= frame.stride_, nullptr, "stride info wrong");
122 
123     if (frame.stride_ == minStride) {
124         CANCEL_SCOPE_EXIT_GUARD(0);
125         holder->isShmem = true;
126         holder->shmem = mem;
127         holder->heap = frame.GetFlattenedData();
128         return holder;
129     }
130 
131     static constexpr int64_t maxAllowedSize = 100 * 1024 * 1024;
132     int64_t memSize = static_cast<int64_t>(minStride) * frame.height_;
133     CHECK_AND_RETURN_RET_LOG(memSize <= maxAllowedSize, nullptr, "alloc heap size too large");
134 
135     uint8_t *heap = new (std::nothrow) uint8_t[memSize];
136     CHECK_AND_RETURN_RET_LOG(heap != nullptr, nullptr, "alloc heap failed");
137 
138     ON_SCOPE_EXIT(1) {
139         delete [] heap;
140     };
141 
142     uint8_t *currDstPos = heap;
143     uint8_t *currSrcPos = frame.GetFlattenedData();
144     for (int32_t row = 0; row < frame.height_; ++row) {
145         errno_t rc = memcpy_s(currDstPos, static_cast<size_t>(memSize), currSrcPos, static_cast<size_t>(minStride));
146         CHECK_AND_RETURN_RET_LOG(rc == EOK, nullptr, "memcpy_s failed");
147 
148         currDstPos += minStride;
149         currSrcPos += frame.stride_;
150         memSize -= minStride;
151     }
152 
153     holder->isShmem = false;
154     holder->heap = heap;
155 
156     CANCEL_SCOPE_EXIT_GUARD(0);
157     CANCEL_SCOPE_EXIT_GUARD(1);
158     return holder;
159 }
160 
CreateAVBufferHolder(const std::shared_ptr<AVBuffer> & avBuffer)161 static AVBufferHolder *CreateAVBufferHolder(const std::shared_ptr<AVBuffer> &avBuffer)
162 {
163     CHECK_AND_RETURN_RET(avBuffer != nullptr && avBuffer->memory_ != nullptr, nullptr);
164     AVBufferHolder *holder = new (std::nothrow) AVBufferHolder;
165     CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "alloc avBuffer holder failed");
166     holder->buffer = avBuffer;
167     return holder;
168 }
169 
CreatePixelMap(const std::shared_ptr<AVSharedMemory> & mem,PixelFormat color,int32_t & rotation)170 static std::shared_ptr<PixelMap> CreatePixelMap(const std::shared_ptr<AVSharedMemory> &mem, PixelFormat color,
171     int32_t &rotation)
172 {
173     CHECK_AND_RETURN_RET_LOG(mem != nullptr, nullptr, "Fetch frame failed");
174     CHECK_AND_RETURN_RET_LOG(mem->GetBase() != nullptr, nullptr, "Addr is nullptr");
175     CHECK_AND_RETURN_RET_LOG(mem->GetSize() > 0, nullptr, "size is incorrect");
176     CHECK_AND_RETURN_RET_LOG(static_cast<uint32_t>(mem->GetSize()) >= sizeof(OutputFrame),
177                              nullptr, "size is incorrect");
178 
179     OutputFrame *frame = reinterpret_cast<OutputFrame *>(mem->GetBase());
180     MEDIA_LOGD("width: %{public}d, stride : %{public}d, height: %{public}d, size: %{public}d, format: %{public}d",
181         frame->width_, frame->stride_, frame->height_, frame->size_, color);
182 
183     rotation = frame->rotation_;
184     InitializationOptions opts;
185     opts.size.width = frame->width_;
186     opts.size.height = frame->height_;
187     opts.pixelFormat = color;
188     opts.editable = true;
189     std::shared_ptr<PixelMap> pixelMap = PixelMap::Create(opts);
190 
191     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "pixelMap create failed");
192     CHECK_AND_RETURN_RET_LOG(pixelMap->GetByteCount() <= frame->size_, nullptr, "Size inconsistent !");
193 
194     PixelMapMemHolder *holder = CreatePixelMapData(mem, *frame);
195     CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "create pixel map data failed");
196 
197     pixelMap->SetPixelsAddr(holder->heap, holder, static_cast<uint32_t>(pixelMap->GetByteCount()),
198         AllocatorType::CUSTOM_ALLOC, FreePixelMapData);
199     return pixelMap;
200 }
201 
CreatePixelMapYuv(const std::shared_ptr<AVBuffer> & frameBuffer,PixelMapInfo & pixelMapInfo)202 std::shared_ptr<PixelMap> AVMetadataHelperImpl::CreatePixelMapYuv(const std::shared_ptr<AVBuffer> &frameBuffer,
203                                                                   PixelMapInfo &pixelMapInfo)
204 {
205     bool isValid = frameBuffer != nullptr && frameBuffer->meta_ != nullptr && frameBuffer->memory_ != nullptr;
206     CHECK_AND_RETURN_RET_LOG(isValid, nullptr, "invalid frame buffer");
207     auto bufferMeta = frameBuffer->meta_;
208 
209     int32_t width = 0;
210     auto hasProperty = bufferMeta->Get<Tag::VIDEO_WIDTH>(width);
211     CHECK_AND_RETURN_RET_LOG(hasProperty, nullptr, "invalid width");
212     int32_t height = 0;
213     hasProperty = bufferMeta->Get<Tag::VIDEO_HEIGHT>(height);
214     CHECK_AND_RETURN_RET_LOG(hasProperty, nullptr, "invalid height");
215 
216     Plugins::VideoRotation rotation = Plugins::VideoRotation::VIDEO_ROTATION_0;
217     bufferMeta->Get<Tag::VIDEO_ROTATION>(rotation);
218     pixelMapInfo.rotation = static_cast<int32_t>(rotation);
219     bufferMeta->Get<Tag::VIDEO_IS_HDR_VIVID>(pixelMapInfo.isHdr);
220     pixelMapInfo.isHdr &= frameBuffer->memory_->GetSurfaceBuffer() != nullptr;
221 
222     std::shared_ptr<PixelMap> pixelMap;
223     bool isPlanesAvailable = false;
224     OH_NativeBuffer_Planes *planes = nullptr;
225     if (pixelMapInfo.isHdr) {
226         auto surfaceBuffer = frameBuffer->memory_->GetSurfaceBuffer();
227         sptr<SurfaceBuffer> mySurfaceBuffer = CopySurfaceBuffer(surfaceBuffer);
228         CHECK_AND_RETURN_RET_LOG(mySurfaceBuffer != nullptr, nullptr, "Create SurfaceBuffer failed");
229         GSError retVal = mySurfaceBuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
230         isPlanesAvailable = (retVal == OHOS::GSERROR_OK) && (planes != nullptr);
231         MEDIA_LOGD("isPlanesAvailable = %{public}d", isPlanesAvailable);
232         pixelMap = OnCreatePixelMapHdr(mySurfaceBuffer);
233         CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Create pixelMap Hdr failed");
234     } else {
235         InitializationOptions options = { .size = { .width = width, .height = height },
236                                           .pixelFormat = PixelFormat::NV12 };
237         pixelMap = OnCreatePixelMapSdr(frameBuffer, pixelMapInfo, options);
238         CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Create pixelMap Sdr failed");
239     }
240     SetPixelMapYuvInfo(pixelMap, isPlanesAvailable, planes);
241     return pixelMap;
242 }
243 
OnCreatePixelMapSdr(const std::shared_ptr<AVBuffer> & frameBuffer,PixelMapInfo & pixelMapInfo,InitializationOptions & options)244 std::shared_ptr<PixelMap> AVMetadataHelperImpl::OnCreatePixelMapSdr(const std::shared_ptr<AVBuffer> &frameBuffer,
245                                                                     PixelMapInfo &pixelMapInfo,
246                                                                     InitializationOptions &options)
247 {
248     bool isValid = frameBuffer != nullptr && frameBuffer->memory_ != nullptr;
249     CHECK_AND_RETURN_RET_LOG(isValid, nullptr, "invalid frame buffer");
250     auto pixelMap = PixelMap::Create(options);
251     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Create pixelMap failed");
252     AVBufferHolder *holder = CreateAVBufferHolder(frameBuffer);
253     CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "Create buffer holder failed");
254     uint8_t *pixelAddr = frameBuffer->memory_->GetAddr();
255     pixelMap->SetPixelsAddr(pixelAddr, holder, pixelMap->GetByteCount(),
256                             AllocatorType::CUSTOM_ALLOC, FreeAvBufferData);
257     const InitializationOptions opts = { .size = { .width = pixelMap->GetWidth(),
258                                                    .height = pixelMap->GetHeight() },
259                                          .srcPixelFormat = PixelFormat::NV12,
260                                          .pixelFormat = pixelMapInfo.pixelFormat };
261     return PixelMap::Create(reinterpret_cast<const uint32_t *>(pixelMap->GetPixels()),
262                             pixelMap->GetByteCount(), opts);
263 }
264 
OnCreatePixelMapHdr(sptr<SurfaceBuffer> & mySurfaceBuffer)265 std::shared_ptr<PixelMap> AVMetadataHelperImpl::OnCreatePixelMapHdr(sptr<SurfaceBuffer> &mySurfaceBuffer)
266 {
267     CHECK_AND_RETURN_RET_LOG(mySurfaceBuffer != nullptr, nullptr, "mySurfaceBuffer is nullptr");
268     InitializationOptions options = { .size = { .width = mySurfaceBuffer->GetWidth(),
269                                                 .height = mySurfaceBuffer->GetHeight() },
270                                       .srcPixelFormat = PixelFormat::YCBCR_P010,
271                                       .pixelFormat = PixelFormat::YCBCR_P010,
272                                       .useDMA = true };
273     int32_t colorLength = mySurfaceBuffer->GetWidth() * mySurfaceBuffer->GetHeight() * PIXEL_SIZE_HDR_YUV;
274     auto pixelMap = PixelMap::Create(reinterpret_cast<const uint32_t *>(mySurfaceBuffer->GetVirAddr()),
275         static_cast<uint32_t>(colorLength), options);
276     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Create pixelMap failed");
277     void* nativeBuffer = mySurfaceBuffer.GetRefPtr();
278     RefBase *ref = reinterpret_cast<RefBase *>(nativeBuffer);
279     ref->IncStrongRef(ref);
280     pixelMap->SetHdrType(ImageHdrType::HDR_VIVID_SINGLE);
281     pixelMap->InnerSetColorSpace(OHOS::ColorManager::ColorSpace(ColorManager::ColorSpaceName::BT2020_HLG));
282     pixelMap->SetPixelsAddr(mySurfaceBuffer->GetVirAddr(), mySurfaceBuffer.GetRefPtr(), mySurfaceBuffer->GetSize(),
283                             AllocatorType::DMA_ALLOC, FreeSurfaceBuffer);
284     return pixelMap;
285 }
286 
SetPixelMapYuvInfo(std::shared_ptr<PixelMap> pixelMap,bool isPlanesAvailable,OH_NativeBuffer_Planes * planes)287 void AVMetadataHelperImpl::SetPixelMapYuvInfo(std::shared_ptr<PixelMap> pixelMap, bool isPlanesAvailable,
288                                               OH_NativeBuffer_Planes *planes)
289 {
290     int32_t srcWidth = pixelMap->GetWidth();
291     int32_t srcHeight = pixelMap->GetHeight();
292     YUVDataInfo yuvDataInfo = { .yWidth = srcWidth,
293                                 .yHeight = srcHeight,
294                                 .uvWidth = srcWidth / 2,
295                                 .uvHeight = srcHeight / 2,
296                                 .yStride = srcWidth,
297                                 .uvStride = srcWidth,
298                                 .uvOffset = srcWidth * srcHeight};
299     if (isPlanesAvailable && planes != nullptr) {
300         yuvDataInfo.yStride = planes->planes[PLANE_Y].columnStride / NUM_2;
301         yuvDataInfo.uvStride = planes->planes[PLANE_U].columnStride / NUM_2;
302         yuvDataInfo.yOffset = planes->planes[PLANE_Y].offset / NUM_2;
303         yuvDataInfo.uvOffset = planes->planes[PLANE_U].offset / NUM_2;
304     }
305     pixelMap->SetImageYUVInfo(yuvDataInfo);
306 }
307 
CopySurfaceBuffer(sptr<SurfaceBuffer> & srcSurfaceBuffer)308 sptr<SurfaceBuffer> AVMetadataHelperImpl::CopySurfaceBuffer(sptr<SurfaceBuffer> &srcSurfaceBuffer)
309 {
310     sptr<SurfaceBuffer> dstSurfaceBuffer = SurfaceBuffer::Create();
311     BufferRequestConfig requestConfig = {
312         .width = srcSurfaceBuffer->GetWidth(),
313         .height = srcSurfaceBuffer->GetHeight(),
314         .strideAlignment = 0x2,
315         .format = srcSurfaceBuffer->GetFormat(),  // always yuv
316         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA | BUFFER_USAGE_MEM_MMZ_CACHE,
317         .timeout = 0,
318     };
319     GSError allocRes = dstSurfaceBuffer->Alloc(requestConfig);
320     CHECK_AND_RETURN_RET_LOG(allocRes == 0, nullptr, "Alloc surfaceBuffer failed, ecode %{public}d", allocRes);
321 
322     MEDIA_LOGI("winddraw %{public}d %{public}d", dstSurfaceBuffer->GetSize(), srcSurfaceBuffer->GetSize());
323 
324     CopySurfaceBufferInfo(srcSurfaceBuffer, dstSurfaceBuffer);
325     CopySurfaceBufferPixels(srcSurfaceBuffer, dstSurfaceBuffer);
326     return dstSurfaceBuffer;
327 }
328 
CopySurfaceBufferInfo(sptr<SurfaceBuffer> & source,sptr<SurfaceBuffer> & dst)329 void AVMetadataHelperImpl::CopySurfaceBufferInfo(sptr<SurfaceBuffer> &source, sptr<SurfaceBuffer> &dst)
330 {
331     if (source == nullptr || dst == nullptr) {
332         MEDIA_LOGI("CopySurfaceBufferInfo failed, source or dst is nullptr");
333         return;
334     }
335     std::vector<uint8_t> hdrMetadataTypeVec;
336     std::vector<uint8_t> colorSpaceInfoVec;
337     std::vector<uint8_t> staticData;
338     std::vector<uint8_t> dynamicData;
339 
340     if (source->GetMetadata(ATTRKEY_HDR_METADATA_TYPE, hdrMetadataTypeVec) == GSERROR_OK) {
341         dst->SetMetadata(ATTRKEY_HDR_METADATA_TYPE, hdrMetadataTypeVec);
342     }
343     if (source->GetMetadata(ATTRKEY_COLORSPACE_INFO, colorSpaceInfoVec) == GSERROR_OK) {
344         dst->SetMetadata(ATTRKEY_COLORSPACE_INFO, colorSpaceInfoVec);
345     }
346     if (GetSbStaticMetadata(source, staticData) && (staticData.size() > 0)) {
347         SetSbStaticMetadata(dst, staticData);
348     }
349     if (GetSbDynamicMetadata(source, dynamicData) && (dynamicData.size()) > 0) {
350         SetSbDynamicMetadata(dst, dynamicData);
351     }
352 }
353 
GetSbStaticMetadata(sptr<SurfaceBuffer> & buffer,std::vector<uint8_t> & staticMetadata)354 bool AVMetadataHelperImpl::GetSbStaticMetadata(sptr<SurfaceBuffer> &buffer, std::vector<uint8_t> &staticMetadata)
355 {
356     return buffer->GetMetadata(ATTRKEY_HDR_STATIC_METADATA, staticMetadata) == GSERROR_OK;
357 }
358 
GetSbDynamicMetadata(sptr<SurfaceBuffer> & buffer,std::vector<uint8_t> & dynamicMetadata)359 bool AVMetadataHelperImpl::GetSbDynamicMetadata(sptr<SurfaceBuffer> &buffer, std::vector<uint8_t> &dynamicMetadata)
360 {
361     return buffer->GetMetadata(ATTRKEY_HDR_DYNAMIC_METADATA, dynamicMetadata) == GSERROR_OK;
362 }
363 
SetSbStaticMetadata(sptr<SurfaceBuffer> & buffer,const std::vector<uint8_t> & staticMetadata)364 bool AVMetadataHelperImpl::SetSbStaticMetadata(sptr<SurfaceBuffer> &buffer, const std::vector<uint8_t> &staticMetadata)
365 {
366     return buffer->SetMetadata(ATTRKEY_HDR_STATIC_METADATA, staticMetadata) == GSERROR_OK;
367 }
368 
SetSbDynamicMetadata(sptr<SurfaceBuffer> & buffer,const std::vector<uint8_t> & dynamicMetadata)369 bool AVMetadataHelperImpl::SetSbDynamicMetadata(sptr<SurfaceBuffer> &buffer,
370                                                 const std::vector<uint8_t> &dynamicMetadata)
371 {
372     return buffer->SetMetadata(ATTRKEY_HDR_DYNAMIC_METADATA, dynamicMetadata) == GSERROR_OK;
373 }
374 
CopySurfaceBufferPixels(sptr<SurfaceBuffer> & srcSurfaceBuffer,sptr<SurfaceBuffer> & dstSurfaceBuffer)375 int32_t AVMetadataHelperImpl::CopySurfaceBufferPixels(sptr<SurfaceBuffer> &srcSurfaceBuffer,
376                                                       sptr<SurfaceBuffer> &dstSurfaceBuffer)
377 {
378     auto res = memcpy_s(dstSurfaceBuffer->GetVirAddr(), dstSurfaceBuffer->GetSize(), srcSurfaceBuffer->GetVirAddr(),
379         srcSurfaceBuffer->GetSize());
380     return res == EOK ? MSERR_OK : MSERR_NO_MEMORY;
381 }
382 
CreateAVMetadataHelper()383 std::shared_ptr<AVMetadataHelper> AVMetadataHelperFactory::CreateAVMetadataHelper()
384 {
385     std::shared_ptr<AVMetadataHelperImpl> impl = std::make_shared<AVMetadataHelperImpl>();
386     CHECK_AND_RETURN_RET_LOG(impl != nullptr, nullptr, "failed to new AVMetadataHelperImpl");
387 
388     int32_t ret = impl->Init();
389     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "failed to init AVMetadataHelperImpl");
390 
391     return impl;
392 }
393 
Init()394 int32_t AVMetadataHelperImpl::Init()
395 {
396     avMetadataHelperService_ = MediaServiceFactory::GetInstance().CreateAVMetadataHelperService();
397     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
398         "failed to create avmetadatahelper service");
399     return MSERR_OK;
400 }
401 
AVMetadataHelperImpl()402 AVMetadataHelperImpl::AVMetadataHelperImpl()
403 {
404     MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
405 }
406 
~AVMetadataHelperImpl()407 AVMetadataHelperImpl::~AVMetadataHelperImpl()
408 {
409     if (avMetadataHelperService_ != nullptr) {
410         (void)MediaServiceFactory::GetInstance().DestroyAVMetadataHelperService(avMetadataHelperService_);
411         avMetadataHelperService_ = nullptr;
412     }
413     MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
414 }
415 
SetHelperCallback(const std::shared_ptr<HelperCallback> & callback)416 int32_t AVMetadataHelperImpl::SetHelperCallback(const std::shared_ptr<HelperCallback> &callback)
417 {
418     MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " SetHelperCallback in", FAKE_POINTER(this));
419     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_SERVICE_DIED,
420         "metadata helper service does not exist..");
421     CHECK_AND_RETURN_RET_LOG(callback != nullptr, MSERR_INVALID_VAL, "callback is nullptr");
422     return avMetadataHelperService_->SetHelperCallback(callback);
423 }
424 
SetScene(Scene scene)425 void AVMetadataHelperImpl::SetScene(Scene scene)
426 {
427     ReportSceneCode(scene);
428 }
429 
ReportSceneCode(Scene scene)430 void AVMetadataHelperImpl::ReportSceneCode(Scene scene)
431 {
432     if (scene != Scene::AV_META_SCENE_CLONE && scene != Scene::AV_META_SCENE_BATCH_HANDLE) {
433         return;
434     }
435     if (scene == Scene::AV_META_SCENE_BATCH_HANDLE && concurrentWorkCount_ < HIGH_CONCRENT_WORK_NUM) {
436         return;
437     }
438     auto sceneCode = SCENE_CODE_MAP[scene];
439     auto lastTsp = SCENE_TIMESTAMP_MAP[scene];
440     auto now =
441         std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
442     auto duration = now - std::chrono::milliseconds(lastTsp);
443     if (duration < std::chrono::milliseconds(SCENE_CODE_EFFECTIVE_DURATION_MS)) {
444         return;
445     }
446     SCENE_TIMESTAMP_MAP[scene] = now.count();
447     MEDIA_LOGI("Report scene code %{public}ld", sceneCode);
448     int32_t ret = HiSysEventWrite(
449         PERFORMANCE_STATS, "CPU_SCENE_ENTRY", OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "PACKAGE_NAME",
450         "media_service", "SCENE_ID", std::to_string(sceneCode).c_str(), "HAPPEN_TIME", now.count());
451     if (ret != MSERR_OK) {
452         MEDIA_LOGW("report error");
453     }
454 }
455 
SetSource(const std::string & uri,int32_t usage)456 int32_t AVMetadataHelperImpl::SetSource(const std::string &uri, int32_t usage)
457 {
458     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
459         "avmetadatahelper service does not exist..");
460     CHECK_AND_RETURN_RET_LOG(!uri.empty(), MSERR_INVALID_VAL, "uri is empty.");
461 
462     concurrentWorkCount_++;
463     ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
464     auto res = avMetadataHelperService_->SetSource(uri, usage);
465     concurrentWorkCount_--;
466     return res;
467 }
468 
SetSource(int32_t fd,int64_t offset,int64_t size,int32_t usage)469 int32_t AVMetadataHelperImpl::SetSource(int32_t fd, int64_t offset, int64_t size, int32_t usage)
470 {
471     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
472         "avmetadatahelper service does not exist..");
473     MEDIA_LOGI("Set file source fd: %{public}d, offset: %{public}" PRIu64 ", size: %{public}" PRIu64,
474         fd, offset, size);
475     CHECK_AND_RETURN_RET_LOG(fd > 0 && offset >= 0 && size >= -1, MSERR_INVALID_VAL,
476         "invalid param");
477 
478     concurrentWorkCount_++;
479     ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
480     auto res = avMetadataHelperService_->SetSource(fd, offset, size, usage);
481     concurrentWorkCount_--;
482     return res;
483 }
484 
SetSource(const std::shared_ptr<IMediaDataSource> & dataSrc)485 int32_t AVMetadataHelperImpl::SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)
486 {
487     MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " SetSource in(dataSrc)", FAKE_POINTER(this));
488     CHECK_AND_RETURN_RET_LOG(dataSrc != nullptr, MSERR_INVALID_VAL, "failed to create data source");
489 
490     concurrentWorkCount_++;
491     ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
492     auto res = avMetadataHelperService_->SetSource(dataSrc);
493     concurrentWorkCount_--;
494     return res;
495 }
496 
ResolveMetadata(int32_t key)497 std::string AVMetadataHelperImpl::ResolveMetadata(int32_t key)
498 {
499     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, "",
500         "avmetadatahelper service does not exist.");
501     concurrentWorkCount_++;
502     auto res = avMetadataHelperService_->ResolveMetadata(key);
503     concurrentWorkCount_--;
504     return res;
505 }
506 
ResolveMetadata()507 std::unordered_map<int32_t, std::string> AVMetadataHelperImpl::ResolveMetadata()
508 {
509     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, {},
510         "avmetadatahelper service does not exist.");
511     concurrentWorkCount_++;
512     auto res = avMetadataHelperService_->ResolveMetadata();
513     concurrentWorkCount_--;
514     return res;
515 }
516 
GetAVMetadata()517 std::shared_ptr<Meta> AVMetadataHelperImpl::GetAVMetadata()
518 {
519     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
520         "avmetadatahelper service does not exist.");
521     concurrentWorkCount_++;
522     auto res = avMetadataHelperService_->GetAVMetadata();
523     concurrentWorkCount_--;
524     return res;
525 }
526 
FetchArtPicture()527 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchArtPicture()
528 {
529     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
530         "avmetadatahelper service does not exist.");
531     concurrentWorkCount_++;
532     auto res = avMetadataHelperService_->FetchArtPicture();
533     concurrentWorkCount_--;
534     return res;
535 }
536 
FetchFrameAtTime(int64_t timeUs,int32_t option,const PixelMapParams & param)537 std::shared_ptr<PixelMap> AVMetadataHelperImpl::FetchFrameAtTime(
538     int64_t timeUs, int32_t option, const PixelMapParams &param)
539 {
540     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
541         "avmetadatahelper service does not exist.");
542 
543     concurrentWorkCount_++;
544     ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
545 
546     OutputConfiguration config;
547     config.colorFormat = param.colorFormat;
548     config.dstHeight = param.dstHeight;
549     config.dstWidth = param.dstWidth;
550 
551     auto mem = avMetadataHelperService_->FetchFrameAtTime(timeUs, option, config);
552     auto pixelMap = CreatePixelMap(mem, PixelFormat::NV12, rotation_);
553 
554     concurrentWorkCount_--;
555 
556     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "pixelMap does not exist.");
557 
558     const InitializationOptions opts = { .size = { .width = pixelMap->GetWidth(), .height = pixelMap->GetHeight() },
559                                          .srcPixelFormat = PixelFormat::NV12 };
560     pixelMap =
561         PixelMap::Create(reinterpret_cast<const uint32_t *>(pixelMap->GetPixels()), pixelMap->GetByteCount(), opts);
562     if (pixelMap == nullptr) {
563         return nullptr;
564     }
565     if (rotation_ > 0) {
566         pixelMap->rotate(rotation_);
567     }
568     int32_t srcWidth = pixelMap->GetWidth();
569     int32_t srcHeight = pixelMap->GetHeight();
570     bool needScale = (param.dstWidth > 0 && param.dstHeight > 0) &&
571                      (param.dstWidth <= srcWidth && param.dstHeight <= srcHeight) &&
572                      (param.dstWidth < srcWidth || param.dstHeight < srcHeight) && srcWidth > 0 && srcHeight > 0;
573     if (needScale) {
574         pixelMap->scale((1.0f * param.dstWidth) / srcWidth, (1.0f * param.dstHeight) / srcHeight);
575     }
576     return pixelMap;
577 }
578 
ScalePixelMap(std::shared_ptr<PixelMap> & pixelMap,PixelMapInfo & info,const PixelMapParams & param)579 void AVMetadataHelperImpl::ScalePixelMap(
580     std::shared_ptr<PixelMap> &pixelMap, PixelMapInfo &info, const PixelMapParams &param)
581 {
582     int32_t srcWidth = pixelMap->GetWidth();
583     int32_t srcHeight = pixelMap->GetHeight();
584     int32_t dstWidth = info.rotation % NUM_180 == 0 ? param.dstWidth : param.dstHeight;
585     int32_t dstHeight = info.rotation % NUM_180 == 0 ? param.dstHeight : param.dstWidth;
586     bool needScale = (dstWidth > 0 && dstHeight > 0) &&
587                      (dstWidth <= srcWidth && dstHeight <= srcHeight) &&
588                      (dstWidth < srcWidth || dstHeight < srcHeight) && srcWidth > 0 && srcHeight > 0;
589     CHECK_AND_RETURN(needScale);
590     pixelMap->scale((1.0f * dstWidth) / srcWidth, (1.0f * dstHeight) / srcHeight, AntiAliasingOption::LOW);
591 }
592 
FetchFrameYuv(int64_t timeUs,int32_t option,const PixelMapParams & param)593 std::shared_ptr<PixelMap> AVMetadataHelperImpl::FetchFrameYuv(int64_t timeUs, int32_t option,
594                                                               const PixelMapParams &param)
595 {
596     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr, "avmetadatahelper service does not exist.");
597 
598     concurrentWorkCount_++;
599     ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
600     OutputConfiguration config = { .dstWidth = param.dstWidth,
601                                    .dstHeight = param.dstHeight,
602                                    .colorFormat = param.colorFormat };
603     auto frameBuffer = avMetadataHelperService_->FetchFrameYuv(timeUs, option, config);
604     CHECK_AND_RETURN_RET(frameBuffer != nullptr, nullptr);
605     concurrentWorkCount_--;
606 
607     PixelMapInfo pixelMapInfo = { .pixelFormat = param.colorFormat };
608     auto pixelMap = CreatePixelMapYuv(frameBuffer, pixelMapInfo);
609     CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "convert to pixelMap failed");
610 
611     ScalePixelMap(pixelMap, pixelMapInfo, param);
612     if (pixelMapInfo.rotation > 0) {
613         pixelMap->rotate(pixelMapInfo.rotation);
614     }
615     return pixelMap;
616 }
617 
GetTimeByFrameIndex(uint32_t index,uint64_t & time)618 int32_t AVMetadataHelperImpl::GetTimeByFrameIndex(uint32_t index, uint64_t &time)
619 {
620     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, 0, "avmetadatahelper service does not exist.");
621     concurrentWorkCount_++;
622     auto res = avMetadataHelperService_->GetTimeByFrameIndex(index, time);
623     concurrentWorkCount_--;
624     return res;
625 }
626 
GetFrameIndexByTime(uint64_t time,uint32_t & index)627 int32_t AVMetadataHelperImpl::GetFrameIndexByTime(uint64_t time, uint32_t &index)
628 {
629     CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, 0, "avmetadatahelper service does not exist.");
630     concurrentWorkCount_++;
631     auto res = avMetadataHelperService_->GetFrameIndexByTime(time, index);
632     concurrentWorkCount_--;
633     return res;
634 }
635 
Release()636 void AVMetadataHelperImpl::Release()
637 {
638     std::lock_guard<std::mutex> lock(releaseMutex_);
639     MEDIA_LOGI("0x%{public}06" PRIXPTR " Release", FAKE_POINTER(this));
640     CHECK_AND_RETURN_LOG(avMetadataHelperService_ != nullptr, "avmetadatahelper service does not exist.");
641     avMetadataHelperService_->Release();
642     (void)MediaServiceFactory::GetInstance().DestroyAVMetadataHelperService(avMetadataHelperService_);
643     avMetadataHelperService_ = nullptr;
644 }
645 } // namespace Media
646 } // namespace OHOS
647