1 /*
2 * Copyright (C) 2021 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 #include "securec.h"
18 #include "i_media_service.h"
19 #include "media_log.h"
20 #include "media_errors.h"
21 #include "scope_guard.h"
22
23 namespace {
24 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN, "AVMetadatahelperImpl"};
25 }
26
27 namespace OHOS {
28 namespace Media {
29 struct PixelMapMemHolder {
30 bool isShmem;
31 std::shared_ptr<AVSharedMemory> shmem;
32 uint8_t *heap;
33 };
34
FreePixelMapData(void * addr,void * context,uint32_t size)35 static void FreePixelMapData(void *addr, void *context, uint32_t size)
36 {
37 (void)size;
38
39 MEDIA_LOGD("free pixel map data");
40
41 CHECK_AND_RETURN_LOG(context != nullptr, "context is nullptr");
42 PixelMapMemHolder *holder = reinterpret_cast<PixelMapMemHolder *>(context);
43 if (holder->isShmem) {
44 if (holder->shmem == nullptr) {
45 MEDIA_LOGE("shmem is nullptr");
46 }
47 holder->shmem = nullptr;
48 holder->heap = nullptr;
49 } else {
50 if (holder->heap == nullptr || holder->heap != addr) {
51 MEDIA_LOGE("heap is invalid");
52 } else {
53 delete [] holder->heap;
54 holder->heap = nullptr;
55 }
56 }
57 delete holder;
58 }
59
CreatePixelMapData(const std::shared_ptr<AVSharedMemory> & mem,const OutputFrame & frame)60 static PixelMapMemHolder *CreatePixelMapData(const std::shared_ptr<AVSharedMemory> &mem, const OutputFrame &frame)
61 {
62 PixelMapMemHolder *holder = new (std::nothrow) PixelMapMemHolder;
63 CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "alloc pixelmap mem holder failed");
64
65 ON_SCOPE_EXIT(0) { delete holder; };
66
67 int32_t minStride = frame.width_ * frame.bytesPerPixel_;
68 CHECK_AND_RETURN_RET_LOG(minStride <= frame.stride_, nullptr, "stride info wrong");
69
70 if (frame.stride_ == minStride) {
71 CANCEL_SCOPE_EXIT_GUARD(0);
72 holder->isShmem = true;
73 holder->shmem = mem;
74 holder->heap = frame.GetFlattenedData();
75 return holder;
76 }
77
78 static constexpr int64_t maxAllowedSize = 100 * 1024 * 1024;
79 int64_t memSize = static_cast<int64_t>(minStride) * frame.height_;
80 CHECK_AND_RETURN_RET_LOG(memSize <= maxAllowedSize, nullptr, "alloc heap size too large");
81
82 uint8_t *heap = new (std::nothrow) uint8_t[memSize];
83 CHECK_AND_RETURN_RET_LOG(heap != nullptr, nullptr, "alloc heap failed");
84
85 ON_SCOPE_EXIT(1) { delete [] heap; };
86
87 uint8_t *currDstPos = heap;
88 uint8_t *currSrcPos = frame.GetFlattenedData();
89 for (int32_t row = 0; row < frame.height_; ++row) {
90 errno_t rc = memcpy_s(currDstPos, static_cast<size_t>(memSize), currSrcPos, static_cast<size_t>(minStride));
91 CHECK_AND_RETURN_RET_LOG(rc == EOK, nullptr, "memcpy_s failed");
92
93 currDstPos += minStride;
94 currSrcPos += frame.stride_;
95 memSize -= minStride;
96 }
97
98 holder->isShmem = false;
99 holder->heap = heap;
100
101 CANCEL_SCOPE_EXIT_GUARD(0);
102 CANCEL_SCOPE_EXIT_GUARD(1);
103 return holder;
104 }
105
CreatePixelMap(const std::shared_ptr<AVSharedMemory> & mem,PixelFormat color)106 static std::shared_ptr<PixelMap> CreatePixelMap(const std::shared_ptr<AVSharedMemory> &mem, PixelFormat color)
107 {
108 CHECK_AND_RETURN_RET_LOG(mem != nullptr, nullptr, "Fetch frame failed");
109 CHECK_AND_RETURN_RET_LOG(mem->GetBase() != nullptr, nullptr, "Addr is nullptr");
110 CHECK_AND_RETURN_RET_LOG(mem->GetSize() > 0, nullptr, "size is incorrect");
111 CHECK_AND_RETURN_RET_LOG(static_cast<uint32_t>(mem->GetSize()) >= sizeof(OutputFrame),
112 nullptr, "size is incorrect");
113
114 OutputFrame *frame = reinterpret_cast<OutputFrame *>(mem->GetBase());
115 MEDIA_LOGD("width: %{public}d, stride : %{public}d, height: %{public}d, size: %{public}d, format: %{public}d",
116 frame->width_, frame->stride_, frame->height_, frame->size_, color);
117
118 ImageInfo info;
119 info.size.width = frame->width_;
120 info.size.height = frame->height_;
121 info.pixelFormat = color;
122 info.colorSpace = ColorSpace::SRGB;
123
124 std::shared_ptr<PixelMap> pixelMap = std::make_shared<PixelMap>();
125 uint32_t ret = pixelMap->SetImageInfo(info);
126 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "Set image info failed");
127 CHECK_AND_RETURN_RET_LOG(pixelMap->GetByteCount() <= frame->size_, nullptr, "Size inconsistent !");
128
129 PixelMapMemHolder *holder = CreatePixelMapData(mem, *frame);
130 CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "create pixel map data failed");
131
132 pixelMap->SetPixelsAddr(holder->heap, holder, static_cast<uint32_t>(pixelMap->GetByteCount()),
133 AllocatorType::CUSTOM_ALLOC, FreePixelMapData);
134 return pixelMap;
135 }
136
CreateAVMetadataHelper()137 std::shared_ptr<AVMetadataHelper> AVMetadataHelperFactory::CreateAVMetadataHelper()
138 {
139 std::shared_ptr<AVMetadataHelperImpl> impl = std::make_shared<AVMetadataHelperImpl>();
140 CHECK_AND_RETURN_RET_LOG(impl != nullptr, nullptr, "failed to new AVMetadataHelperImpl");
141
142 int32_t ret = impl->Init();
143 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "failed to init AVMetadataHelperImpl");
144
145 return impl;
146 }
147
Init()148 int32_t AVMetadataHelperImpl::Init()
149 {
150 avMetadataHelperService_ = MediaServiceFactory::GetInstance().CreateAVMetadataHelperService();
151 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
152 "failed to create avmetadatahelper service");
153 return MSERR_OK;
154 }
155
AVMetadataHelperImpl()156 AVMetadataHelperImpl::AVMetadataHelperImpl()
157 {
158 MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
159 }
160
~AVMetadataHelperImpl()161 AVMetadataHelperImpl::~AVMetadataHelperImpl()
162 {
163 if (avMetadataHelperService_ != nullptr) {
164 (void)MediaServiceFactory::GetInstance().DestroyAVMetadataHelperService(avMetadataHelperService_);
165 avMetadataHelperService_ = nullptr;
166 }
167 MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
168 }
169
SetSource(const std::string & uri,int32_t usage)170 int32_t AVMetadataHelperImpl::SetSource(const std::string &uri, int32_t usage)
171 {
172 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
173 "avmetadatahelper service does not exist..");
174 CHECK_AND_RETURN_RET_LOG(!uri.empty(), MSERR_INVALID_VAL, "uri is empty.");
175
176 return avMetadataHelperService_->SetSource(uri, usage);
177 }
178
SetSource(int32_t fd,int64_t offset,int64_t size,int32_t usage)179 int32_t AVMetadataHelperImpl::SetSource(int32_t fd, int64_t offset, int64_t size, int32_t usage)
180 {
181 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
182 "avmetadatahelper service does not exist..");
183
184 CHECK_AND_RETURN_RET_LOG(fd > 0 && offset >= 0 && size > 0, MSERR_INVALID_VAL, "invalid param");
185
186 return avMetadataHelperService_->SetSource(fd, offset, size, usage);
187 }
188
ResolveMetadata(int32_t key)189 std::string AVMetadataHelperImpl::ResolveMetadata(int32_t key)
190 {
191 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, "",
192 "avmetadatahelper service does not exist.");
193
194 return avMetadataHelperService_->ResolveMetadata(key);
195 }
196
ResolveMetadata()197 std::unordered_map<int32_t, std::string> AVMetadataHelperImpl::ResolveMetadata()
198 {
199 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, {},
200 "avmetadatahelper service does not exist.");
201
202 return avMetadataHelperService_->ResolveMetadata();
203 }
204
FetchArtPicture()205 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchArtPicture()
206 {
207 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
208 "avmetadatahelper service does not exist.");
209
210 return avMetadataHelperService_->FetchArtPicture();
211 }
212
FetchFrameAtTime(int64_t timeUs,int32_t option,const PixelMapParams & param)213 std::shared_ptr<PixelMap> AVMetadataHelperImpl::FetchFrameAtTime(
214 int64_t timeUs, int32_t option, const PixelMapParams ¶m)
215 {
216 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
217 "avmetadatahelper service does not exist.");
218
219 OutputConfiguration config;
220 config.colorFormat = param.colorFormat;
221 config.dstHeight = param.dstHeight;
222 config.dstWidth = param.dstWidth;
223
224 auto mem = avMetadataHelperService_->FetchFrameAtTime(timeUs, option, config);
225 return CreatePixelMap(mem, param.colorFormat);
226 }
227
Release()228 void AVMetadataHelperImpl::Release()
229 {
230 CHECK_AND_RETURN_LOG(avMetadataHelperService_ != nullptr, "avmetadatahelper service does not exist.");
231 avMetadataHelperService_->Release();
232 (void)MediaServiceFactory::GetInstance().DestroyAVMetadataHelperService(avMetadataHelperService_);
233 avMetadataHelperService_ = nullptr;
234 }
235 } // namespace Media
236 } // namespace OHOS
237