From 28de0da9afeb6bcbc2c8a3cad31c79225b07ec7d Mon Sep 17 00:00:00 2001 From: gimli Date: Wed, 3 Apr 2013 06:29:33 +0200 Subject: [rbp/omxplayer] sync up with dvdplayer master changes --- xbmc/cores/omxplayer/OMXPlayer.cpp | 295 +++++++++++++++++++++----------- xbmc/cores/omxplayer/OMXPlayer.h | 22 ++- xbmc/cores/omxplayer/OMXPlayerAudio.cpp | 12 ++ xbmc/cores/omxplayer/OMXPlayerVideo.cpp | 13 ++ xbmc/cores/omxplayer/OMXPlayerVideo.h | 2 + 5 files changed, 240 insertions(+), 104 deletions(-) diff --git a/xbmc/cores/omxplayer/OMXPlayer.cpp b/xbmc/cores/omxplayer/OMXPlayer.cpp index 175938a736..78b51f2ba1 100644 --- a/xbmc/cores/omxplayer/OMXPlayer.cpp +++ b/xbmc/cores/omxplayer/OMXPlayer.cpp @@ -38,6 +38,7 @@ #include "filesystem/SpecialProtocol.h" #include "guilib/GUIWindowManager.h" #include "settings/AdvancedSettings.h" +#include "settings/MediaSettings.h" #include "settings/GUISettings.h" #include "settings/Settings.h" #include "threads/SingleLock.h" @@ -424,9 +425,11 @@ COMXPlayer::COMXPlayer(IPlayerCallback &callback) m_UpdateApplication = 0; m_caching = CACHESTATE_DONE; m_playSpeed = DVD_PLAYSPEED_NORMAL; + m_HasVideo = false; + m_HasAudio = false; - m_State.Clear(); m_dvd.Clear(); + m_State.Clear(); m_EdlAutoSkipMarkers.Clear(); memset(&m_SpeedState, 0, sizeof(m_SpeedState)); @@ -483,7 +486,6 @@ bool COMXPlayer::OpenFile(const CFileItem &file, const CPlayerOptions &options) g_renderManager.PreInit(); Create(); - if(!m_ready.WaitMSec(100)) { CGUIDialogBusy* dialog = (CGUIDialogBusy*)g_windowManager.GetWindow(WINDOW_DIALOG_BUSY); @@ -538,6 +540,9 @@ bool COMXPlayer::CloseFile() m_Edl.Clear(); m_EdlAutoSkipMarkers.Clear(); + m_HasVideo = false; + m_HasAudio = false; + g_renderManager.UnInit(); return true; } @@ -571,7 +576,7 @@ bool COMXPlayer::OpenInputStream() { m_filename = g_mediaManager.TranslateDevicePath(""); } -retry: + // before creating the input stream, if this is an HLS playlist then get the // most appropriate bitrate based on our network settings if (filename.Left(7) == "http://" && filename.Right(5) == ".m3u8") @@ -603,7 +608,6 @@ retry: || m_pInputStream->IsStreamType(DVDSTREAM_TYPE_BLURAY) ) ) { CLog::Log(LOGINFO, "COMXPlayer::OpenInputStream - DVD/BD not supported - Will try..."); - // return false; } // find any available external subtitles for non dvd files @@ -637,7 +641,7 @@ retry: AddSubtitleFile(filenames[i]); } } - } // end loop over all subtitle files + } // end loop over all subtitle files CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleCached = true; } @@ -645,7 +649,6 @@ retry: SetAVDelay(CMediaSettings::Get().GetCurrentVideoSettings().m_AudioDelay); SetSubTitleDelay(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleDelay); m_av_clock.Reset(); - //m_av_clock.OMXReset(); m_dvd.Clear(); m_iChannelEntryTimeOut = 0; @@ -704,8 +707,9 @@ bool COMXPlayer::OpenDemuxStream() void COMXPlayer::OpenDefaultStreams(bool reset) { - // bypass for DVDs. The DVD Navigator has already dictated which streams to open. - if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) + // if input stream dictate, we will open later + if(m_dvd.iSelectedAudioStream >= 0 + || m_dvd.iSelectedSPUStream >= 0) return; OMXSelectionStreams streams; @@ -756,20 +760,15 @@ void COMXPlayer::OpenDefaultStreams(bool reset) CloseSubtitleStream(true); // open teletext stream - /* streams = m_SelectionStreams.Get(STREAM_TELETEXT); valid = false; - for(SelectionStreams::iterator it = streams.begin(); it != streams.end() && !valid; ++it) + for(OMXSelectionStreams::iterator it = streams.begin(); it != streams.end() && !valid; ++it) { if(OpenTeletextStream(it->id, it->source)) valid = true; } if(!valid) CloseTeletextStream(true); - */ - - //m_av_clock.OMXStop(); - //m_av_clock.OMXReset(); } bool COMXPlayer::ReadPacket(DemuxPacket*& packet, CDemuxStream*& stream) @@ -891,6 +890,9 @@ bool COMXPlayer::IsBetterStream(COMXCurrentStream& current, CDemuxStream* stream if(m_PlayerOptions.video_only && current.type != STREAM_VIDEO) return false; + if(stream->disabled) + return false; + if (m_pInputStream && ( m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD) || m_pInputStream->IsStreamType(DVDSTREAM_TYPE_BLURAY) ) ) { @@ -920,9 +922,6 @@ bool COMXPlayer::IsBetterStream(COMXCurrentStream& current, CDemuxStream* stream && stream->iId == current.id) return false; - if(stream->disabled) - return false; - if(stream->type != current.type) return false; @@ -940,21 +939,21 @@ void COMXPlayer::Process() bool bOmxWaitVideo = false; bool bOmxWaitAudio = false; - if(!OpenInputStream()) + if (!OpenInputStream()) { m_bAbortRequest = true; return; } - if(m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) + if (CDVDInputStream::IMenus* ptr = dynamic_cast(m_pInputStream)) { - CLog::Log(LOGNOTICE, "OMXPlayer: playing a dvd with menu's"); + CLog::Log(LOGNOTICE, "OMXPlayer: playing a file with menu's"); m_PlayerOptions.starttime = 0; if(m_PlayerOptions.state.size() > 0) - ((CDVDInputStreamNavigator*)m_pInputStream)->SetNavigatorState(m_PlayerOptions.state); - else - ((CDVDInputStreamNavigator*)m_pInputStream)->EnableSubtitleStream(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleOn); + ptr->SetState(m_PlayerOptions.state); + else if(CDVDInputStreamNavigator* nav = dynamic_cast(m_pInputStream)) + nav->EnableSubtitleStream(CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleOn); CMediaSettings::Get().GetCurrentVideoSettings().m_SubtitleCached = true; } @@ -1098,6 +1097,10 @@ void COMXPlayer::Process() OpenDefaultStreams(); + // never allow first frames after open to be skipped + if( m_player_video.IsInited() ) + m_player_video.SendMessage(new CDVDMsg(CDVDMsg::VIDEO_NOSKIP)); + if (CachePVRStream()) SetCaching(CACHESTATE_PVR); @@ -1154,10 +1157,8 @@ void COMXPlayer::Process() continue; // check for a still frame state - if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) + if (CDVDInputStream::IMenus* pStream = dynamic_cast(m_pInputStream)) { - CDVDInputStreamNavigator* pStream = static_cast(m_pInputStream); - // stills will be skipped if(m_dvd.state == DVDSTATE_STILL) { @@ -1328,7 +1329,7 @@ void COMXPlayer::ProcessPacket(CDemuxStream* pStream, DemuxPacket* pPacket) void COMXPlayer::ProcessAudioData(CDemuxStream* pStream, DemuxPacket* pPacket) { - if (m_CurrentAudio.stream != (void*)pStream + if (m_CurrentAudio.stream != (void*)pStream || m_CurrentAudio.changes != pStream->changes) { /* check so that dmuxer hints or extra data hasn't changed */ @@ -1594,6 +1595,7 @@ void COMXPlayer::HandlePlaySpeed() if(m_caching != caching) SetCaching(caching); + if(GetPlaySpeed() != DVD_PLAYSPEED_NORMAL && GetPlaySpeed() != DVD_PLAYSPEED_PAUSE) { if (IsInMenu()) @@ -1769,6 +1771,24 @@ void COMXPlayer::UpdateTimestamps(COMXCurrentStream& current, DemuxPacket* pPack current.dur = 0.1 * (current.dur * 9 + (dts - current.dts)); current.dts = dts; + + /* send a playback state structure periodically */ + if(current.dts_state == DVD_NOPTS_VALUE + || abs(current.dts - current.dts_state) > DVD_MSEC_TO_TIME(200)) + { + current.dts_state = current.dts; + if (current.inited) + { + // make sure we send no outdated state to a/v players + UpdatePlayState(0); + SendPlayerMessage(new CDVDMsgType(CDVDMsg::PLAYER_DISPLAYTIME, m_StateInput), current.player); + } + else + { + CSingleLock lock(m_StateSection); + m_State = m_StateInput; + } + } } void COMXPlayer::UpdateLimits(double& minimum, double& maximum, double dts) @@ -2079,6 +2099,11 @@ void COMXPlayer::HandleMessages() double start = DVD_NOPTS_VALUE; int time = msg.GetRestore() ? (int)m_Edl.RestoreCutTime(msg.GetTime()) : msg.GetTime(); + + // if input streams doesn't support seektime we must convert back to clock + if(dynamic_cast(m_pInputStream) == NULL) + time -= DVD_TIME_TO_MSEC(m_State.time_offset - m_offset_pts); + CLog::Log(LOGDEBUG, "demuxer seek to: %d", time); if (m_pDemuxer && m_pDemuxer->SeekTime(time, msg.GetBackward(), &start)) { @@ -2088,6 +2113,9 @@ void COMXPlayer::HandleMessages() if(!m_pSubtitleDemuxer->SeekTime(time, msg.GetBackward())) CLog::Log(LOGDEBUG, "failed to seek subtitle demuxer: %d, success", time); } + // dts after successful seek + m_StateInput.dts = start; + FlushBuffers(!msg.GetFlush(), start, msg.GetAccurate()); } else @@ -2145,7 +2173,6 @@ void COMXPlayer::HandleMessages() { m_dvd.iSelectedAudioStream = -1; CloseAudioStream(false); - // TODO : check //CloseVideoStream(false); m_messenger.Put(new CDVDMsgPlayerSeek(GetTime(), true, true, true, true, true)); } } @@ -2196,13 +2223,14 @@ void COMXPlayer::HandleMessages() CDVDMsgPlayerSetState* pMsgPlayerSetState = (CDVDMsgPlayerSetState*)pMsg; - if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) + if (CDVDInputStream::IMenus* ptr = dynamic_cast(m_pInputStream)) { - std::string s = pMsgPlayerSetState->GetState(); - ((CDVDInputStreamNavigator*)m_pInputStream)->SetNavigatorState(s); - m_dvd.state = DVDSTATE_NORMAL; - m_dvd.iDVDStillStartTime = 0; - m_dvd.iDVDStillTime = 0; + if(ptr->SetState(pMsgPlayerSetState->GetState())) + { + m_dvd.state = DVDSTATE_NORMAL; + m_dvd.iDVDStillStartTime = 0; + m_dvd.iDVDStillTime = 0; + } } g_infoManager.SetDisplayAfterSeek(); @@ -2340,6 +2368,24 @@ void COMXPlayer::HandleMessages() m_CurrentVideo.started = true; CLog::Log(LOGDEBUG, "COMXPlayer::HandleMessages - player started %d", player); } + else if (pMsg->IsType(CDVDMsg::PLAYER_DISPLAYTIME)) + { + COMXPlayer::SPlayerState& state = ((CDVDMsgType*)pMsg)->m_value; + + CSingleLock lock(m_StateSection); + /* prioritize data from video player, but only accept data * + * after it has been started to avoid race conditions after seeks */ + if(m_CurrentVideo.started) + { + if(state.player == DVDPLAYER_VIDEO) + m_State = state; + } + else if(m_CurrentAudio.started) + { + if(state.player == DVDPLAYER_AUDIO) + m_State = state; + } + } } catch (...) { @@ -2348,6 +2394,7 @@ void COMXPlayer::HandleMessages() pMsg->Release(); } + } void COMXPlayer::SetCaching(ECacheState state) @@ -2440,14 +2487,12 @@ bool COMXPlayer::IsPaused() const bool COMXPlayer::HasVideo() const { - if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) return true; - - return m_SelectionStreams.Count(STREAM_VIDEO) > 0 ? true : false; + return m_HasVideo; } bool COMXPlayer::HasAudio() const { - return m_SelectionStreams.Count(STREAM_AUDIO) > 0 ? true : false; + return m_HasAudio; } bool COMXPlayer::IsPassthrough() const @@ -2589,17 +2634,17 @@ bool COMXPlayer::SeekScene(bool bPlus) void COMXPlayer::GetAudioInfo(CStdString &strAudioInfo) { { CSingleLock lock(m_StateSection); - strAudioInfo.Format("D(%s)", m_State.demux_audio.c_str()); + strAudioInfo.Format("D(%s)", m_StateInput.demux_audio.c_str()); } - strAudioInfo.AppendFormat(" P(%s)", m_player_audio.GetPlayerInfo().c_str()); + strAudioInfo.AppendFormat("\nP(%s)", m_player_audio.GetPlayerInfo().c_str()); } void COMXPlayer::GetVideoInfo(CStdString &strVideoInfo) { { CSingleLock lock(m_StateSection); - strVideoInfo.Format("D(%s)", m_State.demux_video.c_str()); + strVideoInfo.Format("D(%s)", m_StateInput.demux_video.c_str()); } - strVideoInfo.AppendFormat(" P(%s)", m_player_video.GetPlayerInfo().c_str()); + strVideoInfo.AppendFormat("\nP(%s)", m_player_video.GetPlayerInfo().c_str()); } void COMXPlayer::GetGeneralInfo(CStdString& strGeneralInfo) @@ -2620,7 +2665,7 @@ void COMXPlayer::GetGeneralInfo(CStdString& strGeneralInfo) CStdString strBuf; CSingleLock lock(m_StateSection); - if(m_State.cache_bytes >= 0) + if(m_StateInput.cache_bytes >= 0) { strBuf.AppendFormat(" cache:%s %2.0f%%" , StringUtils::SizeToString(m_State.cache_bytes).c_str() @@ -2666,7 +2711,7 @@ float COMXPlayer::GetPercentage() float COMXPlayer::GetCachePercentage() { CSingleLock lock(m_StateSection); - return m_State.cache_offset * 100; // NOTE: Percentage returned is relative + return m_StateInput.cache_offset * 100; // NOTE: Percentage returned is relative } void COMXPlayer::SetAVDelay(float fValue) @@ -2689,6 +2734,7 @@ float COMXPlayer::GetSubTitleDelay() return -m_player_video.GetSubtitleDelay() / DVD_TIME_BASE; } +// priority: 1: libdvdnav, 2: external subtitles, 3: muxed subtitles int COMXPlayer::GetSubtitleCount() { OMXStreamLock lock(this); @@ -2752,7 +2798,7 @@ int COMXPlayer::GetAudioStream() { return m_SelectionStreams.IndexOf(STREAM_AUDIO, *this); } - + void COMXPlayer::SetAudioStream(int iStream) { m_messenger.Put(new CDVDMsgPlayerSetAudioStream(iStream)); @@ -2788,12 +2834,13 @@ int64_t COMXPlayer::GetTime() { CSingleLock lock(m_StateSection); double offset = 0; + const double limit = DVD_MSEC_TO_TIME(200); if(m_State.timestamp > 0) { offset = m_av_clock.GetAbsoluteClock() - m_State.timestamp; offset *= m_playSpeed / DVD_PLAYSPEED_NORMAL; - if(offset > 1000) offset = 1000; - if(offset < -1000) offset = -1000; + if(offset > limit) offset = limit; + if(offset < -limit) offset = -limit; } return llrint(m_State.time + DVD_TIME_TO_MSEC(offset)); } @@ -2874,6 +2921,7 @@ bool COMXPlayer::OpenAudioStream(int iStream, int source, bool reset) m_CurrentAudio.hint = hint; m_CurrentAudio.stream = (void*)pStream; m_CurrentAudio.started = false; + m_HasAudio = true; /* we are potentially going to be waiting on this */ m_player_audio.SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1); @@ -2928,7 +2976,7 @@ bool COMXPlayer::OpenVideoStream(int iStream, int source, bool reset) if(m_CurrentVideo.id < 0 || m_CurrentVideo.hint != hint) { - if(!m_player_video.OpenStream(hint)) + if (!m_player_video.OpenStream(hint)) { /* mark stream as disabled, to disallaw further attempts */ CLog::Log(LOGWARNING, "%s - Unsupported stream %d. Stream disabled.", __FUNCTION__, iStream); @@ -2955,6 +3003,7 @@ bool COMXPlayer::OpenVideoStream(int iStream, int source, bool reset) m_CurrentVideo.hint = hint; m_CurrentVideo.stream = (void*)pStream; m_CurrentVideo.started = false; + m_HasVideo = true; /* we are potentially going to be waiting on this */ m_player_video.SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1); @@ -3241,6 +3290,11 @@ void COMXPlayer::FlushBuffers(bool queued, double pts, bool accurate) if(pts != DVD_NOPTS_VALUE) m_av_clock.Discontinuity(pts); UpdatePlayState(0); + + // update state, buffers are flushed and it may take some time until + // we get an update from players + CSingleLock lock(m_StateSection); + m_State = m_StateInput; } } @@ -3259,6 +3313,29 @@ int COMXPlayer::OnDVDNavResult(void* pData, int iMessage) m_dvd.iSelectedSPUStream = *(int*)pData; else if(iMessage == 4) m_player_video.EnableSubtitle(*(int*)pData ? true: false); + else if(iMessage == 5) + { + if (m_dvd.state != DVDSTATE_STILL) + { + // else notify the player we have received a still frame + + m_dvd.iDVDStillTime = *(int*)pData; + m_dvd.iDVDStillStartTime = XbmcThreads::SystemClockMillis(); + + /* adjust for the output delay in the video queue */ + unsigned int time = 0; + if( m_CurrentVideo.stream && m_dvd.iDVDStillTime > 0 ) + { + time = (unsigned int)(m_player_video.GetOutputDelay() / ( DVD_TIME_BASE / 1000 )); + if( time < 10000 && time > 0 ) + m_dvd.iDVDStillTime += time; + } + m_dvd.state = DVDSTATE_STILL; + CLog::Log(LOGDEBUG, + "DVDNAV_STILL_FRAME - waiting %i sec, with delay of %d sec", + m_dvd.iDVDStillTime, time / 1000); + } + } return 0; } @@ -3497,11 +3574,12 @@ bool COMXPlayer::OnAction(const CAction &action) pMenus->OnMenu(); // send a message to everyone that we've gone to the menu CGUIMessage msg(GUI_MSG_VIDEO_MENU_STARTED, 0, 0); - g_windowManager.SendMessage(msg); + g_windowManager.SendThreadMessage(msg); return true; } break; } + if (pMenus->IsInMenu()) { switch (action.GetID()) @@ -3774,7 +3852,7 @@ int COMXPlayer::AddSubtitle(const CStdString& strSubPath) int COMXPlayer::GetCacheLevel() const { CSingleLock lock(m_StateSection); - return (int)(m_State.cache_level * 100); + return (int)(m_StateInput.cache_level * 100); } double COMXPlayer::GetQueueTime() @@ -3784,6 +3862,26 @@ double COMXPlayer::GetQueueTime() return max(a, v) * 8000.0 / 100; } +void COMXPlayer::GetVideoStreamInfo(SPlayerVideoStreamInfo &info) +{ + info.bitrate = m_player_video.GetVideoBitrate(); + + CStdString retVal; + if (m_pDemuxer && (m_CurrentVideo.id != -1)) + m_pDemuxer->GetStreamCodecName(m_CurrentVideo.id, retVal); + info.videoCodecName = retVal; + info.videoAspectRatio = g_renderManager.GetAspectRatio(); + g_renderManager.GetVideoRect(info.SrcRect, info.DestRect); +} + +int COMXPlayer::GetSourceBitrate() +{ + if (m_pInputStream) + return (int)m_pInputStream->GetBitstreamStats().GetBitrate(); + + return 0; +} + void COMXPlayer::GetAudioStreamInfo(int index, SPlayerAudioStreamInfo &info) { if (index < 0 || index > GetAudioStreamCount() - 1) @@ -3817,26 +3915,6 @@ void COMXPlayer::GetAudioStreamInfo(int index, SPlayerAudioStreamInfo &info) } } -void COMXPlayer::GetVideoStreamInfo(SPlayerVideoStreamInfo &info) -{ - info.bitrate = m_player_video.GetVideoBitrate(); - - CStdString retVal; - if (m_pDemuxer && (m_CurrentVideo.id != -1)) - m_pDemuxer->GetStreamCodecName(m_CurrentVideo.id, retVal); - info.videoCodecName = retVal; - info.videoAspectRatio = g_renderManager.GetAspectRatio(); - g_renderManager.GetVideoRect(info.SrcRect, info.DestRect); -} - -int COMXPlayer::GetSourceBitrate() -{ - if (m_pInputStream) - return (int)m_pInputStream->GetBitstreamStats().GetBitrate(); - - return 0; -} - int COMXPlayer::AddSubtitleFile(const std::string& filename, const std::string& subfilename, CDemuxStream::EFlags flags) { std::string ext = URIUtils::GetExtension(filename); @@ -3874,18 +3952,16 @@ int COMXPlayer::AddSubtitleFile(const std::string& filename, const std::string& void COMXPlayer::UpdatePlayState(double timeout) { - if(m_State.timestamp != 0 - && m_State.timestamp + DVD_MSEC_TO_TIME(timeout) > m_av_clock.GetAbsoluteClock()) + if(m_StateInput.timestamp != 0 + && m_StateInput.timestamp + DVD_MSEC_TO_TIME(timeout) > m_av_clock.GetAbsoluteClock()) return; - SPlayerState state(m_State); + SPlayerState state(m_StateInput); if (m_CurrentVideo.dts != DVD_NOPTS_VALUE) state.dts = m_CurrentVideo.dts; else if(m_CurrentAudio.dts != DVD_NOPTS_VALUE) state.dts = m_CurrentAudio.dts; - else - state.dts = m_av_clock.GetClock(); if(m_pDemuxer) { @@ -3893,15 +3969,21 @@ void COMXPlayer::UpdatePlayState(double timeout) state.chapter_count = m_pDemuxer->GetChapterCount(); m_pDemuxer->GetChapterName(state.chapter_name); - // TODO : workaround until omx clock handling is rewritten - if(m_playSpeed == DVD_PLAYSPEED_NORMAL) - state.time = DVD_TIME_TO_MSEC(m_av_clock.OMXMediaTime(true, true)); - else - state.time = DVD_TIME_TO_MSEC(m_av_clock.GetClock() + m_offset_pts); + if(state.dts == DVD_NOPTS_VALUE) + state.time = 0; + else + // TODO : workaround until omx clock handling is rewritten + if(m_playSpeed == DVD_PLAYSPEED_NORMAL) + state.time = DVD_TIME_TO_MSEC(m_av_clock.OMXMediaTime(true, true)); + else + state.time = DVD_TIME_TO_MSEC(state.dts + m_offset_pts); state.time_total = m_pDemuxer->GetStreamLength(); - + state.time_src = ETIMESOURCE_CLOCK; } + state.canpause = true; + state.canseek = true; + if(m_pInputStream) { // override from input stream if needed @@ -3917,27 +3999,26 @@ void COMXPlayer::UpdatePlayState(double timeout) { state.time = pDisplayTime->GetTime(); state.time_total = pDisplayTime->GetTotalTime(); + state.time_src = ETIMESOURCE_INPUT; } - if (dynamic_cast(m_pInputStream)) + if (CDVDInputStream::IMenus* ptr = dynamic_cast(m_pInputStream)) { + if(!ptr->GetState(state.player_state)) + state.player_state = ""; + if(m_dvd.state == DVDSTATE_STILL) { state.time = XbmcThreads::SystemClockMillis() - m_dvd.iDVDStillStartTime; state.time_total = m_dvd.iDVDStillTime; + state.time_src = ETIMESOURCE_MENU; } } - if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) - { - CDVDInputStreamPVRManager* pvrinputstream = static_cast(m_pInputStream); - state.canpause = pvrinputstream->CanPause(); - state.canseek = pvrinputstream->CanSeek(); - } - else + if (CDVDInputStream::ISeekable* ptr = dynamic_cast(m_pInputStream)) { - state.canseek = state.time_total > 0 ? true : false; - state.canpause = true; + state.canpause = ptr->CanPause(); + state.canseek = ptr->CanSeek(); } } @@ -3947,15 +4028,13 @@ void COMXPlayer::UpdatePlayState(double timeout) state.time_total = m_Edl.RemoveCutTime(llrint(state.time_total)); } - state.player_state = ""; - if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD)) - { + if(state.time_total <= 0) + state.canseek = false; + + if (state.time_src == ETIMESOURCE_CLOCK) + state.time_offset = m_offset_pts; + else if (state.dts != DVD_NOPTS_VALUE) state.time_offset = DVD_MSEC_TO_TIME(state.time) - state.dts; - if(!((CDVDInputStreamNavigator*)m_pInputStream)->GetNavigatorState(state.player_state)) - state.player_state = ""; - } - else - state.time_offset = 0; if (m_CurrentAudio.id >= 0 && m_pDemuxer) { @@ -4002,7 +4081,7 @@ void COMXPlayer::UpdatePlayState(double timeout) state.timestamp = m_av_clock.GetAbsoluteClock(); CSingleLock lock(m_StateSection); - m_State = state; + m_StateInput = state; } void COMXPlayer::UpdateApplication(double timeout) @@ -4073,11 +4152,21 @@ bool COMXPlayer::GetStreamDetails(CStreamDetails &details) { if (m_pDemuxer) { - bool result=CDVDFileInfo::DemuxerToStreamDetails(m_pInputStream, m_pDemuxer, details); + bool result = CDVDFileInfo::DemuxerToStreamDetails(m_pInputStream, m_pDemuxer, details); if (result && details.GetStreamCount(CStreamDetail::VIDEO) > 0) // this is more correct (dvds in particular) { - ((CStreamDetailVideo*)details.GetNthStream(CStreamDetail::VIDEO,0))->m_fAspect = g_renderManager.GetAspectRatio(); - ((CStreamDetailVideo*)details.GetNthStream(CStreamDetail::VIDEO,0))->m_iDuration = GetTotalTime() / 1000; + /* + * We can only obtain the aspect & duration from dvdplayer when the Process() thread is running + * and UpdatePlayState() has been called at least once. In this case dvdplayer duration/AR will + * return 0 and we'll have to fallback to the (less accurate) info from the demuxer. + */ + float aspect = m_player_video.GetAspectRatio(); + if (aspect > 0.0f) + ((CStreamDetailVideo*)details.GetNthStream(CStreamDetail::VIDEO,0))->m_fAspect = aspect; + + int64_t duration = GetTotalTime() / 1000; + if (duration > 0) + ((CStreamDetailVideo*)details.GetNthStream(CStreamDetail::VIDEO,0))->m_iDuration = duration; } return result; } diff --git a/xbmc/cores/omxplayer/OMXPlayer.h b/xbmc/cores/omxplayer/OMXPlayer.h index 40d9a0508d..9b1aa44046 100644 --- a/xbmc/cores/omxplayer/OMXPlayer.h +++ b/xbmc/cores/omxplayer/OMXPlayer.h @@ -74,6 +74,7 @@ public: int source; double dts; // last dts from demuxer, used to find disncontinuities double dur; // last frame expected duration + double dts_state; // when did we last send a playback state update CDVDStreamInfo hint; // stream hints, used to notice stream changes void* stream; // pointer or integer, identifying stream playing. if it changes stream changed int changes; // remembered counter from stream to track codec changes @@ -96,6 +97,7 @@ public: id = -1; source = STREAM_SOURCE_NONE; dts = DVD_NOPTS_VALUE; + dts_state = DVD_NOPTS_VALUE; dur = DVD_NOPTS_VALUE; hint.Clear(); stream = NULL; @@ -366,15 +368,27 @@ protected: int iSelectedAudioStream; // mpeg stream id, or -1 if disabled } m_dvd; + enum ETimeSource + { + ETIMESOURCE_CLOCK, + ETIMESOURCE_INPUT, + ETIMESOURCE_MENU, + }; + + friend class OMXPlayerVideo; + friend class OMXPlayerAudio; + struct SPlayerState { SPlayerState() { Clear(); } void Clear() { + player = 0; timestamp = 0; time = 0; time_total = 0; time_offset = 0; + time_src = ETIMESOURCE_CLOCK; dts = DVD_NOPTS_VALUE; player_state = ""; chapter = 0; @@ -392,11 +406,14 @@ protected: cache_offset = 0.0; } + int player; // source of this data + double timestamp; // last time of update double time_offset; // difference between time and pts double time; // current playback time double time_total; // total playback time + ETimeSource time_src; // current time source double dts; // last known dts std::string player_state; // full player state @@ -418,7 +435,7 @@ protected: double cache_level; // current estimated required cache level double cache_delay; // time until cache is expected to reach estimated level double cache_offset; // percentage of file ahead of current position - } m_State; + } m_State, m_StateInput; CCriticalSection m_StateSection; CEdl m_Edl; @@ -481,4 +498,7 @@ private: bool m_change_volume; CDVDOverlayContainer m_overlayContainer; ECacheState m_caching; + + bool m_HasVideo; + bool m_HasAudio; }; diff --git a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp index 16ea6c3fc3..04590c7cc2 100644 --- a/xbmc/cores/omxplayer/OMXPlayerAudio.cpp +++ b/xbmc/cores/omxplayer/OMXPlayerAudio.cpp @@ -569,6 +569,18 @@ void OMXPlayerAudio::Process() if(m_started) m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_AUDIO)); } + else if (pMsg->IsType(CDVDMsg::PLAYER_DISPLAYTIME)) + { + COMXPlayer::SPlayerState& state = ((CDVDMsgType*)pMsg)->m_value; + + if(state.time_src == COMXPlayer::ETIMESOURCE_CLOCK) + state.time = DVD_TIME_TO_MSEC(m_av_clock->OMXMediaTime(true, true)); + //state.time = DVD_TIME_TO_MSEC(m_av_clock->GetClock(state.timestamp) + state.time_offset); + else + state.timestamp = m_av_clock->GetAbsoluteClock(); + state.player = DVDPLAYER_AUDIO; + m_messageParent.Put(pMsg->Acquire()); + } else if (pMsg->IsType(CDVDMsg::GENERAL_EOF)) { CLog::Log(LOGDEBUG, "COMXPlayerAudio - CDVDMsg::GENERAL_EOF"); diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp index 96a44280df..45fc51f6a3 100644 --- a/xbmc/cores/omxplayer/OMXPlayerVideo.cpp +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.cpp @@ -42,6 +42,7 @@ #include "DVDOverlayRenderer.h" #include "settings/GUISettings.h" #include "settings/Settings.h" +#include "settings/MediaSettings.h" #include "cores/VideoRenderers/RenderFormats.h" #include "cores/VideoRenderers/RenderFlags.h" @@ -490,6 +491,18 @@ void OMXPlayerVideo::Process() if(m_started) m_messageParent.Put(new CDVDMsgInt(CDVDMsg::PLAYER_STARTED, DVDPLAYER_VIDEO)); } + else if (pMsg->IsType(CDVDMsg::PLAYER_DISPLAYTIME)) + { + COMXPlayer::SPlayerState& state = ((CDVDMsgType*)pMsg)->m_value; + + if(state.time_src == COMXPlayer::ETIMESOURCE_CLOCK) + state.time = DVD_TIME_TO_MSEC(m_av_clock->OMXMediaTime(true, true)); + //state.time = DVD_TIME_TO_MSEC(m_av_clock->GetClock(state.timestamp) + state.time_offset); + else + state.timestamp = m_av_clock->GetAbsoluteClock(); + state.player = DVDPLAYER_VIDEO; + m_messageParent.Put(pMsg->Acquire()); + } else if (pMsg->IsType(CDVDMsg::GENERAL_STREAMCHANGE)) { COMXMsgVideoCodecChange* msg(static_cast(pMsg)); diff --git a/xbmc/cores/omxplayer/OMXPlayerVideo.h b/xbmc/cores/omxplayer/OMXPlayerVideo.h index 1931bf38ab..9c4aa556cb 100644 --- a/xbmc/cores/omxplayer/OMXPlayerVideo.h +++ b/xbmc/cores/omxplayer/OMXPlayerVideo.h @@ -38,6 +38,7 @@ #include "DVDMessageQueue.h" #include "utils/BitstreamStats.h" #include "linux/DllBCM.h" +#include "cores/VideoRenderers/RenderManager.h" using namespace std; @@ -125,6 +126,7 @@ public: void EnableSubtitle(bool bEnable) { m_bRenderSubs = bEnable; } bool IsSubtitleEnabled() { return m_bRenderSubs; } void EnableFullscreen(bool bEnable) { m_bAllowFullscreen = bEnable; } + float GetAspectRatio() { return g_renderManager.GetAspectRatio(); } void SetFlags(unsigned flags) { m_flags = flags; }; int GetFreeSpace(); void SetVideoRect(const CRect &SrcRect, const CRect &DestRect); -- cgit v1.2.3