1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Changed cDvbDevice::GrabImage() to use V4L2

This commit is contained in:
Klaus Schmidinger 2008-12-22 10:26:16 +01:00
parent 7702a6c7e3
commit 7b2085b575
3 changed files with 92 additions and 56 deletions

View File

@ -1478,6 +1478,7 @@ Marco Schl
for a patch that was used to implement handling of DVB-S2 for a patch that was used to implement handling of DVB-S2
for fixing setting the date in the channel display of the classic and sttng skins, for fixing setting the date in the channel display of the classic and sttng skins,
to avoid unnecessary OSD access to avoid unnecessary OSD access
for changing cDvbDevice::GrabImage() to use V4L2
Jürgen Schmitz <j.schmitz@web.de> Jürgen Schmitz <j.schmitz@web.de>
for reporting a bug in displaying the current channel when switching via the SVDRP for reporting a bug in displaying the current channel when switching via the SVDRP

View File

@ -5849,9 +5849,10 @@ Video Disk Recorder Revision History
the patch from ftp://ftp.cadsoft.de/vdr/Developer/av7110_v4ldvb_api5_audiobuf_test_1.diff the patch from ftp://ftp.cadsoft.de/vdr/Developer/av7110_v4ldvb_api5_audiobuf_test_1.diff
to the driver (thanks to Oliver Endriss). to the driver (thanks to Oliver Endriss).
2008-12-20: Version 1.7.3 2008-12-22: Version 1.7.3
- Updated the Russian OSD texts (thanks to Oleg Roitburd). - Updated the Russian OSD texts (thanks to Oleg Roitburd).
- Fixed handling the 'pointer field' in generating and parsing PAT/PMT (thanks to - Fixed handling the 'pointer field' in generating and parsing PAT/PMT (thanks to
Frank Schmirler). Frank Schmirler).
- Fixed handling modulation types for DVB-S transponders when processing the NIT. - Fixed handling modulation types for DVB-S transponders when processing the NIT.
- Changed cDvbDevice::GrabImage() to use V4L2 (thanks to Marco Schlüßler).

View File

