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 "transcoder_server.h"
17 #include "map"
18 #include "media_log.h"
19 #include "media_errors.h"
20 #include "engine_factory_repo.h"
21 #include "param_wrapper.h"
22 #include "accesstoken_kit.h"
23 #include "ipc_skeleton.h"
24 #include "media_dfx.h"
25 
26 namespace {
27     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_DOMAIN_PLAYER, "TransCoderServer"};
28     const std::map<OHOS::Media::TransCoderServer::RecStatus, std::string> TRANSCODER_STATE_MAP = {
29         {OHOS::Media::TransCoderServer::REC_INITIALIZED, "initialized"},
30         {OHOS::Media::TransCoderServer::REC_CONFIGURED, "configured"},
31         {OHOS::Media::TransCoderServer::REC_PREPARED, "prepared"},
32         {OHOS::Media::TransCoderServer::REC_TRANSCODERING, "transcordring"},
33         {OHOS::Media::TransCoderServer::REC_PAUSED, "paused"},
34         {OHOS::Media::TransCoderServer::REC_ERROR, "error"},
35     };
36 }
37 
38 namespace OHOS {
39 namespace Media {
40 const std::string START_TAG = "TransCoderCreate->Start";
41 const std::string STOP_TAG = "TransCoderStop->Destroy";
42 
Create()43 std::shared_ptr<ITransCoderService> TransCoderServer::Create()
44 {
45     std::shared_ptr<TransCoderServer> server = std::make_shared<TransCoderServer>();
46     int32_t ret = server->Init();
47     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, nullptr, "failed to init TransCoderServer");
48     return server;
49 }
50 
TransCoderServer()51 TransCoderServer::TransCoderServer()
52     : taskQue_("TranscoderServer")
53 {
54     taskQue_.Start();
55     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances create", FAKE_POINTER(this));
56     instanceId_ = HiviewDFX::HiTraceChain::GetId().GetChainId();
57 }
58 
~TransCoderServer()59 TransCoderServer::~TransCoderServer()
60 {
61     std::lock_guard<std::mutex> lock(mutex_);
62     ReleaseInner();
63     taskQue_.Stop();
64     MEDIA_LOGD("0x%{public}06" PRIXPTR " Instances destroy", FAKE_POINTER(this));
65 }
66 
Init()67 int32_t TransCoderServer::Init()
68 {
69     MediaTrace trace("TransCoderServer::Init");
70     uint32_t tokenId = IPCSkeleton::GetCallingTokenID();
71     uint64_t fullTokenId = IPCSkeleton::GetCallingFullTokenID();
72     int32_t appUid = IPCSkeleton::GetCallingUid();
73     int32_t appPid = IPCSkeleton::GetCallingPid();
74 
75     auto task = std::make_shared<TaskHandler<MediaServiceErrCode>>([&, this] {
76         auto engineFactory = EngineFactoryRepo::Instance().GetEngineFactory(
77             IEngineFactory::Scene::SCENE_TRANSCODER, appUid);
78         CHECK_AND_RETURN_RET_LOG(engineFactory != nullptr, MSERR_CREATE_REC_ENGINE_FAILED,
79             "failed to get factory");
80         transCoderEngine_ = engineFactory->CreateTransCoderEngine(appUid, appPid, tokenId, fullTokenId);
81         CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_CREATE_REC_ENGINE_FAILED,
82             "failed to create transCoder engine");
83         transCoderEngine_->SetInstanceId(instanceId_);
84         return MSERR_OK;
85     });
86     int32_t ret = taskQue_.EnqueueTask(task);
87     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
88 
89     auto result = task->GetResult();
90     CHECK_AND_RETURN_RET_LOG(result.Value() == MSERR_OK, result.Value(), "Result failed");
91 
92     status_ = REC_INITIALIZED;
93     return MSERR_OK;
94 }
95 
GetStatusDescription(OHOS::Media::TransCoderServer::RecStatus status)96 const std::string& TransCoderServer::GetStatusDescription(OHOS::Media::TransCoderServer::RecStatus status)
97 {
98     static const std::string ILLEGAL_STATE = "PLAYER_STATUS_ILLEGAL";
99     CHECK_AND_RETURN_RET(status >= OHOS::Media::TransCoderServer::REC_INITIALIZED &&
100         status <= OHOS::Media::TransCoderServer::REC_ERROR, ILLEGAL_STATE);
101 
102     return TRANSCODER_STATE_MAP.find(status)->second;
103 }
104 
OnError(TransCoderErrorType errorType,int32_t errorCode)105 void TransCoderServer::OnError(TransCoderErrorType errorType, int32_t errorCode)
106 {
107     (void)errorType;
108     std::lock_guard<std::mutex> lock(cbMutex_);
109     lastErrMsg_ = MSErrorToExtErrorString(static_cast<MediaServiceErrCode>(errorCode));
110     CHECK_AND_RETURN(transCoderCb_ != nullptr);
111     transCoderCb_->OnError(errorCode, lastErrMsg_);
112 }
113 
OnInfo(TransCoderOnInfoType type,int32_t extra)114 void TransCoderServer::OnInfo(TransCoderOnInfoType type, int32_t extra)
115 {
116     std::lock_guard<std::mutex> lock(cbMutex_);
117     CHECK_AND_RETURN(transCoderCb_ != nullptr);
118     transCoderCb_->OnInfo(type, extra);
119 }
120 
SetVideoEncoder(VideoCodecFormat encoder)121 int32_t TransCoderServer::SetVideoEncoder(VideoCodecFormat encoder)
122 {
123     std::lock_guard<std::mutex> lock(mutex_);
124     CHECK_AND_RETURN_RET_LOG(status_ == REC_CONFIGURED, MSERR_INVALID_OPERATION,
125         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
126     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
127     config_.videoCodec = encoder;
128     VideoEnc vidEnc(encoder);
129     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
130         return transCoderEngine_->Configure(vidEnc);
131     });
132     int32_t ret = taskQue_.EnqueueTask(task);
133     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
134 
135     auto result = task->GetResult();
136     return result.Value();
137 }
138 
SetVideoSize(int32_t width,int32_t height)139 int32_t TransCoderServer::SetVideoSize(int32_t width, int32_t height)
140 {
141     std::lock_guard<std::mutex> lock(mutex_);
142     CHECK_AND_RETURN_RET_LOG(status_ == REC_CONFIGURED, MSERR_INVALID_OPERATION,
143         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
144     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
145     config_.width = width;
146     config_.height = height;
147     VideoRectangle vidSize(width, height);
148     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
149         return transCoderEngine_->Configure(vidSize);
150     });
151     int32_t ret = taskQue_.EnqueueTask(task);
152     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
153 
154     auto result = task->GetResult();
155     return result.Value();
156 }
157 
SetVideoEncodingBitRate(int32_t rate)158 int32_t TransCoderServer::SetVideoEncodingBitRate(int32_t rate)
159 {
160     std::lock_guard<std::mutex> lock(mutex_);
161     CHECK_AND_RETURN_RET_LOG(status_ == REC_CONFIGURED, MSERR_INVALID_OPERATION,
162         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
163     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
164     config_.videoBitRate = rate;
165     VideoBitRate vidBitRate(rate);
166     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
167         return transCoderEngine_->Configure(vidBitRate);
168     });
169     int32_t ret = taskQue_.EnqueueTask(task);
170     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
171 
172     auto result = task->GetResult();
173     return result.Value();
174 }
175 
SetAudioEncoder(AudioCodecFormat encoder)176 int32_t TransCoderServer::SetAudioEncoder(AudioCodecFormat encoder)
177 {
178     std::lock_guard<std::mutex> lock(mutex_);
179     CHECK_AND_RETURN_RET_LOG(status_ == REC_CONFIGURED, MSERR_INVALID_OPERATION,
180         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
181     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
182     config_.audioCodec = encoder;
183     AudioEnc audEnc(encoder);
184     MEDIA_LOGD("set audio encoder encoder:%{public}d", encoder);
185     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
186         return transCoderEngine_->Configure(audEnc);
187     });
188     int32_t ret = taskQue_.EnqueueTask(task);
189     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
190 
191     auto result = task->GetResult();
192     return result.Value();
193 }
194 
SetAudioEncodingBitRate(int32_t bitRate)195 int32_t TransCoderServer::SetAudioEncodingBitRate(int32_t bitRate)
196 {
197     std::lock_guard<std::mutex> lock(mutex_);
198     CHECK_AND_RETURN_RET_LOG(status_ == REC_CONFIGURED, MSERR_INVALID_OPERATION,
199         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
200     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
201     config_.audioBitRate = bitRate;
202     AudioBitRate audBitRate(bitRate);
203     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
204         return transCoderEngine_->Configure(audBitRate);
205     });
206     int32_t ret = taskQue_.EnqueueTask(task);
207     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
208 
209     auto result = task->GetResult();
210     return result.Value();
211 }
212 
SetOutputFormat(OutputFormatType format)213 int32_t TransCoderServer::SetOutputFormat(OutputFormatType format)
214 {
215     std::lock_guard<std::mutex> lock(mutex_);
216     CHECK_AND_RETURN_RET_LOG(status_ == REC_INITIALIZED, MSERR_INVALID_OPERATION,
217         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
218     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
219     config_.format = format;
220     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
221         return transCoderEngine_->SetOutputFormat(format);
222     });
223     int32_t ret = taskQue_.EnqueueTask(task);
224     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
225 
226     auto result = task->GetResult();
227     ret = result.Value();
228     status_ = (ret == MSERR_OK ? REC_CONFIGURED : REC_INITIALIZED);
229     return ret;
230 }
231 
SetInputFile(int32_t fd,int64_t offset,int64_t size)232 int32_t TransCoderServer::SetInputFile(int32_t fd, int64_t offset, int64_t size)
233 {
234     std::lock_guard<std::mutex> lock(mutex_);
235     CHECK_AND_RETURN_RET_LOG(status_ == REC_INITIALIZED, MSERR_INVALID_OPERATION,
236         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
237     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
238     config_.srcFd = fd;
239     config_.srcFdOffset = offset;
240     config_.srcFdSize = size;
241     uriHelper_ = std::make_unique<UriHelper>(fd, offset, size);
242     CHECK_AND_RETURN_RET_LOG(uriHelper_->AccessCheck(UriHelper::URI_READ),
243         MSERR_INVALID_VAL, "Failed to read the fd");
244     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
245         return transCoderEngine_->SetInputFile(uriHelper_->FormattedUri());
246     });
247     int32_t ret = taskQue_.EnqueueTask(task);
248     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
249 
250     auto result = task->GetResult();
251     return result.Value();
252 }
253 
SetOutputFile(int32_t fd)254 int32_t TransCoderServer::SetOutputFile(int32_t fd)
255 {
256     std::lock_guard<std::mutex> lock(mutex_);
257     CHECK_AND_RETURN_RET_LOG(status_ == REC_INITIALIZED, MSERR_INVALID_OPERATION,
258         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
259     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
260     config_.dstUrl = fd;
261     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
262         return transCoderEngine_->SetOutputFile(fd);
263     });
264     int32_t ret = taskQue_.EnqueueTask(task);
265     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
266 
267     auto result = task->GetResult();
268     return result.Value();
269 }
270 
SetTransCoderCallback(const std::shared_ptr<TransCoderCallback> & callback)271 int32_t TransCoderServer::SetTransCoderCallback(const std::shared_ptr<TransCoderCallback> &callback)
272 {
273     std::lock_guard<std::mutex> lock(mutex_);
274     CHECK_AND_RETURN_RET_LOG(status_ == REC_INITIALIZED || status_ == REC_CONFIGURED, MSERR_INVALID_OPERATION,
275         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
276     {
277         std::lock_guard<std::mutex> cbLock(cbMutex_);
278         transCoderCb_ = callback;
279     }
280 
281     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
282     std::shared_ptr<ITransCoderEngineObs> obs = shared_from_this();
283     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
284         return transCoderEngine_->SetObs(obs);
285     });
286     int32_t ret = taskQue_.EnqueueTask(task);
287     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
288 
289     auto result = task->GetResult();
290     return result.Value();
291 }
292 
Prepare()293 int32_t TransCoderServer::Prepare()
294 {
295     std::lock_guard<std::mutex> lock(mutex_);
296     MediaTrace trace("TransCoderServer::Prepare");
297     CHECK_AND_RETURN_RET_LOG(status_ != REC_PREPARED, MSERR_INVALID_OPERATION, "Can not repeat Prepare");
298     CHECK_AND_RETURN_RET_LOG(status_ == REC_CONFIGURED, MSERR_INVALID_OPERATION,
299         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
300     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
301     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
302         return transCoderEngine_->Prepare();
303     });
304     int32_t ret = taskQue_.EnqueueTask(task);
305     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
306 
307     auto result = task->GetResult();
308     ret = result.Value();
309     status_ = (ret == MSERR_OK ? REC_PREPARED : REC_ERROR);
310     return ret;
311 }
312 
Start()313 int32_t TransCoderServer::Start()
314 {
315     std::lock_guard<std::mutex> lock(mutex_);
316     MediaTrace trace("TransCoderServer::Start");
317     CHECK_AND_RETURN_RET_LOG(status_ != REC_TRANSCODERING, MSERR_INVALID_OPERATION, "Can not repeat Start");
318     CHECK_AND_RETURN_RET_LOG(status_ == REC_PREPARED, MSERR_INVALID_OPERATION,
319         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
320     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
321     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
322         return transCoderEngine_->Start();
323     });
324     int32_t ret = taskQue_.EnqueueTask(task);
325     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
326 
327     auto result = task->GetResult();
328     ret = result.Value();
329     status_ = (ret == MSERR_OK ? REC_TRANSCODERING : REC_ERROR);
330     return ret;
331 }
332 
Pause()333 int32_t TransCoderServer::Pause()
334 {
335     MediaTrace trace("TransCoderServer::Pause");
336     std::lock_guard<std::mutex> lock(mutex_);
337     CHECK_AND_RETURN_RET_LOG(status_ != REC_PAUSED, MSERR_INVALID_OPERATION, "Can not repeat Pause");
338     CHECK_AND_RETURN_RET_LOG(status_ == REC_TRANSCODERING, MSERR_INVALID_OPERATION,
339         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
340     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
341     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
342         return transCoderEngine_->Pause();
343     });
344     int32_t ret = taskQue_.EnqueueTask(task);
345     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
346 
347     auto result = task->GetResult();
348     ret = result.Value();
349     status_ = (ret == MSERR_OK ? REC_PAUSED : REC_ERROR);
350     return ret;
351 }
352 
Resume()353 int32_t TransCoderServer::Resume()
354 {
355     MediaTrace trace("TransCoderServer::Resume");
356     std::lock_guard<std::mutex> lock(mutex_);
357     CHECK_AND_RETURN_RET_LOG(status_ != REC_TRANSCODERING, MSERR_INVALID_OPERATION, "Can not repeat Resume");
358     CHECK_AND_RETURN_RET_LOG(status_ == REC_TRANSCODERING || status_ == REC_PAUSED, MSERR_INVALID_OPERATION,
359         "invalid status, current status is %{public}s", GetStatusDescription(status_).c_str());
360     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
361     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
362         return transCoderEngine_->Resume();
363     });
364     int32_t ret = taskQue_.EnqueueTask(task);
365     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
366 
367     auto result = task->GetResult();
368     ret = result.Value();
369     status_ = (ret == MSERR_OK ? REC_TRANSCODERING : REC_ERROR);
370     return ret;
371 }
372 
Cancel()373 int32_t TransCoderServer::Cancel()
374 {
375     std::lock_guard<std::mutex> lock(mutex_);
376     MediaTrace trace("TransCoderServer::Cancel");
377     CHECK_AND_RETURN_RET_LOG(transCoderEngine_ != nullptr, MSERR_NO_MEMORY, "engine is nullptr");
378     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
379         return transCoderEngine_->Cancel();
380     });
381     int32_t ret = taskQue_.EnqueueTask(task);
382     CHECK_AND_RETURN_RET_LOG(ret == MSERR_OK, ret, "EnqueueTask failed");
383 
384     auto result = task->GetResult();
385     ret = result.Value();
386     status_ = (ret == MSERR_OK ? REC_INITIALIZED : REC_ERROR);
387     return ret;
388 }
389 
Release()390 int32_t TransCoderServer::Release()
391 {
392     std::lock_guard<std::mutex> lock(mutex_);
393     ReleaseInner();
394     return MSERR_OK;
395 }
396 
ReleaseInner()397 void TransCoderServer::ReleaseInner()
398 {
399     MEDIA_LOGI("ReleaseInner enter");
400     if (transCoderEngine_ == nullptr) {
401         return;
402     }
403     auto task = std::make_shared<TaskHandler<int32_t>>([&, this] {
404         int32_t ret = transCoderEngine_->Cancel();
405         transCoderEngine_ = nullptr;
406         return ret;
407     });
408     (void)taskQue_.EnqueueTask(task);
409     (void)task->GetResult();
410 }
411 
DumpInfo(int32_t fd)412 int32_t TransCoderServer::DumpInfo(int32_t fd)
413 {
414     std::string dumpString;
415     dumpString += "In TransCoderServer::DumpInfo\n";
416     dumpString += "TransCoderServer current state is: " + std::to_string(status_) + "\n";
417     if (lastErrMsg_.size() != 0) {
418         dumpString += "TransCoderServer last error is: " + lastErrMsg_ + "\n";
419     }
420     dumpString += "TransCoderServer videoCodec is: " + std::to_string(config_.videoCodec) + "\n";
421     dumpString += "TransCoderServer audioCodec is: " + std::to_string(config_.audioCodec) + "\n";
422     dumpString += "TransCoderServer width is: " + std::to_string(config_.width) + "\n";
423     dumpString += "TransCoderServer height is: " + std::to_string(config_.height) + "\n";
424     dumpString += "TransCoderServer bitRate is: " + std::to_string(config_.videoBitRate) + "\n";
425     dumpString += "TransCoderServer audioBitRate is: " + std::to_string(config_.audioBitRate) + "\n";
426     dumpString += "TransCoderServer format is: " + std::to_string(config_.format) + "\n";
427     write(fd, dumpString.c_str(), dumpString.size());
428 
429     return MSERR_OK;
430 }
431 } // namespace Media
432 } // namespace OHOS
433