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 <dlfcn.h>
17#include <fcntl.h>
18#include <iostream>
19#include <linux/kd.h>
20
21#include <multimedia/image_framework/image/pixelmap_native.h>
22#include <multimedia/image_framework/image/image_packer_native.h>
23#include <multimedia/image_framework/image/image_source_native.h>
24#include "multimedia/image_framework/image_pixel_map_mdk.h"
25#include "napi/native_api.h"
26
27#include <string>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31
32#undef LOG_DOMAIN
33#undef LOG_TAG
34#define LOG_DOMAIN 0x3200
35#define LOG_TAG "MY_TAG"
36
37namespace {
38    const uint32_t NUM_0 = 0;
39    const uint32_t NUM_1 = 1;
40    const uint32_t NUM_2 = 2;
41    const uint32_t NUM_3 = 3;
42    const uint32_t NUM_4 = 4;
43    const uint32_t NUM_5 = 5;
44    const uint32_t NUM_6 = 6;
45    const uint32_t MAX_BUFFER_SIZE = 512;
46    const uint32_t MAX_COLOR_SIZE = 96;
47    const uint32_t MAX_QUALITY_SIZE = 98;
48    constexpr int8_t ARGB_8888_BYTES = 4;
49}
50
51const char *LOG_APP = "ImageNDK";
52const char* VPE_SO_NAME = "/sys_prod/lib64/VideoProcessingEngine/libaihdr_engine.so";
53
54static void OHLog(const char *module, const char *format, ...)
55{
56
57    char buffer[MAX_BUFFER_SIZE];
58    va_list args;
59    va_start(args, format);
60    vsnprintf(buffer, sizeof(buffer), format, args);
61    va_end(args);
62
63    printf("[%s] %s\n", module, buffer);
64}
65
66#define OH_LOG_ERROR(module, format, ...)                                                                              \
67    do {                                                                                                               \
68        OHLog(module, format, ##__VA_ARGS__);                                                                          \
69    } while (false)
70
71
72#define OH_LOG_INFO(module, format, ...)                                                                               \
73    do {                                                                                                               \
74        OHLog(module, format, ##__VA_ARGS__);                                                                          \
75    } while (false)
76
77static napi_value getJsResult(napi_env env, int result)
78{
79    napi_value resultNapi = nullptr;
80    napi_create_int32(env, result, &resultNapi);
81    return resultNapi;
82}
83
84static napi_value TestInitializationOptionsSetRowStrideNormal(napi_env env, napi_callback_info info)
85{
86    napi_value argValue[NUM_1] = {0};
87    size_t argCount = NUM_1;
88    if (napi_get_cb_info(env, info, &argCount, argValue, nullptr, nullptr) != napi_ok || argCount < NUM_1 ||
89        argValue[NUM_0] == nullptr) {
90        OH_LOG_ERROR(LOG_APP, "napi_get_cb_info failed, argCount: %{public}zu.", argCount);
91        return getJsResult(env, IMAGE_BAD_PARAMETER);
92    }
93    int32_t rowStride = 0;
94    napi_get_value_int32(env, argValue[0], &rowStride);
95    OH_Pixelmap_InitializationOptions *opts = nullptr;
96    Image_ErrorCode errCode = OH_PixelmapInitializationOptions_Create(&opts);
97    if (errCode != IMAGE_SUCCESS) {
98        OH_LOG_ERROR(LOG_APP, "OH_PixelmapInitializationOptions_Create failed, errCode: %{public}d.", errCode);
99        return getJsResult(env, errCode);
100    }
101    errCode = OH_PixelmapInitializationOptions_SetRowStride(opts, rowStride);
102    if (errCode != IMAGE_SUCCESS) {
103        return getJsResult(env, errCode);
104    }
105    int32_t getStride = 0;
106    errCode = OH_PixelmapInitializationOptions_GetRowStride(opts, &getStride);
107    if (errCode != IMAGE_SUCCESS) {
108        return getJsResult(env, errCode);
109    }
110    if (getStride != rowStride) {
111        return getJsResult(env, IMAGE_UNKNOWN_ERROR);
112    }
113    errCode = OH_PixelmapInitializationOptions_Release(opts);
114    if (errCode != IMAGE_SUCCESS) {
115        OH_LOG_ERROR(LOG_APP, "OH_PixelmapInitializationOptions_Release failed, errCode: %{public}d.", errCode);
116        return getJsResult(env, errCode);
117    }
118    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestInitializationOptionsSetRowStrideNormal success.");
119    return getJsResult(env, IMAGE_SUCCESS);
120}
121
122static napi_value TestCreatePixelMapWithStrideAbnormal(napi_env env, napi_callback_info info)
123{
124    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest Test OH_Pixelmap_CreatePixelMapWithStride will call.");
125    void* buffer = nullptr;
126    size_t bufferSize = 0;
127    struct OhosPixelMapCreateOps createOps;
128    napi_value pixelmap = nullptr;
129    size_t rowStride = -1; // set a error row stride
130    std::cout << "cout: ImagePixelmapNativeCTest Test will call OH_Pixelmap_CreatePixelMapWithStride." << std::endl;
131    int32_t res = OH_PixelMap_CreatePixelMapWithStride(env, createOps, buffer, bufferSize, rowStride, &pixelmap);
132    std::cout << "cout: ImagePixelmapNativeCTest Test OH_Pixelmap_CreatePixelMapWithStride." << std::endl;
133    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest Test OH_Pixelmap_CreatePixelMapWithStride, res: %{public}zu.", res);
134    if (res != IMAGE_RESULT_GET_DATA_ABNORMAL) {
135        return getJsResult(env, res);
136    }
137    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestCreatePixelMapWithStrideAbnormal success.");
138    return getJsResult(env, 0);
139}
140
141static napi_value TestNativeScaleWithAntiAliasingAbnormal(napi_env env, napi_callback_info info)
142{
143    float x = 1.5;
144    float y = 1.5;
145    OH_PixelmapNative *pixelmapNative = nullptr;
146    Image_ErrorCode errCode = OH_PixelmapNative_ScaleWithAntiAliasing(pixelmapNative, x, y,
147        OH_PixelmapNative_AntiAliasing_HIGH);
148    if (errCode != IMAGE_BAD_PARAMETER) {
149        OH_LOG_ERROR(LOG_APP, "OH_PixelmapNative_ScaleWithAntiAliasing failed, errCode: %{public}d.", errCode);
150        return getJsResult(env, errCode);
151    }
152    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestNativeScaleWithAntiAliasingNormal success.");
153    return getJsResult(env, IMAGE_SUCCESS);
154}
155
156static napi_value TestScaleWithAntiAliasingAbnormal(napi_env env, napi_callback_info info)
157{
158    napi_value result = nullptr;
159    napi_value thisVar = nullptr;
160    napi_value argValue[NUM_2] = {0};
161    size_t argCount = NUM_2;
162
163    napi_get_undefined(env, &result);
164    if (napi_get_cb_info(env, info, &argCount, argValue, &thisVar, nullptr) != napi_ok ||
165        argCount < NUM_2 || argValue[NUM_0] == nullptr || argValue[NUM_1] == nullptr) {
166        return result;
167    }
168    NativePixelMap* native = nullptr;
169    double x = 0;
170    double y = 0;
171    if (napi_get_value_double(env, argValue[NUM_0], &x) != napi_ok ||
172        napi_get_value_double(env, argValue[NUM_1], &y) != napi_ok) {
173        return result;
174    }
175
176    int32_t errCode = OH_PixelMap_ScaleWithAntiAliasing(
177        native, static_cast<float>(x), static_cast<float>(y), OH_PixelMap_AntiAliasing_HIGH);
178    if (errCode != IMAGE_RESULT_BAD_PARAMETER) {
179        OH_LOG_ERROR(LOG_APP, "OH_Pixelmap_ScaleWithAntiAliasing failed, errCode: %{public}d.", errCode);
180        return getJsResult(env, errCode);
181    }
182    return getJsResult(env, IMAGE_RESULT_SUCCESS);
183}
184
185static napi_value TestNativeGetNativeBufferAbnormal(napi_env env, napi_callback_info info)
186{
187    OH_PixelmapNative *pixelmapNative = nullptr;
188    OH_NativeBuffer **nativeBUffer = nullptr;
189    Image_ErrorCode errCode = OH_PixelmapNative_GetNativeBuffer(pixelmapNative, nativeBUffer);
190    if (errCode != IMAGE_BAD_PARAMETER) {
191        OH_LOG_ERROR(LOG_APP, "OH_PixelmapNative_GetNativeBuffer failed, errCode: %{public}d.", errCode);
192        return getJsResult(env, errCode);
193    }
194    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestNativeGetNativeBufferAbnormal success.");
195    return getJsResult(env, IMAGE_SUCCESS);
196}
197
198static napi_value TestNativeSetMetaDataNull(napi_env env, napi_callback_info info)
199{
200    OH_PixelmapNative *pixelmapNative = nullptr;
201    OH_Pixelmap_HdrMetadataValue *value = nullptr;
202    Image_ErrorCode errCode = OH_PixelmapNative_SetMetadata(pixelmapNative, HDR_METADATA_TYPE, value);
203    if (errCode != IMAGE_BAD_PARAMETER) {
204        OH_LOG_ERROR(LOG_APP, "OH_PixelmapNative_SetMetadata failed, errCode: %{public}d.", errCode);
205        return getJsResult(env, errCode);
206    }
207    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestNativeSetMetaDataNull success.");
208    return getJsResult(env, IMAGE_SUCCESS);
209}
210
211static napi_value TestNativeGetMetaDataNull(napi_env env, napi_callback_info info)
212{
213    OH_PixelmapNative *pixelmapNative = nullptr;
214    OH_Pixelmap_HdrMetadataValue **value = nullptr;
215    Image_ErrorCode errCode = OH_PixelmapNative_GetMetadata(pixelmapNative, HDR_METADATA_TYPE, value);
216    if (errCode != IMAGE_BAD_PARAMETER) {
217        OH_LOG_ERROR(LOG_APP, "OH_PixelmapNative_GetMetadata failed, errCode: %{public}d.", errCode);
218        return getJsResult(env, errCode);
219    }
220    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestNativeGetMetaDataNull success.");
221    return getJsResult(env, IMAGE_SUCCESS);
222}
223
224static napi_value TestNativeSetMemoryName(napi_env env, napi_callback_info info)
225{
226    OH_PixelmapNative *pixelmap = nullptr;
227    char name[] = "testName";
228    size_t len = strlen(name);
229    Image_ErrorCode errCode = OH_PixelmapNative_SetMemoryName(pixelmap, name, &len);
230    if (errCode != IMAGE_BAD_PARAMETER) {
231        OH_LOG_ERROR(LOG_APP, "OH_PixelmapNative_SetMemoryName failed, errCode: %{public}d.", errCode);
232        return getJsResult(env, errCode);
233    }
234    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestNativeSetMemoryName success.");
235    return getJsResult(env, IMAGE_SUCCESS);
236}
237
238static napi_value TestNativeGetArgbPixels(napi_env env, napi_callback_info info)
239{
240    OH_PixelmapNative *pixelMap = nullptr;
241    size_t dataSize = ARGB_8888_BYTES;
242    uint8_t result[ARGB_8888_BYTES];
243    Image_ErrorCode errCode = OH_PixelmapNative_GetArgbPixels(pixelMap, result, &dataSize);
244    if (errCode != IMAGE_BAD_PARAMETER) {
245        OH_LOG_ERROR(LOG_APP, "OH_PixelmapNative_GetArgbPixels failed, errCode: %{public}d.", errCode);
246        return getJsResult(env, errCode);
247    }
248    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestNativeGetArgbPixels success.");
249    return getJsResult(env, IMAGE_SUCCESS);
250}
251
252static napi_value TestNativeGetColorSpaceNative(napi_env env, napi_callback_info info)
253{
254    OH_PixelmapNative *pixelmap = nullptr;
255    OH_NativeColorSpaceManager *getColorSpaceNative = nullptr;
256    Image_ErrorCode errCode = OH_PixelmapNative_GetColorSpaceNative(pixelmap, &getColorSpaceNative);
257    if (errCode != IMAGE_BAD_PARAMETER) {
258        OH_LOG_ERROR(LOG_APP, "OH_PixelmapNative_GetColorSpaceNative failed, errCode: %{public}d.", errCode);
259        return getJsResult(env, errCode);
260    }
261    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestNativeGetColorSpaceNative success.");
262    return getJsResult(env, IMAGE_SUCCESS);
263}
264
265static napi_value TestNativeSetColorSpaceNative(napi_env env, napi_callback_info info)
266{
267    OH_PixelmapNative *pixelmap = nullptr;
268    OH_NativeColorSpaceManager *setColorSpaceNative = nullptr;
269    Image_ErrorCode errCode = OH_PixelmapNative_SetColorSpaceNative(pixelmap, setColorSpaceNative);
270    if (errCode != IMAGE_BAD_PARAMETER) {
271        OH_LOG_ERROR(LOG_APP, "OH_PixelmapNative_SetColorSpaceNative failed, errCode: %{public}d.", errCode);
272        return getJsResult(env, errCode);
273    }
274    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestNativeSetColorSpaceNative success.");
275    return getJsResult(env, IMAGE_SUCCESS);
276}
277
278static napi_value TestNativeSetGetSrcPixelFormat(napi_env env, napi_callback_info info)
279{
280    OH_Pixelmap_InitializationOptions *ops = nullptr;
281    OH_PixelmapInitializationOptions_Create(&ops);
282    int32_t srcpixelFormat = 0;
283    OH_PixelmapInitializationOptions_SetSrcPixelFormat(ops, 1);
284    OH_PixelmapInitializationOptions_GetSrcPixelFormat(ops, &srcpixelFormat);
285    Image_ErrorCode errCode = OH_PixelmapInitializationOptions_Release(ops);
286    if (errCode != IMAGE_BAD_PARAMETER) {
287        OH_LOG_ERROR(LOG_APP, "OH_PixelmapNative_SetGetSrcPixelFormat failed, errCode: %{public}d.", errCode);
288        return getJsResult(env, errCode);
289    }
290    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestNativeSetGetSrcPixelFormat success.");
291    return getJsResult(env, IMAGE_SUCCESS);
292}
293
294static napi_value TestNativeCreateEmptyPixelmap(napi_env env, napi_callback_info info)
295{
296    OH_Pixelmap_InitializationOptions *options = nullptr;
297    OH_PixelmapNative **pixelmap = nullptr;
298    Image_ErrorCode errCode = OH_PixelmapNative_CreateEmptyPixelmap(options, pixelmap);
299    if (errCode != IMAGE_BAD_PARAMETER) {
300        OH_LOG_ERROR(LOG_APP, "OH_PixelmapNative_CreateEmptyPixelmap failed, errCode: %{public}d.", errCode);
301        return getJsResult(env, errCode);
302    }
303    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestNativeCreateEmptyPixelmap success.");
304    return getJsResult(env, IMAGE_SUCCESS);
305}
306
307static napi_value TestNativeConvertAlphaFormat(napi_env env, napi_callback_info info)
308{
309    OH_PixelmapNative* srcpixelmap = nullptr;
310    OH_PixelmapNative* dstpixelmap = nullptr;
311    const bool isPremul = false;
312    Image_ErrorCode errCode = OH_PixelmapNative_ConvertAlphaFormat(srcpixelmap, dstpixelmap, isPremul);
313    if (errCode != IMAGE_BAD_PARAMETER) {
314        OH_LOG_ERROR(LOG_APP, "OH_PixelmapNative_ConvertAlphaFormat failed, errCode: %{public}d.", errCode);
315        return getJsResult(env, errCode);
316    }
317    OH_LOG_INFO(LOG_APP, "ImagePixelmapNativeCTest TestNativeConvertAlphaFormat success.");
318    return getJsResult(env, IMAGE_SUCCESS);
319}
320
321static void setInt32NamedProperty(napi_env env, napi_value object, const char *utf8name, uint32_t value)
322{
323    napi_value tmp;
324    napi_create_int32(env, value, &tmp);
325    napi_set_named_property(env, object, utf8name, tmp);
326}
327
328static bool CheckVpe()
329{
330    void* handle = dlopen(VPE_SO_NAME, RTLD_LAZY);
331    if (handle == nullptr) {
332        OH_LOG_INFO(LOG_APP, "CheckVpe failed");
333        return false;
334    }
335    dlclose(handle);
336    handle = nullptr;
337    return true;
338}
339
340EXTERN_C_START
341static napi_value Init(napi_env env, napi_value exports)
342{
343    napi_property_descriptor desc[] = {
344        {"testCreatePixelMapWithStrideAbnormal", nullptr, TestCreatePixelMapWithStrideAbnormal, nullptr, nullptr,
345         nullptr, napi_default, nullptr},
346        {"testInitializationOptionsSetRowStrideNormal", nullptr, TestInitializationOptionsSetRowStrideNormal, nullptr,
347         nullptr, nullptr, napi_default, nullptr},
348        {"testNativeScaleWithAntiAliasingAbnormal", nullptr, TestNativeScaleWithAntiAliasingAbnormal, nullptr, nullptr,
349         nullptr, napi_default, nullptr},
350        {"testScaleWithAntiAliasingAbnormal", nullptr, TestScaleWithAntiAliasingAbnormal, nullptr, nullptr,
351         nullptr, napi_default, nullptr},
352        {"testNativeGetNativeBufferAbnormal", nullptr, TestNativeGetNativeBufferAbnormal, nullptr, nullptr,
353         nullptr, napi_default, nullptr},
354        {"testNativeSetMetaDataNull", nullptr, TestNativeSetMetaDataNull, nullptr, nullptr,
355         nullptr, napi_default, nullptr},
356        {"testNativeSetMemoryName", nullptr, TestNativeSetMemoryName, nullptr, nullptr,
357         nullptr, napi_default, nullptr},
358        {"testNativeGetArgbPixels", nullptr, TestNativeGetArgbPixels, nullptr, nullptr,
359         nullptr, napi_default, nullptr},
360        {"testNativeGetColorSpaceNative", nullptr, TestNativeGetColorSpaceNative, nullptr, nullptr,
361         nullptr, napi_default, nullptr},
362        {"testNativeSetColorSpaceNative", nullptr, TestNativeSetColorSpaceNative, nullptr, nullptr,
363         nullptr, napi_default, nullptr},
364        {"testNativeGetMetaDataNull", nullptr, TestNativeGetMetaDataNull, nullptr, nullptr,
365         nullptr, napi_default, nullptr},
366        {"testNativeSetGetSrcPixelFormat", nullptr, TestNativeSetGetSrcPixelFormat, nullptr, nullptr,
367         nullptr, napi_default, nullptr},
368        {"testNativeCreateEmptyPixelmap", nullptr, TestNativeCreateEmptyPixelmap, nullptr,
369         nullptr, nullptr, napi_default, nullptr},
370        {"testNativeConvertAlphaFormat", nullptr, TestNativeConvertAlphaFormat, nullptr, nullptr,
371         nullptr, napi_default, nullptr},
372    };
373    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
374    return exports;
375}
376EXTERN_C_END
377
378static napi_module demoModule = {
379    .nm_version = 1,
380    .nm_flags = 0,
381    .nm_filename = nullptr,
382    .nm_register_func = Init,
383    .nm_modname = "entry",
384    .nm_priv = ((void *)0),
385    .reserved = {0},
386};
387
388extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }