Mailing List archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[vdr] Re: Nasty bug in StillPicture()
Oliver Endriss wrote:
>
> On Wednesday 15 October 2003 18:47, Stefan Huelswitt wrote:
> > But, in the meantime I found out that this particular bug is a
> > side effect of the AC3overDVB patch and doesn't happens with
> > plain VDR.
> >
> > With plain VDR all non-video packets are stripped from the data
> > buffer before passing it to StillPicture().
Maybe it's not a bad idea to strip these here, anyway, while we're
already scanning the data. This could later even lead to defining
cDevice::StillPicture() as "audio safe".
> Anyway, the range check should be added to the next vdr release.
I have also received a patch from Thomas Heiligenmann which adds
handling of MPEG1 frames.
Here's the complete cDvbDevice::StillPicture(). Please take a look
at it and let me know if this is ok (especially the part marked
"MPEG-1 PES header", since I haven't tested that myself):
void cDvbDevice::StillPicture(const uchar *Data, int Length)
{
#define VIDEO_STILLPICTURE_WORKS_WITH_VDR_FRAMES
#ifdef VIDEO_STILLPICTURE_WORKS_WITH_VDR_FRAMES
if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) {
// PES data
char *buf = MALLOC(char, Length);
if (!buf)
return;
int i = 0;
int blen = 0;
while (i < Length - 6) {
if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) {
int len = Data[i + 4] * 256 + Data[i + 5];
if ((Data[i + 3] & 0xF0) == 0xE0) { // video packet
// skip PES header
int offs = i + 6;
// skip header extension
if ((Data[i + 6] & 0xC0) == 0x80) {
// MPEG-2 PES header
offs += 3;
offs += Data[i + 8];
len -= 3;
len -= Data[i + 8];
}
else {
// MPEG-1 PES header
while (offs < Length && len > 0 && Data[offs] == 0xFF) {
offs++;
len--;
}
if ((Data[offs] & 0xC0) == 0x40) {
offs += 2;
len -= 2;
}
if ((Data[offs] & 0xF0) == 0x20) {
offs += 5;
len -= 5;
}
else if ((Data[offs] & 0xF0) == 0x30) {
offs += 10;
len -= 10;
}
else if (Data[offs] == 0x0F) {
offs++;
len--;
}
}
if (blen + len > Length) // invalid PES length field
break;
memcpy(&buf[blen], &Data[offs], len);
i = offs + len;
blen += len;
}
else if (Data[i + 3] >= 0xBD && Data[i + 3] <= 0xDF) // other PES packets
i += len + 6;
else
i++;
}
else
i++;
}
video_still_picture sp = { buf, blen };
CHECK(ioctl(fd_video, VIDEO_STILLPICTURE, &sp));
free(buf);
}
else {
// non-PES data
video_still_picture sp = { (char *)Data, Length };
CHECK(ioctl(fd_video, VIDEO_STILLPICTURE, &sp));
}
#else
#define MIN_IFRAME 400000
for (int i = MIN_IFRAME / Length + 1; i > 0; i--) {
safe_write(fd_video, Data, Length);
usleep(1); // allows the buffer to be displayed in case the progress display is active
}
#endif
}
Klaus
--
Info:
To unsubscribe send a mail to ecartis@linuxtv.org with "unsubscribe vdr" as subject.
Home |
Main Index |
Thread Index