From 6162647fa5b2d01c6705a106ed39a5c2e97e0ed3 Mon Sep 17 00:00:00 2001 From: stransky Date: Sat, 29 Jan 2022 19:50:24 +0000 Subject: [PATCH] Bug 1752097 [Linux] Remove SW decoding to dmabuf textures r=alwu,media-playback-reviewers Removing SW decoding to dmabuf surfaces in favour of decode to shm surfaces (Bug 1713276). Differential Revision: https://phabricator.services.mozilla.com/D137032 --- .../platforms/ffmpeg/FFmpegVideoDecoder.cpp | 65 +---------------- .../platforms/ffmpeg/FFmpegVideoDecoder.h | 4 -- .../platforms/ffmpeg/FFmpegVideoFramePool.cpp | 71 +++---------------- .../platforms/ffmpeg/FFmpegVideoFramePool.h | 67 ++++++----------- modules/libpref/init/StaticPrefList.yaml | 6 -- widget/gtk/DMABufLibWrapper.cpp | 9 --- widget/gtk/DMABufLibWrapper.h | 2 - 7 files changed, 35 insertions(+), 189 deletions(-) diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp index c3894e9dce36..ce76a3c8fd0a 100644 --- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp @@ -360,13 +360,6 @@ void FFmpegVideoDecoder::InitHWDecodingPrefs() { mEnableHardwareDecoding = false; FFMPEG_LOG("VA-API is disabled by pref."); } - - if (mEnableHardwareDecoding) { - mUseDMABufSurfaces = widget::GetDMABufDevice()->IsDMABufVideoEnabled(); - if (!mUseDMABufSurfaces) { - FFMPEG_LOG("SW encoding to DMABuf textures is disabled by system/pref."); - } - } } #endif @@ -379,7 +372,6 @@ FFmpegVideoDecoder::FFmpegVideoDecoder( mVAAPIDeviceContext(nullptr), mEnableHardwareDecoding(!aDisableHardwareDecoding), mDisplay(nullptr), - mUseDMABufSurfaces(false), #endif mImageAllocator(aAllocator), mImageContainer(aImageContainer), @@ -623,14 +615,6 @@ int FFmpegVideoDecoder::GetVideoBuffer( return AVERROR(EINVAL); } -# ifdef MOZ_WAYLAND_USE_VAAPI - // For SW decoding + DMABuf case, it's the opposite from the above case, we - // don't want to access GPU data too frequently from CPU. - if (mUseDMABufSurfaces) { - return AVERROR(EINVAL); - } -# endif - if (!IsColorFormatSupportedForUsingCustomizedBuffer(aCodecContext->pix_fmt)) { FFMPEG_LOG("Not support color format %d", aCodecContext->pix_fmt); return AVERROR(EINVAL); @@ -817,8 +801,8 @@ MediaResult FFmpegVideoDecoder::DoDecode( # ifdef MOZ_WAYLAND_USE_VAAPI // Create VideoFramePool in case we need it. - if (!mVideoFramePool && (mUseDMABufSurfaces || mEnableHardwareDecoding)) { - mVideoFramePool = MakeUnique(mEnableHardwareDecoding); + if (!mVideoFramePool && mEnableHardwareDecoding) { + mVideoFramePool = MakeUnique(); } // Release unused VA-API surfaces before avcodec_receive_frame() as @@ -855,14 +839,6 @@ MediaResult FFmpegVideoDecoder::DoDecode( mVideoFramePool = nullptr; return rv; } - } else if (mUseDMABufSurfaces) { - rv = CreateImageDMABuf(mFrame->pkt_pos, mFrame->pkt_pts, - mFrame->pkt_duration, aResults); - if (NS_FAILED(rv)) { - mUseDMABufSurfaces = false; - rv = CreateImage(mFrame->pkt_pos, mFrame->pkt_pts, mFrame->pkt_duration, - aResults); - } } else # endif { @@ -1138,43 +1114,6 @@ MediaResult FFmpegVideoDecoder::CreateImageVAAPI( aResults.AppendElement(std::move(vp)); return NS_OK; } - -MediaResult FFmpegVideoDecoder::CreateImageDMABuf( - int64_t aOffset, int64_t aPts, int64_t aDuration, - MediaDataDecoder::DecodedData& aResults) { - FFMPEG_LOG("DMABuf Got one frame output with pts=%" PRId64 "dts=%" PRId64 - " duration=%" PRId64 " opaque=%" PRId64, - aPts, mFrame->pkt_dts, aDuration, mCodecContext->reordered_opaque); - - MOZ_ASSERT(mTaskQueue->IsOnCurrentThread()); - auto surface = - mVideoFramePool->GetVideoFrameSurface(mCodecContext->pix_fmt, mFrame); - if (!surface) { - return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, - RESULT_DETAIL("dmabuf allocation error")); - } - surface->SetYUVColorSpace(GetFrameColorSpace()); - - if (mLib->av_frame_get_color_range) { - auto range = mLib->av_frame_get_color_range(mFrame); - surface->SetColorRange(range == AVCOL_RANGE_JPEG - ? gfx::ColorRange::FULL - : gfx::ColorRange::LIMITED); - } - - RefPtr vp = VideoData::CreateFromImage( - mInfo.mDisplay, aOffset, TimeUnit::FromMicroseconds(aPts), - TimeUnit::FromMicroseconds(aDuration), surface->GetAsImage(), - !!mFrame->key_frame, TimeUnit::FromMicroseconds(-1)); - - if (!vp) { - return MediaResult(NS_ERROR_DOM_MEDIA_DECODE_ERR, - RESULT_DETAIL("image allocation error")); - } - - aResults.AppendElement(std::move(vp)); - return NS_OK; -} #endif RefPtr diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h index 4c1053c29ba0..459df27d00be 100644 --- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h +++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h @@ -132,16 +132,12 @@ class FFmpegVideoDecoder MediaResult CreateImageVAAPI(int64_t aOffset, int64_t aPts, int64_t aDuration, MediaDataDecoder::DecodedData& aResults); - MediaResult CreateImageDMABuf(int64_t aOffset, int64_t aPts, - int64_t aDuration, - MediaDataDecoder::DecodedData& aResults); #endif #ifdef MOZ_WAYLAND_USE_VAAPI AVBufferRef* mVAAPIDeviceContext; bool mEnableHardwareDecoding; VADisplay mDisplay; - bool mUseDMABufSurfaces; UniquePtr mVideoFramePool; static nsTArray mAcceleratedFormats; #endif diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.cpp index 7cf74dec83e6..ed343b08586f 100644 --- a/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.cpp +++ b/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.cpp @@ -15,11 +15,11 @@ namespace mozilla { -RefPtr VideoFrameSurfaceDMABuf::GetAsImage() { +RefPtr VideoFrameSurfaceVAAPI::GetAsImage() { return new layers::DMABUFSurfaceImage(mSurface); } -VideoFrameSurfaceDMABuf::VideoFrameSurfaceDMABuf(DMABufSurface* aSurface) +VideoFrameSurfaceVAAPI::VideoFrameSurfaceVAAPI(DMABufSurface* aSurface) : mSurface(aSurface) { // Create global refcount object to track mSurface usage over // gects rendering engine. We can't release it until it's used @@ -28,13 +28,10 @@ VideoFrameSurfaceDMABuf::VideoFrameSurfaceDMABuf(DMABufSurface* aSurface) MOZ_RELEASE_ASSERT(mSurface->GetAsDMABufSurfaceYUV()); mSurface->GlobalRefCountCreate(); mSurface->GlobalRefAdd(); - FFMPEG_LOG("VideoFrameSurfaceDMABuf: creating surface UID = %d", + FFMPEG_LOG("VideoFrameSurfaceVAAPI: creating surface UID = %d", mSurface->GetUID()); } -VideoFrameSurfaceVAAPI::VideoFrameSurfaceVAAPI(DMABufSurface* aSurface) - : VideoFrameSurfaceDMABuf(aSurface) {} - void VideoFrameSurfaceVAAPI::LockVAAPIData(AVCodecContext* aAVCodecContext, AVFrame* aAVFrame, FFmpegLibWrapper* aLib) { @@ -73,8 +70,7 @@ VideoFrameSurfaceVAAPI::~VideoFrameSurfaceVAAPI() { ReleaseVAAPIData(/* aForFrameRecycle */ false); } -VideoFramePool::VideoFramePool(bool aUseVAAPI) - : mUseVAAPI(aUseVAAPI), mSurfaceLock("VideoFramePoolSurfaceLock") {} +VideoFramePool::VideoFramePool() : mSurfaceLock("VideoFramePoolSurfaceLock") {} VideoFramePool::~VideoFramePool() { MutexAutoLock lock(mSurfaceLock); @@ -82,14 +78,11 @@ VideoFramePool::~VideoFramePool() { } void VideoFramePool::ReleaseUnusedVAAPIFrames() { - if (!mUseVAAPI) { - return; - } MutexAutoLock lock(mSurfaceLock); for (const auto& surface : mDMABufSurfaces) { - auto* dmabufSurface = surface->AsVideoFrameSurfaceVAAPI(); - if (!dmabufSurface->IsUsed()) { - dmabufSurface->ReleaseVAAPIData(); + auto* vaapiSurface = surface->AsVideoFrameSurfaceVAAPI(); + if (!vaapiSurface->IsUsed()) { + vaapiSurface->ReleaseVAAPIData(); } } } @@ -99,10 +92,9 @@ RefPtr VideoFramePool::GetFreeVideoFrameSurface() { if (surface->IsUsed()) { continue; } - if (auto* vaapiSurface = surface->AsVideoFrameSurfaceVAAPI()) { - vaapiSurface->ReleaseVAAPIData(); - } - surface->MarkAsUsed(); + auto* vaapiSurface = surface->AsVideoFrameSurfaceVAAPI(); + vaapiSurface->ReleaseVAAPIData(); + vaapiSurface->MarkAsUsed(); return surface; } return nullptr; @@ -111,9 +103,6 @@ RefPtr VideoFramePool::GetFreeVideoFrameSurface() { RefPtr VideoFramePool::GetVideoFrameSurface( VADRMPRIMESurfaceDescriptor& aVaDesc, AVCodecContext* aAVCodecContext, AVFrame* aAVFrame, FFmpegLibWrapper* aLib) { - // VADRMPRIMESurfaceDescriptor can be used with VA-API only. - MOZ_ASSERT(mUseVAAPI); - if (aVaDesc.fourcc != VA_FOURCC_NV12 && aVaDesc.fourcc != VA_FOURCC_YV12 && aVaDesc.fourcc != VA_FOURCC_P010) { FFMPEG_LOG("Unsupported VA-API surface format %d", aVaDesc.fourcc); @@ -129,7 +118,7 @@ RefPtr VideoFramePool::GetVideoFrameSurface( return nullptr; } FFMPEG_LOG("Created new VA-API DMABufSurface UID = %d", surface->GetUID()); - RefPtr surf = new VideoFrameSurfaceVAAPI(surface); + RefPtr surf = new VideoFrameSurfaceVAAPI(surface); if (!mTextureCreationWorks) { mTextureCreationWorks = Some(surface->VerifyTextureCreation()); } @@ -153,42 +142,4 @@ RefPtr VideoFramePool::GetVideoFrameSurface( return videoSurface; } -RefPtr VideoFramePool::GetVideoFrameSurface( - AVPixelFormat aPixelFormat, AVFrame* aFrame) { - // We should not use SW surfaces when VA-API is enabled. - MOZ_ASSERT(!mUseVAAPI); - MOZ_ASSERT(aFrame); - - // With SW decode we support only YUV420P format with DMABuf surfaces. - if (aPixelFormat != AV_PIX_FMT_YUV420P) { - return nullptr; - } - - MutexAutoLock lock(mSurfaceLock); - if (RefPtr videoSurface = GetFreeVideoFrameSurface()) { - RefPtr surface = videoSurface->GetDMABufSurface(); - if (!surface->UpdateYUVData((void**)aFrame->data, aFrame->linesize)) { - return nullptr; - } - FFMPEG_LOG("Reusing SW DMABufSurface UID = %d", surface->GetUID()); - return videoSurface; - } - RefPtr surface = DMABufSurfaceYUV::CreateYUVSurface( - aFrame->width, aFrame->height, (void**)aFrame->data, aFrame->linesize); - if (!surface) { - return nullptr; - } - RefPtr surf = new VideoFrameSurfaceDMABuf(surface); - if (!mTextureCreationWorks) { - mTextureCreationWorks = Some(surface->VerifyTextureCreation()); - } - if (!*mTextureCreationWorks) { - FFMPEG_LOG(" failed to create texture over DMABuf memory!"); - return nullptr; - } - FFMPEG_LOG("Created new SW DMABufSurface UID = %d", surface->GetUID()); - mDMABufSurfaces.AppendElement(surf); - return surf; -} - } // namespace mozilla diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h b/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h index bf4cbb356900..c506d22430d4 100644 --- a/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h +++ b/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h @@ -17,7 +17,6 @@ namespace mozilla { class VideoFramePool; -class VideoFrameSurfaceDMABuf; class VideoFrameSurfaceVAAPI; class VideoFrameSurface { @@ -26,9 +25,6 @@ class VideoFrameSurface { VideoFrameSurface() = default; - virtual VideoFrameSurfaceDMABuf* AsVideoFrameSurfaceDMABuf() { - return nullptr; - } virtual VideoFrameSurfaceVAAPI* AsVideoFrameSurfaceVAAPI() { return nullptr; } virtual void SetYUVColorSpace(gfx::YUVColorSpace aColorSpace) = 0; @@ -47,41 +43,6 @@ class VideoFrameSurface { virtual ~VideoFrameSurface(){}; }; -// VideoFrameSurfaceDMABuf is YUV dmabuf surface used for SW video decoding. -// Stores decoded video data in GPU memory. -class VideoFrameSurfaceDMABuf : public VideoFrameSurface { - friend class VideoFramePool; - - public: - explicit VideoFrameSurfaceDMABuf(DMABufSurface* aSurface); - - VideoFrameSurfaceDMABuf* AsVideoFrameSurfaceDMABuf() final { return this; } - - void SetYUVColorSpace(gfx::YUVColorSpace aColorSpace) final { - mSurface->GetAsDMABufSurfaceYUV()->SetYUVColorSpace(aColorSpace); - } - void SetColorRange(gfx::ColorRange aColorRange) final { - mSurface->GetAsDMABufSurfaceYUV()->SetColorRange(aColorRange); - } - - RefPtr GetDMABufSurface() final { - return mSurface->GetAsDMABufSurfaceYUV(); - }; - - RefPtr GetAsImage() final; - - protected: - // Check if DMABufSurface is used by any gecko rendering process - // (WebRender or GL compositor) or by DMABUFSurfaceImage/VideoData. - bool IsUsed() const { return mSurface->IsGlobalRefSet(); } - void MarkAsUsed() { mSurface->GlobalRefAdd(); } - - protected: - const RefPtr mSurface; - - virtual ~VideoFrameSurfaceDMABuf() = default; -}; - // VideoFrameSurfaceVAAPI holds a reference to GPU data with a video frame. // // Actual GPU pixel data are stored at DMABufSurface and @@ -111,7 +72,7 @@ class VideoFrameSurfaceDMABuf : public VideoFrameSurface { // Unfortunately there isn't any obvious way how to mark particular VASurface // as used. The best we can do is to hold a reference to particular AVBuffer // from decoded AVFrame and AVHWFramesContext which owns the AVBuffer. -class VideoFrameSurfaceVAAPI final : public VideoFrameSurfaceDMABuf { +class VideoFrameSurfaceVAAPI final : public VideoFrameSurface { friend class VideoFramePool; public: @@ -119,6 +80,19 @@ class VideoFrameSurfaceVAAPI final : public VideoFrameSurfaceDMABuf { VideoFrameSurfaceVAAPI* AsVideoFrameSurfaceVAAPI() final { return this; } + void SetYUVColorSpace(mozilla::gfx::YUVColorSpace aColorSpace) { + mSurface->GetAsDMABufSurfaceYUV()->SetYUVColorSpace(aColorSpace); + } + void SetColorRange(mozilla::gfx::ColorRange aColorRange) { + mSurface->GetAsDMABufSurfaceYUV()->SetColorRange(aColorRange); + } + + RefPtr GetDMABufSurface() { + return mSurface->GetAsDMABufSurfaceYUV(); + }; + + RefPtr GetAsImage(); + protected: // Lock VAAPI related data void LockVAAPIData(AVCodecContext* aAVCodecContext, AVFrame* aAVFrame, @@ -127,9 +101,15 @@ class VideoFrameSurfaceVAAPI final : public VideoFrameSurfaceDMABuf { // for another frame. void ReleaseVAAPIData(bool aForFrameRecycle = true); + // Check if DMABufSurface is used by any gecko rendering process + // (WebRender or GL compositor) or by DMABUFSurfaceImage/VideoData. + bool IsUsed() const { return mSurface->IsGlobalRefSet(); } + void MarkAsUsed() { mSurface->GlobalRefAdd(); } + private: virtual ~VideoFrameSurfaceVAAPI(); + const RefPtr mSurface; const FFmpegLibWrapper* mLib; AVBufferRef* mAVHWFramesContext; AVBufferRef* mHWAVBuffer; @@ -138,24 +118,21 @@ class VideoFrameSurfaceVAAPI final : public VideoFrameSurfaceDMABuf { // VideoFramePool class is thread-safe. class VideoFramePool final { public: - explicit VideoFramePool(bool aUseVAAPI); + VideoFramePool(); ~VideoFramePool(); RefPtr GetVideoFrameSurface( VADRMPRIMESurfaceDescriptor& aVaDesc, AVCodecContext* aAVCodecContext, AVFrame* aAVFrame, FFmpegLibWrapper* aLib); - RefPtr GetVideoFrameSurface(AVPixelFormat aPixelFormat, - AVFrame* aFrame); void ReleaseUnusedVAAPIFrames(); private: RefPtr GetFreeVideoFrameSurface(); private: - const bool mUseVAAPI; // Protect mDMABufSurfaces pool access Mutex mSurfaceLock; - nsTArray> mDMABufSurfaces; + nsTArray> mDMABufSurfaces; // We may fail to create texture over DMABuf memory due to driver bugs so // check that before we export first DMABuf video frame. Maybe mTextureCreationWorks; diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index f8373ab7d80e..8ed5b2598509 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -8758,12 +8758,6 @@ mirror: always #ifdef MOZ_WAYLAND -# Disable DMABuf for ffmpeg video textures on Linux -- name: media.ffmpeg.dmabuf-textures.disabled - type: RelaxedAtomicBool - value: false - mirror: always - # Use VA-API for ffmpeg video playback on Linux - name: media.ffmpeg.vaapi.enabled type: RelaxedAtomicBool diff --git a/widget/gtk/DMABufLibWrapper.cpp b/widget/gtk/DMABufLibWrapper.cpp index 5397c3323118..d37ce978af4e 100644 --- a/widget/gtk/DMABufLibWrapper.cpp +++ b/widget/gtk/DMABufLibWrapper.cpp @@ -272,15 +272,6 @@ bool nsDMABufDevice::IsDMABufTexturesEnabled() { #else bool nsDMABufDevice::IsDMABufTexturesEnabled() { return false; } #endif -bool nsDMABufDevice::IsDMABufVideoEnabled() { - LOGDMABUF( - ("nsDMABufDevice::IsDMABufVideoEnabled: EGL %d DMABufEnabled %d " - "!media_ffmpeg_dmabuf_textures_disabled %d\n", - gfx::gfxVars::UseEGL(), IsDMABufEnabled(), - !StaticPrefs::media_ffmpeg_dmabuf_textures_disabled())); - return !StaticPrefs::media_ffmpeg_dmabuf_textures_disabled() && - gfx::gfxVars::UseDMABuf() && IsDMABufEnabled(); -} bool nsDMABufDevice::IsDMABufVAAPIEnabled() { LOGDMABUF( ("nsDMABufDevice::IsDMABufVAAPIEnabled: EGL %d " diff --git a/widget/gtk/DMABufLibWrapper.h b/widget/gtk/DMABufLibWrapper.h index 14d486786df0..82a9dee9b682 100644 --- a/widget/gtk/DMABufLibWrapper.h +++ b/widget/gtk/DMABufLibWrapper.h @@ -174,8 +174,6 @@ class nsDMABufDevice { // Use dmabuf for WebRender general web content bool IsDMABufTexturesEnabled(); - // Use dmabuf for video playback - bool IsDMABufVideoEnabled(); // Use dmabuf for VA-API video playback bool IsDMABufVAAPIEnabled(); // Use dmabuf for WebGL content