uint32_t HTMLVideoElement::MozPaintedFrames() { MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread."); if (!sVideoStatsEnabled) { return 0; } layers::ImageContainer* container = GetImageContainer(); return container ? container->GetPaintCount() : 0; }
uint32_t HTMLVideoElement::MozPaintedFrames() { MOZ_ASSERT(NS_IsMainThread(), "Should be on main thread."); if (!IsVideoStatsEnabled()) { return 0; } if (nsContentUtils::ShouldResistFingerprinting(OwnerDoc())) { return nsRFPService::GetSpoofedPresentedFrames(TotalPlayTime(), VideoWidth(), VideoHeight()); } layers::ImageContainer* container = GetImageContainer(); return container ? container->GetPaintCount() : 0; }
void CanvasImageCache::NotifyDrawImage(Element* aImage, HTMLCanvasElement* aCanvas, SourceSurface* aSource, const IntSize& aSize) { if (!gImageCache) { gImageCache = new ImageCache(); nsContentUtils::RegisterShutdownObserver( new CanvasImageCacheShutdownObserver()); } nsCOMPtr<imgIContainer> imgContainer = GetImageContainer(aImage); if (!imgContainer) { return; } AllCanvasImageCacheKey allCanvasCacheKey(imgContainer); ImageCacheKey canvasCacheKey(imgContainer, aCanvas); ImageCacheEntry* entry = gImageCache->mCache.PutEntry(canvasCacheKey); if (entry) { if (entry->mData->mSourceSurface) { // We are overwriting an existing entry. gImageCache->mTotal -= entry->mData->SizeInBytes(); gImageCache->RemoveObject(entry->mData); gImageCache->mAllCanvasCache.RemoveEntry(allCanvasCacheKey); } gImageCache->AddObject(entry->mData); entry->mData->mSourceSurface = aSource; entry->mData->mSize = aSize; gImageCache->mTotal += entry->mData->SizeInBytes(); AllCanvasImageCacheEntry* allEntry = gImageCache->mAllCanvasCache.PutEntry(allCanvasCacheKey); if (allEntry) { allEntry->mSourceSurface = aSource; } } if (!sCanvasImageCacheLimit) return; // Expire the image cache early if its larger than we want it to be. while (gImageCache->mTotal > size_t(sCanvasImageCacheLimit)) gImageCache->AgeOneGeneration(); }
SourceSurface* CanvasImageCache::LookupAllCanvas(Element* aImage) { if (!gImageCache) { return nullptr; } nsCOMPtr<imgIContainer> imgContainer = GetImageContainer(aImage); if (!imgContainer) { return nullptr; } AllCanvasImageCacheEntry* entry = gImageCache->mAllCanvasCache.GetEntry( AllCanvasImageCacheKey(imgContainer)); if (!entry) { return nullptr; } return entry->mSourceSurface; }
SourceSurface* CanvasImageCache::LookupCanvas(Element* aImage, HTMLCanvasElement* aCanvas, IntSize* aSizeOut) { if (!gImageCache) { return nullptr; } nsCOMPtr<imgIContainer> imgContainer = GetImageContainer(aImage); if (!imgContainer) { return nullptr; } ImageCacheEntry* entry = gImageCache->mCache.GetEntry(ImageCacheKey(imgContainer, aCanvas)); if (!entry) { return nullptr; } MOZ_ASSERT(aSizeOut); gImageCache->MarkUsed(entry->mData); *aSizeOut = entry->mData->mSize; return entry->mData->mSourceSurface; }
void VideoFrameContainer::SetCurrentFrames(const VideoSegment& aSegment) { if (aSegment.IsEmpty()) { return; } MutexAutoLock lock(mMutex); // Collect any new frames produced in this iteration. AutoTArray<ImageContainer::NonOwningImage,4> newImages; PrincipalHandle lastPrincipalHandle = PRINCIPAL_HANDLE_NONE; VideoSegment::ConstChunkIterator iter(aSegment); while (!iter.IsEnded()) { VideoChunk chunk = *iter; const VideoFrame* frame = &chunk.mFrame; if (*frame == mLastPlayedVideoFrame) { iter.Next(); continue; } Image* image = frame->GetImage(); CONTAINER_LOG(LogLevel::Verbose, ("VideoFrameContainer %p writing video frame %p (%d x %d)", this, image, frame->GetIntrinsicSize().width, frame->GetIntrinsicSize().height)); if (frame->GetForceBlack()) { if (!mBlackImage) { mBlackImage = GetImageContainer()->CreatePlanarYCbCrImage(); if (mBlackImage) { // Sets the image to a single black pixel, which will be scaled to // fill the rendered size. SetImageToBlackPixel(mBlackImage->AsPlanarYCbCrImage()); } } if (mBlackImage) { image = mBlackImage; } } // Don't append null image to the newImages. if (!image) { iter.Next(); continue; } newImages.AppendElement(ImageContainer::NonOwningImage(image, chunk.mTimeStamp)); lastPrincipalHandle = chunk.GetPrincipalHandle(); mLastPlayedVideoFrame = *frame; iter.Next(); } // Don't update if there are no changes. if (newImages.IsEmpty()) { return; } AutoTArray<ImageContainer::NonOwningImage,4> images; bool principalHandleChanged = lastPrincipalHandle != PRINCIPAL_HANDLE_NONE && lastPrincipalHandle != GetLastPrincipalHandleLocked(); // Add the frames from this iteration. for (auto& image : newImages) { image.mFrameID = NewFrameID(); images.AppendElement(image); } if (principalHandleChanged) { UpdatePrincipalHandleForFrameIDLocked(lastPrincipalHandle, newImages.LastElement().mFrameID); } SetCurrentFramesLocked(mLastPlayedVideoFrame.GetIntrinsicSize(), images); nsCOMPtr<nsIRunnable> event = new VideoFrameContainerInvalidateRunnable(this); mMainThread->Dispatch(event.forget()); images.ClearAndRetainStorage(); }