diff options
-rw-r--r-- | HISTORY | 3 | ||||
-rw-r--r-- | dvbapi.c | 712 | ||||
-rw-r--r-- | menu.c | 7 | ||||
-rw-r--r-- | ringbuffer.c | 252 | ||||
-rw-r--r-- | ringbuffer.h | 85 | ||||
-rw-r--r-- | thread.c | 12 | ||||
-rw-r--r-- | thread.h | 8 |
7 files changed, 562 insertions, 517 deletions
@@ -610,7 +610,7 @@ Video Disk Recorder Revision History - Explicitly switching back to the previously active channel after ending a replay session (to have it shown correctly in case it was in 'Transfer Mode'). -2001-08-03: Version 0.86 +2001-08-05: Version 0.86 - Modified the display of the channel group separators (thanks to Markus Lang for this suggestion). @@ -618,3 +618,4 @@ Video Disk Recorder Revision History the 'libdvdread' library to be installed. - Fixed replay progress display in case replay is paused while watching an ongoing recording. +- Ringbuffer uses semaphores to signal empty/full conditions. @@ -6,7 +6,7 @@ * * DVD support initially written by Andreas Schultz <aschultz@warp10.net> * - * $Id: dvbapi.c 1.97 2001/08/03 13:08:22 kls Exp $ + * $Id: dvbapi.c 1.98 2001/08/05 12:17:02 kls Exp $ */ //#define DVDDEBUG 1 @@ -448,7 +448,7 @@ int cFileName::NextFile(void) // --- cRecordBuffer --------------------------------------------------------- -class cRecordBuffer : public cRingBuffer { +class cRecordBuffer : public cRingBufferLinear { private: cDvbApi *dvbApi; cFileName fileName; @@ -471,7 +471,7 @@ public: }; cRecordBuffer::cRecordBuffer(cDvbApi *DvbApi, const char *FileName, int VPid, int APid1, int APid2, int DPid1, int DPid2) -:cRingBuffer(VIDEOBUFSIZE, true) +:cRingBufferLinear(VIDEOBUFSIZE, true) ,fileName(FileName, true) ,remux(VPid, APid1, APid2, DPid1, DPid2, true) { @@ -628,23 +628,27 @@ int ReadFrame(int f, uchar *b, int Length, int Max) // --- cPlayBuffer --------------------------------------------------------- -class cPlayBuffer : public cRingBuffer { +class cPlayBuffer : public cRingBufferFrame { protected: cDvbApi *dvbApi; int videoDev, audioDev; FILE *dolbyDev; int blockInput, blockOutput; - bool paused, fastForward, fastRewind; + bool still, paused, fastForward, fastRewind; + int readIndex, writeIndex; + bool canDoTrickMode; bool canToggleAudioTrack; uchar audioTrack; - virtual void Clear(bool Block = false); + virtual void Empty(bool Block = false); + virtual void StripAudioPackets(uchar *b, int Length, uchar Except = 0x00) {} + virtual void Output(void); public: cPlayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev); virtual ~cPlayBuffer(); - virtual void Pause(void) {} - virtual void Play(void) = 0; - virtual void Forward(void) {} - virtual void Backward(void) {} + virtual void Pause(void); + virtual void Play(void); + virtual void Forward(void); + virtual void Backward(void); virtual int SkipFrames(int Frames) { return -1; } virtual void SkipSeconds(int Seconds) {} virtual void Goto(int Position, bool Still = false) {} @@ -654,14 +658,16 @@ public: }; cPlayBuffer::cPlayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev) -:cRingBuffer(VIDEOBUFSIZE) +:cRingBufferFrame(VIDEOBUFSIZE) { dvbApi = DvbApi; videoDev = VideoDev; audioDev = AudioDev; dolbyDev = NULL; blockInput = blockOutput = false; - paused = fastForward = fastRewind = false; + still = paused = fastForward = fastRewind = false; + readIndex = writeIndex = -1; + canDoTrickMode = false; canToggleAudioTrack = false; audioTrack = 0xC0; if (cDvbApi::AudioCommand()) { @@ -677,18 +683,136 @@ cPlayBuffer::~cPlayBuffer() pclose(dolbyDev); } -void cPlayBuffer::Clear(bool Block) +void cPlayBuffer::Output(void) { - cRingBuffer::Clear(); - CHECK(ioctl(videoDev, VIDEO_CLEAR_BUFFER)); - CHECK(ioctl(audioDev, AUDIO_CLEAR_BUFFER)); + dsyslog(LOG_INFO, "output thread started (pid=%d)", getpid()); + + while (Busy()) { + if (blockOutput) { + if (blockOutput > 1) + blockOutput = 1; + continue; + } + const cFrame *frame = Get(); + if (frame) { + StripAudioPackets((uchar *)frame->Data(), frame->Count(), (fastForward || fastRewind) ? 0x00 : audioTrack);//XXX + for (int i = 0; i < ((paused && fastRewind) ? 24 : 1); i++) { // show every I_FRAME 24 times in slow rewind mode to achieve roughly the same speed as in slow forward mode + const uchar *p = frame->Data(); + int r = frame->Count(); + while (r > 0 && Busy() && !blockOutput) { + cFile::FileReadyForWriting(videoDev, 100); + int w = write(videoDev, p, r); + if (w > 0) { + p += w; + r -= w; + } + else if (w < 0 && errno != EAGAIN) { + LOG_ERROR; + Stop(); + return; + } + } + writeIndex = frame->Index(); + } + Drop(frame); + } + } + + dsyslog(LOG_INFO, "output thread ended (pid=%d)", getpid()); +} + +void cPlayBuffer::Empty(bool Block) +{ + if (!(blockInput || blockOutput)) { + blockInput = blockOutput = 2; + EnablePut(); + EnableGet(); + time_t t0 = time(NULL); + while ((blockInput > 1 || blockOutput > 1) && time(NULL) - t0 < 2) + usleep(1); + Lock(); + readIndex = writeIndex; + cRingBufferFrame::Clear(); + CHECK(ioctl(videoDev, VIDEO_CLEAR_BUFFER)); + CHECK(ioctl(audioDev, AUDIO_CLEAR_BUFFER)); + } + if (!Block) { + blockInput = blockOutput = 0; + Unlock(); + } +} + +void cPlayBuffer::Pause(void) +{ + paused = !paused; + bool empty = fastForward || fastRewind; + if (empty) + Empty(true); + fastForward = fastRewind = false; + CHECK(ioctl(videoDev, paused ? VIDEO_FREEZE : VIDEO_CONTINUE)); + CHECK(ioctl(audioDev, AUDIO_SET_MUTE, paused)); + still = false; + if (empty) + Empty(false); +} + +void cPlayBuffer::Play(void) +{ + if (fastForward || fastRewind || paused) { + bool empty = !paused || fastRewind; + if (empty) + Empty(true); + still = false; + CHECK(ioctl(videoDev, paused ? VIDEO_CONTINUE : VIDEO_PLAY)); + CHECK(ioctl(audioDev, AUDIO_SET_AV_SYNC, true)); + CHECK(ioctl(audioDev, AUDIO_SET_MUTE, false)); + if (empty) + Empty(false); + fastForward = fastRewind = paused = false; + } +} + +void cPlayBuffer::Forward(void) +{ + if (canDoTrickMode || paused) { + bool empty = !paused || fastRewind; + if (empty) { + Empty(true); + if (fastForward) + readIndex -= 150; // this about compensates for the buffered data, so that we don't get too far ahead + } + still = false; + fastForward = !fastForward; + fastRewind = false; + if (paused) + CHECK(ioctl(videoDev, fastForward ? VIDEO_SLOWMOTION : VIDEO_FREEZE, 2)); + CHECK(ioctl(audioDev, AUDIO_SET_AV_SYNC, !fastForward)); + CHECK(ioctl(audioDev, AUDIO_SET_MUTE, fastForward || paused)); + if (empty) + Empty(false); + } +} + +void cPlayBuffer::Backward(void) +{ + if (canDoTrickMode) { + Empty(true); + still = false; + fastRewind = !fastRewind; + fastForward = false; + if (paused) + CHECK(ioctl(videoDev, fastRewind ? VIDEO_CONTINUE : VIDEO_FREEZE)); + CHECK(ioctl(audioDev, AUDIO_SET_AV_SYNC, !fastRewind)); + CHECK(ioctl(audioDev, AUDIO_SET_MUTE, fastRewind || paused)); + Empty(false); + } } void cPlayBuffer::ToggleAudioTrack(void) { if (CanToggleAudioTrack()) { audioTrack = (audioTrack == 0xC0) ? 0xC1 : 0xC0; - Clear(); + Empty(); } } @@ -698,27 +822,19 @@ class cReplayBuffer : public cPlayBuffer { private: cIndexFile *index; cFileName fileName; - int fileOffset; int replayFile; bool eof; - int lastIndex, stillIndex, playIndex; bool NextFile(uchar FileNumber = 0, int FileOffset = -1); - void Clear(bool Block = false); void Close(void); - void StripAudioPackets(uchar *b, int Length, uchar Except = 0x00); + virtual void StripAudioPackets(uchar *b, int Length, uchar Except = 0x00); void DisplayFrame(uchar *b, int Length); int Resume(void); bool Save(void); protected: virtual void Input(void); - virtual void Output(void); public: cReplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, const char *FileName); virtual ~cReplayBuffer(); - virtual void Pause(void); - virtual void Play(void); - virtual void Forward(void); - virtual void Backward(void); virtual int SkipFrames(int Frames); virtual void SkipSeconds(int Seconds); virtual void Goto(int Position, bool Still = false); @@ -730,10 +846,8 @@ cReplayBuffer::cReplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, const ,fileName(FileName, false) { index = NULL; - fileOffset = 0; replayFile = fileName.Open(); eof = false; - lastIndex = stillIndex = playIndex = -1; if (!fileName.Name()) return; // Create the index file: @@ -745,6 +859,7 @@ cReplayBuffer::cReplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, const delete index; index = NULL; } + canDoTrickMode = index != NULL; dvbApi->SetModeReplay(); Start(); } @@ -762,22 +877,23 @@ void cReplayBuffer::Input(void) { dsyslog(LOG_INFO, "input thread started (pid=%d)", getpid()); - int ResumeIndex = Resume(); - if (ResumeIndex >= 0) - isyslog(LOG_INFO, "resuming replay at index %d (%s)", ResumeIndex, IndexToHMSF(ResumeIndex, true)); + readIndex = Resume(); + if (readIndex >= 0) + isyslog(LOG_INFO, "resuming replay at index %d (%s)", readIndex, IndexToHMSF(readIndex, true)); - int lastIndex = -1; - int brakeCounter = 0; uchar b[MAXFRAMESIZE]; while (Busy() && (blockInput || NextFile())) { - if (!blockInput && stillIndex < 0) { + if (blockInput) { + if (blockInput > 1) + blockInput = 1; + continue; + } + if (!still) { int r = 0; if (fastForward && !paused || fastRewind) { - int Index = (lastIndex >= 0) ? lastIndex : index->Get(fileName.Number(), fileOffset); uchar FileNumber; int FileOffset, Length; - if (!paused || (brakeCounter++ % 24) == 0) // show every I_FRAME 24 times in rmSlowRewind mode to achieve roughly the same speed as in slow forward mode - Index = index->GetNextIFrame(Index, fastForward, &FileNumber, &FileOffset, &Length); + int Index = index->GetNextIFrame(readIndex, fastForward, &FileNumber, &FileOffset, &Length); if (Index >= 0) { if (!NextFile(FileNumber, FileOffset)) break; @@ -787,126 +903,85 @@ void cReplayBuffer::Input(void) Play(); continue; } - lastIndex = Index; - playIndex = -1; + readIndex = Index; r = ReadFrame(replayFile, b, Length, sizeof(b)); - StripAudioPackets(b, r); } else if (index) { - lastIndex = -1; - 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))) + readIndex++; + if (!(index->Get(readIndex, &FileNumber, &FileOffset, NULL, &Length) && NextFile(FileNumber, FileOffset))) break; r = ReadFrame(replayFile, b, Length, sizeof(b)); - StripAudioPackets(b, r, audioTrack); } else // allows replay even if the index file is missing r = read(replayFile, b, sizeof(b)); if (r > 0) { - uchar *p = b; - while (r > 0 && Busy() && !blockInput) { - int w = Put(p, r); - p += w; - r -= w; - usleep(1); // this keeps the CPU load low - } + cFrame *frame = new cFrame(b, r, readIndex); + while (Busy() && !blockInput && !Put(frame)) + ; } - else if (r ==0) + else if (r == 0) eof = true; else if (r < 0 && errno != EAGAIN) { LOG_ERROR; break; } } - else + else//XXX usleep(1); // this keeps the CPU load low - if (blockInput > 1) - blockInput = 1; } dsyslog(LOG_INFO, "input thread ended (pid=%d)", getpid()); } -void cReplayBuffer::Output(void) -{ - dsyslog(LOG_INFO, "output thread started (pid=%d)", getpid()); - - uchar b[MINVIDEODATA]; - while (Busy()) { - int r = blockOutput ? 0 : Get(b, sizeof(b)); - if (r > 0) { - uchar *p = b; - while (r > 0 && Busy() && !blockOutput) { - cFile::FileReadyForWriting(videoDev, 100); - int w = write(videoDev, p, r); - if (w > 0) { - p += w; - r -= w; - fileOffset += w; - } - else if (w < 0 && errno != EAGAIN) { - LOG_ERROR; - Stop(); - return; - } - } - } - else - usleep(1); // this keeps the CPU load low - if (blockOutput > 1) - blockOutput = 1; - } - - dsyslog(LOG_INFO, "output thread ended (pid=%d)", getpid()); -} - 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) { - uchar c = b[i + 3]; - int l = b[i + 4] * 256 + b[i + 5] + 6; - switch (c) { - case 0xBD: // dolby - if (Except && dolbyDev) { - int written = b[i + 8] + 9; // skips the PES header - int n = l - written; - while (n > 0) { - int w = fwrite(&b[i + written], 1, n, dolbyDev); - if (w < 0) { - LOG_ERROR; - break; + if (canDoTrickMode) { + for (int i = 0; i < Length - 6; i++) { + if (b[i] == 0x00 && b[i + 1] == 0x00 && b[i + 2] == 0x01) { + uchar c = b[i + 3]; + int l = b[i + 4] * 256 + b[i + 5] + 6; + switch (c) { + case 0xBD: // dolby + if (Except && dolbyDev) { + int written = b[i + 8] + 9; // skips the PES header + int n = l - written; + while (n > 0) { + int w = fwrite(&b[i + written], 1, n, dolbyDev); + if (w < 0) { + LOG_ERROR; + break; + } + n -= w; + written += w; } - n -= w; - written += w; - } - } - // continue with deleting the data - otherwise it disturbs DVB replay - case 0xC0 ... 0xC1: // audio - if (c == 0xC1) - canToggleAudioTrack = true; - if (!Except || c != Except) { - int n = l; - for (int j = i; j < Length && n--; j++) - b[j] = 0x00; - } - break; - case 0xE0 ... 0xEF: // video - break; - default: - //esyslog(LOG_ERR, "ERROR: unexpected packet id %02X", c); - l = 0; - } - if (l) - i += l - 1; // the loop increments, too! + } + // continue with deleting the data - otherwise it disturbs DVB replay + case 0xC0 ... 0xC1: // audio + if (c == 0xC1) + canToggleAudioTrack = true; + if (!Except || c != Except) { + int n = l; + for (int j = i; j < Length && n--; j++) + b[j] = 0x00; + } + break; + case 0xE0 ... 0xEF: // video + break; + default: + //esyslog(LOG_ERR, "ERROR: unexpected packet id %02X", c); + l = 0; + } + if (l) + i += l - 1; // the loop increments, too! + } + /*XXX + else + esyslog(LOG_ERR, "ERROR: broken packet header"); + XXX*/ } - /*XXX - else - esyslog(LOG_ERR, "ERROR: broken packet header"); - XXX*/ - } + } } void cReplayBuffer::DisplayFrame(uchar *b, int Length) @@ -918,85 +993,11 @@ void cReplayBuffer::DisplayFrame(uchar *b, int Length) CHECK(ioctl(videoDev, VIDEO_STILLPICTURE, &sp)); } -void cReplayBuffer::Clear(bool Block) -{ - if (!(blockInput || blockOutput)) { - blockInput = blockOutput = 2; - time_t t0 = time(NULL); - while ((blockInput > 1 || blockOutput > 1) && time(NULL) - t0 < 2) - usleep(1); - Lock(); - playIndex = -1; - cPlayBuffer::Clear(); - } - if (!Block) { - blockInput = blockOutput = 0; - Unlock(); - } -} - -void cReplayBuffer::Pause(void) -{ - paused = !paused; - CHECK(ioctl(videoDev, paused ? VIDEO_FREEZE : VIDEO_CONTINUE)); - if (fastForward || fastRewind) { - if (paused) - Clear(); - fastForward = fastRewind = false; - } - CHECK(ioctl(audioDev, AUDIO_SET_MUTE, paused)); - stillIndex = -1; -} - -void cReplayBuffer::Play(void) -{ - if (fastForward || fastRewind || paused) { - if (!paused) - Clear(); - stillIndex = -1; - CHECK(ioctl(videoDev, paused ? VIDEO_CONTINUE : VIDEO_PLAY)); - CHECK(ioctl(audioDev, AUDIO_SET_AV_SYNC, true)); - CHECK(ioctl(audioDev, AUDIO_SET_MUTE, false)); - fastForward = fastRewind = paused = false; - } -} - -void cReplayBuffer::Forward(void) -{ - if (index || paused) { - if (!paused) - Clear(true); - stillIndex = -1; - fastForward = !fastForward; - fastRewind = false; - if (paused) - CHECK(ioctl(videoDev, fastForward ? VIDEO_SLOWMOTION : VIDEO_FREEZE, 2)); - CHECK(ioctl(audioDev, AUDIO_SET_AV_SYNC, !fastForward)); - CHECK(ioctl(audioDev, AUDIO_SET_MUTE, fastForward || paused)); - if (!paused) - Clear(false); - } -} - -void cReplayBuffer::Backward(void) -{ - if (index) { - Clear(true); - stillIndex = -1; - fastRewind = !fastRewind; - fastForward = false; - CHECK(ioctl(audioDev, AUDIO_SET_AV_SYNC, !fastRewind)); - CHECK(ioctl(audioDev, AUDIO_SET_MUTE, fastRewind || paused)); - Clear(false); - } -} - void cReplayBuffer::Close(void) { if (replayFile >= 0) { fileName.Close(); replayFile = -1; - fileOffset = 0; } } @@ -1017,7 +1018,7 @@ int cReplayBuffer::Resume(void) bool cReplayBuffer::Save(void) { if (index) { - int Index = index->Get(fileName.Number(), fileOffset); + int Index = writeIndex; if (Index >= 0) { Index -= RESUMEBACKUP; if (Index > 0) @@ -1046,8 +1047,8 @@ int cReplayBuffer::SkipFrames(int Frames) void cReplayBuffer::SkipSeconds(int Seconds) { if (index && Seconds) { - Clear(true); - int Index = index->Get(fileName.Number(), fileOffset); + Empty(true); + int Index = writeIndex; if (Index >= 0) { if (Seconds < 0) { int sec = index->Last() / FRAMESPERSEC; @@ -1059,10 +1060,9 @@ void cReplayBuffer::SkipSeconds(int Seconds) Index = 1; // not '0', to allow GetNextIFrame() below to work! uchar FileNumber; int FileOffset; - if (index->GetNextIFrame(Index, false, &FileNumber, &FileOffset) >= 0) - NextFile(FileNumber, FileOffset); + readIndex = writeIndex = index->GetNextIFrame(Index, false, &FileNumber, &FileOffset) - 1; // Input() will first increment it! } - Clear(false); + Empty(false); Play(); } } @@ -1070,7 +1070,7 @@ void cReplayBuffer::SkipSeconds(int Seconds) void cReplayBuffer::Goto(int Index, bool Still) { if (index) { - Clear(true); + Empty(true); if (paused) CHECK(ioctl(videoDev, VIDEO_CONTINUE)); if (++Index <= 0) @@ -1079,28 +1079,27 @@ void cReplayBuffer::Goto(int Index, bool Still) int FileOffset, Length; Index = index->GetNextIFrame(Index, false, &FileNumber, &FileOffset, &Length); if (Index >= 0 && NextFile(FileNumber, FileOffset) && Still) { - stillIndex = Index; - playIndex = -1; + still = true; uchar b[MAXFRAMESIZE]; int r = ReadFrame(replayFile, b, Length, sizeof(b)); if (r > 0) DisplayFrame(b, r); - fileOffset += Length; paused = true; } else - stillIndex = playIndex = -1; - Clear(false); + still = false; + readIndex = writeIndex = Index; + Empty(false); } } void cReplayBuffer::GetIndex(int &Current, int &Total, bool SnapToIFrame) { if (index) { - if (stillIndex >= 0) - Current = stillIndex; + if (still) + Current = readIndex; else { - Current = index->Get(fileName.Number(), fileOffset); + Current = writeIndex; if (SnapToIFrame) { int i1 = index->GetNextIFrame(Current + 1, false); int i2 = index->GetNextIFrame(Current, true); @@ -1115,10 +1114,8 @@ void cReplayBuffer::GetIndex(int &Current, int &Total, bool SnapToIFrame) bool cReplayBuffer::NextFile(uchar FileNumber, int FileOffset) { - if (FileNumber > 0) { - fileOffset = FileOffset; + if (FileNumber > 0) replayFile = fileName.SetOffset(FileNumber, FileOffset); - } else if (replayFile >= 0 && eof) { Close(); replayFile = fileName.NextFile(); @@ -1131,12 +1128,6 @@ bool cReplayBuffer::NextFile(uchar FileNumber, int FileOffset) class cDVDplayBuffer : public cPlayBuffer { private: - cCondVar ready4input; - cMutex inputMutex; - - cCondVar ready4output; - cMutex outputMutex; - uchar audioTrack; cDVD *dvd;//XXX necessary??? @@ -1186,7 +1177,7 @@ private: int lpcm_count; int is_nav_pack(unsigned char *buffer); void Close(void); - void Clear(bool Block = false); + virtual void Empty(bool Block = false); int decode_packet(unsigned char *sector, int iframe); int ScanVideoPacket(const uchar *Data, int Count, uchar *PictureType); bool PacketStart(uchar **Data, int len); @@ -1201,14 +1192,9 @@ private: void NextState(int State) { prevcycle = cyclestate; cyclestate = State; } protected: virtual void Input(void); - virtual void Output(void); public: cDVDplayBuffer(cDvbApi *DvbApi, int VideoDev, int AudioDev, cDVD *DvD, int title); virtual ~cDVDplayBuffer(); - virtual void Pause(void); - virtual void Play(void); - virtual void Forward(void); - virtual void Backward(void); virtual int SkipFrames(int Frames); virtual void SkipSeconds(int Seconds); virtual void Goto(int Position, bool Still = false); @@ -1224,6 +1210,41 @@ public: #define cOUTPACK 5 #define cOUTFRAMES 6 +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; + brakeCounter = 0; + skipCnt = 0; + logAudioTrack = 0; + canToggleAudioTrack = true;//XXX determine from cDVD! + ac3_config.num_output_ch = 2; + // ac3_config.flags = /* mm_accel() | */ MM_ACCEL_MLIB; + ac3_config.flags = 0; + ac3_init(&ac3_config); + data = new uchar[1024 * DVD_VIDEO_LB_LEN]; + ac3data = new uchar[AC3_BUFFER_SIZE]; + ac3inp = ac3outp = 0; + ac3stat = AC3_START; + canDoTrickMode = true; + dvbApi->SetModeReplay(); + Start(); +} + +cDVDplayBuffer::~cDVDplayBuffer() +{ + Stop(); + Close(); + dvbApi->SetModeNormal(false); + delete ac3data; + delete data; +} + unsigned int cDVDplayBuffer::getAudioStream(unsigned int StreamId) { unsigned int trackID; @@ -1267,40 +1288,6 @@ void cDVDplayBuffer::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; - brakeCounter = 0; - skipCnt = 0; - logAudioTrack = 0; - canToggleAudioTrack = true;//XXX determine from cDVD! - ac3_config.num_output_ch = 2; - // ac3_config.flags = /* mm_accel() | */ MM_ACCEL_MLIB; - ac3_config.flags = 0; - ac3_init(&ac3_config); - data = new uchar[1024 * DVD_VIDEO_LB_LEN]; - ac3data = new uchar[AC3_BUFFER_SIZE]; - ac3inp = ac3outp = 0; - ac3stat = AC3_START; - dvbApi->SetModeReplay(); - Start(); -} - -cDVDplayBuffer::~cDVDplayBuffer() -{ - Stop(); - Close(); - dvbApi->SetModeNormal(false); - delete ac3data; - delete data; -} - /** * 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 @@ -1317,15 +1304,13 @@ void cDVDplayBuffer::Input(void) doplay = true; while (Busy() && doplay) { - inputMutex.Lock(); - while (blockInput) { - if (blockInput > 1) - blockInput = 1; - ready4input.Wait(inputMutex); - } - inputMutex.Unlock(); + if (blockInput) { + if (blockInput > 1) + blockInput = 1; + continue; + } - //BEGIN: riped from play_title + //BEGIN: ripped from play_title /** * Playback by cell in this pgc, starting at the cell for our chapter. @@ -1659,8 +1644,6 @@ void cDVDplayBuffer::Input(void) } // dsyslog(LOG_INF, "DVD: new cyclestate: %d, pktcnt: %d, cur: %d", cyclestate, pktcnt, cur_output_size); - if (blockInput > 1) - blockInput = 1; } dsyslog(LOG_INFO, "output thread ended (pid=%d)", getpid()); @@ -1761,6 +1744,7 @@ int cDVDplayBuffer::SendPCM(int size) while (p_size) { if (ac3outp != ac3inp) { // data in the buffer buffer[(length + 6) ^ 1] = ac3data[ac3outp]; // swab because ac3dec delivers wrong byteorder + // XXX there is no 'swab' here??? (kls) p_size--; length++; ac3outp = (ac3outp + 1) % AC3_BUFFER_SIZE; @@ -1791,18 +1775,9 @@ int cDVDplayBuffer::SendPCM(int size) length += 6; - inputMutex.Lock(); - while (Free() < length && Busy() && !blockInput) - ready4input.Wait(inputMutex); - inputMutex.Unlock(); - - if (Busy() && !blockInput) { - if ((Put(buffer, length) != length)) { - esyslog(LOG_ERR, "ERROR: Put(buffer, length) != length"); - return 0; - } - ready4output.Broadcast(); - } + cFrame *frame = new cFrame(buffer, length); + while (Busy() && !blockInput && !Put(frame)) + ; size -= MAXSIZE; } return 0; @@ -1834,7 +1809,7 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, int trickMode) uchar *osect = sector; #endif - //make sure we got an PS packet header + //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; @@ -1885,7 +1860,7 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, int trickMode) sector += 6; //we are now at the beginning of the payload - //correct a3 data lenght - FIXME: why 13 ??? + //correct ac3 data lenght - FIXME: why 13 ??? ac3datalen -= 13; if (audioTrack == *sector) { sector +=4; @@ -1933,154 +1908,23 @@ int cDVDplayBuffer::decode_packet(unsigned char *sector, int trickMode) return pt; } } - inputMutex.Lock(); - while (Free() < r && Busy() && !blockInput) - ready4input.Wait(inputMutex); - inputMutex.Unlock(); - if (Busy() && !blockInput) { - if (Put(sector, r) != r) { - esyslog(LOG_ERR, "ERROR: Put(sector, r) != r"); - return 0; - } - ready4output.Broadcast(); - } + cFrame *frame = new cFrame(sector, r); + while (Busy() && !blockInput && !Put(frame)) + ; playDecodedAC3(); return pt; } -void cDVDplayBuffer::Output(void) -{ - dsyslog(LOG_INFO, "output thread started (pid=%d)", getpid()); - -#ifdef DVDDEBUG_BUFFER - long long cyl = 0; - long long emp = 0; - long long low = 0; -#endif - - uchar b[MINVIDEODATA]; - while (Busy()) { -#ifdef DVDDEBUG_BUFFER - cyl++; -#endif - outputMutex.Lock(); - if (blockOutput > 1) - blockOutput = 1; - - int r = 0; - while (Busy() && ((r = blockOutput ? 0 : Get(b, sizeof(b))) == 0)) { -#ifdef DVDDEBUG_BUFFER - if (r == 0) { - //ups we just emptied the entire buffer - dsyslog(LOG_INFO, "DVD: %12Ld warning: Get() failed due to empty buffer %12Ld", cyl, emp); - emp++; - } -#endif - ready4output.Wait(outputMutex); - if (blockOutput > 1) - blockOutput = 1; - } - outputMutex.Unlock(); - - if (r > 0) { -#ifdef DVDDEBUG_BUFFER - if (Available() != 0 && Available() < (VIDEOBUFSIZE/20)) { - //5% warning limit - dsyslog(LOG_INFO, "DVD: %12Ld warning: buffer almost empty: %d, %10.2f %12Ld", cyl, Available(), (float)Available() * 100.0 / (float) VIDEOBUFSIZE, low); - low++; - } -#endif - ready4input.Broadcast(); - uchar *p = b; - while (r > 0 && Busy() && !blockOutput) { - cFile::FileReadyForWriting(videoDev, 100); - int w = write(videoDev, p, r); - if (w > 0) { - p += w; - r -= w; - } - else if (w < 0 && errno != EAGAIN) { - LOG_ERROR; - Stop(); - return; - } - } - } - if (blockOutput > 1) - blockOutput = 1; - } - - dsyslog(LOG_INFO, "output thread ended (pid=%d)", getpid()); -} - -void cDVDplayBuffer::Clear(bool Block) +void cDVDplayBuffer::Empty(bool Block) { if (!(blockInput || blockOutput)) { - blockInput = blockOutput = 2; - ready4input.Broadcast(); - ready4output.Broadcast(); - time_t t0 = time(NULL); - while ((blockInput > 1 || blockOutput > 1) && time(NULL) - t0 < 2) - usleep(1); - Lock(); - cPlayBuffer::Clear(); + cPlayBuffer::Empty(true); ac3stat = AC3_START; ac3outp = ac3inp; } - if (!Block) { - blockInput = blockOutput = 0; - ready4input.Broadcast(); - ready4output.Broadcast(); - Unlock(); - } -} -void cDVDplayBuffer::Pause(void) -{ - paused = !paused; - CHECK(ioctl(videoDev, paused ? VIDEO_FREEZE : VIDEO_CONTINUE)); - if (fastForward || fastRewind) { - if (paused) - Clear(); - fastForward = fastRewind = false; - } - CHECK(ioctl(audioDev, AUDIO_SET_MUTE, paused)); -} - -void cDVDplayBuffer::Play(void) -{ - if (fastForward || fastRewind || paused) { - if (!paused) - Clear(); - CHECK(ioctl(videoDev, paused ? VIDEO_CONTINUE : VIDEO_PLAY)); - CHECK(ioctl(audioDev, AUDIO_SET_AV_SYNC, true)); - CHECK(ioctl(audioDev, AUDIO_SET_MUTE, false)); - fastForward = fastRewind = paused = false; - } -} - -void cDVDplayBuffer::Forward(void) -{ - if (!paused) - Clear(true); - fastForward = !fastForward; - fastRewind = false; - if (paused) - CHECK(ioctl(videoDev, fastForward ? VIDEO_SLOWMOTION : VIDEO_FREEZE, 2)); - CHECK(ioctl(audioDev, AUDIO_SET_AV_SYNC, !fastForward)); - CHECK(ioctl(audioDev, AUDIO_SET_MUTE, fastForward || paused)); - if (!paused) - Clear(false); -} - -void cDVDplayBuffer::Backward(void) -{ - Clear(true); - fastRewind = !fastRewind; - fastForward = false; - CHECK(ioctl(audioDev, AUDIO_SET_AV_SYNC, !fastRewind)); - CHECK(ioctl(audioDev, AUDIO_SET_MUTE, fastRewind || paused)); - Clear(false); + if (!Block) + cPlayBuffer::Empty(false); } void cDVDplayBuffer::Close(void) @@ -2116,13 +1960,13 @@ void cDVDplayBuffer::SkipSeconds(int Seconds) int newchapid = Seconds > 0 ? chapid + 1 : chapid - 1; if (newchapid >= 0 && newchapid < tt_srpt->title[titleid].nr_of_ptts) { - Clear(true); + Empty(true); chapid = newchapid; NextState(cOPENCHAPTER); if (ac3stat != AC3_STOP) - ac3stat=AC3_START; + ac3stat = AC3_START; ac3outp = ac3inp; - Clear(false); + Empty(false); Play(); } } @@ -2139,7 +1983,7 @@ void cDVDplayBuffer::GetIndex(int &Current, int &Total, bool SnapToIFrame) // --- cTransferBuffer ------------------------------------------------------- -class cTransferBuffer : public cRingBuffer { +class cTransferBuffer : public cRingBufferLinear { private: cDvbApi *dvbApi; int fromDevice, toDevice; @@ -2155,7 +1999,7 @@ public: }; cTransferBuffer::cTransferBuffer(cDvbApi *DvbApi, int ToDevice, int VPid, int APid) -:cRingBuffer(VIDEOBUFSIZE, true) +:cRingBufferLinear(VIDEOBUFSIZE, true) ,remux(VPid, APid, 0, 0, 0) { dvbApi = DvbApi; @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: menu.c 1.91 2001/08/04 08:08:44 kls Exp $ + * $Id: menu.c 1.92 2001/08/05 10:33:54 kls Exp $ */ #include "menu.h" @@ -2438,11 +2438,10 @@ eOSState cReplayControl::ProcessKey(eKeys Key) // Positioning: case kUp: dvbApi->Play(); break; case kDown: dvbApi->Pause(); break; - case kLeft: dvbApi->Backward(); break; - case kRight: dvbApi->Forward(); break; case kLeft|k_Release: + case kLeft: dvbApi->Backward(); break; case kRight|k_Release: - dvbApi->Play(); break; + case kRight: dvbApi->Forward(); break; case kGreen|k_Repeat: case kGreen: dvbApi->SkipSeconds(-60); break; case kYellow|k_Repeat: diff --git a/ringbuffer.c b/ringbuffer.c index 79ece885..7e09b2af 100644 --- a/ringbuffer.c +++ b/ringbuffer.c @@ -7,7 +7,7 @@ * Parts of this file were inspired by the 'ringbuffy.c' from the * LinuxDVB driver (see linuxtv.org). * - * $Id: ringbuffer.c 1.3 2001/08/02 13:48:38 kls Exp $ + * $Id: ringbuffer.c 1.4 2001/08/05 12:17:45 kls Exp $ */ #include "ringbuffer.h" @@ -41,60 +41,128 @@ cRingBuffer::cRingBuffer(int Size, bool Statistics) { size = Size; statistics = Statistics; - buffer = NULL; inputThread = NULL; outputThread = NULL; + busy = false; maxFill = 0; +} + +cRingBuffer::~cRingBuffer() +{ + delete inputThread; + delete outputThread; + if (statistics) + dsyslog(LOG_INFO, "buffer stats: %d (%d%%) used", maxFill, maxFill * 100 / (size - 1)); +} + +void cRingBuffer::WaitForPut(void) +{ + putMutex.Lock(); + readyForPut.Wait(putMutex); + putMutex.Unlock(); +} + +void cRingBuffer::WaitForGet(void) +{ + getMutex.Lock(); + readyForGet.Wait(getMutex); + getMutex.Unlock(); +} + +void cRingBuffer::EnablePut(void) +{ + readyForPut.Broadcast(); +} + +void cRingBuffer::EnableGet(void) +{ + readyForGet.Broadcast(); +} + +bool cRingBuffer::Start(void) +{ + if (!busy) { + busy = true; + outputThread = new cRingBufferOutputThread(this); + if (!outputThread->Start()) + DELETENULL(outputThread); + inputThread = new cRingBufferInputThread(this); + if (!inputThread->Start()) { + DELETENULL(inputThread); + DELETENULL(outputThread); + } + busy = outputThread && inputThread; + } + return busy; +} + +bool cRingBuffer::Active(void) +{ + return outputThread && outputThread->Active() && inputThread && inputThread->Active(); +} + +void cRingBuffer::Stop(void) +{ busy = false; - if (size > 1) { // 'size - 1' must not be 0! - buffer = new uchar[size]; + for (time_t t0 = time(NULL) + 3; time(NULL) < t0; ) { + if (!((outputThread && outputThread->Active()) || (inputThread && inputThread->Active()))) + break; + } + DELETENULL(inputThread); + DELETENULL(outputThread); +} + +// --- cRingBufferLinear ---------------------------------------------------- + +cRingBufferLinear::cRingBufferLinear(int Size, bool Statistics) +:cRingBuffer(Size, Statistics) +{ + buffer = NULL; + if (Size > 1) { // 'Size - 1' must not be 0! + buffer = new uchar[Size]; if (!buffer) - esyslog(LOG_ERR, "ERROR: can't allocate ring buffer (size=%d)", size); + esyslog(LOG_ERR, "ERROR: can't allocate ring buffer (size=%d)", Size); Clear(); } else - esyslog(LOG_ERR, "ERROR: illegal size for ring buffer (%d)", size); + esyslog(LOG_ERR, "ERROR: illegal size for ring buffer (%d)", Size); } -cRingBuffer::~cRingBuffer() +cRingBufferLinear::~cRingBufferLinear() { - delete inputThread; - delete outputThread; delete buffer; - if (statistics) - dsyslog(LOG_INFO, "buffer stats: %d (%d%%) used", maxFill, maxFill * 100 / (size - 1)); } -int cRingBuffer::Available(void) +int cRingBufferLinear::Available(void) { - mutex.Lock(); + Lock(); int diff = head - tail; - mutex.Unlock(); - return (diff >= 0) ? diff : size + diff; + Unlock(); + return (diff >= 0) ? diff : Size() + diff; } -void cRingBuffer::Clear(void) +void cRingBufferLinear::Clear(void) { - mutex.Lock(); + Lock(); head = tail = 0; - mutex.Unlock(); + Unlock(); } -int cRingBuffer::Put(const uchar *Data, int Count) +int cRingBufferLinear::Put(const uchar *Data, int Count) { if (Count > 0) { - mutex.Lock(); - int rest = size - head; + Lock(); + int rest = Size() - head; int diff = tail - head; - mutex.Unlock(); - int free = (diff > 0) ? diff - 1 : size + diff - 1; + Unlock(); + int free = (diff > 0) ? diff - 1 : Size() + diff - 1; if (statistics) { - int fill = size - free - 1 + Count; - if (fill >= size) - fill = size - 1; + int fill = Size() - free - 1 + Count; + if (fill >= Size()) + fill = Size() - 1; if (fill > maxFill) { maxFill = fill; - int percent = maxFill * 100 / (size - 1); + int percent = maxFill * 100 / (Size() - 1); if (percent > 75) dsyslog(LOG_INFO, "buffer usage: %d%%", percent); } @@ -119,14 +187,14 @@ int cRingBuffer::Put(const uchar *Data, int Count) return Count; } -int cRingBuffer::Get(uchar *Data, int Count) +int cRingBufferLinear::Get(uchar *Data, int Count) { if (Count > 0) { - mutex.Lock(); - int rest = size - tail; + Lock(); + int rest = Size() - tail; int diff = head - tail; - mutex.Unlock(); - int cont = (diff >= 0) ? diff : size + diff; + Unlock(); + int cont = (diff >= 0) ? diff : Size() + diff; if (rest <= 0) return 0; if (cont < Count) @@ -145,36 +213,112 @@ int cRingBuffer::Get(uchar *Data, int Count) return Count; } -bool cRingBuffer::Start(void) +// --- cFrame ---------------------------------------------------------------- + +cFrame::cFrame(const uchar *Data, int Count, int Index) { - if (!busy) { - busy = true; - outputThread = new cRingBufferOutputThread(this); - if (!outputThread->Start()) - DELETENULL(outputThread); - inputThread = new cRingBufferInputThread(this); - if (!inputThread->Start()) { - DELETENULL(inputThread); - DELETENULL(outputThread); + count = Count; + index = Index; + data = new uchar[count]; + if (data) + memcpy(data, Data, count); + else + esyslog(LOG_ERR, "ERROR: can't allocate frame buffer (count=%d)", count); + next = NULL; +} + +cFrame::~cFrame() +{ + delete data; +} + +// --- cRingBufferFrame ------------------------------------------------------ + +cRingBufferFrame::cRingBufferFrame(int Size, bool Statistics = false) +:cRingBuffer(Size, Statistics) +{ + head = NULL; + currentFill = 0; +} + +cRingBufferFrame::~cRingBufferFrame() +{ + Clear(); +} + +void cRingBufferFrame::Clear(void) +{ + Lock(); + const cFrame *p; + while ((p = Get(false)) != NULL) + Drop(p); + Unlock(); + EnablePut(); + EnableGet(); +} + +bool cRingBufferFrame::Put(cFrame *Frame) +{ + if (Frame->Count() <= Free()) { + Lock(); + if (head) { + Frame->next = head->next; + head->next = Frame; + head = Frame; } - busy = outputThread && inputThread; + else { + head = Frame->next = Frame; + } + currentFill += Frame->Count(); + Unlock(); + EnableGet(); + return true; } - return busy; + WaitForPut(); + return false; } -bool cRingBuffer::Active(void) +const cFrame *cRingBufferFrame::Get(bool Wait) { - return outputThread && outputThread->Active() && inputThread && inputThread->Active(); + Lock(); + cFrame *p = head ? head->next : NULL; + Unlock(); + if (!p && Wait) + WaitForGet(); + return p; } -void cRingBuffer::Stop(void) +void cRingBufferFrame::Delete(const cFrame *Frame) { - busy = false; - for (time_t t0 = time(NULL) + 3; time(NULL) < t0; ) { - if (!((outputThread && outputThread->Active()) || (inputThread && inputThread->Active()))) - break; - } - DELETENULL(inputThread); - DELETENULL(outputThread); + currentFill -= Frame->Count(); + delete Frame; +} + +void cRingBufferFrame::Drop(const cFrame *Frame) +{ + Lock(); + if (head) { + if (Frame == head->next) { + if (head->next != head) { + head->next = Frame->next; + Delete(Frame); + } + else { + Delete(head); + head = NULL; + } + } + else + esyslog(LOG_ERR, "ERROR: attempt to drop wrong frame from ring buffer!"); + } + Unlock(); + EnablePut(); } +int cRingBufferFrame::Available(void) +{ + Lock(); + int av = currentFill; + Unlock(); + return av; +} diff --git a/ringbuffer.h b/ringbuffer.h index 2121332b..f61d9e04 100644 --- a/ringbuffer.h +++ b/ringbuffer.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ringbuffer.h 1.3 2001/08/02 13:48:42 kls Exp $ + * $Id: ringbuffer.h 1.4 2001/08/05 11:12:06 kls Exp $ */ #ifndef __RINGBUFFER_H @@ -24,25 +24,24 @@ private: cRingBufferInputThread *inputThread; cRingBufferOutputThread *outputThread; cMutex mutex; - int size, head, tail; - uchar *buffer; - int maxFill; + cCondVar readyForPut, readyForGet; + cMutex putMutex, getMutex; + int size; bool busy; - bool statistics; protected: + int maxFill;//XXX + bool statistics;//XXX + void WaitForPut(void); + void WaitForGet(void); + void EnablePut(void); + void EnableGet(void); + virtual void Clear(void) = 0; + virtual int Available(void) = 0; + int Free(void) { return size - Available() - 1; } void Lock(void) { mutex.Lock(); } void Unlock(void) { mutex.Unlock(); } - int Available(void); - int Free(void) { return size - Available() - 1; } + int Size(void) { return size; } bool Busy(void) { return busy; } - void Clear(void); - // Immediately clears the ring buffer. - int Put(const uchar *Data, int Count); - // Puts at most Count bytes of Data into the ring buffer. - // Returns the number of bytes actually stored. - int Get(uchar *Data, int Count); - // Gets at most Count bytes of Data from the ring buffer. - // Returns the number of bytes actually retrieved. virtual void Input(void) = 0; // Runs as a separate thread and shall continuously read data from // a source and call Put() to store the data in the ring buffer. @@ -57,4 +56,60 @@ public: void Stop(void); }; +class cRingBufferLinear : public cRingBuffer { +private: + int head, tail; + uchar *buffer; +protected: + virtual int Available(void); + virtual void Clear(void); + // Immediately clears the ring buffer. + int Put(const uchar *Data, int Count); + // Puts at most Count bytes of Data into the ring buffer. + // Returns the number of bytes actually stored. + int Get(uchar *Data, int Count); + // Gets at most Count bytes of Data from the ring buffer. + // Returns the number of bytes actually retrieved. +public: + cRingBufferLinear(int Size, bool Statistics = false); + virtual ~cRingBufferLinear(); + }; + +class cFrame { + friend class cRingBufferFrame; +private: + cFrame *next; + uchar *data; + int count; + int index; +public: + cFrame(const uchar *Data, int Count, int Index = -1); + ~cFrame(); + const uchar *Data(void) const { return data; } + int Count(void) const { return count; } + int Index(void) const { return index; } + }; + +class cRingBufferFrame : public cRingBuffer { +private: + cFrame *head; + int currentFill; + void Delete(const cFrame *Frame); +protected: + virtual int Available(void); + virtual void Clear(void); + // Immediately clears the ring buffer. + bool Put(cFrame *Frame); + // Puts the Frame into the ring buffer. + // Returns true if this was possible. + const cFrame *Get(bool Wait = true); + // Gets the next frame from the ring buffer. + // The actual data still remains in the buffer until Drop() is called. + void Drop(const cFrame *Frame); + // Drops the Frame that has just been fetched with Get(). +public: + cRingBufferFrame(int Size, bool Statistics = false); + virtual ~cRingBufferFrame(); + }; + #endif // __RINGBUFFER_H @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: thread.c 1.10 2001/08/02 13:48:45 kls Exp $ + * $Id: thread.c 1.11 2001/08/05 10:36:52 kls Exp $ */ #include "thread.h" @@ -26,15 +26,15 @@ cCondVar::~cCondVar() pthread_cond_destroy(&cond); } -bool cCondVar::Wait(cMutex &_mutex) +bool cCondVar::Wait(cMutex &Mutex) { - return pthread_cond_wait(&cond, &_mutex.mutex); + return pthread_cond_wait(&cond, &Mutex.mutex); } /* -bool cCondVar::TimedWait(cMutex &_mutex, unsigned long tmout) +bool cCondVar::TimedWait(cMutex &Mutex, unsigned long tmout) { - return pthread_cond_timedwait(&cond, &_mutex.mutex, tmout); + return pthread_cond_timedwait(&cond, &Mutex.mutex, tmout); } */ @@ -43,10 +43,12 @@ void cCondVar::Broadcast(void) pthread_cond_broadcast(&cond); } +/* void cCondVar::Signal(void) { pthread_cond_signal(&cond); } +*/ // --- cMutex ---------------------------------------------------------------- @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: thread.h 1.7 2001/08/02 13:48:48 kls Exp $ + * $Id: thread.h 1.8 2001/08/05 10:36:47 kls Exp $ */ #ifndef __THREAD_H @@ -21,10 +21,10 @@ private: public: cCondVar(void); ~cCondVar(); - bool Wait(cMutex &_mutex); - //bool TimedWait(cMutex &_mutex, unsigned long tmout); + bool Wait(cMutex &Mutex); + //bool TimedWait(cMutex &Mutex, unsigned long tmout); void Broadcast(void); - void Signal(void); + //void Signal(void); }; class cMutex { |