• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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 #define MLOG_TAG "MediaCallTranscode"
17 #include "moving_photo_call_transcoder.h"
18 
19 #include "js_native_api_types.h"
20 #include "medialibrary_errno.h"
21 #include "medialibrary_napi_log.h"
22 #include "moving_photo_transcoder_observer.h"
23 #include "native_event.h"
24 #include "unique_fd.h"
25 
26 namespace OHOS {
27 namespace Media {
28 const char* ON_PROGRESS_FUNC = "onProgress";
DoTranscode(const std::shared_ptr<MovingPhotoProgressHandler> & movingPhotoProgressHandler)29 bool MovingPhotoCallTranscoder::DoTranscode(const std::shared_ptr<MovingPhotoProgressHandler>
30     &movingPhotoProgressHandler)
31 {
32     if (movingPhotoProgressHandler == nullptr) {
33         NAPI_ERR_LOG("movingPhotoProgressHandler is null");
34         return false;
35     }
36     auto transCoder = TransCoderFactory::CreateTransCoder();
37     if (transCoder == nullptr) {
38         NAPI_ERR_LOG("Failed to create TransCoder");
39         return false;
40     }
41     auto transCoderCb = std::make_shared<OHOS::Media::MovingphotoTranscoderObserver>();
42     if (transCoderCb == nullptr) {
43         NAPI_ERR_LOG("Failed to create transCoderCb");
44         return false;
45     }
46     transCoderCb->SetMovingPhotoProgress(movingPhotoProgressHandler);
47     transCoderCb->setTransCoder(transCoder);
48     if (transCoder->SetTransCoderCallback(transCoderCb) != E_OK) {
49         return transCoderCb->DoTranscodePrepareError("Failed to set TransCoder callback");
50     }
51     if (transCoder->SetInputFile(movingPhotoProgressHandler->srcFd.Get(), movingPhotoProgressHandler->offset,
52         movingPhotoProgressHandler->size) != E_OK) {
53         return transCoderCb->DoTranscodePrepareError("Failed to set input file for TransCoder");
54     }
55     if (transCoder->SetOutputFile(movingPhotoProgressHandler->destFd.Get()) != E_OK) {
56         return transCoderCb->DoTranscodePrepareError("Failed to set output file for TransCoder");
57     }
58     if (transCoder->SetOutputFormat(FORMAT_MPEG_4) != E_OK) {
59         return transCoderCb->DoTranscodePrepareError("Failed to SetOutputFormat");
60     }
61     if (transCoder->SetColorSpace(TRANSCODER_COLORSPACE_P3_FULL) != E_OK) {
62         return transCoderCb->DoTranscodePrepareError("Failed to SetColorSpace");
63     }
64     if (transCoder->Prepare() != E_OK) {
65         return transCoderCb->DoTranscodePrepareError("Failed to prepare TransCoder");
66     }
67     if (transCoder->Start() != E_OK) {
68         return transCoderCb->DoTranscodePrepareError("Failed to TransCoder Start");
69     }
70     NAPI_INFO_LOG("DoTranscode success");
71     return true;
72 }
73 
DoTranscodePrepareError(const std::string & errorMsg)74 bool MovingphotoTranscoderObserver::DoTranscodePrepareError(const std::string &errorMsg)
75 {
76     NAPI_ERR_LOG("DoTranscodePrepareError errorMsg:%{public}s", errorMsg.c_str());
77     isPrepareError.store(true);
78     if (transCoder_ != nullptr) {
79         transCoder_->Release();
80     }
81     return false;
82 }
83 
CallMovingProgressCallback(bool isComplete)84 void MovingphotoTranscoderObserver::CallMovingProgressCallback(bool isComplete)
85 {
86     NAPI_DEBUG_LOG("CallMovingProgressCallback");
87     if (movingPhotoProgressHandler_ == nullptr || movingPhotoProgressHandler_->onProgressFunc == nullptr) {
88         NAPI_ERR_LOG("CallMovingProgressCallback: movingPhotoProgressHandler_ is null");
89         return;
90     }
91 
92     napi_status status = napi_acquire_threadsafe_function(movingPhotoProgressHandler_->onProgressFunc);
93     if (status != napi_ok) {
94         NAPI_ERR_LOG("napi_acquire_threadsafe_function fail, status: %{public}d", static_cast<int32_t>(status));
95         return;
96     }
97     auto asyncHandler = std::make_unique<MovingPhotoProgressHandler>();
98     if (asyncHandler == nullptr) {
99         NAPI_ERR_LOG("CallMovingProgressCallback: asyncHandler is null");
100         return;
101     }
102     asyncHandler->isComplete = isComplete;
103     if (isComplete) {
104         asyncHandler->env = movingPhotoProgressHandler_->env;
105         asyncHandler->contextData = movingPhotoProgressHandler_->contextData;
106         asyncHandler->errCode = movingPhotoProgressHandler_->errCode;
107         asyncHandler->callbackFunc = movingPhotoProgressHandler_->callbackFunc;
108     } else {
109         asyncHandler->mediaAssetEnv = movingPhotoProgressHandler_->mediaAssetEnv;
110         asyncHandler->extra = movingPhotoProgressHandler_->extra;
111         asyncHandler->progressHandlerRef = movingPhotoProgressHandler_->progressHandlerRef;
112     }
113 
114     status = napi_call_threadsafe_function(movingPhotoProgressHandler_->onProgressFunc, (void *)asyncHandler.get(),
115         napi_tsfn_blocking);
116     if (status != napi_ok) {
117         NAPI_ERR_LOG("napi_call_threadsafe_function fail, status: %{public}d", static_cast<int32_t>(status));
118     }
119     (void)asyncHandler.release();
120 }
121 
OnProgress(napi_env env,napi_value cb,void * context,void * data)122 void MovingPhotoCallTranscoder::OnProgress(napi_env env, napi_value cb, void *context, void *data)
123 {
124     NAPI_DEBUG_LOG("OnProgress");
125     auto mpHandler = reinterpret_cast<MovingPhotoProgressHandler *>(data);
126     if (mpHandler == nullptr) {
127         NAPI_ERR_LOG("Moving photo progress env is null");
128         return;
129     }
130     if (mpHandler->isComplete) {
131         if (mpHandler->callbackFunc == nullptr) {
132             NAPI_ERR_LOG("OnProgress callbackFunc is null");
133             return;
134         }
135         mpHandler->callbackFunc(mpHandler->env, mpHandler->contextData, mpHandler->errCode);
136         return;
137     }
138     if (mpHandler->mediaAssetEnv == nullptr) {
139         NAPI_ERR_LOG("mpHandler mediaAssetEnv is null");
140         return;
141     }
142     napi_value result;
143     napi_status status = napi_create_int32(mpHandler->mediaAssetEnv,
144         mpHandler->extra, &result);
145     if (status != napi_ok) {
146         NAPI_ERR_LOG("OnProgress napi_create_int32 fail");
147         return;
148     }
149     napi_value jsCallback = nullptr;
150     status = napi_get_reference_value(mpHandler->mediaAssetEnv,
151         mpHandler->progressHandlerRef, &jsCallback);
152     if (status != napi_ok) {
153         NAPI_ERR_LOG("Create reference fail, status: %{public}d", status);
154         return;
155     }
156     napi_value jsOnProgress;
157     status = napi_get_named_property(mpHandler->mediaAssetEnv, jsCallback, ON_PROGRESS_FUNC,
158         &jsOnProgress);
159     if (status != napi_ok) {
160         NAPI_ERR_LOG("jsOnProgress napi_get_named_property fail, napi status: %{public}d",
161             static_cast<int>(status));
162         return;
163     }
164     const size_t ARGS_ONE = 1;
165     napi_value argv[ARGS_ONE];
166     napi_value retVal = nullptr;
167     argv[0] = result;
168     napi_call_function(mpHandler->mediaAssetEnv, nullptr, jsOnProgress, ARGS_ONE, argv, &retVal);
169     if (status != napi_ok) {
170         NAPI_ERR_LOG("CallJs napi_call_function fail, status: %{public}d", static_cast<int>(status));
171     }
172 }
173 
SetMovingPhotoProgress(const std::shared_ptr<MovingPhotoProgressHandler> & movingPhotoProgressHandler)174 void MovingphotoTranscoderObserver::SetMovingPhotoProgress(
175     const std::shared_ptr<MovingPhotoProgressHandler> &movingPhotoProgressHandler)
176 {
177     movingPhotoProgressHandler_ = movingPhotoProgressHandler;
178 }
179 
OnInfo(int32_t type,int32_t extra)180 void MovingphotoTranscoderObserver::OnInfo(int32_t type, int32_t extra)
181 {
182     NAPI_INFO_LOG("MediaAssetManagerCallback OnInfo type:%{public}d extra:%{public}d", type, extra);
183     if (movingPhotoProgressHandler_ == nullptr) {
184         NAPI_ERR_LOG("OnInfo, movingPhotoProgressHandler_ is null");
185         return;
186     }
187     if (type == INFO_TYPE_TRANSCODER_COMPLETED) {
188         if (transCoder_ == nullptr) {
189             NAPI_ERR_LOG("transCoder_ is null, cannot release resources");
190             return;
191         }
192         movingPhotoProgressHandler_->errCode = E_OK;
193         CallMovingProgressCallback(true);
194         transCoder_->Release();
195         return;
196     }
197     if (movingPhotoProgressHandler_->progressHandlerRef == nullptr) {
198         NAPI_INFO_LOG("progressHandlerRef is nullptr");
199         return;
200     }
201     movingPhotoProgressHandler_->extra = extra;
202     CallMovingProgressCallback();
203 }
204 
OnError(int32_t errCode,const std::string & errorMsg)205 void MovingphotoTranscoderObserver::OnError(int32_t errCode, const std::string &errorMsg)
206 {
207     NAPI_ERR_LOG("MediaAssetManagerCallback OnError errCode:%{public}d errorMsg:%{public}s",
208         errCode, errorMsg.c_str());
209     if (transCoder_ != nullptr) {
210         transCoder_->Release();
211     }
212     if (isPrepareError.load()) {
213         return;
214     }
215     if (movingPhotoProgressHandler_ != nullptr) {
216         movingPhotoProgressHandler_->errCode = E_ERR;
217     }
218     CallMovingProgressCallback(true);
219 }
220 } // namespace Media
221 } // namespace OHOS
222