From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h | 155 ++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h (limited to 'dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h') diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h b/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h new file mode 100644 index 0000000000..baf89c504d --- /dev/null +++ b/dom/media/platforms/ffmpeg/FFmpegVideoFramePool.h @@ -0,0 +1,155 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __FFmpegVideoFramePool_h__ +#define __FFmpegVideoFramePool_h__ + +#include "FFmpegLibWrapper.h" +#include "FFmpegLibs.h" +#include "FFmpegLog.h" + +#include "mozilla/layers/DMABUFSurfaceImage.h" +#include "mozilla/widget/DMABufLibWrapper.h" +#include "mozilla/widget/DMABufSurface.h" + +namespace mozilla { + +// VideoFrameSurface holds a reference to GPU data with a video frame. +// +// Actual GPU pixel data are stored at DMABufSurface and +// DMABufSurface is passed to gecko GL rendering pipeline via. +// DMABUFSurfaceImage. +// +// VideoFrameSurface can optionally hold VA-API ffmpeg related data to keep +// GPU data locked untill we need them. +// +// VideoFrameSurface is used for both HW accelerated video decoding +// (VA-API) and ffmpeg SW decoding. +// +// VA-API scenario +// +// When VA-API decoding is running, ffmpeg allocates AVHWFramesContext - a pool +// of "hardware" frames. Every "hardware" frame (VASurface) is backed +// by actual piece of GPU memory which holds the decoded image data. +// +// The VASurface is wrapped by DMABufSurface and transferred to +// rendering queue by DMABUFSurfaceImage, where TextureClient is +// created and VASurface is used as a texture there. +// +// As there's a limited number of VASurfaces, ffmpeg reuses them to decode +// next frames ASAP even if they are still attached to DMABufSurface +// and used as a texture in our rendering engine. +// +// 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. +template +class VideoFrameSurface {}; +template <> +class VideoFrameSurface; + +template +class VideoFramePool {}; +template <> +class VideoFramePool; + +template <> +class VideoFrameSurface { + friend class VideoFramePool; + + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoFrameSurface) + + explicit VideoFrameSurface(DMABufSurface* aSurface); + + 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(); + + // Don't allow VideoFrameSurface plain copy as it leads to + // unexpected DMABufSurface/HW buffer releases and we don't want to + // deep copy them. + VideoFrameSurface(const VideoFrameSurface&) = delete; + const VideoFrameSurface& operator=(VideoFrameSurface const&) = delete; + + protected: + // Lock VAAPI related data + void LockVAAPIData(AVCodecContext* aAVCodecContext, AVFrame* aAVFrame, + FFmpegLibWrapper* aLib); + // Release VAAPI related data, DMABufSurface can be reused + // 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(); } + + // Surface points to dmabuf memmory owned by ffmpeg. + bool IsFFMPEGSurface() const { return !!mLib; } + + void MarkAsUsed(VASurfaceID aFFMPEGSurfaceID) { + mFFMPEGSurfaceID = Some(aFFMPEGSurfaceID); + } + + private: + virtual ~VideoFrameSurface(); + + const RefPtr mSurface; + const FFmpegLibWrapper* mLib; + AVBufferRef* mAVHWFrameContext; + AVBufferRef* mHWAVBuffer; + Maybe mFFMPEGSurfaceID; +}; + +// VideoFramePool class is thread-safe. +template <> +class VideoFramePool { + public: + explicit VideoFramePool(int aFFMPEGPoolSize); + ~VideoFramePool(); + + RefPtr> GetVideoFrameSurface( + VADRMPRIMESurfaceDescriptor& aVaDesc, int aWidth, int aHeight, + AVCodecContext* aAVCodecContext, AVFrame* aAVFrame, + FFmpegLibWrapper* aLib); + RefPtr> GetVideoFrameSurface( + AVDRMFrameDescriptor& aDesc, int aWidth, int aHeight, + AVCodecContext* aAVCodecContext, AVFrame* aAVFrame, + FFmpegLibWrapper* aLib); + + void ReleaseUnusedVAAPIFrames(); + + private: + RefPtr> GetFreeVideoFrameSurface(); + bool ShouldCopySurface(); + void CheckNewFFMPEGSurface(VASurfaceID aNewSurfaceID); + + private: + // Protect mDMABufSurfaces pool access + Mutex mSurfaceLock MOZ_UNANNOTATED; + nsTArray>> mDMABufSurfaces; + // Number of dmabuf surfaces allocated by ffmpeg for decoded video frames. + // Can be adjusted by extra_hw_frames at InitVAAPICodecContext(). + int mFFMPEGPoolSize; + // 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; + // We may fail to copy DMABuf memory on NVIDIA drivers. + bool mTextureCopyWorks = true; +}; + +} // namespace mozilla + +#endif // __FFmpegVideoFramePool_h__ -- cgit v1.2.3