diff --git a/content/media/nsMediaDecoder.cpp b/content/media/nsMediaDecoder.cpp index ab503e3df31..ea73a476462 100644 --- a/content/media/nsMediaDecoder.cpp +++ b/content/media/nsMediaDecoder.cpp @@ -80,6 +80,7 @@ nsMediaDecoder::nsMediaDecoder() : mFrameBufferLength(0), mPinnedForSeek(PR_FALSE), mSizeChanged(PR_FALSE), + mImageContainerSizeChanged(PR_FALSE), mShuttingDown(PR_FALSE) { MOZ_COUNT_CTOR(nsMediaDecoder); @@ -138,9 +139,15 @@ void nsMediaDecoder::Invalidate() return; nsIFrame* frame = mElement->GetPrimaryFrame(); + PRBool invalidateFrame = PR_FALSE; { nsAutoLock lock(mVideoUpdateLock); + + // Get mImageContainerSizeChanged while holding the lock. + invalidateFrame = mImageContainerSizeChanged; + mImageContainerSizeChanged = PR_FALSE; + if (mSizeChanged) { nsIntSize scaledSize(mRGBWidth, mRGBHeight); // Apply the aspect ratio to produce the intrinsic size we report @@ -169,8 +176,11 @@ void nsMediaDecoder::Invalidate() if (frame) { nsRect contentRect = frame->GetContentRect() - frame->GetPosition(); - // Only the layer needs to be updated here - frame->InvalidateLayer(contentRect, nsDisplayItem::TYPE_VIDEO); + if (invalidateFrame) { + frame->Invalidate(contentRect); + } else { + frame->InvalidateLayer(contentRect, nsDisplayItem::TYPE_VIDEO); + } } #ifdef MOZ_SVG @@ -257,7 +267,12 @@ void nsMediaDecoder::SetVideoData(const gfxIntSize& aSize, mSizeChanged = PR_TRUE; } if (mImageContainer && aImage) { + gfxIntSize oldFrameSize = mImageContainer->GetCurrentSize(); mImageContainer->SetCurrentImage(aImage); + gfxIntSize newFrameSize = mImageContainer->GetCurrentSize(); + if (oldFrameSize != newFrameSize) { + mImageContainerSizeChanged = PR_TRUE; + } } } diff --git a/content/media/nsMediaDecoder.h b/content/media/nsMediaDecoder.h index 8ad257352ea..e2e0286fc54 100644 --- a/content/media/nsMediaDecoder.h +++ b/content/media/nsMediaDecoder.h @@ -351,9 +351,20 @@ protected: // while seeking. PRPackedBool mPinnedForSeek; - // Has our size changed since the last repaint? + // Set to PR_TRUE when the video width, height or pixel aspect ratio is + // changed by SetVideoData(). The next call to Invalidate() will recalculate + // and update the intrinsic size on the element, request a frame reflow and + // then reset this flag. PRPackedBool mSizeChanged; + // Set to PR_TRUE in SetVideoData() if the new image has a different size + // than the current image. The image size is also affected by transforms + // so this can be true even if mSizeChanged is false, for example when + // zooming. The next call to Invalidate() will call nsIFrame::Invalidate + // when this flag is set, rather than just InvalidateLayer, and then reset + // this flag. + PRPackedBool mImageContainerSizeChanged; + // True if the decoder is being shutdown. At this point all events that // are currently queued need to return immediately to prevent javascript // being run that operates on the element and decoder during shutdown.