/* * Copyright (c) 2021-2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define HST_LOG_TAG "HiPlayerImpl" #include "hiplayer_impl.h" #include "foundation/log.h" #include "foundation/utils/steady_clock.h" #include "pipeline/factory/filter_factory.h" #include "plugin/common/plugin_time.h" namespace { const float MAX_MEDIA_VOLUME = 100.0f; } namespace OHOS { namespace Media { using namespace Pipeline; HiPlayerImpl::HiPlayerImpl() : fsm_(*this), curFsmState_(StateId::IDLE), volume_(-1.0f), mediaStats_() { MEDIA_LOG_I("hiPlayerImpl ctor"); FilterFactory::Instance().Init(); syncManager_ = std::make_shared(); audioSource_ = FilterFactory::Instance().CreateFilterWithType("builtin.player.mediasource", "mediaSource"); #ifdef UNIT_TEST demuxer_ = FilterFactory::Instance().CreateFilterWithType("builtin.player.demuxer", "demuxer"); audioDecoder_ = FilterFactory::Instance().CreateFilterWithType("builtin.player.audiodecoder", "audiodecoder"); audioSink_ = FilterFactory::Instance().CreateFilterWithType("builtin.player.audiosink", "audiosink"); #else demuxer_ = FilterFactory::Instance().CreateFilterWithType("builtin.player.demuxer", "demuxer"); audioSink_ = FilterFactory::Instance().CreateFilterWithType("builtin.player.audiosink", "audioSink"); #ifdef VIDEO_SUPPORT videoSink = FilterFactory::Instance().CreateFilterWithType("builtin.player.videosink", "videoSink"); FALSE_RETURN(videoSink != nullptr); videoSink->SetSyncCenter(syncManager_); #endif #endif FALSE_RETURN(audioSource_ != nullptr); FALSE_RETURN(demuxer_ != nullptr); FALSE_RETURN(audioSink_ != nullptr); audioSink_->SetSyncCenter(syncManager_); pipeline_ = std::make_shared(); } void HiPlayerImpl::UpdateStateNoLock(PlayerStates newState, bool notifyUpward) { if (pipelineStates_ == newState) { return; } pipelineStates_ = newState; if (pipelineStates_ == PlayerStates::PLAYER_IDLE) { MEDIA_LOG_W("do not report idle since audio player will report idle"); return; } if (notifyUpward) { auto ptr = callback_.lock(); if (ptr != nullptr) { while (!pendingStates_.empty()) { auto pendingState = pendingStates_.front(); pendingStates_.pop(); MEDIA_LOG_I("sending pending state change: " PUBLIC_LOG_S, StringnessPlayerState(pendingState).c_str()); } MEDIA_LOG_I("State change to : " PUBLIC_LOG_S, StringnessPlayerState(pipelineStates_.load()).c_str()); } } } HiPlayerImpl::~HiPlayerImpl() { MEDIA_LOG_D("dtor called."); fsm_.SendEventAsync(Intent::STOP); fsm_.Stop(); #ifdef VIDEO_SUPPORT videoSink.reset(); #endif audioSink_.reset(); syncManager_.reset(); } std::shared_ptr HiPlayerImpl::CreateHiPlayerImpl() { return std::shared_ptr(new (std::nothrow) HiPlayerImpl()); } int32_t HiPlayerImpl::Init() { mediaStats_.Reset(); if (initialized_.load()) { return CppExt::to_underlying(ErrorCode::SUCCESS); } pipeline_->Init(this, this); ErrorCode ret = pipeline_->AddFilters({audioSource_.get(), demuxer_.get()}); if (ret == ErrorCode::SUCCESS) { ret = pipeline_->LinkFilters({audioSource_.get(), demuxer_.get()}); } if (ret == ErrorCode::SUCCESS) { fsm_.SetStateCallback(this); fsm_.Start(); initialized_ = true; } else { pipeline_->RemoveFilterChain(audioSource_.get()); UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR); } return CppExt::to_underlying(ret); } int32_t HiPlayerImpl::SetSource(const Source& source) { PROFILE_BEGIN("SetSource begin"); auto ret = Init(); if (ret == CppExt::to_underlying(ErrorCode::SUCCESS)) { std::shared_ptr mediaSource = std::make_shared(source.GetSourceUri()); if (source.GetSourceType() == OHOS::Media::SourceType::SOURCE_TYPE_STREAM) { mediaSource = std::make_shared(source.GetDataConsumer()); } ret = CppExt::to_underlying(fsm_.SendEvent(Intent::SET_SOURCE, mediaSource)); } if (ret != CppExt::to_underlying(ErrorCode::SUCCESS)) { MEDIA_LOG_E("SetSource error: " PUBLIC_LOG_D32, ret); } PROFILE_END("SetSource end."); return ret; } int32_t HiPlayerImpl::Prepare() { MEDIA_LOG_I("Prepare entered, current fsm state: " PUBLIC_LOG_S ".", fsm_.GetCurrentState().c_str()); PROFILE_BEGIN(); auto ret = fsm_.SendEvent(Intent::PREPARE); if (ret != ErrorCode::SUCCESS) { PROFILE_END("Prepare failed,"); MEDIA_LOG_E("prepare failed with error " PUBLIC_LOG_D32, ret); return CppExt::to_underlying(ret); } OSAL::ScopedLock lock(stateMutex_); if (curFsmState_ == StateId::PREPARING) { // Wait state change to ready cond_.Wait(lock, [this] { return curFsmState_ != StateId::PREPARING; }); } MEDIA_LOG_D("Prepare finished, current fsm state: " PUBLIC_LOG "s.", fsm_.GetCurrentState().c_str()); PROFILE_END("Prepare finished, current fsm state: " PUBLIC_LOG "s.", fsm_.GetCurrentState().c_str()); if (curFsmState_ == StateId::READY) { return CppExt::to_underlying(ErrorCode::SUCCESS); } return CppExt::to_underlying(ErrorCode::ERROR_UNKNOWN); } PFilter HiPlayerImpl::CreateAudioDecoder(const std::string& desc) { if (!audioDecoderMap_[desc]) { audioDecoderMap_[desc] = FilterFactory::Instance().CreateFilterWithType( "builtin.player.audiodecoder", "audiodecoder-" + desc); // set parameters to decoder. } return audioDecoderMap_[desc]; } int32_t HiPlayerImpl::Play() { PROFILE_BEGIN(); ErrorCode ret; MEDIA_LOG_I("Play entered."); if (pipelineStates_ == PlayerStates::PLAYER_PAUSED) { ret = fsm_.SendEvent(Intent::RESUME); } else { ret = fsm_.SendEvent(Intent::PLAY); } PROFILE_END("Play ret = " PUBLIC_LOG_D32, CppExt::to_underlying(ret)); return CppExt::to_underlying(ret); } bool HiPlayerImpl::IsPlaying() { return pipelineStates_ == PlayerStates::PLAYER_STARTED; } int32_t HiPlayerImpl::Pause() { PROFILE_BEGIN(); MEDIA_LOG_I("Pause entered."); auto ret = CppExt::to_underlying(fsm_.SendEvent(Intent::PAUSE)); PROFILE_END("Pause ret = " PUBLIC_LOG_D32, ret); return ret; } int32_t HiPlayerImpl::Stop() { PROFILE_BEGIN(); MEDIA_LOG_I("Stop entered."); auto ret = CppExt::to_underlying(fsm_.SendEvent(Intent::STOP)); PROFILE_END("Stop ret = " PUBLIC_LOG_D32, ret); return ret; } ErrorCode HiPlayerImpl::StopAsync() { MEDIA_LOG_I("StopAsync entered."); return fsm_.SendEventAsync(Intent::STOP); } int32_t HiPlayerImpl::Rewind(int64_t mSeconds, int32_t mode) { MEDIA_LOG_I("Rewind entered."); int64_t hstTime = 0; int64_t durationMs = 0; NZERO_RETURN(GetDuration(durationMs)); MEDIA_LOG_D("Rewind durationMs : " PUBLIC_LOG_D64, durationMs); if (mSeconds >= durationMs) { // if exceeds change to duration mSeconds = durationMs; } if (audioSource_->GetSeekable() != Plugin::Seekable::SEEKABLE) { MEDIA_LOG_E("Seek, invalid operation, audio source is unseekable or invalid"); return CppExt::to_underlying(ErrorCode::ERROR_INVALID_OPERATION); } if (!Plugin::Ms2HstTime(mSeconds, hstTime)) { return CppExt::to_underlying(ErrorCode::ERROR_INVALID_PARAMETER_VALUE); } auto smode = Transform2SeekMode(static_cast(mode)); return CppExt::to_underlying(fsm_.SendEvent(Intent::SEEK, SeekInfo{hstTime, smode})); } int32_t HiPlayerImpl::SetVolume(float leftVolume, float rightVolume) { if (leftVolume < 0 || leftVolume > MAX_MEDIA_VOLUME || rightVolume < 0 || rightVolume > MAX_MEDIA_VOLUME) { MEDIA_LOG_E("volume not valid, should be in range [0,100]"); return CppExt::to_underlying(ErrorCode::ERROR_INVALID_PARAMETER_VALUE); } float volume = 0.0f; if (leftVolume < 1e-6 && rightVolume >= 1e-6) { // 1e-6 volume = rightVolume; } else if (rightVolume < 1e-6 && leftVolume >= 1e-6) { // 1e-6 volume = leftVolume; } else { volume = (leftVolume + rightVolume) / 2; // 2 } volume /= MAX_MEDIA_VOLUME; // normalize to 0~1 if (pipelineStates_ == PlayerStates::PLAYER_STOPPED) { return CppExt::to_underlying(ErrorCode::ERROR_INVALID_OPERATION); } volume_ = volume; if (pipelineStates_ == PlayerStates::PLAYER_IDLE || pipelineStates_ == PlayerStates::PLAYER_INITIALIZED || pipelineStates_ == PlayerStates::PLAYER_PREPARING || audioSink_ == nullptr) { MEDIA_LOG_W("cannot set volume, will do this onReady"); return CppExt::to_underlying(ErrorCode::SUCCESS); } return CppExt::to_underlying(SetVolumeToSink(volume_)); } #ifndef SURFACE_DISABLED int32_t HiPlayerImpl::SetSurface(Surface* surface) { return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED); } #endif ErrorCode HiPlayerImpl::SetBufferSize(size_t size) { return audioSource_->SetBufferSize(size); } void HiPlayerImpl::OnEvent(const Event& event) { if (event.type != EventType::EVENT_AUDIO_PROGRESS) { MEDIA_LOG_I("[HiStreamer] OnEvent (" PUBLIC_LOG_S ")", GetEventName(event.type)); } switch (event.type) { case EventType::EVENT_ERROR: { fsm_.SendEventAsync(Intent::NOTIFY_ERROR, event.param); break; } case EventType::EVENT_READY: fsm_.SendEventAsync(Intent::NOTIFY_READY); break; case EventType::EVENT_COMPLETE: mediaStats_.ReceiveEvent(event); if (mediaStats_.IsEventCompleteAllReceived()) { fsm_.SendEventAsync(Intent::NOTIFY_COMPLETE); } break; case EventType::EVENT_PLUGIN_ERROR: { HandlePluginErrorEvent(event); break; } case EventType::EVENT_PLUGIN_EVENT: { Plugin::PluginEvent pluginEvent = Plugin::AnyCast(event.param); if (pluginEvent.type == Plugin::PluginEventType::BELOW_LOW_WATERLINE || pluginEvent.type == Plugin::PluginEventType::ABOVE_LOW_WATERLINE) { MEDIA_LOG_I("Receive PLUGIN_EVENT, type: " PUBLIC_LOG_D32, CppExt::to_underlying(pluginEvent.type)); } break; } default: MEDIA_LOG_E("Unknown event(" PUBLIC_LOG_U32 ")", event.type); } } ErrorCode HiPlayerImpl::DoSetSource(const std::shared_ptr& source) { auto ret = audioSource_->SetSource(source); if (ret != ErrorCode::SUCCESS) { UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR); } return ret; } ErrorCode HiPlayerImpl::PrepareFilters() { auto ret = pipeline_->Prepare(); if (ret != ErrorCode::SUCCESS) { UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR); } return ret; } ErrorCode HiPlayerImpl::DoPlay() { syncManager_->Resume(); auto ret = pipeline_->Start(); if (ret != ErrorCode::SUCCESS) { UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR); } return ret; } ErrorCode HiPlayerImpl::DoPause() { auto ret = pipeline_->Pause(); syncManager_->Pause(); if (ret != ErrorCode::SUCCESS) { UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR); } return ret; } ErrorCode HiPlayerImpl::DoResume() { syncManager_->Resume(); auto ret = pipeline_->Resume(); if (ret != ErrorCode::SUCCESS) { UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR); } return ret; } ErrorCode HiPlayerImpl::DoStop() { MEDIA_LOG_I("HiPlayerImpl DoStop called, stop pipeline."); mediaStats_.Reset(); // 先先关闭demuxer线程,防止元数据解析prepare过程中出现并发问题 if (demuxer_) { demuxer_->StopTask(false); } auto ret = pipeline_->Stop(); syncManager_->Reset(); if (ret != ErrorCode::SUCCESS) { UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR); } return ret; } ErrorCode HiPlayerImpl::DoReset() { return DoStop(); } ErrorCode HiPlayerImpl::DoSeek(int64_t hstTime, Plugin::SeekMode mode, bool appTriggered) { if (appTriggered) { fsm_.Notify(Intent::SEEK, ErrorCode::SUCCESS); } PROFILE_BEGIN(); auto rtv = hstTime >= 0 ? ErrorCode::SUCCESS : ErrorCode::ERROR_INVALID_OPERATION; if (rtv == ErrorCode::SUCCESS) { pipeline_->FlushStart(); PROFILE_END("Flush start"); PROFILE_RESET(); int64_t realSeekTime = hstTime; rtv = demuxer_->SeekTo(hstTime, mode, realSeekTime); if (rtv == ErrorCode::SUCCESS) { syncManager_->Seek(realSeekTime); } PROFILE_END("SeekTo"); pipeline_->FlushEnd(); PROFILE_END("Flush end"); PROFILE_RESET(); } auto ptr = callback_.lock(); if (ptr != nullptr) { if (rtv != ErrorCode::SUCCESS) { ptr->OnError(CppExt::to_underlying(PlayerErrorTypeExt::SEEK_ERROR), CppExt::to_underlying(rtv)); } else { ptr->OnRewindToComplete(); } } if (appTriggered) { return ErrorCode::ERROR_NO_NOTIFY; } return rtv; } ErrorCode HiPlayerImpl::DoOnReady() { SetVolumeToSink(volume_, false); // do not report auto tmpMeta = demuxer_->GetGlobalMetaInfo(); sourceMeta_ = tmpMeta; int64_t duration = 0; bool found = false; if (tmpMeta->Get(duration)) { found = true; } else { MEDIA_LOG_W("Get media duration failed."); } streamMeta_.clear(); int64_t tmp = 0; for (auto& streamMeta : demuxer_->GetStreamMetaInfo()) { streamMeta_.push_back(streamMeta); if (streamMeta->Get(tmp)) { duration = std::max(duration, tmp); found = true; } else { MEDIA_LOG_W("Get media duration failed."); } } if (found) { duration_ = duration; } return ErrorCode::SUCCESS; } ErrorCode HiPlayerImpl::DoOnComplete() { MEDIA_LOG_W("OnComplete looping: " PUBLIC_LOG_D32 ".", singleLoop_.load()); auto ptr = callback_.lock(); FALSE_RETURN_V_MSG(ptr != nullptr, ErrorCode::SUCCESS, "Player callback not exist."); ptr->OnPlaybackComplete(); return ErrorCode::SUCCESS; } ErrorCode HiPlayerImpl::DoOnError(ErrorCode errorCode) { UpdateStateNoLock(PlayerStates::PLAYER_STATE_ERROR); auto ptr = callback_.lock(); FALSE_RETURN_V_MSG(ptr != nullptr, ErrorCode::SUCCESS, "Player callback not exist."); ptr->OnError(PlayerCallback::PlayerCallback::PLAYER_ERROR_UNKNOWN, static_cast(errorCode)); return ErrorCode::SUCCESS; } ErrorCode HiPlayerImpl::SetVolumeToSink(float volume, bool reportUpward) { MEDIA_LOG_I("SetVolumeToSink entered."); ErrorCode ret = ErrorCode::SUCCESS; if (volume_ > 0) { MEDIA_LOG_I("set volume " PUBLIC_LOG_F, volume); ret = audioSink_->SetVolume(volume); } auto ptr = callback_.lock(); if (ptr != nullptr) { if (ret != ErrorCode::SUCCESS) { MEDIA_LOG_E("SetVolume failed with error " PUBLIC_LOG_D32, static_cast(ret)); ptr->OnError(PlayerCallback::PlayerCallback::PLAYER_ERROR_UNKNOWN, CppExt::to_underlying(ret)); } } return ret; } bool HiPlayerImpl::IsSingleLooping() { return singleLoop_.load(); } int32_t HiPlayerImpl::SetLoop(bool loop) { MEDIA_LOG_I("SetLoop entered, loop: " PUBLIC_LOG_D32, loop); singleLoop_ = loop; return CppExt::to_underlying(ErrorCode::SUCCESS); } bool HiPlayerImpl::IsSingleLoop() { // note that we should also consider the live source, which cannot be singleLoop! return singleLoop_; } void HiPlayerImpl::SetPlayerCallback(const std::shared_ptr& cb) { callback_ = cb; } int32_t HiPlayerImpl::Reset() { MEDIA_LOG_I("Reset entered."); singleLoop_ = false; mediaStats_.Reset(); return CppExt::to_underlying(fsm_.SendEvent(Intent::RESET)); } int32_t HiPlayerImpl::Release() { PROFILE_BEGIN(); auto ret = Reset(); fsm_.Stop(); pipeline_.reset(); audioSource_.reset(); demuxer_.reset(); audioDecoderMap_.clear(); audioSink_.reset(); PROFILE_END("Release ret = " PUBLIC_LOG_D32, ret); return ret; } int32_t HiPlayerImpl::DeInit() { return Reset(); } int32_t HiPlayerImpl::GetPlayerState(int32_t& state) { state = static_cast(pipelineStates_.load()); return CppExt::to_underlying(ErrorCode::SUCCESS); } int32_t HiPlayerImpl::GetCurrentPosition(int64_t& currentPositionMs) { currentPositionMs = Plugin::HstTime2Ms(syncManager_->GetMediaTimeNow()); return CppExt::to_underlying(ErrorCode::SUCCESS); } int32_t HiPlayerImpl::GetDuration(int64_t& outDurationMs) { MEDIA_LOG_I("GetDuration entered."); outDurationMs = 0; if (pipelineStates_ == PlayerStates::PLAYER_IDLE || pipelineStates_ == PlayerStates::PLAYER_PREPARING || audioSource_ == nullptr) { return CppExt::to_underlying(ErrorCode::ERROR_INVALID_STATE); } if (duration_ < 0) { outDurationMs = -1; MEDIA_LOG_W("no valid duration"); return CppExt::to_underlying(ErrorCode::ERROR_UNKNOWN); } outDurationMs = Plugin::HstTime2Ms(duration_); MEDIA_LOG_I("GetDuration returned " PUBLIC_LOG_D32, outDurationMs); return CppExt::to_underlying(ErrorCode::SUCCESS); } int32_t HiPlayerImpl::GetVideoWidth(int32_t& videoWidth) { return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED); } int32_t HiPlayerImpl::GetVideoHeight(int32_t& videoHeight) { return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED); } void HiPlayerImpl::HandlePluginErrorEvent(const Event& event) { Plugin::PluginEvent pluginEvent = Plugin::AnyCast(event.param); MEDIA_LOG_I("Receive PLUGIN_ERROR, type: " PUBLIC_LOG_D32, CppExt::to_underlying(pluginEvent.type)); if (pluginEvent.type == Plugin::PluginEventType::CLIENT_ERROR && Plugin::Any::IsSameTypeWith(pluginEvent.param)) { auto netClientErrorCode = Plugin::AnyCast(pluginEvent.param); auto errorCode {-1}; if (netClientErrorCode == Plugin::NetworkClientErrorCode::ERROR_TIME_OUT) { errorCode = CppExt::to_underlying(Plugin::NetworkClientErrorCode::ERROR_TIME_OUT); } auto ptr = callback_.lock(); if (ptr != nullptr) { ptr->OnError(PlayerCallback::PlayerErrorType::PLAYER_ERROR_UNKNOWN, errorCode); } } } int32_t HiPlayerImpl::SetPlaybackSpeed(float speed) { return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED); } int32_t HiPlayerImpl::GetPlaybackSpeed(float& speed) { return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED); } int32_t HiPlayerImpl::SetAudioStreamType(int32_t type) { return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED); } void HiPlayerImpl::GetAudioStreamType(int32_t& type) { type = -1; } int32_t HiPlayerImpl::SetParameter(const Format& params) { return CppExt::to_underlying(ErrorCode::ERROR_UNIMPLEMENTED); } void HiPlayerImpl::OnStateChanged(StateId state) { MEDIA_LOG_I("OnStateChanged from " PUBLIC_LOG_D32 " to " PUBLIC_LOG_D32, curFsmState_.load(), state); UpdateStateNoLock(TransStateId2PlayerState(state)); { OSAL::ScopedLock lock(stateMutex_); curFsmState_ = state; cond_.NotifyOne(); } } ErrorCode HiPlayerImpl::OnCallback(const FilterCallbackType& type, Filter* filter, const Plugin::Any& parameter) { ErrorCode ret = ErrorCode::SUCCESS; switch (type) { case FilterCallbackType::PORT_ADDED: ret = NewAudioPortFound(filter, parameter); if (ret != ErrorCode::SUCCESS) { return ret; } #ifdef VIDEO_SUPPORT ret = NewVideoPortFound(filter, parameter); #endif break; case FilterCallbackType::PORT_REMOVE: ret = RemoveFilterChains(filter, parameter); break; default: break; } return ret; } ErrorCode HiPlayerImpl::GetTrackCnt(size_t& cnt) const { cnt = streamMeta_.size(); return ErrorCode::SUCCESS; } ErrorCode HiPlayerImpl::GetSourceMeta(shared_ptr& meta) const { meta = sourceMeta_.lock(); return meta ? ErrorCode::SUCCESS : ErrorCode::ERROR_AGAIN; } ErrorCode HiPlayerImpl::GetTrackMeta(size_t id, shared_ptr& meta) const { if (id > streamMeta_.size() || id < 0) { return ErrorCode::ERROR_INVALID_PARAMETER_VALUE; } meta = streamMeta_[id].lock(); if (meta == nullptr) { return ErrorCode::ERROR_AGAIN; } return ErrorCode::SUCCESS; } ErrorCode HiPlayerImpl::NewAudioPortFound(Filter* filter, const Plugin::Any& parameter) { if (!Plugin::Any::IsSameTypeWith(parameter)) { return ErrorCode::ERROR_INVALID_PARAMETER_TYPE; } ErrorCode rtv = ErrorCode::ERROR_INVALID_PARAMETER_VALUE; auto param = Plugin::AnyCast(parameter); if (filter == demuxer_.get() && param.type == PortType::OUT) { MEDIA_LOG_I("new port found on demuxer " PUBLIC_LOG_ZU, param.ports.size()); for (const auto& portDesc : param.ports) { if (portDesc.name.compare(0, 5, "audio") != 0) { // 5 is length of "audio" continue; } MEDIA_LOG_I("port name " PUBLIC_LOG_S, portDesc.name.c_str()); auto fromPort = filter->GetOutPort(portDesc.name); if (portDesc.isPcm) { pipeline_->AddFilters({audioSink_.get()}); FAIL_LOG(pipeline_->LinkPorts(fromPort, audioSink_->GetInPort(PORT_NAME_DEFAULT))); ActiveFilters({audioSink_.get()}); } else { auto newAudioDecoder = CreateAudioDecoder(portDesc.name); pipeline_->AddFilters({newAudioDecoder.get(), audioSink_.get()}); FAIL_LOG(pipeline_->LinkPorts(fromPort, newAudioDecoder->GetInPort(PORT_NAME_DEFAULT))); FAIL_LOG(pipeline_->LinkPorts(newAudioDecoder->GetOutPort(PORT_NAME_DEFAULT), audioSink_->GetInPort(PORT_NAME_DEFAULT))); ActiveFilters({newAudioDecoder.get(), audioSink_.get()}); } mediaStats_.Append(audioSink_->GetName()); rtv = ErrorCode::SUCCESS; break; } } return rtv; } #ifdef VIDEO_SUPPORT ErrorCode HiPlayerImpl::NewVideoPortFound(Filter* filter, const Plugin::Any& parameter) { if (!Plugin::Any::IsSameTypeWith(parameter)) { return ErrorCode::ERROR_INVALID_PARAMETER_TYPE; } auto param = Plugin::AnyCast(parameter); if (filter != demuxer_.get() || param.type != PortType::OUT) { return ErrorCode::ERROR_INVALID_PARAMETER_VALUE; } std::vector newFilters; for (const auto& portDesc : param.ports) { if (portDesc.name.compare(0, 5, "video") == 0) { // 5 is length of "video" MEDIA_LOG_I("port name " PUBLIC_LOG_S, portDesc.name.c_str()); videoDecoder = FilterFactory::Instance().CreateFilterWithType( "builtin.player.videodecoder", "videodecoder-" + portDesc.name); if (pipeline_->AddFilters({videoDecoder.get()}) == ErrorCode::SUCCESS) { // link demuxer and video decoder auto fromPort = filter->GetOutPort(portDesc.name); auto toPort = videoDecoder->GetInPort(PORT_NAME_DEFAULT); FAIL_LOG(pipeline_->LinkPorts(fromPort, toPort)); // link ports newFilters.emplace_back(videoDecoder.get()); // link video decoder and video sink if (pipeline_->AddFilters({videoSink.get()}) == ErrorCode::SUCCESS) { fromPort = videoDecoder->GetOutPort(PORT_NAME_DEFAULT); toPort = videoSink->GetInPort(PORT_NAME_DEFAULT); FAIL_LOG(pipeline_->LinkPorts(fromPort, toPort)); // link ports newFilters.push_back(videoSink.get()); mediaStats_.Append(videoSink->GetName()); } } break; } } if (!newFilters.empty()) { ActiveFilters(newFilters); } return ErrorCode::SUCCESS; } #endif ErrorCode HiPlayerImpl::RemoveFilterChains(Filter* filter, const Plugin::Any& parameter) { ErrorCode ret = ErrorCode::SUCCESS; auto param = Plugin::AnyCast(parameter); if (filter != demuxer_.get() || param.type != PortType::OUT) { return ret; } for (const auto& portDesc : param.ports) { MEDIA_LOG_I("remove filter chain for port: " PUBLIC_LOG_S, portDesc.name.c_str()); auto peerPort = filter->GetOutPort(portDesc.name)->GetPeerPort(); if (peerPort) { auto nextFilter = const_cast(reinterpret_cast(peerPort->GetOwnerFilter())); if (nextFilter) { pipeline_->RemoveFilterChain(nextFilter); } } } return ret; } void HiPlayerImpl::ActiveFilters(const std::vector& filters) { for (auto it = filters.rbegin(); it != filters.rend(); ++it) { (*it)->Prepare(); } } PlayerStates HiPlayerImpl::TransStateId2PlayerState(StateId state) { PlayerStates playerState = PLAYER_STATE_ERROR; switch (state) { case StateId::IDLE: playerState = PLAYER_IDLE; break; case StateId::INIT: playerState = PLAYER_INITIALIZED; break; case StateId::PREPARING: playerState = PLAYER_PREPARING; break; case StateId::READY: playerState = PLAYER_PREPARED; break; case StateId::PAUSE: playerState = PLAYER_PAUSED; break; case StateId::PLAYING: playerState = PLAYER_STARTED; break; case StateId::STOPPED: playerState = PLAYER_STOPPED; break; case StateId::EOS: playerState = PLAYER_PLAYBACK_COMPLETE; break; default: break; } return playerState; } Plugin::SeekMode HiPlayerImpl::Transform2SeekMode(PlayerSeekMode mode) { switch (mode) { case PlayerSeekMode::PLAYER_SEEK_NEXT_SYNC: return Plugin::SeekMode::SEEK_NEXT_SYNC; case PlayerSeekMode::PLAYER_SEEK_PREVIOUS_SYNC: return Plugin::SeekMode::SEEK_PREVIOUS_SYNC; case PlayerSeekMode::PLAYER_SEEK_CLOSEST_SYNC: return Plugin::SeekMode::SEEK_CLOSEST_SYNC; case PlayerSeekMode::PLAYER_SEEK_CLOSEST: return Plugin::SeekMode::SEEK_CLOSEST; default: return Plugin::SeekMode::SEEK_CLOSEST; } } const std::string& HiPlayerImpl::StringnessPlayerState(PlayerStates state) { using StateString = std::pair; const static std::array maps = { // array size std::make_pair(PlayerStates::PLAYER_STATE_ERROR, "state error"), std::make_pair(PlayerStates::PLAYER_IDLE, "idle"), std::make_pair(PlayerStates::PLAYER_INITIALIZED, "init"), std::make_pair(PlayerStates::PLAYER_PREPARING, "preparing"), std::make_pair(PlayerStates::PLAYER_PREPARED, "prepared"), std::make_pair(PlayerStates::PLAYER_STARTED, "started"), std::make_pair(PlayerStates::PLAYER_PAUSED, "paused"), std::make_pair(PlayerStates::PLAYER_STOPPED, "stopped"), std::make_pair(PlayerStates::PLAYER_PLAYBACK_COMPLETE, "completed"), }; const static std::string UNKNOWN = "unknown"; auto ite = std::find_if(maps.begin(), maps.end(), [&] (const StateString& item) -> bool { return item.first == state; }); if (ite == maps.end()) { return UNKNOWN; } return ite->second; } } // namespace Media } // namespace OHOS