diff options
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) { |