1 /*
2 * Copyright (c) 2023-2023 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 "output/deferred_photo_proxy_napi.h"
17
18 #include "camera_log.h"
19 #include "deferred_photo_proxy.h"
20 #include "hilog/log.h"
21 #include "image_napi.h"
22 #include "napi/native_common.h"
23 #include "photo_proxy.h"
24 #include "pixel_map_napi.h"
25
26 namespace OHOS {
27 namespace CameraStandard {
28 thread_local napi_ref DeferredPhotoProxyNapi::sConstructor_ = nullptr;
29 thread_local uint32_t DeferredPhotoProxyNapi::deferredPhotoProxyTaskId = DEFERRED_PHOTO_PROXY_TASKID;
DeferredPhotoProxyNapi()30 DeferredPhotoProxyNapi::DeferredPhotoProxyNapi() : env_(nullptr)
31 {
32 }
33
~DeferredPhotoProxyNapi()34 DeferredPhotoProxyNapi::~DeferredPhotoProxyNapi()
35 {
36 MEDIA_DEBUG_LOG("~DeferredPhotoProxyNapi is called");
37 }
38
39 // Constructor callback
DeferredPhotoProxyNapiConstructor(napi_env env,napi_callback_info info)40 napi_value DeferredPhotoProxyNapi::DeferredPhotoProxyNapiConstructor(napi_env env, napi_callback_info info)
41 {
42 MEDIA_DEBUG_LOG("DeferredPhotoProxyNapiConstructor is called");
43 napi_status status;
44 napi_value result = nullptr;
45 napi_value thisVar = nullptr;
46 napi_get_undefined(env, &result);
47 CAMERA_NAPI_GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar);
48 if (status == napi_ok && thisVar != nullptr) {
49 std::unique_ptr<DeferredPhotoProxyNapi> obj = std::make_unique<DeferredPhotoProxyNapi>();
50 obj->env_ = env;
51
52 obj->deferredPhotoProxy_ = static_cast<DeferredPhotoProxy*>(sPhotoProxy_.GetRefPtr());
53 obj->photoProxy_ = obj->deferredPhotoProxy_;
54 status = napi_wrap(env, thisVar, reinterpret_cast<void*>(obj.get()),
55 DeferredPhotoProxyNapi::DeferredPhotoProxyNapiDestructor, nullptr, nullptr);
56 if (status == napi_ok) {
57 obj.release();
58 return thisVar;
59 } else {
60 MEDIA_ERR_LOG("Failure wrapping js to native napi");
61 }
62 }
63 MEDIA_ERR_LOG("DeferredPhotoProxyNapiConstructor call Failed!");
64 return result;
65 }
66
DeferredPhotoProxyNapiDestructor(napi_env env,void * nativeObject,void * finalize_hint)67 void DeferredPhotoProxyNapi::DeferredPhotoProxyNapiDestructor(napi_env env, void* nativeObject, void* finalize_hint)
68 {
69 MEDIA_DEBUG_LOG("DeferredPhotoProxyNapiDestructor is called");
70 DeferredPhotoProxyNapi* deferredPhotoProxy = reinterpret_cast<DeferredPhotoProxyNapi*>(nativeObject);
71 if (deferredPhotoProxy != nullptr) {
72 delete deferredPhotoProxy;
73 }
74 }
75
Init(napi_env env,napi_value exports)76 napi_value DeferredPhotoProxyNapi::Init(napi_env env, napi_value exports)
77 {
78 MEDIA_DEBUG_LOG("Init is called");
79 napi_status status;
80 napi_value ctorObj;
81 int32_t refCount = 1;
82
83 napi_property_descriptor deferred_photo_proxy_properties[] = {
84 // DeferredPhotoProxy
85 DECLARE_NAPI_FUNCTION("getThumbnail", GetThumbnail),
86 DECLARE_NAPI_FUNCTION("release", Release),
87 };
88
89 status = napi_define_class(env, DEFERRED_PHOTO_NAPI_CLASS_NAME, NAPI_AUTO_LENGTH,
90 DeferredPhotoProxyNapiConstructor, nullptr,
91 sizeof(deferred_photo_proxy_properties) / sizeof(deferred_photo_proxy_properties[PARAM0]),
92 deferred_photo_proxy_properties, &ctorObj);
93 if (status == napi_ok) {
94 if (napi_create_reference(env, ctorObj, refCount, &sConstructor_) == napi_ok) {
95 status = napi_set_named_property(env, exports, DEFERRED_PHOTO_NAPI_CLASS_NAME, ctorObj);
96 if (status == napi_ok) {
97 return exports;
98 }
99 }
100 }
101 MEDIA_ERR_LOG("Init call Failed!");
102 return nullptr;
103 }
104
CreateDeferredPhotoProxy(napi_env env,sptr<DeferredPhotoProxy> deferredPhotoProxy)105 napi_value DeferredPhotoProxyNapi::CreateDeferredPhotoProxy(napi_env env, sptr<DeferredPhotoProxy> deferredPhotoProxy)
106 {
107 MEDIA_DEBUG_LOG("CreateDeferredPhotoProxy is called");
108 CAMERA_SYNC_TRACE;
109 napi_status status;
110 napi_value result = nullptr;
111 napi_value constructor;
112 napi_get_undefined(env, &result);
113 status = napi_get_reference_value(env, sConstructor_, &constructor);
114 if (status == napi_ok) {
115 sPhotoProxy_ = deferredPhotoProxy;
116 status = napi_new_instance(env, constructor, 0, nullptr, &result);
117 sPhotoProxy_ = nullptr;
118 if (status == napi_ok && result != nullptr) {
119 return result;
120 } else {
121 MEDIA_ERR_LOG("Failed to create deferredPhotoProxy obj instance");
122 }
123 }
124 napi_get_undefined(env, &result);
125 MEDIA_ERR_LOG("CreateDeferredPhotoProxy call Failed");
126 return result;
127 }
128
GetThumbnail(napi_env env,napi_callback_info info)129 napi_value DeferredPhotoProxyNapi::GetThumbnail(napi_env env, napi_callback_info info)
130 {
131 MEDIA_INFO_LOG("GetThumbnail is called");
132 napi_status status;
133 napi_value result = nullptr;
134 napi_value resource = nullptr;
135 size_t argc = ARGS_ZERO;
136 napi_value argv[ARGS_ZERO];
137 napi_value thisVar = nullptr;
138 CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
139 napi_get_undefined(env, &result);
140 std::unique_ptr<DeferredPhotoProxAsyncContext> asyncContext = std::make_unique<DeferredPhotoProxAsyncContext>();
141 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
142 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
143 CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
144 CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "GetThumbnail");
145 status = napi_create_async_work(
146 env, nullptr, resource,
147 [](napi_env env, void* data) {
148 auto context = static_cast<DeferredPhotoProxAsyncContext*>(data);
149 context->status = false;
150 // Start async trace
151 context->funcName = "DeferredPhotoProxyNapi::GetThumbnail";
152 context->taskId = CameraNapiUtils::IncrementAndGet(deferredPhotoProxyTaskId);
153 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
154 if (context->objectInfo != nullptr) {
155 context->status = true;
156 }
157 },
158 DeferredPhotoAsyncTaskComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
159 if (status != napi_ok) {
160 MEDIA_ERR_LOG("Failed to create napi_create_async_work for DeferredPhotoProxyNapi::GetThumbnail");
161 napi_get_undefined(env, &result);
162 } else {
163 napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
164 asyncContext.release();
165 }
166 } else {
167 MEDIA_ERR_LOG("GetThumbnail call Failed!");
168 }
169 return result;
170 }
171
DeferredPhotoAsyncTaskComplete(napi_env env,napi_status status,void * data)172 void DeferredPhotoProxyNapi::DeferredPhotoAsyncTaskComplete(napi_env env, napi_status status, void* data)
173 {
174 auto context = static_cast<DeferredPhotoProxAsyncContext*>(data);
175 void* fdAddr = context->objectInfo->deferredPhotoProxy_->GetFileDataAddr();
176 int32_t thumbnailWidth = context->objectInfo->deferredPhotoProxy_->GetWidth();
177 int32_t thumbnailHeight = context->objectInfo->deferredPhotoProxy_->GetHeight();
178 Media::InitializationOptions opts;
179 opts.srcPixelFormat = Media::PixelFormat::RGBA_8888;
180 opts.pixelFormat = Media::PixelFormat::RGBA_8888;
181 opts.size = { .width = thumbnailWidth, .height = thumbnailHeight };
182 MEDIA_INFO_LOG("thumbnailWidth:%{public}d, thumbnailheight: %{public}d",
183 thumbnailWidth, thumbnailHeight);
184 auto pixelMap = Media::PixelMap::Create(static_cast<const uint32_t*>(fdAddr),
185 thumbnailWidth * thumbnailHeight * 4, 0, thumbnailWidth, opts, true);
186 napi_value thumbnail = Media::PixelMapNapi::CreatePixelMap(env, std::move(pixelMap));
187 napi_resolve_deferred(env, context->deferred, thumbnail);
188 napi_delete_async_work(env, context->work);
189 }
190
Release(napi_env env,napi_callback_info info)191 napi_value DeferredPhotoProxyNapi::Release(napi_env env, napi_callback_info info)
192 {
193 MEDIA_INFO_LOG("Release is called");
194 napi_status status;
195 napi_value result = nullptr;
196 napi_value resource = nullptr;
197 size_t argc = ARGS_ZERO;
198 napi_value argv[ARGS_ZERO];
199 napi_value thisVar = nullptr;
200 CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
201 napi_get_undefined(env, &result);
202 std::unique_ptr<DeferredPhotoProxAsyncContext> asyncContext = std::make_unique<DeferredPhotoProxAsyncContext>();
203 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
204 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
205 CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
206 CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "Release");
207 status = napi_create_async_work(
208 env, nullptr, resource,
209 [](napi_env env, void* data) {
210 auto context = static_cast<DeferredPhotoProxAsyncContext*>(data);
211 context->status = false;
212 // Start async trace
213 context->funcName = "DeferredPhotoProxyNapi::Release";
214 context->taskId = CameraNapiUtils::IncrementAndGet(deferredPhotoProxyTaskId);
215 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
216 if (context->objectInfo != nullptr) {
217 context->status = true;
218 }
219 },
220 [](napi_env env, napi_status status, void* data) {
221 auto context = static_cast<DeferredPhotoProxAsyncContext*>(data);
222 napi_resolve_deferred(env, context->deferred, nullptr);
223 napi_delete_async_work(env, context->work);
224 delete context->objectInfo;
225 delete context;
226 }, static_cast<void*>(asyncContext.get()), &asyncContext->work);
227 if (status != napi_ok) {
228 MEDIA_ERR_LOG("Failed to create napi_create_async_work for DeferredPhotoProxyNapi::Release");
229 napi_get_undefined(env, &result);
230 } else {
231 napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
232 asyncContext.release();
233 }
234 } else {
235 MEDIA_ERR_LOG("Release call Failed!");
236 }
237 return result;
238 }
239 } // namespace CameraStandard
240 } // namespace OHOS