1
0
mirror of https://github.com/VDR4Arch/vdr.git synced 2023-10-10 13:36:52 +02:00

Implemented an SPU decoder

This commit is contained in:
Klaus Schmidinger 2002-09-08 14:17:51 +02:00
parent 1b396902e4
commit 9133fdcf63
12 changed files with 804 additions and 10 deletions

View File

@ -166,6 +166,7 @@ Andreas Schultz <aschultz@warp10.net>
for making the use of malloc/free and new/delete consistent for making the use of malloc/free and new/delete consistent
for adding cDevice::NewOsd() to allow a derived cDevice class to implement its own for adding cDevice::NewOsd() to allow a derived cDevice class to implement its own
OSD capabilities OSD capabilities
for implementing an SPU decoder
Aaron Holtzman Aaron Holtzman
for writing 'ac3dec' for writing 'ac3dec'

View File

@ -1455,3 +1455,4 @@ Video Disk Recorder Revision History
- Switching through channels with the 'Up' and 'Down' keys now skips channels - Switching through channels with the 'Up' and 'Down' keys now skips channels
that are currently not available (for instance because all devices are that are currently not available (for instance because all devices are
recording and these channels are on different transponders). recording and these channels are on different transponders).
- Implemented an SPU decoder (thanks to Andreas Schultz).

View File

@ -4,7 +4,7 @@
# See the main source file 'vdr.c' for copyright information and # See the main source file 'vdr.c' for copyright information and
# how to reach the author. # how to reach the author.
# #
# $Id: Makefile 1.45 2002/08/09 16:02:02 kls Exp $ # $Id: Makefile 1.46 2002/09/08 14:00:48 kls Exp $
.DELETE_ON_ERROR: .DELETE_ON_ERROR:
@ -32,9 +32,9 @@ endif
DTVLIB = $(DTVDIR)/libdtv.a DTVLIB = $(DTVDIR)/libdtv.a
OBJS = audio.o config.o cutter.o device.o dvbdevice.o dvbosd.o dvbplayer.o eit.o eitscan.o font.o i18n.o\ OBJS = audio.o config.o cutter.o device.o dvbdevice.o dvbosd.o dvbplayer.o dvbspu.o eit.o eitscan.o font.o i18n.o\
interface.o menu.o menuitems.o osdbase.o osd.o player.o plugin.o receiver.o\ interface.o menu.o menuitems.o osdbase.o osd.o player.o plugin.o receiver.o\
recorder.o recording.o remote.o remux.o ringbuffer.o status.o svdrp.o thread.o\ recorder.o recording.o remote.o remux.o ringbuffer.o spu.o status.o svdrp.o thread.o\
tools.o transfer.o vdr.o videodir.o tools.o transfer.o vdr.o videodir.o
OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1 OSDFONT = -adobe-helvetica-medium-r-normal--23-*-100-100-p-*-iso8859-1

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: device.c 1.18 2002/09/08 11:46:53 kls Exp $ * $Id: device.c 1.19 2002/09/08 14:03:43 kls Exp $
*/ */
#include "device.h" #include "device.h"
@ -113,6 +113,11 @@ cOsdBase *cDevice::NewOsd(int x, int y)
return NULL; return NULL;
} }
cSpuDecoder *cDevice::GetSpuDecoder(void)
{
return NULL;
}
cDevice *cDevice::GetDevice(int Index) cDevice *cDevice::GetDevice(int Index)
{ {
return (0 <= Index && Index < numDevices) ? device[Index] : NULL; return (0 <= Index && Index < numDevices) ? device[Index] : NULL;

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: device.h 1.14 2002/09/08 11:17:41 kls Exp $ * $Id: device.h 1.15 2002/09/08 14:02:50 kls Exp $
*/ */
#ifndef __DEVICE_H #ifndef __DEVICE_H
@ -47,6 +47,7 @@ class cOsdBase;
class cChannel; class cChannel;
class cPlayer; class cPlayer;
class cReceiver; class cReceiver;
class cSpuDecoder;
class cDevice : cThread { class cDevice : cThread {
private: private:
@ -128,6 +129,9 @@ public:
// of the OSD at the given coordinates. If a derived cDevice doesn't // of the OSD at the given coordinates. If a derived cDevice doesn't
// implement this function, NULL will be returned by default (which // implement this function, NULL will be returned by default (which
// means the device has no OSD capabilities). // means the device has no OSD capabilities).
virtual cSpuDecoder *GetSpuDecoder(void);
// Returns a pointer to the device's SPU decoder (or NULL, if this
// device doesn't have an SPU decoder).
// Channel facilities // Channel facilities

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbdevice.c 1.11 2002/09/07 13:39:49 kls Exp $ * $Id: dvbdevice.c 1.12 2002/09/08 14:07:08 kls Exp $
*/ */
#include "dvbdevice.h" #include "dvbdevice.h"
@ -80,6 +80,7 @@ cDvbDevice::cDvbDevice(int n)
{ {
frontendType = FrontendType(-1); // don't know how else to initialize this - there is no FE_UNKNOWN frontendType = FrontendType(-1); // don't know how else to initialize this - there is no FE_UNKNOWN
siProcessor = NULL; siProcessor = NULL;
spuDecoder = NULL;
playMode = pmNone; playMode = pmNone;
// Devices that are present on all card types: // Devices that are present on all card types:
@ -128,6 +129,7 @@ cDvbDevice::cDvbDevice(int n)
cDvbDevice::~cDvbDevice() cDvbDevice::~cDvbDevice()
{ {
delete spuDecoder;
delete siProcessor; delete siProcessor;
// We're not explicitly closing any device files here, since this sometimes // We're not explicitly closing any device files here, since this sometimes
// caused segfaults. Besides, the program is about to terminate anyway... // caused segfaults. Besides, the program is about to terminate anyway...
@ -189,6 +191,13 @@ cOsdBase *cDvbDevice::NewOsd(int x, int y)
return new cDvbOsd(x, y); return new cDvbOsd(x, y);
} }
cSpuDecoder *cDvbDevice::GetSpuDecoder(void)
{
if (!spuDecoder && IsPrimaryDevice())
spuDecoder = new cDvbSpuDecoder();
return spuDecoder;
}
bool cDvbDevice::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY) bool cDvbDevice::GrabImage(const char *FileName, bool Jpeg, int Quality, int SizeX, int SizeY)
{ {
int videoDev = DvbOpen(DEV_VIDEO, CardIndex(), O_RDWR, true); int videoDev = DvbOpen(DEV_VIDEO, CardIndex(), O_RDWR, true);

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbdevice.h 1.9 2002/09/07 09:06:40 kls Exp $ * $Id: dvbdevice.h 1.10 2002/09/08 14:05:29 kls Exp $
*/ */
#ifndef __DVBDEVICE_H #ifndef __DVBDEVICE_H
@ -21,6 +21,7 @@
#include <ost/frontend.h> #include <ost/frontend.h>
#endif #endif
#include "device.h" #include "device.h"
#include "dvbspu.h"
#include "eit.h" #include "eit.h"
#define MAXDVBDEVICES 4 #define MAXDVBDEVICES 4
@ -51,8 +52,11 @@ public:
// OSD facilities // OSD facilities
private:
cDvbSpuDecoder *spuDecoder;
public: public:
cOsdBase *NewOsd(int x, int y); cOsdBase *NewOsd(int x, int y);
virtual cSpuDecoder *GetSpuDecoder(void);
// Channel facilities // Channel facilities

505
dvbspu.c Normal file
View File

@ -0,0 +1,505 @@
/*
* SPU decoder for DVB devices
*
* Copyright (C) 2001.2002 Andreas Schultz <aschultz@warp10.net>
*
* This code is distributed under the terms and conditions of the
* GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
*
* parts of this file are derived from the OMS program.
*
* $Id: dvbspu.c 1.1 2002/09/08 14:17:35 kls Exp $
*/
#include <assert.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>
#include "osd.h"
#include "osdbase.h"
#include "device.h"
#include "dvbspu.h"
/*
* cDvbSpubitmap:
*
* this is a bitmap of the full screen and two palettes
* the normal palette for the background and the highlight palette
*
* Inputs:
* - a SPU rle encoded image on creation, which will be decoded into
* the full screen indexed bitmap
*
* Output:
* - a minimal sized cDvbSpuBitmap a given palette, the indexed bitmap
* will be scanned to get the smallest possible resulting bitmap considering
* transparencies
*/
// #define SPUDEBUG
#ifdef SPUDEBUG
#define DEBUG(format, args...) printf (format, ## args)
#else
#define DEBUG(format, args...)
#endif
// --- cDvbSpuPalette----------------------------------
void cDvbSpuPalette::setPalette(const uint32_t * pal)
{
for (int i = 0; i < 16; i++)
palette[i] = yuv2rgb(pal[i]);
}
// --- cDvbSpuBitmap --------------------------------------------
#define setMin(a, b) if (a > b) a = b
#define setMax(a, b) if (a < b) a = b
#define spuXres 720
#define spuYres 576
#define revRect(r1, r2) { r1.x1 = r2.x2; r1.y1 = r2.y2; r1.x2 = r2.x1; r1.y2 = r2.y1; }
cDvbSpuBitmap::cDvbSpuBitmap(sDvbSpuRect size,
uint8_t * fodd, uint8_t * eodd,
uint8_t * feven, uint8_t * eeven)
{
if (size.x1 < 0 || size.y1 < 0 || size.x2 >= spuXres
|| size.y2 >= spuYres)
throw;
bmpsize = size;
revRect(minsize[0], size);
revRect(minsize[1], size);
revRect(minsize[2], size);
revRect(minsize[3], size);
if (!(bmp = new uint8_t[spuXres * spuYres * sizeof(uint8_t)]))
throw;
memset(bmp, 0, spuXres * spuYres * sizeof(uint8_t));
putFieldData(0, fodd, eodd);
putFieldData(1, feven, eeven);
}
cDvbSpuBitmap::~cDvbSpuBitmap()
{
delete[]bmp;
}
cBitmap *cDvbSpuBitmap::getBitmap(const aDvbSpuPalDescr paldescr,
const cDvbSpuPalette & pal,
sDvbSpuRect & size) const
{
int h = size.height();
int w = size.width();
if (size.y1 + h >= spuYres)
h = spuYres - size.y1 - 1;
if (size.x1 + w >= spuXres)
w = spuXres - size.x1 - 1;
if (w & 0x03)
w += 4 - (w & 0x03);
cBitmap *ret = new cBitmap(w, h, 2, true);
// set the palette
for (int i = 0; i < 4; i++) {
uint32_t color =
pal.getColor(paldescr[i].index, paldescr[i].trans);
ret->SetColor(i, (eDvbColor) color);
}
// set the content
for (int yp = 0; yp < h; yp++) {
for (int xp = 0; xp < w; xp++) {
uint8_t idx = bmp[(size.y1 + yp) * spuXres + size.x1 + xp];
ret->SetIndex(xp, yp, idx);
}
}
return ret;
}
// find the minimum non-transparent area
bool cDvbSpuBitmap::getMinSize(const aDvbSpuPalDescr paldescr,
sDvbSpuRect & size) const
{
bool ret = false;
for (int i = 0; i < 4; i++) {
if (paldescr[i].trans != 0) {
if (!ret)
size = minsize[i];
else {
setMin(size.x1, minsize[i].x1);
setMin(size.y1, minsize[i].y1);
setMax(size.x2, minsize[i].x2);
setMax(size.y2, minsize[i].y2);
ret = true;
}
}
}
if (ret)
DEBUG("MinSize: (%d, %d) x (%d, %d)\n",
size.x1, size.y1, size.x2, size.y2);
return ret;
}
void cDvbSpuBitmap::putPixel(int xp, int yp, int len, uint8_t colorid)
{
memset(bmp + spuXres * yp + xp, colorid, len);
setMin(minsize[colorid].x1, xp);
setMin(minsize[colorid].y1, yp);
setMax(minsize[colorid].x2, xp + len - 1);
setMax(minsize[colorid].y2, yp + len - 1);
}
static uint8_t getBits(uint8_t * &data, uint8_t & bitf)
{
uint8_t ret = *data;
if (bitf)
ret >>= 4;
else
data++;
bitf ^= 1;
return (ret & 0xf);
}
void cDvbSpuBitmap::putFieldData(int field, uint8_t * data, uint8_t * endp)
{
int xp = bmpsize.x1;
int yp = bmpsize.y1 + field;
uint8_t bitf = 1;
while (data < endp) {
uint16_t vlc = getBits(data, bitf);
if (vlc < 0x0004) {
vlc = (vlc << 4) | getBits(data, bitf);
if (vlc < 0x0010) {
vlc = (vlc << 4) | getBits(data, bitf);
if (vlc < 0x0040) {
vlc = (vlc << 4) | getBits(data, bitf);
}
}
}
uint8_t color = vlc & 0x03;
int len = vlc >> 2;
// if len == 0 -> end sequence - fill to end of line
len = len ? : bmpsize.x2 - xp + 1;
putPixel(xp, yp, len, color);
xp += len;
if (xp > bmpsize.x2) {
// nextLine
if (!bitf)
data++;
bitf = 1;
xp = bmpsize.x1;
yp += 2;
if (yp > bmpsize.y2)
return;
}
}
}
// --- cDvbSpuDecoder-----------------------------
#define CMD_SPU_MENU 0x00
#define CMD_SPU_SHOW 0x01
#define CMD_SPU_HIDE 0x02
#define CMD_SPU_SET_PALETTE 0x03
#define CMD_SPU_SET_ALPHA 0x04
#define CMD_SPU_SET_SIZE 0x05
#define CMD_SPU_SET_PXD_OFFSET 0x06
#define CMD_SPU_EOF 0xff
#define spuU32(i) ((spu[i] << 8) + spu[i+1])
cDvbSpuDecoder::cDvbSpuDecoder()
{
clean = true;
scaleMode = eSpuNormal;
spu = NULL;
osd = NULL;
spubmp = NULL;
}
cDvbSpuDecoder::~cDvbSpuDecoder()
{
delete spubmp;
delete spu;
delete osd;
}
void cDvbSpuDecoder::processSPU(uint32_t pts, uint8_t * buf)
{
setTime(pts);
DEBUG("SPU pushData: pts: %d\n", pts);
delete spubmp;
spubmp = NULL;
delete[]spu;
spu = buf;
DCSQ_offset = cmdOffs();
prev_DCSQ_offset = 0;
clean = true;
}
void cDvbSpuDecoder::setScaleMode(cSpuDecoder::eScaleMode ScaleMode)
{
scaleMode = ScaleMode;
}
void cDvbSpuDecoder::setPalette(uint32_t * pal)
{
palette.setPalette(pal);
}
void cDvbSpuDecoder::setHighlight(uint16_t sx, uint16_t sy,
uint16_t ex, uint16_t ey,
uint32_t palette)
{
aDvbSpuPalDescr pld;
for (int i = 0; i < 4; i++) {
pld[i].index = 0xf & (palette >> (16 + 4 * i));
pld[i].trans = 0xf & (palette >> (4 * i));
}
bool ne = hlpsize.x1 != sx || hlpsize.y1 != sy ||
hlpsize.x2 != ex || hlpsize.y2 != ey ||
pld[0] != hlpDescr[0] || pld[1] != hlpDescr[1] ||
pld[2] != hlpDescr[2] || pld[3] != hlpDescr[3];
if (ne) {
DEBUG("setHighlight: %d,%d x %d,%d\n", sx, sy, ex, ey);
hlpsize.x1 = sx;
hlpsize.y1 = sy;
hlpsize.x2 = ex;
hlpsize.y2 = ey;
memcpy(hlpDescr, pld, sizeof(aDvbSpuPalDescr));
highlight = true;
clean = false;
}
}
void cDvbSpuDecoder::clearHighlight(void)
{
clean &= !highlight;
highlight = false;
}
int cDvbSpuDecoder::ScaleYcoord(int value)
{
if (scaleMode == eSpuLetterBox)
return lround((value * 3.0) / 4.0 + 72.0);
else
return value;
}
int cDvbSpuDecoder::ScaleYres(int value)
{
if (scaleMode == eSpuLetterBox)
return lround((value * 3.0) / 4.0);
else
return value;
}
void cDvbSpuDecoder::DrawBmp(sDvbSpuRect & size, cBitmap * bmp)
{
osd->Create(size.x1, size.y1, size.width(), size.height(), 2, false);
osd->SetBitmap(size.x1, size.y1, *bmp);
delete bmp;
}
void cDvbSpuDecoder::Draw(void)
{
Hide();
if (!spubmp)
return;
cBitmap *fg = NULL;
cBitmap *bg = NULL;
sDvbSpuRect bgsize;
sDvbSpuRect hlsize;
hlsize.x1 = hlpsize.x1;
hlsize.y1 = ScaleYcoord(hlpsize.y1);
hlsize.x2 = hlpsize.x2;
hlsize.y2 = ScaleYcoord(hlpsize.y2);
if (highlight)
fg = spubmp->getBitmap(hlpDescr, palette, hlsize);
if (spubmp->getMinSize(palDescr, bgsize)) {
bg = spubmp->getBitmap(palDescr, palette, bgsize);
if (scaleMode == eSpuLetterBox) {
// the coordinates have to be modified for letterbox
int y1 = ScaleYres(bgsize.y1) + bgsize.height();
bgsize.y2 = y1 + bgsize.height();
bgsize.y1 = y1;
}
}
if (bg || fg) {
if (osd == NULL)
if ((osd = cOsd::OpenRaw(0, 0)) == NULL) {
dsyslog("OpenRaw failed\n");
return;
}
if (fg)
DrawBmp(hlsize, fg);
if (bg)
DrawBmp(bgsize, bg);
osd->Flush();
}
clean = true;
}
void cDvbSpuDecoder::Hide(void)
{
delete osd;
osd = NULL;
}
void cDvbSpuDecoder::Empty(void)
{
Hide();
delete spubmp;
spubmp = NULL;
delete[]spu;
spu = NULL;
clearHighlight();
clean = true;
}
int cDvbSpuDecoder::setTime(uint32_t pts)
{
if (!spu)
return 0;
if (spu && !clean)
Draw();
while (DCSQ_offset != prev_DCSQ_offset) { /* Display Control Sequences */
int i = DCSQ_offset;
state = spNONE;
uint32_t exec_time = pts + spuU32(i) * 1024;
if ((pts != 0) && (exec_time > pts))
return 0;
DEBUG("offs = %d, rel = %d, time = %d, pts = %d, diff = %d\n",
i, spuU32(i) * 1024, exec_time, pts, exec_time - pts);
if (pts != 0) {
uint16_t feven = 0;
uint16_t fodd = 0;
i += 2;
prev_DCSQ_offset = DCSQ_offset;
DCSQ_offset = spuU32(i);
DEBUG("offs = %d, DCSQ = %d\n", i, DCSQ_offset);
i += 2;
while (spu[i] != CMD_SPU_EOF) { // Command Sequence
switch (spu[i]) {
case CMD_SPU_SHOW: // show subpicture
DEBUG("\tshow subpicture\n");
state = spSHOW;
i++;
break;
case CMD_SPU_HIDE: // hide subpicture
DEBUG("\thide subpicture\n");
state = spHIDE;
i++;
break;
case CMD_SPU_SET_PALETTE: // CLUT
palDescr[0].index = spu[i + 2] & 0xf;
palDescr[1].index = spu[i + 2] >> 4;
palDescr[2].index = spu[i + 1] & 0xf;
palDescr[3].index = spu[i + 1] >> 4;
i += 3;
break;
case CMD_SPU_SET_ALPHA: // transparency palette
palDescr[0].trans = spu[i + 2] & 0xf;
palDescr[1].trans = spu[i + 2] >> 4;
palDescr[2].trans = spu[i + 1] & 0xf;
palDescr[3].trans = spu[i + 1] >> 4;
i += 3;
break;
case CMD_SPU_SET_SIZE: // image coordinates
size.x1 = (spu[i + 1] << 4) | (spu[i + 2] >> 4);
size.x2 = ((spu[i + 2] & 0x0f) << 8) | spu[i + 3];
size.y1 = (spu[i + 4] << 4) | (spu[i + 5] >> 4);
size.y2 = ((spu[i + 5] & 0x0f) << 8) | spu[i + 6];
DEBUG("\t(%d, %d) x (%d, %d)\n",
size.x1, size.y1, size.x2, size.y2);
i += 7;
break;
case CMD_SPU_SET_PXD_OFFSET: // image 1 / image 2 offsets
fodd = spuU32(i + 1);
feven = spuU32(i + 3);
DEBUG("\todd = %d even = %d\n", fodd, feven);
i += 5;
break;
case CMD_SPU_MENU:
DEBUG("\tspu menu\n");
state = spMENU;
i++;
break;
default:
esyslog("invalid sequence in control header (%.2x)\n",
spu[i]);
assert(0);
i++;
break;
}
}
if (fodd != 0 && feven != 0) {
delete spubmp;
spubmp = new cDvbSpuBitmap(size, spu + fodd, spu + feven,
spu + feven, spu + cmdOffs());
}
} else if (!clean)
state = spSHOW;
if (state == spSHOW || state == spMENU)
Draw();
if (state == spHIDE)
Hide();
if (pts == 0)
return 0;
}
return 1;
}

204
dvbspu.h Normal file
View File

@ -0,0 +1,204 @@
/*
* SPU decoder for DVB devices
*
* Copyright (C) 2001.2002 Andreas Schultz <aschultz@warp10.net>
*
* This code is distributed under the terms and conditions of the
* GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
*
* parts of this file are derived from the OMS program.
*
* $Id: dvbspu.h 1.1 2002/09/08 14:17:38 kls Exp $
*/
#ifndef __DVBSPU_H
#define __DVBSPU_H
#include <inttypes.h>
#include "osdbase.h"
#include "spu.h"
typedef struct sDvbSpuPalDescr {
uint8_t index;
uint8_t trans;
bool operator != (const sDvbSpuPalDescr pd) const {
return index != pd.index && trans != pd.trans;
};
} aDvbSpuPalDescr[4];
typedef struct sDvbSpuRect {
int x1, y1;
int x2, y2;
int width() {
return x2 - x1 + 1;
};
int height() {
return y2 - y1 + 1;
};
bool operator != (const sDvbSpuRect r) const {
return r.x1 != x1 || r.y1 != y1 || r.x2 != x2 || r.y2 != y2;
};
}
sDvbSpuRect;
// --- cDvbSpuPalette----------------------------------
class cDvbSpuPalette {
private:
uint32_t palette[16];
private:
uint32_t yuv2rgb(uint32_t yuv_color);
public:
void setPalette(const uint32_t * pal);
uint32_t getColor(uint8_t idx, uint8_t trans) const;
};
// --- cDvbSpuBitmap----------------------------------
class cDvbSpuBitmap {
public:
private:
sDvbSpuRect bmpsize;
sDvbSpuRect minsize[4];
uint8_t *bmp;
private:
void putPixel(int xp, int yp, int len, uint8_t colorid);
void putFieldData(int field, uint8_t * data, uint8_t * endp);
public:
cDvbSpuBitmap(sDvbSpuRect size,
uint8_t * fodd, uint8_t * eodd,
uint8_t * feven, uint8_t * eeven);
~cDvbSpuBitmap();
bool getMinSize(const aDvbSpuPalDescr paldescr,
sDvbSpuRect & size) const;
cBitmap *getBitmap(const aDvbSpuPalDescr paldescr,
const cDvbSpuPalette & pal,
sDvbSpuRect & size) const;
};
// --- cDvbSpuDecoder------------------------------------
class cDvbSpuDecoder:public cSpuDecoder {
private:
cOsdBase * osd;
// processing state
uint8_t *spu;
bool clean;
bool ready;
enum spFlag { spNONE, spHIDE, spSHOW, spMENU };
spFlag state;
cSpuDecoder::eScaleMode scaleMode;
//highligh area
bool highlight;
sDvbSpuRect hlpsize;
aDvbSpuPalDescr hlpDescr;
//palette
cDvbSpuPalette palette;
// spu info's
sDvbSpuRect size;
aDvbSpuPalDescr palDescr;
uint16_t DCSQ_offset;
uint16_t prev_DCSQ_offset;
cDvbSpuBitmap *spubmp;
private:
int cmdOffs(void) {
return ((spu[2] << 8) | spu[3]);
};
int spuSize(void) {
return ((spu[0] << 8) | spu[1]);
};
int ScaleYcoord(int value);
int ScaleYres(int value);
void DrawBmp(sDvbSpuRect & size, cBitmap * bmp);
void Draw();
void Hide();
public:
cDvbSpuDecoder();
~cDvbSpuDecoder();
int setTime(uint32_t pts);
void setScaleMode(cSpuDecoder::eScaleMode ScaleMode);
void setPalette(uint32_t * pal);
void setHighlight(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey,
uint32_t palette);
void clearHighlight(void);
void Empty(void);
void processSPU(uint32_t pts, uint8_t * buf);
};
// --- cDvbSpuPalette -------------------------------------------
inline uint32_t cDvbSpuPalette::yuv2rgb(uint32_t yuv_color)
{
int Y, Cb, Cr;
int Ey, Epb, Epr;
int Eg, Eb, Er;
uint32_t result;
Y = (yuv_color >> 16) & 0xff;
Cb = (yuv_color) & 0xff;
Cr = (yuv_color >> 8) & 0xff;
Ey = (Y - 16);
Epb = (Cb - 128);
Epr = (Cr - 128);
/* ITU-R 709
Eg = (298*Ey - 55*Epb - 137*Epr)/256;
Eb = (298*Ey + 543*Epb)/256;
Er = (298*Ey + 460*Epr)/256;
*/
/* FCC ~= mediaLib */
Eg = (298 * Ey - 100 * Epb - 208 * Epr) / 256;
Eb = (298 * Ey + 516 * Epb) / 256;
Er = (298 * Ey + 408 * Epr) / 256;
if (Eg > 255)
Eg = 255;
if (Eg < 0)
Eg = 0;
if (Eb > 255)
Eb = 255;
if (Eb < 0)
Eb = 0;
if (Er > 255)
Er = 255;
if (Er < 0)
Er = 0;
result = (Eb << 16) | (Eg << 8) | Er;
return result;
}
inline uint32_t cDvbSpuPalette::getColor(uint8_t idx, uint8_t trans) const
{
uint8_t t = trans == 0x0f ? 0xff : trans << 4;
return palette[idx] | (t << 24);
}
#endif // __DVBSPU_H

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: osdbase.h 1.5 2002/08/25 10:01:00 kls Exp $ * $Id: osdbase.h 1.6 2002/09/08 14:12:41 kls Exp $
*/ */
#ifndef __OSDBASE_H #ifndef __OSDBASE_H
@ -50,12 +50,12 @@ private:
bool full; bool full;
protected: protected:
typedef unsigned char tIndexes[MAXNUMCOLORS]; typedef unsigned char tIndexes[MAXNUMCOLORS];
void SetColor(int Index, eDvbColor Color);
eDvbColor GetColor(int Index) { return color[Index]; }
public: public:
cPalette(int Bpp); cPalette(int Bpp);
int Index(eDvbColor Color); int Index(eDvbColor Color);
void Reset(void); void Reset(void);
void SetColor(int Index, eDvbColor Color);
eDvbColor GetColor(int Index) { return Index < maxColors ? color[Index] : clrBlack; }
const eDvbColor *NewColors(int &FirstColor, int &LastColor); const eDvbColor *NewColors(int &FirstColor, int &LastColor);
// With every call this function returns a consecutive range of // With every call this function returns a consecutive range of
// color entries that have been added since the last call. The // color entries that have been added since the last call. The

23
spu.c Normal file
View File

@ -0,0 +1,23 @@
/*
* SPU Decoder Prototype
*
* Copyright (C) 2001.2002 Andreas Schultz <aschultz@warp10.net>
*
* This code is distributed under the terms and conditions of the
* GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
*
* $Id: spu.c 1.1 2002/09/08 14:17:41 kls Exp $
*/
#include <inttypes.h>
#include "spu.h"
// -- cSpuDecoder ----------------
/*
cSpuDecoder::cSpuDecoder()
{};
*/
cSpuDecoder::~cSpuDecoder()
{
};

38
spu.h Normal file
View File

@ -0,0 +1,38 @@
/*
* SPU Decoder Prototype
*
* Copyright (C) 2001.2002 Andreas Schultz <aschultz@warp10.net>
*
* This code is distributed under the terms and conditions of the
* GNU GENERAL PUBLIC LICENSE. See the file COPYING for details.
*
* $Id: spu.h 1.1 2002/09/08 14:17:51 kls Exp $
*/
#ifndef __SPU_VDR_H
#define __SPU_VDR_H
#include <inttypes.h>
// --- cSpuDecoder -------------------------------------------
class cSpuDecoder {
public:
typedef enum { eSpuNormal, eSpuLetterBox, eSpuPanAndScan } eScaleMode;
public:
// cSpuDecoder();
virtual ~ cSpuDecoder();
virtual int setTime(uint32_t pts) = 0;
virtual void setScaleMode(cSpuDecoder::eScaleMode ScaleMode) = 0;
virtual void setPalette(uint32_t * pal) = 0;
virtual void setHighlight(uint16_t sx, uint16_t sy,
uint16_t ex, uint16_t ey,
uint32_t palette) = 0;
virtual void clearHighlight(void) = 0;
virtual void Empty(void) = 0;
virtual void processSPU(uint32_t pts, uint8_t * buf) = 0;
};
#endif // __SPU_VDR_H