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

Message ID 50E60666.8090300@users.sourceforge.net
State New
Headers

Commit Message

Lucian Muresan Jan. 3, 2013, 10:29 p.m. UTC
  Hello,

On 12/25/2012 09:02 PM, Reinhard Nissl wrote:
> Hi,
>
[..]
>
> I appreciate your patches and will have a look at it during the next days.

after some clarifications of the new API, thanks to Klaus and "Johns" 
the author of the softhddevice output device plugin, here is a new 
version of the scaling API patch for vdr-xine.

Regards,
Lucian
  

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	2013-01-03 21:54:57.585874032 +0100
@@ -4405,5 +4405,83 @@ 
   {
     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
+
+    // we need to store the value for the case we have to call ScaleVideo ourselves in vdr-xine
+    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*/)
+  {
+    // refresh stored value
+    vidWinRect = Rect;
+    // 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 = vidWinRect.X();
+    vidWinArea.y1 = vidWinRect.Y();
+    vidWinArea.x2 = vidWinRect.X() + vidWinRect.Width();
+    vidWinArea.y2 = vidWinRect.Y() + vidWinRect.Height();
+    if (vidWinRect == 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 = vidWinRect.Height() * (videoAspect * aspectFactor);
+        int output_height = vidWinRect.Width() / (videoAspect * aspectFactor);
+        if (double(vidWinRect.Width())/double(vidWinRect.Height()) > videoAspect * aspectFactor) {
+            output_height = vidWinRect.Height();
+            vidWinArea.x1 += (vidWinRect.Width() - output_width) / 2;
+        }
+        else if (double(vidWinRect.Width())/double(vidWinRect.Height()) < videoAspect * aspectFactor) {
+            output_width = vidWinRect.Width();
+            vidWinArea.y1 += (vidWinRect.Height() - output_height) / 2;
+        }
+        vidWinArea.x2 = vidWinArea.x1 + output_width;
+        vidWinArea.y2 = vidWinArea.y1 + output_height;
+    }
+    m_xineLib.SetVideoWindow(videoWidth, videoHeight, vidWinArea);
+  }
+
+  const cRect & cXineDevice::GetScaleRect()
+  {
+    // just return the stored value
+    return vidWinRect;
+  }
 
+#endif // APIVERSNUM >= 10733
 };
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	2013-01-03 21:55:07.480878044 +0100
@@ -162,7 +162,14 @@ 
 #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);
+    const cRect & GetScaleRect();
+  private:
+    cRect vidWinRect;
+  public:
+#endif // APIVERSNUM >= 10733
     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	2013-01-03 21:54:10.282851266 +0100
@@ -105,11 +105,20 @@ 
 
 #else
 
+#if APIVERSNUM >= 10733
+
+    // scale to the size and position stored by the last call to cDevice::CanScaleVideo
+    m_xineDevice.ScaleVideo(m_xineDevice.GetScaleRect());
+
+#else
+
 #ifdef SET_VIDEO_WINDOW
     
     m_xineLib.SetVideoWindow(maxOsdWidth, maxOsdHeight, vidWin, dontOptimize);
     
 #endif    
+
+#endif // APIVERSNUM >= 10733
     
     int videoLeft   = frameLeft;
     int videoTop    = frameTop;
@@ -175,6 +184,7 @@ 
 
   cXineOsd::~cXineOsd()
   {
+
 #if APIVERSNUM < 10509
     HideOsd();
 #else