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