summaryrefslogtreecommitdiff
path: root/dvbapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'dvbapi.c')
-rw-r--r--dvbapi.c925
1 files changed, 10 insertions, 915 deletions
diff --git a/dvbapi.c b/dvbapi.c
index 314d91f..55bc573 100644
--- a/dvbapi.c
+++ b/dvbapi.c
@@ -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(&sector, 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) {