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