The original display size of subtitles is now used to scale them properly when displaying them on an HD OSD

This commit is contained in:
Klaus Schmidinger 2011-03-12 16:08:08 +01:00
parent 11cca8015c
commit 2bd17596a0
5 changed files with 81 additions and 17 deletions

View File

@ -6554,3 +6554,5 @@ Video Disk Recorder Revision History
- Updated the Romanian OSD texts (thanks to Lucian Muresan). - Updated the Romanian OSD texts (thanks to Lucian Muresan).
- Now storing the original display size when handling DVB subtitles (thanks to - Now storing the original display size when handling DVB subtitles (thanks to
Reinhard Nissl). Reinhard Nissl).
- The original display size of subtitles is now used to scale them properly when
displaying them on an HD OSD.

View File

@ -7,7 +7,7 @@
* Original author: Marco Schlüßler <marco@lordzodiac.de> * Original author: Marco Schlüßler <marco@lordzodiac.de>
* With some input from the "subtitle plugin" by Pekka Virtanen <pekka.virtanen@sci.fi> * With some input from the "subtitle plugin" by Pekka Virtanen <pekka.virtanen@sci.fi>
* *
* $Id: dvbsubtitle.c 2.10 2011/03/12 13:07:59 kls Exp $ * $Id: dvbsubtitle.c 2.11 2011/03/12 15:13:03 kls Exp $
*/ */
#include "dvbsubtitle.h" #include "dvbsubtitle.h"
@ -420,7 +420,7 @@ public:
int PageId(void) { return pageId; } int PageId(void) { return pageId; }
int Version(void) { return version; } int Version(void) { return version; }
int State(void) { return state; } int State(void) { return state; }
tArea *GetAreas(void); tArea *GetAreas(double Factor);
cSubtitleClut *GetClutById(int ClutId, bool New = false); cSubtitleClut *GetClutById(int ClutId, bool New = false);
cSubtitleObject *GetObjectById(int ObjectId); cSubtitleObject *GetObjectById(int ObjectId);
cSubtitleRegion *GetRegionById(int RegionId, bool New = false); cSubtitleRegion *GetRegionById(int RegionId, bool New = false);
@ -446,16 +446,16 @@ cDvbSubtitlePage::~cDvbSubtitlePage()
{ {
} }
tArea *cDvbSubtitlePage::GetAreas(void) tArea *cDvbSubtitlePage::GetAreas(double Factor)
{ {
if (regions.Count() > 0) { if (regions.Count() > 0) {
tArea *Areas = new tArea[regions.Count()]; tArea *Areas = new tArea[regions.Count()];
tArea *a = Areas; tArea *a = Areas;
for (cSubtitleRegion *sr = regions.First(); sr; sr = regions.Next(sr)) { for (cSubtitleRegion *sr = regions.First(); sr; sr = regions.Next(sr)) {
a->x1 = sr->HorizontalAddress(); a->x1 = int(round(Factor * sr->HorizontalAddress()));
a->y1 = sr->VerticalAddress(); a->y1 = int(round(Factor * sr->VerticalAddress()));
a->x2 = sr->HorizontalAddress() + sr->Width() - 1; a->x2 = int(round(Factor * (sr->HorizontalAddress() + sr->Width() - 1)));
a->y2 = sr->VerticalAddress() + sr->Height() - 1; a->y2 = int(round(Factor * (sr->VerticalAddress() + sr->Height() - 1)));
a->bpp = sr->Bpp(); a->bpp = sr->Bpp();
while ((a->Width() & 3) != 0) while ((a->Width() & 3) != 0)
a->x2++; // aligns width to a multiple of 4, so 2, 4 and 8 bpp will work a->x2++; // aligns width to a multiple of 4, so 2, 4 and 8 bpp will work
@ -616,9 +616,10 @@ private:
int timeout; int timeout;
tArea *areas; tArea *areas;
int numAreas; int numAreas;
double osdFactor;
cVector<cBitmap *> bitmaps; cVector<cBitmap *> bitmaps;
public: public:
cDvbSubtitleBitmaps(int64_t Pts, int Timeout, tArea *Areas, int NumAreas); cDvbSubtitleBitmaps(int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactor);
~cDvbSubtitleBitmaps(); ~cDvbSubtitleBitmaps();
int64_t Pts(void) { return pts; } int64_t Pts(void) { return pts; }
int Timeout(void) { return timeout; } int Timeout(void) { return timeout; }
@ -626,12 +627,13 @@ public:
void Draw(cOsd *Osd); void Draw(cOsd *Osd);
}; };
cDvbSubtitleBitmaps::cDvbSubtitleBitmaps(int64_t Pts, int Timeout, tArea *Areas, int NumAreas) cDvbSubtitleBitmaps::cDvbSubtitleBitmaps(int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactor)
{ {
pts = Pts; pts = Pts;
timeout = Timeout; timeout = Timeout;
areas = Areas; areas = Areas;
numAreas = NumAreas; numAreas = NumAreas;
osdFactor = OsdFactor;
} }
cDvbSubtitleBitmaps::~cDvbSubtitleBitmaps() cDvbSubtitleBitmaps::~cDvbSubtitleBitmaps()
@ -649,8 +651,14 @@ void cDvbSubtitleBitmaps::AddBitmap(cBitmap *Bitmap)
void cDvbSubtitleBitmaps::Draw(cOsd *Osd) void cDvbSubtitleBitmaps::Draw(cOsd *Osd)
{ {
if (Osd->SetAreas(areas, numAreas) == oeOk) { if (Osd->SetAreas(areas, numAreas) == oeOk) {
for (int i = 0; i < bitmaps.Size(); i++) for (int i = 0; i < bitmaps.Size(); i++) {
Osd->DrawBitmap(bitmaps[i]->X0(), bitmaps[i]->Y0(), *bitmaps[i]); cBitmap *b = bitmaps[i];
if (osdFactor != 1.0)
b = b->Scale(osdFactor, osdFactor);
Osd->DrawBitmap(int(round(b->X0() * osdFactor)), int(round(b->Y0() * osdFactor)), *b);
if (b != bitmaps[i])
delete b;
}
Osd->Flush(); Osd->Flush();
} }
} }
@ -670,6 +678,7 @@ cDvbSubtitleConverter::cDvbSubtitleConverter(void)
displayHeight = windowHeight = 576; displayHeight = windowHeight = 576;
windowHorizontalOffset = 0; windowHorizontalOffset = 0;
windowVerticalOffset = 0; windowVerticalOffset = 0;
SetOsdData();
pages = new cList<cDvbSubtitlePage>; pages = new cList<cDvbSubtitlePage>;
bitmaps = new cList<cDvbSubtitleBitmaps>; bitmaps = new cList<cDvbSubtitleBitmaps>;
Start(); Start();
@ -703,6 +712,7 @@ void cDvbSubtitleConverter::Reset(void)
displayHeight = windowHeight = 576; displayHeight = windowHeight = 576;
windowHorizontalOffset = 0; windowHorizontalOffset = 0;
windowVerticalOffset = 0; windowVerticalOffset = 0;
SetOsdData();
Unlock(); Unlock();
} }
@ -850,9 +860,29 @@ tColor cDvbSubtitleConverter::yuv2rgb(int Y, int Cb, int Cr)
return (Er << 16) | (Eg << 8) | Eb; return (Er << 16) | (Eg << 8) | Eb;
} }
void cDvbSubtitleConverter::SetOsdData(void)
{
int OsdWidth;
int OsdHeight;
double OsdAspect;
cDevice::PrimaryDevice()->GetOsdSize(OsdWidth, OsdHeight, OsdAspect);
osdDeltaX = osdDeltaY = 0;
osdFactor = 1.0;
double fw = double(OsdWidth) / displayWidth;
double fh = double(OsdHeight) / displayHeight;
if (fw >= fh) {
osdFactor = fh;
osdDeltaX = (OsdWidth - displayWidth * osdFactor) / 2;
}
else {
osdFactor = fw;
osdDeltaY = (OsdHeight - displayHeight * osdFactor) / 2;
}
}
bool cDvbSubtitleConverter::AssertOsd(void) bool cDvbSubtitleConverter::AssertOsd(void)
{ {
return osd || (osd = cOsdProvider::NewOsd(windowHorizontalOffset, windowVerticalOffset + Setup.SubtitleOffset, OSD_LEVEL_SUBTITLES)); return osd || (osd = cOsdProvider::NewOsd(int(round(osdFactor * windowHorizontalOffset + osdDeltaX)), int(round(osdFactor * windowVerticalOffset + osdDeltaY)) + Setup.SubtitleOffset, OSD_LEVEL_SUBTITLES));
} }
int cDvbSubtitleConverter::ExtractSegment(const uchar *Data, int Length, int64_t Pts) int cDvbSubtitleConverter::ExtractSegment(const uchar *Data, int Length, int64_t Pts)
@ -1026,6 +1056,7 @@ int cDvbSubtitleConverter::ExtractSegment(const uchar *Data, int Length, int64_t
windowVerticalOffset = (Data[15] << 8) | Data[16]; // displayWindowVerticalPositionMinimum windowVerticalOffset = (Data[15] << 8) | Data[16]; // displayWindowVerticalPositionMinimum
windowHeight = ((Data[17] << 8) | Data[18]) - windowVerticalOffset + 1; // displayWindowVerticalPositionMaximum windowHeight = ((Data[17] << 8) | Data[18]) - windowVerticalOffset + 1; // displayWindowVerticalPositionMaximum
} }
SetOsdData();
SetupChanged(); SetupChanged();
ddsVersionNumber = version; ddsVersionNumber = version;
} }
@ -1048,7 +1079,7 @@ void cDvbSubtitleConverter::FinishPage(cDvbSubtitlePage *Page)
{ {
if (!AssertOsd()) if (!AssertOsd())
return; return;
tArea *Areas = Page->GetAreas(); tArea *Areas = Page->GetAreas(osdFactor);
int NumAreas = Page->regions.Count(); int NumAreas = Page->regions.Count();
int Bpp = 8; int Bpp = 8;
bool Reduced = false; bool Reduced = false;
@ -1085,7 +1116,7 @@ void cDvbSubtitleConverter::FinishPage(cDvbSubtitlePage *Page)
} }
} }
} }
cDvbSubtitleBitmaps *Bitmaps = new cDvbSubtitleBitmaps(Page->Pts(), Page->Timeout(), Areas, NumAreas); cDvbSubtitleBitmaps *Bitmaps = new cDvbSubtitleBitmaps(Page->Pts(), Page->Timeout(), Areas, NumAreas, osdFactor);
bitmaps->Add(Bitmaps); bitmaps->Add(Bitmaps);
for (cSubtitleRegion *sr = Page->regions.First(); sr; sr = Page->regions.Next(sr)) { for (cSubtitleRegion *sr = Page->regions.First(); sr; sr = Page->regions.Next(sr)) {
int posX = sr->HorizontalAddress(); int posX = sr->HorizontalAddress();

View File

@ -6,7 +6,7 @@
* *
* Original author: Marco Schlüßler <marco@lordzodiac.de> * Original author: Marco Schlüßler <marco@lordzodiac.de>
* *
* $Id: dvbsubtitle.h 2.4 2011/03/12 13:07:59 kls Exp $ * $Id: dvbsubtitle.h 2.5 2011/03/12 14:03:42 kls Exp $
*/ */
#ifndef __DVBSUBTITLE_H #ifndef __DVBSUBTITLE_H
@ -33,9 +33,13 @@ private:
int windowVerticalOffset; int windowVerticalOffset;
int windowWidth; int windowWidth;
int windowHeight; int windowHeight;
int osdDeltaX;
int osdDeltaY;
double osdFactor;
cList<cDvbSubtitlePage> *pages; cList<cDvbSubtitlePage> *pages;
cList<cDvbSubtitleBitmaps> *bitmaps; cList<cDvbSubtitleBitmaps> *bitmaps;
tColor yuv2rgb(int Y, int Cb, int Cr); tColor yuv2rgb(int Y, int Cb, int Cr);
void SetOsdData(void);
bool AssertOsd(void); bool AssertOsd(void);
int ExtractSegment(const uchar *Data, int Length, int64_t Pts); int ExtractSegment(const uchar *Data, int Length, int64_t Pts);
void FinishPage(cDvbSubtitlePage *Page); void FinishPage(cDvbSubtitlePage *Page);

26
osd.c
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: osd.c 2.16 2011/02/27 11:57:37 kls Exp $ * $Id: osd.c 2.17 2011/03/12 15:32:33 kls Exp $
*/ */
#include "osd.h" #include "osd.h"
@ -807,6 +807,30 @@ void cBitmap::ShrinkBpp(int NewBpp)
} }
} }
cBitmap *cBitmap::Scale(double FactorX, double FactorY)
{
// Fixed point scaling code based on www.inversereality.org/files/bitmapscaling.pdf
// by deltener@mindtremors.com
cBitmap *b = new cBitmap(int(round(Width() * FactorX)), int(round(Height() * FactorY)), Bpp(), X0(), Y0());
b->Replace(*this); // copy palette
int RatioX = (Width() << 16) / b->Width();
int RatioY = (Height() << 16) / b->Height();
tIndex *DestRow = b->bitmap;
int SourceY = 0;
for (int y = 0; y < b->Height(); y++) {
int SourceX = 0;
tIndex *SourceRow = bitmap + (SourceY >> 16) * Width();
tIndex *Dest = DestRow;
for (int x = 0; x < b->Width(); x++) {
*Dest++ = SourceRow[SourceX >> 16];
SourceX += RatioX;
}
SourceY += RatioY;
DestRow += b->Width();
}
return b;
}
// --- cRect ----------------------------------------------------------------- // --- cRect -----------------------------------------------------------------
const cRect cRect::Null; const cRect cRect::Null;

5
osd.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: osd.h 2.10 2011/03/08 15:52:12 kls Exp $ * $Id: osd.h 2.11 2011/03/12 16:06:48 kls Exp $
*/ */
#ifndef __OSD_H #ifndef __OSD_H
@ -273,6 +273,9 @@ public:
///< the 2^NewBpp most frequently used colors as defined in the current palette. ///< the 2^NewBpp most frequently used colors as defined in the current palette.
///< If NewBpp is not smaller than the bitmap's current color depth, ///< If NewBpp is not smaller than the bitmap's current color depth,
///< or if it is not one of 4bpp or 2bpp, nothing happens. ///< or if it is not one of 4bpp or 2bpp, nothing happens.
cBitmap *Scale(double FactorX, double FactorY);
///< Creates a copy of this bitmap, scaled by the given factors.
///< The caller must delete the returned bitmap once it is no longer used.
}; };
struct tArea { struct tArea {