1 /*
2  * Copyright (c) 2021-2021 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 #ifdef RECORDER_SUPPORT
16 #define HST_LOG_TAG "HiRecorderImpl"
17 
18 #include "hirecorder_impl.h"
19 #include <regex>
20 #include "foundation/cpp_ext/type_traits_ext.h"
21 #include "foundation/utils/hitrace_utils.h"
22 #include "foundation/utils/steady_clock.h"
23 #include "pipeline/factory/filter_factory.h"
24 #include "plugin/common/media_sink.h"
25 #include "plugin/common/plugin_time.h"
26 #include "recorder_utils.h"
27 #ifndef WIN32
28 #include <unistd.h> // include the dup function on Linux system
29 #endif
30 
31 namespace OHOS {
32 namespace Media {
33 namespace Record {
34 using namespace Pipeline;
35 
HiRecorderImpl(int32_t appUid,int32_t appPid,uint32_t appTokenId,uint64_t appFullTokenId)36 HiRecorderImpl::HiRecorderImpl(int32_t appUid, int32_t appPid, uint32_t appTokenId, uint64_t appFullTokenId)
37     : appUid_(appUid), appPid_(appPid), appTokenId_(appTokenId), appFullTokenId_(appFullTokenId),
38       fsm_(*this), curFsmState_(StateId::INIT)
39 {
40     SYNC_TRACER();
41     MEDIA_LOG_I("hiRecorderImpl ctor");
42     FilterFactory::Instance().Init();
43     muxer_ = FilterFactory::Instance().CreateFilterWithType<MuxerFilter>(
44             "builtin.recorder.muxer", "muxer");
45     outputSink_ = FilterFactory::Instance().CreateFilterWithType<OutputSinkFilter>(
46             "builtin.recorder.output_sink", "output_sink");
47     FALSE_RETURN(muxer_ != nullptr);
48     FALSE_RETURN(outputSink_ != nullptr);
49     pipeline_ = std::make_shared<PipelineCore>();
50 }
51 
~HiRecorderImpl()52 HiRecorderImpl::~HiRecorderImpl()
53 {
54     fsm_.SendEvent(Intent::RESET);
55     fsm_.Stop();
56     MEDIA_LOG_D("dtor called.");
57 }
58 
Init()59 ErrorCode HiRecorderImpl::Init()
60 {
61     if (initialized_.load()) {
62         return ErrorCode::SUCCESS;
63     }
64     mediaStatStub_.Reset();
65     pipeline_->Init(this, nullptr);
66     ErrorCode ret = pipeline_->AddFilters({muxer_.get(), outputSink_.get()});
67     if (ret == ErrorCode::SUCCESS) {
68         ret = pipeline_->LinkFilters({muxer_.get(), outputSink_.get()});
69     }
70     FALSE_LOG(ret == ErrorCode::SUCCESS);
71     if (ret == ErrorCode::SUCCESS) {
72         fsm_.SetStateCallback(this);
73         fsm_.Start();
74         initialized_ = true;
75     } else {
76         pipeline_->RemoveFilterChain(muxer_.get());
77     }
78     return ret;
79 }
80 
SetAudioSource(AudioSourceType source,int32_t & sourceId)81 int32_t HiRecorderImpl::SetAudioSource(AudioSourceType source, int32_t& sourceId)
82 {
83     SYNC_TRACER();
84     MEDIA_LOG_I("SetAudioSource enter");
85     PROFILE_BEGIN("SetAudioSource begin");
86     sourceId = INVALID_SOURCE_ID;
87     FALSE_RETURN_V(source != AudioSourceType::AUDIO_SOURCE_INVALID,
88                    TransErrorCode(ErrorCode::ERROR_INVALID_PARAMETER_VALUE));
89     FALSE_RETURN_V(audioCount_ < static_cast<int32_t>(AUDIO_SOURCE_MAX_COUNT),
90                    TransErrorCode(ErrorCode::ERROR_INVALID_OPERATION));
91     auto tempSourceId = SourceIdGenerator::GenerateAudioSourceId(audioCount_);
92     auto ret = SetAudioSourceInternal(source, tempSourceId);
93     if (ret == ErrorCode::SUCCESS) {
94         audioCount_++;
95         audioSourceId_ = tempSourceId;
96         sourceId = static_cast<int32_t>(audioSourceId_);
97     }
98     PROFILE_END("SetAudioSource end.");
99     return TransErrorCode(ret);
100 }
101 
SetVideoSource(VideoSourceType source,int32_t & sourceId)102 int32_t HiRecorderImpl::SetVideoSource(VideoSourceType source, int32_t& sourceId)
103 {
104 #ifdef VIDEO_SUPPORT
105     MEDIA_LOG_I("SetVideoSource enter");
106     PROFILE_BEGIN("SetVideoSource begin");
107     sourceId = INVALID_SOURCE_ID;
108     FALSE_RETURN_V(source != VideoSourceType::VIDEO_SOURCE_BUTT,
109                    TransErrorCode(ErrorCode::ERROR_INVALID_PARAMETER_VALUE));
110     FALSE_RETURN_V(videoCount_ < static_cast<int32_t>(VIDEO_SOURCE_MAX_COUNT),
111                    TransErrorCode(ErrorCode::ERROR_INVALID_OPERATION));
112     auto tempSourceId = SourceIdGenerator::GenerateVideoSourceId(videoCount_);
113     auto ret = SetVideoSourceInternal(source, tempSourceId);
114     if (ret == ErrorCode::SUCCESS) {
115         videoCount_++;
116         videoSourceId_ = tempSourceId;
117         sourceId = videoSourceId_;
118     }
119     PROFILE_END("SetVideoSource end.");
120     return TransErrorCode(ret);
121 #else
122     return TransErrorCode(ErrorCode::ERROR_UNIMPLEMENTED);
123 #endif
124 }
125 
GetSurface(int32_t sourceId)126 sptr<Surface> HiRecorderImpl::GetSurface(int32_t sourceId)
127 {
128 #ifdef VIDEO_SUPPORT
129     FALSE_RETURN_V(SourceIdGenerator::IsVideo(sourceId) && sourceId == static_cast<int32_t>(videoSourceId_) &&
130         videoCapture_ != nullptr, nullptr);
131     Plugin::Any any;
132     FALSE_RETURN_V(videoCapture_ ->GetParameter(static_cast<int32_t>(Plugin::Tag::VIDEO_SURFACE), any)
133                    != ErrorCode::SUCCESS, nullptr);
134     return Plugin::Any::IsSameTypeWith<sptr<Surface>>(any) ? Plugin::AnyCast<sptr<Surface>>(any) : nullptr;
135 #else
136     return nullptr;
137 #endif
138 }
139 
SetOutputFormat(OutputFormatType format)140 int32_t HiRecorderImpl::SetOutputFormat(OutputFormatType format)
141 {
142     MEDIA_LOG_I("OutputFormatType enter, format = " PUBLIC_LOG_D32, static_cast<int32_t>(format));
143     FALSE_RETURN_V(format != OutputFormatType::FORMAT_BUTT, TransErrorCode(ErrorCode::ERROR_INVALID_OPERATION));
144     FALSE_RETURN_V((audioCount_ + videoCount_) > static_cast<uint32_t>(0),
145                    TransErrorCode(ErrorCode::ERROR_INVALID_OPERATION));
146     outputFormatType_ = format;
147     auto ret = fsm_.SendEvent(Intent::SET_OUTPUT_FORMAT, outputFormatType_);
148     if (ret != ErrorCode::SUCCESS) {
149         MEDIA_LOG_E("SetOutputFormat failed with error " PUBLIC_LOG_S, GetErrorName(ret));
150     }
151     return TransErrorCode(ret);
152 }
153 
SetObs(const std::weak_ptr<IRecorderEngineObs> & obs)154 int32_t HiRecorderImpl::SetObs(const std::weak_ptr<IRecorderEngineObs>& obs)
155 {
156     MEDIA_LOG_I("SetObs enter");
157     obs_ = obs;
158     return TransErrorCode(ErrorCode::SUCCESS);
159 }
160 
Configure(int32_t sourceId,const RecorderParam & recParam)161 int32_t HiRecorderImpl::Configure(int32_t sourceId, const RecorderParam& recParam)
162 {
163     SYNC_TRACER();
164     MEDIA_LOG_I("Configure enter");
165     FALSE_RETURN_V(outputFormatType_ != OutputFormatType::FORMAT_BUTT,
166                    TransErrorCode(ErrorCode::ERROR_INVALID_OPERATION));
167     FALSE_RETURN_V(CheckParamType(sourceId, recParam), TransErrorCode(ErrorCode::ERROR_INVALID_PARAMETER_VALUE));
168     HstRecParam hstRecParam;
169     auto castRet  = CastRecorderParam(sourceId, recParam, hstRecParam);
170     FALSE_RETURN_V(castRet, TransErrorCode(ErrorCode::ERROR_INVALID_PARAMETER_VALUE));
171     auto ret = fsm_.SendEvent(Intent::CONFIGURE, hstRecParam);
172     if (ret != ErrorCode::SUCCESS) {
173         MEDIA_LOG_E("Configure failed with error " PUBLIC_LOG_S, GetErrorName(ret));
174     }
175     return TransErrorCode(ret);
176 }
177 
Prepare()178 int32_t HiRecorderImpl::Prepare()
179 {
180     SYNC_TRACER();
181     MEDIA_LOG_D("Prepare entered, current fsm state: " PUBLIC_LOG_S ".", fsm_.GetCurrentState().c_str());
182     PROFILE_BEGIN();
183     auto ret = fsm_.SendEvent(Intent::PREPARE);
184     if (ret != ErrorCode::SUCCESS) {
185         PROFILE_END("Prepare failed,");
186         MEDIA_LOG_E("Prepare failed with error " PUBLIC_LOG_S, GetErrorName(ret));
187         return TransErrorCode(ret);
188     } else {
189         PROFILE_END("Prepare successfully,");
190     }
191     OSAL::ScopedLock lock(stateMutex_);
192     if (curFsmState_ == StateId::RECORDING_SETTING) { // Wait state change to ready
193         cond_.Wait(lock, [this] { return curFsmState_ != StateId::RECORDING_SETTING; });
194     }
195     MEDIA_LOG_D("Prepare finished, current fsm state: " PUBLIC_LOG "s.", fsm_.GetCurrentState().c_str());
196     PROFILE_END("Prepare finished, current fsm state: " PUBLIC_LOG "s.", fsm_.GetCurrentState().c_str());
197     if (curFsmState_ == StateId::READY) {
198         ret = ErrorCode::SUCCESS;
199     } else {
200         ret = ErrorCode::ERROR_UNKNOWN;
201     }
202     return TransErrorCode(ret);
203 }
204 
Start()205 int32_t HiRecorderImpl::Start()
206 {
207     SYNC_TRACER();
208     MEDIA_LOG_I("Start enter");
209     PROFILE_BEGIN();
210     ErrorCode ret;
211     if (curFsmState_ == StateId::PAUSE) {
212         ret = fsm_.SendEvent(Intent::RESUME);
213     } else {
214         ret = fsm_.SendEvent(Intent::START);
215     }
216     PROFILE_END("Start ret = " PUBLIC_LOG_D32, TransErrorCode(ret));
217     return TransErrorCode(ret);
218 }
219 
Pause()220 int32_t HiRecorderImpl::Pause()
221 {
222     SYNC_TRACER();
223     MEDIA_LOG_I("Pause enter");
224     PROFILE_BEGIN();
225     auto ret = TransErrorCode(fsm_.SendEvent(Intent::PAUSE));
226     PROFILE_END("Pause ret = " PUBLIC_LOG_D32, ret);
227     return ret;
228 }
229 
Resume()230 int32_t HiRecorderImpl::Resume()
231 {
232     SYNC_TRACER();
233     MEDIA_LOG_I("Resume enter");
234     PROFILE_BEGIN();
235     auto ret = TransErrorCode(fsm_.SendEvent(Intent::RESUME));
236     PROFILE_END("Resume ret = " PUBLIC_LOG_D32, ret);
237     return ret;
238 }
239 
Stop(bool isDrainAll)240 int32_t HiRecorderImpl::Stop(bool isDrainAll)
241 {
242     SYNC_TRACE_START("Hst recorder Stop");
243     MEDIA_LOG_I("Stop enter");
244     PROFILE_BEGIN();
245     MEDIA_LOG_D("Stop start, isDrainAll: " PUBLIC_LOG_U32, static_cast<uint32_t>(isDrainAll));
246     outputFormatType_ = OutputFormatType::FORMAT_BUTT;
247     auto ret = TransErrorCode(fsm_.SendEvent(Intent::STOP, isDrainAll));
248     PROFILE_END("Stop ret = " PUBLIC_LOG_D32, ret);
249     SYNC_TRACE_END();
250     FALSE_RETURN_V_MSG_E(ret == ERR_OK, ret, "send STOP event to fsm fail");
251     OSAL::ScopedLock lock(stateMutex_);
252     cond_.WaitFor(lock, 3000, [this] { // 3000: time out
253         return curFsmState_ == StateId::ERROR || curFsmState_ == StateId::INIT;
254     });
255     FALSE_RETURN_V_MSG_E(curFsmState_ == StateId::INIT, ERR_UNKNOWN_REASON, "stop fail");
256     return ERR_OK;
257 }
258 
Reset()259 int32_t HiRecorderImpl::Reset()
260 {
261     SYNC_TRACER();
262     MEDIA_LOG_I("Reset enter");
263     PROFILE_BEGIN();
264     if (curFsmState_ == StateId::RECORDING) {
265         Stop(false); // avoid start then reset the file is not be saved
266     }
267     auto ret = TransErrorCode(fsm_.SendEvent(Intent::RESET));
268     PROFILE_END("Resume ret = " PUBLIC_LOG_D32, ret);
269     return ret;
270 }
271 
SetParameter(int32_t sourceId,const RecorderParam & recParam)272 int32_t HiRecorderImpl::SetParameter(int32_t sourceId, const RecorderParam &recParam)
273 {
274     return Configure(sourceId, recParam);
275 }
276 
OnEvent(const Event & event)277 void HiRecorderImpl::OnEvent(const Event& event)
278 {
279     MEDIA_LOG_D("[HiStreamer] OnEvent (" PUBLIC_LOG_D32 ")", event.type);
280     switch (event.type) {
281         case EventType::EVENT_ERROR: {
282             fsm_.SendEventAsync(Intent::NOTIFY_ERROR, event.param);
283             auto ptr = obs_.lock();
284             if (ptr != nullptr) {
285                 ptr->OnError(IRecorderEngineObs::ErrorType::ERROR_INTERNAL,
286                              TransErrorCode(Plugin::AnyCast<ErrorCode>(event.param)));
287             }
288             break;
289         }
290         case EventType::EVENT_READY: {
291             fsm_.SendEventAsync(Intent::NOTIFY_READY);
292             break;
293         }
294         case EventType::EVENT_COMPLETE:
295             mediaStatStub_.ReceiveEvent(event);
296             if (mediaStatStub_.IsEventCompleteAllReceived()) {
297                 fsm_.SendEventAsync(Intent::NOTIFY_COMPLETE);
298             }
299             break;
300         default:
301             MEDIA_LOG_E("Unknown event(" PUBLIC_LOG_D32 ")", event.type);
302     }
303 }
304 
OnStateChanged(StateId state)305 void HiRecorderImpl::OnStateChanged(StateId state)
306 {
307     MEDIA_LOG_I("OnStateChanged from " PUBLIC_LOG_D32 " to " PUBLIC_LOG_D32, curFsmState_.load(), state);
308     {
309         OSAL::ScopedLock lock(stateMutex_);
310         curFsmState_ = state;
311         cond_.NotifyOne();
312     }
313     auto ptr = obs_.lock();
314     if (ptr != nullptr) {
315         ptr->OnInfo(IRecorderEngineObs::InfoType::INTERNEL_WARNING, CppExt::to_underlying(state));
316     }
317 }
318 
DoSetVideoSource(const Plugin::Any & param) const319 ErrorCode HiRecorderImpl::DoSetVideoSource(const Plugin::Any& param) const
320 {
321 #ifdef VIDEO_SUPPORT
322     FALSE_RETURN_V_MSG_E(videoCapture_ != nullptr, ErrorCode::ERROR_INVALID_OPERATION,
323                          "videoCapture is NULL");
324     using SrcInputPair = std::pair<int32_t, Plugin::SrcInputType>;
325     if (Plugin::Any::IsSameTypeWith<SrcInputPair>(param)) {
326         auto srcType = Plugin::AnyCast<SrcInputPair>(param).second;
327         return videoCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::SRC_INPUT_TYPE), srcType);
328     } else {
329         return ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
330     }
331 #else
332     return ErrorCode::ERROR_UNIMPLEMENTED;
333 #endif
334 }
335 
DoSetAudioSource(const Plugin::Any & param) const336 ErrorCode HiRecorderImpl::DoSetAudioSource(const Plugin::Any& param) const
337 {
338     FALSE_RETURN_V_MSG_E(audioCapture_ != nullptr, ErrorCode::ERROR_INVALID_OPERATION,
339                          "audioCapture is NULL");
340     using SrcInputPair = std::pair<int32_t, Plugin::SrcInputType>;
341     if (Plugin::Any::IsSameTypeWith<SrcInputPair>(param)) {
342         auto srcType = Plugin::AnyCast<SrcInputPair>(param).second;
343         return audioCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::SRC_INPUT_TYPE), srcType);
344     } else {
345         return ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
346     }
347 }
348 
DoConfigure(const Plugin::Any & param) const349 ErrorCode HiRecorderImpl::DoConfigure(const Plugin::Any &param) const
350 {
351     if (!Plugin::Any::IsSameTypeWith<HstRecParam>(param)) {
352         return ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
353     }
354     ErrorCode ret  = ErrorCode::SUCCESS;
355     const auto* hstParam = Plugin::AnyCast<HstRecParam>(&param);
356     switch (hstParam->stdParamType) {
357         case RecorderPublicParamType::AUD_SAMPLERATE:
358         case RecorderPublicParamType::AUD_CHANNEL:
359         case RecorderPublicParamType::AUD_BITRATE:
360         case RecorderPublicParamType::AUD_ENC_FMT:
361             ret = DoConfigureAudio(*hstParam);
362             break;
363         case RecorderPublicParamType::VID_CAPTURERATE:
364         case RecorderPublicParamType::VID_RECTANGLE:
365         case RecorderPublicParamType::VID_BITRATE:
366         case RecorderPublicParamType::VID_FRAMERATE:
367         case RecorderPublicParamType::VID_ENC_FMT:
368             ret = DoConfigureVideo(*hstParam);
369             break;
370         case RecorderPublicParamType::OUT_PATH:
371         case RecorderPublicParamType::OUT_FD:
372         case RecorderPublicParamType::VID_ORIENTATION_HINT:
373         case RecorderPublicParamType::GEO_LOCATION:
374             ret = DoConfigureOther(*hstParam);
375             break;
376         default:
377             break;
378     }
379     return ret;
380 }
381 
DoSetOutputFormat(const Plugin::Any & param) const382 ErrorCode HiRecorderImpl::DoSetOutputFormat(const Plugin::Any& param) const
383 {
384     ErrorCode ret {ErrorCode::SUCCESS};
385     if (Plugin::Any::IsSameTypeWith<OutputFormatType>(param)) {
386         auto outputFormatType = Plugin::AnyCast<OutputFormatType>(param);
387         if (g_outputFormatToMimeMap.find(outputFormatType) != g_outputFormatToMimeMap.end()) {
388             ret = muxer_->SetOutputFormat(g_outputFormatToMimeMap.at(outputFormatType));
389         } else {
390             ret = ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
391         }
392     } else {
393         ret = ErrorCode::ERROR_INVALID_PARAMETER_TYPE;
394     }
395     if (ret != ErrorCode::SUCCESS) {
396         MEDIA_LOG_E("SetOutputFormat failed with error " PUBLIC_LOG_D32, static_cast<int>(ret));
397     }
398     return ret;
399 }
400 
DoPrepare()401 ErrorCode HiRecorderImpl::DoPrepare()
402 {
403     return pipeline_->Prepare();
404 }
405 
DoStart()406 ErrorCode HiRecorderImpl::DoStart()
407 {
408     return pipeline_->Start();
409 }
410 
DoPause()411 ErrorCode HiRecorderImpl::DoPause()
412 {
413     return curFsmState_ == StateId::READY ? ErrorCode::SUCCESS: pipeline_->Pause();
414 }
415 
DoResume()416 ErrorCode HiRecorderImpl::DoResume()
417 {
418     return pipeline_->Resume();
419 }
420 
DoStop(const Plugin::Any & param)421 ErrorCode HiRecorderImpl::DoStop(const Plugin::Any& param)
422 {
423     ErrorCode ret = ErrorCode::SUCCESS;
424     mediaStatStub_.Reset();
425     if (Plugin::AnyCast<bool>(param)) {
426         if (audioCapture_) {
427             ret = audioCapture_->SendEos();
428         }
429 #ifdef VIDEO_SUPPORT
430         if (videoCapture_) {
431             ret = videoCapture_->SendEos();
432         }
433 #endif
434     } else {
435         ret = muxer_->SendEos();
436     }
437     audioCount_ = 0;
438     videoCount_ = 0;
439     audioSourceId_ = 0;
440     videoSourceId_ = 0;
441     return ret;
442 }
443 
DoReset()444 ErrorCode HiRecorderImpl::DoReset()
445 {
446     ErrorCode ret = pipeline_->Stop();
447     mediaStatStub_.Reset();
448     audioCount_ = 0;
449     videoCount_ = 0;
450     audioSourceId_ = 0;
451     videoSourceId_ = 0;
452     return ret;
453 }
454 
DoOnComplete()455 ErrorCode HiRecorderImpl::DoOnComplete()
456 {
457     return pipeline_->Stop();
458 }
459 
SetAudioSourceInternal(AudioSourceType source,int32_t sourceId)460 ErrorCode HiRecorderImpl::SetAudioSourceInternal(AudioSourceType source, int32_t sourceId)
461 {
462     if (!audioCapture_) {
463         audioCapture_ = FilterFactory::Instance().CreateFilterWithType<AudioCaptureFilter>(
464                 "builtin.recorder.audiocapture", "audiocapture");
465         audioEncoder_ = FilterFactory::Instance().CreateFilterWithType<AudioEncoderFilter>(
466                 "builtin.recorder.audioencoder", "audioencoder");
467         auto ret = pipeline_->AddFilters({audioCapture_.get(), audioEncoder_.get()});
468         FALSE_RETURN_V_MSG_E(ret == ErrorCode::SUCCESS, ret, "AddFilters audioCapture to pipeline fail");
469         ret = pipeline_->LinkFilters({audioCapture_.get(), audioEncoder_.get()});
470         FALSE_RETURN_V_MSG_E(ret == ErrorCode::SUCCESS, ret, "LinkFilters audioCapture and audioEncoder fail");
471         std::shared_ptr<InPort> muxerInPort {nullptr};
472         ret = muxer_->AddTrack(muxerInPort);
473         FALSE_RETURN_V_MSG_E(ret == ErrorCode::SUCCESS, ret, "muxer AddTrack fail");
474         ret = pipeline_->LinkPorts(audioEncoder_->GetOutPort(PORT_NAME_DEFAULT), muxerInPort);
475         FALSE_RETURN_V_MSG_E(ret == ErrorCode::SUCCESS, ret, "LinkPorts audioEncoderOutPort and muxerInPort fail");
476     }
477     FALSE_RETURN_V_MSG_E(audioCapture_ != nullptr && audioEncoder_ != nullptr, ErrorCode::ERROR_UNKNOWN,
478                          "create audioCapture/audioEncoder filter fail");
479     audioCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::APP_TOKEN_ID), appTokenId_);
480     audioCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::APP_FULL_TOKEN_ID), appFullTokenId_);
481     audioCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::APP_UID), appUid_);
482     audioCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::APP_PID), appPid_);
483     return fsm_.SendEvent(Intent::SET_AUDIO_SOURCE,
484                           std::pair<int32_t, Plugin::SrcInputType>(sourceId, TransAudioInputType(source)));
485 }
486 
SetVideoSourceInternal(VideoSourceType source,int32_t sourceId)487 ErrorCode HiRecorderImpl::SetVideoSourceInternal(VideoSourceType source, int32_t sourceId)
488 {
489 #ifdef VIDEO_SUPPORT
490     videoCapture_ = FilterFactory::Instance().CreateFilterWithType<VideoCaptureFilter>(
491             "builtin.recorder.videocapture", "videocapture");
492     videoEncoder_ = FilterFactory::Instance().CreateFilterWithType<VideoEncoderFilter>(
493             "builtin.recorder.videoencoder", "videoencoder");
494     FALSE_RETURN_V_MSG_E(videoCapture_ != nullptr && videoEncoder_ != nullptr, ErrorCode::ERROR_UNKNOWN,
495                          "create videoCapture/videoEncoder filter fail");
496     auto ret = pipeline_->AddFilters({videoCapture_.get(), videoEncoder_.get()});
497     FALSE_RETURN_V_MSG_E(ret == ErrorCode::SUCCESS, ret, "AddFilters videoCapture to pipeline fail");
498     ret = pipeline_->LinkFilters({videoCapture_.get(), videoEncoder_.get()});
499     FALSE_RETURN_V_MSG_E(ret == ErrorCode::SUCCESS, ret, "LinkFilters videoCapture and videoEncoder fail");
500     std::shared_ptr<InPort> muxerInPort {nullptr};
501     ret =muxer_->AddTrack(muxerInPort);
502     FALSE_RETURN_V_MSG_E(ret == ErrorCode::SUCCESS, ret, "muxer AddTrack fail");
503     ret = pipeline_->LinkPorts(videoEncoder_->GetOutPort(PORT_NAME_DEFAULT), muxerInPort);
504     FALSE_RETURN_V_MSG_E(ret == ErrorCode::SUCCESS, ret, "LinkPorts videoEncoderOutPort and muxerInPort fail");
505     MEDIA_LOG_E("SendEvent: SET_VIDEO_SOURCE");
506     return fsm_.SendEvent(Intent::SET_VIDEO_SOURCE,
507                           std::pair<int32_t, Plugin::SrcInputType>(sourceId, TransVideoInputType(source)));
508 #else
509     return ErrorCode::ERROR_UNIMPLEMENTED;
510 #endif
511 }
512 
DoConfigureAudio(const HstRecParam & param) const513 ErrorCode HiRecorderImpl::DoConfigureAudio(const HstRecParam& param) const
514 {
515     FALSE_RETURN_V_MSG_E(audioCapture_ != nullptr && audioEncoder_ != nullptr, ErrorCode::ERROR_INVALID_OPERATION,
516                          "audioCapture/audioEncoder is NULL");
517     switch (param.stdParamType) {
518         case RecorderPublicParamType::AUD_SAMPLERATE: {
519             auto ptr = param.GetValPtr<AudSampleRate>();
520             FALSE_RETURN_V(ptr != nullptr, ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
521             MEDIA_LOG_I("set sample rate : " PUBLIC_LOG_D32, ptr->sampleRate);
522             return audioCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::AUDIO_SAMPLE_RATE),
523                                                static_cast<uint32_t>(ptr->sampleRate));
524         }
525         case RecorderPublicParamType::AUD_CHANNEL: {
526             auto ptr = param.GetValPtr<AudChannel>();
527             FALSE_RETURN_V(ptr != nullptr, ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
528             MEDIA_LOG_I("set channel : " PUBLIC_LOG_D32, ptr->channel);
529             return audioCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::AUDIO_CHANNELS),
530                                                static_cast<uint32_t>(ptr->channel));
531         }
532         case RecorderPublicParamType::AUD_BITRATE: {
533             auto ptr = param.GetValPtr<AudBitRate>();
534             FALSE_RETURN_V(ptr != nullptr && static_cast<int32_t>(ptr->bitRate) > 0,
535                 ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
536             MEDIA_LOG_I("set bitRate : " PUBLIC_LOG_D32, ptr->bitRate);
537             return audioCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::MEDIA_BITRATE),
538                                                static_cast<int64_t>(ptr->bitRate));
539         }
540         case RecorderPublicParamType::AUD_ENC_FMT: {
541             auto ptr = param.GetValPtr<AudEnc>();
542             FALSE_RETURN_V(ptr != nullptr, ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
543             auto encoderMeta = std::make_shared<Plugin::Meta>();
544             if (!TransAudioEncoderFmt(ptr->encFmt, *encoderMeta)) {
545                 return ErrorCode::ERROR_INVALID_PARAMETER_VALUE;
546             }
547             return audioEncoder_->SetAudioEncoder(param.srcId, encoderMeta);
548         }
549         default:
550             MEDIA_LOG_W("RecorderPublicParamType " PUBLIC_LOG_U32 " not supported", param.stdParamType);
551             return ErrorCode::SUCCESS;
552     }
553 }
554 
DoConfigureVideo(const HstRecParam & param) const555 ErrorCode HiRecorderImpl::DoConfigureVideo(const HstRecParam& param) const
556 {
557 #ifdef VIDEO_SUPPORT
558     FALSE_RETURN_V_MSG_E(videoCapture_ != nullptr && videoEncoder_ != nullptr, ErrorCode::ERROR_INVALID_OPERATION,
559                          "videoCapture/videoEncoder is NULL");
560     switch (param.stdParamType) {
561         case RecorderPublicParamType::VID_RECTANGLE: {
562             auto ptr = param.GetValPtr<VidRectangle>();
563             FALSE_RETURN_V(ptr != nullptr, ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
564             auto ret = videoCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::VIDEO_WIDTH),
565                                                    static_cast<uint32_t>(ptr->width));
566             if (ret == ErrorCode::SUCCESS) {
567                 ret = videoCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::VIDEO_HEIGHT),
568                                                   static_cast<uint32_t>(ptr->height));
569             }
570             return ret;
571         }
572         case RecorderPublicParamType::VID_CAPTURERATE: {
573             auto ptr = param.GetValPtr<CaptureRate>();
574             FALSE_RETURN_V(ptr != nullptr, ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
575             return videoCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::VIDEO_CAPTURE_RATE),
576                                                static_cast<double>(ptr->capRate));
577         }
578         case RecorderPublicParamType::VID_BITRATE: {
579             auto ptr = param.GetValPtr<VidBitRate>();
580             FALSE_RETURN_V(ptr != nullptr, ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
581             return videoCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::MEDIA_BITRATE),
582                 static_cast<int64_t>((ptr->bitRate >= 0) ? ptr->bitRate : 0));
583         }
584         case RecorderPublicParamType::VID_FRAMERATE: {
585             auto ptr = param.GetValPtr<VidFrameRate>();
586             FALSE_RETURN_V(ptr != nullptr, ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
587             return videoCapture_->SetParameter(static_cast<int32_t>(Plugin::Tag::VIDEO_FRAME_RATE),
588                 static_cast<uint32_t>((ptr->frameRate >= 0) ? ptr->frameRate : 0));
589         }
590         case RecorderPublicParamType::VID_ENC_FMT: {
591             auto ptr = param.GetValPtr<VidEnc>();
592             FALSE_RETURN_V(ptr != nullptr, ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
593             auto encoderMeta = std::make_shared<Plugin::Meta>();
594             FALSE_RETURN_V(TransVideoEncoderFmt(ptr->encFmt, *encoderMeta),
595                            ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
596             return videoEncoder_->SetVideoEncoder(param.srcId, encoderMeta);
597         }
598         default:
599             MEDIA_LOG_W("ignore RecorderPublicParamType " PUBLIC_LOG_U32, param.stdParamType);
600             return ErrorCode::SUCCESS;
601     }
602 #else
603     return ErrorCode::ERROR_UNIMPLEMENTED;
604 #endif
605 }
606 
DoConfigureOther(const HstRecParam & param) const607 ErrorCode HiRecorderImpl::DoConfigureOther(const HstRecParam& param) const
608 {
609     FALSE_RETURN_V_MSG_E(muxer_ != nullptr && outputSink_ != nullptr, ErrorCode::ERROR_INVALID_OPERATION,
610                          "muxer/outputSink is NULL");
611     switch (param.stdParamType) {
612         case RecorderPublicParamType::OUT_FD: {
613             auto ptr = param.GetValPtr<OutFd>();
614             FALSE_RETURN_V(ptr != nullptr, ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
615             MediaSink mediaSink {Plugin::ProtocolType::FD};
616             int32_t fd = ptr->fd;
617 #ifndef WIN32
618             fd = dup(fd);
619             FALSE_RETURN_V(fd >= 0, ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
620 #endif
621             mediaSink.SetFd(fd);
622             return outputSink_->SetSink(mediaSink);
623         }
624         case RecorderPublicParamType::MAX_DURATION: {
625             auto ptr = param.GetValPtr<MaxDuration>();
626             FALSE_RETURN_V(ptr != nullptr, ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
627             int64_t hstTime = 0;
628             Plugin::Sec2HstTime(ptr->duration, hstTime);
629             return muxer_->SetMaxDuration(hstTime > 0 ? hstTime : 0);
630         }
631         case RecorderPublicParamType::MAX_SIZE: {
632             auto ptr = param.GetValPtr<MaxFileSize>();
633             FALSE_RETURN_V(ptr != nullptr, ErrorCode::ERROR_INVALID_PARAMETER_VALUE);
634             return muxer_->SetMaxSize(ptr->size > 0 ? ptr->size : 0);
635         }
636         case RecorderPublicParamType::VID_ORIENTATION_HINT:
637         case RecorderPublicParamType::GEO_LOCATION:
638         default:
639             MEDIA_LOG_W("ignore RecorderPublicParamType " PUBLIC_LOG_U32, param.stdParamType);
640             return ErrorCode::SUCCESS;
641     }
642 }
643 
CheckParamType(int32_t sourceId,const RecorderParam & recParam) const644 bool HiRecorderImpl::CheckParamType(int32_t sourceId, const RecorderParam& recParam) const
645 {
646     FALSE_RETURN_V((SourceIdGenerator::IsAudio(sourceId) && recParam.IsAudioParam() &&
647         static_cast<int32_t>(audioSourceId_) == sourceId) ||
648         (SourceIdGenerator::IsVideo(sourceId) && recParam.IsVideoParam() &&
649         static_cast<int32_t>(videoSourceId_) == sourceId) ||
650         ((sourceId == DUMMY_SOURCE_ID) && !(recParam.IsAudioParam() || recParam.IsVideoParam())), false);
651     return true;
652 }
653 } // namespace Record
654 } // namespace Media
655 } // namespace OHOS
656 #endif