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 ¶m)
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 ¶m)
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 ¶m)
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