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_receiver.h"
17
18 #include "image_log.h"
19 #include "image_packer.h"
20 #include "image_source.h"
21 #include "image_utils.h"
22 #include "image_receiver_buffer_processor.h"
23 #include "image_receiver_manager.h"
24
25 #undef LOG_DOMAIN
26 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
27
28 #undef LOG_TAG
29 #define LOG_TAG "imageReceiver"
30
31 namespace OHOS {
32 namespace Media {
~ImageReceiver()33 ImageReceiver::~ImageReceiver()
34 {
35 std::lock_guard<std::mutex> guard(imageReceiverMutex_);
36 if (receiverConsumerSurface_ != nullptr) {
37 receiverConsumerSurface_->UnregisterConsumerListener();
38 }
39 SurfaceUtils* utils = SurfaceUtils::GetInstance();
40 if (receiverProducerSurface_ != nullptr && utils != nullptr) {
41 utils->Remove(receiverProducerSurface_->GetUniqueId());
42 }
43 receiverConsumerSurface_ = nullptr;
44 receiverProducerSurface_ = nullptr;
45 iraContext_ = nullptr;
46 surfaceBufferAvaliableListener_ = nullptr;
47 bufferProcessor_ = nullptr;
48 }
49
50 enum class Mode {
51 MODE_PREVIEW = 0,
52 MODE_PHOTO
53 };
54
PackImage(int & fd,std::unique_ptr<PixelMap> pixelMap)55 int64_t PackImage(int &fd, std::unique_ptr<PixelMap> pixelMap)
56 {
57 IMAGE_LOGD("PackImage");
58 ImagePacker imagePacker;
59 PackOption option;
60 option.format = ImageReceiver::OPTION_FORMAT;
61 option.quality = ImageReceiver::OPTION_QUALITY;
62 option.numberHint = ImageReceiver::OPTION_NUMBERHINT;
63 std::set<std::string> formats;
64 if (pixelMap == nullptr) {
65 IMAGE_LOGE("pixelMap is nullptr");
66 return 0;
67 }
68 uint32_t ret = imagePacker.GetSupportedFormats(formats);
69 if (ret != SUCCESS) {
70 IMAGE_LOGE("image packer get supported format failed, ret=%{public}u.", ret);
71 return 0;
72 } else {
73 IMAGE_LOGD("SUCCESS");
74 }
75 imagePacker.StartPacking(fd, option);
76 imagePacker.AddImage(*pixelMap);
77 int64_t packedSize = 0;
78 imagePacker.FinalizePacking(packedSize);
79 IMAGE_LOGD("packedSize=%{public}lld.", static_cast<long long>(packedSize));
80 IMAGE_LOGD("packedSize=%{public}lld.", static_cast<long long>(packedSize));
81 return packedSize;
82 }
83
getSurfacePixelMap(InitializationOptions initializationOpts)84 std::unique_ptr<PixelMap> ImageReceiver::getSurfacePixelMap(InitializationOptions initializationOpts)
85 {
86 uint32_t *addr = reinterpret_cast<uint32_t *>(iraContext_->currentBuffer_->GetVirAddr());
87 int32_t size = iraContext_->currentBuffer_->GetSize();
88 return PixelMap::Create(addr, (uint32_t)size, initializationOpts);
89 }
90
SaveSTP(uint32_t * buffer,uint32_t bufferSize,int & fd,InitializationOptions initializationOpts)91 static int32_t SaveSTP(uint32_t *buffer,
92 uint32_t bufferSize,
93 int &fd,
94 InitializationOptions initializationOpts)
95 {
96 int64_t errorCode = -1;
97 std::unique_ptr<PixelMap> pixelMap = PixelMap::Create(buffer, bufferSize, initializationOpts);
98 if (pixelMap.get() != nullptr) {
99 ImageInfo imageInfo;
100 pixelMap->GetImageInfo(imageInfo);
101 IMAGE_LOGD("create pixel map imageInfo.size.width=%{public}u.", imageInfo.size.width);
102 } else {
103 IMAGE_LOGE("pixelMap.get() == nullptr");
104 return ERR_MEDIA_INVALID_VALUE;
105 }
106 ImagePacker imagePacker;
107 errorCode = PackImage(fd, std::move(pixelMap));
108 if (errorCode > 0) {
109 errorCode = SUCCESS;
110 } else {
111 errorCode = ERR_MEDIA_INVALID_VALUE;
112 }
113 return errorCode;
114 }
115
SaveBufferAsImage(int & fd,OHOS::sptr<OHOS::SurfaceBuffer> buffer,InitializationOptions initializationOpts)116 int32_t ImageReceiver::SaveBufferAsImage(int &fd,
117 OHOS::sptr<OHOS::SurfaceBuffer> buffer,
118 InitializationOptions initializationOpts)
119 {
120 int32_t errorcode = 0;
121 if (buffer != nullptr) {
122 uint32_t *addr = reinterpret_cast<uint32_t *>(buffer->GetVirAddr());
123 int32_t size = buffer->GetSize();
124 errorcode = SaveSTP(addr, static_cast<uint32_t>(size), fd, initializationOpts);
125 if ((iraContext_->GetReceiverBufferConsumer()) != nullptr) {
126 (iraContext_->GetReceiverBufferConsumer())->ReleaseBuffer(buffer, -1);
127 } else {
128 IMAGE_LOGD("iraContext_->GetReceiverBufferConsumer() == nullptr");
129 }
130 } else {
131 IMAGE_LOGD("SaveBufferAsImage buffer == nullptr");
132 }
133 return errorcode;
134 }
135
SaveBufferAsImage(int & fd,InitializationOptions initializationOpts)136 int32_t ImageReceiver::SaveBufferAsImage(int &fd,
137 InitializationOptions initializationOpts)
138 {
139 if (iraContext_->currentBuffer_ != nullptr) {
140 return SaveBufferAsImage(fd, iraContext_->currentBuffer_, initializationOpts);
141 }
142 IMAGE_LOGD("iraContext_->GetCurrentBuffer() == nullptr");
143 return 0;
144 }
145
ReleaseBuffer(OHOS::sptr<OHOS::SurfaceBuffer> & buffer)146 void ImageReceiver::ReleaseBuffer(OHOS::sptr<OHOS::SurfaceBuffer> &buffer) __attribute__((no_sanitize("cfi")))
147 {
148 std::lock_guard<std::mutex> guard(imageReceiverMutex_);
149 if (buffer != nullptr) {
150 if (iraContext_ != nullptr) {
151 auto listenerConsumerSurface = iraContext_->GetReceiverBufferConsumer();
152 if (listenerConsumerSurface != nullptr) {
153 listenerConsumerSurface->ReleaseBuffer(buffer, -1);
154 } else {
155 IMAGE_LOGD("listenerConsumerSurface == nullptr");
156 }
157 } else {
158 IMAGE_LOGD("iraContext_ == nullptr");
159 }
160 buffer = nullptr;
161 }
162 }
163
OnBufferAvailable()164 void ImageReceiverSurfaceListener ::OnBufferAvailable()
165 {
166 IMAGE_LOGD("OnBufferAvailable");
167 auto ir = ir_.lock();
168 if (ir && ir->surfaceBufferAvaliableListener_ != nullptr) {
169 ir->surfaceBufferAvaliableListener_->OnSurfaceBufferAvaliable();
170 }
171 }
172
CreateImageReceiverContext()173 std::shared_ptr<ImageReceiverContext> ImageReceiverContext ::CreateImageReceiverContext()
174 {
175 std::shared_ptr<ImageReceiverContext> irc = std::make_shared<ImageReceiverContext>();
176 return irc;
177 }
178
getSurfaceById(std::string id)179 sptr<Surface> ImageReceiver::getSurfaceById(std::string id)
180 {
181 ImageReceiverManager& imageReceiverManager = ImageReceiverManager::getInstance();
182 sptr<Surface> surface = imageReceiverManager.getSurfaceByKeyId(id);
183 IMAGE_LOGD("getSurfaceById");
184 return surface;
185 }
186
CreateImageReceiver(int32_t width,int32_t height,int32_t format,int32_t capicity)187 std::shared_ptr<ImageReceiver> ImageReceiver::CreateImageReceiver(int32_t width,
188 int32_t height,
189 int32_t format,
190 int32_t capicity)
191 {
192 std::shared_ptr<ImageReceiver> iva = std::make_shared<ImageReceiver>();
193 iva->iraContext_ = ImageReceiverContext::CreateImageReceiverContext();
194 iva->receiverConsumerSurface_ = IConsumerSurface::Create();
195 if (iva->receiverConsumerSurface_ == nullptr) {
196 IMAGE_LOGD("SurfaceAsConsumer == nullptr");
197 return iva;
198 }
199
200 iva->receiverConsumerSurface_->SetDefaultWidthAndHeight(width, height);
201 iva->receiverConsumerSurface_->SetQueueSize(capicity);
202 iva->receiverConsumerSurface_->SetDefaultUsage(BUFFER_USAGE_CPU_READ);
203
204 auto p = iva->receiverConsumerSurface_->GetProducer();
205 iva->receiverProducerSurface_ = Surface::CreateSurfaceAsProducer(p);
206 if (iva->receiverProducerSurface_ == nullptr) {
207 IMAGE_LOGD("SurfaceAsProducer == nullptr");
208 return iva;
209 }
210 SurfaceUtils* utils = SurfaceUtils::GetInstance();
211 if (utils != nullptr) {
212 utils->Add(iva->receiverProducerSurface_->GetUniqueId(), iva->receiverProducerSurface_);
213 }
214 iva->iraContext_->SetReceiverBufferConsumer(iva->receiverConsumerSurface_);
215 iva->iraContext_->SetReceiverBufferProducer(iva->receiverProducerSurface_);
216 iva->iraContext_->SetWidth(width);
217 iva->iraContext_->SetHeight(height);
218 iva->iraContext_->SetFormat(format);
219 iva->iraContext_->SetCapicity(capicity);
220 ImageReceiverManager& imageReceiverManager = ImageReceiverManager::getInstance();
221 std::string receiverKey = imageReceiverManager.SaveImageReceiver(iva);
222 iva->iraContext_->SetReceiverKey(receiverKey);
223 sptr<ImageReceiverSurfaceListener> listener = new ImageReceiverSurfaceListener();
224 listener->ir_ = iva;
225 iva->receiverConsumerSurface_->
226 RegisterConsumerListener((sptr<IBufferConsumerListener> &)listener);
227 return iva;
228 }
229
ReadNextImage(int64_t & timestamp)230 OHOS::sptr<OHOS::SurfaceBuffer> ImageReceiver::ReadNextImage(int64_t ×tamp)
231 {
232 int32_t flushFence = 0;
233 OHOS::Rect damage = {};
234 OHOS::sptr<OHOS::SurfaceBuffer> buffer;
235 sptr<IConsumerSurface> listenerConsumerSurface = iraContext_->GetReceiverBufferConsumer();
236 SurfaceError surfaceError = listenerConsumerSurface->AcquireBuffer(buffer, flushFence, timestamp, damage);
237 if (surfaceError == SURFACE_ERROR_OK) {
238 iraContext_->currentBuffer_ = buffer;
239 } else {
240 IMAGE_LOGD("buffer is null");
241 }
242 IMAGE_LOGD("[ImageReceiver] ReadNextImage %{public}lld", static_cast<long long>(timestamp));
243 return iraContext_->GetCurrentBuffer();
244 }
245
ReadNextImage()246 OHOS::sptr<OHOS::SurfaceBuffer> ImageReceiver::ReadNextImage()
247 {
248 int32_t flushFence = 0;
249 int64_t timestamp = 0;
250 OHOS::Rect damage = {};
251 OHOS::sptr<OHOS::SurfaceBuffer> buffer;
252 sptr<IConsumerSurface> listenerConsumerSurface = iraContext_->GetReceiverBufferConsumer();
253 SurfaceError surfaceError = listenerConsumerSurface->AcquireBuffer(buffer, flushFence, timestamp, damage);
254 if (surfaceError == SURFACE_ERROR_OK) {
255 iraContext_->currentBuffer_ = buffer;
256 } else {
257 IMAGE_LOGD("buffer is null");
258 }
259 IMAGE_LOGD("[ImageReceiver] ReadNextImage %{public}lld", static_cast<long long>(timestamp));
260 return iraContext_->GetCurrentBuffer();
261 }
262
ReadLastImage(int64_t & timestamp)263 OHOS::sptr<OHOS::SurfaceBuffer> ImageReceiver::ReadLastImage(int64_t ×tamp)
264 {
265 int32_t flushFence = 0;
266 OHOS::Rect damage = {};
267 OHOS::sptr<OHOS::SurfaceBuffer> buffer;
268 OHOS::sptr<OHOS::SurfaceBuffer> bufferBefore;
269 sptr<IConsumerSurface> listenerConsumerSurface = iraContext_->GetReceiverBufferConsumer();
270 SurfaceError surfaceError = listenerConsumerSurface->AcquireBuffer(buffer, flushFence, timestamp, damage);
271 while (surfaceError == SURFACE_ERROR_OK) {
272 bufferBefore = buffer;
273 surfaceError = listenerConsumerSurface->AcquireBuffer(buffer, flushFence, timestamp, damage);
274 }
275
276 iraContext_->currentBuffer_ = bufferBefore;
277 IMAGE_LOGD("[ImageReceiver] ReadLastImage %{public}lld", static_cast<long long>(timestamp));
278 return iraContext_->GetCurrentBuffer();
279 }
280
ReadLastImage()281 OHOS::sptr<OHOS::SurfaceBuffer> ImageReceiver::ReadLastImage()
282 {
283 int32_t flushFence = 0;
284 int64_t timestamp = 0;
285 OHOS::Rect damage = {};
286 OHOS::sptr<OHOS::SurfaceBuffer> buffer;
287 OHOS::sptr<OHOS::SurfaceBuffer> bufferBefore;
288 sptr<IConsumerSurface> listenerConsumerSurface = iraContext_->GetReceiverBufferConsumer();
289 SurfaceError surfaceError = listenerConsumerSurface->AcquireBuffer(buffer, flushFence, timestamp, damage);
290 while (surfaceError == SURFACE_ERROR_OK) {
291 bufferBefore = buffer;
292 surfaceError = listenerConsumerSurface->AcquireBuffer(buffer, flushFence, timestamp, damage);
293 }
294
295 iraContext_->currentBuffer_ = bufferBefore;
296 IMAGE_LOGD("[ImageReceiver] ReadLastImage %{public}lld", static_cast<long long>(timestamp));
297 return iraContext_->GetCurrentBuffer();
298 }
299
GetReceiverSurface()300 sptr<Surface> ImageReceiver::GetReceiverSurface()
301 {
302 if (iraContext_ != nullptr) {
303 return iraContext_->GetReceiverBufferProducer();
304 }
305 return nullptr;
306 }
307
ReleaseReceiver()308 void ImageReceiver::ReleaseReceiver()
309 {
310 ImageReceiver::~ImageReceiver();
311 }
312
GetBufferProcessor()313 std::shared_ptr<IBufferProcessor> ImageReceiver::GetBufferProcessor()
314 {
315 if (bufferProcessor_ == nullptr) {
316 bufferProcessor_ = std::make_shared<ImageReceiverBufferProcessor>(this);
317 }
318 return bufferProcessor_;
319 }
320
NextNativeImage()321 std::shared_ptr<NativeImage> ImageReceiver::NextNativeImage()
322 {
323 if (GetBufferProcessor() == nullptr) {
324 return nullptr;
325 }
326 int64_t timestamp = 0;
327 auto surfaceBuffer = ReadNextImage(timestamp);
328 if (surfaceBuffer == nullptr) {
329 return nullptr;
330 }
331 return std::make_shared<NativeImage>(surfaceBuffer, GetBufferProcessor(), timestamp);
332 }
333
LastNativeImage()334 std::shared_ptr<NativeImage> ImageReceiver::LastNativeImage()
335 {
336 if (GetBufferProcessor() == nullptr) {
337 return nullptr;
338 }
339 int64_t timestamp = 0;
340 auto surfaceBuffer = ReadLastImage(timestamp);
341 if (surfaceBuffer == nullptr) {
342 return nullptr;
343 }
344 return std::make_shared<NativeImage>(surfaceBuffer, GetBufferProcessor(), timestamp);
345 }
346 } // namespace Media
347 } // namespace OHOS
348