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