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