Bug 1758610 [Linux] Implement VideoFramePool as template r=alwu

Depends on D141827

Differential Revision: https://phabricator.services.mozilla.com/D141828
This commit is contained in:
stransky 2022-03-23 19:32:32 +00:00
Родитель 39c0400669
Коммит bf36926523
6 изменённых файлов: 48 добавлений и 28 удалений

Просмотреть файл

@ -805,7 +805,7 @@ MediaResult FFmpegVideoDecoder<LIBAV_VER>::DoDecode(
# ifdef MOZ_WAYLAND_USE_VAAPI
// Create VideoFramePool in case we need it.
if (!mVideoFramePool && mEnableHardwareDecoding) {
mVideoFramePool = MakeUnique<VideoFramePool>();
mVideoFramePool = MakeUnique<VideoFramePool<LIBAV_VER>>();
}
// Release unused VA-API surfaces before avcodec_receive_frame() as

Просмотреть файл

@ -16,6 +16,9 @@
#if LIBAVCODEC_VERSION_MAJOR >= 57 && LIBAVUTIL_VERSION_MAJOR >= 56
# include "mozilla/layers/TextureClient.h"
#endif
#ifdef MOZ_WAYLAND_USE_VAAPI
# include "FFmpegVideoFramePool.h"
#endif
struct _VADRMPRIMESurfaceDescriptor;
typedef struct _VADRMPRIMESurfaceDescriptor VADRMPRIMESurfaceDescriptor;
@ -23,7 +26,6 @@ typedef struct _VADRMPRIMESurfaceDescriptor VADRMPRIMESurfaceDescriptor;
namespace mozilla {
class ImageBufferWrapper;
class VideoFramePool;
template <int V>
class FFmpegVideoDecoder : public FFmpegDataDecoder<V> {};
@ -135,7 +137,7 @@ class FFmpegVideoDecoder<LIBAV_VER>
AVBufferRef* mVAAPIDeviceContext;
bool mEnableHardwareDecoding;
VADisplay mDisplay;
UniquePtr<VideoFramePool> mVideoFramePool;
UniquePtr<VideoFramePool<LIBAV_VER>> mVideoFramePool;
static nsTArray<AVCodecID> mAcceleratedFormats;
#endif
RefPtr<KnowsCompositor> mImageAllocator;

Просмотреть файл

@ -15,11 +15,11 @@
namespace mozilla {
RefPtr<layers::Image> VideoFrameSurface::GetAsImage() {
RefPtr<layers::Image> VideoFrameSurface<LIBAV_VER>::GetAsImage() {
return new layers::DMABUFSurfaceImage(mSurface);
}
VideoFrameSurface::VideoFrameSurface(DMABufSurface* aSurface)
VideoFrameSurface<LIBAV_VER>::VideoFrameSurface(DMABufSurface* aSurface)
: mSurface(aSurface),
mLib(nullptr),
mAVHWFramesContext(nullptr),
@ -34,9 +34,9 @@ VideoFrameSurface::VideoFrameSurface(DMABufSurface* aSurface)
mSurface->GetUID());
}
void VideoFrameSurface::LockVAAPIData(AVCodecContext* aAVCodecContext,
AVFrame* aAVFrame,
FFmpegLibWrapper* aLib) {
void VideoFrameSurface<LIBAV_VER>::LockVAAPIData(
AVCodecContext* aAVCodecContext, AVFrame* aAVFrame,
FFmpegLibWrapper* aLib) {
FFMPEG_LOG("VideoFrameSurface: VAAPI locking dmabuf surface UID = %d",
mSurface->GetUID());
mLib = aLib;
@ -44,7 +44,7 @@ void VideoFrameSurface::LockVAAPIData(AVCodecContext* aAVCodecContext,
mHWAVBuffer = aLib->av_buffer_ref(aAVFrame->buf[0]);
}
void VideoFrameSurface::ReleaseVAAPIData(bool aForFrameRecycle) {
void VideoFrameSurface<LIBAV_VER>::ReleaseVAAPIData(bool aForFrameRecycle) {
FFMPEG_LOG("VideoFrameSurface: VAAPI releasing dmabuf surface UID = %d",
mSurface->GetUID());
@ -67,21 +67,22 @@ void VideoFrameSurface::ReleaseVAAPIData(bool aForFrameRecycle) {
}
}
VideoFrameSurface::~VideoFrameSurface() {
VideoFrameSurface<LIBAV_VER>::~VideoFrameSurface() {
FFMPEG_LOG("VideoFrameSurface: deleting dmabuf surface UID = %d",
mSurface->GetUID());
// We're about to quit, no need to recycle the frames.
ReleaseVAAPIData(/* aForFrameRecycle */ false);
}
VideoFramePool::VideoFramePool() : mSurfaceLock("VideoFramePoolSurfaceLock") {}
VideoFramePool<LIBAV_VER>::VideoFramePool()
: mSurfaceLock("VideoFramePoolSurfaceLock") {}
VideoFramePool::~VideoFramePool() {
VideoFramePool<LIBAV_VER>::~VideoFramePool() {
MutexAutoLock lock(mSurfaceLock);
mDMABufSurfaces.Clear();
}
void VideoFramePool::ReleaseUnusedVAAPIFrames() {
void VideoFramePool<LIBAV_VER>::ReleaseUnusedVAAPIFrames() {
MutexAutoLock lock(mSurfaceLock);
for (const auto& surface : mDMABufSurfaces) {
if (!surface->IsUsed()) {
@ -90,7 +91,8 @@ void VideoFramePool::ReleaseUnusedVAAPIFrames() {
}
}
RefPtr<VideoFrameSurface> VideoFramePool::GetFreeVideoFrameSurface() {
RefPtr<VideoFrameSurface<LIBAV_VER>>
VideoFramePool<LIBAV_VER>::GetFreeVideoFrameSurface() {
for (auto& surface : mDMABufSurfaces) {
if (surface->IsUsed()) {
continue;
@ -101,7 +103,8 @@ RefPtr<VideoFrameSurface> VideoFramePool::GetFreeVideoFrameSurface() {
return nullptr;
}
RefPtr<VideoFrameSurface> VideoFramePool::GetVideoFrameSurface(
RefPtr<VideoFrameSurface<LIBAV_VER>>
VideoFramePool<LIBAV_VER>::GetVideoFrameSurface(
VADRMPRIMESurfaceDescriptor& aVaDesc, AVCodecContext* aAVCodecContext,
AVFrame* aAVFrame, FFmpegLibWrapper* aLib) {
if (aVaDesc.fourcc != VA_FOURCC_NV12 && aVaDesc.fourcc != VA_FOURCC_YV12 &&
@ -111,7 +114,8 @@ RefPtr<VideoFrameSurface> VideoFramePool::GetVideoFrameSurface(
}
MutexAutoLock lock(mSurfaceLock);
RefPtr<VideoFrameSurface> videoSurface = GetFreeVideoFrameSurface();
RefPtr<VideoFrameSurface<LIBAV_VER>> videoSurface =
GetFreeVideoFrameSurface();
if (!videoSurface) {
RefPtr<DMABufSurfaceYUV> surface =
DMABufSurfaceYUV::CreateYUVSurface(aVaDesc);
@ -119,7 +123,8 @@ RefPtr<VideoFrameSurface> VideoFramePool::GetVideoFrameSurface(
return nullptr;
}
FFMPEG_LOG("Created new VA-API DMABufSurface UID = %d", surface->GetUID());
RefPtr<VideoFrameSurface> surf = new VideoFrameSurface(surface);
RefPtr<VideoFrameSurface<LIBAV_VER>> surf =
new VideoFrameSurface<LIBAV_VER>(surface);
if (!mTextureCreationWorks) {
mTextureCreationWorks = Some(surface->VerifyTextureCreation());
}

Просмотреть файл

@ -7,17 +7,12 @@
#ifndef __FFmpegVideoFramePool_h__
#define __FFmpegVideoFramePool_h__
#include "FFmpegVideoDecoder.h"
#include "FFmpegLibWrapper.h"
#include "mozilla/layers/DMABUFSurfaceImage.h"
#include "mozilla/widget/DMABufLibWrapper.h"
#include "mozilla/widget/DMABufSurface.h"
namespace mozilla {
class VideoFramePool;
// VideoFrameSurface holds a reference to GPU data with a video frame.
//
// Actual GPU pixel data are stored at DMABufSurface and
@ -47,8 +42,19 @@ class VideoFramePool;
// 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 VideoFrameSurface {
friend class VideoFramePool;
template <int V>
class VideoFrameSurface {};
template <>
class VideoFrameSurface<LIBAV_VER>;
template <int V>
class VideoFramePool {};
template <>
class VideoFramePool<LIBAV_VER>;
template <>
class VideoFrameSurface<LIBAV_VER> {
friend class VideoFramePool<LIBAV_VER>;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoFrameSurface)
@ -97,23 +103,24 @@ class VideoFrameSurface {
};
// VideoFramePool class is thread-safe.
class VideoFramePool final {
template <>
class VideoFramePool<LIBAV_VER> {
public:
VideoFramePool();
~VideoFramePool();
RefPtr<VideoFrameSurface> GetVideoFrameSurface(
RefPtr<VideoFrameSurface<LIBAV_VER>> GetVideoFrameSurface(
VADRMPRIMESurfaceDescriptor& aVaDesc, AVCodecContext* aAVCodecContext,
AVFrame* aAVFrame, FFmpegLibWrapper* aLib);
void ReleaseUnusedVAAPIFrames();
private:
RefPtr<VideoFrameSurface> GetFreeVideoFrameSurface();
RefPtr<VideoFrameSurface<LIBAV_VER>> GetFreeVideoFrameSurface();
private:
// Protect mDMABufSurfaces pool access
Mutex mSurfaceLock MOZ_UNANNOTATED;
nsTArray<RefPtr<VideoFrameSurface>> mDMABufSurfaces;
nsTArray<RefPtr<VideoFrameSurface<LIBAV_VER>>> 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<bool> mTextureCreationWorks;

Просмотреть файл

@ -30,6 +30,9 @@ if CONFIG['MOZ_WAYLAND']:
CXXFLAGS += CONFIG['MOZ_GTK3_CFLAGS']
DEFINES['MOZ_WAYLAND_USE_VAAPI'] = 1
USE_LIBS += ['mozva']
UNIFIED_SOURCES += [
'../FFmpegVideoFramePool.cpp',
]
include("/ipc/chromium/chromium-config.mozbuild")

Просмотреть файл

@ -30,6 +30,9 @@ if CONFIG["MOZ_WAYLAND"]:
CXXFLAGS += CONFIG["MOZ_GTK3_CFLAGS"]
DEFINES["MOZ_WAYLAND_USE_VAAPI"] = 1
USE_LIBS += ["mozva"]
UNIFIED_SOURCES += [
"../FFmpegVideoFramePool.cpp",
]
include("/ipc/chromium/chromium-config.mozbuild")