vdr-xine-0.9.4 vdr-1.7.33 video scaling API (YAEPG-Hack now obsolete)

Message ID 50D77F4A.8060004@users.sourceforge.net
State New
Headers

Commit Message

Lucian Muresan Dec. 23, 2012, 10:01 p.m. UTC
  Hi,

attached you'll find a patch against vdr-xine-0.9.4 that makes use of
the new video scaling API introduced in vdr-1.7.33, yielding correct
aspect ratio when scaling.

How can it be used? Well, have a look at yaepg-hd patched with [1], but
even more exciting when the video output plugin supports true color OSD
(unfortunately vdr-xine can do this only in non-X11-overlay mode) is the
new true color skin nOpacity [2].

BTW, Reinhard, do you still plan on maintaining vdr-xine? I was
wondering because the homepage of the plugin is no longer accessible...


[1]
https://github.com/lucianm/gen2ovl-googoo2/tree/master/media-plugins/vdr-yaepghd/files

[2]
http://www.vdr-portal.de/board16-video-disk-recorder/board55-vdr-plugins/p1112090-nopacity-0-0-4/#post1112090


Regards & Happy Christmas,
Lucian

P.S. Just for convenience, I also attached the obligatory PmtParser Patch.

diff -Naur xine-0.9.4_orig/xineDevice.c xine-0.9.4/xineDevice.c
--- xine-0.9.4_orig/xineDevice.c	2011-02-27 19:14:19.000000000 +0100
+++ xine-0.9.4/xineDevice.c	2012-12-23 22:06:02.578457473 +0100
@@ -4405,5 +4405,84 @@
   {
     return theXineDevice;
   }
+#if APIVERSNUM >= 10733
+  ///< Asks the output device whether it can scale the currently shown video in
+  ///< such a way that it fits into the given Rect, while retaining its proper
+  ///< aspect ratio. If the scaled video doesn't exactly fit into Rect, Alignment
+  ///< is used to determine how to align the actual rectangle with the requested
+  ///< one. The actual rectangle can be smaller, larger or the same size as the
+  ///< given Rect, and its location may differ, depending on the capabilities of
+  ///< the output device, which may not be able to display a scaled video at
+  ///< arbitrary sizes and locations. The device shall, however, do its best to
+  ///< match the requested Rect as closely as possible, preferring a size and
+  ///< location that fits completely into the requested Rect if possible.
+  ///< Returns the rectangle that can actually be used when scaling the video.
+  ///< A skin plugin using this function should rearrange its content according
+  ///< to the rectangle returned from calling this function, and should especially
+  ///< be prepared for cases where the returned rectangle is way off the requested
+  ///< Rect, or even Null. In such cases, the skin may want to fall back to
+  ///< working with full screen video.
+  ///< If this device can't scale the video, a Null rectangle is returned (this
+  ///< is also the default implementation).
+  cRect cXineDevice::CanScaleVideo(const cRect &Rect, int Alignment/* = taCenter*/)
+  {
+    // first implementation: we can always scale, we're a soft device ;-), ignore alignment for now
+
+    // so let's just remember what the next call to ScaleVideo should actually use as a rectangle
+    // argument if called with cRect(-1,-1,-1,-1)
+    vidWinRect = Rect;
+    return vidWinRect;
+  }
 
