TT6400 dvbhddevice ScaleVideo aspect ratio correction

Message ID 515F0BC3.3060005@users.sourceforge.net
State New
Headers

Commit Message

Lucian Muresan April 5, 2013, 5:37 p.m. UTC
  Hi,

I wrote a patch for the ScaleVideo implementation in the dvbhddevice,
for keeping the actual aspect ratio of the video material when scaling.
It was tested by users at vdr-portal.de which also reported the
distortions (I don't own such a device), and they said it works [1]. You
can test it with the nOpacity skin and/or with the upcoming
yaepghd-0.0.4 plugin [2].

Regards,
Lucian


[1]
http://www.vdr-portal.de/board1-news/board2-vdr-news/p1137059-announce-nopacity-0-1-0/#post1137059
[2] http://sourceforge.net/projects/vdryaepghd/files/
From 1591c4cdc50dda35c52902ce46851ab57291351c Mon Sep 17 00:00:00 2001
From: Lucian Muresan <Lucian.Muresan@siemens.com>
Date: Fri, 5 Apr 2013 11:21:25 +0200
Subject: [PATCH] vdr-2.0.0 dvbhdffdevice ScaleVideo Aspect v3

---
 PLUGINS/src/dvbhddevice/dvbhdffdevice.c | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)
  

Comments

VDRU VDRU April 5, 2013, 6:24 p.m. UTC | #1
It's a shame truecolor support still hasn't been added to this plugin.
Also, last I spoke with bball he had lost his password to vdr-developer so
it's not exactly that he had abandoned it as is being claimed. None the
less thanks for bothering enough to fork it and continuing work. Would be
nice if all the work people have done was consolidated but we can't have
everything I guess. :)

On Fri, Apr 5, 2013 at 10:37 AM, Lucian Muresan <
lucianm@users.sourceforge.net> wrote:

