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 == options) {
90 IMAGE_LOGE("Invalid parameter: options=null.");
91 return IMAGE_BAD_PARAMETER;
92 }
93 size->width = static_cast<uint32_t>(options->width);
94 size->height = static_cast<uint32_t>(options->height);
95 return IMAGE_SUCCESS;
96 }
97
98 MIDK_EXPORT
OH_ImageReceiverOptions_SetSize(OH_ImageReceiverOptions * options,Image_Size size)99 Image_ErrorCode OH_ImageReceiverOptions_SetSize(OH_ImageReceiverOptions* options, Image_Size size)
100 {
101 if (nullptr == options) {
102 IMAGE_LOGE("Invalid parameter: options=null.");
103 return IMAGE_BAD_PARAMETER;
104 }
105 options->width = static_cast<int32_t>(size.width);
106 options->height = static_cast<int32_t>(size.height);
107 return IMAGE_SUCCESS;
108 }
109
110 MIDK_EXPORT
OH_ImageReceiverOptions_GetCapacity(OH_ImageReceiverOptions * options,int32_t * capacity)111 Image_ErrorCode OH_ImageReceiverOptions_GetCapacity(OH_ImageReceiverOptions* options, int32_t* capacity)
112 {
113 if (nullptr == options) {
114 IMAGE_LOGE("Invalid parameter: options=null.");
115 return IMAGE_BAD_PARAMETER;
116 }
117 *capacity = options->capacity;
118 return IMAGE_SUCCESS;
119 }
120
121 MIDK_EXPORT
OH_ImageReceiverOptions_SetCapacity(OH_ImageReceiverOptions * options,int32_t capacity)122 Image_ErrorCode OH_ImageReceiverOptions_SetCapacity(OH_ImageReceiverOptions* options, int32_t capacity)
123 {
124 if (nullptr == options) {
125 IMAGE_LOGE("Invalid parameter: options=null.");
126 return IMAGE_BAD_PARAMETER;
127 }
128 options->capacity = capacity;
129 return IMAGE_SUCCESS;
130 }
131
132 MIDK_EXPORT
OH_ImageReceiverOptions_Release(OH_ImageReceiverOptions * options)133 Image_ErrorCode OH_ImageReceiverOptions_Release(OH_ImageReceiverOptions* options)
134 {
135 if (nullptr != options) {
136 IMAGE_LOGI("OH_ImageReceiverOptions Release.");
137 delete options;
138 }
139 return IMAGE_SUCCESS;
140 }
141
142 MIDK_EXPORT
OH_ImageReceiverNative_Create(OH_ImageReceiverOptions * options,OH_ImageReceiverNative ** receiver)143 Image_ErrorCode OH_ImageReceiverNative_Create(OH_ImageReceiverOptions* options, OH_ImageReceiverNative** receiver)
144 {
145 if (nullptr == options || nullptr == receiver) {
146 IMAGE_LOGE("OH_ImageReceiverNative_Create: Invalid parameter");
147 return IMAGE_BAD_PARAMETER;
148 }
149
150 auto rst = new OH_ImageReceiverNative;
151 if (nullptr == rst) {
152 IMAGE_LOGE("OH_ImageReceiverNative create failed.");
153 return IMAGE_ALLOC_FAILED;
154 }
155
156 rst->ptrImgRcv = OHOS::Media::ImageReceiver::CreateImageReceiver(
157 options->width, options->height, options->format, options->capacity);
158 if (!(rst->ptrImgRcv)) {
159 delete rst;
160 IMAGE_LOGE("OH_ImageReceiverNative data create failed.");
161 return IMAGE_UNKNOWN_ERROR;
162 }
163
164 *receiver = rst;
165 IMAGE_LOGI("OH_ImageReceiverNative Create.");
166 return IMAGE_SUCCESS;
167 }
168
ConvertToUint64(const std::string & str,uint64_t & value)169 static bool ConvertToUint64(const std::string& str, uint64_t& value)
170 {
171 auto [ptr, errCode] = std::from_chars(str.data(), str.data() + str.size(), value);
172 bool ret = errCode == std::errc{} && (ptr == str.data() + str.size());
173 return ret;
174 }
175
176 MIDK_EXPORT
OH_ImageReceiverNative_GetReceivingSurfaceId(OH_ImageReceiverNative * receiver,uint64_t * surfaceId)177 Image_ErrorCode OH_ImageReceiverNative_GetReceivingSurfaceId(OH_ImageReceiverNative* receiver, uint64_t* surfaceId)
178 {
179 if (nullptr == receiver) {
180 IMAGE_LOGE("Invalid parameter: receiver=null.");
181 return IMAGE_BAD_PARAMETER;
182 }
183 if (nullptr == receiver->ptrImgRcv || nullptr == receiver->ptrImgRcv->iraContext_) {
184 IMAGE_LOGE("Bad parameter: receiver data empty.");
185 return IMAGE_BAD_PARAMETER;
186 }
187
188 std::string strKey = receiver->ptrImgRcv->iraContext_->GetReceiverKey();
189 if (strKey.empty()) {
190 IMAGE_LOGE("Bad data: key string empty.");
191 return IMAGE_UNKNOWN_ERROR;
192 }
193 IMAGE_LOGI("OH_ImageReceiverNative_GetReceivingSurfaceId Receiver key = %{public}s", strKey.c_str());
194
195 if (!ConvertToUint64(strKey, *surfaceId)) {
196 IMAGE_LOGI("strKey = %{public}s convert string to uint64_t failed", strKey.c_str());
197 return IMAGE_UNKNOWN_ERROR;
198 }
199 return IMAGE_SUCCESS;
200 }
201
202 MIDK_EXPORT
OH_ImageReceiverNative_ReadLatestImage(OH_ImageReceiverNative * receiver,OH_ImageNative ** image)203 Image_ErrorCode OH_ImageReceiverNative_ReadLatestImage(OH_ImageReceiverNative* receiver, OH_ImageNative** image)
204 {
205 if (nullptr == receiver) {
206 IMAGE_LOGE("Invalid parameter: receiver=null.");
207 return IMAGE_BAD_PARAMETER;
208 }
209 if (nullptr == receiver->ptrImgRcv) {
210 IMAGE_LOGE("Bad parameter: receiver data empty.");
211 return IMAGE_BAD_PARAMETER;
212 }
213
214 auto bufferProcessor = receiver->ptrImgRcv->GetBufferProcessor();
215 if (nullptr == bufferProcessor) {
216 IMAGE_LOGE("Bad data: buffer processor empty.");
217 return IMAGE_UNKNOWN_ERROR;
218 }
219
220 int64_t timestamp = 0;
221 auto surfaceBuffer = receiver->ptrImgRcv->ReadLastImage(timestamp);
222 if (nullptr == surfaceBuffer) {
223 IMAGE_LOGE("Bad data: surfacebuffer empty.");
224 return IMAGE_UNKNOWN_ERROR;
225 }
226
227 auto rst = new OH_ImageNative;
228 if (nullptr == rst) {
229 IMAGE_LOGE("OH_ImageNative create failed.");
230 return IMAGE_ALLOC_FAILED;
231 }
232
233 rst->imgNative = new OHOS::Media::NativeImage(surfaceBuffer, bufferProcessor, timestamp);
234 if (!(rst->imgNative)) {
235 delete rst;
236 IMAGE_LOGE("OH_ImageNative data create failed.");
237 return IMAGE_UNKNOWN_ERROR;
238 }
239
240 *image = rst;
241 IMAGE_LOGI("OH_ImageNative ReadLatestImage.");
242 return IMAGE_SUCCESS;
243 }
244
245 MIDK_EXPORT
OH_ImageReceiverNative_ReadNextImage(OH_ImageReceiverNative * receiver,OH_ImageNative ** image)246 Image_ErrorCode OH_ImageReceiverNative_ReadNextImage(OH_ImageReceiverNative* receiver, OH_ImageNative** image)
247 {
248 if (nullptr == receiver) {
249 IMAGE_LOGE("Invalid parameter: receiver=null.");
250 return IMAGE_BAD_PARAMETER;
251 }
252 if (nullptr == receiver->ptrImgRcv) {
253 IMAGE_LOGE("Bad parameter: receiver data empty.");
254 return IMAGE_BAD_PARAMETER;
255 }
256
257 auto bufferProcessor = receiver->ptrImgRcv->GetBufferProcessor();
258 if (nullptr == bufferProcessor) {
259 IMAGE_LOGE("Bad data: buffer processor empty.");
260 return IMAGE_UNKNOWN_ERROR;
261 }
262
263 int64_t timestamp = 0;
264 auto surfaceBuffer = receiver->ptrImgRcv->ReadNextImage(timestamp);
265 if (nullptr == surfaceBuffer) {
266 IMAGE_LOGE("Bad data: surfacebuffer empty.");
267 return IMAGE_UNKNOWN_ERROR;
268 }
269
270 auto rst = new OH_ImageNative;
271 if (nullptr == rst) {
272 IMAGE_LOGE("OH_ImageNative create failed.");
273 return IMAGE_ALLOC_FAILED;
274 }
275
276 rst->imgNative = new OHOS::Media::NativeImage(surfaceBuffer, bufferProcessor, timestamp);
277 if (!(rst->imgNative)) {
278 delete rst;
279 IMAGE_LOGE("OH_ImageNative data create failed.");
280 return IMAGE_UNKNOWN_ERROR;
281 }
282
283 *image = rst;
284 IMAGE_LOGI("OH_ImageNative ReadNextImage.");
285 return IMAGE_SUCCESS;
286 }
287
288 MIDK_EXPORT
OH_ImageReceiverNative_On(OH_ImageReceiverNative * receiver,OH_ImageReceiver_OnCallback callback)289 Image_ErrorCode OH_ImageReceiverNative_On(OH_ImageReceiverNative* receiver, OH_ImageReceiver_OnCallback callback)
290 {
291 if (nullptr == receiver || nullptr == callback) {
292 IMAGE_LOGE("OH_ImageReceiverNative_On: Invalid parameter");
293 return IMAGE_BAD_PARAMETER;
294 }
295 if (nullptr == receiver->ptrImgRcv) {
296 IMAGE_LOGE("Bad parameter: receiver data empty.");
297 return IMAGE_BAD_PARAMETER;
298 }
299
300 auto listener = std::make_shared<OHOS::Media::ImageReceiverListener>(receiver);
301 listener->callback_ = callback;
302 receiver->ptrImgRcv->RegisterBufferAvaliableListener(listener);
303 return IMAGE_SUCCESS;
304 }
305
306 MIDK_EXPORT
OH_ImageReceiverNative_Off(OH_ImageReceiverNative * receiver)307 Image_ErrorCode OH_ImageReceiverNative_Off(OH_ImageReceiverNative* receiver)
308 {
309 if (nullptr == receiver) {
310 IMAGE_LOGE("Invalid parameter: receiver=null.");
311 return IMAGE_BAD_PARAMETER;
312 }
313 if (nullptr == receiver->ptrImgRcv) {
314 IMAGE_LOGE("Bad parameter: receiver data empty.");
315 return IMAGE_BAD_PARAMETER;
316 }
317
318 receiver->ptrImgRcv->UnRegisterBufferAvaliableListener();
319 return IMAGE_SUCCESS;
320 }
321
322 MIDK_EXPORT
OH_ImageReceiverNative_GetSize(OH_ImageReceiverNative * receiver,Image_Size * size)323 Image_ErrorCode OH_ImageReceiverNative_GetSize(OH_ImageReceiverNative* receiver, Image_Size* size)
324 {
325 if (nullptr == receiver || nullptr == size) {
326 IMAGE_LOGE("OH_ImageReceiverNative_GetSize: Invalid parameter");
327 return IMAGE_BAD_PARAMETER;
328 }
329 if (nullptr == receiver->ptrImgRcv || nullptr == receiver->ptrImgRcv->iraContext_) {
330 IMAGE_LOGE("Bad parameter: receiver data empty.");
331 return IMAGE_BAD_PARAMETER;
332 }
333
334 size->width = static_cast<uint32_t>(receiver->ptrImgRcv->iraContext_->GetWidth());
335 size->height = static_cast<uint32_t>(receiver->ptrImgRcv->iraContext_->GetHeight());
336 return IMAGE_SUCCESS;
337 }
338
339 MIDK_EXPORT
OH_ImageReceiverNative_GetCapacity(OH_ImageReceiverNative * receiver,int32_t * capacity)340 Image_ErrorCode OH_ImageReceiverNative_GetCapacity(OH_ImageReceiverNative* receiver, int32_t* capacity)
341 {
342 if (nullptr == receiver || nullptr == capacity) {
343 IMAGE_LOGE("OH_ImageReceiverNative_GetCapacity: Invalid parameter");
344 return IMAGE_BAD_PARAMETER;
345 }
346 if (nullptr == receiver->ptrImgRcv || nullptr == receiver->ptrImgRcv->iraContext_) {
347 IMAGE_LOGE("Bad parameter: receiver data empty.");
348 return IMAGE_BAD_PARAMETER;
349 }
350
351 *capacity = receiver->ptrImgRcv->iraContext_->GetCapicity();
352 return IMAGE_SUCCESS;
353 }
354
355 MIDK_EXPORT
OH_ImageReceiverNative_Release(OH_ImageReceiverNative * receiver)356 Image_ErrorCode OH_ImageReceiverNative_Release(OH_ImageReceiverNative* receiver)
357 {
358 if (nullptr == receiver) {
359 IMAGE_LOGE("Invalid parameter: receiver=null.");
360 return IMAGE_BAD_PARAMETER;
361 }
362 receiver->ptrImgRcv.reset();
363 IMAGE_LOGI("OH_ImageReceiverNative Release.");
364 delete receiver;
365 return IMAGE_SUCCESS;
366 }
367
368 #ifdef __cplusplus
369 };
370 #endif