• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &param)
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