summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2000-09-17 13:47:06 +0200
committerKlaus Schmidinger <vdr@tvdr.de>2000-09-17 13:47:06 +0200
commit925780c20f09c7d0ef4a921f355a47f5e472878e (patch)
treec934c608bb59b3bda0a9cde282fcb22d8458914f
parentb3c78919d5e8dcfcf8f5eb635bbb86efa98a3fa4 (diff)
downloadvdr-925780c20f09c7d0ef4a921f355a47f5e472878e.tar.gz
vdr-925780c20f09c7d0ef4a921f355a47f5e472878e.tar.bz2
Implemented overlay handling
-rw-r--r--CONTRIBUTORS1
-rw-r--r--HISTORY3
-rw-r--r--dvbapi.c157
-rw-r--r--dvbapi.h23
-rw-r--r--svdrp.c122
-rw-r--r--svdrp.h9
6 files changed, 310 insertions, 5 deletions
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index fd220b16..03fd4bc0 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -20,6 +20,7 @@ Guido Fiala <gfiala@s.netic.de>
for implementing slow forward/back
for implementing the SVDRP command 'HITK'
for implementing image grabbing
+ for implementing overlay capabilities (see his 'kvdr' tool at http://www.s.netic.de/gfiala)
Robert Schneider <Robert.Schneider@lotus.com>
for implementing EIT support for displaying the current/next info
diff --git a/HISTORY b/HISTORY
index 6fade416..a54c3dcd 100644
--- a/HISTORY
+++ b/HISTORY
@@ -187,3 +187,6 @@ Video Disk Recorder Revision History
a parameter for a list of all valid key names.
- The new SVDRP command 'GRAB' (thanks to Guido Fiala!) can be used to grab
the current frame and save it to a file.
+- The new SVDRP commands 'OVL*' can be used to control video overlays (thanks
+ to Guido Fiala!). This is mainly for use in the 'kvdr' tool (see the 'kvdr'
+ page at http://www.s.netic.de/gfiala).
diff --git a/dvbapi.c b/dvbapi.c
index 2c8a6ba1..1468de60 100644
--- a/dvbapi.c
+++ b/dvbapi.c
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: dvbapi.c 1.26 2000/09/17 11:53:35 kls Exp $
+ * $Id: dvbapi.c 1.27 2000/09/17 12:45:55 kls Exp $
*/
#include "dvbapi.h"
@@ -1069,6 +1069,11 @@ cDvbApi::cDvbApi(const char *FileName)
if (videoDev < 0)
LOG_ERROR;
cols = rows = 0;
+
+ ovlGeoSet = ovlStat = ovlFbSet = false;
+ ovlBrightness = ovlColour = ovlHue = ovlContrast = 32768;
+ ovlClipCount = 0;
+
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
initscr();
keypad(stdscr, true);
@@ -1093,6 +1098,7 @@ cDvbApi::~cDvbApi()
Close();
Stop();
StopRecord();
+ OvlO(false); //Overlay off!
close(videoDev);
}
#if defined(DEBUG_OSD) || defined(REMOTE_KBD)
@@ -1274,10 +1280,159 @@ bool cDvbApi::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX,
LOG_ERROR_STR(FileName);
result |= 1;
}
+
+ if (ovlStat && ovlGeoSet) {
+ // switch the Overlay on again (gf: why have i to do anything again?)
+ OvlG(ovlSizeX, ovlSizeY, ovlPosX, ovlPosY);
+ }
+ if (ovlFbSet)
+ OvlP(ovlBrightness, ovlColour, ovlHue, ovlContrast);
+
munmap(mem, msize);
return result == 0;
}
+bool cDvbApi::OvlF(int SizeX, int SizeY, int FbAddr, int Bpp, int Palette)
+{
+ int result = 0;
+ // get the actual X-Server settings???
+ // plausibility-check problem: can't be verified w/o X-server!!!
+ if (SizeX <= 0 || SizeY <= 0 || FbAddr == 0 || Bpp / 8 > 4 ||
+ Bpp / 8 <= 0 || Palette <= 0 || Palette > 13 || ovlClipCount < 0 ||
+ SizeX > 4096 || SizeY > 4096) {
+ ovlFbSet = ovlGeoSet = false;
+ OvlO(false);
+ return false;
+ }
+ else {
+ dsyslog(LOG_INFO, "OvlF: %d %d %x %d %d", SizeX, SizeY, FbAddr, Bpp, Palette);
+ // this is the problematic part!
+ struct video_buffer vb;
+ result |= ioctl(videoDev, VIDIOCGFBUF, &vb);
+ vb.base = (void*)FbAddr;
+ vb.depth = Bpp;
+ vb.height = SizeY;
+ vb.width = SizeX;
+ vb.bytesperline = ((vb.depth + 1) / 8) * vb.width;
+ //now the real thing: setting the framebuffer
+ result |= ioctl(videoDev, VIDIOCSFBUF, &vb);
+ if (result) {
+ ovlFbSet = ovlGeoSet = false;
+ ovlClipCount = 0;
+ OvlO(false);
+ return false;
+ }
+ else {
+ ovlFbSizeX = SizeX;
+ ovlFbSizeY = SizeY;
+ ovlBpp = Bpp;
+ ovlPalette = Palette;
+ ovlFbSet = true;
+ return true;
+ }
+ }
+}
+
+bool cDvbApi::OvlG(int SizeX, int SizeY, int PosX, int PosY)
+{
+ int result = 0;
+ // get the actual X-Server settings???
+ struct video_capability vc;
+ result |= ioctl(videoDev, VIDIOCGCAP, &vc);
+ if (!ovlFbSet)
+ return false;
+ if (SizeX < vc.minwidth || SizeY < vc.minheight ||
+ SizeX > vc.maxwidth || SizeY>vc.maxheight
+// || PosX > FbSizeX || PosY > FbSizeY
+// PosX < -SizeX || PosY < -SizeY ||
+ ) {
+ ovlGeoSet = false;
+ OvlO(false);
+ return false;
+ }
+ else {
+ struct video_window vw;
+ result |= ioctl(videoDev, VIDIOCGWIN, &vw);
+ vw.x = PosX;
+ vw.y = PosY;
+ vw.width = SizeX;
+ vw.height = SizeY;
+ vw.chromakey = ovlPalette;
+ vw.flags = VIDEO_WINDOW_CHROMAKEY; // VIDEO_WINDOW_INTERLACE; //VIDEO_CLIP_BITMAP;
+ vw.clips = ovlClipRects;
+ vw.clipcount = ovlClipCount;
+ result |= ioctl(videoDev, VIDIOCSWIN, &vw);
+ if (result) {
+ ovlGeoSet = false;
+ ovlClipCount = 0;
+ return false;
+ }
+ else {
+ ovlSizeX = SizeX;
+ ovlSizeY = SizeY;
+ ovlPosX = PosX;
+ ovlPosY = PosY;
+ ovlGeoSet = true;
+ ovlStat = true;
+ return true;
+ }
+ }
+}
+
+bool cDvbApi::OvlC(int ClipCount, CRect *cr)
+{
+ if (ovlGeoSet && ovlFbSet) {
+ for (int i = 0; i < ClipCount; i++) {
+ ovlClipRects[i].x = cr[i].x;
+ ovlClipRects[i].y = cr[i].y;
+ ovlClipRects[i].width = cr[i].width;
+ ovlClipRects[i].height = cr[i].height;
+ ovlClipRects[i].next = &(ovlClipRects[i + 1]);
+ }
+ ovlClipCount = ClipCount;
+ //use it:
+ return OvlG(ovlSizeX, ovlSizeY, ovlPosX, ovlPosY);
+ }
+ return false;
+}
+
+bool cDvbApi::OvlP(__u16 Brightness, __u16 Colour, __u16 Hue, __u16 Contrast)
+{
+ int result = 0;
+ ovlBrightness = Brightness;
+ ovlColour = Colour;
+ ovlHue = Hue;
+ ovlContrast = Contrast;
+ struct video_picture vp;
+ if (!ovlFbSet)
+ return false;
+ result |= ioctl(videoDev, VIDIOCGPICT, &vp);
+ vp.brightness = Brightness;
+ vp.colour = Colour;
+ vp.hue = Hue;
+ vp.contrast = Contrast;
+ vp.depth = ovlBpp;
+ vp.palette = ovlPalette; // gf: is this always ok? VIDEO_PALETTE_RGB565;
+ result |= ioctl(videoDev, VIDIOCSPICT, &vp);
+ return result == 0;
+}
+
+bool cDvbApi::OvlO(bool Value)
+{
+ int result = 0;
+ if (!ovlGeoSet && Value)
+ return false;
+ int one = 1;
+ int zero = 0;
+ result |= ioctl(videoDev, VIDIOCCAPTURE, Value ? &one : &zero);
+ ovlStat = Value;
+ if (result) {
+ ovlStat = false;
+ return false;
+ }
+ return true;
+}
+
#ifdef DEBUG_OSD
void cDvbApi::SetColor(eDvbColor colorFg, eDvbColor colorBg)
{
diff --git a/dvbapi.h b/dvbapi.h
index 5ae3a513..08ba4bfc 100644
--- a/dvbapi.h
+++ b/dvbapi.h
@@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: dvbapi.h 1.15 2000/09/17 11:43:10 kls Exp $
+ * $Id: dvbapi.h 1.16 2000/09/17 12:15:05 kls Exp $
*/
#ifndef __DVBAPI_H
@@ -21,6 +21,12 @@ typedef unsigned char __u8;
#include <stdio.h>
#include <dvb.h>
+// Overlay facilities
+#define MAXCLIPRECTS 100
+typedef struct CRect {
+ signed short x, y, width, height;
+ };
+
#define MenuLines 15
#define MenuColumns 40
@@ -74,6 +80,21 @@ public:
bool GrabImage(const char *FileName, bool Jpeg = true, int Quality = -1, int SizeX = -1, int SizeY = -1);
+ // Overlay facilities
+
+private:
+ bool ovlStat, ovlGeoSet, ovlFbSet;
+ int ovlSizeX, ovlSizeY, ovlPosX, ovlPosY, ovlBpp, ovlPalette, ovlClips, ovlClipCount;
+ int ovlFbSizeX, ovlFbSizeY;
+ __u16 ovlBrightness, ovlColour, ovlHue, ovlContrast;
+ struct video_clip ovlClipRects[MAXCLIPRECTS];
+public:
+ bool OvlF(int SizeX, int SizeY, int FbAddr, int Bpp, int Palette);
+ bool OvlG(int SizeX, int SizeY, int PosX, int PosY);
+ bool OvlC(int ClipCount, CRect *Cr);
+ bool OvlP(__u16 Brightness, __u16 Color, __u16 Hue, __u16 Contrast);
+ bool OvlO(bool Value);
+
// On Screen Display facilities
private:
diff --git a/svdrp.c b/svdrp.c
index 09cffe3d..c9ea7c38 100644
--- a/svdrp.c
+++ b/svdrp.c
@@ -10,7 +10,7 @@
* and interact with the Video Disk Recorder - or write a full featured
* graphical interface that sits on top of an SVDRP connection.
*
- * $Id: svdrp.c 1.9 2000/09/17 11:29:33 kls Exp $
+ * $Id: svdrp.c 1.10 2000/09/17 13:39:37 kls Exp $
*/
#define _GNU_SOURCE
@@ -154,6 +154,16 @@ const char *HelpPages[] = {
" Create a new timer. Settings must be in the same format as returned\n"
" by the LSTT command. It is an error if a timer with the same channel,\n"
" day, start and stop time already exists.",
+ "OVLF <sizex> <sizey> <fbaddr> <bpp> <palette>\n"
+ " Set the size, address depth and palette of the overlay.",
+ "OVLG <sizex> <sizey> <posx> <posy>\n"
+ " Set the size and position of the overlay.",
+ "OVLC <clipcount> <base16-CRect-array>\n"
+ " Set the overlay clipping rectangles.",
+ "OVLP <brightness> <colour> <hue> <contrast>\n"
+ " Set the picture parameters for the overlay.",
+ "OVLO 0 | 1\n"
+ " Switch the overlay on or off.",
"UPDT <settings>\n"
" Updates a timer. Settings must be in the same format as returned\n"
" by the LSTT command. If a timer with the same channel, day, start\n"
@@ -240,8 +250,11 @@ bool cSVDRP::Send(const char *s, int length)
int wbytes = write(file, s, length);
if (wbytes == length)
return true;
- if (wbytes < 0)
+ if (wbytes < 0) {
LOG_ERROR;
+ file.Close();
+ cDvbApi::PrimaryDvbApi->OvlO(false);
+ }
else //XXX while...???
esyslog(LOG_ERR, "Wrote %d bytes to client while expecting %d\n", wbytes, length);
return false;
@@ -659,6 +672,106 @@ void cSVDRP::CmdNEWT(const char *Option)
Reply(501, "Missing timer settings");
}
+void cSVDRP::CmdOVLF(const char *Option)
+{
+ if (*Option) {
+ int SizeX = 0, SizeY = 0, Bpp = 0, Palette = 0, FbAddr = 0;
+ if (5 == sscanf(Option, "%d %d %x %d %d", &SizeX, &SizeY, &FbAddr, &Bpp, &Palette)) {
+ //somehow_set_overlay_geometry;
+ if (cDvbApi::PrimaryDvbApi->OvlF(SizeX, SizeY, FbAddr, Bpp, Palette))
+ Reply(250, "Overlay framebuffer set");
+ else
+ Reply(451, "Illegal overlay framebuffer settings");
+ }
+ else
+ Reply(501, "Could not parse overlay framebuffer settings");
+ }
+ else
+ Reply(501, "Missing overlay framebuffer settings");
+}
+
+void cSVDRP::CmdOVLG(const char *Option)
+{
+ if (*Option) {
+ int SizeX = 0, SizeY = 0, PosX = 0, PosY = 0;
+ if (4 == sscanf(Option, "%d %d %d %d", &SizeX, &SizeY, &PosX, &PosY)) {
+ //somehow_set_overlay_geometry;
+ if (cDvbApi::PrimaryDvbApi->OvlG(SizeX, SizeY, PosX, PosY))
+ Reply(250, "Overlay geometry set");
+ else
+ Reply(451, "Illegal overlay geometry settings");
+ }
+ else
+ Reply(501, "Could not parse overlay geometry settings");
+ }
+ else
+ Reply(501, "Missing overlay geometry settings");
+}
+
+void cSVDRP::CmdOVLC(const char *Option)
+{
+ if (*Option) {
+ int ClipCount = 0;
+ unsigned char s[2 * MAXCLIPRECTS * sizeof(CRect) + 2];
+ if (2 == sscanf(Option, "%d %s", &ClipCount, s)) {
+ // Base16-decoding of CRect-array:
+ unsigned char *p = (unsigned char*)ovlClipRects;
+ int i = 0, size = sizeof(CRect)*ClipCount;
+ for (int j = 0; i < size; i++) {
+ p[i] = (s[j++] - 65);
+ p[i] += (s[j++] - 65) << 4;
+ }
+ if (((unsigned)ClipCount == (i / sizeof(CRect))) && (ClipCount >= 0)) {
+ // apply it:
+ if (cDvbApi::PrimaryDvbApi->OvlC(ClipCount, ovlClipRects))
+ Reply(250, "Overlay-Clipping set");
+ else
+ Reply(451, "Illegal overlay clipping settings");
+ return;
+ }
+ }
+ Reply(501, "Error parsing Overlay-Clipping settings");
+ }
+ else
+ Reply(501, "Missing Clipping settings");
+}
+
+void cSVDRP::CmdOVLP(const char *Option)
+{
+ if (*Option) {
+ int Brightness = 0, Colour = 0, Hue = 0, Contrast = 0;
+ if (4 == sscanf(Option, "%d %d %d %d", &Brightness, &Colour, &Hue, &Contrast)) {
+ //somehow_set_overlay_picture_settings;
+ if (cDvbApi::PrimaryDvbApi->OvlP(Brightness, Colour, Hue, Contrast))
+ Reply(250, "Overlay picture settings set");
+ else
+ Reply(451, "Illegal overlay picture settings");
+ }
+ else
+ Reply(501, "Could not parse overlay picture settings");
+ }
+ else
+ Reply(501, "Missing overlay picture settings");
+}
+
+void cSVDRP::CmdOVLO(const char *Option)
+{
+ if (*Option) {
+ int Value;
+ if (1 == sscanf(Option, "%d", &Value)) {
+ //somehow_set_overlay_picture_settings;
+ if (cDvbApi::PrimaryDvbApi->OvlO(Value))
+ Reply(250, "Overlay capture set");
+ else
+ Reply(451, "Error setting overlay capture");
+ }
+ else
+ Reply(501, "Could not parse status");
+ }
+ else
+ Reply(501, "Missing overlay capture status");
+}
+
void cSVDRP::CmdUPDT(const char *Option)
{
if (*Option) {
@@ -712,6 +825,11 @@ void cSVDRP::Execute(char *Cmd)
else if (CMD("MOVT")) CmdMOVT(s);
else if (CMD("NEWC")) CmdNEWC(s);
else if (CMD("NEWT")) CmdNEWT(s);
+ else if (CMD("OVLF")) CmdOVLF(s);
+ else if (CMD("OVLG")) CmdOVLG(s);
+ else if (CMD("OVLC")) CmdOVLC(s);
+ else if (CMD("OVLP")) CmdOVLP(s);
+ else if (CMD("OVLO")) CmdOVLO(s);
else if (CMD("UPDT")) CmdUPDT(s);
else if (CMD("QUIT")
|| CMD("\x04")) Close();
diff --git a/svdrp.h b/svdrp.h
index 134332a0..12eb11e3 100644
--- a/svdrp.h
+++ b/svdrp.h
@@ -4,12 +4,13 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
- * $Id: svdrp.h 1.5 2000/09/17 10:22:49 kls Exp $
+ * $Id: svdrp.h 1.6 2000/09/17 13:22:04 kls Exp $
*/
#ifndef __SVDRP_H
#define __SVDRP_H
+#include "dvbapi.h"
#include "tools.h"
class cSocket {
@@ -29,6 +30,7 @@ class cSVDRP {
private:
cSocket socket;
cFile file;
+ CRect ovlClipRects[MAXCLIPRECTS];
void Close(void);
bool Send(const char *s, int length = -1);
void Reply(int Code, const char *fmt, ...);
@@ -46,6 +48,11 @@ private:
void CmdMOVT(const char *Option);
void CmdNEWC(const char *Option);
void CmdNEWT(const char *Option);
+ void CmdOVLF(const char *Option);
+ void CmdOVLG(const char *Option);
+ void CmdOVLC(const char *Option);
+ void CmdOVLP(const char *Option);
+ void CmdOVLO(const char *Option);
void CmdUPDT(const char *Option);
void Execute(char *Cmd);
public: