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:
parent
1b396902e4
commit
9133fdcf63
@ -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'
|
||||||
|
1
HISTORY
1
HISTORY
@ -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).
|
||||||
|
6
Makefile
6
Makefile
@ -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
|
||||||
|
7
device.c
7
device.c
@ -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;
|
||||||
|
6
device.h
6
device.h
@ -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
|
||||||
|
|
||||||
|
11
dvbdevice.c
11
dvbdevice.c
@ -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);
|
||||||
|
@ -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
505
dvbspu.c
Normal 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
204
dvbspu.h
Normal 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
|
@ -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
23
spu.c
Normal 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
38
spu.h
Normal 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
|
Loading…
Reference in New Issue
Block a user