/* * Copyright (C) 2005-2018 Team Kodi * This file is part of Kodi - https://kodi.tv * * SPDX-License-Identifier: GPL-2.0-or-later * See LICENSES/README.md for more information. */ #include "ProcessInfo.h" #include "ServiceBroker.h" #include "cores/DataCacheCore.h" #include "settings/AdvancedSettings.h" #include "settings/SettingsComponent.h" #include CCriticalSection createSection; std::map CProcessInfo::m_processControls; void CProcessInfo::RegisterProcessControl(const std::string& id, CreateProcessControl createFunc) { std::unique_lock lock(createSection); m_processControls.clear(); m_processControls[id] = createFunc; } CProcessInfo* CProcessInfo::CreateInstance() { std::unique_lock lock(createSection); CProcessInfo *ret = nullptr; for (auto &info : m_processControls) { ret = info.second(); if (ret) return ret; } return new CProcessInfo(); } CProcessInfo::CProcessInfo() { m_videoSettingsLocked.reset(new CVideoSettingsLocked(m_videoSettings, m_settingsSection)); } void CProcessInfo::SetDataCache(CDataCacheCore *cache) { m_dataCache = cache;; ResetVideoCodecInfo(); m_renderGuiLayer = false; m_renderVideoLayer = false; m_dataCache->SetGuiRender(m_renderGuiLayer); m_dataCache->SetVideoRender(m_renderVideoLayer); } //****************************************************************************** // video codec //****************************************************************************** void CProcessInfo::ResetVideoCodecInfo() { std::unique_lock lock(m_videoCodecSection); m_videoIsHWDecoder = false; m_videoDecoderName = "unknown"; m_videoDeintMethod = "unknown"; m_videoPixelFormat = "unknown"; m_videoStereoMode.clear(); m_videoWidth = 0; m_videoHeight = 0; m_videoFPS = 0.0; m_videoDAR = 0.0; m_videoIsInterlaced = false; m_deintMethods.clear(); m_deintMethods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_NONE); m_deintMethodDefault = EINTERLACEMETHOD::VS_INTERLACEMETHOD_NONE; m_stateSeeking = false; if (m_dataCache) { m_dataCache->SetVideoDecoderName(m_videoDecoderName, m_videoIsHWDecoder); m_dataCache->SetVideoDeintMethod(m_videoDeintMethod); m_dataCache->SetVideoPixelFormat(m_videoPixelFormat); m_dataCache->SetVideoDimensions(m_videoWidth, m_videoHeight); m_dataCache->SetVideoFps(m_videoFPS); m_dataCache->SetVideoDAR(m_videoDAR); m_dataCache->SetStateSeeking(m_stateSeeking); m_dataCache->SetVideoStereoMode(m_videoStereoMode); } } void CProcessInfo::SetVideoDecoderName(const std::string &name, bool isHw) { std::unique_lock lock(m_videoCodecSection); m_videoIsHWDecoder = isHw; m_videoDecoderName = name; if (m_dataCache) m_dataCache->SetVideoDecoderName(m_videoDecoderName, m_videoIsHWDecoder); } std::string CProcessInfo::GetVideoDecoderName() { std::unique_lock lock(m_videoCodecSection); return m_videoDecoderName; } bool CProcessInfo::IsVideoHwDecoder() { std::unique_lock lock(m_videoCodecSection); return m_videoIsHWDecoder; } void CProcessInfo::SetVideoDeintMethod(const std::string &method) { std::unique_lock lock(m_videoCodecSection); m_videoDeintMethod = method; if (m_dataCache) m_dataCache->SetVideoDeintMethod(m_videoDeintMethod); } std::string CProcessInfo::GetVideoDeintMethod() { std::unique_lock lock(m_videoCodecSection); return m_videoDeintMethod; } void CProcessInfo::SetVideoPixelFormat(const std::string &pixFormat) { std::unique_lock lock(m_videoCodecSection); m_videoPixelFormat = pixFormat; if (m_dataCache) m_dataCache->SetVideoPixelFormat(m_videoPixelFormat); } std::string CProcessInfo::GetVideoPixelFormat() { std::unique_lock lock(m_videoCodecSection); return m_videoPixelFormat; } void CProcessInfo::SetVideoStereoMode(const std::string &mode) { std::unique_lock lock(m_videoCodecSection); m_videoStereoMode = mode; if (m_dataCache) m_dataCache->SetVideoStereoMode(m_videoStereoMode); } std::string CProcessInfo::GetVideoStereoMode() { std::unique_lock lock(m_videoCodecSection); return m_videoStereoMode; } void CProcessInfo::SetVideoDimensions(int width, int height) { std::unique_lock lock(m_videoCodecSection); m_videoWidth = width; m_videoHeight = height; if (m_dataCache) m_dataCache->SetVideoDimensions(m_videoWidth, m_videoHeight); } void CProcessInfo::GetVideoDimensions(int &width, int &height) { std::unique_lock lock(m_videoCodecSection); width = m_videoWidth; height = m_videoHeight; } void CProcessInfo::SetVideoFps(float fps) { std::unique_lock lock(m_videoCodecSection); m_videoFPS = fps; if (m_dataCache) m_dataCache->SetVideoFps(m_videoFPS); } float CProcessInfo::GetVideoFps() { std::unique_lock lock(m_videoCodecSection); return m_videoFPS; } void CProcessInfo::SetVideoDAR(float dar) { std::unique_lock lock(m_videoCodecSection); m_videoDAR = dar; if (m_dataCache) m_dataCache->SetVideoDAR(m_videoDAR); } float CProcessInfo::GetVideoDAR() { std::unique_lock lock(m_videoCodecSection); return m_videoDAR; } void CProcessInfo::SetVideoInterlaced(bool interlaced) { std::unique_lock lock(m_videoCodecSection); m_videoIsInterlaced = interlaced; if (m_dataCache) m_dataCache->SetVideoInterlaced(interlaced); } bool CProcessInfo::GetVideoInterlaced() { std::unique_lock lock(m_videoCodecSection); return m_videoIsInterlaced; } EINTERLACEMETHOD CProcessInfo::GetFallbackDeintMethod() { return VS_INTERLACEMETHOD_DEINTERLACE; } void CProcessInfo::SetSwDeinterlacingMethods() { std::list methods; methods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_NONE); methods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_DEINTERLACE); methods.push_back(EINTERLACEMETHOD::VS_INTERLACEMETHOD_DEINTERLACE_HALF); UpdateDeinterlacingMethods(methods); SetDeinterlacingMethodDefault(EINTERLACEMETHOD::VS_INTERLACEMETHOD_DEINTERLACE); } void CProcessInfo::UpdateDeinterlacingMethods(std::list &methods) { std::unique_lock lock(m_videoCodecSection); m_deintMethods = methods; for (auto &deint : m_renderInfo.m_deintMethods) { if (!Supports(deint)) m_deintMethods.push_back(deint); } if (!Supports(EINTERLACEMETHOD::VS_INTERLACEMETHOD_NONE)) m_deintMethods.push_front(EINTERLACEMETHOD::VS_INTERLACEMETHOD_NONE); } bool CProcessInfo::Supports(EINTERLACEMETHOD method) const { std::unique_lock lock(m_videoCodecSection); auto it = std::find(m_deintMethods.begin(), m_deintMethods.end(), method); if (it != m_deintMethods.end()) return true; return false; } void CProcessInfo::SetDeinterlacingMethodDefault(EINTERLACEMETHOD method) { std::unique_lock lock(m_videoCodecSection); m_deintMethodDefault = method; } EINTERLACEMETHOD CProcessInfo::GetDeinterlacingMethodDefault() const { std::unique_lock lock(m_videoCodecSection); return m_deintMethodDefault; } CVideoBufferManager& CProcessInfo::GetVideoBufferManager() { return m_videoBufferManager; } std::vector CProcessInfo::GetPixFormats() { std::unique_lock lock(m_videoCodecSection); if (m_pixFormats.empty()) { return GetRenderFormats(); } return m_pixFormats; } void CProcessInfo::SetPixFormats(std::vector &formats) { std::unique_lock lock(m_videoCodecSection); m_pixFormats = formats; } //****************************************************************************** // player audio info //****************************************************************************** void CProcessInfo::ResetAudioCodecInfo() { std::unique_lock lock(m_audioCodecSection); m_audioDecoderName = "unknown"; m_audioChannels = "unknown"; m_audioSampleRate = 0;; m_audioBitsPerSample = 0; if (m_dataCache) { m_dataCache->SetAudioDecoderName(m_audioDecoderName); m_dataCache->SetAudioChannels(m_audioChannels); m_dataCache->SetAudioSampleRate(m_audioSampleRate); m_dataCache->SetAudioBitsPerSample(m_audioBitsPerSample); } } void CProcessInfo::SetAudioDecoderName(const std::string &name) { std::unique_lock lock(m_audioCodecSection); m_audioDecoderName = name; if (m_dataCache) m_dataCache->SetAudioDecoderName(m_audioDecoderName); } std::string CProcessInfo::GetAudioDecoderName() { std::unique_lock lock(m_audioCodecSection); return m_audioDecoderName; } void CProcessInfo::SetAudioChannels(const std::string &channels) { std::unique_lock lock(m_audioCodecSection); m_audioChannels = channels; if (m_dataCache) m_dataCache->SetAudioChannels(m_audioChannels); } std::string CProcessInfo::GetAudioChannels() { std::unique_lock lock(m_audioCodecSection); return m_audioChannels; } void CProcessInfo::SetAudioSampleRate(int sampleRate) { std::unique_lock lock(m_audioCodecSection); m_audioSampleRate = sampleRate; if (m_dataCache) m_dataCache->SetAudioSampleRate(m_audioSampleRate); } int CProcessInfo::GetAudioSampleRate() { std::unique_lock lock(m_audioCodecSection); return m_audioSampleRate; } void CProcessInfo::SetAudioBitsPerSample(int bitsPerSample) { std::unique_lock lock(m_audioCodecSection); m_audioBitsPerSample = bitsPerSample; if (m_dataCache) m_dataCache->SetAudioBitsPerSample(m_audioBitsPerSample); } int CProcessInfo::GetAudioBitsPerSample() { std::unique_lock lock(m_audioCodecSection); return m_audioBitsPerSample; } bool CProcessInfo::AllowDTSHDDecode() { return true; } void CProcessInfo::SetRenderClockSync(bool enabled) { std::unique_lock lock(m_renderSection); m_isClockSync = enabled; if (m_dataCache) m_dataCache->SetRenderClockSync(enabled); } bool CProcessInfo::IsRenderClockSync() { std::unique_lock lock(m_renderSection); return m_isClockSync; } void CProcessInfo::UpdateRenderInfo(CRenderInfo &info) { std::unique_lock lock(m_renderSection); m_renderInfo = info; for (auto &deint : m_renderInfo.m_deintMethods) { if (!Supports(deint)) m_deintMethods.push_back(deint); } } void CProcessInfo::UpdateRenderBuffers(int queued, int discard, int free) { std::unique_lock lock(m_renderSection); m_renderBufQueued = queued; m_renderBufDiscard = discard; m_renderBufFree = free; } void CProcessInfo::GetRenderBuffers(int &queued, int &discard, int &free) { std::unique_lock lock(m_renderSection); queued = m_renderBufQueued; discard = m_renderBufDiscard; free = m_renderBufFree; } std::vector CProcessInfo::GetRenderFormats() { std::vector formats; formats.push_back(AV_PIX_FMT_YUV420P); return formats; } //****************************************************************************** // player states //****************************************************************************** void CProcessInfo::SeekFinished(int64_t offset) { std::unique_lock lock(m_stateSection); if (m_dataCache) m_dataCache->SeekFinished(offset); } void CProcessInfo::SetStateSeeking(bool active) { std::unique_lock lock(m_renderSection); m_stateSeeking = active; if (m_dataCache) m_dataCache->SetStateSeeking(active); } bool CProcessInfo::IsSeeking() { std::unique_lock lock(m_stateSection); return m_stateSeeking; } void CProcessInfo::SetStateRealtime(bool state) { std::unique_lock lock(m_renderSection); m_realTimeStream = state; } bool CProcessInfo::IsRealtimeStream() { std::unique_lock lock(m_stateSection); return m_realTimeStream; } void CProcessInfo::SetSpeed(float speed) { std::unique_lock lock(m_stateSection); m_speed = speed; m_newSpeed = speed; if (m_dataCache) m_dataCache->SetSpeed(m_newTempo, speed); } void CProcessInfo::SetNewSpeed(float speed) { std::unique_lock lock(m_stateSection); m_newSpeed = speed; if (m_dataCache) m_dataCache->SetSpeed(m_tempo, speed); } float CProcessInfo::GetNewSpeed() { std::unique_lock lock(m_stateSection); return m_newSpeed; } void CProcessInfo::SetFrameAdvance(bool fa) { std::unique_lock lock(m_stateSection); m_frameAdvance = fa; if (m_dataCache) m_dataCache->SetFrameAdvance(fa); } bool CProcessInfo::IsFrameAdvance() { std::unique_lock lock(m_stateSection); return m_frameAdvance; } void CProcessInfo::SetTempo(float tempo) { std::unique_lock lock(m_stateSection); m_tempo = tempo; m_newTempo = tempo; if (m_dataCache) m_dataCache->SetSpeed(tempo, m_newSpeed); } void CProcessInfo::SetNewTempo(float tempo) { std::unique_lock lock(m_stateSection); m_newTempo = tempo; if (m_dataCache) m_dataCache->SetSpeed(tempo, m_speed); } float CProcessInfo::GetNewTempo() { std::unique_lock lock(m_stateSection); return m_newTempo; } float CProcessInfo::MinTempoPlatform() { return 0.75f; } float CProcessInfo::MaxTempoPlatform() { return 1.55f; } bool CProcessInfo::IsTempoAllowed(float tempo) { if (tempo > MinTempoPlatform() && (tempo < MaxTempoPlatform() || tempo < CServiceBroker::GetSettingsComponent()->GetAdvancedSettings()->m_maxTempo)) return true; return false; } unsigned int CProcessInfo::GetMaxPassthroughOffSyncDuration() const { return CServiceBroker::GetSettingsComponent() ->GetAdvancedSettings() ->m_maxPassthroughOffSyncDuration; } void CProcessInfo::SetLevelVQ(int level) { m_levelVQ = level; } int CProcessInfo::GetLevelVQ() { return m_levelVQ; } void CProcessInfo::SetGuiRender(bool gui) { std::unique_lock lock(m_stateSection); bool change = (m_renderGuiLayer != gui); m_renderGuiLayer = gui; if (change) { if (m_dataCache) m_dataCache->SetGuiRender(gui); } } bool CProcessInfo::GetGuiRender() { std::unique_lock lock(m_stateSection); return m_renderGuiLayer; } void CProcessInfo::SetVideoRender(bool video) { std::unique_lock lock(m_stateSection); bool change = (m_renderVideoLayer != video); m_renderVideoLayer = video; if (change) { if (m_dataCache) m_dataCache->SetVideoRender(video); } } bool CProcessInfo::GetVideoRender() { std::unique_lock lock(m_stateSection); return m_renderVideoLayer; } void CProcessInfo::SetPlayTimes(time_t start, int64_t current, int64_t min, int64_t max) { std::unique_lock lock(m_stateSection); m_startTime = start; m_time = current; m_timeMin = min; m_timeMax = max; if (m_dataCache) { m_dataCache->SetPlayTimes(start, current, min, max); } } int64_t CProcessInfo::GetMaxTime() { std::unique_lock lock(m_stateSection); return m_timeMax; } //****************************************************************************** // settings //****************************************************************************** CVideoSettings CProcessInfo::GetVideoSettings() { std::unique_lock lock(m_settingsSection); return m_videoSettings; } CVideoSettingsLocked& CProcessInfo::GetVideoSettingsLocked() { std::unique_lock lock(m_settingsSection); return *m_videoSettingsLocked; } void CProcessInfo::SetVideoSettings(CVideoSettings &settings) { std::unique_lock lock(m_settingsSection); m_videoSettings = settings; }