summaryrefslogtreecommitdiff
path: root/dvbsubtitle.c
diff options
context:
space:
mode:
Diffstat (limited to 'dvbsubtitle.c')
-rw-r--r--dvbsubtitle.c84
1 files changed, 52 insertions, 32 deletions
diff --git a/dvbsubtitle.c b/dvbsubtitle.c
index c1a0a0c..de1cd1c 100644
--- a/dvbsubtitle.c
+++ b/dvbsubtitle.c
@@ -7,10 +7,13 @@
* Original author: Marco Schlüßler <marco@lordzodiac.de>
* With some input from the "subtitle plugin" by Pekka Virtanen <pekka.virtanen@sci.fi>
*
- * $Id: dvbsubtitle.c 2.11 2011/03/12 15:13:03 kls Exp $
+ * $Id: dvbsubtitle.c 2.17 2011/04/17 14:34:05 kls Exp $
*/
+
#include "dvbsubtitle.h"
+#define __STDC_FORMAT_MACROS // Required for format specifiers
+#include <inttypes.h>
#include "device.h"
#define PAGE_COMPOSITION_SEGMENT 0x10
@@ -420,7 +423,7 @@ public:
int PageId(void) { return pageId; }
int Version(void) { return version; }
int State(void) { return state; }
- tArea *GetAreas(double Factor);
+ tArea *GetAreas(double FactorX, double FactorY);
cSubtitleClut *GetClutById(int ClutId, bool New = false);
cSubtitleObject *GetObjectById(int ObjectId);
cSubtitleRegion *GetRegionById(int RegionId, bool New = false);
@@ -446,16 +449,16 @@ cDvbSubtitlePage::~cDvbSubtitlePage()
{
}
-tArea *cDvbSubtitlePage::GetAreas(double Factor)
+tArea *cDvbSubtitlePage::GetAreas(double FactorX, double FactorY)
{
if (regions.Count() > 0) {
tArea *Areas = new tArea[regions.Count()];
tArea *a = Areas;
for (cSubtitleRegion *sr = regions.First(); sr; sr = regions.Next(sr)) {
- a->x1 = int(round(Factor * sr->HorizontalAddress()));
- a->y1 = int(round(Factor * sr->VerticalAddress()));
- a->x2 = int(round(Factor * (sr->HorizontalAddress() + sr->Width() - 1)));
- a->y2 = int(round(Factor * (sr->VerticalAddress() + sr->Height() - 1)));
+ a->x1 = int(round(FactorX * sr->HorizontalAddress()));
+ a->y1 = int(round(FactorY * sr->VerticalAddress()));
+ a->x2 = int(round(FactorX * (sr->HorizontalAddress() + sr->Width() - 1)));
+ a->y2 = int(round(FactorY * (sr->VerticalAddress() + sr->Height() - 1)));
a->bpp = sr->Bpp();
while ((a->Width() & 3) != 0)
a->x2++; // aligns width to a multiple of 4, so 2, 4 and 8 bpp will work
@@ -616,10 +619,11 @@ private:
int timeout;
tArea *areas;
int numAreas;
- double osdFactor;
+ double osdFactorX;
+ double osdFactorY;
cVector<cBitmap *> bitmaps;
public:
- cDvbSubtitleBitmaps(int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactor);
+ cDvbSubtitleBitmaps(int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY);
~cDvbSubtitleBitmaps();
int64_t Pts(void) { return pts; }
int Timeout(void) { return timeout; }
@@ -627,13 +631,14 @@ public:
void Draw(cOsd *Osd);
};
-cDvbSubtitleBitmaps::cDvbSubtitleBitmaps(int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactor)
+cDvbSubtitleBitmaps::cDvbSubtitleBitmaps(int64_t Pts, int Timeout, tArea *Areas, int NumAreas, double OsdFactorX, double OsdFactorY)
{
pts = Pts;
timeout = Timeout;
areas = Areas;
numAreas = NumAreas;
- osdFactor = OsdFactor;
+ osdFactorX = OsdFactorX;
+ osdFactorY = OsdFactorY;
}
cDvbSubtitleBitmaps::~cDvbSubtitleBitmaps()
@@ -650,12 +655,27 @@ void cDvbSubtitleBitmaps::AddBitmap(cBitmap *Bitmap)
void cDvbSubtitleBitmaps::Draw(cOsd *Osd)
{
+ bool Scale = !(DoubleEqual(osdFactorX, 1.0) && DoubleEqual(osdFactorY, 1.0));
+ bool AntiAlias = true;
+ if (Scale && osdFactorX > 1.0 || osdFactorY > 1.0) {
+ // Upscaling requires 8bpp:
+ int Bpp[MAXOSDAREAS];
+ for (int i = 0; i < numAreas; i++) {
+ Bpp[i] = areas[i].bpp;
+ areas[i].bpp = 8;
+ }
+ if (Osd->CanHandleAreas(areas, numAreas) != oeOk) {
+ for (int i = 0; i < numAreas; i++)
+ Bpp[i] = areas[i].bpp = Bpp[i];
+ AntiAlias = false;
+ }
+ }
if (Osd->SetAreas(areas, numAreas) == oeOk) {
for (int i = 0; i < bitmaps.Size(); 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 (Scale)
+ b = b->Scaled(osdFactorX, osdFactorY, AntiAlias);
+ Osd->DrawBitmap(int(round(b->X0() * osdFactorX)), int(round(b->Y0() * osdFactorY)), *b);
if (b != bitmaps[i])
delete b;
}
@@ -733,7 +753,7 @@ int cDvbSubtitleConverter::ConvertFragments(const uchar *Data, int Length)
if (Length > PayloadOffset + SubstreamHeaderLength) {
int64_t pts = PesHasPts(Data) ? PesGetPts(Data) : 0;
if (pts)
- dbgconverter("Converter PTS: %lld\n", pts);
+ dbgconverter("Converter PTS: %"PRId64"\n", pts);
const uchar *data = Data + PayloadOffset + SubstreamHeaderLength; // skip substream header
int length = Length - PayloadOffset - SubstreamHeaderLength; // skip substream header
if (ResetSubtitleAssembler)
@@ -769,7 +789,7 @@ int cDvbSubtitleConverter::Convert(const uchar *Data, int Length)
if (Length > PayloadOffset) {
int64_t pts = PesGetPts(Data);
if (pts)
- dbgconverter("Converter PTS: %lld\n", pts);
+ dbgconverter("Converter PTS: %"PRId64"\n", pts);
const uchar *data = Data + PayloadOffset;
int length = Length - PayloadOffset;
if (length > 3) {
@@ -828,7 +848,7 @@ void cDvbSubtitleConverter::Action(void)
if (AssertOsd()) {
sb->Draw(osd);
Timeout.Set(sb->Timeout() * 1000);
- dbgconverter("PTS: %lld STC: %lld (%lld) timeout: %d\n", sb->Pts(), cDevice::PrimaryDevice()->GetSTC(), Delta, sb->Timeout());
+ dbgconverter("PTS: %"PRId64" STC: %"PRId64" (%"PRId64") timeout: %d\n", sb->Pts(), cDevice::PrimaryDevice()->GetSTC(), Delta, sb->Timeout());
}
bitmaps->Del(sb);
}
@@ -862,27 +882,27 @@ tColor cDvbSubtitleConverter::yuv2rgb(int Y, int Cb, int Cr)
void cDvbSubtitleConverter::SetOsdData(void)
{
- int OsdWidth;
- int OsdHeight;
+ int OsdWidth, OsdHeight;
double OsdAspect;
+ int VideoWidth, VideoHeight;
+ double VideoAspect;
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;
+ cDevice::PrimaryDevice()->GetVideoSize(VideoWidth, VideoHeight, VideoAspect);
+ if (OsdWidth == displayWidth && OsdHeight == displayHeight) {
+ osdFactorX = osdFactorY = 1.0;
+ osdDeltaX = osdDeltaY = 0;
}
else {
- osdFactor = fw;
- osdDeltaY = (OsdHeight - displayHeight * osdFactor) / 2;
+ osdFactorX = VideoAspect * OsdHeight / displayWidth;
+ osdFactorY = double(OsdHeight) / displayHeight;
+ osdDeltaX = (OsdWidth - displayWidth * osdFactorX) / 2;
+ osdDeltaY = (OsdHeight - displayHeight * osdFactorY) / 2;
}
}
bool cDvbSubtitleConverter::AssertOsd(void)
{
- return osd || (osd = cOsdProvider::NewOsd(int(round(osdFactor * windowHorizontalOffset + osdDeltaX)), int(round(osdFactor * windowVerticalOffset + osdDeltaY)) + Setup.SubtitleOffset, OSD_LEVEL_SUBTITLES));
+ return osd || (osd = cOsdProvider::NewOsd(int(round(osdFactorX * windowHorizontalOffset + osdDeltaX)), int(round(osdFactorY * windowVerticalOffset + osdDeltaY)) + Setup.SubtitleOffset, OSD_LEVEL_SUBTITLES));
}
int cDvbSubtitleConverter::ExtractSegment(const uchar *Data, int Length, int64_t Pts)
@@ -918,7 +938,7 @@ int cDvbSubtitleConverter::ExtractSegment(const uchar *Data, int Length, int64_t
page->SetTimeout(Data[6]);
page->SetState((Data[6 + 1] & 0x0C) >> 2);
page->regions.Clear();
- dbgpages("Update page id %d version %d pts %lld timeout %d state %d\n", pageId, page->Version(), page->Pts(), page->Timeout(), page->State());
+ dbgpages("Update page id %d version %d pts %"PRId64" timeout %d state %d\n", pageId, page->Version(), page->Pts(), page->Timeout(), page->State());
for (int i = 6 + 2; i < segmentLength; i += 6) {
cSubtitleRegion *region = page->GetRegionById(Data[i], true);
region->SetHorizontalAddress((Data[i + 2] << 8) + Data[i + 3]);
@@ -1079,7 +1099,7 @@ void cDvbSubtitleConverter::FinishPage(cDvbSubtitlePage *Page)
{
if (!AssertOsd())
return;
- tArea *Areas = Page->GetAreas(osdFactor);
+ tArea *Areas = Page->GetAreas(osdFactorX, osdFactorY);
int NumAreas = Page->regions.Count();
int Bpp = 8;
bool Reduced = false;
@@ -1116,7 +1136,7 @@ void cDvbSubtitleConverter::FinishPage(cDvbSubtitlePage *Page)
}
}
}
- cDvbSubtitleBitmaps *Bitmaps = new cDvbSubtitleBitmaps(Page->Pts(), Page->Timeout(), Areas, NumAreas, osdFactor);
+ cDvbSubtitleBitmaps *Bitmaps = new cDvbSubtitleBitmaps(Page->Pts(), Page->Timeout(), Areas, NumAreas, osdFactorX, osdFactorY);
bitmaps->Add(Bitmaps);
for (cSubtitleRegion *sr = Page->regions.First(); sr; sr = Page->regions.Next(sr)) {
int posX = sr->HorizontalAddress();