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 #include "cj_avtranscoder.h"
17 #include "media_core.h"
18 #include "media_log.h"
19 #include "cj_avtranscoder_callback.h"
20
21 namespace OHOS {
22 namespace Media {
23
24 std::unordered_map<CjAVTransCoderOpt, const char *, EnumClassHash> OPT2CSTR = {
25 {CjAVTransCoderOpt::PREPARE, "Prepare"},
26 {CjAVTransCoderOpt::START, "Start"},
27 {CjAVTransCoderOpt::PAUSE, "Pause"},
28 {CjAVTransCoderOpt::RESUME, "Resume"},
29 {CjAVTransCoderOpt::CANCEL, "Cancel"},
30 {CjAVTransCoderOpt::RELEASE, "Release"},
31 {CjAVTransCoderOpt::SET_FD, "SetFd"}
32 };
33
34 std::unordered_map<CjAVTransCoderState, const char *, EnumClassHash> STATE2CSTR = {
35 {CjAVTransCoderState::STATE_IDLE, "idle"},
36 {CjAVTransCoderState::STATE_PREPARED, "prepared"},
37 {CjAVTransCoderState::STATE_STARTED, "started"},
38 {CjAVTransCoderState::STATE_PAUSED, "paused"},
39 {CjAVTransCoderState::STATE_CANCELLED, "cancelled"},
40 {CjAVTransCoderState::STATE_COMPLETED, "completed"},
41 {CjAVTransCoderState::STATE_RELEASED, "released"},
42 {CjAVTransCoderState::STATE_ERROR, "error"}
43
44 };
45
46 const std::unordered_map<CjAVTransCoderState, std::vector<CjAVTransCoderOpt>, EnumClassHash> STATE_LIST = {
47 {CjAVTransCoderState::STATE_IDLE, {
48 CjAVTransCoderOpt::SET_FD,
49 CjAVTransCoderOpt::PREPARE,
50 CjAVTransCoderOpt::RELEASE
51 }},
52 {CjAVTransCoderState::STATE_PREPARED, {
53 CjAVTransCoderOpt::START,
54 CjAVTransCoderOpt::CANCEL,
55 CjAVTransCoderOpt::RELEASE
56 }},
57 {CjAVTransCoderState::STATE_STARTED, {
58 CjAVTransCoderOpt::PAUSE,
59 CjAVTransCoderOpt::CANCEL,
60 CjAVTransCoderOpt::RELEASE
61 }},
62 {CjAVTransCoderState::STATE_PAUSED, {
63 CjAVTransCoderOpt::RESUME,
64 CjAVTransCoderOpt::CANCEL,
65 CjAVTransCoderOpt::RELEASE
66 }},
67 {CjAVTransCoderState::STATE_CANCELLED, {
68 CjAVTransCoderOpt::RELEASE
69 }},
70 {CjAVTransCoderState::STATE_COMPLETED, {
71 CjAVTransCoderOpt::RELEASE
72 }},
73 {CjAVTransCoderState::STATE_RELEASED, {}},
74 {CjAVTransCoderState::STATE_ERROR, {
75 CjAVTransCoderOpt::RELEASE
76 }},
77 };
78
CreateAVTranscoder(int32_t * errorcode)79 int64_t CJAVTranscoder::CreateAVTranscoder(int32_t* errorcode)
80 {
81 CJAVTranscoder *cjAVTranscoder = FFIData::Create<CJAVTranscoder>();
82 if (cjAVTranscoder == nullptr) {
83 MEDIA_LOGE("No memory!");
84 *errorcode = MSERR_EXT_API9_NO_MEMORY;
85 return INVALID_ID;
86 }
87
88 cjAVTranscoder->transCoder_ = TransCoderFactory::CreateTransCoder();
89 if (cjAVTranscoder->transCoder_ == nullptr) {
90 FFIData::Release(cjAVTranscoder->GetID());
91 MEDIA_LOGE("failed to CreateTransCoder");
92 *errorcode = MSERR_EXT_API9_NO_MEMORY;
93 return INVALID_ID;
94 }
95
96 cjAVTranscoder->transCoderCb_ = std::make_shared<CJAVTranscoderCallback>();
97 (void)cjAVTranscoder->transCoder_->SetTransCoderCallback(cjAVTranscoder->transCoderCb_);
98
99 MEDIA_LOGI("Constructor success");
100 *errorcode = MSERR_EXT_API9_OK;
101 return cjAVTranscoder->GetID();
102 }
103
GetReturnRet(int32_t errCode)104 int32_t CJAVTranscoder::GetReturnRet(int32_t errCode)
105 {
106 MediaServiceExtErrCodeAPI9 err = MSErrorToExtErrorAPI9(static_cast<MediaServiceErrCode>(errCode));
107 MEDIA_LOGE("errCode: %{public}d, err: %{public}d", errCode, err);
108 return err;
109 }
110
GetAudioCodecFormat(const std::string & mime,AudioCodecFormat & codecFormat)111 int32_t CJAVTranscoder::GetAudioCodecFormat(const std::string &mime, AudioCodecFormat &codecFormat)
112 {
113 MEDIA_LOGI("mime %{public}s", mime.c_str());
114 const std::map<std::string_view, AudioCodecFormat> mimeStrToCodecFormat = {
115 { MediaAVCodec::CodecMimeType::AUDIO_AAC, AudioCodecFormat::AAC_LC },
116 { "", AudioCodecFormat::AUDIO_DEFAULT },
117 };
118
119 auto iter = mimeStrToCodecFormat.find(mime);
120 if (iter != mimeStrToCodecFormat.end()) {
121 codecFormat = iter->second;
122 return MSERR_OK;
123 }
124 return MSERR_INVALID_VAL;
125 }
126
GetVideoCodecFormat(const std::string & mime,VideoCodecFormat & codecFormat)127 int32_t CJAVTranscoder::GetVideoCodecFormat(const std::string &mime, VideoCodecFormat &codecFormat)
128 {
129 MEDIA_LOGI("mime %{public}s", mime.c_str());
130 const std::map<std::string_view, VideoCodecFormat> mimeStrToCodecFormat = {
131 { MediaAVCodec::CodecMimeType::VIDEO_AVC, VideoCodecFormat::H264 },
132 { MediaAVCodec::CodecMimeType::VIDEO_HEVC, VideoCodecFormat::H265 },
133 { "", VideoCodecFormat::VIDEO_DEFAULT },
134 };
135
136 auto iter = mimeStrToCodecFormat.find(mime);
137 if (iter != mimeStrToCodecFormat.end()) {
138 codecFormat = iter->second;
139 return MSERR_OK;
140 }
141 return MSERR_INVALID_VAL;
142 }
143
GetOutputFormat(const std::string & extension,OutputFormatType & type)144 int32_t CJAVTranscoder::GetOutputFormat(const std::string &extension, OutputFormatType &type)
145 {
146 MEDIA_LOGI("mime %{public}s", extension.c_str());
147 const std::map<std::string, OutputFormatType> extensionToOutputFormat = {
148 { "mp4", OutputFormatType::FORMAT_MPEG_4 },
149 { "m4a", OutputFormatType::FORMAT_M4A },
150 { "", OutputFormatType::FORMAT_DEFAULT },
151 };
152
153 auto iter = extensionToOutputFormat.find(extension);
154 if (iter != extensionToOutputFormat.end()) {
155 type = iter->second;
156 return MSERR_OK;
157 }
158 return MSERR_INVALID_VAL;
159 }
160
GetConfig(const CAVTransCoderConfig & cconfig,CjAVTransCoderConfig & config)161 int32_t CJAVTranscoder::GetConfig(const CAVTransCoderConfig &cconfig, CjAVTransCoderConfig &config)
162 {
163 int32_t ret = GetAudioCodecFormat(std::string(cconfig.audioCodecFormat), config.audioCodecFormat);
164 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "GetAudioCodecFormat failed");
165
166 ret = GetVideoCodecFormat(std::string(cconfig.videoCodecFormat), config.videoCodecFormat);
167 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "GetVideoCodecFormat failed");
168
169 ret = GetOutputFormat(std::string(cconfig.fileFormat), config.fileFormat);
170 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "GetOutputFormat failed");
171
172 config.audioBitrate = cconfig.audioBitrate;
173 config.videoBitrate = cconfig.videoBitrate;
174 config.videoFrameWidth = cconfig.videoFrameWidth;
175 config.videoFrameHeight = cconfig.videoFrameHeight;
176
177 return MSERR_OK;
178 }
179
StateCallback(CjAVTransCoderState state)180 void CJAVTranscoder::StateCallback(CjAVTransCoderState state)
181 {
182 if (STATE2CSTR.find(state) != STATE2CSTR.end()) {
183 MEDIA_LOGI("Change state to %{public}s", STATE2CSTR.at(state));
184 } else {
185 MEDIA_LOGW("state %{public}d is not in STATE2CSTR", static_cast<int32_t>(state));
186 }
187
188 CHECK_AND_RETURN_LOG(transCoderCb_ != nullptr, "transCoderCb_ is nullptr!");
189 auto cjCb = std::static_pointer_cast<CJAVTranscoderCallback>(transCoderCb_);
190 CjAVTransCoderState curState = cjCb->GetState();
191 if (curState == CjAVTransCoderState::STATE_ERROR && state != CjAVTransCoderState::STATE_RELEASED) {
192 MEDIA_LOGI("current state is error, only can execute release");
193 return;
194 }
195 cjCb->SendStateCallback(state, StateChangeReason::USER);
196 }
197
CheckStateMachine(CjAVTransCoderOpt opt)198 int32_t CJAVTranscoder::CheckStateMachine(CjAVTransCoderOpt opt)
199 {
200 auto cjCb = std::static_pointer_cast<CJAVTranscoderCallback>(transCoderCb_);
201 CHECK_AND_RETURN_RET_LOG(cjCb != nullptr, MSERR_NO_MEMORY, "cjCb is nullptr!");
202
203 CjAVTransCoderState curState = cjCb->GetState();
204 CHECK_AND_RETURN_RET_LOG(STATE_LIST.find(curState) != STATE_LIST.end(),
205 MSERR_INVALID_VAL, "state is not in list");
206 std::vector<CjAVTransCoderOpt> allowedOpt = STATE_LIST.at(curState);
207 if (find(allowedOpt.begin(), allowedOpt.end(), opt) == allowedOpt.end()) {
208 if ((OPT2CSTR.find(opt) == OPT2CSTR.end()) || (STATE2CSTR.find(curState) == STATE2CSTR.end())) {
209 MEDIA_LOGW("opt %{public}d is not in OPT2CSTR or state %{public}d is not in STATE2CSTR",
210 static_cast<int32_t>(opt), static_cast<int32_t>(curState));
211 MEDIA_LOGE("The %{public}d operation is not allowed in the %{public}d state!",
212 static_cast<int32_t>(opt), static_cast<int32_t>(curState));
213 } else {
214 MEDIA_LOGE("The %{public}s operation is not allowed in the %{public}s state!",
215 OPT2CSTR.at(opt), STATE2CSTR.at(curState));
216 }
217 return MSERR_INVALID_OPERATION;
218 }
219
220 return MSERR_OK;
221 }
222
CancelCallback()223 void CJAVTranscoder::CancelCallback()
224 {
225 CHECK_AND_RETURN_LOG(transCoderCb_ != nullptr, "transCoderCb_ is nullptr!");
226 auto cjCb = std::static_pointer_cast<CJAVTranscoderCallback>(transCoderCb_);
227 cjCb->ClearCallbackReference();
228 }
229
Prepare(std::shared_ptr<TransCoder> transCoder,const CAVTransCoderConfig & cconfig)230 int32_t CJAVTranscoder::Prepare(std::shared_ptr<TransCoder> transCoder, const CAVTransCoderConfig &cconfig)
231 {
232 int32_t ret = CheckStateMachine(CjAVTransCoderOpt::PREPARE);
233 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
234
235 CjAVTransCoderConfig config;
236 ret = GetConfig(cconfig, config);
237 CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, MSERR_EXT_API9_INVALID_PARAMETER, "GetConfig failed");
238
239 if (hasConfiged_) {
240 MEDIA_LOGE("CjAVTransCoderConfig has been configured and will not be configured again");
241 return MSERR_EXT_API9_OK;
242 }
243
244 ret = transCoder->SetOutputFormat(config.fileFormat);
245 CHECK_AND_RETURN_RET(ret == MSERR_OK, ((void)transCoder->Cancel(), GetReturnRet(ret)));
246
247 ret = transCoder->SetAudioEncoder(config.audioCodecFormat);
248 CHECK_AND_RETURN_RET(ret == MSERR_OK, ((void)transCoder->Cancel(), GetReturnRet(ret)));
249
250 ret = transCoder->SetAudioEncodingBitRate(config.audioBitrate);
251 CHECK_AND_RETURN_RET(ret == MSERR_OK, ((void)transCoder->Cancel(), GetReturnRet(ret)));
252
253 ret = transCoder->SetVideoEncoder(config.videoCodecFormat);
254 CHECK_AND_RETURN_RET(ret == MSERR_OK, ((void)transCoder->Cancel(), GetReturnRet(ret)));
255
256 ret = transCoder->SetVideoSize(config.videoFrameWidth, config.videoFrameHeight);
257 CHECK_AND_RETURN_RET(ret == MSERR_OK, ((void)transCoder->Cancel(), GetReturnRet(ret)));
258
259 ret = transCoder->SetVideoEncodingBitRate(config.videoBitrate);
260 CHECK_AND_RETURN_RET(ret == MSERR_OK, ((void)transCoder->Cancel(), GetReturnRet(ret)));
261
262 hasConfiged_ = true;
263
264 ret = transCoder->Prepare();
265 CHECK_AND_RETURN_RET(ret == MSERR_OK, ((void)transCoder->Cancel(), GetReturnRet(ret)));
266
267 StateCallback(CjAVTransCoderState::STATE_PREPARED);
268 return MSERR_EXT_API9_OK;
269 }
270
Start(std::shared_ptr<TransCoder> transCoder)271 int32_t CJAVTranscoder::Start(std::shared_ptr<TransCoder> transCoder)
272 {
273 int32_t ret = CheckStateMachine(CjAVTransCoderOpt::START);
274 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
275
276 ret = transCoder->Start();
277 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
278 StateCallback(CjAVTransCoderState::STATE_STARTED);
279 return MSERR_EXT_API9_OK;
280 }
281
Pause(std::shared_ptr<TransCoder> transCoder)282 int32_t CJAVTranscoder::Pause(std::shared_ptr<TransCoder> transCoder)
283 {
284 int32_t ret = CheckStateMachine(CjAVTransCoderOpt::PAUSE);
285 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
286
287 ret = transCoder->Pause();
288 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
289 StateCallback(CjAVTransCoderState::STATE_PAUSED);
290 return MSERR_EXT_API9_OK;
291 }
292
Resume(std::shared_ptr<TransCoder> transCoder)293 int32_t CJAVTranscoder::Resume(std::shared_ptr<TransCoder> transCoder)
294 {
295 int32_t ret = CheckStateMachine(CjAVTransCoderOpt::RESUME);
296 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
297
298 ret = transCoder->Resume();
299 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
300 StateCallback(CjAVTransCoderState::STATE_STARTED);
301 return MSERR_EXT_API9_OK;
302 }
303
Cancel(std::shared_ptr<TransCoder> transCoder)304 int32_t CJAVTranscoder::Cancel(std::shared_ptr<TransCoder> transCoder)
305 {
306 int32_t ret = CheckStateMachine(CjAVTransCoderOpt::CANCEL);
307 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
308
309 ret = transCoder->Cancel();
310 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
311 StateCallback(CjAVTransCoderState::STATE_CANCELLED);
312 hasConfiged_ = false;
313 return MSERR_EXT_API9_OK;
314 }
315
Release(std::shared_ptr<TransCoder> transCoder)316 int32_t CJAVTranscoder::Release(std::shared_ptr<TransCoder> transCoder)
317 {
318 int32_t ret = CheckStateMachine(CjAVTransCoderOpt::RELEASE);
319 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
320
321 ret = transCoder->Release();
322 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
323 StateCallback(CjAVTransCoderState::STATE_RELEASED);
324 CancelCallback();
325 hasConfiged_ = false;
326 return MSERR_EXT_API9_OK;
327 }
328
GetInputFile()329 CAVFileDescriptor CJAVTranscoder::GetInputFile()
330 {
331 return CAVFileDescriptor{
332 .fd = fdSrc_.fd, .offset = fdSrc_.offset, .length = fdSrc_.length};
333 }
334
SetInputFile(std::shared_ptr<TransCoder> transCoder,CAVFileDescriptor fdSrc)335 int32_t CJAVTranscoder::SetInputFile(std::shared_ptr<TransCoder> transCoder, CAVFileDescriptor fdSrc)
336 {
337 int32_t ret = CheckStateMachine(CjAVTransCoderOpt::SET_FD);
338 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
339
340 fdSrc_.fd = fdSrc.fd;
341 fdSrc_.offset = fdSrc.offset;
342 fdSrc_.length = fdSrc.length;
343 ret = transCoder->SetInputFile(fdSrc_.fd, fdSrc_.offset, fdSrc_.length);
344 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
345 return MSERR_EXT_API9_OK;
346 }
347
GetOutputFile()348 int32_t CJAVTranscoder::GetOutputFile()
349 {
350 return fdDst_;
351 }
352
SetOutputFile(std::shared_ptr<TransCoder> transCoder,int32_t fdDst)353 int32_t CJAVTranscoder::SetOutputFile(std::shared_ptr<TransCoder> transCoder, int32_t fdDst)
354 {
355 int32_t ret = CheckStateMachine(CjAVTransCoderOpt::SET_FD);
356 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
357
358 fdDst_ = fdDst;
359 ret = transCoder->SetOutputFile(fdDst);
360 CHECK_AND_RETURN_RET(ret == MSERR_OK, GetReturnRet(ret));
361 return MSERR_EXT_API9_OK;
362 }
363
OnProgressUpdate(int64_t callbackId)364 int32_t CJAVTranscoder::OnProgressUpdate(int64_t callbackId)
365 {
366 if (transCoderCb_ == nullptr) {
367 return MSERR_EXT_API9_NO_MEMORY;
368 }
369
370 auto cjCb = std::static_pointer_cast<CJAVTranscoderCallback>(transCoderCb_);
371 cjCb->SaveCallbackReference(CJAVTranscoderEvent::EVENT_PROGRESS_UPDATE, callbackId);
372 return MSERR_EXT_API9_OK;
373 }
374
OffProgressUpdate()375 int32_t CJAVTranscoder::OffProgressUpdate()
376 {
377 if (transCoderCb_ == nullptr) {
378 return MSERR_EXT_API9_NO_MEMORY;
379 }
380 auto cjCb = std::static_pointer_cast<CJAVTranscoderCallback>(transCoderCb_);
381 cjCb->CancelCallbackReference(CJAVTranscoderEvent::EVENT_PROGRESS_UPDATE);
382 return MSERR_EXT_API9_OK;
383 }
384
385
OnComplete(int64_t callbackId)386 int32_t CJAVTranscoder::OnComplete(int64_t callbackId)
387 {
388 if (transCoderCb_ == nullptr) {
389 return MSERR_EXT_API9_NO_MEMORY;
390 }
391
392 auto cjCb = std::static_pointer_cast<CJAVTranscoderCallback>(transCoderCb_);
393 cjCb->SaveCallbackReference(CJAVTranscoderEvent::EVENT_COMPLETE, callbackId);
394 return MSERR_EXT_API9_OK;
395 }
396
OffComplete()397 int32_t CJAVTranscoder::OffComplete()
398 {
399 if (transCoderCb_ == nullptr) {
400 return MSERR_EXT_API9_NO_MEMORY;
401 }
402 auto cjCb = std::static_pointer_cast<CJAVTranscoderCallback>(transCoderCb_);
403 cjCb->CancelCallbackReference(CJAVTranscoderEvent::EVENT_COMPLETE);
404 return MSERR_EXT_API9_OK;
405 }
406
OnError(int64_t callbackId)407 int32_t CJAVTranscoder::OnError(int64_t callbackId)
408 {
409 if (transCoderCb_ == nullptr) {
410 return MSERR_EXT_API9_NO_MEMORY;
411 }
412
413 auto cjCb = std::static_pointer_cast<CJAVTranscoderCallback>(transCoderCb_);
414 cjCb->SaveCallbackReference(CJAVTranscoderEvent::EVENT_ERROR, callbackId);
415 return MSERR_EXT_API9_OK;
416 }
417
OffError()418 int32_t CJAVTranscoder::OffError()
419 {
420 if (transCoderCb_ == nullptr) {
421 return MSERR_EXT_API9_NO_MEMORY;
422 }
423 auto cjCb = std::static_pointer_cast<CJAVTranscoderCallback>(transCoderCb_);
424 cjCb->CancelCallbackReference(CJAVTranscoderEvent::EVENT_ERROR);
425 return MSERR_EXT_API9_OK;
426 }
427 }
428 }