[vdr] VDR-1.3.27: updated cVideoRepacker
Simon Baxter
linuxtv at nzbaxters.com
Mon Jul 18 10:26:25 CEST 2005
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 at gmx.de>
To: "Klaus Schmidinger's VDR" <vdr at linuxtv.org>
Sent: Sunday, July 17, 2005 11:17 AM
Subject: [vdr] 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 at gmx.de
>
--------------------------------------------------------------------------------
> --- 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 at linuxtv.org
> 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
More information about the vdr
mailing list