From 4c96c884960617bd5c63d47491a4aaff1bebfffd Mon Sep 17 00:00:00 2001 From: Eric Rahm Date: Wed, 19 Mar 2014 14:33:12 -0700 Subject: [PATCH] Bug 962154 - Use MallocSizeOf to report decoded-video memory. r=cpearce,njn --- content/media/MediaData.cpp | 16 ++++++++ content/media/MediaData.h | 2 + content/media/MediaDecoder.cpp | 6 +-- content/media/MediaDecoder.h | 2 +- content/media/MediaDecoderReader.cpp | 48 ++++++++++++++++++---- content/media/MediaDecoderReader.h | 40 +++--------------- content/media/MediaDecoderStateMachine.h | 6 +-- content/media/gtest/TestAudioCompactor.cpp | 16 +++++++- gfx/layers/ImageContainer.cpp | 20 +++++++++ gfx/layers/ImageContainer.h | 6 +++ gfx/layers/basic/BasicImages.cpp | 12 ++++++ gfx/layers/ipc/SharedPlanarYCbCrImage.cpp | 11 +++++ gfx/layers/ipc/SharedPlanarYCbCrImage.h | 7 ++++ 13 files changed, 142 insertions(+), 50 deletions(-) diff --git a/content/media/MediaData.cpp b/content/media/MediaData.cpp index 3a5db51a571..d2b00ded50d 100644 --- a/content/media/MediaData.cpp +++ b/content/media/MediaData.cpp @@ -89,6 +89,22 @@ VideoData::~VideoData() MOZ_COUNT_DTOR(VideoData); } +size_t +VideoData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const +{ + size_t size = aMallocSizeOf(this); + + // Currently only PLANAR_YCBCR has a well defined function for determining + // it's size, so reporting is limited to that type. + if (mImage && mImage->GetFormat() == ImageFormat::PLANAR_YCBCR) { + const mozilla::layers::PlanarYCbCrImage* img = + static_cast(mImage.get()); + size += img->SizeOfIncludingThis(aMallocSizeOf); + } + + return size; +} + /* static */ VideoData* VideoData::ShallowCopyUpdateDuration(VideoData* aOther, int64_t aDuration) diff --git a/content/media/MediaData.h b/content/media/MediaData.h index d800dad8da7..9d0cd2371be 100644 --- a/content/media/MediaData.h +++ b/content/media/MediaData.h @@ -225,6 +225,8 @@ public: ~VideoData(); + size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; + // Dimensions at which to display the video frame. The picture region // will be scaled to this size. This is should be the picture region's // dimensions scaled with respect to its aspect ratio. diff --git a/content/media/MediaDecoder.cpp b/content/media/MediaDecoder.cpp index 2536e7f2b7e..7134c93d544 100644 --- a/content/media/MediaDecoder.cpp +++ b/content/media/MediaDecoder.cpp @@ -1564,9 +1564,9 @@ nsresult MediaDecoder::GetBuffered(dom::TimeRanges* aBuffered) { return NS_ERROR_FAILURE; } -int64_t MediaDecoder::VideoQueueMemoryInUse() { +size_t MediaDecoder::SizeOfVideoQueue() { if (mDecoderStateMachine) { - return mDecoderStateMachine->VideoQueueMemoryInUse(); + return mDecoderStateMachine->SizeOfVideoQueue(); } return 0; } @@ -1836,7 +1836,7 @@ MediaMemoryTracker::CollectReports(nsIHandleReportCallback* aHandleReport, DecodersArray& decoders = Decoders(); for (size_t i = 0; i < decoders.Length(); ++i) { MediaDecoder* decoder = decoders[i]; - video += decoder->VideoQueueMemoryInUse(); + video += decoder->SizeOfVideoQueue(); audio += decoder->SizeOfAudioQueue(); if (decoder->GetResource()) { diff --git a/content/media/MediaDecoder.h b/content/media/MediaDecoder.h index 8d6017e3675..07840d4ea84 100644 --- a/content/media/MediaDecoder.h +++ b/content/media/MediaDecoder.h @@ -646,7 +646,7 @@ public: // Returns the size, in bytes, of the heap memory used by the currently // queued decoded video and audio data. - virtual int64_t VideoQueueMemoryInUse(); + size_t SizeOfVideoQueue(); size_t SizeOfAudioQueue(); VideoFrameContainer* GetVideoFrameContainer() MOZ_FINAL MOZ_OVERRIDE diff --git a/content/media/MediaDecoderReader.cpp b/content/media/MediaDecoderReader.cpp index dbc1a473cfa..3f6c26db2b4 100644 --- a/content/media/MediaDecoderReader.cpp +++ b/content/media/MediaDecoderReader.cpp @@ -31,18 +31,36 @@ extern PRLogModuleInfo* gMediaDecoderLog; #define SEEK_LOG(type, msg) #endif -void* MediaDecoderReader::VideoQueueMemoryFunctor::operator()(void* anObject) { - const VideoData* v = static_cast(anObject); - if (!v->mImage) { +class VideoQueueMemoryFunctor : public nsDequeFunctor { +public: + VideoQueueMemoryFunctor() : mSize(0) {} + + MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf); + + virtual void* operator()(void* aObject) { + const VideoData* v = static_cast(aObject); + mSize += v->SizeOfIncludingThis(MallocSizeOf); return nullptr; } - if (v->mImage->GetFormat() == ImageFormat::PLANAR_YCBCR) { - mozilla::layers::PlanarYCbCrImage* vi = static_cast(v->mImage.get()); - mResult += vi->GetDataSize(); + size_t mSize; +}; + + +class AudioQueueMemoryFunctor : public nsDequeFunctor { +public: + AudioQueueMemoryFunctor() : mSize(0) {} + + MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf); + + virtual void* operator()(void* aObject) { + const AudioData* audioData = static_cast(aObject); + mSize += audioData->SizeOfIncludingThis(MallocSizeOf); + return nullptr; } - return nullptr; -} + + size_t mSize; +}; MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder) : mAudioCompactor(mAudioQueue), @@ -58,6 +76,20 @@ MediaDecoderReader::~MediaDecoderReader() MOZ_COUNT_DTOR(MediaDecoderReader); } +size_t MediaDecoderReader::SizeOfVideoQueueInBytes() const +{ + VideoQueueMemoryFunctor functor; + mVideoQueue.LockedForEach(functor); + return functor.mSize; +} + +size_t MediaDecoderReader::SizeOfAudioQueueInBytes() const +{ + AudioQueueMemoryFunctor functor; + mAudioQueue.LockedForEach(functor); + return functor.mSize; +} + nsresult MediaDecoderReader::ResetDecode() { nsresult res = NS_OK; diff --git a/content/media/MediaDecoderReader.h b/content/media/MediaDecoderReader.h index 4189731ad49..05b06827e99 100644 --- a/content/media/MediaDecoderReader.h +++ b/content/media/MediaDecoderReader.h @@ -132,41 +132,13 @@ public: virtual nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime); - class VideoQueueMemoryFunctor : public nsDequeFunctor { - public: - VideoQueueMemoryFunctor() : mResult(0) {} + // Returns the number of bytes of memory allocated by structures/frames in + // the video queue. + size_t SizeOfVideoQueueInBytes() const; - virtual void* operator()(void* anObject); - - int64_t mResult; - }; - - virtual int64_t VideoQueueMemoryInUse() { - VideoQueueMemoryFunctor functor; - mVideoQueue.LockedForEach(functor); - return functor.mResult; - } - - class AudioQueueMemoryFunctor : public nsDequeFunctor { - public: - AudioQueueMemoryFunctor() : mSize(0) {} - - MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf); - - virtual void* operator()(void* anObject) { - const AudioData* audioData = static_cast(anObject); - mSize += audioData->SizeOfIncludingThis(MallocSizeOf); - return nullptr; - } - - size_t mSize; - }; - - size_t SizeOfAudioQueue() { - AudioQueueMemoryFunctor functor; - mAudioQueue.LockedForEach(functor); - return functor.mSize; - } + // Returns the number of bytes of memory allocated by structures/frames in + // the audio queue. + size_t SizeOfAudioQueueInBytes() const; // Only used by WebMReader and MediaOmxReader for now, so stub here rather // than in every reader than inherits from MediaDecoderReader. diff --git a/content/media/MediaDecoderStateMachine.h b/content/media/MediaDecoderStateMachine.h index 4067b73bd1b..3cdd673a1b8 100644 --- a/content/media/MediaDecoderStateMachine.h +++ b/content/media/MediaDecoderStateMachine.h @@ -266,16 +266,16 @@ public: void SetPlaybackRate(double aPlaybackRate); void SetPreservesPitch(bool aPreservesPitch); - int64_t VideoQueueMemoryInUse() { + size_t SizeOfVideoQueue() { if (mReader) { - return mReader->VideoQueueMemoryInUse(); + return mReader->SizeOfVideoQueueInBytes(); } return 0; } size_t SizeOfAudioQueue() { if (mReader) { - return mReader->SizeOfAudioQueue(); + return mReader->SizeOfAudioQueueInBytes(); } return 0; } diff --git a/content/media/gtest/TestAudioCompactor.cpp b/content/media/gtest/TestAudioCompactor.cpp index 40b86992c15..bcfe33eb3bd 100644 --- a/content/media/gtest/TestAudioCompactor.cpp +++ b/content/media/gtest/TestAudioCompactor.cpp @@ -13,6 +13,20 @@ using mozilla::AudioDataValue; using mozilla::MediaDecoderReader; using mozilla::MediaQueue; +class MemoryFunctor : public nsDequeFunctor { +public: + MemoryFunctor() : mSize(0) {} + MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf); + + virtual void* operator()(void* anObject) { + const AudioData* audioData = static_cast(anObject); + mSize += audioData->SizeOfIncludingThis(MallocSizeOf); + return nullptr; + } + + size_t mSize; +}; + class TestCopy { public: @@ -60,7 +74,7 @@ static void TestAudioCompactor(size_t aBytes) EXPECT_GT(callCount, 0U) << "copy functor never called"; EXPECT_EQ(frames, frameCount) << "incorrect number of frames copied"; - MediaDecoderReader::AudioQueueMemoryFunctor memoryFunc; + MemoryFunctor memoryFunc; queue.LockedForEach(memoryFunc); size_t allocSize = memoryFunc.mSize - (callCount * sizeof(AudioData)); size_t slop = allocSize - aBytes; diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp index cd2beb50623..77442d9d590 100644 --- a/gfx/layers/ImageContainer.cpp +++ b/gfx/layers/ImageContainer.cpp @@ -472,6 +472,26 @@ PlanarYCbCrImage::~PlanarYCbCrImage() } } +size_t +PlanarYCbCrImage::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const +{ + // Ignoring: + // - mData - just wraps mBuffer + // - Surfaces should be reported under gfx-surfaces-*: + // - mDeprecatedSurface + // - mSourceSurface + // - Base class: + // - mImplData is not used + // Not owned: + // - mRecycleBin + size_t size = mBuffer.SizeOfExcludingThis(aMallocSizeOf); + + // Could add in the future: + // - mBackendData (from base class) + + return size; +} + uint8_t* PlanarYCbCrImage::AllocateBuffer(uint32_t aSize) { diff --git a/gfx/layers/ImageContainer.h b/gfx/layers/ImageContainer.h index faca559e58c..213fa8df6ba 100644 --- a/gfx/layers/ImageContainer.h +++ b/gfx/layers/ImageContainer.h @@ -863,6 +863,12 @@ public: virtual SharedPlanarYCbCrImage *AsSharedPlanarYCbCrImage() { return nullptr; } virtual DeprecatedSharedPlanarYCbCrImage *AsDeprecatedSharedPlanarYCbCrImage() { return nullptr; } + virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); + } + + virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const; + protected: /** * Make a copy of the YCbCr data into local storage. diff --git a/gfx/layers/basic/BasicImages.cpp b/gfx/layers/basic/BasicImages.cpp index d606c5c06ad..93f76d15c29 100644 --- a/gfx/layers/basic/BasicImages.cpp +++ b/gfx/layers/basic/BasicImages.cpp @@ -55,6 +55,18 @@ public: already_AddRefed DeprecatedGetAsSurface(); TemporaryRef GetAsSourceSurface(); + virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE + { + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); + } + + virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE + { + size_t size = PlanarYCbCrImage::SizeOfExcludingThis(aMallocSizeOf); + size += mDecodedBuffer.SizeOfExcludingThis(aMallocSizeOf); + return size; + } + private: nsAutoArrayPtr mDecodedBuffer; gfx::IntSize mScaleHint; diff --git a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp index 05d94f9cb71..da5143afdaf 100644 --- a/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp +++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.cpp @@ -62,6 +62,17 @@ DeprecatedSharedPlanarYCbCrImage::~DeprecatedSharedPlanarYCbCrImage() { } } +size_t +SharedPlanarYCbCrImage::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const +{ + // NB: Explicitly skipping mTextureClient, the memory is already reported + // at time of allocation in GfxMemoryImageReporter. + // Not owned: + // - mCompositable + size_t size = PlanarYCbCrImage::SizeOfExcludingThis(aMallocSizeOf); + return size; +} + TextureClient* SharedPlanarYCbCrImage::GetTextureClient(CompositableClient* aClient) { diff --git a/gfx/layers/ipc/SharedPlanarYCbCrImage.h b/gfx/layers/ipc/SharedPlanarYCbCrImage.h index 3168c069cef..8773b22d6bd 100644 --- a/gfx/layers/ipc/SharedPlanarYCbCrImage.h +++ b/gfx/layers/ipc/SharedPlanarYCbCrImage.h @@ -113,6 +113,13 @@ public: virtual bool IsValid() MOZ_OVERRIDE; + virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE + { + return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); + } + + virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE; + private: RefPtr mTextureClient; RefPtr mCompositable;