Re: Memory usage during webp decoding

536 views
Skip to first unread message

James Zern

unread,
Apr 26, 2013, 3:41:24 PM4/26/13
to webp-d...@webmproject.org
Hi,

On Thursday, April 25, 2013 4:19:06 PM UTC-7, marcu...@gmail.com wrote:
Hi,

We inherited a iOS / Android Game project that uses the webp format to store textures and libwebp to load them and pass them to OpenGL. There are a few 2048x2048 RGBA (16MB) textures in the game. When running a memory profile of the app on iOS, I noticed massive spikes of live memory when textures are loading, and that memory is allocated from within WebPDecode().

For example, when loading a 2048x2048 RGBA image (16MB uncompressed), WebPDecode() requires up 44MB of memory allocated in a few large blocks. Here is a rudimentary stack trace of where those memory blocks are allocated (note that due to hand-made instrumentation, line number might be slightly off):

[...]


It looks like of the two ~16MB blocks, one is used to store the resulting image and is returned to the caller, and the other one is used internally as an additional buffer. The 4MB blocks seem to be used to decode the alpha, but I'm not sure why the decoder would need any of them, since there is room for the alpha channel already in the output buffer.


With VP8 (lossy) + alpha the two are actually different bitstreams. The lossy side is VP8 for the RGB (encoded as YUV actually) and the alpha is done losslessly, with the alpha channel stored in the green channel for compression.


Has anybody experienced the same issue?

Is it an issue that has been addressed in a later version of the library? (I'm not sure exactly which version of libwebp is used in the project, by the header file says WEBP_DECODER_ABI_VERSION = 0x0200).

You can call WebPGetDecoderVersion(), but this is enough.
 
Is there an easy known fix for this, like specific options to pass to the decoder?

There are a few things you can do using the advanced decode api [1].
1) decode to an external buffer to avoid the additional allocation.
2) use the incremental decoder to avoid keeping the full source image in memory*
   * Support for alpha bearing files was recently added, that full plane is still needed. You'll have to work with a newer version of the lib from git for this to work:
      ead4d47 Add incremental support for extended format files

WebKit^WBlink [2] uses both.

Urvang Joshi

unread,
May 3, 2013, 5:23:34 AM5/3/13
to webp-d...@webmproject.org
Hi Marcus,


On Thu, Apr 25, 2013 at 4:19 PM, <marcu...@gmail.com> wrote:
Hi,

We inherited a iOS / Android Game project that uses the webp format to store textures and libwebp to load them and pass them to OpenGL. There are a few 2048x2048 RGBA (16MB) textures in the game. When running a memory profile of the app on iOS, I noticed massive spikes of live memory when textures are loading, and that memory is allocated from within WebPDecode().

For example, when loading a 2048x2048 RGBA image (16MB uncompressed), WebPDecode() requires up 44MB of memory allocated in a few large blocks. Here is a rudimentary stack trace of where those memory blocks are allocated (note that due to hand-made instrumentation, line number might be slightly off):


WEBP: Allocating 16.00 MB
  #0    WebPSafeMalloc()              at webp/utils/utils.c:38
  #1    AllocateBuffer()              at webp/dec/buffer.c:104
  #2    WebPAllocateDecBuffer()       at webp/dec/buffer.c:166
  #3    DecodeInto()                  at webp/dec/webp.c:429
  #4    WebPDecode()                  at webp/dec/webp.c:710


WEBP: Allocating 4.11 MB
  #0    WebPSafeMalloc()              at webp/utils/utils.c:38
  #1    AllocateMemory()              at webp/dec/frame.c:439
  #2    VP8InitFrame()                at webp/dec/frame.c:522
  #3    VP8Decode()                   at webp/dec/vp8.c:749
  #4    DecodeInto()                  at webp/dec/webp.c:432
  #5    WebPDecode()                  at webp/dec/webp.c:710


WEBP: Allocating 4.00 MB
  #0    DecodeAlpha()                 at webp/dec/alpha.c:81
  #1    VP8DecompressAlphaRows()      at webp/dec/alpha.c:135
  #2    FinishRow()                   at webp/dec/frame.c:210
  #3    VP8ProcessRow()               at webp/dec/frame.c:263
  #4    ParseFrame()                  at webp/dec/vp8.c:701
  #5    VP8Decode()                   at webp/dec/vp8.c:752
  #6    DecodeInto()                  at webp/dec/webp.c:432
  #7    WebPDecode()                  at webp/dec/webp.c:710


WEBP: Allocating 16.13 MB
  #0    WebPSafeMalloc()              at webp/utils/utils.c:38
  #1    AllocateARGBBuffers()         at webp/dec/vp8l.c:1053
  #2    VP8LDecodeAlphaImageStream()  at webp/dec/vp8l.c:1110
  #3    DecodeAlpha()                 at webp/dec/alpha.c:83
  #4    VP8DecompressAlphaRows()      at webp/dec/alpha.c:135
  #5    FinishRow()                   at webp/dec/frame.c:210
  #6    VP8ProcessRow()               at webp/dec/frame.c:263
  #7    ParseFrame()                  at webp/dec/vp8.c:701
  #8    VP8Decode()                   at webp/dec/vp8.c:752
  #9    DecodeInto()                  at webp/dec/webp.c:432
  #10   WebPDecode()                  at webp/dec/webp.c:710


WEBP: Allocating 4.00 MB
  #0    DecodeAlpha()                 at webp/dec/alpha.c:96
  #1    VP8DecompressAlphaRows()      at webp/dec/alpha.c:135
  #2    FinishRow()                   at webp/dec/frame.c:210
  #3    VP8ProcessRow()               at webp/dec/frame.c:263
  #4    ParseFrame()                  at webp/dec/vp8.c:701
  #5    VP8Decode()                   at webp/dec/vp8.c:752
  #6    DecodeInto()                  at webp/dec/webp.c:432
  #7    WebPDecode()                  at webp/dec/webp.c:710



It looks like of the two ~16MB blocks, one is used to store the resulting image and is returned to the caller, and the other one is used internally as an additional buffer. The 4MB blocks seem to be used to decode the alpha, but I'm not sure why the decoder would need any of them, since there is room for the alpha channel already in the output buffer.

I just pushed a change for review: https://gerrit.chromium.org/gerrit/#/c/50003/
This should remove any mallocs happening in DecodeAlpha() -- thereby reducing memory usage by 'width x height' bytes for images with alpha.

Once this change is merged, I'd encourage you to run your analysis again using the latest code in git:
 



Has anybody experienced the same issue?

Is it an issue that has been addressed in a later version of the library? (I'm not sure exactly which version of libwebp is used in the project, by the header file says WEBP_DECODER_ABI_VERSION = 0x0200).

Is there an easy known fix for this, like specific options to pass to the decoder?


--
You received this message because you are subscribed to the Google Groups "WebP Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to webp-discuss...@webmproject.org.
To post to this group, send email to webp-d...@webmproject.org.
Visit this group at http://groups.google.com/a/webmproject.org/group/webp-discuss/?hl=en.
For more options, visit https://groups.google.com/a/webmproject.org/groups/opt_out.
 
 

Reply all
Reply to author
Forward
0 new messages