+  ///< Scales the currently shown video in such a way that it fits into the given
+  ///< Rect. Rect should be one retrieved through a previous call to
+  ///< CanScaleVideo() (otherwise results may be undefined).
+  ///< Even if video output is scaled, the functions GetVideoSize() and
+  ///< GetOsdSize() must still return the same values as if in full screen mode!
+  ///< If this device can't scale the video, nothing happens.
+  ///< To restore full screen video, call this function with a Null rectangle.
+  void cXineDevice::ScaleVideo(const cRect &Rect/* = cRect::Null*/)
+  {
+    const cRect * actualRect = &Rect;
+    if (Rect == cRect(-1,-1,-1,-1)) {
+      // actual rectangle was stored here by the previous call to CanScaleVideo
+      actualRect = &vidWinRect;
+    } else {
+      actualRect = &Rect;
+      // remember the value, just for the case we were called explicitly with a real value
+      vidWinRect = *actualRect;
+    }
+    // let our specialized code do the actual resizing / repositioning, get accurate parameters first
+    int videoLeft, videoTop, videoWidth, videoHeight, videoZoomX, videoZoomY, osdWidth, osdHeight;
+    double videoAspect, pixelAspect;
+    m_xineLib.execFuncVideoSize(videoLeft, videoTop, videoWidth, videoHeight, videoZoomX, videoZoomY, &videoAspect);
+    GetOsdSize(osdWidth, osdHeight, pixelAspect);
+    tArea vidWinArea;
+    vidWinArea.x1 = actualRect->X();
+    vidWinArea.y1 = actualRect->Y();
+    vidWinArea.x2 = actualRect->X() + actualRect->Width();
+    vidWinArea.y2 = actualRect->Y() + actualRect->Height();
+    if (*actualRect == cRect::Null) {
+        // will just resize to full size
+        vidWinArea.bpp = 0;
+    } else {
+        vidWinArea.bpp = 12;
+        // make corrections
+        double aspectFactor = (double(osdWidth) / double(osdHeight)) / videoAspect;
+        int output_width = actualRect->Height() * (videoAspect * aspectFactor);
+        int output_height = actualRect->Width() / (videoAspect * aspectFactor);
+        if (double(actualRect->Width())/double(actualRect->Height()) > videoAspect * aspectFactor) {
+            output_height = actualRect->Height();
+            vidWinArea.x1 += (actualRect->Width() - output_width) / 2;
+        }
+        else if (double(actualRect->Width())/double(actualRect->Height()) < videoAspect * aspectFactor) {
+            output_width = actualRect->Width();
+            vidWinArea.y1 += (actualRect->Height() - output_height) / 2;
+        }
+        vidWinArea.x2 = vidWinArea.x1 + output_width;
+        vidWinArea.y2 = vidWinArea.y1 + output_height;
+    }
+    m_xineLib.SetVideoWindow(videoWidth, videoHeight, vidWinArea);
+  }
+#endif
 };
diff -Naur xine-0.9.4_orig/xineDevice.h xine-0.9.4/xineDevice.h
--- xine-0.9.4_orig/xineDevice.h	2011-02-27 15:28:58.000000000 +0100
+++ xine-0.9.4/xineDevice.h	2012-12-23 22:03:34.530316428 +0100
@@ -162,7 +162,13 @@
 #else    
     void OnFreeOsd(cOsd *const osd);
 #endif
-
+#if APIVERSNUM >= 10733
+    virtual cRect CanScaleVideo(const cRect &Rect, int Alignment = taCenter);
+    virtual void ScaleVideo(const cRect &Rect = cRect::Null);
+  private:
+    cRect vidWinRect;
+  public:
+#endif
     cXineLib m_xineLib;
     cMutex m_osdMutex;
 
diff -Naur xine-0.9.4_orig/xineOsd.c xine-0.9.4/xineOsd.c
--- xine-0.9.4_orig/xineOsd.c	2011-03-15 21:00:18.000000000 +0100
+++ xine-0.9.4/xineOsd.c	2012-12-23 22:03:16.702299730 +0100
@@ -105,11 +105,21 @@
 
 #else
 
+#if APIVERSNUM >= 10733
+
+    // scale to the size and position stored by the last call to cDevice::CanScaleVideo
+    // by passing a cRect(-1,-1,-1,-1) as by our convention
+    m_xineDevice.ScaleVideo(cRect(-1,-1,-1,-1));
+
+#else
+
 #ifdef SET_VIDEO_WINDOW
     
     m_xineLib.SetVideoWindow(maxOsdWidth, maxOsdHeight, vidWin, dontOptimize);
     
 #endif    
