diff options
Diffstat (limited to 'dvbdevice.c')
-rw-r--r-- | dvbdevice.c | 97 |
1 files changed, 81 insertions, 16 deletions
diff --git a/dvbdevice.c b/dvbdevice.c index f29745b..fd0a0d0 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.c 1.64 2003/09/06 13:19:33 kls Exp $ + * $Id: dvbdevice.c 1.67 2003/10/17 15:36:13 kls Exp $ */ #include "dvbdevice.h" @@ -307,6 +307,8 @@ void cDvbTuner::Action(void) // --- cDvbDevice ------------------------------------------------------------ +int cDvbDevice::devVideoOffset = -1; + cDvbDevice::cDvbDevice(int n) { dvbTuner = NULL; @@ -317,7 +319,7 @@ cDvbDevice::cDvbDevice(int n) // Devices that are present on all card types: - int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK); + int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK); // Devices that are only present on cards with decoders: @@ -329,6 +331,35 @@ cDvbDevice::cDvbDevice(int n) fd_dvr = -1; + // The offset of the /dev/video devices: + + if (devVideoOffset < 0) { // the first one checks this + FILE *f = NULL; + char buffer[PATH_MAX]; + for (int ofs = 0; ofs < 100; ofs++) { + snprintf(buffer, sizeof(buffer), "/proc/video/dev/video%d", ofs); + if ((f = fopen(buffer, "r")) != NULL) { + if (fgets(buffer, sizeof(buffer), f)) { + if (strstr(buffer, "DVB Board")) { // found the _first_ DVB card + devVideoOffset = ofs; + dsyslog("video device offset is %d", devVideoOffset); + break; + } + } + else + break; + fclose(f); + } + else + break; + } + if (devVideoOffset < 0) + devVideoOffset = 0; + if (f) + fclose(f); + } + devVideoIndex = (devVideoOffset >= 0 && HasDecoder()) ? devVideoOffset++ : -1; + // Video format: SetVideoFormat(Setup.VideoFormat ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3); @@ -427,8 +458,10 @@ cSpuDecoder *cDvbDevice::GetSpuDecoder(void) bool cDvbDevice::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY) { + if (devVideoIndex < 0) + return false; char buffer[PATH_MAX]; - snprintf(buffer, sizeof(buffer), "%s%d", DEV_VIDEO, CardIndex()); + snprintf(buffer, sizeof(buffer), "%s%d", DEV_VIDEO, devVideoIndex); int videoDev = open(buffer, O_RDWR); if (videoDev < 0) LOG_ERROR_STR(buffer); @@ -915,21 +948,53 @@ void cDvbDevice::StillPicture(const uchar *Data, int Length) return; int i = 0; int blen = 0; - while (i < Length - 4) { - if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01 && (Data[i + 3] & 0xF0) == 0xE0) { - // skip PES header - int offs = i + 6; + 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]; - // skip header extension - if ((Data[i + 6] & 0xC0) == 0x80) { - offs += 3; - offs += Data[i + 8]; - len -= 3; - len -= Data[i + 8]; + 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; } - 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++; |