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 InitializationOptions opts;
119 opts.size.width = frame->width_;
120 opts.size.height = frame->height_;
121 opts.pixelFormat = color;
122 opts.editable = true;
123 std::shared_ptr<PixelMap> pixelMap = PixelMap::Create(opts);
124
125 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, nullptr, "pixelMap create failed");
126 CHECK_AND_RETURN_RET_LOG(pixelMap->GetByteCount() <= frame->size_, nullptr, "Size inconsistent !");
127
128 PixelMapMemHolder *holder = CreatePixelMapData(mem, *frame);
129 CHECK_AND_RETURN_RET_LOG(holder != nullptr, nullptr, "create pixel map data failed");
130
131 pixelMap->SetPixelsAddr(holder->heap, holder, static_cast<uint32_t>(pixelMap->GetByteCount()),
132 AllocatorType::CUSTOM_ALLOC, FreePixelMapData);
133 return pixelMap;
134 }
135
CreateAVMetadataHelper()136 std::shared_ptr<AVMetadataHelper> AVMetadataHelperFactory::CreateAVMetadataHelper()
137 {
138 std::shared_ptr<AVMetadataHelperImpl> impl = std::make_shared<AVMetadataHelperImpl>();
139 CHECK_AND_RETURN_RET_LOG(impl != nullptr, nullptr, "failed to new AVMetadataHelperImpl");
140
141 int32_t ret = impl->Init();
142 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "failed to init AVMetadataHelperImpl");
143
144 return impl;
145 }
146
Init()147 int32_t AVMetadataHelperImpl::Init()
148 {
149 avMetadataHelperService_ = MediaServiceFactory::GetInstance().CreateAVMetadataHelperService();
150 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
151 "failed to create avmetadatahelper service");
152 return MSERR_OK;
153 }
154
AVMetadataHelperImpl()155 AVMetadataHelperImpl::AVMetadataHelperImpl()
156 {
157 MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
158 }
159
~AVMetadataHelperImpl()160 AVMetadataHelperImpl::~AVMetadataHelperImpl()
161 {
162 if (avMetadataHelperService_ != nullptr) {
163 (void)MediaServiceFactory::GetInstance().DestroyAVMetadataHelperService(avMetadataHelperService_);
164 avMetadataHelperService_ = nullptr;
165 }
166 MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
167 }
168
SetHelperCallback(const std::shared_ptr<HelperCallback> & callback)169 int32_t AVMetadataHelperImpl::SetHelperCallback(const std::shared_ptr<HelperCallback> &callback)
170 {
171 MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " SetHelperCallback in", FAKE_POINTER(this));
172 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_SERVICE_DIED,
173 "metadata helper service does not exist..");
174 CHECK_AND_RETURN_RET_LOG(callback != nullptr, MSERR_INVALID_VAL, "callback is nullptr");
175 return avMetadataHelperService_->SetHelperCallback(callback);
176 }
177
SetSource(const std::string & uri,int32_t usage)178 int32_t AVMetadataHelperImpl::SetSource(const std::string &uri, int32_t usage)
179 {
180 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
181 "avmetadatahelper service does not exist..");
182 CHECK_AND_RETURN_RET_LOG(!uri.empty(), MSERR_INVALID_VAL, "uri is empty.");
183
184 return avMetadataHelperService_->SetSource(uri, usage);
185 }
186
SetSource(int32_t fd,int64_t offset,int64_t size,int32_t usage)187 int32_t AVMetadataHelperImpl::SetSource(int32_t fd, int64_t offset, int64_t size, int32_t usage)
188 {
189 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, MSERR_NO_MEMORY,
190 "avmetadatahelper service does not exist..");
191 MEDIA_LOGI("Set file source fd: %{public}d, offset: %{public}" PRIu64 ", size: %{public}" PRIu64,
192 fd, offset, size);
193 CHECK_AND_RETURN_RET_LOG(fd > 0 && offset >= 0 && size >= -1, MSERR_INVALID_VAL,
194 "invalid param");
195
196 return avMetadataHelperService_->SetSource(fd, offset, size, usage);
197 }
198
SetSource(const std::shared_ptr<IMediaDataSource> & dataSrc)199 int32_t AVMetadataHelperImpl::SetSource(const std::shared_ptr<IMediaDataSource> &dataSrc)
200 {
201 MEDIA_LOGD("AVMetadataHelperImpl:0x%{public}06" PRIXPTR " SetSource in(dataSrc)", FAKE_POINTER(this));
202 CHECK_AND_RETURN_RET_LOG(dataSrc != nullptr, MSERR_INVALID_VAL, "failed to create data source");
203 return avMetadataHelperService_->SetSource(dataSrc);
204 }
205
ResolveMetadata(int32_t key)206 std::string AVMetadataHelperImpl::ResolveMetadata(int32_t key)
207 {
208 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, "",
209 "avmetadatahelper service does not exist.");
210
211 return avMetadataHelperService_->ResolveMetadata(key);
212 }
213
ResolveMetadata()214 std::unordered_map<int32_t, std::string> AVMetadataHelperImpl::ResolveMetadata()
215 {
216 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, {},
217 "avmetadatahelper service does not exist.");
218
219 return avMetadataHelperService_->ResolveMetadata();
220 }
221
FetchArtPicture()222 std::shared_ptr<AVSharedMemory> AVMetadataHelperImpl::FetchArtPicture()
223 {
224 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
225 "avmetadatahelper service does not exist.");
226
227 return avMetadataHelperService_->FetchArtPicture();
228 }
229
FetchFrameAtTime(int64_t timeUs,int32_t option,const PixelMapParams & param)230 std::shared_ptr<PixelMap> AVMetadataHelperImpl::FetchFrameAtTime(
231 int64_t timeUs, int32_t option, const PixelMapParams ¶m)
232 {
233 CHECK_AND_RETURN_RET_LOG(avMetadataHelperService_ != nullptr, nullptr,
234 "avmetadatahelper service does not exist.");
235
236 OutputConfiguration config;
237 config.colorFormat = param.colorFormat;
238 config.dstHeight = param.dstHeight;
239 config.dstWidth = param.dstWidth;
240
241 auto mem = avMetadataHelperService_->FetchFrameAtTime(timeUs, option, config);
242 return CreatePixelMap(mem, param.colorFormat);
243 }
244
Release()245 void AVMetadataHelperImpl::Release()
246 {
247 CHECK_AND_RETURN_LOG(avMetadataHelperService_ != nullptr, "avmetadatahelper service does not exist.");
248 avMetadataHelperService_->Release();
249 (void)MediaServiceFactory::GetInstance().DestroyAVMetadataHelperService(avMetadataHelperService_);
250 avMetadataHelperService_ = nullptr;
251 }
252 } // namespace Media
253 } // namespace OHOS
254