Issue #2393 - Part 3 - Remove extra copy of YUV buffer on Windows

This commit is contained in:
trav90 2023-11-28 14:41:34 -06:00 • committed by roytam1
commit b09b3771c6
9 changed files with 70 additions and 20 deletions

View file

@ -9,9 +9,16 @@
#include "ImageContainer.h" #include "ImageContainer.h"
#include "mozilla/layers/SharedRGBImage.h" #include "mozilla/layers/SharedRGBImage.h"
#include "YCbCrUtils.h" #include "YCbCrUtils.h"
#include "mozilla/layers/ImageBridgeChild.h"
#include "mozilla/layers/KnowsCompositor.h"
#include <stdint.h> #include <stdint.h>
#ifdef XP_WIN
#include "mozilla/WindowsVersion.h"
#include "mozilla/layers/D3D11YCbCrImage.h"
#endif
namespace mozilla { namespace mozilla {
using namespace mozilla::gfx; using namespace mozilla::gfx;
@ -218,19 +225,14 @@ VideoData::ShallowCopyUpdateTimestampAndDuration(const VideoData* aOther,
return v.forget(); return v.forget();
} }
/* static */ PlanarYCbCrData
bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage, ConstructPlanarYCbCrData(const VideoInfo& aInfo,
const VideoInfo& aInfo, const VideoData::YCbCrBuffer& aBuffer,
const YCbCrBuffer &aBuffer, const IntRect& aPicture)
const IntRect& aPicture,
bool aCopyData)
{ {
if (!aVideoImage) { const VideoData::YCbCrBuffer::Plane& Y = aBuffer.mPlanes[0];
return false; const VideoData::YCbCrBuffer::Plane& Cb = aBuffer.mPlanes[1];
} const VideoData::YCbCrBuffer::Plane& Cr = aBuffer.mPlanes[2];
const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
PlanarYCbCrData data; PlanarYCbCrData data;
data.mYChannel = Y.mData + Y.mOffset; data.mYChannel = Y.mData + Y.mOffset;
@ -249,6 +251,21 @@ bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
data.mStereoMode = aInfo.mStereoMode; data.mStereoMode = aInfo.mStereoMode;
data.mYUVColorSpace = aBuffer.mYUVColorSpace; data.mYUVColorSpace = aBuffer.mYUVColorSpace;
data.mColorRange = aBuffer.mColorRange; 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); aVideoImage->SetDelayedConversion(true);
if (aCopyData) { if (aCopyData) {
@ -268,7 +285,8 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
const YCbCrBuffer& aBuffer, const YCbCrBuffer& aBuffer,
bool aKeyframe, bool aKeyframe,
int64_t aTimecode, int64_t aTimecode,
const IntRect& aPicture) const IntRect& aPicture,
layers::KnowsCompositor* aAllocator)
{ {
if (!aContainer) { if (!aContainer) {
// Create a dummy VideoData with no image. This gives us something to // Create a dummy VideoData with no image. This gives us something to
@ -296,6 +314,23 @@ VideoData::CreateAndCopyData(const VideoInfo& aInfo,
0)); 0));
// Currently our decoder only knows how to output to ImageFormat::PLANAR_YCBCR // Currently our decoder only knows how to output to ImageFormat::PLANAR_YCBCR
// format. // 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<layers::D3D11YCbCrImage> 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) { if (!v->mImage) {
v->mImage = aContainer->CreatePlanarYCbCrImage(); v->mImage = aContainer->CreatePlanarYCbCrImage();
} }

View file

