Changed cDvbDevice::GrabImage() to use V4L2 (backport from version 1.7.3)

This commit is contained in:
Klaus Schmidinger 2012-02-14 13:41:52 +01:00
parent 1857a0ca20
commit 17485ccc96
5 changed files with 103 additions and 60 deletions

View File

@ -2363,3 +2363,7 @@ Edgar Toernig <froese@gmx.de>
Winfried Köhler <w_koehl@gmx.de> Winfried Köhler <w_koehl@gmx.de>
for fixing wrong value for TableIdBAT in libsi/si.h for fixing wrong value for TableIdBAT in libsi/si.h
Ralf Schueler <dl4mw@schueler.ws>
for backporting "Changed cDvbDevice::GrabImage() to use V4L" from version 1.7.3
to 1.6.0-3

View File

@ -5758,3 +5758,8 @@ Video Disk Recorder Revision History
- Fixed wrong value for TableIdBAT in libsi/si.h (thanks to Winfried Köhler). - Fixed wrong value for TableIdBAT in libsi/si.h (thanks to Winfried Köhler).
- Removed unneeded include files <linux/dvb/dmx.h> und <time.h> from remux.h - Removed unneeded include files <linux/dvb/dmx.h> und <time.h> from remux.h
(reported by Tobias Grimm). (reported by Tobias Grimm).
2012-02-14: Version 1.6.0-3
- Changed cDvbDevice::GrabImage() to use V4L2
(backport from version 1.7.3, thanks to Ralf Schueler).

View File

@ -4,7 +4,7 @@
* 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: config.h 1.310.1.2 2008/09/06 14:30:00 kls Exp $ * $Id: config.h 1.310.1.3 2012/02/14 12:16:31 kls Exp $
*/ */
#ifndef __CONFIG_H #ifndef __CONFIG_H
@ -22,7 +22,7 @@
// VDR's own version number: // VDR's own version number:
#define VDRVERSION "1.6.0-2" #define VDRVERSION "1.6.0-3"
#define VDRVERSNUM 10600 // Version * 10000 + Major * 100 + Minor #define VDRVERSNUM 10600 // Version * 10000 + Major * 100 + Minor
// The plugin API's version number: // The plugin API's version number:

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 1.170 2008/02/09 16:11:44 kls Exp $ * $Id: dvbdevice.c 1.170.1.1 2012/02/14 12:36:30 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>
@ -521,69 +521,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;
} }

View File

@ -4,7 +4,7 @@
* 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.h 1.47 2008/02/08 13:48:31 kls Exp $ * $Id: dvbdevice.h 1.47.1.1 2012/02/14 12:46:35 kls Exp $
*/ */
#ifndef __DVBDEVICE_H #ifndef __DVBDEVICE_H
@ -15,8 +15,8 @@
#include "device.h" #include "device.h"
#include "dvbspu.h" #include "dvbspu.h"
#if DVB_API_VERSION != 3 #if (DVB_API_VERSION << 8 | DVB_API_VERSION_MINOR) < 0x0300
#error VDR requires Linux DVB driver API version 3! #error VDR requires Linux DVB driver API version 3.0 or higher!
#endif #endif
#define MAXDVBDEVICES 8 #define MAXDVBDEVICES 8