Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.cpp

Issue 2365943005: Cap memory usage in webp catch up (Closed)
Patch Set: Simplifying another piece. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 WEBPImageDecoder::WEBPImageDecoder(AlphaOption alphaOption, GammaAndColorProfile Option colorOptions, size_t maxDecodedBytes) 124 WEBPImageDecoder::WEBPImageDecoder(AlphaOption alphaOption, GammaAndColorProfile Option colorOptions, size_t maxDecodedBytes)
125 : ImageDecoder(alphaOption, colorOptions, maxDecodedBytes) 125 : ImageDecoder(alphaOption, colorOptions, maxDecodedBytes)
126 , m_decoder(0) 126 , m_decoder(0)
127 , m_formatFlags(0) 127 , m_formatFlags(0)
128 , m_frameBackgroundHasAlpha(false) 128 , m_frameBackgroundHasAlpha(false)
129 , m_demux(0) 129 , m_demux(0)
130 , m_demuxState(WEBP_DEMUX_PARSING_HEADER) 130 , m_demuxState(WEBP_DEMUX_PARSING_HEADER)
131 , m_haveAlreadyParsedThisData(false) 131 , m_haveAlreadyParsedThisData(false)
132 , m_repetitionCount(cAnimationLoopOnce) 132 , m_repetitionCount(cAnimationLoopOnce)
133 , m_decodedHeight(0) 133 , m_decodedHeight(0)
134 , m_purgeAggressively(false)
134 { 135 {
135 m_blendFunction = (alphaOption == AlphaPremultiplied) ? alphaBlendPremultipl ied : alphaBlendNonPremultiplied; 136 m_blendFunction = (alphaOption == AlphaPremultiplied) ? alphaBlendPremultipl ied : alphaBlendNonPremultiplied;
136 } 137 }
137 138
138 WEBPImageDecoder::~WEBPImageDecoder() 139 WEBPImageDecoder::~WEBPImageDecoder()
139 { 140 {
140 clear(); 141 clear();
141 } 142 }
142 143
143 void WEBPImageDecoder::clear() 144 void WEBPImageDecoder::clear()
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 buffer->setAlphaBlendSource(animatedFrame.blend_method == WEBP_MUX_BLEND ? I mageFrame::BlendAtopPreviousFrame : ImageFrame::BlendAtopBgcolor); 406 buffer->setAlphaBlendSource(animatedFrame.blend_method == WEBP_MUX_BLEND ? I mageFrame::BlendAtopPreviousFrame : ImageFrame::BlendAtopBgcolor);
406 buffer->setRequiredPreviousFrameIndex(findRequiredPreviousFrame(index, !anim atedFrame.has_alpha)); 407 buffer->setRequiredPreviousFrameIndex(findRequiredPreviousFrame(index, !anim atedFrame.has_alpha));
407 WebPDemuxReleaseIterator(&animatedFrame); 408 WebPDemuxReleaseIterator(&animatedFrame);
408 } 409 }
409 410
410 void WEBPImageDecoder::decode(size_t index) 411 void WEBPImageDecoder::decode(size_t index)
411 { 412 {
412 if (failed()) 413 if (failed())
413 return; 414 return;
414 415
416 updateAggressivePurging(index);
urvang 2016/10/03 21:07:23 You only need to call this method when number of f
cblume 2016/10/10 21:18:38 Sounds good. It looks like updateDemuxer() is cal
urvang 2016/10/10 21:30:50 Yes, updateDemuxer() updates the demuxer and relat
417
415 Vector<size_t> framesToDecode; 418 Vector<size_t> framesToDecode;
416 size_t frameToDecode = index; 419 size_t frameToDecode = index;
417 do { 420 do {
418 framesToDecode.append(frameToDecode); 421 framesToDecode.append(frameToDecode);
419 frameToDecode = m_frameBufferCache[frameToDecode].requiredPreviousFrameI ndex(); 422 frameToDecode = m_frameBufferCache[frameToDecode].requiredPreviousFrameI ndex();
420 } while (frameToDecode != kNotFound && m_frameBufferCache[frameToDecode].get Status() != ImageFrame::FrameComplete); 423 } while (frameToDecode != kNotFound && m_frameBufferCache[frameToDecode].get Status() != ImageFrame::FrameComplete);
421 424
422 ASSERT(m_demux); 425 ASSERT(m_demux);
423 for (auto i = framesToDecode.rbegin(); i != framesToDecode.rend(); ++i) { 426 for (auto i = framesToDecode.rbegin(); i != framesToDecode.rend(); ++i) {
424 if ((m_formatFlags & ANIMATION_FLAG) && !initFrameBuffer(*i)) 427 if ((m_formatFlags & ANIMATION_FLAG) && !initFrameBuffer(*i))
425 return; 428 return;
426 WebPIterator webpFrame; 429 WebPIterator webpFrame;
427 if (!WebPDemuxGetFrame(m_demux, *i + 1, &webpFrame)) { 430 if (!WebPDemuxGetFrame(m_demux, *i + 1, &webpFrame)) {
428 setFailed(); 431 setFailed();
429 } else { 432 } else {
430 decodeSingleFrame(webpFrame.fragment.bytes, webpFrame.fragment.size, *i); 433 decodeSingleFrame(webpFrame.fragment.bytes, webpFrame.fragment.size, *i);
431 WebPDemuxReleaseIterator(&webpFrame); 434 WebPDemuxReleaseIterator(&webpFrame);
432 } 435 }
433 if (failed()) 436 if (failed())
434 return; 437 return;
435 438
439 if (m_purgeAggressively)
440 clearCacheExceptFrame(*i);
urvang 2016/09/26 18:37:05 I think you need to purge after line#444. Otherwis
cblume 2016/10/01 11:06:23 Done. I should do this on the GIF decoder as well.
urvang 2016/10/03 19:12:36 I don't see this change yet. Forgot to upload?
cblume 2016/10/10 21:18:38 Oh, yeah. Sorry.
441
436 // We need more data to continue decoding. 442 // We need more data to continue decoding.
437 if (m_frameBufferCache[*i].getStatus() != ImageFrame::FrameComplete) 443 if (m_frameBufferCache[*i].getStatus() != ImageFrame::FrameComplete)
438 break; 444 break;
439 } 445 }
440 446
441 // It is also a fatal error if all data is received and we have decoded all 447 // It is also a fatal error if all data is received and we have decoded all
442 // frames available but the file is truncated. 448 // frames available but the file is truncated.
443 if (index >= m_frameBufferCache.size() - 1 && isAllDataReceived() && m_demux && m_demuxState != WEBP_DEMUX_DONE) 449 if (index >= m_frameBufferCache.size() - 1 && isAllDataReceived() && m_demux && m_demuxState != WEBP_DEMUX_DONE)
444 setFailed(); 450 setFailed();
445 } 451 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 applyPostProcessing(frameIndex); 504 applyPostProcessing(frameIndex);
499 return false; 505 return false;
500 } 506 }
501 // FALLTHROUGH 507 // FALLTHROUGH
502 default: 508 default:
503 clear(); 509 clear();
504 return setFailed(); 510 return setFailed();
505 } 511 }
506 } 512 }
507 513
514 void WEBPImageDecoder::updateAggressivePurging(size_t index)
scroggo_chromium 2016/09/26 12:04:48 This looks to be the exact same method as in GIFIm
cblume 2016/10/01 11:06:23 Good call. I've moved this into ImageDecoder in ht
515 {
516 if (m_purgeAggressively)
517 return;
518
519 // We don't want to cache so much that we cause a memory issue.
520 //
521 // If we used a LRU cache we would fill it and then on next animation loop
522 // we would need to decode all the frames again -- the LRU would give no
523 // benefit and would consume more memory.
524 // So instead, simply purge unused frames if caching all of the frames of
525 // the image would use more memory than the image decoder is allowed
526 // (m_maxDecodedBytes) or would overflow 32 bits..
527 //
528 // As we decode we will learn the total number of frames, and thus total
529 // possible image memory used.
530
531 const uint64_t frameArea = decodedSize().area();
532 const uint64_t frameMemoryUsage = frameArea * 4; // 4 bytes per pixel
533 if (frameMemoryUsage / 4 != frameArea) { // overflow occurred
534 m_purgeAggressively = true;
535 return;
536 }
537
538 const uint64_t totalMemoryUsage = frameMemoryUsage * index;
skal 2016/09/26 12:22:51 this multiply is still even more likely to overflo
cblume 2016/10/01 11:06:23 Ah, got ya. Fixed. I've moved this into ImageDecod
539 if (totalMemoryUsage > m_maxDecodedBytes) {
540 m_purgeAggressively = true;
541 }
542 }
508 } // namespace blink 543 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/image-decoders/webp/WEBPImageDecoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698