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 &param)695 std::shared_ptr<PixelMap> AVMetadataHelperImpl::FetchFrameAtTime(
696     int64_t timeUs, int32_t option, const PixelMapParams &param)
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 &param)737 void AVMetadataHelperImpl::ScalePixelMap(
738     std::shared_ptr<PixelMap> &pixelMap, PixelMapInfo &info, const PixelMapParams &param)
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 &param)751 std::shared_ptr<PixelMap> AVMetadataHelperImpl::FetchFrameYuv(int64_t timeUs, int32_t option,
752                                                               const PixelMapParams &param)
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