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