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