@ -25,6 +25,7 @@ namespace mozilla {
namespace layers { namespace layers {
class Image; class Image;
class ImageContainer; class ImageContainer;
class KnowsCompositor;
} // namespace layers } // namespace layers
class MediaByteBuffer; class MediaByteBuffer;
@ -472,7 +473,8 @@ public:
const YCbCrBuffer &aBuffer, const YCbCrBuffer &aBuffer,
bool aKeyframe, bool aKeyframe,
int64_t aTimecode, int64_t aTimecode,
const IntRect& aPicture); const IntRect& aPicture,
layers::KnowsCompositor* aAllocator = nullptr);
static already_AddRefed<VideoData> CreateAndCopyData(const VideoInfo& aInfo, static already_AddRefed<VideoData> CreateAndCopyData(const VideoInfo& aInfo,
ImageContainer* aContainer, ImageContainer* aContainer,

View file

@ -38,7 +38,8 @@ ogg_packet InitTheoraPacket(const unsigned char* aData, size_t aLength,
} }
TheoraDecoder::TheoraDecoder(const CreateDecoderParams& aParams) TheoraDecoder::TheoraDecoder(const CreateDecoderParams& aParams)
: mImageContainer(aParams.mImageContainer) : mImageAllocator(aParams.mKnowsCompositor)
, mImageContainer(aParams.mImageContainer)
, mTaskQueue(aParams.mTaskQueue) , mTaskQueue(aParams.mTaskQueue)
, mCallback(aParams.mCallback) , mCallback(aParams.mCallback)
, mIsFlushing(false) , mIsFlushing(false)
@ -176,7 +177,8 @@ TheoraDecoder::DoDecode(MediaRawData* aSample)
aSample->mKeyframe, aSample->mKeyframe,
aSample->mTimecode, aSample->mTimecode,
mInfo.ScaledImageRect(mTheoraInfo.frame_width, mInfo.ScaledImageRect(mTheoraInfo.frame_width,
mTheoraInfo.frame_height)); mTheoraInfo.frame_height),
mImageAllocator);
if (!v) { if (!v) {
LOG("Image allocation error source %ldx%ld display %ldx%ld picture %ldx%ld", 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, mTheoraInfo.frame_width, mTheoraInfo.frame_height, mInfo.mDisplay.width, mInfo.mDisplay.height,

View file

@ -43,6 +43,7 @@ private:
MediaResult DoDecode(MediaRawData* aSample); MediaResult DoDecode(MediaRawData* aSample);
void ProcessDrain(); void ProcessDrain();
RefPtr<KnowsCompositor> mImageAllocator;
RefPtr<ImageContainer> mImageContainer; RefPtr<ImageContainer> mImageContainer;
RefPtr<TaskQueue> mTaskQueue; RefPtr<TaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback; MediaDataDecoderCallback* mCallback;

View file

@ -69,6 +69,7 @@ InitContext(vpx_codec_ctx_t* aCtx,
VPXDecoder::VPXDecoder(const CreateDecoderParams& aParams) VPXDecoder::VPXDecoder(const CreateDecoderParams& aParams)
: mImageContainer(aParams.mImageContainer) : mImageContainer(aParams.mImageContainer)
, mImageAllocator(aParams.mKnowsCompositor)
, mTaskQueue(aParams.mTaskQueue) , mTaskQueue(aParams.mTaskQueue)
, mCallback(aParams.mCallback) , mCallback(aParams.mCallback)
, mIsFlushing(false) , mIsFlushing(false)
@ -149,7 +150,7 @@ VPXDecoder::DoDecode(MediaRawData* aSample)
"WebM image format not I420 or I444"); "WebM image format not I420 or I444");
NS_ASSERTION(!alpha_decoded, NS_ASSERTION(!alpha_decoded,
"Multiple frames per packet that contains alpha"); "Multiple frames per packet that contains alpha");
if (aSample->AlphaSize() > 0) { if (aSample->AlphaSize() > 0) {
if(!alpha_decoded){ if(!alpha_decoded){
MediaResult rv = DecodeAlpha(&img_alpha, aSample); MediaResult rv = DecodeAlpha(&img_alpha, aSample);
@ -221,7 +222,8 @@ VPXDecoder::DoDecode(MediaRawData* aSample)
aSample->mKeyframe, aSample->mKeyframe,
aSample->mTimecode, aSample->mTimecode,
mInfo.ScaledImageRect(img->d_w, mInfo.ScaledImageRect(img->d_w,
img->d_h)); img->d_h),
mImageAllocator);
} else { } else {
VideoData::YCbCrBuffer::Plane alpha_plane; VideoData::YCbCrBuffer::Plane alpha_plane;
alpha_plane.mData = img_alpha->planes[0]; alpha_plane.mData = img_alpha->planes[0];

View file

@ -61,6 +61,7 @@ private:
MediaRawData* aSample); MediaRawData* aSample);
const RefPtr<ImageContainer> mImageContainer; const RefPtr<ImageContainer> mImageContainer;
RefPtr<layers::KnowsCompositor> mImageAllocator;
const RefPtr<TaskQueue> mTaskQueue; const RefPtr<TaskQueue> mTaskQueue;
MediaDataDecoderCallback* mCallback; MediaDataDecoderCallback* mCallback;
Atomic<bool> mIsFlushing; Atomic<bool> mIsFlushing;

View file

@ -44,6 +44,7 @@ public:
aParams.mTaskQueue, aParams.mTaskQueue,
aParams.mCallback, aParams.mCallback,
aParams.VideoConfig(), aParams.VideoConfig(),
aParams.mKnowsCompositor,
aParams.mImageContainer); aParams.mImageContainer);
return decoder.forget(); return decoder.forget();
} }

