diff --git a/FORMATS b/FORMATS index 3a70871e..0f047352 100644 --- a/FORMATS +++ b/FORMATS @@ -128,3 +128,12 @@ Video Disk Recorder File Formats - marks must have a frame number, and that frame MUST be an I-frame (this means that only marks generated by VDR itself can be used, since they will always be guaranteed to mark I-frames). + +* 001.vdr ... 255.vdr + + These are the actual recorded MPEG data files. In order to keep the size of + an individual file below a given limit, a recording is split into several + files. The contents of these files is "Packetized Elementary Stream" (PES) + and contains ES packets with ids 0xE0 for video, 0xC0 for audio 1 and 0xC1 + for audio 2 (if available). + diff --git a/HISTORY b/HISTORY index 855b3011..3617b25d 100644 --- a/HISTORY +++ b/HISTORY @@ -510,3 +510,20 @@ Video Disk Recorder Revision History - Increased timeout until reporting "broken video data stream" when recording. - Modified method of turning off PIDs when switching channel. +- Increased amount of non-useful data received by cRemux before assuming the + recording will fail. +- If there are two audio PIDs defined for a channel, both audio tracks will + now be recorded and can be selectively replayed later. See the FORMATS file + for details on how these different audio tracks are stored in the recorded + files. In order for this to work properly you need to make sure that the + StartHWFilter() function in the driver's 'dvb.c' has + + u16 mode=0x0320; + + instead of the default + + u16 mode=0x0820; + + This will create packets for the second audio track that are small enough + to multiplex smoothly with the video data. + diff --git a/MANUAL b/MANUAL index 9a72c512..06686f14 100644 --- a/MANUAL +++ b/MANUAL @@ -122,6 +122,8 @@ Video Disk Recorder User's Manual to toggle between these. There can be two different audio PIDs per channel, assuming that typically a channel broadcasts a country specific language plus the movie's original soundtrack. + Recordings made form such channels will contain both audio tracks, and when + replaying the desired audio track can be selected the same way. * Switching through channel groups diff --git a/dvbapi.c b/dvbapi.c index a9e52b8f..325d095e 100644 --- a/dvbapi.c +++ b/dvbapi.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbapi.c 1.72 2001/06/14 08:19:43 kls Exp $ + * $Id: dvbapi.c 1.73 2001/06/14 15:10:16 kls Exp $ */ #include "dvbapi.h" @@ -451,14 +451,14 @@ protected: virtual void Input(void); virtual void Output(void); public: - cRecordBuffer(cDvbApi *DvbApi, const char *FileName, dvb_pid_t VPid, dvb_pid_t APid); + cRecordBuffer(cDvbApi *DvbApi, const char *FileName, dvb_pid_t VPid, dvb_pid_t APid1, dvb_pid_t APid2); virtual ~cRecordBuffer(); }; -cRecordBuffer::cRecordBuffer(cDvbApi *DvbApi, const char *FileName, dvb_pid_t VPid, dvb_pid_t APid) +cRecordBuffer::cRecordBuffer(cDvbApi *DvbApi, const char *FileName, dvb_pid_t VPid, dvb_pid_t APid1, dvb_pid_t APid2) :cRingBuffer(VIDEOBUFSIZE, true) ,fileName(FileName, true) -,remux(VPid, APid, true) +,remux(VPid, APid1, APid2, true) { dvbApi = DvbApi; index = NULL; @@ -608,12 +608,14 @@ private: bool eof; int blockInput, blockOutput; bool paused, fastForward, fastRewind; - int lastIndex, stillIndex; + int lastIndex, stillIndex, playIndex; + bool canToggleAudioTrack; + uchar audioTrack; bool NextFile(uchar FileNumber = 0, int FileOffset = -1); void Clear(bool Block = false); void Close(void); int ReadFrame(uchar *b, int Length, int Max); - void StripAudioPackets(uchar *b, int Length); + void StripAudioPackets(uchar *b, int Length, uchar Except = 0x00); void DisplayFrame(uchar *b, int Length); int Resume(void); bool Save(void); @@ -631,6 +633,8 @@ public: void SkipSeconds(int Seconds); void Goto(int Position, bool Still = false); void GetIndex(int &Current, int &Total, bool SnapToIFrame = false); + bool CanToggleAudioTrack(void) { return canToggleAudioTrack; } + void ToggleAudioTrack(void); }; cReplayBuffer::cReplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, const char *FileName) @@ -646,7 +650,9 @@ cReplayBuffer::cReplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, const eof = false; blockInput = blockOutput = false; paused = fastForward = fastRewind = false; - lastIndex = stillIndex = -1; + lastIndex = stillIndex = playIndex = -1; + canToggleAudioTrack = false; + audioTrack = 0xC0; if (!fileName.Name()) return; // Create the index file: @@ -701,12 +707,19 @@ void cReplayBuffer::Input(void) continue; } lastIndex = Index; + playIndex = -1; r = ReadFrame(b, Length, sizeof(b)); - StripAudioPackets(b, Length); + StripAudioPackets(b, r); } else { lastIndex = -1; - r = read(replayFile, b, sizeof(b)); + playIndex = (playIndex >= 0) ? playIndex + 1 : index->Get(fileName.Number(), fileOffset); + uchar FileNumber; + int FileOffset, Length; + if (!(index->Get(playIndex, &FileNumber, &FileOffset, NULL, &Length) && NextFile(FileNumber, FileOffset))) + break; + r = ReadFrame(b, Length, sizeof(b)); + StripAudioPackets(b, r, audioTrack); } if (r > 0) { uchar *p = b; @@ -778,17 +791,20 @@ int cReplayBuffer::ReadFrame(uchar *b, int Length, int Max) return -1; } -void cReplayBuffer::StripAudioPackets(uchar *b, int Length) +void cReplayBuffer::StripAudioPackets(uchar *b, int Length, uchar Except) { for (int i = 0; i < Length - 6; i++) { if (b[i] == 0x00 && b[i + 1] == 0x00 && b[i + 2] == 0x01) { - switch (b[i + 3]) { + uchar c = b[i + 3]; + switch (c) { case 0xC0 ... 0xDF: // audio - { - int n = b[i + 4] * 256 + b[i + 5]; - for (int j = i; j < Length && n--; j++) - b[j] = 0x00; - } + if (c == 0xC1) + canToggleAudioTrack = true; + if (!Except || c != Except) { + int n = b[i + 4] * 256 + b[i + 5]; + for (int j = i; j < Length && n--; j++) + b[j] = 0x00; + } break; case 0xE0 ... 0xEF: // video i += b[i + 4] * 256 + b[i + 5]; @@ -816,6 +832,7 @@ void cReplayBuffer::Clear(bool Block) usleep(1); Lock(); cRingBuffer::Clear(); + playIndex = -1; CHECK(ioctl(videoDev, VIDEO_FREEZE)); CHECK(ioctl(videoDev, VIDEO_CLEAR_BUFFER)); CHECK(ioctl(audioDev, AUDIO_CLEAR_BUFFER)); @@ -969,6 +986,7 @@ void cReplayBuffer::Goto(int Index, bool Still) Index = index->GetNextIFrame(Index, false, &FileNumber, &FileOffset, &Length); if (Index >= 0 && NextFile(FileNumber, FileOffset) && Still) { stillIndex = Index; + playIndex = -1; uchar b[MAXFRAMESIZE]; int r = ReadFrame(b, Length, sizeof(b)); if (r > 0) @@ -977,7 +995,7 @@ void cReplayBuffer::Goto(int Index, bool Still) paused = true; } else - stillIndex = -1; + stillIndex = playIndex = -1; Clear(false); } } @@ -1015,6 +1033,14 @@ bool cReplayBuffer::NextFile(uchar FileNumber, int FileOffset) return replayFile >= 0; } +void cReplayBuffer::ToggleAudioTrack(void) +{ + if (CanToggleAudioTrack()) { + audioTrack = (audioTrack == 0xC0) ? 0xC1 : 0xC0; + Clear(); + } +} + // --- cTransferBuffer ------------------------------------------------------- class cTransferBuffer : public cRingBuffer { @@ -1329,33 +1355,34 @@ cDvbApi::cDvbApi(int n) // Devices that are only present on DVB-C or DVB-S cards: - fd_qamfe = OstOpen(DEV_OST_QAMFE, n, O_RDWR); - fd_qpskfe = OstOpen(DEV_OST_QPSKFE, n, O_RDWR); - fd_sec = OstOpen(DEV_OST_SEC, n, O_RDWR); + fd_qamfe = OstOpen(DEV_OST_QAMFE, n, O_RDWR); + fd_qpskfe = OstOpen(DEV_OST_QPSKFE, n, O_RDWR); + fd_sec = OstOpen(DEV_OST_SEC, n, O_RDWR); // Devices that all DVB cards must have: - fd_demuxv = OstOpen(DEV_OST_DEMUX, n, O_RDWR | O_NONBLOCK, true); - fd_demuxa = OstOpen(DEV_OST_DEMUX, n, O_RDWR | O_NONBLOCK, true); - fd_demuxt = OstOpen(DEV_OST_DEMUX, n, O_RDWR | O_NONBLOCK, true); + fd_demuxv = OstOpen(DEV_OST_DEMUX, n, O_RDWR | O_NONBLOCK, true); + fd_demuxa1 = OstOpen(DEV_OST_DEMUX, n, O_RDWR | O_NONBLOCK, true); + fd_demuxa2 = OstOpen(DEV_OST_DEMUX, n, O_RDWR | O_NONBLOCK, true); + fd_demuxt = OstOpen(DEV_OST_DEMUX, n, O_RDWR | O_NONBLOCK, true); // Devices not present on "budget" cards: - fd_osd = OstOpen(DEV_OST_OSD, n, O_RDWR); - fd_video = OstOpen(DEV_OST_VIDEO, n, O_RDWR | O_NONBLOCK); - fd_audio = OstOpen(DEV_OST_AUDIO, n, O_RDWR | O_NONBLOCK); + fd_osd = OstOpen(DEV_OST_OSD, n, O_RDWR); + fd_video = OstOpen(DEV_OST_VIDEO, n, O_RDWR | O_NONBLOCK); + fd_audio = OstOpen(DEV_OST_AUDIO, n, O_RDWR | O_NONBLOCK); // Devices that may not be available, and are not necessary for normal operation: - videoDev = OstOpen(DEV_VIDEO, n, O_RDWR); + videoDev = OstOpen(DEV_VIDEO, n, O_RDWR); // Devices that will be dynamically opened and closed when necessary: - fd_dvr = -1; + fd_dvr = -1; // We only check the devices that must be present - the others will be checked before accessing them: - if (((fd_qpskfe >= 0 && fd_sec >= 0) || fd_qamfe >= 0) && fd_demuxv >= 0 && fd_demuxa >= 0 && fd_demuxt >= 0) { + if (((fd_qpskfe >= 0 && fd_sec >= 0) || fd_qamfe >= 0) && fd_demuxv >= 0 && fd_demuxa1 >= 0 && fd_demuxa2 >= 0 && fd_demuxt >= 0) { siProcessor = new cSIProcessor(OstName(DEV_OST_DEMUX, n)); if (!dvbApi[0]) // only the first one shall set the system time siProcessor->SetUseTSTime(Setup.SetSystemTime); @@ -2026,7 +2053,8 @@ bool cDvbApi::SetPid(int fd, dmxPesType_t PesType, dvb_pid_t Pid, dmxOutput_t Ou bool cDvbApi::SetPids(bool ForRecording) { return SetVpid(vPid, ForRecording ? DMX_OUT_TS_TAP : DMX_OUT_DECODER) && - SetApid(aPid1, 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); } bool cDvbApi::SetChannel(int ChannelNumber, int FrequencyMHz, char Polarization, int Diseqc, int Srate, int Vpid, int Apid1, int Apid2, int Tpid, int Ca, int Pnr) @@ -2048,9 +2076,10 @@ bool cDvbApi::SetChannel(int ChannelNumber, int FrequencyMHz, char Polarization, // Turn off current PIDs: - SetVpid(0, DMX_OUT_DECODER); - SetApid(0, DMX_OUT_DECODER); - SetTpid(0, DMX_OUT_DECODER); + SetVpid( 0, DMX_OUT_DECODER); + SetApid1(0, DMX_OUT_DECODER); + SetApid2(0, DMX_OUT_DECODER); + SetTpid( 0, DMX_OUT_DECODER); bool ChannelSynced = false; @@ -2110,7 +2139,7 @@ bool cDvbApi::SetChannel(int ChannelNumber, int FrequencyMHz, char Polarization, esyslog(LOG_ERR, "ERROR %d in qpsk get event", res); } else - fprintf(stderr, "ERROR: timeout while tuning\n"); + esyslog(LOG_ERR, "ERROR: timeout while tuning\n"); } else if (fd_qamfe >= 0) { // DVB-C @@ -2137,7 +2166,7 @@ bool cDvbApi::SetChannel(int ChannelNumber, int FrequencyMHz, char Polarization, esyslog(LOG_ERR, "ERROR %d in qam get event", res); } else - fprintf(stderr, "ERROR: timeout while tuning\n"); + esyslog(LOG_ERR, "ERROR: timeout while tuning\n"); } else { esyslog(LOG_ERR, "ERROR: attempt to set channel without DVB-S or DVB-C device"); @@ -2187,28 +2216,6 @@ bool cDvbApi::SetChannel(int ChannelNumber, int FrequencyMHz, char Polarization, return true; } -bool cDvbApi::CanToggleAudioPid(void) -{ - return aPid1 && aPid2 && aPid1 != aPid2; -} - -bool cDvbApi::ToggleAudioPid(void) -{ - if (CanToggleAudioPid()) { - int a = aPid2; - aPid2 = aPid1; - aPid1 = a; - if (transferringFromDvbApi) - return transferringFromDvbApi->ToggleAudioPid(); - else { - if (transferBuffer) - transferBuffer->SetAudioPid(aPid1); - return SetPids(transferBuffer != NULL); - } - } - return false; -} - bool cDvbApi::Transferring(void) { return transferBuffer; @@ -2278,7 +2285,7 @@ bool cDvbApi::StartRecord(const char *FileName, int Ca, int Priority) // Create recording buffer: - recordBuffer = new cRecordBuffer(this, FileName, vPid, aPid1); + recordBuffer = new cRecordBuffer(this, FileName, vPid, aPid1, aPid2); if (recordBuffer) { ca = Ca; @@ -2390,6 +2397,32 @@ void cDvbApi::Goto(int Position, bool Still) replayBuffer->Goto(Position, Still); } +bool cDvbApi::CanToggleAudioTrack(void) +{ + return replayBuffer ? replayBuffer->CanToggleAudioTrack() : (aPid1 && aPid2 && aPid1 != aPid2); +} + +bool cDvbApi::ToggleAudioTrack(void) +{ + if (replayBuffer) { + replayBuffer->ToggleAudioTrack(); + return true; + } + else { + int a = aPid2; + aPid2 = aPid1; + aPid1 = a; + if (transferringFromDvbApi) + return transferringFromDvbApi->ToggleAudioTrack(); + else { + if (transferBuffer) + transferBuffer->SetAudioPid(aPid1); + return SetPids(transferBuffer != NULL); + } + } + return false; +} + // --- cEITScanner ----------------------------------------------------------- cEITScanner::cEITScanner(void) diff --git a/dvbapi.h b/dvbapi.h index e9b59cdc..02211eab 100644 --- a/dvbapi.h +++ b/dvbapi.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbapi.h 1.37 2001/06/03 11:51:30 kls Exp $ + * $Id: dvbapi.h 1.38 2001/06/14 14:54:25 kls Exp $ */ #ifndef __DVBAPI_H @@ -66,11 +66,12 @@ class cDvbApi { friend class cTransferBuffer; private: int videoDev; - int fd_osd, fd_qpskfe, fd_qamfe, fd_sec, fd_dvr, fd_audio, fd_video, fd_demuxa, fd_demuxv, fd_demuxt; + int fd_osd, fd_qpskfe, fd_qamfe, fd_sec, fd_dvr, fd_audio, fd_video, fd_demuxa1, fd_demuxa2, fd_demuxv, fd_demuxt; int vPid, aPid1, aPid2; bool SetPid(int fd, dmxPesType_t PesType, dvb_pid_t Pid, dmxOutput_t Output); bool SetVpid(int Vpid, dmxOutput_t Output) { return SetPid(fd_demuxv, DMX_PES_VIDEO, Vpid, Output); } - bool SetApid(int Apid, dmxOutput_t Output) { return SetPid(fd_demuxa, DMX_PES_AUDIO, Apid, Output); } + bool SetApid1(int Apid, dmxOutput_t Output) { return SetPid(fd_demuxa1, DMX_PES_AUDIO, Apid, Output); } + bool SetApid2(int Apid, dmxOutput_t Output) { return SetPid(fd_demuxa2, DMX_PES_OTHER, Apid, Output); } bool SetTpid(int Tpid, dmxOutput_t Output) { return SetPid(fd_demuxt, DMX_PES_TELETEXT, Tpid, Output); } bool SetPids(bool ForRecording); cDvbApi(int n); @@ -180,8 +181,6 @@ public: bool SetChannel(int ChannelNumber, int FrequencyMHz, char Polarization, int Diseqc, int Srate, int Vpid, int Apid1, int Apid2, int Tpid, int Ca, int Pnr); static int CurrentChannel(void) { return PrimaryDvbApi ? PrimaryDvbApi->currentChannel : 0; } int Channel(void) { return currentChannel; } - bool CanToggleAudioPid(void); - bool ToggleAudioPid(void); // Transfer facilities @@ -262,6 +261,14 @@ public: void Goto(int Index, bool Still = false); // Positions to the given index and displays that frame as a still picture // if Still is true. + + // Audio track facilities + + bool CanToggleAudioTrack(void); + // Returns true if we are currently replaying and this recording has two + // audio tracks, or if the current channel has two audio PIDs. + bool ToggleAudioTrack(void); + // Toggles the audio track if possible. }; class cEITScanner { diff --git a/menu.c b/menu.c index d45ac8dd..78539237 100644 --- a/menu.c +++ b/menu.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.72 2001/06/02 13:51:28 kls Exp $ + * $Id: menu.c 1.73 2001/06/14 14:55:16 kls Exp $ */ #include "menu.h" @@ -1726,7 +1726,7 @@ cMenuMain::cMenuMain(bool Replaying) } if (cVideoCutter::Active()) Add(new cOsdItem(tr(" Cancel editing"), osCancelEdit)); - SetHelp(tr("Record"), cDvbApi::PrimaryDvbApi->CanToggleAudioPid() ? tr("Language") : NULL, NULL, cReplayControl::LastReplayed() ? tr("Resume") : NULL); + SetHelp(tr("Record"), cDvbApi::PrimaryDvbApi->CanToggleAudioTrack() ? tr("Language") : NULL, NULL, cReplayControl::LastReplayed() ? tr("Resume") : NULL); Display(); lastActivity = time(NULL); SetHasHotkeys(); @@ -1761,9 +1761,9 @@ eOSState cMenuMain::ProcessKey(eKeys Key) case kRed: if (!HasSubMenu()) state = osRecord; break; - case kGreen: if (cDvbApi::PrimaryDvbApi->CanToggleAudioPid()) { + case kGreen: if (cDvbApi::PrimaryDvbApi->CanToggleAudioTrack()) { Interface->Clear(); - cDvbApi::PrimaryDvbApi->ToggleAudioPid(); + cDvbApi::PrimaryDvbApi->ToggleAudioTrack(); state = osEnd; } break; diff --git a/remux.c b/remux.c index 1fdb579d..51bd2a4a 100644 --- a/remux.c +++ b/remux.c @@ -8,7 +8,7 @@ * the Linux DVB driver's 'tuxplayer' example and were rewritten to suit * VDR's needs. * - * $Id: remux.c 1.3 2001/06/02 15:39:16 kls Exp $ + * $Id: remux.c 1.4 2001/06/14 15:30:09 kls Exp $ */ /* The calling interface of the 'cRemux::Process()' function is defined @@ -107,6 +107,11 @@ #define IPACKS 2048 +// Start codes: +#define SC_PICTURE 0x00 // "picture header" + +#define MAXNONUSEFULDATA (10*1024*1024) + class cTS2PES { private: int size; @@ -114,6 +119,7 @@ private: int count; uint8_t *buf; uint8_t cid; + uint8_t audioCid; int plength; uint8_t plen[2]; uint8_t flag1; @@ -132,7 +138,7 @@ private: void write_ipack(const uint8_t *Data, int Count); void instant_repack(const uint8_t *Buf, int Count); public: - cTS2PES(uint8_t *ResultBuffer, int *ResultCount, int Size); + cTS2PES(uint8_t *ResultBuffer, int *ResultCount, int Size, uint8_t AudioCid = 0x00); ~cTS2PES(); void ts_to_pes(const uint8_t *Buf); // don't need count (=188) void Clear(void); @@ -140,11 +146,12 @@ public: uint8_t cTS2PES::headr[] = { 0x00, 0x00, 0x01 }; -cTS2PES::cTS2PES(uint8_t *ResultBuffer, int *ResultCount, int Size) +cTS2PES::cTS2PES(uint8_t *ResultBuffer, int *ResultCount, int Size, uint8_t AudioCid) { resultBuffer = ResultBuffer; resultCount = ResultCount; size = Size; + audioCid = AudioCid; if (!(buf = new uint8_t[size])) esyslog(LOG_ERR, "Not enough memory for ts_transform"); @@ -164,7 +171,10 @@ void cTS2PES::Clear(void) void cTS2PES::store(uint8_t *Data, int Count) { - //XXX overflow check??? + if (*resultCount + Count > RESULTBUFFERSIZE) { + esyslog(LOG_ERR, "ERROR: result buffer overflow (%d + %d > %d)", *resultCount, Count, RESULTBUFFERSIZE); + Count = RESULTBUFFERSIZE - *resultCount; + } memcpy(resultBuffer + *resultCount, Data, Count); *resultCount += Count; } @@ -188,7 +198,7 @@ void cTS2PES::send_ipack(void) { if (count < 10) return; - buf[3] = cid; + buf[3] = (AUDIO_STREAM_S <= cid && cid <= AUDIO_STREAM_E && audioCid) ? audioCid : cid; buf[4] = (uint8_t)(((count - 6) & 0xFF00) >> 8); buf[5] = (uint8_t)((count - 6) & 0x00FF); store(buf, count); @@ -409,22 +419,25 @@ void cTS2PES::ts_to_pes(const uint8_t *Buf) // don't need count (=188) // --- cRemux ---------------------------------------------------------------- -cRemux::cRemux(dvb_pid_t VPid, dvb_pid_t APid, bool ExitOnFailure) +cRemux::cRemux(dvb_pid_t VPid, dvb_pid_t APid1, dvb_pid_t APid2, bool ExitOnFailure) { vPid = VPid; - aPid = APid; + aPid1 = APid1; + aPid2 = APid2; exitOnFailure = ExitOnFailure; synced = false; skipped = 0; resultCount = resultDelivered = 0; - vTS2PES = new cTS2PES(resultBuffer, &resultCount, IPACKS); - aTS2PES = new cTS2PES(resultBuffer, &resultCount, IPACKS); + vTS2PES = new cTS2PES(resultBuffer, &resultCount, IPACKS); + aTS2PES1 = new cTS2PES(resultBuffer, &resultCount, IPACKS, 0xC0); + aTS2PES2 = aPid2 ? new cTS2PES(resultBuffer, &resultCount, IPACKS, 0xC1) : NULL; } cRemux::~cRemux() { delete vTS2PES; - delete aTS2PES; + delete aTS2PES1; + delete aTS2PES2; } int cRemux::GetPid(const uchar *Data) @@ -463,9 +476,9 @@ int cRemux::ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &Pic void cRemux::SetAudioPid(int APid) { - aPid = APid; + aPid1 = APid; vTS2PES->Clear(); - aTS2PES->Clear(); + aTS2PES1->Clear(); resultCount = resultDelivered = 0; } @@ -501,8 +514,10 @@ XXX*/ if (Data[i + 3] & 0x10) { // got payload if (pid == vPid) vTS2PES->ts_to_pes(Data + i); - else if (pid == aPid) - aTS2PES->ts_to_pes(Data + i); + else if (pid == aPid1) + aTS2PES1->ts_to_pes(Data + i); + else if (pid == aPid2 && aTS2PES2) + aTS2PES2->ts_to_pes(Data + i); } used += TS_SIZE; if (resultCount > (int)sizeof(resultBuffer) / 2) @@ -520,7 +535,7 @@ XXX*/ // Check if we're getting anywhere here: if (!synced && skipped >= 0) { - if (skipped > 1024*1024) { + if (skipped > MAXNONUSEFULDATA) { esyslog(LOG_ERR, "ERROR: no useful data seen within %d byte of video stream", skipped); skipped = -1; if (exitOnFailure) @@ -538,7 +553,7 @@ XXX*/ for (int i = 0; i < resultCount; i++) { if (resultBuffer[i] == 0 && resultBuffer[i + 1] == 0 && resultBuffer[i + 2] == 1) { switch (resultBuffer[i + 3]) { - case SC_VIDEO: + case VIDEO_STREAM_S ... VIDEO_STREAM_E: { uchar pt = NO_PICTURE; int l = ScanVideoPacket(resultBuffer, resultCount, i, pt); @@ -572,7 +587,7 @@ XXX*/ } } break; - case SC_AUDIO: + case AUDIO_STREAM_S ... AUDIO_STREAM_E: { int l = GetPacketLength(resultBuffer, resultCount, i); if (l < 0) diff --git a/remux.h b/remux.h index 011dd3b6..ae19a441 100644 --- a/remux.h +++ b/remux.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: remux.h 1.3 2001/06/02 15:15:43 kls Exp $ + * $Id: remux.h 1.4 2001/06/14 15:27:07 kls Exp $ */ #ifndef __REMUX_H @@ -19,18 +19,11 @@ #define P_FRAME 2 #define B_FRAME 3 -//XXX -> remux.c??? -// Start codes: -#define SC_PICTURE 0x00 // "picture header" -#define SC_SEQU 0xB3 // "sequence header" -#define SC_PHEAD 0xBA // "pack header" -#define SC_SHEAD 0xBB // "system header" -#define SC_AUDIO 0xC0 -#define SC_VIDEO 0xE0 - // The minimum amount of video data necessary to identify frames: #define MINVIDEODATA (16*1024) // just a safe guess (max. size of any frame block, plus some safety) +#define RESULTBUFFERSIZE (MINVIDEODATA * 4) + typedef unsigned char uchar; class cTS2PES; @@ -39,16 +32,16 @@ private: bool exitOnFailure; bool synced; int skipped; - dvb_pid_t vPid, aPid; - cTS2PES *vTS2PES, *aTS2PES; - uchar resultBuffer[MINVIDEODATA * 4];//XXX + dvb_pid_t vPid, aPid1, aPid2; + cTS2PES *vTS2PES, *aTS2PES1, *aTS2PES2; + uchar resultBuffer[RESULTBUFFERSIZE]; int resultCount; int resultDelivered; int GetPid(const uchar *Data); int GetPacketLength(const uchar *Data, int Count, int Offset); int ScanVideoPacket(const uchar *Data, int Count, int Offset, uchar &PictureType); public: - cRemux(dvb_pid_t VPid, dvb_pid_t APid, bool ExitOnFailure = false); + cRemux(dvb_pid_t VPid, dvb_pid_t APid1, dvb_pid_t APid2 = 0, bool ExitOnFailure = false); ~cRemux(); void SetAudioPid(int APid); const uchar *Process(const uchar *Data, int &Count, int &Result, uchar *PictureType = NULL);