mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Improved SPU handling on devices with limited OSD capabilities
This commit is contained in:
parent
fa5db6d777
commit
1b973fd8eb
@ -2514,3 +2514,6 @@ Milan Hrala <hrala.milan@gmail.com>
|
|||||||
|
|
||||||
Andreas Schaefers <andreas_schaefers@gmx.de>
|
Andreas Schaefers <andreas_schaefers@gmx.de>
|
||||||
for adding the audio id to the call of PlayAudio() in cDevice::PlayTsAudio()
|
for adding the audio id to the call of PlayAudio() in cDevice::PlayTsAudio()
|
||||||
|
|
||||||
|
Matthieu Castet <castet.matthieu@free.fr>
|
||||||
|
for improving SPU handling on devices with limited OSD capabilities
|
||||||
|
2
HISTORY
2
HISTORY
@ -6207,3 +6207,5 @@ Video Disk Recorder Revision History
|
|||||||
cPatPmtGenerator::GeneratePmt(), because VDR doesn't record the PCR pid.
|
cPatPmtGenerator::GeneratePmt(), because VDR doesn't record the PCR pid.
|
||||||
- Updated the Estonian OSD texts (thanks to Arthur Konovalov).
|
- Updated the Estonian OSD texts (thanks to Arthur Konovalov).
|
||||||
- The 'sky' plugin is no longer part of the VDR source.
|
- The 'sky' plugin is no longer part of the VDR source.
|
||||||
|
- Improved SPU handling on devices with limited OSD capabilities (thanks to
|
||||||
|
Matthieu Castet).
|
||||||
|
122
dvbspu.c
122
dvbspu.c
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* parts of this file are derived from the OMS program.
|
* parts of this file are derived from the OMS program.
|
||||||
*
|
*
|
||||||
* $Id: dvbspu.c 2.2 2009/11/22 14:17:59 kls Exp $
|
* $Id: dvbspu.c 2.3 2009/12/05 14:41:40 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "dvbspu.h"
|
#include "dvbspu.h"
|
||||||
@ -340,6 +340,35 @@ sDvbSpuRect cDvbSpuDecoder::CalcAreaSize(sDvbSpuRect fgsize, cBitmap *fgbmp, sDv
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cDvbSpuBitmap::getMinBpp(const aDvbSpuPalDescr paldescr)
|
||||||
|
{
|
||||||
|
int col = 1;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (paldescr[i].trans != 0) {
|
||||||
|
col++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return col > 2 ? 2 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cDvbSpuDecoder::CalcAreaBpp(cBitmap *fgbmp, cBitmap *bgbmp)
|
||||||
|
{
|
||||||
|
int fgbpp = 0;
|
||||||
|
int bgbpp = 0;
|
||||||
|
int ret;
|
||||||
|
if (fgbmp) {
|
||||||
|
fgbpp = spubmp->getMinBpp(hlpDescr);
|
||||||
|
}
|
||||||
|
if (bgbmp) {
|
||||||
|
bgbpp = spubmp->getMinBpp(palDescr);
|
||||||
|
}
|
||||||
|
ret = fgbpp + bgbpp;
|
||||||
|
if (ret > 2)
|
||||||
|
ret = 4;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void cDvbSpuDecoder::Draw(void)
|
void cDvbSpuDecoder::Draw(void)
|
||||||
{
|
{
|
||||||
cMutexLock MutexLock(&mutex);
|
cMutexLock MutexLock(&mutex);
|
||||||
@ -347,43 +376,89 @@ void cDvbSpuDecoder::Draw(void)
|
|||||||
Hide();
|
Hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
sDvbSpuRect bgsize;
|
||||||
cBitmap *fg = NULL;
|
cBitmap *fg = NULL;
|
||||||
cBitmap *bg = NULL;
|
cBitmap *bg = NULL;
|
||||||
sDvbSpuRect bgsize;
|
|
||||||
sDvbSpuRect hlsize;
|
|
||||||
|
|
||||||
hlsize.x1 = hlpsize.x1;
|
|
||||||
hlsize.y1 = hlpsize.y1;
|
|
||||||
hlsize.x2 = hlpsize.x2;
|
|
||||||
hlsize.y2 = hlpsize.y2;
|
|
||||||
|
|
||||||
if (highlight)
|
if (highlight)
|
||||||
fg = spubmp->getBitmap(hlpDescr, palette, hlsize);
|
fg = spubmp->getBitmap(hlpDescr, palette, hlpsize);
|
||||||
|
|
||||||
if (spubmp->getMinSize(palDescr, bgsize))
|
if (spubmp->getMinSize(palDescr, bgsize))
|
||||||
bg = spubmp->getBitmap(palDescr, palette, bgsize);
|
bg = spubmp->getBitmap(palDescr, palette, bgsize);
|
||||||
|
|
||||||
sDvbSpuRect areaSize = CalcAreaSize(hlsize, fg, bgsize, bg);
|
if (osd == NULL) {
|
||||||
|
restricted_osd = false;
|
||||||
|
osd = cOsdProvider::NewOsd(0, 0);
|
||||||
|
|
||||||
if (!fg || !bg || !osd) {
|
tArea Area = { size.x1, size.y1, size.x2, size.y2, 4};
|
||||||
Hide();
|
if (osd->CanHandleAreas(&Area, 1) != oeOk)
|
||||||
}
|
restricted_osd = true;
|
||||||
|
else
|
||||||
|
osd->SetAreas(&Area, 1);
|
||||||
|
}
|
||||||
|
if (restricted_osd) {
|
||||||
|
sDvbSpuRect hlsize;
|
||||||
|
bool setarea = false;
|
||||||
|
/* reduce fg area (only valid if there is no bg below) */
|
||||||
|
if (fg) {
|
||||||
|
spubmp->getMinSize(hlpDescr,hlsize);
|
||||||
|
/* clip to the highligh area */
|
||||||
|
setMax(hlsize.x1, hlpsize.x1);
|
||||||
|
setMax(hlsize.y1, hlpsize.y1);
|
||||||
|
setMin(hlsize.x2, hlpsize.x2);
|
||||||
|
setMin(hlsize.y2, hlpsize.y2);
|
||||||
|
if (hlsize.x1 > hlsize.x2 || hlsize.y1 > hlsize.y2) {
|
||||||
|
hlsize.x1 = hlsize.x2 = hlsize.y1 = hlsize.y2 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sDvbSpuRect areaSize = CalcAreaSize((fg && bg) ? hlpsize : hlsize, fg, bgsize, bg);
|
||||||
|
|
||||||
if (bg || fg) {
|
#define DIV(a, b) (a/b)?:1
|
||||||
if (osd == NULL) {
|
for (int d = 1; !setarea && d <= 2; d++) {
|
||||||
osd = cOsdProvider::NewOsd(0, 0);
|
|
||||||
if ((areaSize.width() & 3) != 0)
|
/* first try old behaviour */
|
||||||
areaSize.x2 += 4 - (areaSize.width() & 3);
|
tArea Area = { areaSize.x1, areaSize.y1, areaSize.x2, areaSize.y2, DIV(CalcAreaBpp(fg, bg), d) };
|
||||||
tArea Area = { areaSize.x1, areaSize.y1, areaSize.x2, areaSize.y2, (fg && bg) ? 4 : 2 };
|
|
||||||
if (osd->SetAreas(&Area, 1) != oeOk)
|
if ((Area.Width() & 7) != 0)
|
||||||
|
Area.x2 += 8 - (Area.Width() & 7);
|
||||||
|
|
||||||
|
if (osd->CanHandleAreas(&Area, 1) == oeOk &&
|
||||||
|
osd->SetAreas(&Area, 1) == oeOk)
|
||||||
|
setarea = true;
|
||||||
|
|
||||||
|
/* second try to split area if there is both area */
|
||||||
|
if (!setarea && fg && bg) {
|
||||||
|
tArea Area_Both [2] = {
|
||||||
|
{bgsize.x1, bgsize.y1, bgsize.x2, bgsize.y2, DIV(CalcAreaBpp(0, bg), d)},
|
||||||
|
{hlpsize.x1, hlpsize.y1, hlpsize.x2, hlpsize.y2, DIV(CalcAreaBpp(fg, 0), d)}
|
||||||
|
};
|
||||||
|
if (!Area_Both[0].Intersects(Area_Both[1])) {
|
||||||
|
/* there is no intersection. We can reduce hl */
|
||||||
|
Area_Both[1].x1 = hlsize.x1;
|
||||||
|
Area_Both[1].y1 = hlsize.y1;
|
||||||
|
Area_Both[1].x2 = hlsize.x2;
|
||||||
|
Area_Both[1].y2 = hlsize.y2;
|
||||||
|
|
||||||
|
if ((Area_Both[0].Width() & 7) != 0)
|
||||||
|
Area_Both[0].x2 += 8 - (Area_Both[0].Width() & 7);
|
||||||
|
if ((Area_Both[1].Width() & 7) != 0)
|
||||||
|
Area_Both[1].x2 += 8 - (Area_Both[1].Width() & 7);
|
||||||
|
if (osd->CanHandleAreas(Area_Both, 2) == oeOk &&
|
||||||
|
osd->SetAreas(Area_Both, 2) == oeOk)
|
||||||
|
setarea = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!setarea)
|
||||||
dsyslog("dvbspu: AreaSize (%d, %d) (%d, %d) Bpp %d", areaSize.x1, areaSize.y1, areaSize.x2, areaSize.y2, (fg && bg) ? 4 : 2 );
|
dsyslog("dvbspu: AreaSize (%d, %d) (%d, %d) Bpp %d", areaSize.x1, areaSize.y1, areaSize.x2, areaSize.y2, (fg && bg) ? 4 : 2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* we could draw use DrawPixel on osd */
|
||||||
|
if (bg || fg) {
|
||||||
if (bg)
|
if (bg)
|
||||||
osd->DrawBitmap(bgsize.x1, bgsize.y1, *bg);
|
osd->DrawBitmap(bgsize.x1, bgsize.y1, *bg);
|
||||||
if (fg)
|
if (fg)
|
||||||
osd->DrawBitmap(hlsize.x1, hlsize.y1, *fg);
|
osd->DrawBitmap(hlpsize.x1, hlpsize.y1, *fg);
|
||||||
delete fg;
|
delete fg;
|
||||||
delete bg;
|
delete bg;
|
||||||
|
|
||||||
@ -514,6 +589,7 @@ int cDvbSpuDecoder::setTime(uint32_t pts)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fodd != 0 && feven != 0) {
|
if (fodd != 0 && feven != 0) {
|
||||||
|
Hide();
|
||||||
delete spubmp;
|
delete spubmp;
|
||||||
spubmp = new cDvbSpuBitmap(size, spu + fodd, spu + feven,
|
spubmp = new cDvbSpuBitmap(size, spu + fodd, spu + feven,
|
||||||
spu + feven, spu + cmdOffs());
|
spu + feven, spu + cmdOffs());
|
||||||
|
5
dvbspu.h
5
dvbspu.h
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* parts of this file are derived from the OMS program.
|
* parts of this file are derived from the OMS program.
|
||||||
*
|
*
|
||||||
* $Id: dvbspu.h 2.1 2009/05/09 16:26:45 kls Exp $
|
* $Id: dvbspu.h 2.2 2009/12/05 14:40:08 kls Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __DVBSPU_H
|
#ifndef __DVBSPU_H
|
||||||
@ -80,6 +80,7 @@ class cDvbSpuBitmap {
|
|||||||
|
|
||||||
bool getMinSize(const aDvbSpuPalDescr paldescr,
|
bool getMinSize(const aDvbSpuPalDescr paldescr,
|
||||||
sDvbSpuRect & size) const;
|
sDvbSpuRect & size) const;
|
||||||
|
int getMinBpp(const aDvbSpuPalDescr paldescr);
|
||||||
cBitmap *getBitmap(const aDvbSpuPalDescr paldescr,
|
cBitmap *getBitmap(const aDvbSpuPalDescr paldescr,
|
||||||
const cDvbSpuPalette & pal,
|
const cDvbSpuPalette & pal,
|
||||||
sDvbSpuRect & size) const;
|
sDvbSpuRect & size) const;
|
||||||
@ -97,6 +98,7 @@ class cDvbSpuDecoder:public cSpuDecoder {
|
|||||||
uint32_t spupts;
|
uint32_t spupts;
|
||||||
bool clean;
|
bool clean;
|
||||||
bool ready;
|
bool ready;
|
||||||
|
bool restricted_osd;
|
||||||
|
|
||||||
enum spFlag { spNONE, spHIDE, spSHOW, spMENU };
|
enum spFlag { spNONE, spHIDE, spSHOW, spMENU };
|
||||||
spFlag state;
|
spFlag state;
|
||||||
@ -129,6 +131,7 @@ class cDvbSpuDecoder:public cSpuDecoder {
|
|||||||
};
|
};
|
||||||
|
|
||||||
sDvbSpuRect CalcAreaSize(sDvbSpuRect fgsize, cBitmap *fgbmp, sDvbSpuRect bgsize, cBitmap *bgbmp);
|
sDvbSpuRect CalcAreaSize(sDvbSpuRect fgsize, cBitmap *fgbmp, sDvbSpuRect bgsize, cBitmap *bgbmp);
|
||||||
|
int CalcAreaBpp(cBitmap *fgbmp, cBitmap *bgbmp);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
cDvbSpuDecoder();
|
cDvbSpuDecoder();
|
||||||
|
Loading…
Reference in New Issue
Block a user