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 CHECK_ERROR_RETURN_RET(status == napi_ok, exports);
97 }
98 }
99 MEDIA_ERR_LOG("Init call Failed!");
100 return nullptr;
101 }
102
CreateDeferredPhotoProxy(napi_env env,sptr<DeferredPhotoProxy> deferredPhotoProxy)103 napi_value DeferredPhotoProxyNapi::CreateDeferredPhotoProxy(napi_env env, sptr<DeferredPhotoProxy> deferredPhotoProxy)
104 {
105 MEDIA_DEBUG_LOG("CreateDeferredPhotoProxy is called");
106 CAMERA_SYNC_TRACE;
107 napi_status status;
108 napi_value result = nullptr;
109 napi_value constructor;
110 napi_get_undefined(env, &result);
111 status = napi_get_reference_value(env, sConstructor_, &constructor);
112 if (status == napi_ok) {
113 sPhotoProxy_ = deferredPhotoProxy;
114 status = napi_new_instance(env, constructor, 0, nullptr, &result);
115 sPhotoProxy_ = nullptr;
116 if (status == napi_ok && result != nullptr) {
117 return result;
118 } else {
119 MEDIA_ERR_LOG("Failed to create deferredPhotoProxy obj instance");
120 }
121 }
122 napi_get_undefined(env, &result);
123 MEDIA_ERR_LOG("CreateDeferredPhotoProxy call Failed");
124 return result;
125 }
126
GetThumbnail(napi_env env,napi_callback_info info)127 napi_value DeferredPhotoProxyNapi::GetThumbnail(napi_env env, napi_callback_info info)
128 {
129 MEDIA_INFO_LOG("GetThumbnail is called");
130 napi_status status;
131 napi_value result = nullptr;
132 napi_value resource = nullptr;
133 size_t argc = ARGS_ZERO;
134 napi_value argv[ARGS_ZERO];
135 napi_value thisVar = nullptr;
136 CAMERA_NAPI_GET_JS_ARGS(env, info, argc, argv, thisVar);
137 napi_get_undefined(env, &result);
138 std::unique_ptr<DeferredPhotoProxAsyncContext> asyncContext = std::make_unique<DeferredPhotoProxAsyncContext>();
139 status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->objectInfo));
140 if (status == napi_ok && asyncContext->objectInfo != nullptr) {
141 CAMERA_NAPI_CREATE_PROMISE(env, asyncContext->callbackRef, asyncContext->deferred, result);
142 CAMERA_NAPI_CREATE_RESOURCE_NAME(env, resource, "GetThumbnail");
143 status = napi_create_async_work(
144 env, nullptr, resource,
145 [](napi_env env, void* data) {
146 auto context = static_cast<DeferredPhotoProxAsyncContext*>(data);
147 context->status = false;
148 // Start async trace
149 context->funcName = "DeferredPhotoProxyNapi::GetThumbnail";
150 context->taskId = CameraNapiUtils::IncrementAndGet(deferredPhotoProxyTaskId);
151 CAMERA_START_ASYNC_TRACE(context->funcName, context->taskId);
152 if (context->objectInfo != nullptr) {
153 context->status = true;
154 }
155 },
156 DeferredPhotoAsyncTaskComplete, static_cast<void*>(asyncContext.get()), &asyncContext->work);
157 if (status != napi_ok) {
158 MEDIA_ERR_LOG("Failed to create napi_create_async_work for DeferredPhotoProxyNapi::GetThumbnail");
159 napi_get_undefined(env, &result);
160 } else {
161 napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
162 asyncContext.release();
163 }
164 } else {
165 MEDIA_ERR_LOG("GetThumbnail call Failed!");
166 }
167 return result;
168 }
169
DeferredPhotoAsyncTaskComplete(napi_env env,napi_status status,void * data)170 void DeferredPhotoProxyNapi::DeferredPhotoAsyncTaskComplete(napi_env env, napi_status status, void* data)
171 {
172 auto context = static_cast<DeferredPhotoProxAsyncContext*>(data);
173 CAMERA_FINISH_ASYNC_TRACE(context->funcName, context->taskId);
174 void* fdAddr = context->objectInfo->deferredPhotoProxy_->GetFileDataAddr();
175 int32_t thumbnailWidth = context->objectInfo->deferredPhotoProxy_->GetWidth();
176 int32_t thumbnailHeight = context->objectInfo->deferredPhotoProxy_->GetHeight();
177 Media::InitializationOptions opts;
178 opts.srcPixelFormat = Media::PixelFormat::RGBA_8888;
179 opts.pixelFormat = Media::PixelFormat::RGBA_8888;
180 opts.size = { .width = thumbnailWidth, .height = thumbnailHeight };
181 MEDIA_INFO_LOG("thumbnailWidth:%{public}d, thumbnailheight: %{public}d",
182 thumbnailWidth, thumbnailHeight);
183 auto pixelMap = Media::PixelMap::Create(static_cast<const uint32_t*>(fdAddr),
184 thumbnailWidth * thumbnailHeight * 4, 0, thumbnailWidth, opts, true);
185 napi_value thumbnail = Media::PixelMapNapi::CreatePixelMap(env, std::move(pixelMap));
186 napi_resolve_deferred(env, context->deferred, thumbnail);
187 napi_delete_async_work(env, context->work);
188 delete context;
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 CAMERA_FINISH_ASYNC_TRACE(context->funcName, context->taskId);
223 napi_value result = nullptr;
224 napi_get_undefined(env, &result);
225 napi_resolve_deferred(env, context->deferred, result);
226 napi_delete_async_work(env, context->work);
227 delete context->objectInfo;
228 delete context;
229 }, static_cast<void*>(asyncContext.get()), &asyncContext->work);
230 if (status != napi_ok) {
231 MEDIA_ERR_LOG("Failed to create napi_create_async_work for DeferredPhotoProxyNapi::Release");
232 napi_get_undefined(env, &result);
233 } else {
234 napi_queue_async_work_with_qos(env, asyncContext->work, napi_qos_user_initiated);
235 asyncContext.release();
236 }
237 } else {
238 MEDIA_ERR_LOG("Release call Failed!");
239 }
240 return result;
241 }
242 } // namespace CameraStandard
243 } // namespace OHOS