gnash-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-dev] Optimization to jpeg decoding


From: dolphinling
Subject: [Gnash-dev] Optimization to jpeg decoding
Date: Wed, 26 Nov 2008 20:32:03 -0500
User-agent: Thunderbird 2.0.0.18 (X11/20081105)

Hitachi's animation The Hard Drive is the New Bling (Bling_Final.swf, available from e.g. http://dagobah.biz/flash/Bling_Final.swf) plays slowly in gnash. It contains a small number of very large jpegs (up to 3422x2516 px), and a profile shows that there are over 8 million calls to JpegImageInput::getWidth, nearly 2% of the total cpu time (in a debug build with video and audio output disabled).

All but 32 of those 8 million calls are from ImageInput::readSWFJpeg3. This patch simply stores the result of getWidth within readSWFJpeg3.

This has not been run through make check--I don't have all the packages for that. It has been tested on Bling_Final.swf, though, and works fine.

Jpeg decoding as a whole takes up just barely under 50% of the total time (again, debug build run with -r0 so no output) so there may be other improvements that could be made in the area. In fact, boost::scoped_array<unsigned char>::operator[] is called nearly 25 million times from readSWFJpeg3, for 5.67% of the run time, but I don't see a trivial way to eliminate those calls like with getWidth.

Any comments or questions of course welcome.

--
dolphinling
<http://dolphinling.net/>
=== modified file 'libbase/GnashImage.cpp'
--- libbase/GnashImage.cpp      2008-10-27 16:05:13 +0000
+++ libbase/GnashImage.cpp      2008-11-27 00:42:16 +0000
@@ -20,7 +20,7 @@
 // Based on the public domain work of Thatcher Ulrich <address@hidden> 2002
 
 #include <cstring>
-#include <memory>              // for auto_ptr
+#include <memory> // for auto_ptr
 #include <boost/scoped_array.hpp>
 #include <boost/shared_ptr.hpp>
 
@@ -140,7 +140,7 @@
     assert(x < _width);
     assert(y < _height);
 
-    boost::uint8_t*    data = scanline(y) + 4 * x;
+    boost::uint8_t* data = scanline(y) + 4 * x;
 
     data[0] = r;
     data[1] = g;
@@ -301,18 +301,23 @@
     assert(j_in.get());
 
     j_in->read();
+    
+    // For large images, getWidth can be called millions of times, so cache it
+    // here. Cache getHeight for symmetry.
+    const size_t j_in_width = j_in->getWidth();
+    const size_t j_in_height = j_in->getHeight();
 
-    im.reset(new ImageRGBA(j_in->getWidth(), j_in->getHeight()));
+    im.reset(new ImageRGBA(j_in_width, j_in_height));
 
     boost::scoped_array<boost::uint8_t> line (
-            new boost::uint8_t[3 * j_in->getWidth()]);
+            new boost::uint8_t[3 * j_in_width]);
 
-    for (size_t y = 0; y < j_in->getHeight(); y++) 
+    for (size_t y = 0; y < j_in_height; y++) 
     {
         j_in->readScanline(line.get());
 
-        boost::uint8_t*        data = im->scanline(y);
-        for (size_t x = 0; x < j_in->getWidth(); x++) 
+        boost::uint8_t* data = im->scanline(y);
+        for (size_t x = 0; x < j_in_width; x++) 
         {
             data[4*x+0] = line[3*x+0];
             data[4*x+1] = line[3*x+1];


reply via email to

[Prev in Thread] Current Thread [Next in Thread]