[rbp] Ensure GPU does resize when caching thumbnails
authorpopcornmix <popcornmix@gmail.com>
Wed, 3 Apr 2013 22:44:09 +0000 (23:44 +0100)
committerpopcornmix <popcornmix@gmail.com>
Sat, 6 Apr 2013 10:48:16 +0000 (11:48 +0100)
On a Pi, imageres and fanartres are set quite low (typically 512 and 720 or lower).
So, when caching the artwork there is a resize step involved.
The OMXImage jpeg decoder has the option to resize "for free".
Unfortunately this currently only limits the resize to current GUI resolution,
so there is often a second resize done by the ARM. This is very slow.
The larger decoded image also requires more RAM.

With fanartres=512, you currently get resize during decode of 1920x1080 to 1280x720 (gui res).
Then before encode there is a resize to 910x512. The two stage resize reduces image quality.

This fix takes a bit more care to include the imageres/fanartres resize during the decode.
I needed to make the 16:9 check a little more lax to also detect a 16:9 image after it's been resized.
I've gone for differs from 16:9 by 1%, rather than the existing exact match of 16:9.

xbmc/cores/omxplayer/OMXImage.cpp
xbmc/guilib/Texture.cpp
xbmc/pictures/Picture.cpp

index 13f0822..95615f6 100644 (file)
@@ -486,30 +486,47 @@ bool COMXImage::ClampLimits(unsigned int &width, unsigned int &height)
 {
   RESOLUTION_INFO& res_info =  CDisplaySettings::Get().GetResolutionInfo(g_graphicsContext.GetVideoResolution());
   const bool transposed = m_orientation & 4;
-  const int gui_width  = transposed ? res_info.iHeight:res_info.iWidth;
-  const int gui_height = transposed ? res_info.iWidth:res_info.iHeight;
-  const unsigned int max_width  = min(gui_width, 2048);
-  const unsigned int max_height = min(gui_height, 2048);
+  unsigned int max_width = width;
+  unsigned int max_height = height;
+  const unsigned int gui_width  = transposed ? res_info.iHeight:res_info.iWidth;
+  const unsigned int gui_height = transposed ? res_info.iWidth:res_info.iHeight;
+  const float aspect = (float)m_width / m_height;
 
-  if(!max_width || !max_height)
-    return false;
+  if (max_width == 0 || max_height == 0)
+  {
+    max_height = g_advancedSettings.m_imageRes;
 
-  const float ar = (float)width/(float)height;
-  // bigger than maximum, so need to clamp
-  if (width > max_width || height > max_height) {
-    // wider than max, so clamp width first
-    if (ar > (float)max_width/(float)max_height)
-    {
-      width = max_width;
-      height = (float)max_width / ar + 0.5f;
-    // taller than max, so clamp height first
-    } else {
-      height = max_height;
-      width = (float)max_height * ar + 0.5f;
+    if (g_advancedSettings.m_fanartRes > g_advancedSettings.m_imageRes)
+    { // 16x9 images larger than the fanart res use that rather than the image res
+      if (fabsf(aspect / (16.0f/9.0f) - 1.0f) <= 0.01f && m_height >= g_advancedSettings.m_fanartRes)
+      {
+        max_height = g_advancedSettings.m_fanartRes;
+      }
     }
-    return true;
+    max_width = max_height * 16/9;
   }
 
+  if (gui_width)
+    max_width = min(max_width, gui_width);
+  if (gui_height)
+    max_height = min(max_height, gui_height);
+
+  max_width  = min(max_width, 2048U);
+  max_height = min(max_height, 2048U);
+
+
+  width = m_width;
+  height = m_height;
+  if (width > max_width || height > max_height)
+  {
+    if ((unsigned int)(max_width / aspect + 0.5f) > max_height)
+      max_width = (unsigned int)(max_height * aspect + 0.5f);
+    else
+      max_height = (unsigned int)(max_width / aspect + 0.5f);
+    width = max_width;
+    height = max_height;
+    return true;
+  }
   return false;
 }
 
@@ -548,7 +565,6 @@ bool COMXImage::ReadFile(const CStdString& inputFile)
     CLog::Log(LOGERROR, "%s::%s %s m_width=%d m_height=%d\n", CLASSNAME, __func__, inputFile.c_str(), m_width, m_height);
     return false;
   }
-  ClampLimits(m_width, m_height);
 
   m_is_open = true;
 
@@ -717,26 +733,6 @@ bool COMXImage::Decode(unsigned width, unsigned height)
   }
 
   m_decoder_open = true;
-
-  if(width == 0 || height == 0)
-  {
-    height = g_advancedSettings.m_imageRes;
-    if (g_advancedSettings.m_fanartRes > g_advancedSettings.m_imageRes)
-    { // a separate fanart resolution is specified - check if the image is exactly equal to this res
-      if (m_width == (unsigned int)g_advancedSettings.m_fanartRes * 16/9 &&
-          m_height == (unsigned int)g_advancedSettings.m_fanartRes)
-      { // special case for fanart res
-        height = g_advancedSettings.m_fanartRes;
-      }
-    }
-    width = height * 16/9;
-    if(!width || !height)
-    {
-      width = CDisplaySettings::Get().GetCurrentResolutionInfo().iWidth;
-      height = CDisplaySettings::Get().GetCurrentResolutionInfo().iHeight;
-    }
-  }
-
   ClampLimits(width, height);
 
   // set input format
index 5f9ad77..0dda500 100644 (file)
@@ -223,7 +223,7 @@ bool CBaseTexture::LoadFromFileInternal(const CStdString& texturePath, unsigned
 
     if(omx_image.ReadFile(texturePath))
     {
-      if(omx_image.Decode(omx_image.GetWidth(), omx_image.GetHeight()))
+      if(omx_image.Decode(maxWidth, maxHeight))
       {
         Allocate(omx_image.GetDecodedWidth(), omx_image.GetDecodedHeight(), XB_FMT_A8R8G8B8);
 
index f4028d3..4fd93d0 100644 (file)
@@ -119,9 +119,9 @@ bool CPicture::CacheTexture(uint8_t *pixels, uint32_t width, uint32_t height, ui
 
   uint32_t max_height = g_advancedSettings.m_imageRes;
   if (g_advancedSettings.m_fanartRes > g_advancedSettings.m_imageRes)
-  { // a separate fanart resolution is specified - check if the image is exactly equal to this res
-    if (width * 9 == height * 16 && height >= g_advancedSettings.m_fanartRes)
-    { // special case for 16x9 images larger than the fanart res
+  { // 16x9 images larger than the fanart res use that rather than the image res
+    if (fabsf((float)width / (float)height / (16.0f/9.0f) - 1.0f) <= 0.01f && height >= g_advancedSettings.m_fanartRes)
+    {
       max_height = g_advancedSettings.m_fanartRes;
     }
   }