diff options
Diffstat (limited to 'PLUGINS/src/dvbhddevice')
-rw-r--r-- | PLUGINS/src/dvbhddevice/HISTORY | 4 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/Makefile | 7 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/dvbhddevice.c | 4 | ||||
-rw-r--r-- | PLUGINS/src/dvbhddevice/dvbhdffdevice.c | 217 |
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; +} |