summaryrefslogtreecommitdiff
path: root/PLUGINS/src/dvbhddevice
diff options
context:
space:
mode:
Diffstat (limited to 'PLUGINS/src/dvbhddevice')
-rw-r--r--PLUGINS/src/dvbhddevice/HISTORY4
-rw-r--r--PLUGINS/src/dvbhddevice/Makefile7
-rw-r--r--PLUGINS/src/dvbhddevice/dvbhddevice.c4
-rw-r--r--PLUGINS/src/dvbhddevice/dvbhdffdevice.c217
4 files changed, 225 insertions, 7 deletions
diff --git a/PLUGINS/src/dvbhddevice/HISTORY b/PLUGINS/src/dvbhddevice/HISTORY
index 280e0ad..2fffbea 100644
--- a/PLUGINS/src/dvbhddevice/HISTORY
+++ b/PLUGINS/src/dvbhddevice/HISTORY
@@ -39,7 +39,11 @@ VDR Plugin 'dvbhddevice' Revision History
- Allow to disable true color OSD support via setup option
2011-04-xx: Version 0.0.4
+
- locally define DVB OSD API extensions to support compiling with original DVB headers
- Return correct pixel aspect ratio in GetOsdSize
- Adapt Makefile to changes introduced in recent VDR versions
+2012-12-27: Version 0.0.5
+
+- Adapted Makefile to changes introduced in recent VDR versions.
diff --git a/PLUGINS/src/dvbhddevice/Makefile b/PLUGINS/src/dvbhddevice/Makefile
index ef6ef51..67ff5e0 100644
--- a/PLUGINS/src/dvbhddevice/Makefile
+++ b/PLUGINS/src/dvbhddevice/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for a Video Disk Recorder plugin
#
-# $Id: Makefile 1.19 2012/12/23 10:01:00 kls Exp $
+# $Id: Makefile 1.20 2012/12/28 10:08:50 kls Exp $
# The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin.
@@ -19,6 +19,7 @@ VERSION = $(shell grep 'static const char \*VERSION *=' $(PLUGIN).c | awk '{ pri
PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(shell pkg-config --variable=$(1) vdr || pkg-config --variable=$(1) ../../../vdr.pc))
LIBDIR = $(DESTDIR)$(call PKGCFG,libdir)
LOCDIR = $(DESTDIR)$(call PKGCFG,locdir)
+PLGCFG = $(call PKGCFG,plgcfg)
#
TMPDIR ?= /tmp
@@ -31,6 +32,10 @@ export CXXFLAGS = $(call PKGCFG,cxxflags)
APIVERSION = $(call PKGCFG,apiversion)
+### Allow user defined options to overwrite defaults:
+
+-include $(PLGCFG)
+
### The name of the distribution archive:
ARCHIVE = $(PLUGIN)-$(VERSION)
diff --git a/PLUGINS/src/dvbhddevice/dvbhddevice.c b/PLUGINS/src/dvbhddevice/dvbhddevice.c
index 20b6762..2218e3f 100644
--- a/PLUGINS/src/dvbhddevice/dvbhddevice.c
+++ b/PLUGINS/src/dvbhddevice/dvbhddevice.c
@@ -3,7 +3,7 @@
*
* See the README file for copyright information and how to reach the author.
*
- * $Id: dvbhddevice.c 1.17 2012/06/07 09:33:18 kls Exp $
+ * $Id: dvbhddevice.c 1.18 2012/12/27 10:30:48 kls Exp $
*/
#include <vdr/plugin.h>
@@ -12,7 +12,7 @@
#include "menu.h"
#include "setup.h"
-static const char *VERSION = "0.0.4";
+static const char *VERSION = "0.0.5";
static const char *DESCRIPTION = trNOOP("HD Full Featured DVB device");
static const char *MAINMENUENTRY = "dvbhddevice";
diff --git a/PLUGINS/src/dvbhddevice/dvbhdffdevice.c b/PLUGINS/src/dvbhddevice/dvbhdffdevice.c
index 845fa6b..e81d93b 100644
--- a/PLUGINS/src/dvbhddevice/dvbhdffdevice.c
+++ b/PLUGINS/src/dvbhddevice/dvbhdffdevice.c
@@ -3,7 +3,7 @@
*
* See the README file for copyright information and how to reach the author.
*
- * $Id: dvbhdffdevice.c 1.46 2012/11/15 09:19:10 kls Exp $
+ * $Id: dvbhdffdevice.c 1.47 2012/12/29 13:23:22 kls Exp $
*/
#include <stdint.h>
@@ -23,6 +23,10 @@
#include "hdffosd.h"
#include "setup.h"
+
+static uchar *YuvToJpeg(uchar *Mem, int Width, int Height, int &Size, int Quality);
+
+
// --- cDvbHdFfDevice ----------------------------------------------------------
int cDvbHdFfDevice::devHdffOffset = -1;
@@ -123,8 +127,112 @@ cSpuDecoder *cDvbHdFfDevice::GetSpuDecoder(void)
uchar *cDvbHdFfDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
{
- //TODO
- return NULL;
+ #define BUFFER_SIZE (sizeof(struct v4l2_pix_format) + 1920 * 1080 * 2)
+ int fd;
+ uint8_t * buffer;
+ uint8_t * result = NULL;
+
+ fd = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDONLY);
+ if (fd < 0) {
+ esyslog("GrabImage: failed open DVB video device");
+ return NULL;
+ }
+
+ buffer = (uint8_t *) malloc(BUFFER_SIZE);
+ if (buffer)
+ {
+ int readBytes;
+
+ readBytes = read(fd, buffer, BUFFER_SIZE);
+ if (readBytes < (int) sizeof(struct v4l2_pix_format))
+ esyslog("GrabImage: failed reading from DVB video device");
+ else {
+ struct v4l2_pix_format * pixfmt;
+ int dataSize;
+
+ pixfmt = (struct v4l2_pix_format *) buffer;
+ dsyslog("GrabImage: Read image of size %d x %d",
+ pixfmt->width, pixfmt->height);
+ dataSize = readBytes - sizeof(struct v4l2_pix_format);
+ if (dataSize < (int) pixfmt->sizeimage)
+ esyslog("GrabImage: image is not complete");
+ else {
+ if (Jpeg) {
+ uint8_t * temp;
+ temp = (uint8_t *) malloc(pixfmt->width * 3 * pixfmt->height);
+ if (temp) {
+ int numPixels = pixfmt->width * pixfmt->height;
+ uint8_t * destData = temp;
+ uint8_t * srcData = buffer + sizeof(struct v4l2_pix_format);
+ while (numPixels > 0)
+ {
+ destData[0] = srcData[1];
+ destData[1] = srcData[0];
+ destData[2] = srcData[2];
+ destData[3] = srcData[3];
+ destData[4] = srcData[0];
+ destData[5] = srcData[2];
+ srcData += 4;
+ destData += 6;
+ numPixels -= 2;
+ }
+ if (Quality < 0)
+ Quality = 100;
+ result = YuvToJpeg(temp, pixfmt->width, pixfmt->height, Size, Quality);
+ free(temp);
+ }
+ }
+ else {
+ // convert to PNM:
+ char buf[32];
+ snprintf(buf, sizeof(buf), "P6\n%d\n%d\n255\n",
+ pixfmt->width, pixfmt->height);
+ int l = strlen(buf);
+ Size = l + pixfmt->width * 3 * pixfmt->height;
+ result = (uint8_t *) malloc(Size);
+ if (result)
+ {
+ memcpy(result, buf, l);
+ uint8_t * destData = result + l;
+ uint8_t * srcData = buffer + sizeof(struct v4l2_pix_format);
+ int numPixels = pixfmt->width * pixfmt->height;
+ while (numPixels > 0)
+ {
+ int cb = srcData[0] - 128;
+ int y1 = srcData[1];
+ int cr = srcData[2] - 128;
+ int y2 = srcData[3];
+ int r;
+ int g;
+ int b;
+
+ r = y1 + (int) (1.402f * cr);
+ g = y1 - (int) (0.344f * cb + 0.714f * cr);
+ b = y1 + (int) (1.772f * cb);
+ destData[0] = r > 255 ? 255 : r < 0 ? 0 : r;
+ destData[1] = g > 255 ? 255 : g < 0 ? 0 : g;
+ destData[2] = b > 255 ? 255 : b < 0 ? 0 : b;
+ r = y2 + (int) (1.402f * cr);
+ g = y2 - (int) (0.344f * cb + 0.714f * cr);
+ b = y2 + (int) (1.772f * cb);
+ destData[3] = r > 255 ? 255 : r < 0 ? 0 : r;
+ destData[4] = g > 255 ? 255 : g < 0 ? 0 : g;
+ destData[5] = b > 255 ? 255 : b < 0 ? 0 : b;
+
+ srcData += 4;
+ destData += 6;
+ numPixels -= 2;
+ }
+ }
+ }
+ }
+ }
+ free(buffer);
+ }
+
+ close(fd);
+
+ return result;
}
void cDvbHdFfDevice::SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
@@ -423,7 +531,7 @@ bool cDvbHdFfDevice::SetPlayMode(ePlayMode PlayMode)
mHdffCmdIf->CmdAvSetDecoderInput(0, 2);
ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY);
- }
+ }
}
playMode = PlayMode;
return true;
@@ -840,3 +948,104 @@ bool cDvbHdFfDeviceProbe::Probe(int Adapter, int Frontend)
}
return false;
}
+
+
+// --- YuvToJpeg -------------------------------------------------------------
+
+#include <jpeglib.h>
+
+#define JPEGCOMPRESSMEM 4000000
+
+struct tJpegCompressData {
+ int size;
+ uchar *mem;
+ };
+
+static void JpegCompressInitDestination(j_compress_ptr cinfo)
+{
+ tJpegCompressData *jcd = (tJpegCompressData *)cinfo->client_data;
+ if (jcd) {
+ cinfo->dest->free_in_buffer = jcd->size = JPEGCOMPRESSMEM;
+ cinfo->dest->next_output_byte = jcd->mem = MALLOC(uchar, jcd->size);
+ }
+}
+
+static boolean JpegCompressEmptyOutputBuffer(j_compress_ptr cinfo)
+{
+ tJpegCompressData *jcd = (tJpegCompressData *)cinfo->client_data;
+ if (jcd) {
+ int Used = jcd->size;
+ int NewSize = jcd->size + JPEGCOMPRESSMEM;
+ if (uchar *NewBuffer = (uchar *)realloc(jcd->mem, NewSize)) {
+ jcd->size = NewSize;
+ jcd->mem = NewBuffer;
+ }
+ else {
+ esyslog("ERROR: out of memory");
+ return false;
+ }
+ if (jcd->mem) {
+ cinfo->dest->next_output_byte = jcd->mem + Used;
+ cinfo->dest->free_in_buffer = jcd->size - Used;
+ return true;
+ }
+ }
+ return false;
+}
+
+static void JpegCompressTermDestination(j_compress_ptr cinfo)
+{
+ tJpegCompressData *jcd = (tJpegCompressData *)cinfo->client_data;
+ if (jcd) {
+ int Used = cinfo->dest->next_output_byte - jcd->mem;
+ if (Used < jcd->size) {
+ if (uchar *NewBuffer = (uchar *)realloc(jcd->mem, Used)) {
+ jcd->size = Used;
+ jcd->mem = NewBuffer;
+ }
+ else
+ esyslog("ERROR: out of memory");
+ }
+ }
+}
+
+static uchar *YuvToJpeg(uchar *Mem, int Width, int Height, int &Size, int Quality)
+{
+ if (Quality < 0)
+ Quality = 0;
+ else if (Quality > 100)
+ Quality = 100;
+
+ jpeg_destination_mgr jdm;
+
+ jdm.init_destination = JpegCompressInitDestination;
+ jdm.empty_output_buffer = JpegCompressEmptyOutputBuffer;
+ jdm.term_destination = JpegCompressTermDestination;
+
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+ cinfo.dest = &jdm;
+ tJpegCompressData jcd;
+ cinfo.client_data = &jcd;
+ cinfo.image_width = Width;
+ cinfo.image_height = Height;
+ cinfo.input_components = 3;
+ cinfo.in_color_space = JCS_YCbCr;
+
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, Quality, true);
+ jpeg_start_compress(&cinfo, true);
+
+ int rs = Width * 3;
+ JSAMPROW rp[Height];
+ for (int k = 0; k < Height; k++)
+ rp[k] = &Mem[rs * k];
+ jpeg_write_scanlines(&cinfo, rp, Height);
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+
+ Size = jcd.size;
+ return jcd.mem;
+}