• 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 #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 }