diff --git a/dom/media/MediaData.cpp b/dom/media/MediaData.cpp index 9f1205a0e1..e770fa1449 100644 --- a/dom/media/MediaData.cpp +++ b/dom/media/MediaData.cpp @@ -9,9 +9,16 @@ #include "ImageContainer.h" #include "mozilla/layers/SharedRGBImage.h" #include "YCbCrUtils.h" +#include "mozilla/layers/ImageBridgeChild.h" +#include "mozilla/layers/KnowsCompositor.h" #include +#ifdef XP_WIN +#include "mozilla/WindowsVersion.h" +#include "mozilla/layers/D3D11YCbCrImage.h" +#endif + namespace mozilla { using namespace mozilla::gfx; @@ -218,19 +225,14 @@ VideoData::ShallowCopyUpdateTimestampAndDuration(const VideoData* aOther, return v.forget(); } -/* static */ -bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage, - const VideoInfo& aInfo, - const YCbCrBuffer &aBuffer, - const IntRect& aPicture, - bool aCopyData) +PlanarYCbCrData +ConstructPlanarYCbCrData(const VideoInfo& aInfo, + const VideoData::YCbCrBuffer& aBuffer, + const IntRect& aPicture) { - if (!aVideoImage) { - return false; - } - const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0]; - const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1]; - const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2]; + const VideoData::YCbCrBuffer::Plane& Y = aBuffer.mPlanes[0]; + const VideoData::YCbCrBuffer::Plane& Cb = aBuffer.mPlanes[1]; + const VideoData::YCbCrBuffer::Plane& Cr = aBuffer.mPlanes[2]; PlanarYCbCrData data; data.mYChannel = Y.mData + Y.mOffset; @@ -249,6 +251,21 @@ bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage, data.mStereoMode = aInfo.mStereoMode; data.mYUVColorSpace = aBuffer.mYUVColorSpace; data.mColorRange = aBuffer.mColorRange; + return data; +} + +/* static */ bool +VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage, + const VideoInfo& aInfo, + const YCbCrBuffer &aBuffer, + const IntRect& aPicture, + bool aCopyData) +{ + if (!aVideoImage) { + return false; + } + + PlanarYCbCrData data = ConstructPlanarYCbCrData(aInfo, aBuffer, aPicture); aVideoImage->SetDelayedConversion(true); if (aCopyData) { @@ -268,7 +285,8 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo, const YCbCrBuffer& aBuffer, bool aKeyframe, int64_t aTimecode, - const IntRect& aPicture) + const IntRect& aPicture, + layers::KnowsCompositor* aAllocator) { if (!aContainer) { // Create a dummy VideoData with no image. This gives us something to @@ -296,6 +314,23 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo, 0)); // Currently our decoder only knows how to output to ImageFormat::PLANAR_YCBCR // format. +#if XP_WIN + // We disable this code path on Windows 7 due to intermittent crashes with old drivers. + // See Mozilla bug 1405110. + if (IsWin8OrLater() && !XRE_IsParentProcess() && + aAllocator && aAllocator->GetCompositorBackendType() + == layers::LayersBackend::LAYERS_D3D11) { + RefPtr d3d11Image = new layers::D3D11YCbCrImage(); + PlanarYCbCrData data = ConstructPlanarYCbCrData(aInfo, aBuffer, aPicture); + if (d3d11Image->SetData(layers::ImageBridgeChild::GetSingleton() + ? layers::ImageBridgeChild::GetSingleton().get() + : aAllocator, + aContainer, data)) { + v->mImage = d3d11Image; + return v.forget(); + } + } +#endif if (!v->mImage) { v->mImage = aContainer->CreatePlanarYCbCrImage(); } diff --git a/dom/media/MediaData.h b/dom/media/MediaData.h index 02a7162f42..4fe8dbc5f2 100644 --- a/dom/media/MediaData.h +++ b/dom/media/MediaData.h @@ -25,6 +25,7 @@ namespace mozilla { namespace layers { class Image; class ImageContainer; +class KnowsCompositor; } // namespace layers class MediaByteBuffer; @@ -472,7 +473,8 @@ public: const YCbCrBuffer &aBuffer, bool aKeyframe, int64_t aTimecode, - const IntRect& aPicture); + const IntRect& aPicture, + layers::KnowsCompositor* aAllocator = nullptr); static already_AddRefed CreateAndCopyData(const VideoInfo& aInfo, ImageContainer* aContainer, diff --git a/dom/media/platforms/agnostic/TheoraDecoder.cpp b/dom/media/platforms/agnostic/TheoraDecoder.cpp index de715df876..2075d9aa9f 100644 --- a/dom/media/platforms/agnostic/TheoraDecoder.cpp +++ b/dom/media/platforms/agnostic/TheoraDecoder.cpp @@ -38,7 +38,8 @@ ogg_packet InitTheoraPacket(const unsigned char* aData, size_t aLength, } TheoraDecoder::TheoraDecoder(const CreateDecoderParams& aParams) - : mImageContainer(aParams.mImageContainer) + : mImageAllocator(aParams.mKnowsCompositor) + , mImageContainer(aParams.mImageContainer) , mTaskQueue(aParams.mTaskQueue) , mCallback(aParams.mCallback) , mIsFlushing(false) @@ -176,7 +177,8 @@ TheoraDecoder::DoDecode(MediaRawData* aSample) aSample->mKeyframe, aSample->mTimecode, mInfo.ScaledImageRect(mTheoraInfo.frame_width, - mTheoraInfo.frame_height)); + mTheoraInfo.frame_height), + mImageAllocator); if (!v) { LOG("Image allocation error source %ldx%ld display %ldx%ld picture %ldx%ld", mTheoraInfo.frame_width, mTheoraInfo.frame_height, mInfo.mDisplay.width, mInfo.mDisplay.height, diff --git a/dom/media/platforms/agnostic/TheoraDecoder.h b/dom/media/platforms/agnostic/TheoraDecoder.h index 9181989be8..7af6d27bc0 100644 --- a/dom/media/platforms/agnostic/TheoraDecoder.h +++ b/dom/media/platforms/agnostic/TheoraDecoder.h @@ -43,6 +43,7 @@ private: MediaResult DoDecode(MediaRawData* aSample); void ProcessDrain(); + RefPtr mImageAllocator; RefPtr mImageContainer; RefPtr mTaskQueue; MediaDataDecoderCallback* mCallback; diff --git a/dom/media/platforms/agnostic/VPXDecoder.cpp b/dom/media/platforms/agnostic/VPXDecoder.cpp index 00cf7d85cc..9479b89251 100644 --- a/dom/media/platforms/agnostic/VPXDecoder.cpp +++ b/dom/media/platforms/agnostic/VPXDecoder.cpp @@ -69,6 +69,7 @@ InitContext(vpx_codec_ctx_t* aCtx, VPXDecoder::VPXDecoder(const CreateDecoderParams& aParams) : mImageContainer(aParams.mImageContainer) + , mImageAllocator(aParams.mKnowsCompositor) , mTaskQueue(aParams.mTaskQueue) , mCallback(aParams.mCallback) , mIsFlushing(false) @@ -149,7 +150,7 @@ VPXDecoder::DoDecode(MediaRawData* aSample) "WebM image format not I420 or I444"); NS_ASSERTION(!alpha_decoded, "Multiple frames per packet that contains alpha"); - + if (aSample->AlphaSize() > 0) { if(!alpha_decoded){ MediaResult rv = DecodeAlpha(&img_alpha, aSample); @@ -221,7 +222,8 @@ VPXDecoder::DoDecode(MediaRawData* aSample) aSample->mKeyframe, aSample->mTimecode, mInfo.ScaledImageRect(img->d_w, - img->d_h)); + img->d_h), + mImageAllocator); } else { VideoData::YCbCrBuffer::Plane alpha_plane; alpha_plane.mData = img_alpha->planes[0]; diff --git a/dom/media/platforms/agnostic/VPXDecoder.h b/dom/media/platforms/agnostic/VPXDecoder.h index 25d9bc1d33..e2686dd02f 100644 --- a/dom/media/platforms/agnostic/VPXDecoder.h +++ b/dom/media/platforms/agnostic/VPXDecoder.h @@ -61,6 +61,7 @@ private: MediaRawData* aSample); const RefPtr mImageContainer; + RefPtr mImageAllocator; const RefPtr mTaskQueue; MediaDataDecoderCallback* mCallback; Atomic mIsFlushing; diff --git a/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h b/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h index 95b156ff96..c6536da5a1 100644 --- a/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h +++ b/dom/media/platforms/ffmpeg/FFmpegDecoderModule.h @@ -44,6 +44,7 @@ public: aParams.mTaskQueue, aParams.mCallback, aParams.VideoConfig(), + aParams.mKnowsCompositor, aParams.mImageContainer); return decoder.forget(); } diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp index d9e0758534..fc01b24ffa 100644 --- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp @@ -11,6 +11,7 @@ #include "MediaInfo.h" #include "VPXDecoder.h" #include "MP4Decoder.h" +#include "mozilla/layers/KnowsCompositor.h" #include "FFmpegVideoDecoder.h" #include "FFmpegLog.h" @@ -108,8 +109,9 @@ FFmpegVideoDecoder::PtsCorrectionContext::Reset() FFmpegVideoDecoder::FFmpegVideoDecoder(FFmpegLibWrapper* aLib, TaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback, const VideoInfo& aConfig, - ImageContainer* aImageContainer) + KnowsCompositor* aAllocator, ImageContainer* aImageContainer) : FFmpegDataDecoder(aLib, aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType)) + , mImageAllocator(aAllocator) , mImageContainer(aImageContainer) , mInfo(aConfig) , mCodecParser(nullptr) @@ -395,7 +397,8 @@ FFmpegVideoDecoder::CreateImage(int64_t aOffset, int64_t aPts, !!mFrame->key_frame, -1, mInfo.ScaledImageRect(mFrame->width, - mFrame->height)); + mFrame->height), + mImageAllocator); if (!v) { return MediaResult(NS_ERROR_OUT_OF_MEMORY, diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h index adf331ce49..f58ca9d7b0 100644 --- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h +++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h @@ -24,11 +24,13 @@ class FFmpegVideoDecoder : public FFmpegDataDecoder { typedef mozilla::layers::Image Image; typedef mozilla::layers::ImageContainer ImageContainer; + typedef mozilla::layers::KnowsCompositor KnowsCompositor; public: FFmpegVideoDecoder(FFmpegLibWrapper* aLib, TaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback, const VideoInfo& aConfig, + KnowsCompositor* aAllocator, ImageContainer* aImageContainer); virtual ~FFmpegVideoDecoder(); @@ -62,6 +64,7 @@ private: int AllocateYUV420PVideoBuffer(AVCodecContext* aCodecContext, AVFrame* aFrame); + RefPtr mImageAllocator; RefPtr mImageContainer; VideoInfo mInfo;