fixed: Improved DVDPlayer to fix problem with switch channels
[xbmc:xbmc-antiquated.git] / XBMC / xbmc / cores / dvdplayer / DVDPlayer.h
1 #pragma once
2
3 /*
4  *      Copyright (C) 2005-2008 Team XBMC
5  *      http://www.xbmc.org
6  *
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)
10  *  any later version.
11  *
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.
16  *
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
21  *
22  */
23
24 #include "cores/IPlayer.h"
25 #include "utils/Thread.h"
26
27 #include "IDVDPlayer.h"
28
29 #include "DVDMessageQueue.h"
30 #include "DVDClock.h"
31 #include "DVDPlayerAudio.h"
32 #include "DVDPlayerVideo.h"
33 #include "DVDPlayerSubtitle.h"
34 #include "DVDPlayerTeletext.h"
35
36 //#include "DVDChapterReader.h"
37 #include "DVDSubtitles/DVDFactorySubtitle.h"
38 #include "utils/BitstreamStats.h"
39
40 #include "Edl.h"
41 #include "dlgcache.h"
42 #include "FileItem.h"
43
44
45 class CDVDInputStream;
46
47 class CDVDDemux;
48 class CDemuxStreamVideo;
49 class CDemuxStreamAudio;
50 class CDemuxStreamData;
51 class CStreamInfo;
52
53 #define DVDSTATE_NORMAL           0x00000001 // normal dvd state
54 #define DVDSTATE_STILL            0x00000002 // currently displaying a still frame
55 #define DVDSTATE_WAIT             0x00000003 // waiting for demuxer read error
56
57 class CCurrentStream
58 {
59 public:
60   int              id;     // demuxerid of current playing stream
61   int              source;
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
65   bool             inited;
66   const StreamType type;
67   // stuff to handle starting after seek
68   double                     startpts;
69   CDVDMsgGeneralSynchronize* startsync;
70
71   CCurrentStream(StreamType t)
72     : type(t)
73   {
74     startsync = NULL;
75     Clear();
76   }
77
78   void Clear()
79   {
80     id     = -1;
81     source = STREAM_SOURCE_NONE;
82     dts    = DVD_NOPTS_VALUE;
83     hint.Clear();
84     stream = NULL;
85     inited = false;
86     if(startsync)
87       startsync->Release();
88     startsync = NULL;
89     startpts  = DVD_NOPTS_VALUE;
90   }
91 };
92
93 typedef struct
94 {
95   StreamType   type;
96   std::string  filename;
97   std::string  language;
98   std::string  name;
99   int          source;
100   int          id;
101 } SelectionStream;
102
103 class CSelectionStreams
104 {
105   CCriticalSection m_section;
106   SelectionStream  m_invalid;
107 public:
108   CSelectionStreams()
109   {
110     m_invalid.id = -1;
111     m_invalid.source = STREAM_SOURCE_NONE;
112     m_invalid.type = STREAM_NONE;
113   }
114   std::vector<SelectionStream> m_Streams;
115
116   int              IndexOf (StreamType type, int source, int id);
117   int              IndexOf (StreamType type, CDVDPlayer& p);
118   int              Count   (StreamType type) { return IndexOf(type, STREAM_SOURCE_NONE, -1) + 1; }
119   SelectionStream& Get     (StreamType type, int index);
120
121   void             Clear   (StreamType type, StreamSource source);
122   int              Source  (StreamSource source, std::string filename);
123
124   void             Update  (SelectionStream& s);
125   void             Update  (CDVDInputStream* input, CDVDDemux* demuxer);
126 };
127
128
129 #define DVDPLAYER_AUDIO    1
130 #define DVDPLAYER_VIDEO    2
131 #define DVDPLAYER_SUBTITLE 3
132 #define DVDPLAYER_TELETEXT 4
133
134 class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer
135 {
136 public:
137   CDVDPlayer(IPlayerCallback& callback);
138   virtual ~CDVDPlayer();
139   virtual void RegisterAudioCallback(IAudioCallback* pCallback) { m_dvdPlayerAudio.RegisterAudioCallback(pCallback); }
140   virtual void UnRegisterAudioCallback()                        { m_dvdPlayerAudio.UnRegisterAudioCallback(); }
141   virtual bool OpenFile(const CFileItem& file, const CPlayerOptions &options);
142   virtual bool CloseFile();
143   virtual bool IsPlaying() const;
144   virtual void Pause();
145   virtual bool IsPaused() const;
146   virtual bool HasVideo() const;
147   virtual bool HasAudio() const;
148   virtual bool IsPassthrough() const;
149   virtual bool CanSeek();
150   virtual void Seek(bool bPlus, bool bLargeStep);
151   virtual bool SeekScene(bool bPlus = true);
152   virtual void SeekPercentage(float iPercent);
153   virtual float GetPercentage();
154   virtual void SetVolume(long nVolume)                          { m_dvdPlayerAudio.SetVolume(nVolume); }
155   virtual void SetDynamicRangeCompression(long drc)             { m_dvdPlayerAudio.SetDynamicRangeCompression(drc); }
156   virtual void GetAudioInfo(CStdString& strAudioInfo);
157   virtual void GetVideoInfo(CStdString& strVideoInfo);
158   virtual void GetGeneralInfo( CStdString& strVideoInfo);
159   virtual void Update(bool bPauseDrawing)                       { m_dvdPlayerVideo.Update(bPauseDrawing); }
160   virtual void GetVideoRect(CRect& SrcRect, CRect& DestRect)    { m_dvdPlayerVideo.GetVideoRect(SrcRect, DestRect); }
161   virtual void GetVideoAspectRatio(float& fAR)                  { fAR = m_dvdPlayerVideo.GetAspectRatio(); }
162   virtual bool CanRecord();
163   virtual bool IsRecording();
164   virtual bool Record(bool bOnOff);
165   virtual void PlaybackReset();
166   virtual void SetAVDelay(float fValue = 0.0f);
167   virtual float GetAVDelay();
168
169   virtual void SetSubTitleDelay(float fValue = 0.0f);
170   virtual float GetSubTitleDelay();
171   virtual int GetSubtitleCount();
172   virtual int GetSubtitle();
173   virtual void GetSubtitleName(int iStream, CStdString &strStreamName);
174   virtual void SetSubtitle(int iStream);
175   virtual bool GetSubtitleVisible();
176   virtual void SetSubtitleVisible(bool bVisible);
177   virtual bool GetSubtitleExtension(CStdString &strSubtitleExtension) { return false; }
178   virtual bool AddSubtitle(const CStdString& strSubPath);
179
180   virtual int GetAudioStreamCount();
181   virtual int GetAudioStream();
182   virtual void GetAudioStreamName(int iStream, CStdString &strStreamName);
183   virtual void SetAudioStream(int iStream);
184
185   virtual TextCacheStruct_t* GetTeletextCache();
186   virtual void LoadPage(int p, int sp, unsigned char* buffer);
187
188   virtual int  GetChapterCount();
189   virtual int  GetChapter();
190   virtual void GetChapterName(CStdString& strChapterName);
191   virtual int  SeekChapter(int iChapter);
192
193   virtual void SeekTime(__int64 iTime);
194   virtual __int64 GetTime();
195   virtual int GetTotalTime();
196   virtual void ToFFRW(int iSpeed);
197   virtual bool OnAction(const CAction &action);
198   virtual bool HasMenu();
199   virtual int GetAudioBitrate();
200   virtual int GetVideoBitrate();
201   virtual int GetSourceBitrate();
202   virtual int GetChannels();
203   virtual CStdString GetAudioCodecName();
204   virtual CStdString GetVideoCodecName();
205   virtual int GetPictureWidth();
206   virtual bool GetStreamDetails(CStreamDetails &details);
207
208   virtual bool GetCurrentSubtitle(CStdString& strSubtitle);
209
210   virtual CStdString GetPlayerState();
211   virtual bool SetPlayerState(CStdString state);
212   
213   virtual CStdString GetPlayingTitle();
214
215   virtual bool IsCaching() const { return m_caching; }
216   virtual int GetCacheLevel() const ;
217
218   virtual int OnDVDNavResult(void* pData, int iMessage);
219 protected:
220   friend class CSelectionStreams;
221   void LockStreams()                                            { EnterCriticalSection(&m_critStreamSection); }
222   void UnlockStreams()                                          { LeaveCriticalSection(&m_critStreamSection); }
223
224   virtual void OnStartup();
225   virtual void OnExit();
226   virtual void Process();
227
228   bool OpenAudioStream(int iStream, int source);
229   bool OpenVideoStream(int iStream, int source);
230   bool OpenSubtitleStream(int iStream, int source);
231   bool OpenTeletextStream(int iStream, int source);
232   bool CloseAudioStream(bool bWaitForBuffers);
233   bool CloseVideoStream(bool bWaitForBuffers);
234   bool CloseSubtitleStream(bool bKeepOverlays);
235   bool CloseTeletextStream(bool bWaitForBuffers);
236
237   void ProcessPacket(CDemuxStream* pStream, DemuxPacket* pPacket);
238   void ProcessAudioData(CDemuxStream* pStream, DemuxPacket* pPacket);
239   void ProcessVideoData(CDemuxStream* pStream, DemuxPacket* pPacket);
240   void ProcessSubData(CDemuxStream* pStream, DemuxPacket* pPacket);
241   void ProcessTeletextData(CDemuxStream* pStream, DemuxPacket* pPacket);
242
243   bool AddSubtitleFile(const std::string& filename);
244   /**
245    * one of the DVD_PLAYSPEED defines
246    */
247   void SetPlaySpeed(int iSpeed);
248   int GetPlaySpeed()                                                { return m_playSpeed; }
249   void SetCaching(bool enabled);
250
251   __int64 GetTotalTimeInMsec();
252   void FlushBuffers(bool queued);
253
254   void HandleMessages();
255   void HandlePlaySpeed();
256   bool IsInMenu() const;
257
258   void SyncronizePlayers(DWORD sources, double pts = DVD_NOPTS_VALUE);
259   void SyncronizeDemuxer(DWORD timeout);
260   void CheckAutoSceneSkip();
261   void CheckContinuity(CCurrentStream& current, DemuxPacket* pPacket);
262   bool CheckSceneSkip(CCurrentStream& current);
263   bool CheckPlayerInit(CCurrentStream& current, unsigned int source);
264   bool CheckStartCaching(CCurrentStream& current);
265   void SendPlayerMessage(CDVDMsg* pMsg, unsigned int target);
266
267   bool ReadPacket(DemuxPacket*& packet, CDemuxStream*& stream);
268   bool IsValidStream(CCurrentStream& stream);
269   bool IsBetterStream(CCurrentStream& current, CDemuxStream* stream);
270
271   bool OpenInputStream();
272   bool OpenDemuxStream();
273   void OpenDefaultStreams();
274
275   void UpdateApplication(double timeout);
276   void UpdatePlayState(double timeout);
277   double m_UpdateApplication;
278
279   bool m_bAbortRequest;
280
281   std::string m_filename; // holds the actual filename
282   std::string m_content;  // hold a hint to what content file contains (mime type)
283   bool        m_caching;  // player is filling up the demux queue
284   bool        m_seeking;  // player is currently trying to fullfill a seek request
285   CFileItem   m_item;
286
287   CCurrentStream m_CurrentAudio;
288   CCurrentStream m_CurrentVideo;
289   CCurrentStream m_CurrentSubtitle;
290   CCurrentStream m_CurrentTeletext;
291
292   CSelectionStreams m_SelectionStreams;
293
294   int m_playSpeed;
295   struct SSpeedState
296   {
297     double lastpts;  // holds last display pts during ff/rw operations
298     double lasttime;
299   } m_SpeedState;
300
301   int m_errorCount;
302
303   CDVDMessageQueue m_messenger;     // thread messenger
304
305   CDVDPlayerVideo m_dvdPlayerVideo; // video part
306   CDVDPlayerAudio m_dvdPlayerAudio; // audio part
307   CDVDPlayerSubtitle m_dvdPlayerSubtitle; // subtitle part
308   CDVDTeletextData m_dvdPlayerTeletext; // teletext part
309
310   CDVDClock m_clock;                // master clock
311   CDVDOverlayContainer m_overlayContainer;
312
313   CDVDInputStream* m_pInputStream;  // input stream for current playing file
314   CDVDDemux* m_pDemuxer;            // demuxer for current playing file
315   CDVDDemux* m_pSubtitleDemuxer;
316
317   struct SDVDInfo
318   {
319     void Clear()
320     {
321       state                =  DVDSTATE_NORMAL;
322       iSelectedSPUStream   = -1;
323       iSelectedAudioStream = -1;
324       iDVDStillTime        =  0;
325       iDVDStillStartTime   =  0;
326     }
327
328     int state;                // current dvdstate
329     DWORD iDVDStillTime;      // total time in ticks we should display the still before continuing
330     DWORD iDVDStillStartTime; // time in ticks when we started the still
331     int iSelectedSPUStream;   // mpeg stream id, or -1 if disabled
332     int iSelectedAudioStream; // mpeg stream id, or -1 if disabled
333   } m_dvd;
334
335   CDlgCache *m_pDlgCache;
336
337   struct SPlayerState
338   {
339     void Clear()
340     {
341       timestamp     = 0;
342       time          = 0;
343       time_total    = 0;
344       player_state  = "";
345       chapter       = 0;
346       chapter_count = 0;
347       canrecord     = false;
348       recording     = false;
349       demux_video   = "";
350       demux_audio   = "";
351     }
352
353     double timestamp;         // last time of update
354
355     double time;              // current playback time
356     double time_total;        // total playback time
357
358     std::string player_state;  // full player state
359
360     int         chapter;      // current chapter
361     std::string chapter_name; // name of current chapter
362     int         chapter_count;// number of chapter
363
364     bool canrecord;           // can input stream record
365     bool recording;           // are we currently recording
366
367     std::string demux_video;
368     std::string demux_audio;
369   } m_State;
370   CCriticalSection m_StateSection;
371
372   class CPlayerSeek
373   {
374   public:
375     CPlayerSeek(CDVDPlayer* player);
376     ~CPlayerSeek();
377     CDVDPlayer& m_player;
378   };
379
380   HANDLE m_hReadyEvent;
381   CRITICAL_SECTION m_critStreamSection; // need to have this lock when switching streams (audio / video)
382
383   CEdl m_Edl;
384
385   struct SEdlAutoSkipMarkers {
386
387     void Clear()
388     {
389       cut = -1;
390       commbreak_start = -1;
391       commbreak_end = -1;
392       seek_to_start = false;
393       reset = 0;
394     }
395
396     void ResetCutMarker(double timeout)
397     {
398       if(reset != 0
399       && reset + DVD_MSEC_TO_TIME(timeout) > CDVDClock::GetAbsoluteClock())
400         return;
401
402       /*
403        * Reset the automatic EDL skip marker for a cut so automatic seeking can happen again if,
404        * for example, the initial automatic skip ended up back in the cut due to seeking
405        * inaccuracies.
406        */
407       cut = -1;
408
409       reset = CDVDClock::GetAbsoluteClock();
410     }
411
412     int cut;              // last automatically skipped EDL cut seek position
413     int commbreak_start;  // start time of the last commercial break automatically skipped
414     int commbreak_end;    // end time of the last commercial break automatically skipped
415     bool seek_to_start;   // whether seeking can go back to the start of a previously skipped break
416     double reset;         // last actual reset time
417
418   } m_EdlAutoSkipMarkers;
419
420   CPlayerOptions m_PlayerOptions;
421 };
422