1 /*
2 * Copyright (C) 2024 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 <memory>
17 #include <string>
18 #include <charconv>
19
20 #include "common_utils.h"
21 #include "image_log.h"
22 #include "image_receiver_native.h"
23 #include "image_kits.h"
24 #include "image_receiver.h"
25
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29
30 struct OH_ImageReceiverNative {
31 std::shared_ptr<OHOS::Media::ImageReceiver> ptrImgRcv;
32 };
33
34 struct OH_ImageReceiverOptions {
35 /* Default width of the image received by the consumer, in pixels. */
36 int32_t width = 0;
37 /* Default height of the image received by the consumer, in pixels. */
38 int32_t height = 0;
39 /* Image format {@link OHOS_IMAGE_FORMAT_JPEG} created by using the receiver. */
40 int32_t format = 0;
41 /* Maximum number of images that can be cached. */
42 int32_t capacity = 0;
43 };
44
45 namespace OHOS {
46 namespace Media {
47 class ImageReceiverListener : public SurfaceBufferAvaliableListener {
48 public:
ImageReceiverListener(OH_ImageReceiverNative * receiver)49 explicit ImageReceiverListener(OH_ImageReceiverNative* receiver) : receiver_(receiver), callback_(nullptr) {}
50
~ImageReceiverListener()51 ~ImageReceiverListener() override
52 {
53 callback_ = nullptr;
54 }
55
OnSurfaceBufferAvaliable()56 void OnSurfaceBufferAvaliable() __attribute__((no_sanitize("cfi"))) override
57 {
58 if (nullptr != callback_) {
59 callback_(receiver_);
60 }
61 }
62
63 OH_ImageReceiverNative* receiver_;
64 OH_ImageReceiver_OnCallback callback_;
65 };
66 } // namespace Media
67 } // namespace OHOS
68
69 MIDK_EXPORT
OH_ImageReceiverOptions_Create(OH_ImageReceiverOptions ** options)70 Image_ErrorCode OH_ImageReceiverOptions_Create(OH_ImageReceiverOptions** options)
71 {
72 if (nullptr == options) {
73 IMAGE_LOGE("Invalid parameter: options=null.");
74 return IMAGE_BAD_PARAMETER;
75 }
76 auto rst = new OH_ImageReceiverOptions;
77 if (nullptr == rst) {
78 IMAGE_LOGE("OH_ImageReceiverOptions create failed.");
79 return IMAGE_ALLOC_FAILED;
80 }
81 *options = rst;
82 IMAGE_LOGI("OH_ImageReceiverOptions Create.");
83 return IMAGE_SUCCESS;
84 }
85
86 MIDK_EXPORT
OH_ImageReceiverOptions_GetSize(OH_ImageReceiverOptions * options,Image_Size * size)87 Image_ErrorCode OH_ImageReceiverOptions_GetSize(OH_ImageReceiverOptions* options, Image_Size* size)
88 {
89 if (nullptr == size) {
90 IMAGE_LOGE("Invalid parameter: size=null.");
91 return IMAGE_BAD_PARAMETER;
92 }
93 if (nullptr == options) {
94 IMAGE_LOGE("Invalid parameter: options=null.");
95 return IMAGE_BAD_PARAMETER;
96 }
97 size->width = static_cast<uint32_t>(options->width);
98 size->height = static_cast<uint32_t>(options->height);
99 return IMAGE_SUCCESS;
100 }
101
102 MIDK_EXPORT
OH_ImageReceiverOptions_SetSize(OH_ImageReceiverOptions * options,Image_Size size)103 Image_ErrorCode OH_ImageReceiverOptions_SetSize(OH_ImageReceiverOptions* options, Image_Size size)
104 {
105 if (nullptr == options) {
106 IMAGE_LOGE("Invalid parameter: options=null.");
107 return IMAGE_BAD_PARAMETER;
108 }
109 options->width = static_cast<int32_t>(size.width);
110 options->height = static_cast<int32_t>(size.height);
111 return IMAGE_SUCCESS;
112 }
113
114 MIDK_EXPORT
OH_ImageReceiverOptions_GetCapacity(OH_ImageReceiverOptions * options,int32_t * capacity)115 Image_ErrorCode OH_ImageReceiverOptions_GetCapacity(OH_ImageReceiverOptions* options, int32_t* capacity)
116 {
117 if (nullptr == capacity) {
118 IMAGE_LOGE("Invalid parameter: capacity=null.");
119 return IMAGE_BAD_PARAMETER;
120 }
121 if (nullptr == options) {
122 IMAGE_LOGE("Invalid parameter: options=null.");
123 return IMAGE_BAD_PARAMETER;
124 }
125 *capacity = options->capacity;
126 return IMAGE_SUCCESS;
127 }
128
129 MIDK_EXPORT
OH_ImageReceiverOptions_SetCapacity(OH_ImageReceiverOptions * options,int32_t capacity)130 Image_ErrorCode OH_ImageReceiverOptions_SetCapacity(OH_ImageReceiverOptions* options, int32_t capacity)
131 {
132 if (nullptr == options) {
133 IMAGE_LOGE("Invalid parameter: options=null.");
134 return IMAGE_BAD_PARAMETER;
135 }
136 options->capacity = capacity;
137 return IMAGE_SUCCESS;
138 }
139
140 MIDK_EXPORT
OH_ImageReceiverOptions_Release(OH_ImageReceiverOptions * options)141 Image_ErrorCode OH_ImageReceiverOptions_Release(OH_ImageReceiverOptions* options)
142 {
143 if (nullptr != options) {
144 IMAGE_LOGI("OH_ImageReceiverOptions Release.");
145 delete options;
146 }
147 return IMAGE_SUCCESS;
148 }
149
150 MIDK_EXPORT
OH_ImageReceiverNative_Create(OH_ImageReceiverOptions * options,OH_ImageReceiverNative ** receiver)151 Image_ErrorCode OH_ImageReceiverNative_Create(OH_ImageReceiverOptions* options, OH_ImageReceiverNative** receiver)
152 {
153 if (nullptr == options || nullptr == receiver) {
154 IMAGE_LOGE("OH_ImageReceiverNative_Create: Invalid parameter");
155 return IMAGE_BAD_PARAMETER;
156 }
157
158 auto rst = new OH_ImageReceiverNative;
159 if (nullptr == rst) {
160 IMAGE_LOGE("OH_ImageReceiverNative create failed.");
161 return IMAGE_ALLOC_FAILED;
162 }
163
164 rst->ptrImgRcv = OHOS::Media::ImageReceiver::CreateImageReceiver(
165 options->width, options->height, options->format, options->capacity);
166 if (!(rst->ptrImgRcv)) {
167 delete rst;
168 IMAGE_LOGE("OH_ImageReceiverNative data create failed.");
169 return IMAGE_UNKNOWN_ERROR;
170 }
171
172 *receiver = rst;
173 IMAGE_LOGI("OH_ImageReceiverNative Create.");
174 return IMAGE_SUCCESS;
175 }
176
ConvertToUint64(const std::string & str,uint64_t & value)177 static bool ConvertToUint64(const std::string& str, uint64_t& value)
178 {
179 auto [ptr, errCode] = std::from_chars(str.data(), str.data() + str.size(), value);
180 bool ret = errCode == std::errc{} && (ptr == str.data() + str.size());
181 return ret;
182 }
183
184 MIDK_EXPORT
OH_ImageReceiverNative_GetReceivingSurfaceId(OH_ImageReceiverNative * receiver,uint64_t * surfaceId)185 Image_ErrorCode OH_ImageReceiverNative_GetReceivingSurfaceId(OH_ImageReceiverNative* receiver, uint64_t* surfaceId)
186 {
187 if (nullptr == surfaceId) {
188 IMAGE_LOGE("Invalid parameter: surfaceId=null.");
189 return IMAGE_BAD_PARAMETER;
190 }
191 if (nullptr == receiver) {
192 IMAGE_LOGE("Invalid parameter: receiver=null.");
193 return IMAGE_BAD_PARAMETER;
194 }
195 if (nullptr == receiver->ptrImgRcv || nullptr == receiver->ptrImgRcv->iraContext_) {
196 IMAGE_LOGE("Bad parameter: receiver data empty.");
197 return IMAGE_BAD_PARAMETER;
198 }
199
200 std::string strKey = receiver->ptrImgRcv->iraContext_->GetReceiverKey();
201 if (strKey.empty()) {
202 IMAGE_LOGE("Bad data: key string empty.");
203 return IMAGE_UNKNOWN_ERROR;
204 }
205 IMAGE_LOGD("OH_ImageReceiverNative_GetReceivingSurfaceId Receiver key = %{public}s", strKey.c_str());
206
207 if (!ConvertToUint64(strKey, *surfaceId)) {
208 IMAGE_LOGI("strKey = %{public}s convert string to uint64_t failed", strKey.c_str());
209 return IMAGE_UNKNOWN_ERROR;
210 }
211 return IMAGE_SUCCESS;
212 }
213
214 MIDK_EXPORT
OH_ImageReceiverNative_ReadLatestImage(OH_ImageReceiverNative * receiver,OH_ImageNative ** image)215 Image_ErrorCode OH_ImageReceiverNative_ReadLatestImage(OH_ImageReceiverNative* receiver, OH_ImageNative** image)
216 {
217 if (nullptr == image) {
218 IMAGE_LOGE("Invalid parameter: image=null.");
219 return IMAGE_BAD_PARAMETER;
220 }
221 if (nullptr == receiver) {
222 IMAGE_LOGE("Invalid parameter: receiver=null.");
223 return IMAGE_BAD_PARAMETER;
224 }
225 if (nullptr == receiver->ptrImgRcv) {
226 IMAGE_LOGE("Bad parameter: receiver data empty.");
227 return IMAGE_BAD_PARAMETER;
228 }
229
230 auto bufferProcessor = receiver->ptrImgRcv->GetBufferProcessor();
231 if (nullptr == bufferProcessor) {
232 IMAGE_LOGE("Bad data: buffer processor empty.");
233 return IMAGE_UNKNOWN_ERROR;
234 }
235
236 int64_t timestamp = 0;
237 auto surfaceBuffer = receiver->ptrImgRcv->ReadLastImage(timestamp);
238 if (nullptr == surfaceBuffer) {
239 IMAGE_LOGE("Bad data: surfacebuffer empty.");
240 return IMAGE_UNKNOWN_ERROR;
241 }
242
243 auto rst = new OH_ImageNative;
244 if (nullptr == rst) {
245 IMAGE_LOGE("OH_ImageNative create failed.");
246 return IMAGE_ALLOC_FAILED;
247 }
248
249 rst->imgNative = new OHOS::Media::NativeImage(surfaceBuffer, bufferProcessor, timestamp);
250 if (!(rst->imgNative)) {
251 delete rst;
252 IMAGE_LOGE("OH_ImageNative data create failed.");
253 return IMAGE_UNKNOWN_ERROR;
254 }
255
256 *image = rst;
257 IMAGE_LOGD("OH_ImageNative ReadLatestImage.");
258 return IMAGE_SUCCESS;
259 }
260
261 MIDK_EXPORT
OH_ImageReceiverNative_ReadNextImage(OH_ImageReceiverNative * receiver,OH_ImageNative ** image)262 Image_ErrorCode OH_ImageReceiverNative_ReadNextImage(OH_ImageReceiverNative* receiver, OH_ImageNative** image)
263 {
264 if (nullptr == image) {
265 IMAGE_LOGE("Invalid parameter: image=null.");
266 return IMAGE_BAD_PARAMETER;
267 }
268 if (nullptr == receiver) {
269 IMAGE_LOGE("Invalid parameter: receiver=null.");
270 return IMAGE_BAD_PARAMETER;
271 }
272 if (nullptr == receiver->ptrImgRcv) {
273 IMAGE_LOGE("Bad parameter: receiver data empty.");
274 return IMAGE_BAD_PARAMETER;
275 }
276
277 auto bufferProcessor = receiver->ptrImgRcv->GetBufferProcessor();
278 if (nullptr == bufferProcessor) {
279 IMAGE_LOGE("Bad data: buffer processor empty.");
280 return IMAGE_UNKNOWN_ERROR;
281 }
282
283 int64_t timestamp = 0;
284 auto surfaceBuffer = receiver->ptrImgRcv->ReadNextImage(timestamp);
285 if (nullptr == surfaceBuffer) {
286 IMAGE_LOGE("Bad data: surfacebuffer empty.");
287 return IMAGE_UNKNOWN_ERROR;
288 }
289
290 auto rst = new OH_ImageNative;
291 if (nullptr == rst) {
292 IMAGE_LOGE("OH_ImageNative create failed.");
293 return IMAGE_ALLOC_FAILED;
294 }
295
296 rst->imgNative = new OHOS::Media::NativeImage(surfaceBuffer, bufferProcessor, timestamp);
297 if (!(rst->imgNative)) {
298 delete rst;
299 IMAGE_LOGE("OH_ImageNative data create failed.");
300 return IMAGE_UNKNOWN_ERROR;
301 }
302
303 *image = rst;
304 IMAGE_LOGI("OH_ImageNative ReadNextImage.");
305 return IMAGE_SUCCESS;
306 }
307
308 MIDK_EXPORT
OH_ImageReceiverNative_On(OH_ImageReceiverNative * receiver,OH_ImageReceiver_OnCallback callback)309 Image_ErrorCode OH_ImageReceiverNative_On(OH_ImageReceiverNative* receiver, OH_ImageReceiver_OnCallback callback)
310 {
311 if (nullptr == receiver || nullptr == callback) {
312 IMAGE_LOGE("OH_ImageReceiverNative_On: Invalid parameter");
313 return IMAGE_BAD_PARAMETER;
314 }
315 if (nullptr == receiver->ptrImgRcv) {
316 IMAGE_LOGE("Bad parameter: receiver data empty.");
317 return IMAGE_BAD_PARAMETER;
318 }
319
320 auto listener = std::make_shared<OHOS::Media::ImageReceiverListener>(receiver);
321 listener->callback_ = callback;
322 receiver->ptrImgRcv->RegisterBufferAvaliableListener(listener);
323 return IMAGE_SUCCESS;
324 }
325
326 MIDK_EXPORT
OH_ImageReceiverNative_Off(OH_ImageReceiverNative * receiver)327 Image_ErrorCode OH_ImageReceiverNative_Off(OH_ImageReceiverNative* receiver)
328 {
329 if (nullptr == receiver) {
330 IMAGE_LOGE("Invalid parameter: receiver=null.");
331 return IMAGE_BAD_PARAMETER;
332 }
333 if (nullptr == receiver->ptrImgRcv) {
334 IMAGE_LOGE("Bad parameter: receiver data empty.");
335 return IMAGE_BAD_PARAMETER;
336 }
337
338 receiver->ptrImgRcv->UnRegisterBufferAvaliableListener();
339 return IMAGE_SUCCESS;
340 }
341
342 MIDK_EXPORT
OH_ImageReceiverNative_GetSize(OH_ImageReceiverNative * receiver,Image_Size * size)343 Image_ErrorCode OH_ImageReceiverNative_GetSize(OH_ImageReceiverNative* receiver, Image_Size* size)
344 {
345 if (nullptr == receiver || nullptr == size) {
346 IMAGE_LOGE("OH_ImageReceiverNative_GetSize: Invalid parameter");
347 return IMAGE_BAD_PARAMETER;
348 }
349 if (nullptr == receiver->ptrImgRcv || nullptr == receiver->ptrImgRcv->iraContext_) {
350 IMAGE_LOGE("Bad parameter: receiver data empty.");
351 return IMAGE_BAD_PARAMETER;
352 }
353
354 size->width = static_cast<uint32_t>(receiver->ptrImgRcv->iraContext_->GetWidth());
355 size->height = static_cast<uint32_t>(receiver->ptrImgRcv->iraContext_->GetHeight());
356 return IMAGE_SUCCESS;
357 }
358
359 MIDK_EXPORT
OH_ImageReceiverNative_GetCapacity(OH_ImageReceiverNative * receiver,int32_t * capacity)360 Image_ErrorCode OH_ImageReceiverNative_GetCapacity(OH_ImageReceiverNative* receiver, int32_t* capacity)
361 {
362 if (nullptr == receiver || nullptr == capacity) {
363 IMAGE_LOGE("OH_ImageReceiverNative_GetCapacity: Invalid parameter");
364 return IMAGE_BAD_PARAMETER;
365 }
366 if (nullptr == receiver->ptrImgRcv || nullptr == receiver->ptrImgRcv->iraContext_) {
367 IMAGE_LOGE("Bad parameter: receiver data empty.");
368 return IMAGE_BAD_PARAMETER;
369 }
370
371 *capacity = receiver->ptrImgRcv->iraContext_->GetCapicity();
372 return IMAGE_SUCCESS;
373 }
374
375 MIDK_EXPORT
OH_ImageReceiverNative_Release(OH_ImageReceiverNative * receiver)376 Image_ErrorCode OH_ImageReceiverNative_Release(OH_ImageReceiverNative* receiver)
377 {
378 if (nullptr == receiver) {
379 IMAGE_LOGE("Invalid parameter: receiver=null.");
380 return IMAGE_BAD_PARAMETER;
381 }
382 receiver->ptrImgRcv.reset();
383 IMAGE_LOGI("OH_ImageReceiverNative Release.");
384 delete receiver;
385 return IMAGE_SUCCESS;
386 }
387
388 MIDK_EXPORT
OH_ImageReceiverNative_OnImageArrive(OH_ImageReceiverNative * receiver,OH_ImageReceiver_ImageArriveCallback callback,void * userdata)389 Image_ErrorCode OH_ImageReceiverNative_OnImageArrive(OH_ImageReceiverNative* receiver,
390 OH_ImageReceiver_ImageArriveCallback callback, void* userdata)
391 {
392 if (nullptr == receiver || nullptr == callback) {
393 IMAGE_LOGE("OH_ImageReceiverNative_OnImageArrive: Invalid parameter");
394 return IMAGE_RECEIVER_INVALID_PARAMETER;
395 }
396 if (nullptr == receiver->ptrImgRcv) {
397 IMAGE_LOGE("Bad parameter: receiver data empty.");
398 return IMAGE_RECEIVER_INVALID_PARAMETER;
399 }
400 if (receiver->ptrImgRcv->surfaceBufferAvaliableArriveListener_ == nullptr) {
401 receiver->ptrImgRcv->surfaceBufferAvaliableArriveListener_ =
402 std::make_shared<OHOS::Media::ImageReceiverArriveListener>(receiver);
403 }
404 bool ret = receiver->ptrImgRcv->surfaceBufferAvaliableArriveListener_->RegisterCallback(callback, userdata);
405 if (!ret) {
406 IMAGE_LOGD("callback has registered.");
407 }
408 return IMAGE_SUCCESS;
409 }
410
OH_ImageReceiverNative_OffImageArrive(OH_ImageReceiverNative * receiver,OH_ImageReceiver_ImageArriveCallback callback)411 Image_ErrorCode OH_ImageReceiverNative_OffImageArrive(OH_ImageReceiverNative *receiver,
412 OH_ImageReceiver_ImageArriveCallback callback)
413 {
414 if (nullptr == receiver) {
415 IMAGE_LOGE("Invalid parameter: receiver=null.");
416 return IMAGE_RECEIVER_INVALID_PARAMETER;
417 }
418 if (nullptr == receiver->ptrImgRcv) {
419 IMAGE_LOGE("Bad parameter: receiver data empty.");
420 return IMAGE_RECEIVER_INVALID_PARAMETER;
421 }
422 if (nullptr == callback) {
423 receiver->ptrImgRcv->surfaceBufferAvaliableArriveListener_.reset();
424 return IMAGE_SUCCESS;
425 }
426 if (receiver->ptrImgRcv->surfaceBufferAvaliableArriveListener_ == nullptr) {
427 IMAGE_LOGE("listener is nullptr. not registered.");
428 return IMAGE_RECEIVER_INVALID_PARAMETER;
429 }
430 if (!receiver->ptrImgRcv->surfaceBufferAvaliableArriveListener_->UnregisterCallback(callback)) {
431 IMAGE_LOGE("callback is not registered.");
432 return IMAGE_RECEIVER_INVALID_PARAMETER;
433 }
434 return IMAGE_SUCCESS;
435 }
436
437 #ifdef __cplusplus
438 };
439 #endif