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 ¶m) 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>(¶m);
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