From 96edccb5cb63380a6b501338c9512bcd458f11fa Mon Sep 17 00:00:00 2001 From: scop Date: Mon, 14 Mar 2005 22:21:07 +0000 Subject: Borrowed OSD scaler from the Xine plugin (Luca Olivetti). --- HISTORY | 3 +- Makefile | 6 +- dxr3interface_spu_encoder.c | 190 ++++++++++++++++++++++++++++++++++++++++++++ dxr3interface_spu_encoder.h | 155 ++++++++++++++++++++++++++++++++++++ 4 files changed, 352 insertions(+), 2 deletions(-) create mode 100644 dxr3interface_spu_encoder.h 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 +#include +#include +#include + +namespace XineScaler +{ + + template + 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 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 + * 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 +#include +#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 +{ +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_*/ -- cgit v1.2.3