Hi Reinhard. Tried the new repacker, but it was not successful : Jul 18 08:42:04 media vdr[4972]: cVideoRepacker: found system start code: stream seems to be scrambled or not demultiplexed Jul 18 08:42:04 media vdr[4972]: cVideoRepacker: skipped 1545 bytes while syncing on next picture Jul 18 08:42:04 media vdr[4972]: cVideoRepacker: skipped 493 bytes while syncing on next picture Jul 18 08:42:04 media vdr[4972]: cVideoRepacker: skipped 2039 bytes while syncing on next picture Jul 18 08:42:04 media last message repeated 5 times Jul 18 08:42:04 media vdr[4972]: cVideoRepacker: skipped 1398 bytes while syncing on next picture Jul 18 08:42:04 media vdr[4972]: cVideoRepacker: skipped 4 bytes to sync on next picture Jul 18 08:42:04 media vdr[4969]: cVideoRepacker: found system start code: stream seems to be scrambled or not demultiplexed Jul 18 08:42:04 media vdr[4969]: cVideoRepacker: skipped 1545 bytes while syncing on next picture Jul 18 08:42:04 media vdr[4969]: cVideoRepacker: skipped 493 bytes while syncing on next picture Jul 18 08:42:04 media vdr[4969]: cVideoRepacker: skipped 2039 bytes while syncing on next picture Jul 18 08:42:04 media last message repeated 5 times Jul 18 08:42:04 media vdr[4969]: cVideoRepacker: skipped 1398 bytes while syncing on next picture Jul 18 08:42:04 media vdr[4969]: cVideoRepacker: skipped 4 bytes to sync on next picture Jul 18 08:42:20 media vdr[4970]: ERROR: 1 ring buffer overflow (65 bytes dropped) Jul 18 08:42:26 media vdr[4970]: ERROR: 10022 ring buffer overflows (1884136 bytes dropped) Jul 18 08:42:32 media vdr[4970]: ERROR: 9840 ring buffer overflows (1849920 bytes dropped) Jul 18 08:42:35 media vdr[4968]: ERROR: video data stream broken Jul 18 08:42:35 media vdr[4968]: initiating emergency exit Jul 18 08:42:35 media vdr[4555]: emergency exit requested - shutting down ----- Original Message ----- From: "Reinhard Nissl" <rnissl@xxxxxx> To: "Klaus Schmidinger's VDR" <vdr@xxxxxxxxxxx> Sent: Sunday, July 17, 2005 11:17 AM Subject: VDR-1.3.27: updated cVideoRepacker > Hi, > > I'd like to invite you to test the attached patch which now also > supports MPEG1 video streams (vdr-1.3.27-remux-repacker.patch). > > Besides that, a major change has been made in error reporting. Previous > versions often reported a buffer overflow (although there was no buffer > overflow) just as an indication for not beeing able to handle the data. > Most likely this lead to the assumption that the repacker got stuck. > > VDR-1.3.28 will also (most likely) receive the second attached patch > "vdr-1.3.27-dvbplayer-sequence-end-code.patch". It will cause a still > image to be immediately shown by (softdevices like) vdr-xine, e. g. when > moving or jumping to cutting marks. Does this patch have any bad impact > on FF-devices? > > As old recordings (prior to VDR-1.3.26 or 1.3.27 with cVideoRepacker > disabled) can have fragmented frames and VDR doesn't handle them > correctly when passing still images to a device, it is hardly possible > to edit cutting marks (at least) in vdr-xine for such recordings. > > The patch http://home.vr-web.de/~rnissl/vdr-1.3.24-dvbplayer.patch is a > hack to at least fix the I-frames needed for fast forward, fast rewind, > slow rewind and editing cutting marks. As you may see, it collides with > the attached dvbplayer patch, so you have to decide whether to use the > attached one and just edit new recordings or to use the one taken at > version 1.3.24 and be able to edit new and old -- but only MPEG2 -- > recordings. > > Bye. > -- > Dipl.-Inform. (FH) Reinhard Nissl > mailto:rnissl@xxxxxx > -------------------------------------------------------------------------------- > --- vdr-1.3.27-orig/remux.c 2005-06-19 12:17:00.000000000 +0200 > +++ vdr-1.3.27/remux.c 2005-07-16 20:54:47.499277234 +0200 > @@ -26,17 +26,92 @@ class cRepacker { > protected: > int maxPacketSize; > uint8_t subStreamId; > + static void DroppedData(const char *Reason, int Count) { esyslog("%s > (dropped %d bytes)", Reason, Count); } > + static int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int > Count) > + { > + int n = ResultBuffer->Put(Data, Count); > + if (n != Count) > + esyslog("ERROR: result buffer overflow, dropped %d out of %d > byte", Count - n, Count); > + return n; > + } > + static int AnalyzePesHeader(const uchar *Data, int Count, int > &PesPayloadOffset, bool *ContinueationHeader = 0); > public: > cRepacker(void) { maxPacketSize = 6 + 65535; subStreamId = 0; } > virtual ~cRepacker() {} > virtual void Reset(void) {} > - virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int > Count) = 0; > + virtual void Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, > int Count) = 0; > virtual int BreakAt(const uchar *Data, int Count) = 0; > virtual int QuerySnoopSize(void) { return 0; } > void SetMaxPacketSize(int MaxPacketSize) { maxPacketSize = > MaxPacketSize; } > void SetSubStreamId(uint8_t SubStreamId) { subStreamId = SubStreamId; } > }; > > +int cRepacker::AnalyzePesHeader(const uchar *Data, int Count, int > &PesPayloadOffset, bool *ContinueationHeader) > +{ > + if (Count < 7) > + return -1; // too short > + > + if ((Data[6] & 0xC0) == 0x80) { // MPEG 2 > + if (Count < 9) > + return -1; // too short > + > + PesPayloadOffset = 6 + 3 + Data[8]; > + if (Count < PesPayloadOffset) > + return -1; // too short > + > + if (ContinueationHeader) > + *ContinueationHeader = ((Data[6] == 0x80) && !Data[7] && > !Data[8]); > + > + return 2; // MPEG 2 > + } > + > + // check for MPEG 1 ... > + PesPayloadOffset = 6; > + > + // skip up to 16 stuffing bytes > + for (int i = 0; i < 16; i++) { > + if (Data[PesPayloadOffset] != 0xFF) > + break; > + > + if (Count <= ++PesPayloadOffset) > + return -1; // too short > + } > + > + // skip STD_buffer_scale/size > + if ((Data[PesPayloadOffset] & 0xC0) == 0x40) { > + PesPayloadOffset += 2; > + > + if (Count <= PesPayloadOffset) > + return -1; // too short > + } > + > + if (ContinueationHeader) > + *ContinueationHeader = false; > + > + if ((Data[PesPayloadOffset] & 0xF0) == 0x20) { > + // skip PTS only > + PesPayloadOffset += 5; > + } > + else if ((Data[PesPayloadOffset] & 0xF0) == 0x30) { > + // skip PTS and DTS > + PesPayloadOffset += 10; > + } > + else if (Data[PesPayloadOffset] == 0x0F) { > + // continueation header > + PesPayloadOffset++; > + > + if (ContinueationHeader) > + *ContinueationHeader = true; > + } > + else > + return 0; // unknown > + > + if (Count < PesPayloadOffset) > + return -1; // too short > + > + return 1; // MPEG 1 > +} > + > // --- > cVideoRepacker -------------------------------------------------------- > > class cVideoRepacker : public cRepacker { > @@ -61,7 +136,7 @@ private: > public: > cVideoRepacker(void); > virtual void Reset(void); > - virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int > Count); > + virtual void Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, > int Count); > virtual int BreakAt(const uchar *Data, int Count); > virtual int QuerySnoopSize() { return 4; } > }; > @@ -95,7 +170,7 @@ bool cVideoRepacker::PushOutPacket(cRing > // to strip off any partially contained start code. > int Bite = fragmentLen + (Count >= 0 ? 0 : Count); > // put data into result buffer > - int n = ResultBuffer->Put(fragmentData, Bite); > + int n = Put(ResultBuffer, fragmentData, Bite); > if (n != Bite) { > Reset(); > return false; > @@ -110,7 +185,7 @@ bool cVideoRepacker::PushOutPacket(cRing > // to strip off any partially contained start code. > int Bite = pesHeaderLen + (Count >= 0 ? 0 : Count); > // put data into result buffer > - int n = ResultBuffer->Put(pesHeader, Bite); > + int n = Put(ResultBuffer, pesHeader, Bite); > if (n != Bite) { > Reset(); > return false; > @@ -122,7 +197,7 @@ bool cVideoRepacker::PushOutPacket(cRing > // amount of data to put into result buffer > int Bite = Count; > // put data into result buffer > - int n = ResultBuffer->Put(Data, Bite); > + int n = Put(ResultBuffer, Data, Bite); > if (n != Bite) { > Reset(); > return false; > @@ -132,23 +207,29 @@ bool cVideoRepacker::PushOutPacket(cRing > return true; > } > > -int cVideoRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar > *Data, int Count) > +void cVideoRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar > *Data, int Count) > { > + // synchronisation is detected some bytes after frame start. > + const int SkippedBytesLimit = 4; > + > // reset local scanner > localStart = -1; > - > - // check for MPEG 2 > - if ((Data[6] & 0xC0) != 0x80) > - return 0; > > - // backup PES header > - if (Data[6] != 0x80 || Data[7] != 0x00 || Data[8] != 0x00) { > - pesHeaderBackupLen = 6 + 3 + Data[8]; > - memcpy(pesHeaderBackup, Data, pesHeaderBackupLen); > + int pesPayloadOffset = 0; > + bool continueationHeader = false; > + int mpegLevel = AnalyzePesHeader(Data, Count, pesPayloadOffset, > &continueationHeader); > + if (mpegLevel <= 0) { > + DroppedData("cVideoRepacker: no valid PES packet header found", > Count); > + return; > } > + if (!continueationHeader) { > + // backup PES header > + pesHeaderBackupLen = pesPayloadOffset; > + memcpy(pesHeaderBackup, Data, pesHeaderBackupLen); > + } > > // skip PES header > - int done = 6 + 3 + Data[8]; > + int done = pesPayloadOffset; > int todo = Count - done; > const uchar *data = Data + done; > // remember start of the data > @@ -191,15 +272,17 @@ int cVideoRepacker::Put(cRingBufferLinea > // the byte count get's negative then the current > buffer ends in a > // partitial start code that must be stripped off, as > it shall be put > // in the next packet. > - if (!PushOutPacket(ResultBuffer, payload, data - 3 - > payload)) > - return done - 3; > + if (!PushOutPacket(ResultBuffer, payload, data - 3 - > payload)) { > + DroppedData("cVideoRepacker: result buffer > overflow", Count - (done - 3)); > + return; > + } > // go on with syncing to the next picture > state = syncing; > } > if (state == syncing) { > // report that syncing dropped some bytes > - if (skippedBytes > 4) > - esyslog("cVideoRepacker: skipped %d bytes to sync > on next picture", skippedBytes - 4); > + if (skippedBytes > SkippedBytesLimit) > + esyslog("cVideoRepacker: skipped %d bytes to sync > on next picture", skippedBytes - SkippedBytesLimit); > skippedBytes = 0; > // if there is a PES header available, then use it > ... > if (pesHeaderBackupLen > 0) { > @@ -222,9 +305,14 @@ int cVideoRepacker::Put(cRingBufferLinea > pesHeader[pesHeaderLen++] = Data[3]; // video > stream ID > pesHeader[pesHeaderLen++] = 0x00; // length still > unknown > pesHeader[pesHeaderLen++] = 0x00; // length still > unknown > - pesHeader[pesHeaderLen++] = 0x80; > - pesHeader[pesHeaderLen++] = 0x00; > - pesHeader[pesHeaderLen++] = 0x00; > + > + if (mpegLevel == 2) { > + pesHeader[pesHeaderLen++] = 0x80; > + pesHeader[pesHeaderLen++] = 0x00; > + pesHeader[pesHeaderLen++] = 0x00; > + } > + else > + pesHeader[pesHeaderLen++] = 0x0F; > } > // append the first three bytes of the start code > pesHeader[pesHeaderLen++] = 0x00; > @@ -299,8 +387,10 @@ int cVideoRepacker::Put(cRingBufferLinea > const uchar *excessData = fragmentData + fragmentLen + bite; > // a negative byte count means to drop some bytes from the > current > // fragment's tail, to not exceed the maximum packet size. > - if (!PushOutPacket(ResultBuffer, payload, bite)) > - return done; > + if (!PushOutPacket(ResultBuffer, payload, bite)) { > + DroppedData("cVideoRepacker: result buffer overflow", > Count - done); > + return; > + } > // create a continuation PES header > pesHeaderLen = 0; > pesHeader[pesHeaderLen++] = 0x00; > @@ -309,9 +399,15 @@ int cVideoRepacker::Put(cRingBufferLinea > pesHeader[pesHeaderLen++] = Data[3]; // video stream ID > pesHeader[pesHeaderLen++] = 0x00; // length still unknown > pesHeader[pesHeaderLen++] = 0x00; // length still unknown > - pesHeader[pesHeaderLen++] = 0x80; > - pesHeader[pesHeaderLen++] = 0x00; > - pesHeader[pesHeaderLen++] = 0x00; > + > + if (mpegLevel == 2) { > + pesHeader[pesHeaderLen++] = 0x80; > + pesHeader[pesHeaderLen++] = 0x00; > + pesHeader[pesHeaderLen++] = 0x00; > + } > + else > + pesHeader[pesHeaderLen++] = 0x0F; > + > // copy any excess data > while (bite++ < 0) { > // append the excess data here > @@ -344,22 +440,20 @@ int cVideoRepacker::Put(cRingBufferLinea > fragmentLen += bite; > } > } > - // we've eaten the whole packet ;-) > - return Count; > + // report that syncing dropped some bytes > + if (skippedBytes > SkippedBytesLimit) { > + esyslog("cVideoRepacker: skipped %d bytes while syncing on next > picture", skippedBytes - SkippedBytesLimit); > + skippedBytes = SkippedBytesLimit; > + } > } > > int cVideoRepacker::BreakAt(const uchar *Data, int Count) > { > - // enough data for test? > - if (Count < 6 + 3) > - return -1; > - // check for MPEG 2 > - if ((Data[6] & 0xC0) != 0x80) > - return -1; > - int headerLen = Data[8] + 6 + 3; > - // enough data for test? > - if (Count < headerLen) > - return -1; > + int PesPayloadOffset = 0; > + > + if (AnalyzePesHeader(Data, Count, PesPayloadOffset) <= 0) > + return -1; // not enough data for test > + > // just detect end of picture > if (state == scanPicture) { > // setup local scanner > @@ -368,7 +462,7 @@ int cVideoRepacker::BreakAt(const uchar > localStart = 0; > } > // start where we've stopped at the last run > - const uchar *data = Data + headerLen + localStart; > + const uchar *data = Data + PesPayloadOffset + localStart; > const uchar *limit = Data + Count; > // scan data > while (data < limit) { > @@ -386,7 +480,7 @@ int cVideoRepacker::BreakAt(const uchar > } > } > // just fill up packet and append next start code > - return headerLen + packetTodo + 4; > + return PesPayloadOffset + packetTodo + 4; > } > > // --- > cDolbyRepacker -------------------------------------------------------- > @@ -412,6 +506,7 @@ private: > get_length, > output_packet > } state; > + int skippedBytes; > void ResetPesHeader(bool ContinuationFrame = false); > void AppendSubStreamID(bool ContinuationFrame = false); > bool FinishRemainder(cRingBufferLinear *ResultBuffer, const uchar *const > Data, const int Todo, int &Done, int &Bite); > @@ -419,7 +514,7 @@ private: > public: > cDolbyRepacker(void); > virtual void Reset(void); > - virtual int Put(cRingBufferLinear *ResultBuffer, const uchar *Data, int > Count); > + virtual void Repack(cRingBufferLinear *ResultBuffer, const uchar *Data, > int Count); > virtual int BreakAt(const uchar *Data, int Count); > }; > > @@ -490,6 +585,7 @@ void cDolbyRepacker::Reset(void) > fragmentLen = 0; > fragmentTodo = 0; > pesHeaderBackupLen = 0; > + skippedBytes = 0; > } > > bool cDolbyRepacker::FinishRemainder(cRingBufferLinear *ResultBuffer, > const uchar *const Data, const int Todo, int &Done, int &Bite) > @@ -499,7 +595,7 @@ bool cDolbyRepacker::FinishRemainder(cRi > // output a previous fragment first > if (fragmentLen > 0) { > Bite = fragmentLen; > - int n = ResultBuffer->Put(fragmentData, Bite); > + int n = Put(ResultBuffer, fragmentData, Bite); > if (Bite != n) { > Reset(); > return false; > @@ -507,7 +603,7 @@ bool cDolbyRepacker::FinishRemainder(cRi > fragmentLen = 0; > } > Bite = fragmentTodo; > - int n = ResultBuffer->Put(Data, Bite); > + int n = Put(ResultBuffer, Data, Bite); > if (Bite != n) { > Reset(); > Done += n; > @@ -543,13 +639,13 @@ bool cDolbyRepacker::StartNewPacket(cRin > Bite = pesHeaderLen; > // enough data available to put PES packet into buffer? > if (packetLen - pesHeaderLen <= Todo) { > - int n = ResultBuffer->Put(pesHeader, Bite); > + int n = Put(ResultBuffer, pesHeader, Bite); > if (Bite != n) { > Reset(); > return false; > } > Bite = packetLen - pesHeaderLen; > - n = ResultBuffer->Put(Data, Bite); > + n = Put(ResultBuffer, Data, Bite); > if (Bite != n) { > Reset(); > Done += n; > @@ -582,11 +678,16 @@ bool cDolbyRepacker::StartNewPacket(cRin > return true; > } > > -int cDolbyRepacker::Put(cRingBufferLinear *ResultBuffer, const uchar > *Data, int Count) > +void cDolbyRepacker::Repack(cRingBufferLinear *ResultBuffer, const uchar > *Data, int Count) > { > + // synchronisation is detected some bytes after frame start. > + const int SkippedBytesLimit = 4; > + > // check for MPEG 2 > - if ((Data[6] & 0xC0) != 0x80) > - return 0; > + if ((Data[6] & 0xC0) != 0x80) { > + DroppedData("cDolbyRepacker: MPEG 2 PES header expected", Count); > + return; > + } > > // backup PES header > if (Data[6] != 0x80 || Data[7] != 0x00 || Data[8] != 0x00) { > @@ -616,6 +717,7 @@ int cDolbyRepacker::Put(cRingBufferLinea > data++; > done++; > todo--; > + skippedBytes++; // collect number of skipped bytes while > syncing > continue; > case find_77: > if (*data != 0x77) { > @@ -625,18 +727,21 @@ int cDolbyRepacker::Put(cRingBufferLinea > data++; > done++; > todo--; > + skippedBytes++; // collect number of skipped bytes while > syncing > ++(int &)state; > continue; > case store_chk1: > chk1 = *data++; > done++; > todo--; > + skippedBytes++; // collect number of skipped bytes while > syncing > ++(int &)state; > continue; > case store_chk2: > chk2 = *data++; > done++; > todo--; > + skippedBytes++; // collect number of skipped bytes while > syncing > ++(int &)state; > continue; > case get_length: > @@ -664,6 +769,10 @@ int cDolbyRepacker::Put(cRingBufferLinea > state = find_0b; > continue; > } > + // report that syncing dropped some bytes > + if (skippedBytes > SkippedBytesLimit) > + esyslog("cDolbyRepacker: skipped %d bytes to sync on > next AC3 frame", skippedBytes - SkippedBytesLimit); > + skippedBytes = 0; > // append read data to header for common output processing > pesHeader[pesHeaderLen++] = 0x0B; > pesHeader[pesHeaderLen++] = 0x77; > @@ -676,13 +785,17 @@ int cDolbyRepacker::Put(cRingBufferLinea > int bite = 0; > // finish remainder of ac3 frame? > if (fragmentTodo > 0) { > - if (!FinishRemainder(ResultBuffer, data, todo, done, > bite)) > - return done; > + if (!FinishRemainder(ResultBuffer, data, todo, done, > bite)) { > + DroppedData("cDolbyRepacker: result buffer > overflow", Count - done); > + return; > + } > } > else { > // start a new packet > - if (!StartNewPacket(ResultBuffer, data, todo, done, > bite)) > - return done; > + if (!StartNewPacket(ResultBuffer, data, todo, done, > bite)) { > + DroppedData("cDolbyRepacker: result buffer > overflow", Count - done); > + return; > + } > // prepare for next (continuation) packet > ResetPesHeader(state == output_packet); > } > @@ -693,7 +806,11 @@ int cDolbyRepacker::Put(cRingBufferLinea > } > } > } > - return Count; > + // report that syncing dropped some bytes > + if (skippedBytes > SkippedBytesLimit) { > + esyslog("cDolbyRepacker: skipped %d bytes while syncing on next AC3 > frame", skippedBytes - 4); > + skippedBytes = SkippedBytesLimit; > + } > } > > int cDolbyRepacker::BreakAt(const uchar *Data, int Count) > @@ -845,9 +962,13 @@ void cTS2PES::Clear(void) > > void cTS2PES::store(uint8_t *Data, int Count) > { > - int n = repacker ? repacker->Put(resultBuffer, Data, Count) : > resultBuffer->Put(Data, Count); > - if (n != Count) > - esyslog("ERROR: result buffer overflow, dropped %d out of %d byte", > Count - n, Count); > + if (repacker) > + repacker->Repack(resultBuffer, Data, Count); > + else { > + int n = resultBuffer->Put(Data, Count); > + if (n != Count) > + esyslog("ERROR: result buffer overflow, dropped %d out of %d > byte", Count - n, Count); > + } > } > > void cTS2PES::reset_ipack(void) > @@ -867,7 +988,7 @@ void cTS2PES::reset_ipack(void) > > void cTS2PES::send_ipack(void) > { > - if (count < 10) > + if (count <= ((mpeg == 2) ? 9 : 7)) // skip empty packets > return; > buf[3] = (AUDIO_STREAM_S <= cid && cid <= AUDIO_STREAM_E && audioCid) ? > audioCid : cid; > buf[4] = (uint8_t)(((count - 6) & 0xFF00) >> 8); > @@ -1155,7 +1276,7 @@ cRemux::cRemux(int VPid, const int *APid > resultBuffer = new cRingBufferLinear(RESULTBUFFERSIZE, IPACKS, false, > "Result"); > resultBuffer->SetTimeouts(0, 100); > if (VPid) > -//#define TEST_cVideoRepacker > +#define TEST_cVideoRepacker > #ifdef TEST_cVideoRepacker > ts2pes[numTracks++] = new cTS2PES(VPid, resultBuffer, IPACKS, 0x00, > 0x00, new cVideoRepacker); > #else > -------------------------------------------------------------------------------- > --- ../vdr-1.3.27-orig/dvbplayer.c 2005-05-22 13:26:51.000000000 +0200 > +++ dvbplayer.c 2005-07-16 22:57:43.000000000 +0200 > @@ -666,11 +666,34 @@ 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) { > - uchar b[MAXFRAMESIZE]; > + uchar b[MAXFRAMESIZE + 4 + 5 + 4]; > int r = ReadFrame(replayFile, b, Length, sizeof(b)); > if (r > 0) { > if (playMode == pmPause) > DevicePlay(); > + // append sequence end code to get the image shown immediately > with softdevices > + if (r > 6) { // should be always true > + b[r++] = 0x00; > + b[r++] = 0x00; > + b[r++] = 0x01; > + b[r++] = b[3]; > + if (b[6] & 0x80) { // MPEG 2 > + b[r++] = 0x00; > + b[r++] = 0x07; > + b[r++] = 0x80; > + b[r++] = 0x00; > + b[r++] = 0x00; > + } > + else { // MPEG 1 > + b[r++] = 0x00; > + b[r++] = 0x05; > + b[r++] = 0x0F; > + } > + b[r++] = 0x00; > + b[r++] = 0x00; > + b[r++] = 0x01; > + b[r++] = 0xB7; > + } > DeviceStillPicture(b, r); > } > playMode = pmStill; > -------------------------------------------------------------------------------- > _______________________________________________ > vdr mailing list > vdr@xxxxxxxxxxx > http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr > -------------------------------------------------------------------------------- No virus found in this incoming message. Checked by AVG Anti-Virus. Version: 7.0.323 / Virus Database: 267.9.0/49 - Release Date: 16/07/2005