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 "image_format_convert.h"
33 #include "color_space.h"
34 #include "param_wrapper.h"
35
36 namespace {
37 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_DOMAIN_METADATA, "AVMetadatahelperImpl" };
38 constexpr int32_t SCENE_CODE_EFFECTIVE_DURATION_MS = 20000;
39 static constexpr char PERFORMANCE_STATS[] = "PERFORMANCE";
40 static std::atomic<uint32_t> concurrentWorkCount_ = 0;
41 static constexpr uint8_t HIGH_CONCRENT_WORK_NUM = 4;
42 static constexpr int32_t PLANE_Y = 0;
43 static constexpr int32_t PLANE_U = 1;
44 static constexpr uint8_t HDR_PIXEL_SIZE = 2;
45 static constexpr uint8_t SDR_PIXEL_SIZE = 1;
46 constexpr int32_t NUM_180 = 180;
47 static const std::string FILE_DIR_IN_THE_SANDBOX = "/data/storage/el2/base/files/";
48 const std::string DUMP_FILE_NAME_AVBUFFER = "_avbuffer.dat";
49 const std::string DUMP_FILE_NAME_PIXEMAP = "_pixelMap.dat";
50 const std::string DUMP_FILE_NAME_AFTER_SCLAE = "_afterScale.dat";
51 const std::string DUMP_FILE_NAME_AFTER_ROTATE = "_afterRotate.dat";
52 }
53
54 namespace OHOS {
55 namespace Media {
56 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
57 static constexpr uint8_t PIXEL_SIZE_HDR_YUV = 3;
58 static std::map<Scene, long> SCENE_CODE_MAP = { { Scene::AV_META_SCENE_CLONE, 1 },
59 { Scene::AV_META_SCENE_BATCH_HANDLE, 2 } };
60 static std::map<Scene, int64_t> SCENE_TIMESTAMP_MAP = { { Scene::AV_META_SCENE_CLONE, 0 },
61 { Scene::AV_META_SCENE_BATCH_HANDLE, 0 } };
62
63 struct PixelMapMemHolder {
64 bool isShmem;
65 std::shared_ptr<AVSharedMemory> shmem;
66 uint8_t *heap;
67 };
68
69 struct AVBufferHolder {
70 std::shared_ptr<AVBuffer> buffer;
71 };
72
FreePixelMapData(void *addr, void *context, uint32_t size)73 static void FreePixelMapData(void *addr, void *context, uint32_t size)
74 {
75 (void)size;
76
77 MEDIA_LOGD("free pixel map data");
78
79 CHECK_AND_RETURN_LOG(context != nullptr, "context is nullptr");
80 PixelMapMemHolder *holder = reinterpret_cast<PixelMapMemHolder *>(context);
81 if (holder->isShmem) {
82 if (holder->shmem == nullptr) {
83 MEDIA_LOGE("shmem is nullptr");
84 }
85 holder->shmem = nullptr;
86 holder->heap = nullptr;
87 } else {
88 if (holder->heap == nullptr || holder->heap != addr) {
89 MEDIA_LOGE("heap is invalid");
90 } else {
91 delete [] holder->heap;
92 holder->heap = nullptr;
93 }
94 }
95 delete holder;
96 }
97
FreeAvBufferData(void *addr, void *context, uint32_t size)98 static void FreeAvBufferData(void *addr, void *context, uint32_t size)
99 {
100 (void)addr;
101 (void)size;
102 CHECK_AND_RETURN_LOG(context != nullptr, "context is nullptr");
103 AVBufferHolder *holder = reinterpret_cast<AVBufferHolder *>(context);
104 delete holder;
105 }
106
FreeSurfaceBuffer(void *addr, void *context, uint32_t size)107 static void FreeSurfaceBuffer(void *addr, void *context, uint32_t size)
108 {
109 (void)addr;
110 (void)size;
111 CHECK_AND_RETURN_LOG(context != nullptr, "context is nullptr");
112 void* nativeBuffer = context;
113 RefBase *ref = reinterpret_cast<RefBase *>(nativeBuffer);
114 ref->DecStrongRef(ref);
115 }
116
CreatePixelMapData(const std::shared_ptr<AVSharedMemory> &mem, const OutputFrame &frame)117 static PixelMapMemHolder *CreatePixelMapData(const std::shared_ptr<AVSharedMemory> &mem, const OutputFrame &frame)
118 {
119 PixelMapMemHolder *holder = new (std::nothrow) PixelMapMemHolder;
120 CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "alloc pixelmap mem holder failed");
121
122 ON_SCOPE_EXIT(0) {
123 delete holder;
124 };
125
126 int32_t minStride = frame.width_ * frame.bytesPerPixel_;
127 CHECK_AND_RETURN_RET_LOG(minStride <= frame.stride_, nullptr, "stride info wrong");
128
129 if (frame.stride_ == minStride) {
130 CANCEL_SCOPE_EXIT_GUARD(0);
131 holder->isShmem = true;
132 holder->shmem = mem;
133 holder->heap = frame.GetFlattenedData();
134 return holder;
135 }
136
137 static constexpr int64_t maxAllowedSize = 100 * 1024 * 1024;
138 int64_t memSize = static_cast<int64_t>(minStride) * frame.height_;
139 CHECK_AND_RETURN_RET_LOG(memSize <= maxAllowedSize, nullptr, "alloc heap size too large");
140
141 uint8_t *heap = new (std::nothrow) uint8_t[memSize];
142 CHECK_AND_RETURN_RET_LOG(heap != nullptr, nullptr, "alloc heap failed");
143
144 ON_SCOPE_EXIT(1) {
145 delete [] heap;
146 };
147
148 uint8_t *currDstPos = heap;
149 uint8_t *currSrcPos = frame.GetFlattenedData();
150 for (int32_t row = 0; row < frame.height_; ++row) {
151 errno_t rc = memcpy_s(currDstPos, static_cast<size_t>(memSize), currSrcPos, static_cast<size_t>(minStride));
152 CHECK_AND_RETURN_RET_LOG(rc == EOK, nullptr, "memcpy_s failed");
153
154 currDstPos += minStride;
155 currSrcPos += frame.stride_;
156 memSize -= minStride;
157 }
158
159 holder->isShmem = false;
160 holder->heap = heap;
161
162 CANCEL_SCOPE_EXIT_GUARD(0);
163 CANCEL_SCOPE_EXIT_GUARD(1);
164 return holder;
165 }
166
CreateAVBufferHolder(const std::shared_ptr<AVBuffer> &avBuffer)167 static AVBufferHolder *CreateAVBufferHolder(const std::shared_ptr<AVBuffer> &avBuffer)
168 {
169 CHECK_AND_RETURN_RET(avBuffer != nullptr && avBuffer->memory_ != nullptr, nullptr);
170 AVBufferHolder *holder = new (std::nothrow) AVBufferHolder;
171 CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "alloc avBuffer holder failed");
172 holder->buffer = avBuffer;
173 return holder;
174 }
175
CreatePixelMap(const std::shared_ptr<AVSharedMemory> &mem, PixelFormat color, int32_t &rotation)176 static std::shared_ptr<PixelMap> CreatePixelMap(const std::shared_ptr<AVSharedMemory> &mem, PixelFormat color,
177 int32_t &rotation)
178 {
179 CHECK_AND_RETURN_RET_LOG(mem != nullptr, nullptr, "Fetch frame failed");
180 CHECK_AND_RETURN_RET_LOG(mem->GetBase() != nullptr, nullptr, "Addr is nullptr");
181 CHECK_AND_RETURN_RET_LOG(mem->GetSize() > 0, nullptr, "size is incorrect");
182 CHECK_AND_RETURN_RET_LOG(static_cast<uint32_t>(mem->GetSize()) >= sizeof(OutputFrame),
183 nullptr, "size is incorrect");
184
185 OutputFrame *frame = reinterpret_cast<OutputFrame *>(mem->GetBase());
186 MEDIA_LOGD("width: %{public}d, stride : %{public}d, height: %{public}d, size: %{public}d, format: %{public}d",
187 frame->width_, frame->stride_, frame->height_, frame->size_, color);
188
189 rotation = frame->rotation_;
190 InitializationOptions opts;
191 opts.size.width = frame->width_;
192 opts.size.height = frame->height_;
193 opts.pixelFormat = color;
194 opts.editable = true;
195 std::shared_ptr<PixelMap> pixelMap = PixelMap::Create(opts);
196
197 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "pixelMap create failed");
198 CHECK_AND_RETURN_RET_LOG(pixelMap->GetByteCount() <= frame->size_, nullptr, "Size inconsistent !");
199
200 PixelMapMemHolder *holder = CreatePixelMapData(mem, *frame);
201 CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "create pixel map data failed");
202
203 pixelMap->SetPixelsAddr(holder->heap, holder, static_cast<uint32_t>(pixelMap->GetByteCount()),
204 AllocatorType::CUSTOM_ALLOC, FreePixelMapData);
205 return pixelMap;
206 }
207
SaveDataToFile(const std::string &fileName, const char *data, const size_t &totalSize)208 int32_t AVMetadataHelperImpl::SaveDataToFile(const std::string &fileName, const char *data, const size_t &totalSize)
209 {
210 CHECK_AND_RETURN_RET_LOG(data != nullptr, MSERR_INVALID_VAL, "data is nullptr");
211 std::ofstream outFile(FILE_DIR_IN_THE_SANDBOX + fileName, std::ofstream::out);
212 if (!outFile.is_open()) {
213 MEDIA_LOGI("winddraw::SaveDataToFile write error, path=%{public}s", fileName.c_str());
214 return MSERR_UNKNOWN;
215 }
216
217 outFile.write(data, totalSize);
218 return MSERR_OK;
219 }
220
InitDumpFlag()221 void AVMetadataHelperImpl::InitDumpFlag()
222 {
223 const std::string dumpTag = "sys.media.avmetadatahelper.dump.enable";
224 std::string dumpEnable;
225 int32_t dumpRes = OHOS::system::GetStringParameter(dumpTag, dumpEnable, "false");
226 isDump_ = (dumpEnable == "true");
227 MEDIA_LOGI("get dump flag, dumpRes: %{public}d, isDump_: %{public}d", dumpRes, isDump_);
228 }
229
DumpPixelMap(bool isDump, std::shared_ptr<PixelMap> pixelMap, const std::string &fileNameSuffix)230 int32_t AVMetadataHelperImpl::DumpPixelMap(bool isDump, std::shared_ptr<PixelMap> pixelMap,
231 const std::string &fileNameSuffix)
232 {
233 if (!isDump) {
234 return MSERR_INVALID_VAL;
235 }
236 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, MSERR_INVALID_VAL, "invalid pixelMap");
237 std::string width = std::to_string(pixelMap->GetWidth());
238 std::string height = std::to_string(pixelMap->GetHeight());
239 std::string pixelFormat = pixelFormatToString(pixelMap->GetPixelFormat());
240 auto fileName = GetLocalTime() + "_" + width + "_" + height + "_" + pixelFormat + fileNameSuffix;
241 if (pixelMap->GetAllocatorType() == AllocatorType::DMA_ALLOC) {
242 auto surfaceBuffer = static_cast<SurfaceBuffer*>(pixelMap->GetFd());
243 CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, MSERR_INVALID_VAL, "invalid surface buffer");
244 return SaveDataToFile(fileName,
245 reinterpret_cast<const char *>(surfaceBuffer->GetVirAddr()),
246 surfaceBuffer->GetSize());
247 }
248 return SaveDataToFile(fileName,
249 reinterpret_cast<const char *>(pixelMap->GetPixels()),
250 pixelMap->GetByteCount());
251 }
252
DumpAVBuffer(bool isDump, const std::shared_ptr<AVBuffer> &frameBuffer, const std::string &fileNameSuffix)253 int32_t AVMetadataHelperImpl::DumpAVBuffer(bool isDump, const std::shared_ptr<AVBuffer> &frameBuffer,
254 const std::string &fileNameSuffix)
255 {
256 if (!isDump) {
257 return MSERR_INVALID_VAL;
258 }
259 bool isValid = frameBuffer != nullptr && frameBuffer->meta_ != nullptr && frameBuffer->memory_ != nullptr;
260 CHECK_AND_RETURN_RET_LOG(isValid, MSERR_INVALID_VAL, "invalid frame buffer");
261 auto bufferMeta = frameBuffer->meta_;
262 int32_t width = 0;
263 int32_t height = 0;
264 bool isHdr = false;
265 bufferMeta->Get<Tag::VIDEO_WIDTH>(width);
266 bufferMeta->Get<Tag::VIDEO_HEIGHT>(height);
267 bufferMeta->Get<Tag::VIDEO_IS_HDR_VIVID>(isHdr);
268 std::string widthStr = std::to_string(width);
269 std::string heightStr = std::to_string(height);
270 std::string pixelFormat = isHdr ? pixelFormatToString(PixelFormat::YCBCR_P010):
271 pixelFormatToString(PixelFormat::NV12);
272 auto fileName = GetLocalTime() + "_" + widthStr + "_" + heightStr + "_" + pixelFormat + fileNameSuffix;
273 auto surfaceBuffer = frameBuffer->memory_->GetSurfaceBuffer();
274 if (surfaceBuffer == nullptr) {
275 return SaveDataToFile(fileName,
276 reinterpret_cast<const char *>(frameBuffer->memory_->GetAddr()),
277 frameBuffer->memory_->GetSize());
278 }
279 return SaveDataToFile(fileName,
280 reinterpret_cast<const char *>(surfaceBuffer->GetVirAddr()),
281 surfaceBuffer->GetSize());
282 }
283
pixelFormatToString(PixelFormat pixelFormat)284 std::string AVMetadataHelperImpl::pixelFormatToString(PixelFormat pixelFormat)
285 {
286 switch (pixelFormat) {
287 case PixelFormat::RGB_565:
288 return "RGB_565";
289 case PixelFormat::RGBA_8888:
290 return "RGBA_8888";
291 case PixelFormat::RGB_888:
292 return "RGB_888";
293 case PixelFormat::NV12:
294 return "NV12";
295 case PixelFormat::YCBCR_P010:
296 return "YCBCR_P010";
297 default:
298 return "UNKNOWN";
299 }
300 }
301
CreatePixelMapYuv(const std::shared_ptr<AVBuffer> &frameBuffer, PixelMapInfo &pixelMapInfo)302 std::shared_ptr<PixelMap> AVMetadataHelperImpl::CreatePixelMapYuv(const std::shared_ptr<AVBuffer> &frameBuffer,
303 PixelMapInfo &pixelMapInfo)
304 {
305 bool isValid = frameBuffer != nullptr && frameBuffer->meta_ != nullptr && frameBuffer->memory_ != nullptr;
306 CHECK_AND_RETURN_RET_LOG(isValid, nullptr, "invalid frame buffer");
307 auto bufferMeta = frameBuffer->meta_;
308
309 int32_t width = 0;
310 auto hasProperty = bufferMeta->Get<Tag::VIDEO_WIDTH>(width);
311 CHECK_AND_RETURN_RET_LOG(hasProperty, nullptr, "invalid width");
312 int32_t height = 0;
313 hasProperty = bufferMeta->Get<Tag::VIDEO_HEIGHT>(height);
314 CHECK_AND_RETURN_RET_LOG(hasProperty, nullptr, "invalid height");
315
316 Plugins::VideoRotation rotation = Plugins::VideoRotation::VIDEO_ROTATION_0;
317 bufferMeta->Get<Tag::VIDEO_ROTATION>(rotation);
318 pixelMapInfo.rotation = static_cast<int32_t>(rotation);
319 bufferMeta->Get<Tag::VIDEO_IS_HDR_VIVID>(pixelMapInfo.isHdr);
320
321 if (frameBuffer->memory_->GetSize() != 0 && frameBuffer->memory_->GetSurfaceBuffer() == nullptr) {
322 InitializationOptions options = { .size = { .width = width, .height = height },
323 .pixelFormat = PixelFormat::NV12 };
324 return CreatePixelMapFromAVShareMemory(frameBuffer, pixelMapInfo, options);
325 }
326
327 auto surfaceBuffer = frameBuffer->memory_->GetSurfaceBuffer();
328 CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, nullptr, "srcSurfaceBuffer is nullptr");
329 sptr<SurfaceBuffer> mySurfaceBuffer = CopySurfaceBuffer(surfaceBuffer);
330 CHECK_AND_RETURN_RET_LOG(mySurfaceBuffer != nullptr, nullptr, "Create SurfaceBuffer failed");
331
332 int32_t outputHeight = height;
333 bufferMeta->Get<Tag::VIDEO_SLICE_HEIGHT>(outputHeight);
334 pixelMapInfo.outputHeight = outputHeight;
335 MEDIA_LOGD("pixelMapInfo.outputHeight = %{public}d", pixelMapInfo.outputHeight);
336
337 return CreatePixelMapFromSurfaceBuffer(mySurfaceBuffer, pixelMapInfo);
338 }
339
CreatePixelMapFromAVShareMemory(const std::shared_ptr<AVBuffer> &frameBuffer, PixelMapInfo &pixelMapInfo, InitializationOptions &options)340 std::shared_ptr<PixelMap> AVMetadataHelperImpl::CreatePixelMapFromAVShareMemory(const std::shared_ptr<AVBuffer>
341 &frameBuffer,
342 PixelMapInfo &pixelMapInfo,
343 InitializationOptions &options)
344 {
345 bool isValid = frameBuffer != nullptr && frameBuffer->memory_ != nullptr;
346 CHECK_AND_RETURN_RET_LOG(isValid, nullptr, "invalid frame buffer");
347 std::shared_ptr<PixelMap> pixelMap = PixelMap::Create(options);
348 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Create pixelMap failed");
349 AVBufferHolder *holder = CreateAVBufferHolder(frameBuffer);
350 CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "Create buffer holder failed");
351 uint8_t *pixelAddr = frameBuffer->memory_->GetAddr();
352 pixelMap->SetPixelsAddr(pixelAddr, holder, pixelMap->GetByteCount(),
353 AllocatorType::CUSTOM_ALLOC, FreeAvBufferData);
354 const InitializationOptions opts = { .size = { .width = pixelMap->GetWidth(),
355 .height = pixelMap->GetHeight() },
356 .srcPixelFormat = PixelFormat::NV12,
357 .pixelFormat = pixelMapInfo.pixelFormat };
358 pixelMap = PixelMap::Create(reinterpret_cast<const uint32_t *>(pixelMap->GetPixels()),
359 pixelMap->GetByteCount(), opts);
360 sptr<SurfaceBuffer> surfaceBuffer = nullptr;
361 SetPixelMapYuvInfo(surfaceBuffer, pixelMap, pixelMapInfo);
362 return pixelMap;
363 }
364
CreatePixelMapFromSurfaceBuffer(sptr<SurfaceBuffer> &surfaceBuffer, PixelMapInfo &pixelMapInfo)365 std::shared_ptr<PixelMap> AVMetadataHelperImpl::CreatePixelMapFromSurfaceBuffer(sptr<SurfaceBuffer> &surfaceBuffer,
366 PixelMapInfo &pixelMapInfo)
367 {
368 CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, nullptr, "surfaceBuffer is nullptr");
369 InitializationOptions options = { .size = { .width = surfaceBuffer->GetWidth(),
370 .height = surfaceBuffer->GetHeight() } };
371 bool isHdr = pixelMapInfo.isHdr;
372 options.srcPixelFormat = isHdr ? PixelFormat::YCBCR_P010 : PixelFormat::NV12;
373 options.pixelFormat = isHdr ? PixelFormat::YCBCR_P010 : PixelFormat::NV12;
374 options.useDMA = (isHdr || pixelMapInfo.pixelFormat == PixelFormat::NV12) ? true : false;
375 int32_t colorLength = surfaceBuffer->GetWidth() * surfaceBuffer->GetHeight() * PIXEL_SIZE_HDR_YUV;
376 colorLength = isHdr ? colorLength : colorLength / HDR_PIXEL_SIZE;
377 std::shared_ptr<PixelMap> pixelMap;
378
379 if (!options.useDMA) {
380 pixelMap = PixelMap::Create(options);
381 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Create pixelMap failed");
382 auto ret = CopySurfaceBufferToPixelMap(surfaceBuffer, pixelMap, pixelMapInfo);
383 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "CopySurfaceBufferToPixelMap failed");
384 options.pixelFormat = pixelMapInfo.pixelFormat;
385 pixelMap = PixelMap::Create(reinterpret_cast<const uint32_t *>(pixelMap->GetPixels()),
386 pixelMap->GetByteCount(), options);
387 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Create non-DMA pixelMap failed");
388 } else {
389 pixelMap = PixelMap::Create(reinterpret_cast<const uint32_t *>(surfaceBuffer->GetVirAddr()),
390 static_cast<uint32_t>(colorLength), options);
391 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "Create DMA pixelMap failed");
392 void* nativeBuffer = surfaceBuffer.GetRefPtr();
393 RefBase *ref = reinterpret_cast<RefBase *>(nativeBuffer);
394 ref->IncStrongRef(ref);
395 if (isHdr) {
396 pixelMap->InnerSetColorSpace(OHOS::ColorManager::ColorSpace(ColorManager::ColorSpaceName::BT2020_HLG));
397 }
398 pixelMap->SetPixelsAddr(surfaceBuffer->GetVirAddr(), surfaceBuffer.GetRefPtr(), surfaceBuffer->GetSize(),
399 AllocatorType::DMA_ALLOC, FreeSurfaceBuffer);
400 }
401
402 SetPixelMapYuvInfo(surfaceBuffer, pixelMap, pixelMapInfo);
403
404 return pixelMap;
405 }
406
CopySurfaceBufferToPixelMap(sptr<SurfaceBuffer> &surfaceBuffer, std::shared_ptr<PixelMap> pixelMap, PixelMapInfo &pixelMapInfo)407 int32_t AVMetadataHelperImpl::CopySurfaceBufferToPixelMap(sptr<SurfaceBuffer> &surfaceBuffer,
408 std::shared_ptr<PixelMap> pixelMap,
409 PixelMapInfo &pixelMapInfo)
410 {
411 CHECK_AND_RETURN_RET(surfaceBuffer != nullptr && pixelMap != nullptr, MSERR_INVALID_VAL);
412 int32_t width = surfaceBuffer->GetWidth();
413 int32_t height = surfaceBuffer->GetHeight();
414 int32_t stride = surfaceBuffer->GetStride();
415
416 uint8_t *srcPtr = static_cast<uint8_t *>(surfaceBuffer->GetVirAddr());
417 uint8_t *dstPtr = const_cast<uint8_t *>(pixelMap->GetPixels());
418 // copy src Y component to dst
419 int32_t lineByteCount = width;
420 for (int32_t y = 0; y < height; y++) {
421 auto ret = memcpy_s(dstPtr, lineByteCount, srcPtr, lineByteCount);
422 TRUE_LOG(ret != EOK, MEDIA_LOGW, "Memcpy Y component failed.");
423 srcPtr += stride;
424 dstPtr += lineByteCount;
425 }
426
427 srcPtr = static_cast<uint8_t *>(surfaceBuffer->GetVirAddr()) + stride * pixelMapInfo.outputHeight;
428
429 // copy src UV component to dst, height(UV) = height(Y) / 2
430 for (int32_t uv = 0; uv < height / 2; uv++) {
431 auto ret = memcpy_s(dstPtr, lineByteCount, srcPtr, lineByteCount);
432 TRUE_LOG(ret != EOK, MEDIA_LOGW, "Memcpy UV component failed.");
433 srcPtr += stride;
434 dstPtr += lineByteCount;
435 }
436 return MSERR_OK;
437 }
438
SetPixelMapYuvInfo(sptr<SurfaceBuffer> &surfaceBuffer, std::shared_ptr<PixelMap> pixelMap, PixelMapInfo &pixelMapInfo)439 void AVMetadataHelperImpl::SetPixelMapYuvInfo(sptr<SurfaceBuffer> &surfaceBuffer, std::shared_ptr<PixelMap> pixelMap,
440 PixelMapInfo &pixelMapInfo)
441 {
442 CHECK_AND_RETURN_LOG(pixelMap != nullptr, "invalid pixelMap");
443 uint8_t ratio = pixelMapInfo.isHdr ? HDR_PIXEL_SIZE : SDR_PIXEL_SIZE;
444 int32_t srcWidth = pixelMap->GetWidth();
445 int32_t srcHeight = pixelMap->GetHeight();
446 YUVDataInfo yuvDataInfo = { .yWidth = srcWidth,
447 .yHeight = srcHeight,
448 .uvWidth = srcWidth / 2,
449 .uvHeight = srcHeight / 2,
450 .yStride = srcWidth,
451 .uvStride = srcWidth,
452 .uvOffset = srcWidth * srcHeight};
453
454 if (surfaceBuffer == nullptr) {
455 pixelMap->SetImageYUVInfo(yuvDataInfo);
456 return;
457 }
458 OH_NativeBuffer_Planes *planes = nullptr;
459 GSError retVal = surfaceBuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
460 if (retVal != OHOS::GSERROR_OK || planes == nullptr) {
461 pixelMap->SetImageYUVInfo(yuvDataInfo);
462 return;
463 }
464
465 yuvDataInfo.yStride = planes->planes[PLANE_Y].columnStride / ratio;
466 yuvDataInfo.uvStride = planes->planes[PLANE_U].columnStride / ratio;
467 yuvDataInfo.yOffset = planes->planes[PLANE_Y].offset / ratio;
468 yuvDataInfo.uvOffset = planes->planes[PLANE_U].offset / ratio;
469
470 pixelMap->SetImageYUVInfo(yuvDataInfo);
471 }
472
CopySurfaceBuffer(sptr<SurfaceBuffer> &srcSurfaceBuffer)473 sptr<SurfaceBuffer> AVMetadataHelperImpl::CopySurfaceBuffer(sptr<SurfaceBuffer> &srcSurfaceBuffer)
474 {
475 CHECK_AND_RETURN_RET_LOG(srcSurfaceBuffer != nullptr, nullptr, "srcSurfaceBuffer is nullptr");
476 sptr<SurfaceBuffer> dstSurfaceBuffer = SurfaceBuffer::Create();
477 BufferRequestConfig requestConfig = {
478 .width = srcSurfaceBuffer->GetWidth(),
479 .height = srcSurfaceBuffer->GetHeight(),
480 .strideAlignment = 0x2,
481 .format = srcSurfaceBuffer->GetFormat(), // always yuv
482 .usage = srcSurfaceBuffer->GetUsage(),
483 .timeout = 0,
484 };
485 CHECK_AND_RETURN_RET_LOG(dstSurfaceBuffer != nullptr, nullptr, "Create surfaceBuffer failed");
486 GSError allocRes = dstSurfaceBuffer->Alloc(requestConfig);
487 CHECK_AND_RETURN_RET_LOG(allocRes == 0, nullptr, "Alloc surfaceBuffer failed, ecode %{public}d", allocRes);
488
489 CopySurfaceBufferInfo(srcSurfaceBuffer, dstSurfaceBuffer);
490 int32_t copyRes = memcpy_s(dstSurfaceBuffer->GetVirAddr(), dstSurfaceBuffer->GetSize(),
491 srcSurfaceBuffer->GetVirAddr(), srcSurfaceBuffer->GetSize());
492 CHECK_AND_RETURN_RET_LOG(copyRes == EOK, nullptr, "copy surface buffer pixels failed, copyRes %{public}d", copyRes);
493 return dstSurfaceBuffer;
494 }
495
CopySurfaceBufferInfo(sptr<SurfaceBuffer> &source, sptr<SurfaceBuffer> &dst)496 void AVMetadataHelperImpl::CopySurfaceBufferInfo(sptr<SurfaceBuffer> &source, sptr<SurfaceBuffer> &dst)
497 {
498 if (source == nullptr || dst == nullptr) {
499 MEDIA_LOGI("CopySurfaceBufferInfo failed, source or dst is nullptr");
500 return;
501 }
502 std::vector<uint8_t> hdrMetadataTypeVec;
503 std::vector<uint8_t> colorSpaceInfoVec;
504 std::vector<uint8_t> staticData;
505 std::vector<uint8_t> dynamicData;
506
507 if (source->GetMetadata(ATTRKEY_HDR_METADATA_TYPE, hdrMetadataTypeVec) == GSERROR_OK) {
508 dst->SetMetadata(ATTRKEY_HDR_METADATA_TYPE, hdrMetadataTypeVec);
509 }
510 if (source->GetMetadata(ATTRKEY_COLORSPACE_INFO, colorSpaceInfoVec) == GSERROR_OK) {
511 dst->SetMetadata(ATTRKEY_COLORSPACE_INFO, colorSpaceInfoVec);
512 }
513 if (GetSbStaticMetadata(source, staticData) && (staticData.size() > 0)) {
514 SetSbStaticMetadata(dst, staticData);
515 }
516 if (GetSbDynamicMetadata(source, dynamicData) && (dynamicData.size()) > 0) {
517 SetSbDynamicMetadata(dst, dynamicData);
518 }
519 }
520
GetSbStaticMetadata(sptr<SurfaceBuffer> &buffer, std::vector<uint8_t> &staticMetadata)521 bool AVMetadataHelperImpl::GetSbStaticMetadata(sptr<SurfaceBuffer> &buffer, std::vector<uint8_t> &staticMetadata)
522 {
523 return buffer->GetMetadata(ATTRKEY_HDR_STATIC_METADATA, staticMetadata) == GSERROR_OK;
524 }
525
GetSbDynamicMetadata(sptr<SurfaceBuffer> &buffer, std::vector<uint8_t> &dynamicMetadata)526 bool AVMetadataHelperImpl::GetSbDynamicMetadata(sptr<SurfaceBuffer> &buffer, std::vector<uint8_t> &dynamicMetadata)
527 {
528 return buffer->GetMetadata(ATTRKEY_HDR_DYNAMIC_METADATA, dynamicMetadata) == GSERROR_OK;
529 }
530
SetSbStaticMetadata(sptr<SurfaceBuffer> &buffer, const std::vector<uint8_t> &staticMetadata)531 bool AVMetadataHelperImpl::SetSbStaticMetadata(sptr<SurfaceBuffer> &buffer, const std::vector<uint8_t> &staticMetadata)
532 {
533 return buffer->SetMetadata(ATTRKEY_HDR_STATIC_METADATA, staticMetadata) == GSERROR_OK;
534 }
535
SetSbDynamicMetadata(sptr<SurfaceBuffer> &buffer, const std::vector<uint8_t> &dynamicMetadata)536 bool AVMetadataHelperImpl::SetSbDynamicMetadata(sptr<SurfaceBuffer> &buffer,
537 const std::vector<uint8_t> &dynamicMetadata)
538 {
539 return buffer->SetMetadata(ATTRKEY_HDR_DYNAMIC_METADATA, dynamicMetadata) == GSERROR_OK;
540 }
541
CreateAVMetadataHelper()542 std::shared_ptr<AVMetadataHelper> AVMetadataHelperFactory::CreateAVMetadataHelper()
543 {
544 std::shared_ptr<AVMetadataHelperImpl> impl = std::make_shared<AVMetadataHelperImpl>();
545 CHECK_AND_RETURN_RET_LOG(impl != nullptr, nullptr, "failed to new AVMetadataHelperImpl");
546
547 int32_t ret = impl->Init();
548 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "failed to init AVMetadataHelperImpl");
549
550 return impl;
551 }
552
Init()553 int32_t AVMetadataHelperImpl::Init()
554 {
555 avMetadataHelperService_ = MediaServiceFactory::GetInstance().CreateAVMetadataHelperService();
556 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
557 "failed to create avmetadatahelper service");
558 InitDumpFlag();
559 return MSERR_OK;
560 }
561
AVMetadataHelperImpl()562 AVMetadataHelperImpl::AVMetadataHelperImpl()
563 {
564 MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
565 }
566
~AVMetadataHelperImpl()567 AVMetadataHelperImpl::~AVMetadataHelperImpl()
568 {
569 if (avMetadataHelperService_ != nullptr) {
570 (void)MediaServiceFactory::GetInstance().DestroyAVMetadataHelperService(avMetadataHelperService_);
571 avMetadataHelperService_ = nullptr;
572 }
573 MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
574 }
575
SetHelperCallback(const std::shared_ptr<HelperCallback> &callback)576 int32_t AVMetadataHelperImpl::SetHelperCallback(const std::shared_ptr<HelperCallback> &callback)
577 {
578 MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " SetHelperCallback in", FAKE_POINTER(this));
579 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_SERVICE_DIED,
580 "metadata helper service does not exist..");
581 CHECK_AND_RETURN_RET_LOG(callback != nullptr, MSERR_INVALID_VAL, "callback is nullptr");
582 return avMetadataHelperService_->SetHelperCallback(callback);
583 }
584
SetScene(Scene scene)585 void AVMetadataHelperImpl::SetScene(Scene scene)
586 {
587 ReportSceneCode(scene);
588 }
589
ReportSceneCode(Scene scene)590 void AVMetadataHelperImpl::ReportSceneCode(Scene scene)
591 {
592 if (scene != Scene::AV_META_SCENE_CLONE && scene != Scene::AV_META_SCENE_BATCH_HANDLE) {
593 return;
594 }
595 if (scene == Scene::AV_META_SCENE_BATCH_HANDLE && concurrentWorkCount_ < HIGH_CONCRENT_WORK_NUM) {
596 return;
597 }
598 auto sceneCode = SCENE_CODE_MAP[scene];
599 auto lastTsp = SCENE_TIMESTAMP_MAP[scene];
600 auto now =
601 std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
602 auto duration = now - std::chrono::milliseconds(lastTsp);
603 if (duration < std::chrono::milliseconds(SCENE_CODE_EFFECTIVE_DURATION_MS)) {
604 return;
605 }
606 SCENE_TIMESTAMP_MAP[scene] = now.count();
607 MEDIA_LOGI("Report scene code %{public}ld", sceneCode);
608 int32_t ret = HiSysEventWrite(
609 PERFORMANCE_STATS, "CPU_SCENE_ENTRY", OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR, "PACKAGE_NAME",
610 "media_service", "SCENE_ID", std::to_string(sceneCode).c_str(), "HAPPEN_TIME", now.count());
611 if (ret != MSERR_OK) {
612 MEDIA_LOGW("report error");
613 }
614 }
615
SetSource(const std::string &uri, int32_t usage)616 int32_t AVMetadataHelperImpl::SetSource(const std::string &uri, int32_t usage)
617 {
618 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
619 "avmetadatahelper service does not exist..");
620 CHECK_AND_RETURN_RET_LOG(!uri.empty(), MSERR_INVALID_VAL, "uri is empty.");
621
622 concurrentWorkCount_++;
623 ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
624 auto res = avMetadataHelperService_->SetSource(uri, usage);
625 concurrentWorkCount_--;
626 return res;
627 }
628
SetSource(int32_t fd, int64_t offset, int64_t size, int32_t usage)629 int32_t AVMetadataHelperImpl::SetSource(int32_t fd, int64_t offset, int64_t size, int32_t usage)
630 {
631 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
632 "avmetadatahelper service does not exist..");
633 MEDIA_LOGI("Set file source fd: %{public}d, offset: %{public}" PRIu64 ", size: %{public}" PRIu64,
634 fd, offset, size);
635
636 concurrentWorkCount_++;
637 ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
638 auto res = avMetadataHelperService_->SetSource(fd, offset, size, usage);
639 concurrentWorkCount_--;
640 return res;
641 }
642
SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)643 int32_t AVMetadataHelperImpl::SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)
644 {
645 MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " SetSource in(dataSrc)", FAKE_POINTER(this));
646 CHECK_AND_RETURN_RET_LOG(dataSrc != nullptr, MSERR_INVALID_VAL, "failed to create data source");
647
648 concurrentWorkCount_++;
649 ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
650 auto res = avMetadataHelperService_->SetSource(dataSrc);
651 concurrentWorkCount_--;
652 return res;
653 }
654
ResolveMetadata(int32_t key)655 std::string AVMetadataHelperImpl::ResolveMetadata(int32_t key)
656 {
657 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, "",
658 "avmetadatahelper service does not exist.");
659 concurrentWorkCount_++;
660 auto res = avMetadataHelperService_->ResolveMetadata(key);
661 concurrentWorkCount_--;
662 return res;
663 }
664
ResolveMetadata()665 std::unordered_map<int32_t, std::string> AVMetadataHelperImpl::ResolveMetadata()
666 {
667 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, {},
668 "avmetadatahelper service does not exist.");
669 concurrentWorkCount_++;
670 auto res = avMetadataHelperService_->ResolveMetadata();
671 concurrentWorkCount_--;
672 return res;
673 }
674
GetAVMetadata()675 std::shared_ptr<Meta> AVMetadataHelperImpl::GetAVMetadata()
676 {
677 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
678 "avmetadatahelper service does not exist.");
679 concurrentWorkCount_++;
680 auto res = avMetadataHelperService_->GetAVMetadata();
681 concurrentWorkCount_--;
682 return res;
683 }
684
FetchArtPicture()685 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchArtPicture()
686 {
687 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
688 "avmetadatahelper service does not exist.");
689 concurrentWorkCount_++;
690 auto res = avMetadataHelperService_->FetchArtPicture();
691 concurrentWorkCount_--;
692 return res;
693 }
694
FetchFrameAtTime( int64_t timeUs, int32_t option, const PixelMapParams ¶m)695 std::shared_ptr<PixelMap> AVMetadataHelperImpl::FetchFrameAtTime(
696 int64_t timeUs, int32_t option, const PixelMapParams ¶m)
697 {
698 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
699 "avmetadatahelper service does not exist.");
700
701 concurrentWorkCount_++;
702 ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
703
704 OutputConfiguration config;
705 config.colorFormat = param.colorFormat;
706 config.dstHeight = param.dstHeight;
707 config.dstWidth = param.dstWidth;
708
709 auto mem = avMetadataHelperService_->FetchFrameAtTime(timeUs, option, config);
710 auto pixelMap = CreatePixelMap(mem, PixelFormat::NV12, rotation_);
711
712 concurrentWorkCount_--;
713
714 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "pixelMap does not exist.");
715
716 const InitializationOptions opts = { .size = { .width = pixelMap->GetWidth(), .height = pixelMap->GetHeight() },
717 .srcPixelFormat = PixelFormat::NV12 };
718 pixelMap =
719 PixelMap::Create(reinterpret_cast<const uint32_t *>(pixelMap->GetPixels()), pixelMap->GetByteCount(), opts);
720 if (pixelMap == nullptr) {
721 return nullptr;
722 }
723 if (rotation_ > 0) {
724 pixelMap->rotate(rotation_);
725 }
726 int32_t srcWidth = pixelMap->GetWidth();
727 int32_t srcHeight = pixelMap->GetHeight();
728 bool needScale = (param.dstWidth > 0 && param.dstHeight > 0) &&
729 (param.dstWidth <= srcWidth && param.dstHeight <= srcHeight) &&
730 (param.dstWidth < srcWidth || param.dstHeight < srcHeight) && srcWidth > 0 && srcHeight > 0;
731 if (needScale) {
732 pixelMap->scale((1.0f * param.dstWidth) / srcWidth, (1.0f * param.dstHeight) / srcHeight);
733 }
734 return pixelMap;
735 }
736
ScalePixelMap( std::shared_ptr<PixelMap> &pixelMap, PixelMapInfo &info, const PixelMapParams ¶m)737 void AVMetadataHelperImpl::ScalePixelMap(
738 std::shared_ptr<PixelMap> &pixelMap, PixelMapInfo &info, const PixelMapParams ¶m)
739 {
740 int32_t srcWidth = pixelMap->GetWidth();
741 int32_t srcHeight = pixelMap->GetHeight();
742 int32_t dstWidth = info.rotation % NUM_180 == 0 ? param.dstWidth : param.dstHeight;
743 int32_t dstHeight = info.rotation % NUM_180 == 0 ? param.dstHeight : param.dstWidth;
744 bool needScale = (dstWidth > 0 && dstHeight > 0) &&
745 (dstWidth <= srcWidth && dstHeight <= srcHeight) &&
746 (dstWidth < srcWidth || dstHeight < srcHeight) && srcWidth > 0 && srcHeight > 0;
747 CHECK_AND_RETURN(needScale);
748 pixelMap->scale((1.0f * dstWidth) / srcWidth, (1.0f * dstHeight) / srcHeight);
749 }
750
FetchFrameYuv(int64_t timeUs, int32_t option, const PixelMapParams ¶m)751 std::shared_ptr<PixelMap> AVMetadataHelperImpl::FetchFrameYuv(int64_t timeUs, int32_t option,
752 const PixelMapParams ¶m)
753 {
754 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr, "avmetadatahelper service does not exist.");
755
756 concurrentWorkCount_++;
757 ReportSceneCode(AV_META_SCENE_BATCH_HANDLE);
758 OutputConfiguration config = { .dstWidth = param.dstWidth,
759 .dstHeight = param.dstHeight,
760 .colorFormat = param.colorFormat };
761 auto frameBuffer = avMetadataHelperService_->FetchFrameYuv(timeUs, option, config);
762 CHECK_AND_RETURN_RET(frameBuffer != nullptr && frameBuffer->memory_ != nullptr, nullptr);
763 concurrentWorkCount_--;
764
765 DumpAVBuffer(isDump_, frameBuffer, DUMP_FILE_NAME_AVBUFFER);
766
767 PixelMapInfo pixelMapInfo = { .pixelFormat = param.colorFormat };
768 auto pixelMap = CreatePixelMapYuv(frameBuffer, pixelMapInfo);
769 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "convert to pixelMap failed");
770
771 DumpPixelMap(isDump_, pixelMap, DUMP_FILE_NAME_PIXEMAP);
772
773 ScalePixelMap(pixelMap, pixelMapInfo, param);
774
775 DumpPixelMap(isDump_, pixelMap, DUMP_FILE_NAME_AFTER_SCLAE);
776
777 if (pixelMapInfo.rotation > 0) {
778 pixelMap->rotate(pixelMapInfo.rotation);
779 }
780
781 DumpPixelMap(isDump_, pixelMap, DUMP_FILE_NAME_AFTER_ROTATE);
782 return pixelMap;
783 }
784
GetTimeByFrameIndex(uint32_t index, uint64_t &time)785 int32_t AVMetadataHelperImpl::GetTimeByFrameIndex(uint32_t index, uint64_t &time)
786 {
787 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, 0, "avmetadatahelper service does not exist.");
788 concurrentWorkCount_++;
789 auto res = avMetadataHelperService_->GetTimeByFrameIndex(index, time);
790 concurrentWorkCount_--;
791 return res;
792 }
793
GetFrameIndexByTime(uint64_t time, uint32_t &index)794 int32_t AVMetadataHelperImpl::GetFrameIndexByTime(uint64_t time, uint32_t &index)
795 {
796 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, 0, "avmetadatahelper service does not exist.");
797 concurrentWorkCount_++;
798 auto res = avMetadataHelperService_->GetFrameIndexByTime(time, index);
799 concurrentWorkCount_--;
800 return res;
801 }
802
Release()803 void AVMetadataHelperImpl::Release()
804 {
805 MEDIA_LOGI("0x%{public}06" PRIXPTR " Release", FAKE_POINTER(this));
806 CHECK_AND_RETURN_LOG(avMetadataHelperService_ != nullptr, "avmetadatahelper service does not exist.");
807 avMetadataHelperService_->Release();
808 (void)MediaServiceFactory::GetInstance().DestroyAVMetadataHelperService(avMetadataHelperService_);
809 avMetadataHelperService_ = nullptr;
810 }
811
SetIsNapiInstance(bool isNapiInstance)812 void AVMetadataHelperImpl::SetIsNapiInstance(bool isNapiInstance)
813 {
814 CHECK_AND_RETURN_LOG(avMetadataHelperService_ != nullptr, "avmetadatahelper service does not exist.");
815 avMetadataHelperService_->SetIsNapiInstance(isNapiInstance);
816 }
817 } // namespace Media
818 } // namespace OHOS
819