Merge pull request #473 from Montellese/onplaybackspeedchanged
[vuplus_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 "threads/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 "FileItem.h"
42 #include "threads/SingleLock.h"
43
44
45 class CDVDInputStream;
46
47 class CDVDDemux;
48 class CDemuxStreamVideo;
49 class CDemuxStreamAudio;
50 class CStreamInfo;
51
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
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   bool             started; // has the player started
67   const StreamType type;
68   // stuff to handle starting after seek
69   double   startpts;
70   CDVDMsg* startsync;
71
72   CCurrentStream(StreamType t)
73     : type(t)
74   {
75     startsync = NULL;
76     Clear();
77   }
78
79   void Clear()
80   {
81     id     = -1;
82     source = STREAM_SOURCE_NONE;
83     dts    = DVD_NOPTS_VALUE;
84     hint.Clear();
85     stream = NULL;
86     inited = false;
87     started = false;
88     if(startsync)
89       startsync->Release();
90     startsync = NULL;
91     startpts  = DVD_NOPTS_VALUE;
92   }
93 };
94
95 typedef struct
96 {
97   StreamType   type;
98   std::string  filename;
99   std::string  filename2;  // for vobsub subtitles, 2 files are necessary (idx/sub) 
100   std::string  language;
101   std::string  name;
102   CDemuxStream::EFlags flags;
103   int          source;
104   int          id;
105   std::string  codec;
106   int          channels;
107 } SelectionStream;
108
109 class CSelectionStreams
110 {
111   CCriticalSection m_section;
112   SelectionStream  m_invalid;
113 public:
114   CSelectionStreams()
115   {
116     m_invalid.id = -1;
117     m_invalid.source = STREAM_SOURCE_NONE;
118     m_invalid.type = STREAM_NONE;
119   }
120   std::vector<SelectionStream> m_Streams;
121
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);
127
128   void             Clear   (StreamType type, StreamSource source);
129   int              Source  (StreamSource source, std::string filename);
130
131   void             Update  (SelectionStream& s);
132   void             Update  (CDVDInputStream* input, CDVDDemux* demuxer);
133 };
134
135
136 #define DVDPLAYER_AUDIO    1
137 #define DVDPLAYER_VIDEO    2
138 #define DVDPLAYER_SUBTITLE 3
139 #define DVDPLAYER_TELETEXT 4
140
141 class CDVDPlayer : public IPlayer, public CThread, public IDVDPlayer
142 {
143 public:
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();
162
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();
176
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);
188
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);
194
195   virtual TextCacheStruct_t* GetTeletextCache();
196   virtual void LoadPage(int p, int sp, unsigned char* buffer);
197
198   virtual int  GetChapterCount();
199   virtual int  GetChapter();
200   virtual void GetChapterName(CStdString& strChapterName);
201   virtual int  SeekChapter(int iChapter);
202
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);
218
219   virtual bool GetCurrentSubtitle(CStdString& strSubtitle);
220
221   virtual CStdString GetPlayerState();
222   virtual bool SetPlayerState(CStdString state);
223
224   virtual CStdString GetPlayingTitle();
225
226   enum ECacheState
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
232   };
233
234   virtual bool IsCaching() const { return m_caching == CACHESTATE_FULL; }
235   virtual int GetCacheLevel() const ;
236
237   virtual int OnDVDNavResult(void* pData, int iMessage);
238 protected:
239   friend class CSelectionStreams;
240
241   class StreamLock : public CSingleLock
242   {
243   public:
244     inline StreamLock(CDVDPlayer* cdvdplayer) : CSingleLock(cdvdplayer->m_critStreamSection) {}
245   };
246
247   virtual void OnStartup();
248   virtual void OnExit();
249   virtual void Process();
250
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);
259
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);
265
266   int  AddSubtitleFile(const std::string& filename, const std::string& subfilename = "", CDemuxStream::EFlags flags = CDemuxStream::FLAG_NONE);
267
268   /**
269    * one of the DVD_PLAYSPEED defines
270    */
271   void SetPlaySpeed(int iSpeed);
272   int GetPlaySpeed()                                                { return m_playSpeed; }
273   void SetCaching(ECacheState state);
274
275   __int64 GetTotalTimeInMsec();
276
277   double GetQueueTime();
278   bool GetCachingTimes(double& play_left, double& cache_left, double& file_offset);
279
280
281   void FlushBuffers(bool queued, double pts = DVD_NOPTS_VALUE, bool accurate = true);
282
283   void HandleMessages();
284   void HandlePlaySpeed();
285   bool IsInMenu() const;
286
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);
296
297   bool ReadPacket(DemuxPacket*& packet, CDemuxStream*& stream);
298   bool IsValidStream(CCurrentStream& stream);
299   bool IsBetterStream(CCurrentStream& current, CDemuxStream* stream);
300
301   bool OpenInputStream();
302   bool OpenDemuxStream();
303   void OpenDefaultStreams();
304
305   void UpdateApplication(double timeout);
306   void UpdatePlayState(double timeout);
307   double m_UpdateApplication;
308
309   bool m_bAbortRequest;
310
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;
314   CFileItem   m_item;
315
316
317   CCurrentStream m_CurrentAudio;
318   CCurrentStream m_CurrentVideo;
319   CCurrentStream m_CurrentSubtitle;
320   CCurrentStream m_CurrentTeletext;
321
322   CSelectionStreams m_SelectionStreams;
323
324   int m_playSpeed;
325   struct SSpeedState
326   {
327     double lastpts;  // holds last display pts during ff/rw operations
328     double lasttime;
329   } m_SpeedState;
330
331   int m_errorCount;
332
333   CDVDMessageQueue m_messenger;     // thread messenger
334
335   CDVDPlayerVideo m_dvdPlayerVideo; // video part
336   CDVDPlayerAudio m_dvdPlayerAudio; // audio part
337   CDVDPlayerSubtitle m_dvdPlayerSubtitle; // subtitle part
338   CDVDTeletextData m_dvdPlayerTeletext; // teletext part
339
340   CDVDClock m_clock;                // master clock
341   CDVDOverlayContainer m_overlayContainer;
342
343   CDVDInputStream* m_pInputStream;  // input stream for current playing file
344   CDVDDemux* m_pDemuxer;            // demuxer for current playing file
345   CDVDDemux* m_pSubtitleDemuxer;
346
347   CStdString m_lastSub;
348   
349   struct SDVDInfo
350   {
351     void Clear()
352     {
353       state                =  DVDSTATE_NORMAL;
354       iSelectedSPUStream   = -1;
355       iSelectedAudioStream = -1;
356       iDVDStillTime        =  0;
357       iDVDStillStartTime   =  0;
358     }
359
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
365   } m_dvd;
366
367   struct SPlayerState
368   {
369     SPlayerState() { Clear(); }
370     void Clear()
371     {
372       timestamp     = 0;
373       time          = 0;
374       time_total    = 0;
375       time_offset   = 0;
376       dts           = DVD_NOPTS_VALUE;
377       player_state  = "";
378       chapter       = 0;
379       chapter_name  = "";
380       chapter_count = 0;
381       canrecord     = false;
382       recording     = false;
383       demux_video   = "";
384       demux_audio   = "";
385       cache_bytes   = 0;
386       cache_level   = 0.0;
387       cache_delay   = 0.0;
388       cache_offset  = 0.0;
389     }
390
391     double timestamp;         // last time of update
392     double time_offset;       // difference between time and pts
393
394     double time;              // current playback time
395     double time_total;        // total playback time
396     double dts;               // last known dts
397
398     std::string player_state;  // full player state
399
400     int         chapter;      // current chapter
401     std::string chapter_name; // name of current chapter
402     int         chapter_count;// number of chapter
403
404     bool canrecord;           // can input stream record
405     bool recording;           // are we currently recording
406
407     std::string demux_video;
408     std::string demux_audio;
409
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
414   } m_State;
415   CCriticalSection m_StateSection;
416
417   CEvent m_ready;
418   CCriticalSection m_critStreamSection; // need to have this lock when switching streams (audio / video)
419
420   CEdl m_Edl;
421
422   struct SEdlAutoSkipMarkers {
423
424     void Clear()
425     {
426       cut = -1;
427       commbreak_start = -1;
428       commbreak_end = -1;
429       seek_to_start = false;
430       reset = 0;
431       mute = false;
432     }
433
434     void ResetCutMarker(double timeout)
435     {
436       if(reset != 0
437       && reset + DVD_MSEC_TO_TIME(timeout) > CDVDClock::GetAbsoluteClock())
438         return;
439
440       /*
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
443        * inaccuracies.
444        */
445       cut = -1;
446
447       reset = CDVDClock::GetAbsoluteClock();
448     }
449
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
456
457   } m_EdlAutoSkipMarkers;
458
459   CPlayerOptions m_PlayerOptions;
460 };