mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-12 22:09:25 +08:00
video: add vdpau acceleration support
Adds the VDPAU acceleration for GNU/Linux systems and enable it by devault. Can be disabled using ./configure --disable-vdpau Support for H.264, H.263 and MPEG4, as long as the hardware supports them. Requires libvdpau and ffmpeg 3.3 (contrib bump included by this patch) [guillaume roguez: re-word ci msg to be more explicit] Change-Id: I7479f4d7e3d51caf702be8c85284a4fca01605b3 Reviewed-by: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
This commit is contained in:

committed by
Guillaume Roguez

parent
f62dccacb3
commit
45faaa25d6
19
configure.ac
19
configure.ac
@ -442,7 +442,8 @@ dnl Ring video acceleration compile-time dependencies
|
||||
AS_IF([test "${SYS}" = linux && test -z "${HAVE_ANDROID_FALSE}"], [
|
||||
x11_available="no"
|
||||
vaapi_available="no"
|
||||
dnl ffmpeg's vaapi implementation depends on x11
|
||||
vdpau_available="no"
|
||||
dnl ffmpeg's vaapi and vdpau implementations depend on x11
|
||||
PKG_CHECK_MODULES([X11], [x11], [x11_available="yes"], [])
|
||||
AS_IF([test "${x11_available}" = "yes"], [
|
||||
PKG_CHECK_MODULES([LIBVA], [libva], [
|
||||
@ -454,13 +455,18 @@ AS_IF([test "${SYS}" = linux && test -z "${HAVE_ANDROID_FALSE}"], [
|
||||
])
|
||||
AC_CHECK_HEADERS([libavcodec/vaapi.h], [vaapi_available="yes"])
|
||||
], [vaapi_available=no])
|
||||
PKG_CHECK_MODULES([VDPAU], [vdpau], [
|
||||
AC_CHECK_HEADERS([libavcodec/vdpau.h], [
|
||||
AC_DEFINE([HAVE_VDPAU_ACCEL], [1], [Vdpau found])
|
||||
vdpau_available="yes"
|
||||
])
|
||||
], [vdpau_available="no"])
|
||||
])
|
||||
])
|
||||
|
||||
AC_ARG_ENABLE([accel], AS_HELP_STRING([--disable-accel], [Disable all hardware accelerations]))
|
||||
AC_ARG_ENABLE([vdpau], AS_HELP_STRING([--disable-vdpau], [Disable VDPAU hardware acceleration]))
|
||||
AC_ARG_ENABLE([vaapi], AS_HELP_STRING([--disable-vaapi], [Disable VAAPI hardware acceleration]))
|
||||
|
||||
dnl video acceleration only works if there's video
|
||||
AS_IF([test "x$enable_video" != "xno" -a "x$enable_accel" != "xno"], [
|
||||
ring_accel="yes"
|
||||
AC_DEFINE([RING_ACCEL], [1], [Hardware acceleration is enabled in Ring])
|
||||
@ -470,9 +476,16 @@ AS_IF([test "x$enable_video" != "xno" -a "x$enable_accel" != "xno"], [
|
||||
AC_DEFINE([RING_VAAPI], [1], [VAAPI is available in Ring])
|
||||
])
|
||||
])
|
||||
AS_IF([test "x$enable_vdpau" != "xno"], [
|
||||
AS_IF([test "x${vdpau_available}" = "xyes"], [
|
||||
ring_vdpau="yes"
|
||||
AC_DEFINE([RING_VDPAU], [1], [VDPAU is available in Ring])
|
||||
])
|
||||
])
|
||||
])
|
||||
AM_CONDITIONAL([RING_ACCEL], [test "x${ring_accel}" = "xyes"])
|
||||
AM_CONDITIONAL([RING_VAAPI], [test "x${ring_vaapi}" = "xyes"])
|
||||
AM_CONDITIONAL([RING_VDPAU], [test "x${ring_vdpau}" = "xyes"])
|
||||
|
||||
dnl check for GnuTLS
|
||||
PKG_CHECK_MODULES([GNUTLS], [gnutls >= 3.4.14], [HAVE_GNUTLS=1], [HAVE_GNUTLS=0])
|
||||
|
@ -1,9 +1,9 @@
|
||||
--- a/configure 2016-08-17 10:38:51.000000000 -0400
|
||||
+++ b/configure 2016-08-17 10:38:53.000000000 -0400
|
||||
@@ -5293,7 +5293,7 @@
|
||||
--- a/configure 2017-05-17 11:54:39.000000000 -0500
|
||||
+++ b/configure 2017-05-17 11:55:14.000000000 -0500
|
||||
@@ -5549,7 +5549,7 @@
|
||||
|
||||
check_func access
|
||||
check_func arc4random
|
||||
check_func_headers stdlib.h arc4random
|
||||
-check_func_headers time.h clock_gettime || { check_func_headers time.h clock_gettime -lrt && add_extralibs -lrt && LIBRT="-lrt"; }
|
||||
+#check_func_headers time.h clock_gettime || { check_func_headers time.h clock_gettime -lrt && add_extralibs -lrt && LIBRT="-lrt"; }
|
||||
check_func fcntl
|
||||
|
@ -1,4 +1,4 @@
|
||||
FFMPEG_HASH := c46d22a4a58467bdc7885685b06a2114dd181c43
|
||||
FFMPEG_HASH := f7e9275f83ec116fc859367d61998eae8af438fc
|
||||
FFMPEG_URL := https://git.ffmpeg.org/gitweb/ffmpeg.git/snapshot/$(FFMPEG_HASH).tar.gz
|
||||
|
||||
ifdef HAVE_WIN32
|
||||
@ -93,13 +93,17 @@ FFMPEGCONF += \
|
||||
endif
|
||||
|
||||
ifdef HAVE_LINUX
|
||||
ifndef HAVE_ANDROID
|
||||
FFMPEGCONF += \
|
||||
--disable-vdpau \
|
||||
--enable-vdpau \
|
||||
--enable-hwaccel=h264_vdpau \
|
||||
--enable-hwaccel=mpeg4_vdpau \
|
||||
--enable-vaapi \
|
||||
--enable-hwaccel=h264_vaapi \
|
||||
--enable-hwaccel=mpeg4_vaapi \
|
||||
--enable-hwaccel=h263_vaapi
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef HAVE_MACOSX
|
||||
FFMPEGCONF += \
|
||||
@ -173,7 +177,7 @@ FFMPEGCONF += --target-os=mingw32 --enable-memalign-hack
|
||||
FFMPEGCONF += --enable-w32threads --disable-decoder=dca
|
||||
endif
|
||||
|
||||
ifeq ($(call need_pkg,"libavcodec >= 57.48.101 libavformat >= 57.41.100 libswscale >= 4.1.100 libavdevice >= 57.0.101 libavutil >= 55.28.100"),)
|
||||
ifeq ($(call need_pkg,"libavcodec >= 57.89.100 libavformat >= 57.71.100 libswscale >= 4.6.100 libavdevice >= 57.6.100 libavutil >= 55.58.100"),)
|
||||
PKGS_FOUND += ffmpeg
|
||||
endif
|
||||
|
||||
@ -189,7 +193,6 @@ ffmpeg: ffmpeg-$(FFMPEG_HASH).tar.xz .sum-ffmpeg
|
||||
mkdir -p $@-$(FFMPEG_HASH)
|
||||
(cd $@-$(FFMPEG_HASH) && tar x $(if ${BATCH_MODE},,-v) --strip-components=1 -f ../$<)
|
||||
$(UPDATE_AUTOCONFIG)
|
||||
$(APPLY) $(SRC)/ffmpeg/0004-avformat-fix-find_stream_info-not-considering-extradata.patch
|
||||
ifdef HAVE_IOS
|
||||
$(APPLY) $(SRC)/ffmpeg/clock_gettime.patch
|
||||
endif
|
||||
|
@ -27,6 +27,10 @@
|
||||
#include "v4l2/vaapi.h"
|
||||
#endif
|
||||
|
||||
#ifdef RING_VDPAU
|
||||
#include "v4l2/vdpau.h"
|
||||
#endif
|
||||
|
||||
#include "string_utils.h"
|
||||
#include "logger.h"
|
||||
|
||||
@ -150,6 +154,7 @@ std::unique_ptr<HardwareAccel>
|
||||
makeHardwareAccel(AVCodecContext* codecCtx)
|
||||
{
|
||||
enum class AccelID {
|
||||
Vdpau,
|
||||
Vaapi,
|
||||
};
|
||||
|
||||
@ -174,8 +179,11 @@ makeHardwareAccel(AVCodecContext* codecCtx)
|
||||
* in this array.
|
||||
*/
|
||||
const AccelInfo accels[] = {
|
||||
#if RING_VAAPI
|
||||
#ifdef RING_VAAPI
|
||||
{ AccelID::Vaapi, "vaapi", AV_PIX_FMT_VAAPI, makeHardwareAccel<VaapiAccel> },
|
||||
#endif
|
||||
#ifdef RING_VDPAU
|
||||
{ AccelID::Vdpau, "vdpau", AV_PIX_FMT_VDPAU, makeHardwareAccel<VdpauAccel> },
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -184,6 +192,7 @@ makeHardwareAccel(AVCodecContext* codecCtx)
|
||||
case AV_CODEC_ID_H264:
|
||||
case AV_CODEC_ID_MPEG4:
|
||||
case AV_CODEC_ID_H263P:
|
||||
possibleAccels.push_back(AccelID::Vdpau);
|
||||
possibleAccels.push_back(AccelID::Vaapi);
|
||||
break;
|
||||
case AV_CODEC_ID_VP8:
|
||||
|
@ -6,12 +6,16 @@ libv4l2_la_SOURCES = \
|
||||
video_device_impl.cpp \
|
||||
video_device_monitor_impl.cpp
|
||||
|
||||
if RING_VDPAU
|
||||
libv4l2_la_SOURCES += vdpau.h vdpau.cpp
|
||||
endif
|
||||
|
||||
if RING_VAAPI
|
||||
libv4l2_la_SOURCES += vaapi.h vaapi.cpp
|
||||
endif
|
||||
|
||||
AM_CXXFLAGS = @LIBAVCODEC_CFLAGS@ @LIBAVFORMAT_CFLAGS@ @LIBAVDEVICE_CFLAGS@ @LIBSWSCALE_CFLAGS@
|
||||
AM_CXXFLAGS += @UDEV_CFLAGS@ @LIBVA_CFLAGS@ @LIBVA_DRM_CFLAGS@ @LIBVA_X11_CFLAGS@
|
||||
AM_CXXFLAGS += @UDEV_CFLAGS@ @VDPAU_CFLAGS@ @LIBVA_CFLAGS@ @LIBVA_DRM_CFLAGS@ @LIBVA_X11_CFLAGS@
|
||||
|
||||
libv4l2_la_LIBADD = @LIBAVCODEC_LIBS@ @LIBAVFORMAT_LIBS@ @LIBAVDEVICE_LIBS@ @LIBSWSCALE_LIBS@ @LIBAVUTIL_LIBS@
|
||||
libv4l2_la_LIBADD += @UDEV_LIBS@ @X11_LIBS@ @LIBVA_LIBS@ @LIBVA_DRM_LIBS@ @LIBVA_X11_LIBS@
|
||||
libv4l2_la_LIBADD += @UDEV_LIBS@ @X11_LIBS@ @VDPAU_LIBS@ @LIBVA_LIBS@ @LIBVA_DRM_LIBS@ @LIBVA_X11_LIBS@
|
||||
|
119
src/media/video/v4l2/vdpau.cpp
Normal file
119
src/media/video/v4l2/vdpau.cpp
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "libav_deps.h" // MUST BE INCLUDED FIRST
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef RING_VDPAU
|
||||
|
||||
#include "video/v4l2/vdpau.h"
|
||||
#include "video/accel.h"
|
||||
|
||||
#include "fileutils.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
namespace ring { namespace video {
|
||||
|
||||
static auto avBufferRefDeleter = [](AVBufferRef* buf){ av_buffer_unref(&buf); };
|
||||
|
||||
VdpauAccel::VdpauAccel(const std::string name, const AVPixelFormat format)
|
||||
: HardwareAccel(name, format)
|
||||
, deviceBufferRef_(nullptr, avBufferRefDeleter)
|
||||
, framesBufferRef_(nullptr, avBufferRefDeleter)
|
||||
{
|
||||
}
|
||||
|
||||
VdpauAccel::~VdpauAccel()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
VdpauAccel::allocateBuffer(AVFrame* frame, int flags)
|
||||
{
|
||||
return av_hwframe_get_buffer(framesBufferRef_.get(), frame, 0);
|
||||
}
|
||||
|
||||
void
|
||||
VdpauAccel::extractData(VideoFrame& input, VideoFrame& output)
|
||||
{
|
||||
auto inFrame = input.pointer();
|
||||
auto outFrame = output.pointer();
|
||||
|
||||
if (av_hwframe_transfer_data(outFrame, inFrame, 0) < 0) {
|
||||
throw std::runtime_error("Unable to extract data from VDPAU frame");
|
||||
}
|
||||
|
||||
if (av_frame_copy_props(outFrame, inFrame) < 0 ) {
|
||||
av_frame_unref(outFrame);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
VdpauAccel::check()
|
||||
{
|
||||
AVBufferRef* hardwareDeviceCtx;
|
||||
if (av_hwdevice_ctx_create(&hardwareDeviceCtx, AV_HWDEVICE_TYPE_VDPAU, nullptr, nullptr, 0) == 0) {
|
||||
deviceBufferRef_.reset(hardwareDeviceCtx);
|
||||
return true;
|
||||
}
|
||||
|
||||
av_buffer_unref(&hardwareDeviceCtx);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
VdpauAccel::init()
|
||||
{
|
||||
auto device = reinterpret_cast<AVHWDeviceContext*>(deviceBufferRef_->data);
|
||||
auto hardwareContext = static_cast<AVVDPAUDeviceContext*>(device->hwctx);
|
||||
|
||||
framesBufferRef_.reset(av_hwframe_ctx_alloc(deviceBufferRef_.get()));
|
||||
auto frames = reinterpret_cast<AVHWFramesContext*>(framesBufferRef_->data);
|
||||
frames->format = AV_PIX_FMT_VDPAU;
|
||||
frames->sw_format = AV_PIX_FMT_YUV420P;
|
||||
frames->width = width_;
|
||||
frames->height = height_;
|
||||
|
||||
if (av_hwframe_ctx_init(framesBufferRef_.get()) < 0) {
|
||||
RING_ERR("Failed to initialize VDPAU frame context");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (av_vdpau_bind_context(codecCtx_, hardwareContext->device, hardwareContext->get_proc_address, 0)) {
|
||||
RING_ERR("Could not bind VDPAU context");
|
||||
return false;
|
||||
}
|
||||
|
||||
RING_DBG("VDPAU decoder initialized");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}} // namespace ring::video
|
||||
|
||||
#endif // RING_VDPAU
|
64
src/media/video/v4l2/vdpau.h
Normal file
64
src/media/video/v4l2/vdpau.h
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Philippe Gorley <philippe.gorley@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "libav_deps.h" // MUST BE INCLUDED FIRST
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef RING_VDPAU
|
||||
|
||||
extern "C" {
|
||||
#include <stdint.h>
|
||||
|
||||
#include <libavcodec/vdpau.h>
|
||||
#include <libavutil/buffer.h>
|
||||
#include <libavutil/frame.h>
|
||||
#include <libavutil/hwcontext.h>
|
||||
#include <libavutil/hwcontext_vdpau.h>
|
||||
}
|
||||
|
||||
#include "video/accel.h"
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
namespace ring { namespace video {
|
||||
|
||||
class VdpauAccel : public HardwareAccel {
|
||||
public:
|
||||
VdpauAccel(const std::string name, const AVPixelFormat format);
|
||||
~VdpauAccel();
|
||||
|
||||
bool check() override;
|
||||
bool init() override;
|
||||
int allocateBuffer(AVFrame* frame, int flags) override;
|
||||
void extractData(VideoFrame& input, VideoFrame& output) override;
|
||||
|
||||
private:
|
||||
using AVBufferRefPtr = std::unique_ptr<AVBufferRef, std::function<void(AVBufferRef*)>>;
|
||||
AVBufferRefPtr deviceBufferRef_;
|
||||
AVBufferRefPtr framesBufferRef_;
|
||||
};
|
||||
|
||||
}} // namespace ring::video
|
||||
|
||||
#endif // RING_VDPAU
|
Reference in New Issue
Block a user