From patchwork Fri Mar 25 22:54:43 2005 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reinhard Nissl X-Patchwork-Id: 11822 Received: from pop.gmx.net ([213.165.64.20] helo=mail.gmx.net) by www.linuxtv.org with smtp (Exim 4.34) id 1DExhm-0002if-Bk for vdr@linuxtv.org; Fri, 25 Mar 2005 23:55:02 +0100 Received: (qmail invoked by alias); 25 Mar 2005 22:54:43 -0000 Received: from D312f.d.pppool.de (EHLO [192.168.101.15]) [80.184.49.47] by mail.gmx.net (mp007) with SMTP; 25 Mar 2005 23:54:43 +0100 X-Authenticated: #527675 Message-ID: <424496B3.7060009@gmx.de> Date: Fri, 25 Mar 2005 23:54:43 +0100 From: Reinhard Nissl User-Agent: Mozilla Thunderbird 1.0 (X11/20041206) X-Accept-Language: en-us, en MIME-Version: 1.0 To: Klaus Schmidinger's VDR Subject: Re: [vdr] vdr-xine: what's wrong with this piece of code-- threadingissue? References: <1378040502EA7F46A1EB0DB1A826D7A53CC80B@ad-atlas.teklaad.tekla.com> In-Reply-To: <1378040502EA7F46A1EB0DB1A826D7A53CC80B@ad-atlas.teklaad.tekla.com> X-Y-GMX-Trusted: 0 X-BeenThere: vdr@linuxtv.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: Klaus Schmidinger's VDR List-Id: Klaus Schmidinger's VDR List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 25 Mar 2005 22:55:02 -0000 Status: O X-Status: X-Keywords: X-UID: 1100 Hi, Rantanen Teemu wrote: >>This typically happens when moving cutting marks, and I'm >>investigating this already. >> >>Expect it for 0.8.0, but the next release will still be 0.7.3. > > Looking forward to both 0.8.0 and 0.7.3 ... > > In my experience the most problems I've had are starting/ending > recording, and all rewinds. At these points may happen that xine > disconnects. Not very often but sometimes. When xine disconnects VDR > will "play" the recording really fast and it's minutes past the place > when xine reconnects. I've had no problems with cutting marks... Please apply the attached patch to vdr-1.3.23 and tell me, whether there is any improvement. At least there was one for me ;-) Bye. --- ../vdr-1.3.23-orig/dvbplayer.c 2005-01-14 15:00:56.000000000 +0100 +++ dvbplayer.c 2005-03-25 19:44:38.000000000 +0100 @@ -358,6 +358,89 @@ void cDvbPlayer::Activate(bool On) } } +static uchar *findStartCode(uchar *Data, int Length) +{ + uchar *limit = Data + Length; + Data += 6 + 3 + Data[6 + 2] + 3; // move to PES payload and skip 00 00 01 + while (Data < limit) { + // possible start codes that appear before/after picture data + // 00 00 01 B3: sequence header code + // 00 00 01 B8: group start code + // 00 00 01 00: picture start code + // 00 00 01 B7: sequence end code + if (0x01 == Data[-1] && (0xB3 == Data[0] || 0xB8 == Data[0] || 0x00 == Data[0] || 0xB7 == Data[0]) && 0x00 == Data[-2] && 0x00 == Data[-3]) + return Data - 3; + Data++; + } + + return 0; +} + +static void fixIFrameHead(uchar *Data, int Length) +{ + uchar *p = findStartCode(Data, Length); + if (!p) { + esyslog("fixIframeHead: start code not found!\n"); + return; + } + + Data += 6 + 3 + Data[6 + 2]; // move to PES payload + if (Data < p) + memset(Data, 0, p - Data); // zero preceeding bytes +} + +static int fixIFrameTail(uchar *Data, int Length, bool StillImage) +{ + uchar *p = findStartCode(Data, Length); + if (!p) { + esyslog("fixIframeTail: start code not found!\n"); + return 0; + } + + int dropBytes = Length - (p - Data); + if (StillImage) + { + // need to append sequence end code + dropBytes -= 4; + p[3] = 0xB7; + } + + // adjust PES payload size + int payloadSize = Data[4] * 256 + Data[5]; + payloadSize -= dropBytes; + Data[4] = payloadSize >> 8; + Data[5] = payloadSize & 0xFF; + + return dropBytes; +} + +static void fixIFrame(uchar *Data, int &Length, bool StillImage) +{ + int done = 0; + + while (done < Length) { + if (0x00 != Data[0] || 0x00 != Data[1] || 0x01 != Data[2]) { + esyslog("fixIFrame: PES start code not found at offset %d (data length: %d)!", done, Length); + return; + } + + int lenPES = 6 + Data[4] * 256 + Data[5]; + if (0xE0 == (0xF0 & Data[ 3 ])) { // video packet + int todo = Length - done; + int bite = (lenPES < todo) ? lenPES : todo; + if (0 == done) // first packet + fixIFrameHead(Data, bite); + else if (bite == todo) // last packet + Length -= fixIFrameTail(Data, bite, StillImage); + } + + done += lenPES; + Data += lenPES; + } +} + +#define IPACKS 2048 // originally defined in remux.c + void cDvbPlayer::Action(void) { uchar *b = NULL; @@ -380,18 +463,25 @@ void cDvbPlayer::Action(void) // Read the next frame from the file: - if (!readFrame && (replayFile >= 0 || readIndex >= 0)) { - if (playMode != pmStill) { + if (playMode != pmStill && playMode != pmPause) { + if (!readFrame && (replayFile >= 0 || readIndex >= 0)) { if (!nonBlockingFileReader->Reading()) { if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) { uchar FileNumber; int FileOffset; int Index = index->GetNextIFrame(readIndex, playDir == pdForward, &FileNumber, &FileOffset, &Length, true); if (Index >= 0) { + Length += IPACKS; // fixIFrame needs next video packet if (!NextFile(FileNumber, FileOffset)) continue; } else { +// // hit end of recording: signal end of file but don't change playMode +// if (playDir == pdForward) { +// readIndex = -1; +// eof = true; +// continue; +// } // hit begin of recording: wait for device buffers to drain // before changing play mode: if (!DeviceFlush(100)) @@ -428,6 +518,8 @@ void cDvbPlayer::Action(void) } int r = nonBlockingFileReader->Read(replayFile, b, Length); if (r > 0) { + if (playMode == pmFast || (playMode == pmSlow && playDir == pdBackward)) + fixIFrame(b, r, false); readFrame = new cFrame(b, -r, ftUnknown, readIndex); // hands over b to the ringBuffer b = NULL; } @@ -438,16 +530,16 @@ void cDvbPlayer::Action(void) break; } } - else - cCondWait::SleepMs(3); // this keeps the CPU load low - } - // Store the frame in the buffer: + // Store the frame in the buffer: - if (readFrame) { - if (ringBuffer->Put(readFrame)) - readFrame = NULL; + if (readFrame) { + if (ringBuffer->Put(readFrame)) + readFrame = NULL; + } } + else + cCondWait::SleepMs(3); // this keeps the CPU load low // Get the next frame from the buffer: @@ -659,11 +751,13 @@ void cDvbPlayer::Goto(int Index, bool St int FileOffset, Length; Index = index->GetNextIFrame(Index, false, &FileNumber, &FileOffset, &Length); if (Index >= 0 && NextFile(FileNumber, FileOffset) && Still) { + Length += IPACKS; // fixIFrame needs next video packet uchar b[MAXFRAMESIZE]; int r = ReadFrame(replayFile, b, Length, sizeof(b)); if (r > 0) { if (playMode == pmPause) DevicePlay(); + fixIFrame(b, r, true); DeviceStillPicture(b, r); } playMode = pmStill;