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