summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscop <scop>2005-03-14 22:21:07 +0000
committerscop <scop>2005-03-14 22:21:07 +0000
commit96edccb5cb63380a6b501338c9512bcd458f11fa (patch)
tree36eb14ae769ba80fe173c277508eed8f60c0aca8
parent1b409fbe08c18799d6c82d2483a723ce5d71e4c9 (diff)
downloadvdr-plugin-dxr3-96edccb5cb63380a6b501338c9512bcd458f11fa.tar.gz
vdr-plugin-dxr3-96edccb5cb63380a6b501338c9512bcd458f11fa.tar.bz2
Borrowed OSD scaler from the Xine plugin (Luca Olivetti).
-rw-r--r--HISTORY3
-rw-r--r--Makefile6
-rw-r--r--dxr3interface_spu_encoder.c190
-rw-r--r--dxr3interface_spu_encoder.h155
4 files changed, 352 insertions, 2 deletions
diff --git a/HISTORY b/HISTORY
index e01b65f..c311e11 100644
--- a/HISTORY
+++ b/HISTORY
@@ -264,4 +264,5 @@ NOTE: I havent found time to include all of the languages, will be done in pre2
- improved GetSTC(): fixes DVB subtitles sync problems (Mikko Tuumanen)
- limit OSD flush rate: prevents OSD from going berserk due to being
refreshed too often (Luca Olivetti, Ville Skyttä)
-- improve OSD scaler for small resolutions (#1014339, Luca Olivetti)
+- borrow better OSD scaling routines from the Xine plugin (Luca Olivetti)
+- improve original OSD scaler for small resolutions (#1014339, Luca Olivetti)
diff --git a/Makefile b/Makefile
index 97e1e1b..de708ba 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
#
# Makefile for a Video Disk Recorder plugin
#
-# $Id: Makefile,v 1.1.2.6 2005/03/14 20:48:42 scop Exp $
+# $Id: Makefile,v 1.1.2.7 2005/03/14 22:21:07 scop Exp $
# The official name of this plugin.
# This name will be used in the '-P...' option of VDR to load the plugin.
@@ -61,6 +61,10 @@ DEFINES += -DMICROCODE=\"/usr/share/misc/em8300.uc\"
# where should we write our log?
DEFINES += -DLOGPATH=\"/video/\" # note: path must end with /
+# use OSD scaler borrowed from the Xine plugin?
+# comment this out to use the traditional vdr-dxr3 scaler
+DEFINES += -DUSE_XINE_SCALER
+
### The object files (add further files here):
OBJS = $(PLUGIN).o dxr3multichannelaudio.o dxr3sysclock.o dxr3colormanager.o dxr3syncbuffer.o dxr3audiodecoder.o \
diff --git a/dxr3interface_spu_encoder.c b/dxr3interface_spu_encoder.c
index 8e49216..9553f07 100644
--- a/dxr3interface_spu_encoder.c
+++ b/dxr3interface_spu_encoder.c
@@ -34,6 +34,187 @@ ToDo:
*/
+#ifdef USE_XINE_SCALER
+/*=======================================================================
+ *
+ * Scaling functions taken from the xine plugin
+ *
+ */
+
+#include <math.h>
+#include <signal.h>
+#include <string>
+#include <vdr/plugin.h>
+
+namespace XineScaler
+{
+
+ template <const int yInc = 1, class T = int>
+ class cBresenham
+ {
+ const int m_dx;
+ const int m_dy;
+
+ int m_eps;
+ T m_y;
+
+ public:
+ cBresenham(const int dy, const int dx, const int eps, T const y0 = 0)
+ : m_dx(dx)
+ , m_dy(dy)
+ , m_eps(eps - m_dx)
+ , m_y(y0)
+ {
+ }
+
+ int eps() const
+ {
+ return m_eps;
+ }
+
+ T step()
+ {
+ m_eps += m_dy;
+
+ while (m_eps >= 0)
+ {
+ m_eps -= m_dx;
+
+ m_y += yInc;
+ }
+
+ return m_y;
+ }
+
+ T step(int n)
+ {
+ if (n <= 0)
+ return m_y;
+
+ while (--n > 0)
+ step();
+
+ return step();
+ }
+
+ T stepRelative(int n = 1)
+ {
+ T const y = m_y;
+
+ return step(n) - y;
+ }
+ };
+
+ static uint8_t *ScaleBitmapLQ(const uint8_t *src, uint8_t *dest, int x0, int y0, int w, int h, int ws, int hs, int x1, int y1, int w1, int h1, const uint8_t transparentIndex)
+ {
+ uint8_t *const screen = new uint8_t[ OSDHEIGHT * OSDWIDTH ];
+ {
+ int x1 = x0 + w;
+ int y1 = y0 + h;
+ int x2 = OSDWIDTH;
+ int y2 = OSDHEIGHT;
+
+ if (x1 > x2)
+ x1 = x2;
+
+ if (y1 > y2)
+ y1 = y2;
+
+ uint8_t *dst = screen;
+
+ for (int y = 0; y < y0; y++)
+ {
+ for (int x = 0; x < x2; x++)
+ *dst++ = transparentIndex;
+ }
+
+ for (int y = y0; y < y1; y++)
+ {
+ for (int x = 0; x < x0; x++)
+ *dst++ = transparentIndex;
+
+ for (int x = x0; x < x1; x++)
+ *dst++ = *src++;
+
+ for (int x = x1; x < x2; x++)
+ *dst++ = transparentIndex;
+ }
+
+ for (int y = y1; y < y2; y++)
+ {
+ for (int x = 0; x < x2; x++)
+ *dst++ = transparentIndex;
+ }
+ }
+
+ uint8_t *scaled = dest; //new uint8_t[ hs * ws ];
+ {
+ int x2 = x1 + w1;
+ int y2 = y1 + h1;
+
+ if (x2 > ws)
+ {
+ x2 = ws;
+
+ w1 = x2 - x1;
+ if (w1 < 0)
+ w1 = 0;
+ }
+
+ if (y2 > hs)
+ {
+ y2 = hs;
+
+ h1 = y2 - y1;
+ if (h1 < 0)
+ h1 = 0;
+ }
+
+ cBresenham<OSDWIDTH, uint8_t *> yyBh(2 * OSDHEIGHT, 2 * hs, hs, screen);
+ uint8_t *screen0 = yyBh.step(y1); //(((2 * y1 + 1) * OSDHEIGHT / hs) / 2);
+
+ cBresenham<> xxBh0(2 * OSDWIDTH, 2 * ws, ws);
+ xxBh0.step(x1); //(((2 * x1 + 1) * OSDWIDTH / ws) / 2);
+
+ uint8_t *scaled0 = scaled + y1 * OSDWIDTH; //ws; ******
+
+ for (int y = y1; y < y2; y++)
+ {
+ cBresenham<> xxBh(xxBh0);
+ int xxx = xxBh.step(0); //(((2 * x1 + 1) * OSDWIDTH / ws) / 2);
+
+ uint8_t *screen00 = screen0 + xxx;
+
+ uint8_t *scaled00 = scaled0 + x1;
+
+ for (int x = x1; x < x2; x++)
+ {
+ *scaled00++ = *screen00;
+
+ screen00 += xxBh.stepRelative();
+ }
+
+ scaled0 += OSDWIDTH; //ws; *******
+
+ screen0 = yyBh.step();
+ }
+ }
+
+ delete [] screen;
+
+ return scaled;
+ }
+
+};
+
+/*=======================================================================
+ *
+ * End of scaling functions taken from the xine plugin
+ *
+ */
+#endif /* USE_XINE_SCALER */
+
+
// ==================================
// dec.
cSpuData::~cSpuData()
@@ -341,12 +522,19 @@ void cSPUEncoder::EncodePixelbufRle(int x, int y, int w, int h, u_char *inbuf, i
pb.x = w;
pb.y = h;
+#ifdef USE_XINE_SCALER
+ int ws = cDxr3Interface::Instance().GetHorizontalSize();
+ int hs = cDxr3Interface::Instance().GetVerticalSize();
+ if (ws < 720 || hs < 576 )
+ inbuf = XineScaler::ScaleBitmapLQ(inbuf, OSD_Screen2, 0, 0, OSDWIDTH, OSDHEIGHT, ws, hs, 0, 0, ws, hs, 0 /* clrTransparent */);
+#else
if (cDxr3Interface::Instance().GetHorizontalSize() < 700)
{
double fac = (double)OSDWIDTH / (double)OSDWIDTH2;
ScaleOSD(fac, inbuf,10);
inbuf = OSD_Screen2;
}
+#endif /* USE_XINE_SCALER */
m_ColorManager = new cColorManager();
@@ -374,6 +562,7 @@ void cSPUEncoder::EncodePixelbufRle(int x, int y, int w, int h, u_char *inbuf, i
delete m_ColorManager;
}
+#ifndef USE_XINE_SCALER
// ==================================
void cSPUEncoder::ScaleOSD(double fac, unsigned char* buf, unsigned char NumColors)
{
@@ -431,6 +620,7 @@ void cSPUEncoder::ScaleOSD(double fac, unsigned char* buf, unsigned char NumColo
}
}
}
+#endif /* not USE_XINE_SCALER */
// ==================================
// taken from mplayer (spuenc.c)
diff --git a/dxr3interface_spu_encoder.h b/dxr3interface_spu_encoder.h
new file mode 100644
index 0000000..20119b0
--- /dev/null
+++ b/dxr3interface_spu_encoder.h
@@ -0,0 +1,155 @@
+/*
+ * dxr3interface_spu_encoder.h - encodes an OSD bitmap as subpicture
+ *
+ * Assimilated and adapted by
+ * Stefan Schluenss <dxr3_osd@schluenss.de>
+ * Nov. 2002
+ *
+ * Based on the subpicture encoding routines from MPlayer and
+ * the information given by
+ * Samuel Hocevar
+ * Michel Lespinasse
+ * and http://members.aol.com/mpucoder/DVD/spu.html
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#ifndef _DXR3_INTERFACE_SPU_ENCODER_
+#define _DXR3_INTERFACE_SPU_ENCODER_
+
+#include <stdlib.h>
+#include <linux/dvb/osd.h>
+#include "dxr3vdrincludes.h"
+#include "dxr3palettemanager.h"
+#include "dxr3colormanager.h"
+#include "dxr3interface.h"
+#include "dxr3singleton.h"
+
+// ==================================
+#define MAXWINDOWS 8
+#define DATASIZE 53220
+#define OSDWIDTH 720
+#define OSDWIDTH2 480
+#define OSDHEIGHT 576
+
+// ==================================
+// basic infos about one osd "window"
+struct sOSD_Window
+{
+ size_t x0;
+ size_t y0;
+ size_t x1;
+ size_t y1;
+
+ unsigned char colors[16];
+ unsigned char opacity[16];
+
+ size_t NumColors;
+};
+
+// ==================================
+// used to get active osd area
+struct sRectal
+{
+ sRectal() : x0(0), x1(0), y0(0), y1(0) {}
+
+ size_t x0;
+ size_t x1;
+ size_t y0;
+ size_t y1;
+};
+
+// ==================================
+// our spu(data) with all needed routines
+class cSpuData
+{
+public:
+ cSpuData(): count(0), malloc_size(0) {}
+ ~cSpuData();
+
+ void Clear();
+ u_char* GetData() const { return data; }
+
+ // write operations
+ void WriteByte(uint8_t byte);
+ void WriteNibble(int *higher_nibble, uint8_t nibble);
+ void WriteRle(int *higher_nibble, int length, int color);
+
+private:
+ u_char *data;
+ size_t count; // the count of bytes written
+ size_t malloc_size; // size of data
+};
+
+// ==================================
+struct pixbuf
+{
+ int x, y;
+ u_int rgb[4];
+ u_char* pixels;
+};
+
+// ==================================
+struct encodedata
+{
+ u_char data[DATASIZE];
+ int count; // the count of bytes written
+ int oddstart;
+ int nibblewaiting;
+};
+
+// ==================================
+class cSPUEncoder : public Singleton<cSPUEncoder>
+{
+public:
+ cSPUEncoder();
+ ~cSPUEncoder() {}
+
+ int Cmd(OSD_Command cmd, int color = 0, int x0 = 0, int y0 = 0, int x1 = 0, int y1 = 0, const void *data = 0);
+
+private:
+ cSPUEncoder(cSPUEncoder&); // no copy constructor
+
+ // helper functions
+ void CopyBlockIntoOSD(int linewidth, int x0,int y0, int x1, int y1, u_char *data);
+ void EncodePixelbufRle(int x, int y, int w, int h, u_char *inbuf, int stride, encodedata *ed);
+#ifndef USE_XINE_SCALER
+ void ScaleOSD(double fac, unsigned char* buf, unsigned char NumColors=4);
+#endif
+ void encode_put_nibble(encodedata* ed, u_char nibble);
+ void encode_pixels(encodedata* ed, int color, int number);
+ void encode_eol(encodedata* ed);
+ void encode_do_row(encodedata* ed, pixbuf* pb, int row);
+ void encode_do_control(int x,int y, encodedata* ed, pixbuf* pb);
+
+ void CalculateActiveOsdArea();
+
+ sOSD_Window m_windows[8];
+ cDxr3PaletteManager m_palManager;
+ cColorManager* m_ColorManager;
+ encodedata m_encodeddata;
+ int m_lastwindow;
+
+ // our osd :)
+ u_char OSD_Screen[OSDWIDTH * OSDHEIGHT];
+ u_char OSD_Screen2[OSDWIDTH * OSDHEIGHT];
+ u_char OSD_Screen3[OSDWIDTH * OSDHEIGHT];
+
+ // 'active' osd sizes
+ sRectal m_active_osd;
+};
+
+#endif /*_DXR3_INTERFACE_SPU_ENCODER_*/