• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "media_source_napi.h"
17 #include "media_log.h"
18 #include "media_dfx.h"
19 
20 namespace {
21 constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "MediaSourceNapi"};
22 constexpr uint32_t MAX_MEDIA_STREAM_ARRAY_LENGTH = 10;
23 }
24 
25 namespace OHOS {
26 namespace Media {
27 using namespace FunctionName;
28 const std::string CLASS_NAME = "MediaSource";
29 thread_local napi_ref MediaSourceNapi::constructor_ = nullptr;
30 
Init(napi_env env,napi_value exports)31 napi_value MediaSourceNapi::Init(napi_env env, napi_value exports)
32 {
33     napi_property_descriptor staticProperty[] = {
34         DECLARE_NAPI_STATIC_FUNCTION("createMediaSourceWithUrl", JsCreateMediaSourceWithUrl),
35         DECLARE_NAPI_STATIC_FUNCTION("createMediaSourceWithStreamData", JsCreateMediaSourceWithStreamData),
36     };
37 
38     napi_property_descriptor properties[] = {
39         DECLARE_NAPI_FUNCTION("setMimeType", JsSetMimeType),
40         DECLARE_NAPI_FUNCTION("setMediaResourceLoaderDelegate", JsSetMediaResourceLoaderDelegate),
41     };
42 
43     napi_value constructor = nullptr;
44     napi_status status = napi_define_class(env, CLASS_NAME.c_str(), NAPI_AUTO_LENGTH, Constructor, nullptr,
45         sizeof(properties) / sizeof(properties[0]), properties, &constructor);
46     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define AVPlayer class");
47 
48     status = napi_create_reference(env, constructor, 1, &constructor_);
49     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to create reference of constructor");
50 
51     status = napi_set_named_property(env, exports, CLASS_NAME.c_str(), constructor);
52     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to set constructor");
53 
54     status = napi_define_properties(env, exports, sizeof(staticProperty) / sizeof(staticProperty[0]), staticProperty);
55     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "Failed to define static function");
56     return exports;
57 }
58 
GetMediaSource(napi_env env,napi_value jsMediaSource)59 std::shared_ptr<AVMediaSourceTmp> MediaSourceNapi::GetMediaSource(napi_env env, napi_value jsMediaSource)
60 {
61     MediaSourceNapi *mediaSource = nullptr;
62     napi_status status = napi_unwrap(env, jsMediaSource, reinterpret_cast<void **>(&mediaSource));
63     CHECK_AND_RETURN_RET_LOG(status == napi_ok && mediaSource != nullptr, nullptr, "failed to napi_unwrap");
64 
65     return mediaSource->mediaSource_;
66 }
67 
GetSourceLoader(napi_env env,napi_value jsMediaSource)68 std::shared_ptr<MediaSourceLoaderCallback> MediaSourceNapi::GetSourceLoader(napi_env env, napi_value jsMediaSource)
69 {
70     MediaSourceNapi *mediaSource = nullptr;
71     napi_status status = napi_unwrap(env, jsMediaSource, reinterpret_cast<void **>(&mediaSource));
72     CHECK_AND_RETURN_RET_LOG(status == napi_ok && mediaSource != nullptr, nullptr, "failed to napi_unwrap");
73 
74     return mediaSource->mediaSourceLoaderCb_;
75 }
76 
Constructor(napi_env env,napi_callback_info info)77 napi_value MediaSourceNapi::Constructor(napi_env env, napi_callback_info info)
78 {
79     napi_value result = nullptr;
80     napi_get_undefined(env, &result);
81 
82     size_t argCount = 0;
83     napi_value jsThis = nullptr;
84     napi_status status = napi_get_cb_info(env, info, &argCount, nullptr, &jsThis, nullptr);
85     CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "failed to napi_get_cb_info");
86 
87     MediaSourceNapi *jsMediaSource = new(std::nothrow) MediaSourceNapi();
88     CHECK_AND_RETURN_RET_LOG(jsMediaSource != nullptr, result, "failed to new MediaSourceNapi");
89 
90     jsMediaSource->env_ = env;
91     jsMediaSource->mediaSource_ = std::make_shared<AVMediaSourceTmp>();
92     if (jsMediaSource->mediaSource_ == nullptr) {
93         delete jsMediaSource;
94         MEDIA_LOGE("Failed to Create MediaSource");
95         return result;
96     }
97 
98     status = napi_wrap(env, jsThis, reinterpret_cast<void *>(jsMediaSource),
99         MediaSourceNapi::Destructor, nullptr, nullptr);
100     if (status != napi_ok) {
101         delete jsMediaSource;
102         MEDIA_LOGE("Failed to wrap native instance");
103         return result;
104     }
105 
106     MEDIA_LOGI("0x%{public}06" PRIXPTR " Constructor success", FAKE_POINTER(jsMediaSource));
107     return jsThis;
108 }
109 
Destructor(napi_env env,void * nativeObject,void * finalize)110 void MediaSourceNapi::Destructor(napi_env env, void *nativeObject, void *finalize)
111 {
112     (void)env;
113     (void)finalize;
114     if (nativeObject != nullptr) {
115         MediaSourceNapi *jsMediaSource = reinterpret_cast<MediaSourceNapi *>(nativeObject);
116         jsMediaSource->mediaSource_ = nullptr;
117         if (jsMediaSource->mediaSourceLoaderCb_ != nullptr) {
118             jsMediaSource->mediaSourceLoaderCb_->ClearCallbackReference();
119             jsMediaSource->mediaSourceLoaderCb_ = nullptr;
120         }
121         delete jsMediaSource;
122     }
123     MEDIA_LOGI("Destructor success");
124 }
125 
JsCreateMediaSourceWithUrl(napi_env env,napi_callback_info info)126 napi_value MediaSourceNapi::JsCreateMediaSourceWithUrl(napi_env env, napi_callback_info info)
127 {
128     MEDIA_LOGD("JsCreateMediaSourceWithUrl In");
129     size_t argCount = 2;
130     napi_value args[2] = { nullptr };
131     napi_value jsMediaSource = nullptr;
132     napi_get_undefined(env, &jsMediaSource);
133     napi_status status = napi_get_cb_info(env, info, &argCount, args, nullptr, nullptr);
134     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "failed to napi_get_cb_info");
135 
136     napi_valuetype valueType = napi_undefined;
137     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_string) {
138         return nullptr;
139     }
140 
141     napi_value constructor = nullptr;
142     napi_status ret = napi_get_reference_value(env, constructor_, &constructor);
143     if (ret != napi_ok || constructor == nullptr) {
144         return nullptr;
145     }
146     napi_new_instance(env, constructor, 0, nullptr, &jsMediaSource);
147 
148     std::shared_ptr<AVMediaSourceTmp> mediaSource = GetMediaSource(env, jsMediaSource);
149     if (mediaSource == nullptr) {
150         MEDIA_LOGE("JsCreateMediaSourceWithUrl GetMediaSource fail");
151         return nullptr;
152     }
153     mediaSource->url = CommonNapi::GetStringArgument(env, args[0]);
154     MEDIA_LOGE("JsCreateMediaSourceWithUrl get map");
155     (void)CommonNapi::GetPropertyMap(env, args[1], mediaSource->header);
156     return jsMediaSource;
157 }
158 
JsCreateMediaSourceWithStreamData(napi_env env,napi_callback_info info)159 napi_value MediaSourceNapi::JsCreateMediaSourceWithStreamData(napi_env env, napi_callback_info info)
160 {
161     MEDIA_LOGD("JsCreateMediaSourceWithStreamData In");
162     size_t argCount = 1;
163     napi_value args[1] = { nullptr };
164     napi_value jsMediaSource = nullptr;
165     napi_get_undefined(env, &jsMediaSource);
166     napi_status status = napi_get_cb_info(env, info, &argCount, args, nullptr, nullptr);
167     CHECK_AND_RETURN_RET_LOG(status == napi_ok, nullptr, "failed to napi_get_cb_info");
168 
169     bool isArray = false;
170     if (argCount < 1 || napi_is_array(env, args[0], &isArray) != napi_ok || !isArray) {
171         return nullptr;
172     }
173 
174     uint32_t length = 0;
175     if (napi_get_array_length(env, args[0], &length) != napi_ok || length == 0)  {
176         return nullptr;
177     }
178     CHECK_AND_RETURN_RET_LOG(length <= MAX_MEDIA_STREAM_ARRAY_LENGTH, nullptr, "length Array<MediaStream> is too long");
179 
180     napi_value constructor = nullptr;
181     napi_status ret = napi_get_reference_value(env, constructor_, &constructor);
182     if (ret != napi_ok || constructor == nullptr) {
183         return nullptr;
184     }
185     napi_new_instance(env, constructor, 0, nullptr, &jsMediaSource);
186 
187     std::shared_ptr<AVMediaSourceTmp> mediaSource = GetMediaSource(env, jsMediaSource);
188     if (mediaSource == nullptr) {
189         MEDIA_LOGE("JsCreateMediaSourceWithStreamData GetMediaSource fail");
190         return nullptr;
191     }
192 
193     for (uint32_t i = 0; i < length; i++) {
194         napi_value element;
195         AVPlayMediaStreamTmp mediaStream;
196         status = napi_get_element(env, args[0], i, &element);
197         if (status != napi_ok) {
198             return nullptr;
199         }
200         if (!CommonNapi::GetPlayMediaStreamData(env, element, mediaStream)) {
201             return nullptr;
202         }
203         MEDIA_LOGI("url=%{private}s width=%{public}d height=%{public}d bitrate=%{public}d",
204             mediaStream.url.c_str(),
205             mediaStream.width,
206             mediaStream.height,
207             mediaStream.bitrate);
208         mediaSource->AddAVPlayMediaStreamTmp(mediaStream);
209     }
210     MEDIA_LOGD("JsCreateMediaSourceWithStreamData get mediaStreamVec length=%{public}u", length);
211     return jsMediaSource;
212 }
213 
JsSetMimeType(napi_env env,napi_callback_info info)214 napi_value MediaSourceNapi::JsSetMimeType(napi_env env, napi_callback_info info)
215 {
216     MEDIA_LOGI("JsSetMimeType In");
217     napi_value undefinedResult = nullptr;
218     napi_get_undefined(env, &undefinedResult);
219     size_t argCount = 1;
220     napi_value args[1] = {nullptr};
221     napi_value jsThis = nullptr;
222     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
223     CHECK_AND_RETURN_RET_LOG(status == napi_ok, undefinedResult, "failed to napi_get_cb_info");
224 
225     napi_valuetype valueType = napi_undefined;
226     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_string) {
227         return undefinedResult;
228     }
229 
230     std::string mimeType = CommonNapi::GetStringArgument(env, args[0]);
231     std::shared_ptr<AVMediaSourceTmp> mediaSource = GetMediaSource(env, jsThis);
232 
233     if (mediaSource == nullptr) {
234         MEDIA_LOGE("Fail to get mediaSource instance.");
235         return undefinedResult;
236     }
237     if (mimeType.empty()) {
238         MEDIA_LOGE("MimeType is empty.");
239         return undefinedResult;
240     }
241 
242     mediaSource->SetMimeType(mimeType);
243 
244     return undefinedResult;
245 }
246 
JsSetMediaResourceLoaderDelegate(napi_env env,napi_callback_info info)247 napi_value MediaSourceNapi::JsSetMediaResourceLoaderDelegate(napi_env env, napi_callback_info info)
248 {
249     MediaTrace trace("MediaSourceNapi::SetMediaResourceLoaderDelegate");
250     napi_value result = nullptr;
251     napi_get_undefined(env, &result);
252     MEDIA_LOGI("JsSetMediaResourceLoaderDelegate In");
253 
254     napi_value args[1] = { nullptr };
255     size_t argCount = 1;
256 
257     napi_value jsThis = nullptr;
258     napi_status status = napi_get_cb_info(env, info, &argCount, args, &jsThis, nullptr);
259     CHECK_AND_RETURN_RET_LOG(status == napi_ok && jsThis != nullptr, nullptr, "failed to napi_get_cb_info");
260 
261     MediaSourceNapi *mediaSource = nullptr;
262     status = napi_unwrap(env, jsThis, reinterpret_cast<void **>(&mediaSource));
263     CHECK_AND_RETURN_RET_LOG(status == napi_ok && mediaSource != nullptr, nullptr, "failed to napi_unwrap");
264 
265     napi_valuetype valueType = napi_undefined;
266     if (argCount < 1 || napi_typeof(env, args[0], &valueType) != napi_ok || valueType != napi_object) {
267         MEDIA_LOGE("SetMediaResourceLoaderDelegate invalid parameters");
268         return result;
269     }
270 
271     mediaSource->mediaSourceLoaderCb_ = std::make_shared<MediaSourceLoaderCallback>(env);
272     CHECK_AND_RETURN_RET_LOG(mediaSource->mediaSourceLoaderCb_ != nullptr, result, "Cb_ is nullptr");
273 
274     napi_value callback = nullptr;
275     napi_ref ref = nullptr;
276     napi_get_named_property(env, args[0], SOURCE_OPEN.c_str(), &callback);
277     status = napi_create_reference(env, callback, 1, &ref);
278     CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create open reference!");
279     std::shared_ptr<AutoRef> autoRef = std::make_shared<AutoRef>(env, ref);
280     CHECK_AND_RETURN_RET_LOG(autoRef != nullptr, result, "open is nullptr");
281     mediaSource->mediaSourceLoaderCb_->SaveCallbackReference(SOURCE_OPEN, autoRef);
282 
283     napi_get_named_property(env, args[0], SOURCE_READ.c_str(), &callback);
284     status = napi_create_reference(env, callback, 1, &ref);
285     CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create read reference!");
286     autoRef = std::make_shared<AutoRef>(env, ref);
287     CHECK_AND_RETURN_RET_LOG(autoRef != nullptr, result, "read is nullptr");
288     mediaSource->mediaSourceLoaderCb_->SaveCallbackReference(SOURCE_READ, autoRef);
289 
290     napi_get_named_property(env, args[0], SOURCE_CLOSE.c_str(), &callback);
291     status = napi_create_reference(env, callback, 1, &ref);
292     CHECK_AND_RETURN_RET_LOG(status == napi_ok && ref != nullptr, result, "failed to create close reference!");
293     autoRef = std::make_shared<AutoRef>(env, ref);
294     CHECK_AND_RETURN_RET_LOG(autoRef != nullptr, result, "close is nullptr");
295     mediaSource->mediaSourceLoaderCb_->SaveCallbackReference(SOURCE_CLOSE, autoRef);
296     MEDIA_LOGI("JsSetMediaResourceLoaderDelegate Out");
297     return result;
298 }
299 } // Media
300 } // OHOS