diff options
author | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2002-02-24 18:00:00 +0100 |
---|---|---|
committer | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2002-02-24 18:00:00 +0100 |
commit | fb8e7fa302ef8a73feb6958b0cb32cc54f76e677 (patch) | |
tree | 74cf9dd5cd1892aaf1c05db32796eb356d7bc860 /dvbapi.c | |
parent | a1da0e5c5de55009716e2c327dda16c61c1dae83 (diff) | |
download | vdr-patch-lnbsharing-fb8e7fa302ef8a73feb6958b0cb32cc54f76e677.tar.gz vdr-patch-lnbsharing-fb8e7fa302ef8a73feb6958b0cb32cc54f76e677.tar.bz2 |
Version 1.0.0pre1vdr-1.0.0pre1
- Added scanning for EPG data for another 4 days on channels that support this
(thanks to Oleg Assovski).
- Removed '#define VFAT 1' from recording.c (was a leftover from testing).
- Fixed the "Low disk space!" message (thanks to Sergei Haller).
- Added the TPID to Hessen-3 in 'channels.conf' (thanks to Sergei Haller).
- Fixed a crash when replaying with DEBUG_OSD=1 (thanks to Stefan Huelswitt).
- Implemented the "First day" parameter for repeating timers. See FORMATS for
information about the enhanced 'timers.conf' file format, and MANUAL for
a description of the new item in the "Edit Timer" menu and the enhanced
functionality of the "Blue" button in the "Timers" menu.
- When deleting a recording that is currently still being recorded, the related
timer will now automatically be terminated. If this is a repeating timer, it
will receive a "First day" setting that skips the timer for this day.
- Fixed closing all unused file descriptors when opening a pipe (thanks to
Werner Fink).
- Instant recordings now take the EPG data from the point in time at 5 minutes
from the start time of the recording. In order for this to work the 'active'
parameter of a timer now uses the second bit to indicate that this is an
"instant" recording (see FORMATS for details).
- Fixed the SVDRP GRAB command in case the video device can't be opened (thanks
to Adrian Stabiszewski).
- At startup the data written into 'epg.data' is now read into the EPG data
structures. In order for this to work, the 'E' record has been extended to
(optionally) contain the 'table ID' (see FORMATS for details).
- The new SVDRP command PUTE can be used to put EPG data into the EPG list.
See FORMATS for details about the required data format.
- Taking the German umlauts 'as is' when compiled with VFAT.
- The new Setup parameter RecordDolbyDigital can be used to generally turn off
recording the Dolby Digital audio channels in case you want to save disk space
or don't have the equipment to replay Dolby Digital audio.
- Reading the 'setup.conf' file no longer terminates in case of an error, but
rather attempts to read the rest of the file.
- Removed DVD support from the core VDR source, since the current version from
Andreas Schultz is already much further developed (DVD menu navigation) and
the concept of "additional players" in VDR is going to change in version 1.1.0,
where a new "plugin" interface shall allow the easy implementation of new
players without having to patch the core VDR source. Until then, Andreas has
agreed to provide his DVD support as a completely external patch.
- The contents of the distribution archive now contains the directory name with
the current version number, as in 'vdr-1.0.0pre1/...' in order to avoid
inadvertently overwriting an existing VDR directory with a new version.
- Added a missing error message in SVDRP command LSTC in case the given channel
can't be found.
Diffstat (limited to 'dvbapi.c')
-rw-r--r-- | dvbapi.c | 925 |
1 files changed, 10 insertions, 915 deletions
@@ -4,14 +4,9 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * DVD support initially written by Andreas Schultz <aschultz@warp10.net> - * based on dvdplayer-0.5 by Matjaz Thaler <matjaz.thaler@guest.arnes.si> - * - * $Id: dvbapi.c 1.147 2002/02/02 13:04:00 kls Exp $ + * $Id: dvbapi.c 1.152 2002/02/24 12:53:51 kls Exp $ */ -//#define DVDDEBUG 1 - #include "dvbapi.h" #include <dirent.h> #include <errno.h> @@ -26,13 +21,6 @@ extern "C" { #include <sys/stat.h> #include <sys/time.h> #include <unistd.h> - -#ifdef DVDSUPPORT -extern "C" { -#include "ac3dec/ac3.h" -} -#endif //DVDSUPPORT - #include "config.h" #include "recording.h" #include "remux.h" @@ -1320,865 +1308,6 @@ bool cReplayBuffer::NextFile(uchar FileNumber, int FileOffset) return replayFile >= 0; } -#ifdef DVDSUPPORT - -#define SYSTEM_HEADER 0xBB -#define PROG_STREAM_MAP 0xBC -#ifndef PRIVATE_STREAM1 -#define PRIVATE_STREAM1 0xBD -#endif -#define PADDING_STREAM 0xBE -#ifndef PRIVATE_STREAM2 -#define PRIVATE_STREAM2 0xBF -#endif -#define AUDIO_STREAM_S 0xC0 -#define AUDIO_STREAM_E 0xDF -#define VIDEO_STREAM_S 0xE0 -#define VIDEO_STREAM_E 0xEF -#define ECM_STREAM 0xF0 -#define EMM_STREAM 0xF1 -#define DSM_CC_STREAM 0xF2 -#define ISO13522_STREAM 0xF3 -#define PROG_STREAM_DIR 0xFF - -#define cOPENDVD 0 -#define cOPENTITLE 1 -#define cOPENCHAPTER 2 -#define cOUTCELL 3 -#define cREADFRAME 4 -#define cOUTPACK 5 -#define cOUTFRAMES 6 - -// --- cAC3toPCM ------------------------------------------------------------- - -class cAC3toPCM { -private: - enum { AC3_STOP, AC3_START, AC3_PLAY } ac3stat; - uchar *ac3data; - int ac3inp; - int ac3outp; -public: - cAC3toPCM(void); - ~cAC3toPCM(); - void Clear(void); - void Put(unsigned char *sector, int length); - cFrame *Get(int size, uchar PTSflags = 0, uchar *PTSdata = 0); - }; - -cAC3toPCM::cAC3toPCM(void) -{ - ac3dec_init(); - ac3data = new uchar[AC3_BUFFER_SIZE]; - Clear(); -} - -cAC3toPCM::~cAC3toPCM() -{ - delete ac3data; -} - -void cAC3toPCM::Clear(void) -{ - ac3stat = AC3_START; - ac3outp = ac3inp = 0; -} - -void cAC3toPCM::Put(unsigned char *sector, int length) -{ - ac3dec_decode_data(sector, sector + length, ac3stat == AC3_START, &ac3inp, &ac3outp, (char *)ac3data); - ac3stat = AC3_PLAY; -} - -// data=PCM samples, 16 bit, LSB first, 48kHz, stereo -cFrame *cAC3toPCM::Get(int size, uchar PTSflags, uchar *PTSdata) -{ - if (ac3inp == ac3outp) - return NULL; - -#define MAXSIZE 2022 - - uchar buffer[2048]; - uchar *data; - - if (size > 0) { - int p_size = (size > MAXSIZE) ? MAXSIZE : size; - int length = 10; // default header bytes - int header = 0; - - switch (PTSflags) { - case 2: header = 5; // additional header bytes - break; - case 3: header = 10; - break; - default: header = 0; - } - - length += header; - - buffer[0] = 0x00; - buffer[1] = 0x00; - buffer[2] = 0x01; - buffer[3] = PRIVATE_STREAM1; - - buffer[6] = 0x80; - buffer[7] = PTSflags << 6; - buffer[8] = header; - - if (header) - memcpy(&buffer[9], (void *)PTSdata, header); - - // add data - data = buffer + 9 + header + 7; - int cnt = 0; - while (p_size) { - if (ac3outp != ac3inp) { // data in the buffer - data[cnt ^ 1] = ac3data[ac3outp]; // swab because ac3dec delivers wrong byteorder (the "xor" (^) is a swab!) - p_size--; - cnt++; - length++; - ac3outp = (ac3outp + 1) % AC3_BUFFER_SIZE; - } - else - break; - } - - data = buffer + 9 + header; - data[0] = aLPCM; // substream ID - data[1] = 0x00; // other stuff (see DVB specs), ignored by driver - data[2] = 0x00; - data[3] = 0x00; - data[4] = 0x00; - data[5] = 0x00; - data[6] = 0x00; - - buffer[4] = (length >> 8) & 0xff; - buffer[5] = length & 0xff; - - length += 6; - - return new cFrame(buffer, length); - } - return NULL; -} - -// --- cDVDplayBuffer -------------------------------------------------------- - -class cDVDplayBuffer : public cPlayBuffer { -private: - cAC3toPCM AC3toPCM; - uchar audioTrack; - - cDVD *dvd;//XXX necessary??? - - int titleid; - int chapid; - int angle; - dvd_file_t *title; - ifo_handle_t *vmg_file; - ifo_handle_t *vts_file; - - int doplay; - int cyclestate; - int prevcycle; - int skipCnt; - - tt_srpt_t *tt_srpt; - vts_ptt_srpt_t *vts_ptt_srpt; - pgc_t *cur_pgc; - dsi_t dsi_pack; - unsigned int next_vobu; - unsigned int prev_vobu; - unsigned int next_ilvu_start; - unsigned int cur_output_size; - unsigned int min_output_size; - unsigned int pktcnt; - int pgc_id; - int start_cell; - int next_cell; - int prev_cell; - int cur_cell; - unsigned int cur_pack; - int ttn; - int pgn; - - uchar *data; - - int logAudioTrack; - int maxAudioTrack; - - int is_nav_pack(unsigned char *buffer); - void Close(void); - virtual void Empty(bool Block = false); - int decode_packet(unsigned char *sector, bool trickmode); - int ScanVideoPacket(const uchar *Data, int Count, uchar *PictureType); - bool PacketStart(uchar **Data, int len); - int GetPacketType(const uchar *Data); - int GetStuffingLen(const uchar *Data); - int GetPacketLength(const uchar *Data); - int GetPESHeaderLength(const uchar *Data); - void handleAC3(unsigned char *sector, int length, uchar PTSflags, uchar *PTSdata); - unsigned int getAudioStream(unsigned int StreamId); - void setChapid(void); - void NextState(int State) { prevcycle = cyclestate; cyclestate = State; } -protected: - virtual void Input(void); -public: - cDVDplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, cDVD *DvD, int title); - virtual ~cDVDplayBuffer(); - virtual int SkipFrames(int Frames); - virtual void SkipSeconds(int Seconds); - virtual void Goto(int Position, bool Still = false); - virtual void GetIndex(int &Current, int &Total, bool SnapToIFrame = false); - virtual void ToggleAudioTrack(void); - }; - -cDVDplayBuffer::cDVDplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, cDVD *DvD, int title) -:cPlayBuffer(DvbApi, VideoDev, AudioDev) -{ - dvd = DvD; - titleid = title; - chapid = 0; - angle = 0; - cyclestate = cOPENDVD; - prevcycle = 0; - skipCnt = 0; - logAudioTrack = 0; - canToggleAudioTrack = true;//XXX determine from cDVD! - data = new uchar[1024 * DVD_VIDEO_LB_LEN]; - canDoTrickMode = true; - skipAC3bytes = true; - dvbApi->SetModeReplay(); - Start(); -} - -cDVDplayBuffer::~cDVDplayBuffer() -{ - Stop(); - Close(); - dvbApi->SetModeNormal(false); - delete data; -} - -unsigned int cDVDplayBuffer::getAudioStream(unsigned int StreamId) -{ - if (cyclestate < cOPENCHAPTER || StreamId > 7) - return 0; - if (!(cur_pgc->audio_control[StreamId] & 0x8000)) - return 0; - int track = (cur_pgc->audio_control[StreamId] >> 8) & 0x07; - return dvd->getAudioTrack(track) | track; -} - -void cDVDplayBuffer::ToggleAudioTrack(void) -{ - unsigned int newTrack; - - if (CanToggleAudioTrack() && maxAudioTrack != 0) { - logAudioTrack = (logAudioTrack + 1) % maxAudioTrack; - if ((newTrack = getAudioStream(logAudioTrack)) != 0) - audioTrack = newTrack; -#ifdef DVDDEBUG - dsyslog(LOG_INFO, "DVB: Audio Stream ID changed to: %x", audioTrack); -#endif - AC3toPCM.Clear(); - } -} - -/** - * Returns true if the pack is a NAV pack. This check is clearly insufficient, - * and sometimes we incorrectly think that valid other packs are NAV packs. I - * need to make this stronger. - */ -inline int cDVDplayBuffer::is_nav_pack(unsigned char *buffer) -{ - return buffer[41] == 0xbf && buffer[1027] == 0xbf; -} - -void cDVDplayBuffer::Input(void) -{ - dsyslog(LOG_INFO, "input thread started (pid=%d)", getpid()); - - doplay = true; - while (Busy() && doplay) { - if (blockInput) { - if (blockInput > 1) - blockInput = 1; - continue; - } - - //BEGIN: ripped from play_title - - /** - * Playback by cell in this pgc, starting at the cell for our chapter. - */ - - //dsyslog(LOG_INFO, "DVD: cyclestate: %d", cyclestate); - switch (cyclestate) { - - case cOPENDVD: // open the DVD and get all the basic information - { - if (!dvd->isValid()) { - doplay = false; - break; - } - - /** - * Load the video manager to find out the information about the titles on - * this disc. - */ - vmg_file = dvd->openVMG(); - if (!vmg_file) { - esyslog(LOG_ERR, "ERROR: can't open VMG info"); - doplay = false; - break; - } - tt_srpt = vmg_file->tt_srpt; - - NextState(cOPENTITLE); - break; - } - - case cOPENTITLE: // open the selected title - { - /** - * Make sure our title number is valid. - */ - isyslog(LOG_INFO, "DVD: there are %d titles on this DVD", tt_srpt->nr_of_srpts); - if (titleid < 0 || titleid >= tt_srpt->nr_of_srpts) { - esyslog(LOG_ERR, "ERROR: invalid title %d", titleid + 1); - doplay = false; - break; - } - - /** - * Load the VTS information for the title set our title is in. - */ - vts_file = dvd->openVTS(tt_srpt->title[titleid].title_set_nr); - if (!vts_file) { - esyslog(LOG_ERR, "ERROR: can't open the title %d info file", tt_srpt->title[titleid].title_set_nr); - doplay = false; - break; - } - - NextState(cOPENCHAPTER); - break; - } - - case cOPENCHAPTER: - { - /** - * Make sure the chapter number is valid for this title. - */ - isyslog(LOG_INFO, "DVD: there are %d chapters in this title", tt_srpt->title[titleid].nr_of_ptts); - if (chapid < 0 || chapid >= tt_srpt->title[titleid].nr_of_ptts) { - esyslog(LOG_ERR, "ERROR: invalid chapter %d", chapid + 1); - doplay = false; - break; - } - - /** - * Determine which program chain we want to watch. This is based on the - * chapter number. - */ - ttn = tt_srpt->title[titleid].vts_ttn; - vts_ptt_srpt = vts_file->vts_ptt_srpt; - pgc_id = vts_ptt_srpt->title[ttn - 1].ptt[chapid].pgcn; - pgn = vts_ptt_srpt->title[ttn - 1].ptt[chapid].pgn; - cur_pgc = vts_file->vts_pgcit->pgci_srp[pgc_id - 1].pgc; - start_cell = cur_pgc->program_map[pgn - 1] - 1; - - /** - * setup Audio information - **/ - for (maxAudioTrack = 0; maxAudioTrack < 8; maxAudioTrack++) { - if (!(cur_pgc->audio_control[maxAudioTrack] & 0x8000)) - break; - } - canToggleAudioTrack = (maxAudioTrack > 0); - // init the AudioInformation - audioTrack = getAudioStream(logAudioTrack); -#ifdef DVDDEBUG - dsyslog(LOG_INFO, "DVD: max: %d, track: %x", maxAudioTrack, audioTrack); -#endif - - /** - * We've got enough info, time to open the title set data. - */ - title = dvd->openTitle(tt_srpt->title[titleid].title_set_nr, DVD_READ_TITLE_VOBS); - if (!title) { - esyslog(LOG_ERR, "ERROR: can't open title VOBS (VTS_%02d_1.VOB).", tt_srpt->title[titleid].title_set_nr); - doplay = false; - break; - } - - /** - * Playback by cell in this pgc, starting at the cell for our chapter. - */ - next_cell = start_cell; - prev_cell = start_cell; - cur_cell = start_cell; - - NextState(cOUTCELL); - break; - } - - case cOUTCELL: - { -#ifdef DVDDEBUG - dsyslog(LOG_INFO, "DVD: new cell: %d", cur_cell); - dsyslog(LOG_INFO, "DVD: vob_id: %x, cell_nr: %x", cur_pgc->cell_position[cur_cell].vob_id_nr, cur_pgc->cell_position[cur_cell].cell_nr); -#endif - - if (cur_cell < 0) { - cur_cell = 0; - Backward(); - } - doplay = (cur_cell < cur_pgc->nr_of_cells); - if (!doplay) - break; - - /* Check if we're entering an angle block. */ - if (cur_pgc->cell_playback[cur_cell].block_type == BLOCK_TYPE_ANGLE_BLOCK) { - cur_cell += angle; - for (int i = 0; ; ++i) { - if (cur_pgc->cell_playback[cur_cell + i].block_mode == BLOCK_MODE_LAST_CELL) { - next_cell = cur_cell + i + 1; - break; - } - } - } - else { - next_cell = cur_cell + 1; - prev_cell = cur_cell - 1; - } - - // init settings for next state - if (playDir == pdForward) - cur_pack = cur_pgc->cell_playback[cur_cell].first_sector; - else - cur_pack = cur_pgc->cell_playback[cur_cell].last_vobu_start_sector; - - NextState(cOUTPACK); - break; - } - - case cOUTPACK: - { -#ifdef DVDDEBUG - dsyslog(LOG_INFO, "DVD: new pack: %d", cur_pack); -#endif - /** - * We loop until we're out of this cell. - */ - - if (playDir == pdForward) { - if (cur_pack >= cur_pgc->cell_playback[cur_cell].last_sector) { - cur_cell = next_cell; -#ifdef DVDDEBUG - dsyslog(LOG_INFO, "DVD: end of pack"); -#endif - NextState(cOUTCELL); - break; - } - } - else { -#ifdef DVDDEBUG - dsyslog(LOG_INFO, "DVD: prev: %d, curr: %x, next: %x, prev: %x", prevcycle, cur_pack, next_vobu, prev_vobu); -#endif - if ((cur_pack & 0x80000000) != 0) { - cur_cell = prev_cell; -#ifdef DVDDEBUG - dsyslog(LOG_INFO, "DVD: start of pack"); -#endif - NextState(cOUTCELL); - break; - } - } - - /** - * Read NAV packet. - */ - int len = DVDReadBlocks(title, cur_pack, 1, data); - if (len == 0) { - esyslog(LOG_ERR, "ERROR: read failed for block %d", cur_pack); - doplay = false; - break; - } - if (!is_nav_pack(data)) { - esyslog(LOG_ERR, "ERROR: no nav_pack"); - return; - } - - /** - * Parse the contained dsi packet. - */ - navRead_DSI(&dsi_pack, &(data[DSI_START_BYTE])); - if (cur_pack != dsi_pack.dsi_gi.nv_pck_lbn) { - esyslog(LOG_ERR, "ERROR: cur_pack != dsi_pack.dsi_gi.nv_pck_lbn"); - return; - } - // navPrint_DSI(&dsi_pack); - - /** - * Determine where we go next. These values are the ones we mostly - * care about. - */ - next_ilvu_start = cur_pack + dsi_pack.sml_agli.data[angle].address; - cur_output_size = dsi_pack.dsi_gi.vobu_ea; - min_output_size = dsi_pack.dsi_gi.vobu_1stref_ea; - - /** - * If we're not at the end of this cell, we can determine the next - * VOBU to display using the VOBU_SRI information section of the - * DSI. Using this value correctly follows the current angle, - * avoiding the doubled scenes in The Matrix, and makes our life - * really happy. - * - * Otherwise, we set our next address past the end of this cell to - * force the code above to go to the next cell in the program. - */ - if (dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL) - next_vobu = cur_pack + (dsi_pack.vobu_sri.next_vobu & 0x7fffffff); - else - next_vobu = cur_pack + cur_output_size + 1; - - if (dsi_pack.vobu_sri.prev_vobu != SRI_END_OF_CELL) - prev_vobu = cur_pack - (dsi_pack.vobu_sri.prev_vobu & 0x7fffffff); - else { -#ifdef DVDDEBUG - dsyslog(LOG_INFO, "DVD: cur: %x, prev: %x", cur_pack, dsi_pack.vobu_sri.prev_vobu); -#endif - prev_vobu = 0x80000000; - } - -#ifdef DVDDEBUG - dsyslog(LOG_INFO, "DVD: curr: %x, next: %x, prev: %x", cur_pack, next_vobu, prev_vobu); -#endif - if (cur_output_size >= 1024) { - esyslog(LOG_ERR, "ERROR: cur_output_size >= 1024"); - return; - } - cur_pack++; - - NextState(cREADFRAME); - break; - } - - case cREADFRAME: - { - bool trickMode = (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)); - - /* FIXME: - * the entire trickMode code relies on the assumtion - * that there is only one I-FRAME per PACK - * - * I have no clue wether that is correct or not !!! - */ - if (trickMode && (skipCnt++ % 4 != 0)) { - cur_pack = (playDir == pdForward) ? next_vobu : prev_vobu; - NextState(cOUTPACK); - break; - } - - if (trickMode) - cur_output_size = min_output_size; - - /** - * Read in cursize packs. - */ -#ifdef DVDDEBUG - dsyslog(LOG_INFO, "DVD: read pack: %d", cur_pack); -#endif - int len = DVDReadBlocks(title, cur_pack, cur_output_size, data); - if (len != (int)cur_output_size) { - esyslog(LOG_ERR, "ERROR: read failed for %d blocks at %d", cur_output_size, cur_pack); - doplay = false; - break; - } - pktcnt = 0; - NextState(cOUTFRAMES); - break; - } - - case cOUTFRAMES: - { - bool trickMode = (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)); - - /** - * Output cursize packs. - */ - if (pktcnt >= cur_output_size) { - cur_pack = next_vobu; - NextState(cOUTPACK); - break; - } - //dsyslog(LOG_INFO, "DVD: pack: %d, frame: %d", cur_pack, pktcnt); - - if (decode_packet(&data[pktcnt * DVD_VIDEO_LB_LEN], trickMode) != 1) { //we've got a video packet - if (trickMode) { - //dsyslog(LOG_INFO, "DVD: did pack: %d", pktcnt); - cur_pack = (playDir == pdForward) ? next_vobu : prev_vobu; - NextState(cOUTPACK); - break; - } - } - - pktcnt++; - - if (pktcnt >= cur_output_size) { - cur_pack = next_vobu; - NextState(cOUTPACK); - break; - } - break; - } - - default: - { - esyslog(LOG_ERR, "ERROR: cyclestate %d not known", cyclestate); - return; - } - } - - // dsyslog(LOG_INF, "DVD: new cyclestate: %d, pktcnt: %d, cur: %d", cyclestate, pktcnt, cur_output_size); - } - - dsyslog(LOG_INFO, "input thread ended (pid=%d)", getpid()); -} - -#define NO_PICTURE 0 -#define SC_PICTURE 0x00 - -inline bool cDVDplayBuffer::PacketStart(uchar **Data, int len) -{ - while (len > 6 && !((*Data)[0] == 0x00 && (*Data)[1] == 0x00 && (*Data)[2] == 0x01)) - (*Data)++; - return ((*Data)[0] == 0x00 && (*Data)[1] == 0x00 && (*Data)[2] == 0x01); -} - -inline int cDVDplayBuffer::GetPacketType(const uchar *Data) -{ - return Data[3]; -} - -inline int cDVDplayBuffer::GetStuffingLen(const uchar *Data) -{ - return Data[13] & 0x07; -} - -inline int cDVDplayBuffer::GetPacketLength(const uchar *Data) -{ - return (Data[4] << 8) + Data[5] + 6; -} - -inline int cDVDplayBuffer::GetPESHeaderLength(const uchar *Data) -{ - return (Data[8]); -} - -int cDVDplayBuffer::ScanVideoPacket(const uchar *Data, int Count, uchar *PictureType) -{ - // Scans the video packet starting at Offset and returns its length. - // If the return value is -1 the packet was not completely in the buffer. - - int Length = GetPacketLength(Data); - if (Length > 0 && Length <= Count) { - int i = 8; // the minimum length of the video packet header - i += Data[i] + 1; // possible additional header bytes - for (; i < Length; i++) { - if (Data[i] == 0 && Data[i + 1] == 0 && Data[i + 2] == 1) { - switch (Data[i + 3]) { - case SC_PICTURE: *PictureType = (uchar)(Data[i + 5] >> 3) & 0x07; - return Length; - } - } - } - PictureType = NO_PICTURE; - return Length; - } - return -1; -} - -void cDVDplayBuffer::handleAC3(unsigned char *sector, int length, uchar PTSflags, uchar *PTSdata) -{ -#define PCM_FRAME_SIZE 1536 - AC3toPCM.Put(sector, length); - cFrame *frame; - if (ac3_buffersize() <= 100) { - if ((frame = AC3toPCM.Get(PCM_FRAME_SIZE, PTSflags, PTSdata)) != NULL) - putFrame(frame); - } - while ((frame = AC3toPCM.Get(PCM_FRAME_SIZE)) != NULL) - putFrame(frame); -} - -int cDVDplayBuffer::decode_packet(unsigned char *sector, bool trickMode) -{ - //XXX kls 2001-11-03: do we really need all these different return values? - uchar pt = 1; - - //make sure we got a PS packet header - if (!PacketStart(§or, DVD_VIDEO_LB_LEN) && GetPacketType(sector) != 0xBA) { - esyslog(LOG_ERR, "ERROR: got unexpected packet: %x %x %x %x", sector[0], sector[1], sector[2], sector[3]); - return -1; - } - - int offset = 14 + GetStuffingLen(sector); - sector += offset; - int r = DVD_VIDEO_LB_LEN - offset; - int datalen = r; - - sector[6] &= 0x8f; - uchar PTSflags = sector[7] >> 6; - uchar *PTSdata = sector + 9; - uchar *data = sector; - - switch (GetPacketType(sector)) { - case VIDEO_STREAM_S ... VIDEO_STREAM_E: - { - ScanVideoPacket(sector, r, &pt); - if (trickMode && pt != 1) - return pt; - putFrame(sector, r, ftVideo); - break; - } - case AUDIO_STREAM_S ... AUDIO_STREAM_E: { - // no sound in trick mode - if (trickMode) - return 1; - if (audioTrack != GetPacketType(sector)) - return 5; - putFrame(sector, r, ftAudio); - break; - } - case PRIVATE_STREAM1: - { - datalen = GetPacketLength(sector); - //skip optional Header bytes - datalen -= GetPESHeaderLength(sector); - data += GetPESHeaderLength(sector); - //skip mandatory header bytes - data += 3; - //fallthrough is intended - } - case PRIVATE_STREAM2: - { - //FIXME: Stream1 + Stream2 is ok, but is Stream2 alone also? - - // no sound in trick mode - if (trickMode) - return 1; - - // skip PS header bytes - data += 6; - // data now points to the beginning of the payload - - if (audioTrack == *data) { - switch (audioTrack & 0xF8) { - case aAC3: - if (dolbyDev) - putFrame(sector, r, ftDolby); - data += 4; - datalen -= 13; // 3 (mandatory header) + 6 (PS header) + 4 (AC3 header) = 13 - handleAC3(data, datalen, PTSflags, PTSdata); - break; - case aLPCM: - // write(audio, sector+14 , sector[19]+(sector[18]<<8)+6); - putFrame(sector, GetPacketLength(sector), ftAudio); - break; - default: - break; - } - } - return pt; - } - default: - case SYSTEM_HEADER: - case PROG_STREAM_MAP: - { - esyslog(LOG_ERR, "ERROR: don't know what to do - packetType: %x", GetPacketType(sector)); - // just skip them for now,l but try to debug it - dsyslog(LOG_INFO, "DVD: curr cell: %8x, Nr of cells: %8x", cur_cell, cur_pgc->nr_of_cells); - dsyslog(LOG_INFO, "DVD: curr pack: %8x, last sector: %8x", cur_pack, cur_pgc->cell_playback[cur_cell].last_sector); - dsyslog(LOG_INFO, "DVD: curr pkt: %8x, output size: %8x", pktcnt, cur_output_size); -#if 0 - // looks like my DVD is/was brocken ....... - for (int n = 0; n <= 255; n++) { - dsyslog(LOG_INFO, "%4x %2x %2x %2x %2x %2x %2x %2x %2x", n * 8, - osect[n * 8 + 0], osect[n * 8 + 1], osect[n * 8 + 2], osect[n * 8 + 3], - osect[n * 8 + 4], osect[n * 8 + 5], osect[n * 8 + 6], osect[n * 8 + 7]); - } - return 0; -#endif - return pt; - } - } - return pt; -} - -void cDVDplayBuffer::Empty(bool Block) -{ - if (!(blockInput || blockOutput)) { - cPlayBuffer::Empty(true); - AC3toPCM.Clear(); - } - if (!Block) - cPlayBuffer::Empty(false); -} - -void cDVDplayBuffer::Close(void) -{ - dvd->Close(); -} - -int cDVDplayBuffer::SkipFrames(int Frames) -{ - return -1; -} - -/* Figure out the correct pgN from the cell and update state. */ -void cDVDplayBuffer::setChapid(void) -{ - int new_pgN = 0; - - while (new_pgN < cur_pgc->nr_of_programs && cur_cell >= cur_pgc->program_map[new_pgN]) - new_pgN++; - - if (new_pgN == cur_pgc->nr_of_programs) { /* We are at the last program */ - if (cur_cell > cur_pgc->nr_of_cells) - chapid = 1; /* We are past the last cell */ - } - - chapid = new_pgN; -} - -void cDVDplayBuffer::SkipSeconds(int Seconds) -{ - if (Seconds) { - setChapid(); - int newchapid = Seconds > 0 ? chapid + 1 : chapid - 1; - - if (newchapid >= 0 && newchapid < tt_srpt->title[titleid].nr_of_ptts) { - Empty(true); - chapid = newchapid; - NextState(cOPENCHAPTER); - AC3toPCM.Clear(); - Empty(false); - Play(); - } - } -} - -void cDVDplayBuffer::Goto(int Index, bool Still) -{ -} - -void cDVDplayBuffer::GetIndex(int &Current, int &Total, bool SnapToIFrame) -{ - Current = Total = -1; -} -#endif //DVDSUPPORT - // --- cTransferBuffer ------------------------------------------------------- class cTransferBuffer : public cRingBufferLinear { @@ -2732,18 +1861,11 @@ void cDvbApi::Cleanup(void) PrimaryDvbApi = NULL; } -const cSchedules *cDvbApi::Schedules(cThreadLock *ThreadLock) const -{ - if (siProcessor && ThreadLock->Lock(siProcessor)) - return siProcessor->Schedules(); - return NULL; -} - bool cDvbApi::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY) { - int result = 0; - int videoDev = OstOpen(DEV_VIDEO, CardIndex(), O_RDWR); + int videoDev = OstOpen(DEV_VIDEO, CardIndex(), O_RDWR, true); if (videoDev >= 0) { + int result = 0; struct video_mbuf mbuf; result |= ioctl(videoDev, VIDIOCGMBUF, &mbuf); if (result == 0) { @@ -2827,8 +1949,9 @@ bool cDvbApi::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, result |= 1; } close(videoDev); + return result == 0; } - return result == 0; + return false; } #ifdef DEBUG_OSD @@ -3017,7 +2140,9 @@ void cDvbApi::Text(int x, int y, const char *s, eDvbColor colorFg, eDvbColor col void cDvbApi::Flush(void) { -#ifndef DEBUG_OSD +#ifdef DEBUG_OSD + refresh(); +#else if (osd) osd->Flush(); #endif @@ -3106,9 +2231,9 @@ bool cDvbApi::SetPids(bool ForRecording) { return SetVpid(vPid, ForRecording ? DMX_OUT_TS_TAP : DMX_OUT_DECODER) && SetApid1(aPid1, ForRecording ? DMX_OUT_TS_TAP : DMX_OUT_DECODER) && - SetApid2(ForRecording ? aPid2 : 0, DMX_OUT_TS_TAP) && + SetApid2(ForRecording ? aPid2 : 0, DMX_OUT_TS_TAP) && (!Setup.RecordDolbyDigital || SetDpid1(ForRecording ? dPid1 : 0, DMX_OUT_TS_TAP) && - SetDpid2(ForRecording ? dPid2 : 0, DMX_OUT_TS_TAP); + SetDpid2(ForRecording ? dPid2 : 0, DMX_OUT_TS_TAP)); } eSetChannelResult cDvbApi::SetChannel(int ChannelNumber, int Frequency, char Polarization, int Diseqc, int Srate, int Vpid, int Apid1, int Apid2, int Dpid1, int Dpid2, int Tpid, int Ca, int Pnr) @@ -3416,36 +2541,6 @@ bool cDvbApi::StartReplay(const char *FileName) return false; } -#ifdef DVDSUPPORT -bool cDvbApi::StartDVDplay(cDVD *dvd, int TitleID) -{ - if (Recording()) { - esyslog(LOG_ERR, "ERROR: StartDVDplay() called while recording - ignored!"); - return false; - } - StopTransfer(); - StopReplay(); - if (fd_video >= 0 && fd_audio >= 0) { - - // Check DeviceName: - - if (!dvd) { - esyslog(LOG_ERR, "ERROR: StartDVDplay: DVD device is (null)"); - return false; - } - - // Create replay buffer: - - replayBuffer = new cDVDplayBuffer(this, fd_video, fd_audio, dvd, TitleID); - if (replayBuffer) - return true; - else - esyslog(LOG_ERR, "ERROR: can't allocate replaying buffer"); - } - return false; -} -#endif //DVDSUPPORT - void cDvbApi::StopReplay(void) { if (replayBuffer) { |