> Hi,
>
> I wrote a patch for the ScaleVideo implementation in the dvbhddevice,
> for keeping the actual aspect ratio of the video material when scaling.
> It was tested by users at vdr-portal.de which also reported the
> distortions (I don't own such a device), and they said it works [1]. You
> can test it with the nOpacity skin and/or with the upcoming
> yaepghd-0.0.4 plugin [2].
>
> Regards,
> Lucian
>
>
> [1]
>
> http://www.vdr-portal.de/board1-news/board2-vdr-news/p1137059-announce-nopacity-0-1-0/#post1137059
> [2] http://sourceforge.net/projects/vdryaepghd/files/
>
>
> _______________________________________________
> vdr mailing list
> vdr@linuxtv.org
> http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr
>
>
  
Udo Richter April 5, 2013, 7:35 p.m. UTC | #2
Am 05.04.2013 19:37, schrieb Lucian Muresan:
> I wrote a patch for the ScaleVideo implementation in the dvbhddevice,
> for keeping the actual aspect ratio of the video material when scaling.

My initial thought on the code was that it seemed to unnecessary do too
many double to int conversions, plus not doing any of them with proper
rounding. But I also thought, this might turn out simpler when
transforming it a bit. So I just did some math transforms, and it came
out quite embarrassingly simple:

// Scale to units of 1/1000 osd, with rounding
int x = (Rect.X() * 1000 + osdWidth / 2) / osdWidth;
int y = (Rect.Y() * 1000 + osdHeight / 2) / osdHeight;
int w = (Rect.Width() * 1000 + osdWidth / 2) / osdWidth;
int h = (Rect.Height() * 1000 + osdHeight / 2) / osdHeight;

// make aspect corrections
if (w > h) {
    x += (w - h) / 2;
    w = h;
}
else if (w < h) {
    y += (h - w) / 2;
    h = w;
}
mHdffCmdIf->CmdAvSetVideoWindow(0, true, x, y, w, h);


This should be functionally identical to the original code, except for
less rounding errors. I haven't tested it though.

Cheers,

Udo
  
Klaus Schmidinger April 8, 2013, 8:36 a.m. UTC | #3
On 05.04.2013 21:35, Udo Richter wrote:
> Am 05.04.2013 19:37, schrieb Lucian Muresan:
>> I wrote a patch for the ScaleVideo implementation in the dvbhddevice,
>> for keeping the actual aspect ratio of the video material when scaling.
>
> My initial thought on the code was that it seemed to unnecessary do too
> many double to int conversions, plus not doing any of them with proper
> rounding. But I also thought, this might turn out simpler when
> transforming it a bit. So I just did some math transforms, and it came
> out quite embarrassingly simple:
>
> // Scale to units of 1/1000 osd, with rounding
> int x = (Rect.X() * 1000 + osdWidth / 2) / osdWidth;
> int y = (Rect.Y() * 1000 + osdHeight / 2) / osdHeight;
> int w = (Rect.Width() * 1000 + osdWidth / 2) / osdWidth;
> int h = (Rect.Height() * 1000 + osdHeight / 2) / osdHeight;
>
> // make aspect corrections
> if (w > h) {
>      x += (w - h) / 2;
>      w = h;
> }
> else if (w < h) {
>      y += (h - w) / 2;
>      h = w;
> }
> mHdffCmdIf->CmdAvSetVideoWindow(0, true, x, y, w, h);
>
>
> This should be functionally identical to the original code, except for
> less rounding errors. I haven't tested it though.

Am I getting this right? cDvbHdFfDevice::ScaleVideo() apparently sets the
video window in units of 1/1000 of the OSD width and height, respectively.
Since this resolution is less than the possible acual OSD width or height,
the rectangle actually used in this function might be different from the
one given in the Rect parameter. While this is, of course, allowed, shouldn't
the same calculations also be done in cDvbHdFfDevice::CanScaleVideo(), to return
the correct rectangle to the skin?

Klaus
  
Lucian Muresan April 8, 2013, 5:42 p.m. UTC | #4
On 08.04.2013 10:36, Klaus Schmidinger wrote:
> Am I getting this right? cDvbHdFfDevice::ScaleVideo() apparently sets the
> video window in units of 1/1000 of the OSD width and height, respectively.
> Since this resolution is less than the possible acual OSD width or height,
> the rectangle actually used in this function might be different from the
> one given in the Rect parameter. While this is, of course, allowed,
> shouldn't
> the same calculations also be done in cDvbHdFfDevice::CanScaleVideo(),
> to return
> the correct rectangle to the skin?

I think if the actual cDvbHdFfDevice::CanScaleVideo implementation would
have really calculated something, it should have only converted
internally to whatever needed (1/1000 in this case), and back to Osd
pixel dimensions before returning the value. Since it doesn't (as it
just returns the input rectangle, possibly because the device "is" able
to handle any size within the limits, maybe nothing should be changed.
Or maybe checking against the limits could be done, changed the size to
a reasonable default (like Null for full size) and log an error if the
input size wasn't within the Osd limits.
Udo's variant looks well, but for all this maybe Andreas Regel should
also be consulted. Btw, I sent him a PM on vdr-portal.de, he did not
react so far.

Regards,
Lucian
  
Andreas Regel April 9, 2013, 5:48 a.m. UTC | #5
On 08.04.2013 19:42, Lucian Muresan wrote:
> On 08.04.2013 10:36, Klaus Schmidinger wrote:
>> Am I getting this right? cDvbHdFfDevice::ScaleVideo() apparently sets the
>> video window in units of 1/1000 of the OSD width and height, respectively.
>> Since this resolution is less than the possible acual OSD width or height,
>> the rectangle actually used in this function might be different from the
>> one given in the Rect parameter. While this is, of course, allowed,
>> shouldn't
>> the same calculations also be done in cDvbHdFfDevice::CanScaleVideo(),
>> to return
>> the correct rectangle to the skin?
> 
> I think if the actual cDvbHdFfDevice::CanScaleVideo implementation would
> have really calculated something, it should have only converted
> internally to whatever needed (1/1000 in this case), and back to Osd
> pixel dimensions before returning the value. Since it doesn't (as it
> just returns the input rectangle, possibly because the device "is" able
> to handle any size within the limits, maybe nothing should be changed.
> Or maybe checking against the limits could be done, changed the size to
> a reasonable default (like Null for full size) and log an error if the
> input size wasn't within the Osd limits.
> Udo's variant looks well, but for all this maybe Andreas Regel should
> also be consulted. Btw, I sent him a PM on vdr-portal.de, he did not
> react so far.
> 
> Regards,
> Lucian

Hi,

I will look into this shortly.

Best regards
Andreas
  
Andreas Regel April 9, 2013, 6:56 p.m. UTC | #6
Am 08.04.2013 19:42, schrieb Lucian Muresan:
> On 08.04.2013 10:36, Klaus Schmidinger wrote:
>> Am I getting this right? cDvbHdFfDevice::ScaleVideo() apparently sets the
>> video window in units of 1/1000 of the OSD width and height, respectively.
>> Since this resolution is less than the possible acual OSD width or height,
>> the rectangle actually used in this function might be different from the
>> one given in the Rect parameter. While this is, of course, allowed,
>> shouldn't
>> the same calculations also be done in cDvbHdFfDevice::CanScaleVideo(),
>> to return
>> the correct rectangle to the skin?
> 
> I think if the actual cDvbHdFfDevice::CanScaleVideo implementation would
> have really calculated something, it should have only converted
> internally to whatever needed (1/1000 in this case), and back to Osd
> pixel dimensions before returning the value. Since it doesn't (as it
> just returns the input rectangle, possibly because the device "is" able
> to handle any size within the limits, maybe nothing should be changed.
> Or maybe checking against the limits could be done, changed the size to
> a reasonable default (like Null for full size) and log an error if the
> input size wasn't within the Osd limits.
> Udo's variant looks well, but for all this maybe Andreas Regel should
> also be consulted. Btw, I sent him a PM on vdr-portal.de, he did not
> react so far.

Hi,

I tested the scaling myself using the nopacity skin. I integrated Udo's patch as is a bit clearer and directly points to the main requirement for correct aspect ratio: The width and height values must be equal as they represent percentages.

Best regards,
Andreas
  

Patch

diff --git a/PLUGINS/src/dvbhddevice/dvbhdffdevice.c b/PLUGINS/src/dvbhddevice/dvbhdffdevice.c
index dd7ace5..7a05ccb 100644
--- a/PLUGINS/src/dvbhddevice/dvbhdffdevice.c
+++ b/PLUGINS/src/dvbhddevice/dvbhdffdevice.c
@@ -579,9 +579,24 @@  void cDvbHdFfDevice::ScaleVideo(const cRect &Rect)
         double osdPixelAspect;
 
         GetOsdSize(osdWidth, osdHeight, osdPixelAspect);
+
+        // make corrections
+        double osdAspect = double(osdWidth) / double(osdHeight);
+        cRect corRect(Rect);
+        corRect.SetWidth(Rect.Height() * osdAspect);
+        corRect.SetHeight(Rect.Width() / osdAspect);
+        if (double(Rect.Width())/double(Rect.Height()) > osdAspect) {
+            corRect.SetHeight(Rect.Height());
+            corRect.SetX(Rect.X() + (Rect.Width() - corRect.Width()) / 2);
+        }
+        else if (double(Rect.Width())/double(Rect.Height()) < osdAspect) {
+            corRect.SetWidth(Rect.Width());
+            corRect.SetY(Rect.Y() + (Rect.Height() - corRect.Height()) / 2);
+        }
+
         mHdffCmdIf->CmdAvSetVideoWindow(0, true,
-            Rect.X() * 1000 / osdWidth, Rect.Y() * 1000 / osdHeight,
-            Rect.Width() * 1000 / osdWidth, Rect.Height() * 1000 / osdHeight);
+            corRect.X() * 1000 / osdWidth, corRect.Y() * 1000 / osdHeight,
+            corRect.Width() * 1000 / osdWidth, corRect.Height() * 1000 / osdHeight);
     }
 }