/* * DVD Player plugin for VDR * * Copyright (C) 2001.2002 Andreas Schultz * * This code is distributed under the terms and conditions of the * GNU GENERAL PUBLIC LICENSE. See the file COPYING for details. * */ #ifndef __PLAYER_DVD_H #define __PLAYER_DVD_H #include #include #include #include #include #include #include #include "common-dvd.h" class cDvdPlayer; #include "dvdspu.h" #include "ca52.h" class IntegerListObject : public cListObject { private: int value; public: IntegerListObject() { value=0; } IntegerListObject( const IntegerListObject & v ) { value=v.value; } IntegerListObject( int i ) { value=i; } int getValue() const { return value; } void setValue(int v) { value=v; } virtual bool operator==(const cListObject & ListObject ) const { return value == ((IntegerListObject *)&ListObject)->value; } virtual bool operator<(const cListObject & ListObject ) /* const */ { return value < ((IntegerListObject *)&ListObject)->value; } virtual bool operator>(const cListObject & ListObject ) const { return value > ((IntegerListObject *)&ListObject)->value; } operator int () const { return value; } }; class cDvdPlayerControl ; class cIframeAssembler; class cDVDPlayerResume; class cDvdPlayer : public cPlayer, cThread { private: enum ePlayModes { pmPlay, pmPause, pmSlow, pmFast, pmStill }; enum ePlayDirs { pdForward, pdBackward }; enum ePacketType { pktNone=0, pktVideo=1, pktAudio=2, pktIFrame=4, pktSpu=8 }; cDvdPlayerControl *controller; cSPUassembler SPUassembler; cSpuDecoder *SPUdecoder; A52decoder a52dec; #ifdef NOT_YET cDTSdecoder dtsdec; #endif int hsize; int vsize; int vaspect; cIframeAssembler *iframeAssembler; int IframeCnt; uint8_t * event_buf; cRingBufferFrame *ringBuffer; cFrame *rframe, *pframe; dvdnav_cell_change_event_t lastCellEventInfo ; uint32_t pgcCurrentBlockNum, pgcTotalBlockNum; int64_t pgcTotalTicks; int64_t pgcTicksPerBlock; bool UpdateBlockInfo(void); bool isInMenuDomain; bool isInFeature; int dvd_aspect; int dvd_scaleperm; void UpdateVTSInfo(void); bool skipPlayVideo; int fastWindFactor; uint32_t cntVidBlocksPlayed; uint32_t cntAudBlocksPlayed; int currentNavSubpStream; bool currentNavSubpStreamUsrLocked; bool changeNavSubpStreamOnceInSameCell; cList navSubpStreamSeen; void clearSeenSubpStream(void); void setAllSubpStreams(void); int SearchSubpStream(int SubpStreamId) const; void notifySeenSubpStream( int navSubpStream ); int SetSubpStream(int id); bool GetCurrentNavSubpStreamUsrLocked(void) const ; void SetCurrentNavSubpStreamUsrLocked(bool lock) ; uint32_t stillTimer; dvdnav_t *nav; pci_t *current_pci; int prev_e_ptm; int ptm_offs; uint8_t stillFrame; uint8_t lastFrameType; uint64_t VideoPts; uint64_t stcPTS; uint64_t pktpts; uint64_t stcPTSAudio; uint64_t stcPTSLastAudio; uint64_t pktptsAudio; uint64_t pktptsLastAudio; uint64_t pictureNumber; bool pictureFlip; int currentNavAudioTrack; uint16_t currentNavAudioTrackLangCode; int currentNavAudioTrackType; // aAC3, aDTS, aLPCM, aMPEG int lastNavAudioTrackType; // aAC3, aDTS, aLPCM, aMPEG bool currentNavAudioTrackUsrLocked; cList navAudioTracksSeen; void clearSeenAudioTrack(void); void setAllAudioTracks(void); int notifySeenAudioTrack(int navAudioTrack); int SearchAudioStream(int AudioStreamId) const; bool SetCurrentNavAudioTrackType(int atype); static int Speeds[]; bool running; bool active; ePlayModes playMode; ePlayDirs playDir; int trickSpeed; static const char * dummy_title; static const char * dummy_n_a; char * title_str; char * titleinfo_str; char * aspect_str; void SetTitleString( void ) ; void SetTitleInfoString( void ); void SetAspectString( void ); //player stuff void StillSkip(void); void TrickSpeed(int Increment); void Empty(bool emptyDeviceToo=true); void StripAudioPackets(uchar *b, int Length, uchar Except = 0x00); int Resume(void); bool Save(void); static bool BitStreamOutActive; static bool HasBitStreamOut; static bool SoftDeviceOutActive; // currently used to switch for xine static bool HasSoftDeviceOut; // currently used to switch for xine //dvd stuff int currButtonN; void ClearButtonHighlight(void); void UpdateButtonHighlight(dvdnav_highlight_event_t *hlevt); void DoScaleMode(int &vaspect); cSpuDecoder::eScaleMode getSPUScaleMode(); void SendIframe(bool doSend); int playPacket(unsigned char *&cache_buf, bool trickMode, bool noAudio); void playSPU(int spuId, unsigned char *data, int datalen); uint16_t GetAudioTrackLanguageCode(int channel) const; int GetAudioStreamNumbers(void) const ; uint16_t GetSubtitleLanguageCode(int Channel) const; int GetSubtitleStreamNumbers(void) const ; //resuming /** * the resume database */ cDVDPlayerResume* resume; /** * GetDVDResumeKey(): * computes a (hopefully) unique id for storing the resume data of the current disc. * * this get returns a new allocated memory area .. * must be freed by callee .. */ char* GetDVDResumeKey() const; /** * SaveResume(): * handles everything to save the current position on the disc for later resuming. */ void SaveResume(); /** * LoadResume(): * loads the resume data for the current disc and stores it in the given arguments. * returns false if no resume data for the disc can be found or and error occured while loading. */ bool LoadResume(int& title, int& chapter, int64_t& second); protected: //Player virtual void Activate(bool On); virtual void Action(void); void DeviceReset(void); void DeviceClear(void); void DevicePlay(void); public: /** * returns the CurrentFrame and TotalFrame of the actual PGC ! * the timebase is accurate (BlockNumber/Ticks), but the resulting * "frame" number is calculated using the magic number FRAMESPERSEC ;-) * * optional snap to the next IFrame (not functional now) */ bool GetIndex(int &CurrentFrame, int &TotalFrame, bool SnapToIFrame); bool GetReplayMode(bool &Play, bool &Forward, int &Speed) ; void SetAudioTrack(eTrackType Type, const tTrackId *TrackId); protected: void seenSpuPts(uint64_t pts); uint64_t time_ticks(void); uint64_t delay_ticks(uint64_t ticks); public: static const int MaxAudioTracks; static const int AudioTrackMask; static const int AC3AudioTrackMask; static const int MaxSubpStreams; static const int SubpStreamMask; cDvdPlayer(void); virtual ~cDvdPlayer(); bool Active(void) const { return active ; } bool DVDActiveAndRunning(void) const { return active && nav != NULL && running; } bool DVDRemoveable(void) const { return !active && !running; } void GetAudioLanguageStr(const char **AudioLanguageStr) const ; void GetSubtitleLanguageStr( const char **SubtitleLanguageStr ) const ; // -- control stuff -- void setController (cDvdPlayerControl *ctrl ); bool IsDvdNavigationForced() const ; void DrawSPU(); void HideSPU(); void EmptySPU(); void Pause(void); void Play(void); void Stop(void); void Forward(void); void Backward(void); /** * these getter returns a new allocated memory area .. * must be freed by callee .. */ char *GetTitleString(void) const ; char *GetTitleInfoString(void) const ; char *GetAspectString(void) const ; int GetProgramNumber(void) const ; int GetCellNumber(void) const ; /** * returns the PG (e.g. chapter) lenght in ticks * * 90000 ticks are 1 second, acording to MPEG ! */ int64_t GetPGLengthInTicks(void) ; /** * returns the PGC (e.g. whole title) lenght in ticks * * 90000 ticks are 1 second, acording to MPEG ! */ int64_t GetPGCLengthInTicks(void) ; /** * returns the Ticks and TotalTicks according to the given * BlockNum, TotalBlockNum of the actual PGC ! * * the TotalBlockNum of the actual PGC is fetched ! * * 90000 ticks are 1 second, acording to MPEG ! */ void BlocksToPGCTicks(uint32_t BlockNum, int64_t &Ticks, int64_t &TotalTicks) ; /** * returns the CurrentBlockNum and TotalBlockNum according to the given * Ticks, TotalTicks of the actual PGC ! * * the TotalTicks of the actual PGC is fetched ! * * 90000 ticks are 1 second, acording to MPEG ! */ void PGCTicksToBlocks(int64_t Ticks, uint32_t &BlockNum, uint32_t &TotalBlockNum) ; bool GetPositionInSec(int64_t &CurrentSec, int64_t &TotalSec) ; bool GetPositionInTicks(int64_t &CurrentTicks, int64_t &TotalTicks) ; int getWidth() const { return hsize; } int getHeight() const { return vsize; } int getAspect() const { return vaspect; } /** * we assume FRAMESPERSEC ! */ int SkipFrames(int Frames); void SkipSeconds(int Seconds); /** * set the position of the actual PGC to the given Seconds */ void Goto(int Seconds, bool Still = false); int GotoAngle(int Angle); /** * jump to the next Angle (rotate) */ void NextAngle(void); /** * jump to the next Title (rotate) */ void NextTitle(void); /** * goto to the Title * * return set title .. */ // GotoTitle now optionally takes a chapter to seek to in the given title int GotoTitle(int Title, int Chapter = 1); /** * jump to the previous Title (rotate) */ void PreviousTitle(void); /** * goto to the Part * * return set Part .. */ int GotoPart(int Part); /** * jump to the next Part (rotate) */ void NextPart(void); /** * jump to the previous Part (rotate) */ void PreviousPart(void); /** * jump to the next PG */ void NextPG(void); /** * jump to the previous PG */ void PreviousPG(void); int GetCurrentNavSubpStream(void) const ; int GetCurrentNavSubpStreamIdx(void) const ; int NextSubpStream(); bool GetCurrentNavAudioTrackUsrLocked(void) const ; void SetCurrentNavAudioTrackUsrLocked(bool lock); int GetCurrentNavAudioTrack(void) const ; int GetCurrentNavAudioTrackIdx(void) const ; int GetCurrentNavAudioTrackType(void) const ; // aAC3, aDTS, aLPCM, aMPEG void selectUpButton(void); void selectDownButton(void); void selectLeftButton(void); void selectRightButton(void); void activateButton(void); int callRootMenu(void); int callTitleMenu(void); int callSubpMenu(void); int callAudioMenu(void); bool IsInMenuDomain() const; bool IsInStillFrame() const ; bool IsInMenuDomainOrStillFrame() const ; // -- callbacks -- void seenAPTS(uint64_t pts); void seenVPTS(uint64_t pts); int cbPlayVideo(uchar *Data, int Length); int cbPlayAudio(uchar *Data, int Length); /** * 90000 ticks are 1 second, acording to MPEG ! */ static const char *PTSTicksToHMSm(int64_t ticks, bool WithMS=false); static int64_t PTSTicksToMilliSec(int64_t ticks) { return ticks / 90L; } static int64_t PTSTicksToSec(int64_t ticks) { return ticks / 90000L; } }; #define CIF_MAXSIZE 512 // --- cDvdPlayer --------------------------------------------------- inline bool cDvdPlayer::IsInMenuDomain() const { // return isInMenuDomain; return (current_pci && current_pci->hli.hl_gi.hli_ss); } inline bool cDvdPlayer::IsInStillFrame() const { return stillFrame!=0; } inline bool cDvdPlayer::IsInMenuDomainOrStillFrame() const { return IsInStillFrame()||IsInMenuDomain(); } inline int cDvdPlayer::cbPlayVideo(uchar *Data, int Length) { if (ringBuffer) { cFrame *cbFrame = new cFrame(Data, Length, ftVideo); if(cbFrame && !ringBuffer->Put(cbFrame)) DELETENULL(cbFrame); } return Length; } inline int cDvdPlayer::cbPlayAudio(uchar *Data, int Length) { if (ringBuffer) { cFrame *cbFrame = new cFrame(Data, Length, ftDolby); if(cbFrame && !ringBuffer->Put(cbFrame)) DELETENULL(cbFrame); } return Length; } // --- navigation stuff --- inline void cDvdPlayer::selectUpButton(void) { DEBUGDVD("selectUpButton\n"); if (nav && current_pci) { dvdnav_upper_button_select(nav, current_pci); } } inline void cDvdPlayer::selectDownButton(void) { DEBUGDVD("selectDownButton\n"); if (nav && current_pci) { dvdnav_lower_button_select(nav, current_pci); } } inline void cDvdPlayer::selectLeftButton(void) { DEBUGDVD("selectLeftButton\n"); if (nav && current_pci) { dvdnav_left_button_select(nav, current_pci); } } inline void cDvdPlayer::selectRightButton(void) { DEBUGDVD("selectRightButton\n"); if (nav && current_pci) { dvdnav_right_button_select(nav, current_pci); } } #endif //__PLAYER_DVD_H