1 /*
2 * Copyright (C) 2022 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 "image_creator.h"
17
18 #include "display/composer/v1_2/display_composer_type.h"
19 #include "image_creator_buffer_processor.h"
20 #include "image_creator_manager.h"
21 #include "image_log.h"
22 #include "image_packer.h"
23 #include "image_source.h"
24 #include "image_utils.h"
25
26 #undef LOG_DOMAIN
27 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
28
29 #undef LOG_TAG
30 #define LOG_TAG "imageCreator"
31
32 namespace OHOS {
33 namespace Media {
34 std::map<uint8_t*, ImageCreator*> ImageCreator::bufferCreatorMap_;
35 std::mutex ImageCreator::creatorMutex_;
~ImageCreator()36 ImageCreator::~ImageCreator()
37 {
38 if (iraContext_ != nullptr) {
39 ImageCreatorManager::ReleaseCreatorById(iraContext_->GetCreatorKey());
40 }
41 creatorConsumerSurface_ = nullptr;
42 creatorProducerSurface_ = nullptr;
43 iraContext_ = nullptr;
44 surfaceBufferReleaseListener_ = nullptr;
45 surfaceBufferAvaliableListener_ = nullptr;
46 }
47
OnBufferRelease(sptr<SurfaceBuffer> & buffer)48 GSError ImageCreator::OnBufferRelease(sptr<SurfaceBuffer> &buffer)
49 {
50 IMAGE_LOGI("OnBufferRelease");
51 if (buffer == nullptr) {
52 return GSERROR_NO_ENTRY;
53 }
54 std::lock_guard<std::mutex> guard(creatorMutex_);
55 auto iter = bufferCreatorMap_.find(static_cast<uint8_t*>(buffer->GetVirAddr()));
56 if (iter == bufferCreatorMap_.end()) {
57 return GSERROR_NO_ENTRY;
58 }
59 auto icr = iter->second;
60 if (icr->surfaceBufferReleaseListener_ == nullptr) {
61 IMAGE_LOGI("empty icr");
62 return GSERROR_NO_ENTRY;
63 }
64 icr->surfaceBufferReleaseListener_->OnSurfaceBufferRelease();
65 bufferCreatorMap_.erase(iter);
66 return GSERROR_NO_ENTRY;
67 }
68
CreateImageCreatorContext()69 std::shared_ptr<ImageCreatorContext> ImageCreatorContext ::CreateImageCreatorContext()
70 {
71 std::shared_ptr<ImageCreatorContext> icc = std::make_shared<ImageCreatorContext>();
72 return icc;
73 }
74
OnBufferAvailable()75 void ImageCreatorSurfaceListener ::OnBufferAvailable()
76 {
77 IMAGE_LOGD("CreatorBufferAvailable");
78 if (ic_->surfaceBufferAvaliableListener_ != nullptr) {
79 ic_->surfaceBufferAvaliableListener_->OnSurfaceBufferAvaliable();
80 }
81 }
82
CreateImageCreator(int32_t width,int32_t height,int32_t format,int32_t capicity)83 std::shared_ptr<ImageCreator> ImageCreator::CreateImageCreator(int32_t width,
84 int32_t height, int32_t format, int32_t capicity)
85 {
86 std::shared_ptr<ImageCreator> iva = std::make_shared<ImageCreator>();
87 iva->iraContext_ = ImageCreatorContext::CreateImageCreatorContext();
88 iva->creatorConsumerSurface_ = IConsumerSurface::Create();
89 if (iva->creatorConsumerSurface_ == nullptr) {
90 IMAGE_LOGD("SurfaceAsConsumer == nullptr");
91 return iva;
92 }
93 iva->creatorConsumerSurface_->SetDefaultWidthAndHeight(width, height);
94 iva->creatorConsumerSurface_->SetQueueSize(capicity);
95 sptr<ImageCreatorSurfaceListener> listener = new ImageCreatorSurfaceListener();
96 listener->ic_ = iva;
97 iva->creatorConsumerSurface_->
98 RegisterConsumerListener((sptr<IBufferConsumerListener> &)listener);
99 auto p = iva->creatorConsumerSurface_->GetProducer();
100 iva->creatorProducerSurface_ = Surface::CreateSurfaceAsProducer(p);
101 if (iva->creatorProducerSurface_ == nullptr) {
102 IMAGE_LOGD("SurfaceAsProducer == nullptr");
103 return iva;
104 }
105 iva->creatorProducerSurface_->SetQueueSize(capicity);
106 iva->iraContext_->SetCreatorBufferConsumer(iva->creatorConsumerSurface_);
107 iva->iraContext_->SetCreatorBufferProducer(iva->creatorProducerSurface_);
108 iva->iraContext_->SetWidth(width);
109 iva->iraContext_->SetHeight(height);
110 iva->iraContext_->SetFormat(format);
111 iva->iraContext_->SetCapicity(capicity);
112 ImageCreatorManager& imageCreatorManager = ImageCreatorManager::getInstance();
113 std::string creatorKey = imageCreatorManager.SaveImageCreator(iva);
114 iva->iraContext_->SetCreatorKey(creatorKey);
115 iva->creatorProducerSurface_->
116 RegisterReleaseListener(OnBufferRelease);
117 return iva;
118 }
119
CreatorPackImage(uint8_t * tempBuffer,uint32_t bufferSize,std::unique_ptr<PixelMap> pixelMap)120 int64_t CreatorPackImage(uint8_t *tempBuffer, uint32_t bufferSize, std::unique_ptr<PixelMap> pixelMap)
121 {
122 IMAGE_LOGD("PackImage");
123 ImagePacker imagePacker;
124 PackOption option;
125 option.format = ImageReceiver::OPTION_FORMAT;
126 option.quality = ImageReceiver::OPTION_QUALITY;
127 option.numberHint = static_cast<uint32_t>(ImageReceiver::OPTION_NUMBERHINT);
128 std::set<std::string> formats;
129
130 uint32_t ret = imagePacker.GetSupportedFormats(formats);
131 if (ret != SUCCESS) {
132 IMAGE_LOGE("image packer get supported format failed, ret=%{public}u.", ret);
133 return 0;
134 } else {
135 IMAGE_LOGD("SUCCESS");
136 }
137 imagePacker.StartPacking(tempBuffer, bufferSize, option);
138 imagePacker.AddImage(*pixelMap);
139 int64_t packedSize = 0;
140 imagePacker.FinalizePacking(packedSize);
141 IMAGE_LOGI("packedSize=%{public}lld.", static_cast<long long>(packedSize));
142 return packedSize;
143 }
144 static const int BIT4 = 4;
145 static const int PRINT_WIDTH = 100;
146 static const int PRINT_WIDTH_MOD = 99;
147 static const uint8_t BIT4_MASK = 0xf;
dumpBuffer(const uint8_t * tempBuffer,int64_t size)148 static void dumpBuffer(const uint8_t* tempBuffer, int64_t size)
149 {
150 std::vector<char> ss;
151 char xx[] = "0123456789ABCDEF";
152 for (int i = 0; i < size; i++) {
153 ss.push_back(xx[(tempBuffer[i]>>BIT4)&BIT4_MASK]);
154 ss.push_back(xx[tempBuffer[i]&BIT4_MASK]);
155 if (i % PRINT_WIDTH == PRINT_WIDTH_MOD) {
156 ss.push_back('\0');
157 IMAGE_LOGI("buffer[%{public}d] = [%{public}s]", i, ss.data());
158 ss.clear();
159 ss.resize(0);
160 }
161 }
162 ss.push_back('\0');
163 IMAGE_LOGI("buffer[LAST] = [%{public}s]", ss.data());
164 ss.clear();
165 ss.resize(0);
166 }
167
SaveSTP(uint32_t * buffer,uint8_t * tempBuffer,uint32_t bufferSize,InitializationOptions initializationOpts)168 int32_t ImageCreator::SaveSTP(uint32_t *buffer,
169 uint8_t *tempBuffer, uint32_t bufferSize, InitializationOptions initializationOpts)
170 {
171 int64_t errorCode = -1;
172 std::unique_ptr<PixelMap> pixelMap = PixelMap::Create(buffer, bufferSize, initializationOpts);
173 if (pixelMap.get() != nullptr) {
174 ImageInfo imageInfo;
175 pixelMap->GetImageInfo(imageInfo);
176 IMAGE_LOGD("create pixel map imageInfo.size.width=%{public}u.",
177 imageInfo.size.width);
178 } else {
179 IMAGE_LOGE("pixelMap.get() == nullptr");
180 return ERR_MEDIA_INVALID_VALUE;
181 }
182 ImagePacker imagePacker;
183 errorCode = CreatorPackImage(tempBuffer, bufferSize, std::move(pixelMap));
184 if (errorCode > 0) {
185 int64_t len = errorCode < bufferSize ? errorCode : bufferSize;
186 dumpBuffer(tempBuffer, len);
187 errorCode = SUCCESS;
188 } else {
189 errorCode = ERR_MEDIA_INVALID_VALUE;
190 }
191 return errorCode;
192 }
193
ReleaseBuffer(AllocatorType allocatorType,uint8_t ** buffer)194 static void ReleaseBuffer(AllocatorType allocatorType, uint8_t **buffer)
195 {
196 if (allocatorType == AllocatorType::HEAP_ALLOC) {
197 if (*buffer != nullptr) {
198 free(*buffer);
199 *buffer = nullptr;
200 }
201 return;
202 }
203 }
204
AllocHeapBuffer(uint64_t bufferSize,uint8_t ** buffer)205 static bool AllocHeapBuffer(uint64_t bufferSize, uint8_t **buffer)
206 {
207 if (bufferSize == 0 || bufferSize > MALLOC_MAX_LENTH) {
208 IMAGE_LOGE("[PostProc]Invalid value of bufferSize");
209 return false;
210 }
211 *buffer = static_cast<uint8_t *>(malloc(bufferSize));
212 if (*buffer == nullptr) {
213 IMAGE_LOGE("[PostProc]alloc covert color buffersize[%{public}llu] failed.",
214 static_cast<unsigned long long>(bufferSize));
215 return false;
216 }
217 errno_t errRet = memset_s(*buffer, bufferSize, 0, bufferSize);
218 if (errRet != EOK) {
219 IMAGE_LOGE("[PostProc]memset convertData fail, errorCode = %{public}d", errRet);
220 ReleaseBuffer(AllocatorType::HEAP_ALLOC, buffer);
221 return false;
222 }
223 return true;
224 }
225
SaveSenderBufferAsImage(OHOS::sptr<OHOS::SurfaceBuffer> buffer,InitializationOptions initializationOpts)226 int32_t ImageCreator::SaveSenderBufferAsImage(OHOS::sptr<OHOS::SurfaceBuffer> buffer,
227 InitializationOptions initializationOpts)
228 {
229 int32_t errorcode = 0;
230 if (buffer != nullptr) {
231 uint32_t *addr = static_cast<uint32_t *>(buffer->GetVirAddr());
232 uint8_t *addr2 = nullptr;
233 uint32_t size = buffer->GetSize();
234 if (!AllocHeapBuffer(size, &addr2)) {
235 IMAGE_LOGE("AllocHeapBuffer failed");
236 return ERR_MEDIA_INVALID_VALUE;
237 }
238 errorcode = SaveSTP(addr, addr2, size, initializationOpts);
239 ReleaseBuffer(AllocatorType::HEAP_ALLOC, &addr2);
240 (iraContext_->GetCreatorBufferConsumer())->ReleaseBuffer(buffer, -1);
241 IMAGE_LOGI("start release");
242 } else {
243 IMAGE_LOGD("SaveBufferAsImage buffer == nullptr");
244 }
245 return errorcode;
246 }
247
DequeueImage()248 OHOS::sptr<OHOS::SurfaceBuffer> ImageCreator::DequeueImage()
249 {
250 int32_t flushFence = 0;
251 OHOS::sptr<OHOS::SurfaceBuffer> buffer;
252 sptr<Surface> creatorSurface = iraContext_->GetCreatorBufferProducer();
253 BufferRequestConfig config;
254 config.width = iraContext_->GetWidth();
255 config.height = iraContext_->GetHeight();
256 config.format = OHOS::HDI::Display::Composer::V1_2::PixelFormat::PIXEL_FMT_RGBA_8888;
257 config.strideAlignment = 0x8;
258 config.usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA;
259 config.timeout = 0;
260 SurfaceError surfaceError = creatorSurface->RequestBuffer(buffer, flushFence, config);
261 if (surfaceError == SURFACE_ERROR_OK) {
262 iraContext_->currentCreatorBuffer_ = buffer;
263 } else {
264 IMAGE_LOGD("error : request buffer is null");
265 }
266 if (buffer != nullptr && buffer->GetVirAddr() != nullptr) {
267 std::lock_guard<std::mutex> guard(creatorMutex_);
268 bufferCreatorMap_.insert(
269 std::map<uint8_t*, ImageCreator*>::value_type(static_cast<uint8_t*>(buffer->GetVirAddr()), this));
270 }
271 return iraContext_->currentCreatorBuffer_;
272 }
273
QueueImage(OHOS::sptr<OHOS::SurfaceBuffer> & buffer)274 void ImageCreator::QueueImage(OHOS::sptr<OHOS::SurfaceBuffer> &buffer)
275 {
276 IMAGE_LOGI("start Queue Image");
277 int32_t flushFence = -1;
278 BufferFlushConfig config;
279 config.damage.w = iraContext_->GetWidth();
280 config.damage.h = iraContext_->GetHeight();
281 sptr<Surface> creatorSurface = iraContext_->GetCreatorBufferProducer();
282 SurfaceError surfaceError = creatorSurface->FlushBuffer(buffer, flushFence, config);
283 IMAGE_LOGI("finish Queue Image");
284 if (surfaceError != SURFACE_ERROR_OK) {
285 IMAGE_LOGD("Queue fail");
286 }
287 }
GetCreatorSurface()288 sptr<IConsumerSurface> ImageCreator::GetCreatorSurface()
289 {
290 return iraContext_->GetCreatorBufferConsumer();
291 }
292
getSurfaceById(std::string id)293 sptr<IConsumerSurface> ImageCreator::getSurfaceById(std::string id)
294 {
295 ImageCreatorManager& imageCreatorManager = ImageCreatorManager::getInstance();
296 sptr<IConsumerSurface> surface = imageCreatorManager.GetSurfaceByKeyId(id);
297 IMAGE_LOGD("getSurfaceByCreatorId");
298 return surface;
299 }
ReleaseCreator()300 void ImageCreator::ReleaseCreator()
301 {
302 ImageCreator::~ImageCreator();
303 }
304
GetBufferProcessor()305 std::shared_ptr<IBufferProcessor> ImageCreator::GetBufferProcessor()
306 {
307 if (bufferProcessor_ == nullptr) {
308 bufferProcessor_ = std::make_shared<ImageCreatorBufferProcessor>(this);
309 }
310 return bufferProcessor_;
311 }
DequeueNativeImage()312 std::shared_ptr<NativeImage> ImageCreator::DequeueNativeImage()
313 {
314 if (GetBufferProcessor() == nullptr) {
315 return nullptr;
316 }
317
318 auto surfaceBuffer = DequeueImage();
319 if (surfaceBuffer == nullptr) {
320 return nullptr;
321 }
322 return std::make_shared<NativeImage>(surfaceBuffer, GetBufferProcessor());
323 }
QueueNativeImage(std::shared_ptr<NativeImage> image)324 void ImageCreator::QueueNativeImage(std::shared_ptr<NativeImage> image)
325 {
326 if (image == nullptr || image->GetBuffer() == nullptr) {
327 return;
328 }
329 auto buffer = image->GetBuffer();
330 QueueImage(buffer);
331 }
332 } // namespace Media
333 } // namespace OHOS
334