+
+#endif // APIVERSNUM >= 10733
     
     int videoLeft   = frameLeft;
     int videoTop    = frameTop;
@@ -175,6 +185,13 @@
 
   cXineOsd::~cXineOsd()
   {
+#if APIVERSNUM >= 10733
+
+    // re-scale to full size when distroying the Osd
+    m_xineDevice.ScaleVideo();
+
+#endif
+
 #if APIVERSNUM < 10509
     HideOsd();
 #else
@@ -410,11 +427,21 @@
     int maxOsdWidth, maxOsdHeight;
     GetMaxOsdSize(maxOsdWidth, maxOsdHeight);
 
+#if APIVERSNUM >= 10733
+
+    // scale to the size and position stored by the last call to cDevice::CanScaleVideo
+    // by passing a cRect(-1,-1,-1,-1) as by our convention
+    m_xineDevice.ScaleVideo(cRect(-1,-1,-1,-1));
+
+#else
+
 #ifdef SET_VIDEO_WINDOW
     
     m_xineLib.SetVideoWindow(maxOsdWidth, maxOsdHeight, vidWin);
 
 #endif    
+
+#endif // APIVERSNUM >= 10733
     
     int videoLeft   = -1;
     int videoTop    = -1;
  

Comments

Reinhard Nissl Dec. 25, 2012, 8:02 p.m. UTC | #1
Hi,

Am 23.12.2012 23:01, schrieb Lucian Muresan:

> attached you'll find a patch against vdr-xine-0.9.4 that makes use of
> the new video scaling API introduced in vdr-1.7.33, yielding correct
> aspect ratio when scaling.
>
> How can it be used? Well, have a look at yaepg-hd patched with [1], but
> even more exciting when the video output plugin supports true color OSD
> (unfortunately vdr-xine can do this only in non-X11-overlay mode) is the
> new true color skin nOpacity [2].
>
> BTW, Reinhard, do you still plan on maintaining vdr-xine? I was
> wondering because the homepage of the plugin is no longer accessible...

I appreciate your patches and will have a look at it during the 
next days.

Regarding vdr-xine's homepage, I was quite busy throughout the 
year so I haven't managed to look for a new provider in time. I 
hope the homepage can go online again early next year.

Bye.
  
VDRU VDRU Dec. 25, 2012, 8:40 p.m. UTC | #2
On Tue, Dec 25, 2012 at 12:02 PM, Reinhard Nissl <rnissl@gmx.de> wrote:
> Regarding vdr-xine's homepage, I was quite busy throughout the year so I
> haven't managed to look for a new provider in time. I hope the homepage can
> go online again early next year.

Have you considered putting it at http://projects.vdr-developer.org/ ?
Many plugins call that place home now. It's a great _central_ location
for VDR users to find plugins & extras. I can't remember if there's
already a mirror there for vdr-xine but imo it's better to not bother
with mirrors since they can be problematic.
  

Patch

diff -Naur xine-0.9.4_orig/xineDevice.c xine-0.9.4/xineDevice.c
--- xine-0.9.4_orig/xineDevice.c	2011-02-27 19:14:19.000000000 +0100
+++ xine-0.9.4/xineDevice.c	2012-12-22 18:42:36.389557075 +0100
@@ -1200,7 +1200,11 @@ 
       int pid = TsPid(Data);
       if (pid == 0)
         patPmtParser.ParsePat(Data, TS_SIZE);
+#if APIVERSNUM >= 10732
+      else if (patPmtParser.IsPmtPid(pid))
+#else
       else if (pid == patPmtParser.PmtPid())
+#endif
         patPmtParser.ParsePmt(Data, TS_SIZE);
       else if (pid == patPmtParser.Vpid())
       {