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