View file

@ -11,6 +11,7 @@
#include "MediaInfo.h" #include "MediaInfo.h"
#include "VPXDecoder.h" #include "VPXDecoder.h"
#include "MP4Decoder.h" #include "MP4Decoder.h"
#include "mozilla/layers/KnowsCompositor.h"
#include "FFmpegVideoDecoder.h" #include "FFmpegVideoDecoder.h"
#include "FFmpegLog.h" #include "FFmpegLog.h"
@ -108,8 +109,9 @@ FFmpegVideoDecoder<LIBAV_VER>::PtsCorrectionContext::Reset()
FFmpegVideoDecoder<LIBAV_VER>::FFmpegVideoDecoder(FFmpegLibWrapper* aLib, FFmpegVideoDecoder<LIBAV_VER>::FFmpegVideoDecoder(FFmpegLibWrapper* aLib,
TaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback, TaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
const VideoInfo& aConfig, const VideoInfo& aConfig,
ImageContainer* aImageContainer) KnowsCompositor* aAllocator, ImageContainer* aImageContainer)
: FFmpegDataDecoder(aLib, aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType)) : FFmpegDataDecoder(aLib, aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
, mImageAllocator(aAllocator)
, mImageContainer(aImageContainer) , mImageContainer(aImageContainer)
, mInfo(aConfig) , mInfo(aConfig)
, mCodecParser(nullptr) , mCodecParser(nullptr)
@ -395,7 +397,8 @@ FFmpegVideoDecoder<LIBAV_VER>::CreateImage(int64_t aOffset, int64_t aPts,
!!mFrame->key_frame, !!mFrame->key_frame,
-1, -1,
mInfo.ScaledImageRect(mFrame->width, mInfo.ScaledImageRect(mFrame->width,
mFrame->height)); mFrame->height),
mImageAllocator);
if (!v) { if (!v) {
return MediaResult(NS_ERROR_OUT_OF_MEMORY, return MediaResult(NS_ERROR_OUT_OF_MEMORY,

View file

@ -24,11 +24,13 @@ class FFmpegVideoDecoder<LIBAV_VER> : public FFmpegDataDecoder<LIBAV_VER>
{ {
typedef mozilla::layers::Image Image; typedef mozilla::layers::Image Image;
typedef mozilla::layers::ImageContainer ImageContainer; typedef mozilla::layers::ImageContainer ImageContainer;
typedef mozilla::layers::KnowsCompositor KnowsCompositor;
public: public:
FFmpegVideoDecoder(FFmpegLibWrapper* aLib, TaskQueue* aTaskQueue, FFmpegVideoDecoder(FFmpegLibWrapper* aLib, TaskQueue* aTaskQueue,
MediaDataDecoderCallback* aCallback, MediaDataDecoderCallback* aCallback,
const VideoInfo& aConfig, const VideoInfo& aConfig,
KnowsCompositor* aAllocator,
ImageContainer* aImageContainer); ImageContainer* aImageContainer);
virtual ~FFmpegVideoDecoder(); virtual ~FFmpegVideoDecoder();
@ -62,6 +64,7 @@ private:
int AllocateYUV420PVideoBuffer(AVCodecContext* aCodecContext, int AllocateYUV420PVideoBuffer(AVCodecContext* aCodecContext,
AVFrame* aFrame); AVFrame* aFrame);
RefPtr<KnowsCompositor> mImageAllocator;
RefPtr<ImageContainer> mImageContainer; RefPtr<ImageContainer> mImageContainer;
VideoInfo mInfo; VideoInfo mInfo;