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