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