@ -4,13 +4,13 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbdevice.c 2.6 2008/12/13 14:38:07 kls Exp $ * $Id: dvbdevice.c 2.7 2008/12/22 10:24:10 kls Exp $
*/ */
#include "dvbdevice.h" #include "dvbdevice.h"
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <linux/videodev.h> #include <linux/videodev2.h>
#include <linux/dvb/audio.h> #include <linux/dvb/audio.h>
#include <linux/dvb/dmx.h> #include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h> #include <linux/dvb/frontend.h>
@ -604,69 +604,103 @@ uchar *cDvbDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int S
int videoDev = open(buffer, O_RDWR); int videoDev = open(buffer, O_RDWR);
if (videoDev >= 0) { if (videoDev >= 0) {
uchar *result = NULL; uchar *result = NULL;
struct video_mbuf mbuf; // set up the size and RGB
if (ioctl(videoDev, VIDIOCGMBUF, &mbuf) == 0) { v4l2_format fmt;
int msize = mbuf.size; memset(&fmt, 0, sizeof(fmt));
unsigned char *mem = (unsigned char *)mmap(0, msize, PROT_READ | PROT_WRITE, MAP_SHARED, videoDev, 0); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (mem && mem != (unsigned char *)-1) { fmt.fmt.pix.width = SizeX;
// set up the size and RGB fmt.fmt.pix.height = SizeY;
struct video_capability vc; fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
if (ioctl(videoDev, VIDIOCGCAP, &vc) == 0) { fmt.fmt.pix.field = V4L2_FIELD_ANY;
struct video_mmap vm; if (ioctl(videoDev, VIDIOC_S_FMT, &fmt) == 0) {
vm.frame = 0; v4l2_requestbuffers reqBuf;
if ((SizeX > 0) && (SizeX <= vc.maxwidth) && memset(&reqBuf, 0, sizeof(reqBuf));
(SizeY > 0) && (SizeY <= vc.maxheight)) { reqBuf.count = 2;
vm.width = SizeX; reqBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vm.height = SizeY; reqBuf.memory = V4L2_MEMORY_MMAP;
} if (ioctl(videoDev, VIDIOC_REQBUFS, &reqBuf) >= 0) {
else { v4l2_buffer mbuf;
vm.width = vc.maxwidth; memset(&mbuf, 0, sizeof(mbuf));
vm.height = vc.maxheight; mbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
} mbuf.memory = V4L2_MEMORY_MMAP;
vm.format = VIDEO_PALETTE_RGB24; if (ioctl(videoDev, VIDIOC_QUERYBUF, &mbuf) == 0) {
if (ioctl(videoDev, VIDIOCMCAPTURE, &vm) == 0 && ioctl(videoDev, VIDIOCSYNC, &vm.frame) == 0) { int msize = mbuf.length;
// make RGB out of BGR: unsigned char *mem = (unsigned char *)mmap(0, msize, PROT_READ | PROT_WRITE, MAP_SHARED, videoDev, 0);
int memsize = vm.width * vm.height; if (mem && mem != (unsigned char *)-1) {
unsigned char *mem1 = mem; v4l2_buffer buf;
for (int i = 0; i < memsize; i++) { memset(&buf, 0, sizeof(buf));
unsigned char tmp = mem1[2]; buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
mem1[2] = mem1[0]; buf.memory = V4L2_MEMORY_MMAP;
mem1[0] = tmp; buf.index = 0;
mem1 += 3; if (ioctl(videoDev, VIDIOC_QBUF, &buf) == 0) {
} v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl (videoDev, VIDIOC_STREAMON, &type) == 0) {
memset(&buf, 0, sizeof(buf));
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
if (ioctl(videoDev, VIDIOC_DQBUF, &buf) == 0) {
if (ioctl(videoDev, VIDIOC_STREAMOFF, &type) == 0) {
// make RGB out of BGR:
int memsize = fmt.fmt.pix.width * fmt.fmt.pix.height;
unsigned char *mem1 = mem;
for (int i = 0; i < memsize; i++) {
unsigned char tmp = mem1[2];
mem1[2] = mem1[0];
mem1[0] = tmp;
mem1 += 3;
}
if (Quality < 0) if (Quality < 0)
Quality = 100; Quality = 100;
dsyslog("grabbing to %s %d %d %d", Jpeg ? "JPEG" : "PNM", Quality, vm.width, vm.height); dsyslog("grabbing to %s %d %d %d", Jpeg ? "JPEG" : "PNM", Quality, fmt.fmt.pix.width, fmt.fmt.pix.height);
if (Jpeg) { if (Jpeg) {
// convert to JPEG: // convert to JPEG:
result = RgbToJpeg(mem, vm.width, vm.height, Size, Quality); result = RgbToJpeg(mem, fmt.fmt.pix.width, fmt.fmt.pix.height, Size, Quality);
if (!result) if (!result)
esyslog("ERROR: failed to convert image to JPEG"); esyslog("ERROR: failed to convert image to JPEG");
} }
else { else {
// convert to PNM: // convert to PNM:
char buf[32]; char buf[32];
snprintf(buf, sizeof(buf), "P6\n%d\n%d\n255\n", vm.width, vm.height); snprintf(buf, sizeof(buf), "P6\n%d\n%d\n255\n", fmt.fmt.pix.width, fmt.fmt.pix.height);
int l = strlen(buf); int l = strlen(buf);
int bytes = memsize * 3; int bytes = memsize * 3;
Size = l + bytes; Size = l + bytes;
result = MALLOC(uchar, Size); result = MALLOC(uchar, Size);
if (result) { if (result) {
memcpy(result, buf, l); memcpy(result, buf, l);
memcpy(result + l, mem, bytes); memcpy(result + l, mem, bytes);
}
else
esyslog("ERROR: failed to convert image to PNM");
}
}
else
esyslog("ERROR: video device VIDIOC_STREAMOFF failed");
}
else
esyslog("ERROR: video device VIDIOC_DQBUF failed");
} }
else else
esyslog("ERROR: failed to convert image to PNM"); esyslog("ERROR: video device VIDIOC_STREAMON failed");
} }
else
esyslog("ERROR: video device VIDIOC_QBUF failed");
munmap(mem, msize);
} }
else
esyslog("ERROR: failed to memmap video device");
} }
munmap(mem, msize); else
esyslog("ERROR: video device VIDIOC_QUERYBUF failed");
} }
else else
esyslog("ERROR: failed to memmap video device"); esyslog("ERROR: video device VIDIOC_REQBUFS failed");
} }
else
esyslog("ERROR: video device VIDIOC_S_FMT failed");
close(videoDev); close(videoDev);
return result; return result;
} }