4 * Copyright (C) 2005-2008 Team XBMC
7 * This Program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2, or (at your option)
12 * This Program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with XBMC; see the file COPYING. If not, write to
19 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20 * http://www.gnu.org/copyleft/gpl.html
24 #include "cores/IPlayer.h"
25 #include "threads/Thread.h"
27 #include "IDVDPlayer.h"
29 #include "DVDMessageQueue.h"
31 #include "DVDPlayerAudio.h"
32 #include "DVDPlayerVideo.h"
33 #include "DVDPlayerSubtitle.h"
34 #include "DVDPlayerTeletext.h"
36 //#include "DVDChapterReader.h"
37 #include "DVDSubtitles/DVDFactorySubtitle.h"
38 #include "utils/BitstreamStats.h"
42 #include "threads/SingleLock.h"
45 class CDVDInputStream;
48 class CDemuxStreamVideo;
49 class CDemuxStreamAudio;
52 #define DVDSTATE_NORMAL 0x00000001 // normal dvd state
53 #define DVDSTATE_STILL 0x00000002 // currently displaying a still frame
54 #define DVDSTATE_WAIT 0x00000003 // waiting for demuxer read error
55 #define DVDSTATE_SEEK 0x00000004 // we are finishing a seek request
60 int id; // demuxerid of current playing stream
62 double dts; // last dts from demuxer, used to find disncontinuities
63 CDVDStreamInfo hint; // stream hints, used to notice stream changes
64 void* stream; // pointer or integer, identifying stream playing. if it changes stream changed
66 bool started; // has the player started
67 const StreamType type;
68 // stuff to handle starting after seek
72 CCurrentStream(StreamType t)
82 source = STREAM_SOURCE_NONE;
83 dts = DVD_NOPTS_VALUE;
91 startpts = DVD_NOPTS_VALUE;
99 std::string filename2; // for vobsub subtitles, 2 files are necessary (idx/sub)
100 std::string language;
102 CDemuxStream::EFlags flags;
109 class CSelectionStreams
111 CCriticalSection m_section;
112 SelectionStream m_invalid;
117 m_invalid.source = STREAM_SOURCE_NONE;
118 m_invalid.type = STREAM_NONE;
120 std::vector<SelectionStream> m_Streams;
122 int IndexOf (StreamType type, int source, int id);
123 int IndexOf (StreamType type, CDVDPlayer& p);
124 int Count (StreamType type) { return IndexOf(type, STREAM_SOURCE_NONE, -1) + 1; }
125 SelectionStream& Get (StreamType type, int index);
126 bool Get (StreamType type, CDemuxStream::EFlags flag, SelectionStream& out);
128 void Clear (StreamType type, StreamSource source);
129 int Source (StreamSource source, std::string filename);
131 void Update (SelectionStream& s);
132 void Update (CDVDInputStream* input, CDVDDemux* demuxer);
136 #define DVDPLAYER_AUDIO 1
137 #define DVDPLAYER_VIDEO 2
138 #define DVDPLAYER_SUBTITLE 3
139 #define DVDPLAYER_TELETEXT 4
141 class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer
144 CDVDPlayer(IPlayerCallback& callback);
145 virtual ~CDVDPlayer();
146 virtual void RegisterAudioCallback(IAudioCallback* pCallback) { m_dvdPlayerAudio.RegisterAudioCallback(pCallback); }
147 virtual void UnRegisterAudioCallback() { m_dvdPlayerAudio.UnRegisterAudioCallback(); }
148 virtual bool OpenFile(const CFileItem& file, const CPlayerOptions &options);
149 virtual bool CloseFile();
150 virtual bool IsPlaying() const;
151 virtual void Pause();
152 virtual bool IsPaused() const;
153 virtual bool HasVideo() const;
154 virtual bool HasAudio() const;
155 virtual bool IsPassthrough() const;
156 virtual bool CanSeek();
157 virtual void Seek(bool bPlus, bool bLargeStep);
158 virtual bool SeekScene(bool bPlus = true);
159 virtual void SeekPercentage(float iPercent);
160 virtual float GetPercentage();
161 virtual float GetCachePercentage();
163 virtual void SetVolume(long nVolume) { m_dvdPlayerAudio.SetVolume(nVolume); }
164 virtual void SetDynamicRangeCompression(long drc) { m_dvdPlayerAudio.SetDynamicRangeCompression(drc); }
165 virtual void GetAudioInfo(CStdString& strAudioInfo);
166 virtual void GetVideoInfo(CStdString& strVideoInfo);
167 virtual void GetGeneralInfo( CStdString& strVideoInfo);
168 virtual void Update(bool bPauseDrawing) { m_dvdPlayerVideo.Update(bPauseDrawing); }
169 virtual void GetVideoRect(CRect& SrcRect, CRect& DestRect) { m_dvdPlayerVideo.GetVideoRect(SrcRect, DestRect); }
170 virtual void GetVideoAspectRatio(float& fAR) { fAR = m_dvdPlayerVideo.GetAspectRatio(); }
171 virtual bool CanRecord();
172 virtual bool IsRecording();
173 virtual bool Record(bool bOnOff);
174 virtual void SetAVDelay(float fValue = 0.0f);
175 virtual float GetAVDelay();
177 virtual void SetSubTitleDelay(float fValue = 0.0f);
178 virtual float GetSubTitleDelay();
179 virtual int GetSubtitleCount();
180 virtual int GetSubtitle();
181 virtual void GetSubtitleName(int iStream, CStdString &strStreamName);
182 virtual void GetSubtitleLanguage(int iStream, CStdString &strStreamLang);
183 virtual void SetSubtitle(int iStream);
184 virtual bool GetSubtitleVisible();
185 virtual void SetSubtitleVisible(bool bVisible);
186 virtual bool GetSubtitleExtension(CStdString &strSubtitleExtension) { return false; }
187 virtual int AddSubtitle(const CStdString& strSubPath);
189 virtual int GetAudioStreamCount();
190 virtual int GetAudioStream();
191 virtual void GetAudioStreamName(int iStream, CStdString &strStreamName);
192 virtual void SetAudioStream(int iStream);
193 virtual void GetAudioStreamLanguage(int iStream, CStdString &strLanguage);
195 virtual TextCacheStruct_t* GetTeletextCache();
196 virtual void LoadPage(int p, int sp, unsigned char* buffer);
198 virtual int GetChapterCount();
199 virtual int GetChapter();
200 virtual void GetChapterName(CStdString& strChapterName);
201 virtual int SeekChapter(int iChapter);
203 virtual void SeekTime(__int64 iTime);
204 virtual __int64 GetTime();
205 virtual int GetTotalTime();
206 virtual void ToFFRW(int iSpeed);
207 virtual bool OnAction(const CAction &action);
208 virtual bool HasMenu();
209 virtual int GetAudioBitrate();
210 virtual int GetVideoBitrate();
211 virtual int GetSourceBitrate();
212 virtual int GetChannels();
213 virtual CStdString GetAudioCodecName();
214 virtual CStdString GetVideoCodecName();
215 virtual int GetPictureWidth();
216 virtual int GetPictureHeight();
217 virtual bool GetStreamDetails(CStreamDetails &details);
219 virtual bool GetCurrentSubtitle(CStdString& strSubtitle);
221 virtual CStdString GetPlayerState();
222 virtual bool SetPlayerState(CStdString state);
224 virtual CStdString GetPlayingTitle();
227 { CACHESTATE_DONE = 0
228 , CACHESTATE_FULL // player is filling up the demux queue
229 , CACHESTATE_INIT // player is waiting for first packet of each stream
230 , CACHESTATE_PLAY // player is waiting for players to not be stalled
231 , CACHESTATE_FLUSH // temporary state player will choose startup between init or full
234 virtual bool IsCaching() const { return m_caching == CACHESTATE_FULL; }
235 virtual int GetCacheLevel() const ;
237 virtual int OnDVDNavResult(void* pData, int iMessage);
239 friend class CSelectionStreams;
241 class StreamLock : public CSingleLock
244 inline StreamLock(CDVDPlayer* cdvdplayer) : CSingleLock(cdvdplayer->m_critStreamSection) {}
247 virtual void OnStartup();
248 virtual void OnExit();
249 virtual void Process();
251 bool OpenAudioStream(int iStream, int source);
252 bool OpenVideoStream(int iStream, int source);
253 bool OpenSubtitleStream(int iStream, int source);
254 bool OpenTeletextStream(int iStream, int source);
255 bool CloseAudioStream(bool bWaitForBuffers);
256 bool CloseVideoStream(bool bWaitForBuffers);
257 bool CloseSubtitleStream(bool bKeepOverlays);
258 bool CloseTeletextStream(bool bWaitForBuffers);
260 void ProcessPacket(CDemuxStream* pStream, DemuxPacket* pPacket);
261 void ProcessAudioData(CDemuxStream* pStream, DemuxPacket* pPacket);
262 void ProcessVideoData(CDemuxStream* pStream, DemuxPacket* pPacket);
263 void ProcessSubData(CDemuxStream* pStream, DemuxPacket* pPacket);
264 void ProcessTeletextData(CDemuxStream* pStream, DemuxPacket* pPacket);
266 int AddSubtitleFile(const std::string& filename, const std::string& subfilename = "", CDemuxStream::EFlags flags = CDemuxStream::FLAG_NONE);
269 * one of the DVD_PLAYSPEED defines
271 void SetPlaySpeed(int iSpeed);
272 int GetPlaySpeed() { return m_playSpeed; }
273 void SetCaching(ECacheState state);
275 __int64 GetTotalTimeInMsec();
277 double GetQueueTime();
278 bool GetCachingTimes(double& play_left, double& cache_left, double& file_offset);
281 void FlushBuffers(bool queued, double pts = DVD_NOPTS_VALUE, bool accurate = true);
283 void HandleMessages();
284 void HandlePlaySpeed();
285 bool IsInMenu() const;
287 void SynchronizePlayers(DWORD sources);
288 void SynchronizeDemuxer(DWORD timeout);
289 void CheckAutoSceneSkip();
290 void CheckContinuity(CCurrentStream& current, DemuxPacket* pPacket);
291 bool CheckSceneSkip(CCurrentStream& current);
292 bool CheckPlayerInit(CCurrentStream& current, unsigned int source);
293 bool CheckStartCaching(CCurrentStream& current);
294 void UpdateTimestamps(CCurrentStream& current, DemuxPacket* pPacket);
295 void SendPlayerMessage(CDVDMsg* pMsg, unsigned int target);
297 bool ReadPacket(DemuxPacket*& packet, CDemuxStream*& stream);
298 bool IsValidStream(CCurrentStream& stream);
299 bool IsBetterStream(CCurrentStream& current, CDemuxStream* stream);
301 bool OpenInputStream();
302 bool OpenDemuxStream();
303 void OpenDefaultStreams();
305 void UpdateApplication(double timeout);
306 void UpdatePlayState(double timeout);
307 double m_UpdateApplication;
309 bool m_bAbortRequest;
311 std::string m_filename; // holds the actual filename
312 std::string m_mimetype; // hold a hint to what content file contains (mime type)
313 ECacheState m_caching;
317 CCurrentStream m_CurrentAudio;
318 CCurrentStream m_CurrentVideo;
319 CCurrentStream m_CurrentSubtitle;
320 CCurrentStream m_CurrentTeletext;
322 CSelectionStreams m_SelectionStreams;
327 double lastpts; // holds last display pts during ff/rw operations
333 CDVDMessageQueue m_messenger; // thread messenger
335 CDVDPlayerVideo m_dvdPlayerVideo; // video part
336 CDVDPlayerAudio m_dvdPlayerAudio; // audio part
337 CDVDPlayerSubtitle m_dvdPlayerSubtitle; // subtitle part
338 CDVDTeletextData m_dvdPlayerTeletext; // teletext part
340 CDVDClock m_clock; // master clock
341 CDVDOverlayContainer m_overlayContainer;
343 CDVDInputStream* m_pInputStream; // input stream for current playing file
344 CDVDDemux* m_pDemuxer; // demuxer for current playing file
345 CDVDDemux* m_pSubtitleDemuxer;
347 CStdString m_lastSub;
353 state = DVDSTATE_NORMAL;
354 iSelectedSPUStream = -1;
355 iSelectedAudioStream = -1;
357 iDVDStillStartTime = 0;
360 int state; // current dvdstate
361 unsigned int iDVDStillTime; // total time in ticks we should display the still before continuing
362 unsigned int iDVDStillStartTime; // time in ticks when we started the still
363 int iSelectedSPUStream; // mpeg stream id, or -1 if disabled
364 int iSelectedAudioStream; // mpeg stream id, or -1 if disabled
369 SPlayerState() { Clear(); }
376 dts = DVD_NOPTS_VALUE;
391 double timestamp; // last time of update
392 double time_offset; // difference between time and pts
394 double time; // current playback time
395 double time_total; // total playback time
396 double dts; // last known dts
398 std::string player_state; // full player state
400 int chapter; // current chapter
401 std::string chapter_name; // name of current chapter
402 int chapter_count;// number of chapter
404 bool canrecord; // can input stream record
405 bool recording; // are we currently recording
407 std::string demux_video;
408 std::string demux_audio;
410 __int64 cache_bytes; // number of bytes current's cached
411 double cache_level; // current estimated required cache level
412 double cache_delay; // time until cache is expected to reach estimated level
413 double cache_offset; // percentage of file ahead of current position
415 CCriticalSection m_StateSection;
418 CCriticalSection m_critStreamSection; // need to have this lock when switching streams (audio / video)
422 struct SEdlAutoSkipMarkers {
427 commbreak_start = -1;
429 seek_to_start = false;
434 void ResetCutMarker(double timeout)
437 && reset + DVD_MSEC_TO_TIME(timeout) > CDVDClock::GetAbsoluteClock())
441 * Reset the automatic EDL skip marker for a cut so automatic seeking can happen again if,
442 * for example, the initial automatic skip ended up back in the cut due to seeking
447 reset = CDVDClock::GetAbsoluteClock();
450 int cut; // last automatically skipped EDL cut seek position
451 int commbreak_start; // start time of the last commercial break automatically skipped
452 int commbreak_end; // end time of the last commercial break automatically skipped
453 bool seek_to_start; // whether seeking can go back to the start of a previously skipped break
454 double reset; // last actual reset time
455 bool mute; // whether EDL mute is on
457 } m_EdlAutoSkipMarkers;
459 CPlayerOptions m_PlayerOptions;