MythTV  master
dvdringbuffer.h
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 #ifndef DVD_RING_BUFFER_H_
3 #define DVD_RING_BUFFER_H_
4 
5 #define DVD_BLOCK_SIZE 2048LL
6 #define DVD_MENU_MAX 7
7 
8 // Qt headers
9 #include <QMap>
10 #include <QString>
11 #include <QMutex>
12 #include <QRect>
13 #include <QCoreApplication>
14 
15 // MythTV headers
16 #include "ringbuffer.h"
17 #include "mythdate.h"
18 #include "referencecounter.h"
19 
20 extern "C" {
21 #include "libavcodec/avcodec.h"
22 }
23 
24 #include "dvdnav/dvdnav.h"
25 
33 {
34  friend class DVDRingBuffer;
35 
36  public:
37  MythDVDContext() = delete; // Default constructor should not be called
38  ~MythDVDContext() override = default;
39 
40  int64_t GetStartPTS() const { return (int64_t)m_pci.pci_gi.vobu_s_ptm; }
41  int64_t GetEndPTS() const { return (int64_t)m_pci.pci_gi.vobu_e_ptm; }
42  int64_t GetSeqEndPTS() const { return (int64_t)m_pci.pci_gi.vobu_se_e_ptm; }
43  uint32_t GetLBA() const { return m_pci.pci_gi.nv_pck_lbn; }
44  uint32_t GetLBAPrevVideoFrame() const;
45  int GetNumFrames() const;
46  int GetNumFramesPresent() const;
47  int GetFPS() const { return (m_pci.pci_gi.e_eltm.frame_u & 0x80) ? 30 : 25; }
48 
49  protected:
50  MythDVDContext(const dsi_t& dsi, const pci_t& pci);
51 
52  protected:
53  dsi_t m_dsi;
54  pci_t m_pci;
55 };
56 
63 class MythDVDPlayer;
64 
66 {
67  friend class DVDRingBuffer;
69 
70  public:
71  explicit DVDInfo(const QString &filename);
72  ~DVDInfo(void);
73  bool IsValid(void) const { return m_nav != nullptr; }
74  bool GetNameAndSerialNum(QString &name, QString &serialnum);
75  QString GetLastError(void) const { return m_lastError; }
76 
77  protected:
78  static void GetNameAndSerialNum(dvdnav_t* nav,
79  QString &name,
80  QString &serialnum,
81  const QString &filename,
82  const QString &logPrefix);
83 
84  protected:
85  dvdnav_t *m_nav {nullptr};
86  QString m_name;
87  QString m_serialnumber;
88  QString m_lastError;
89 };
90 
92 {
93  Q_DECLARE_TR_FUNCTIONS(DVDRingBuffer);
94 
95  public:
96  explicit DVDRingBuffer(const QString &lfilename);
97  ~DVDRingBuffer() override;
98 
99  // gets
100  int GetTitle(void) const { return m_title; }
101  bool DVDWaitingForPlayer(void) { return m_playerWait; }
102  int GetPart(void) const { return m_part; }
103  int GetCurrentAngle(void) const { return m_currentAngle; }
104  int GetNumAngles(void) { return m_currentTitleAngleCount; }
105  bool IsOpen(void) const override { return m_dvdnav; } // RingBuffer
106  long long GetTotalReadPosition(void) { return m_titleLength; }
107  uint GetChapterLength(void) const { return m_pgLength / 90000; }
108  void GetChapterTimes(QList<long long> &times);
109  uint64_t GetChapterTimes(uint title);
110  long long GetReadPosition(void) const override; // RingBuffer
111  void GetDescForPos(QString &desc);
112  void GetPartAndTitle(int &_part, int &_title) const
113  { _part = m_part; _title = m_title; }
114  uint GetTotalTimeOfTitle(void);
115  float GetAspectOverride(void) { return m_forcedAspect; }
116  bool IsBookmarkAllowed(void) override; // RingBuffer
117  bool IsSeekingAllowed(void) override; // RingBuffer
118  bool IsStreamed(void) override { return true; } // RingBuffer
119  int BestBufferSize(void) override { return 2048; } // RingBuffer
120 
121  uint GetCellStart(void);
122  bool PGCLengthChanged(void);
123  bool CellChanged(void);
124  bool IsInStillFrame(void) const override { return m_still > 0; } // RingBuffer
125  bool IsStillFramePending(void) const { return dvdnav_get_next_still_flag(m_dvdnav) > 0; }
126  bool AudioStreamsChanged(void) const { return m_audioStreamsChanged; }
127  bool IsWaiting(void) const { return m_dvdWaiting; }
128  int NumPartsInTitle(void) const { return m_titleParts; }
129  void GetMenuSPUPkt(uint8_t *buf, int buf_size, int stream_id, uint32_t startTime);
130 
131  uint32_t AdjustTimestamp(uint32_t timestamp);
132  int64_t AdjustTimestamp(int64_t timestamp);
133  MythDVDContext* GetDVDContext(void);
134  int32_t GetLastEvent(void) const { return m_dvdEvent; }
135 
136  // Public menu/button stuff
137  AVSubtitle *GetMenuSubtitle(uint &version);
138  int NumMenuButtons(void) const;
139  QRect GetButtonCoords(void);
140  void ReleaseMenuButton(void);
141  bool IsInMenu(void) const override { return m_inMenu; } // RingBuffer
142  bool HandleAction(const QStringList &actions, int64_t pts) override; // RingBuffer
143 
144  // Subtitles
145  uint GetSubtitleLanguage(int id);
146  int GetSubtitleTrackNum(uint stream_id);
147  bool DecodeSubtitles(AVSubtitle * sub, int * gotSubtitles,
148  const uint8_t * spu_pkt, int buf_size, uint32_t startTime);
149 
150  uint GetAudioLanguage(int idx);
151  int GetAudioTrackNum(uint stream_id);
152  int GetAudioTrackType(uint idx);
153 
154  bool GetNameAndSerialNum(QString& _name, QString& _serialnum);
155  bool GetDVDStateSnapshot(QString& state);
156  bool RestoreDVDStateSnapshot(QString& state);
157  double GetFrameRate(void);
158  bool StartOfTitle(void) { return (m_part == 0); }
159  bool EndOfTitle(void) { return ((m_titleParts == 0) ||
160  (m_part == (m_titleParts - 1)) ||
161  (m_titleParts == 1)); }
162 
163  // commands
164  bool OpenFile(const QString &lfilename,
165  uint retry_ms = kDefaultOpenTimeout) override; //RingBuffer
166  void PlayTitleAndPart(int _title, int _part)
167  { dvdnav_part_play(m_dvdnav, _title, _part); }
168  bool StartFromBeginning(void) override; //RingBuffer
169  void CloseDVD(void);
170  bool playTrack(int track);
171  bool nextTrack(void);
172  void prevTrack(void);
173  long long NormalSeek(long long time);
174  bool SectorSeek(uint64_t sector);
175  void SkipStillFrame(void);
176  void WaitSkip(void);
177  void SkipDVDWaitingForPlayer(void) { m_playerWait = false; }
178  void UnblockReading(void) { m_processState = PROCESS_REPROCESS; }
179  bool IsReadingBlocked(void) { return (m_processState == PROCESS_WAIT); }
180  bool GoToMenu(const QString &str);
181  void GoToNextProgram(void);
182  void GoToPreviousProgram(void);
183  bool GoBack(void);
184 
185  void IgnoreWaitStates(bool ignore) override { m_skipstillorwait = ignore; } // RingBuffer
186  void AudioStreamsChanged(bool change) { m_audioStreamsChanged = change; }
187  int64_t GetCurrentTime(void) { return (m_currentTime / 90000); }
188  uint TitleTimeLeft(void);
189  void SetTrack(uint type, int trackNo);
190  int GetTrack(uint type);
191  uint8_t GetNumAudioChannels(int idx);
192  void SetDVDSpeed(void);
193  void SetDVDSpeed(int speed);
194  bool SwitchAngle(uint angle);
195 
196  void SetParent(MythDVDPlayer *p) { m_parent = p; }
197 
198  protected:
199  int safe_read(void *data, uint sz) override; //RingBuffer
200  long long SeekInternal(long long pos, int whence) override; //RingBuffer
201 
202  typedef enum
203  {
206  PROCESS_WAIT
207  }processState_t;
208 
209  dvdnav_t *m_dvdnav {nullptr};
210  unsigned char m_dvdBlockWriteBuf[DVD_BLOCK_SIZE] {0};
211  unsigned char *m_dvdBlockReadBuf {nullptr};
212  int m_dvdBlockRPos {0};
213  int m_dvdBlockWPos {0};
214  long long m_pgLength {0};
215  long long m_pgcLength {0};
216  long long m_cellStart {0};
217  bool m_cellChanged {false};
218  bool m_pgcLengthChanged {false};
219  long long m_pgStart {0};
220  long long m_currentpos {0};
221  dvdnav_t *m_lastNav {nullptr}; // This really belongs in the player.
222  int32_t m_part {0};
223  int32_t m_lastPart {0};
224  int32_t m_title {0};
225  int32_t m_lastTitle {0};
226  bool m_playerWait {false};
227  int32_t m_titleParts {0};
228  bool m_gotStop {false};
229  int m_currentAngle {0};
230  int m_currentTitleAngleCount {0};
231  int64_t m_endPts {0};
232  int64_t m_timeDiff {0};
233 
234  int m_still {0};
235  int m_lastStill {0};
236  bool m_audioStreamsChanged {false};
237  bool m_dvdWaiting {false};
238  long long m_titleLength {0};
239  bool m_skipstillorwait {true};
240  long long m_cellstartPos {0};
241  bool m_buttonSelected {false};
242  bool m_buttonExists {false};
243  bool m_buttonSeenInCell {false};
244  bool m_lastButtonSeenInCell {false};
245  int m_cellid {0};
246  int m_lastcellid {0};
247  int m_vobid {0};
248  int m_lastvobid {0};
249  bool m_cellRepeated {false};
250 
251  int m_curAudioTrack {0};
252  int8_t m_curSubtitleTrack {0};
253  bool m_autoselectsubtitle {true};
254  QString m_dvdname;
255  QString m_serialnumber;
256  bool m_seeking {false};
257  int64_t m_seektime {0};
258  int64_t m_currentTime {0};
259  QMap<uint, uint> m_seekSpeedMap;
260  QMap<uint, QList<uint64_t> > m_chapterMap;
261 
262  MythDVDPlayer *m_parent {nullptr};
263  float m_forcedAspect {-1.0F};
264 
265  QMutex m_contextLock {QMutex::Recursive};
266  MythDVDContext *m_context {nullptr};
267  processState_t m_processState {PROCESS_NORMAL};
268  dvdnav_status_t m_dvdStat {DVDNAV_STATUS_OK};
269  int32_t m_dvdEvent {0};
270  int32_t m_dvdEventSize {0};
271 
272  // Private menu/button stuff
273  void ActivateButton(void);
274  void MoveButtonLeft(void);
275  void MoveButtonRight(void);
276  void MoveButtonUp(void);
277  void MoveButtonDown(void);
278  bool DVDButtonUpdate(bool b_mode);
279  void ClearMenuSPUParameters(void);
280  void ClearMenuButton(void);
281 
282  bool m_inMenu {false};
283  uint m_buttonVersion {1};
284  int m_buttonStreamID {0};
285  uint32_t m_clut[16] {0};
286  uint8_t m_button_color[4] {0};
287  uint8_t m_button_alpha[4] {0};
288  QRect m_hl_button {0,0,0,0};
289  uint8_t *m_menuSpuPkt {nullptr};
290  int m_menuBuflength {0};
291  AVSubtitle m_dvdMenuButton {};
293 
294  QMutex m_seekLock;
295  long long Seek(long long time);
296 
297  void ClearChapterCache(void);
298  uint ConvertLangCode(uint16_t code);
299  void SelectDefaultButton(void);
300  void WaitForPlayer(void);
301 
302  int get_nibble(const uint8_t *buf, int nibble_offset);
303  int decode_rle(uint8_t *bitmap, int linesize, int w, int h,
304  const uint8_t *buf, int nibble_offset, int buf_size);
305  void guess_palette(uint32_t *rgba_palette,const uint8_t *palette,
306  const uint8_t *alpha);
307  int is_transp(const uint8_t *buf, int pitch, int n,
308  const uint8_t *transp_color);
309  int find_smallest_bounding_rectangle(AVSubtitle *s);
310 };
311 
312 #endif // DVD_RING_BUFFER_H_
int GetPart(void) const
void AudioStreamsChanged(bool change)
int GetCurrentAngle(void) const
QMap< uint, uint > m_seekSpeedMap
QString m_dvdname
void IgnoreWaitStates(bool ignore) override
Encapsulates playback context at any given moment.
Definition: dvdringbuffer.h:32
bool IsStreamed(void) override
bool StartOfTitle(void)
virtual bool OpenFile(const QString &lfilename, uint retry_ms=kDefaultOpenTimeout)=0
Opens a file for reading.
int NumPartsInTitle(void) const
void SkipDVDWaitingForPlayer(void)
QMutex m_menuBtnLock
General purpose reference counter.
QString m_lastError
Definition: dvdringbuffer.h:88
int GetFPS() const
Definition: dvdringbuffer.h:47
QString m_serialnumber
Definition: dvdringbuffer.h:87
unsigned int uint
Definition: compat.h:140
int BestBufferSize(void) override
virtual long long SeekInternal(long long pos, int whence)=0
QString m_name
Definition: dvdringbuffer.h:86
bool EndOfTitle(void)
void GetPartAndTitle(int &_part, int &_title) const
bool DVDWaitingForPlayer(void)
bool IsStillFramePending(void) const
bool IsReadingBlocked(void)
#define MTV_PUBLIC
Definition: mythtvexp.h:15
uint32_t GetLBA() const
Definition: dvdringbuffer.h:43
long long GetTotalReadPosition(void)
int64_t GetStartPTS() const
Definition: dvdringbuffer.h:40
bool IsInStillFrame(void) const override
uint GetChapterLength(void) const
Q_DECLARE_TR_FUNCTIONS(DVDRingBuffer)
unsigned short uint16_t
Definition: iso6937tables.h:1
virtual bool IsBookmarkAllowed(void)
const char * name
Definition: ParseText.cpp:328
#define DVD_BLOCK_SIZE
Definition: dvdringbuffer.h:5
void SetParent(MythDVDPlayer *p)
bool IsWaiting(void) const
bool IsOpen(void) const override
Returns true if open for either reading or writing.
virtual long long GetReadPosition(void) const =0
Returns how far into the file we have read.
virtual int safe_read(void *data, uint sz)=0
virtual bool StartFromBeginning(void)
QString GetLastError(void) const
Definition: dvdringbuffer.h:75
bool GetNameAndSerialNum(QString &_name, QString &_serialnum)
Get the dvd title and serial num.
QMap< uint, QList< uint64_t > > m_chapterMap
int32_t GetLastEvent(void) const
void PlayTitleAndPart(int _title, int _part)
virtual bool IsSeekingAllowed(void)
int64_t GetEndPTS() const
Definition: dvdringbuffer.h:41
QString m_serialnumber
bool IsValid(void) const
Definition: dvdringbuffer.h:73
int64_t GetSeqEndPTS() const
Definition: dvdringbuffer.h:42
float GetAspectOverride(void)
int GetNumAngles(void)
Implements a file/stream reader/writer.
bool IsInMenu(void) const override
long long Seek(long long pos, int whence, bool has_lock=false)
Seeks to a particular position in the file.
Definition: ringbuffer.cpp:510
int64_t GetCurrentTime(void)
void UnblockReading(void)
int GetTitle(void) const
bool AudioStreamsChanged(void) const
virtual bool HandleAction(const QStringList &, int64_t)