• 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     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 &param)
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