Skip to content

Commit

Permalink
Merge pull request #437 from ferdnyc/hw-accel-ffmpeg34
Browse files Browse the repository at this point in the history
Limit HW accel support to FFmpeg 3.4+
  • Loading branch information
ferdnyc authored Feb 14, 2020
2 parents 99fda01 + 4106b99 commit fe8ea21
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 60 deletions.
35 changes: 30 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ matrix:

- name: "Coverage (Ubuntu 18.04 Bionic)"
env:
- BUILD_VERSION=coverage_ffmpeg3
- BUILD_VERSION=coverage_ffmpeg34
- CMAKE_EXTRA_ARGS="-DENABLE_COVERAGE=1"
- TEST_TARGET=coverage
os: linux
Expand Down Expand Up @@ -80,9 +80,9 @@ matrix:
- libavresample4
- libswresample3

- name: "FFmpeg 3 GCC (Ubuntu 18.04 Bionic)"
- name: "FFmpeg 3.4 GCC (Ubuntu 18.04 Bionic)"
env:
- BUILD_VERSION=ffmpeg3
- BUILD_VERSION=ffmpeg34
- CMAKE_EXTRA_ARGS=""
- TEST_TARGET=test
os: linux
Expand All @@ -97,9 +97,9 @@ matrix:
- qt5-default
- libjsoncpp-dev

- name: "FFmpeg 3 Clang (Ubuntu 18.04 Bionic)"
- name: "FFmpeg 3.4 Clang (Ubuntu 18.04 Bionic)"
env:
- BUILD_VERSION=clang_ffmpeg3
- BUILD_VERSION=clang_ffmpeg34
- CMAKE_EXTRA_ARGS=""
- TEST_TARGET=test
os: linux
Expand All @@ -115,6 +115,31 @@ matrix:
- qt5-default
- libomp-dev

- name: "FFmpeg 3.2 GCC (Ubuntu 16.04 Xenial)"
env:
- BUILD_VERSION=ffmpeg32
- CMAKE_EXTRA_ARGS=""
- TEST_TARGET="os_test"
os: linux
dist: xenial
addons:
apt:
sources:
- sourceline: 'ppa:openshot.developers/libopenshot-daily'
- sourceline: 'ppa:beineri/opt-qt-5.10.0-xenial'
- sourceline: 'ppa:jon-hedgerows/ffmpeg-backports'
packages:
- *ff_common
- libavcodec57
- libavdevice57
- libavfilter6
- libavformat57
- libavresample3
- libavutil55
- libpostproc54
- libswresample2
- libswscale4

- name: "FFmpeg 2 GCC (Ubuntu 16.04 Xenial)"
env:
- BUILD_VERSION=ffmpeg2
Expand Down
2 changes: 1 addition & 1 deletion doc/HW-ACCEL.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ The following table summarizes our current level of support:

## Supported FFmpeg Versions

* HW accel is supported from FFmpeg version 3.2 (3.3 for nVidia drivers)
* HW accel is supported from FFmpeg version 3.4
* HW accel was removed for nVidia drivers in Ubuntu for FFmpeg 4+

**Notice:** The FFmpeg versions of Ubuntu and PPAs for Ubuntu show the
Expand Down
7 changes: 3 additions & 4 deletions include/FFmpegReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ namespace openshot {
AVFormatContext *pFormatCtx;
int i, videoStream, audioStream;
AVCodecContext *pCodecCtx, *aCodecCtx;
#if (LIBAVFORMAT_VERSION_MAJOR >= 57)
#if HAVE_HW_ACCEL
AVBufferRef *hw_device_ctx = NULL; //PM
#endif
AVStream *pStream, *aStream;
Expand Down Expand Up @@ -147,12 +147,11 @@ namespace openshot {
int64_t current_video_frame; // can't reliably use PTS of video to determine this

int hw_de_supported = 0; // Is set by FFmpegReader
#if IS_FFMPEG_3_2
#if HAVE_HW_ACCEL
AVPixelFormat hw_de_av_pix_fmt = AV_PIX_FMT_NONE;
AVHWDeviceType hw_de_av_device_type = AV_HWDEVICE_TYPE_NONE;
#endif

int IsHardwareDecodeSupported(int codecid);
#endif

/// Check for the correct frames per second value by scanning the 1st few seconds of video packets.
void CheckFPS();
Expand Down
4 changes: 4 additions & 0 deletions include/FFmpegUtilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
#ifndef IS_FFMPEG_3_2
#define IS_FFMPEG_3_2 (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 64, 101))
#endif

#ifndef HAVE_HW_ACCEL
#define HAVE_HW_ACCEL (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 107, 100))
#endif

// Include the FFmpeg headers
extern "C" {
Expand Down
41 changes: 24 additions & 17 deletions src/FFmpegReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@

#define ENABLE_VAAPI 0

#if IS_FFMPEG_3_2
#if HAVE_HW_ACCEL
#pragma message "You are compiling with experimental hardware decode"
#else
#pragma message "You are compiling only with software decode"
#endif

#if IS_FFMPEG_3_2
#if HAVE_HW_ACCEL
#define MAX_SUPPORTED_WIDTH 1950
#define MAX_SUPPORTED_HEIGHT 1100

Expand Down Expand Up @@ -71,14 +71,14 @@ typedef struct VAAPIDecodeContext {
enum AVPixelFormat surface_format;
int surface_count;
} VAAPIDecodeContext;
#endif
#endif
#endif // ENABLE_VAAPI
#endif // HAVE_HW_ACCEL


using namespace openshot;

int hw_de_on = 0;
#if IS_FFMPEG_3_2
#if HAVE_HW_ACCEL
AVPixelFormat hw_de_av_pix_fmt_global = AV_PIX_FMT_NONE;
AVHWDeviceType hw_de_av_device_type_global = AV_HWDEVICE_TYPE_NONE;
#endif
Expand Down Expand Up @@ -153,7 +153,7 @@ bool AudioLocation::is_near(AudioLocation location, int samples_per_frame, int64
return false;
}

#if IS_FFMPEG_3_2
#if HAVE_HW_ACCEL

// Get hardware pix format
static enum AVPixelFormat get_hw_dec_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_fmts)
Expand Down Expand Up @@ -234,7 +234,7 @@ int FFmpegReader::IsHardwareDecodeSupported(int codecid)
}
return ret;
}
#endif
#endif // HAVE_HW_ACCEL

void FFmpegReader::Open() {
// Open reader if not already open
Expand Down Expand Up @@ -287,7 +287,7 @@ void FFmpegReader::Open() {
// If hw accel is selected but hardware cannot handle repeat with software decoding
do {
pCodecCtx = AV_GET_CODEC_CONTEXT(pStream, pCodec);
#if IS_FFMPEG_3_2
#if HAVE_HW_ACCEL
if (hw_de_on && (retry_decode_open==2)) {
// Up to here no decision is made if hardware or software decode
hw_de_supported = IsHardwareDecodeSupported(pCodecCtx->codec_id);
Expand All @@ -304,7 +304,7 @@ void FFmpegReader::Open() {

// Init options
av_dict_set(&opts, "strict", "experimental", 0);
#if IS_FFMPEG_3_2
#if HAVE_HW_ACCEL
if (hw_de_on && hw_de_supported) {
// Open Hardware Acceleration
int i_decoder_hw = 0;
Expand Down Expand Up @@ -433,13 +433,13 @@ void FFmpegReader::Open() {
throw InvalidCodec("Hardware device create failed.", path);
}
}
#endif
#endif // HAVE_HW_ACCEL

// Open video codec
if (avcodec_open2(pCodecCtx, pCodec, &opts) < 0)
throw InvalidCodec("A video codec was found, but could not be opened.", path);

#if IS_FFMPEG_3_2
#if HAVE_HW_ACCEL
if (hw_de_on && hw_de_supported) {
AVHWFramesConstraints *constraints = NULL;
void *hwconfig = NULL;
Expand All @@ -449,7 +449,7 @@ void FFmpegReader::Open() {
#if ENABLE_VAAPI
((AVVAAPIHWConfig *)hwconfig)->config_id = ((VAAPIDecodeContext *)(pCodecCtx->priv_data))->va_config;
constraints = av_hwdevice_get_hwframe_constraints(hw_device_ctx,hwconfig);
#endif
#endif // ENABLE_VAAPI
if (constraints) {
if (pCodecCtx->coded_width < constraints->min_width ||
pCodecCtx->coded_height < constraints->min_height ||
Expand Down Expand Up @@ -506,7 +506,7 @@ void FFmpegReader::Open() {
}
#else
retry_decode_open = 0;
#endif
#endif // HAVE_HW_ACCEL
} while (retry_decode_open); // retry_decode_open
// Free options
av_dict_free(&opts);
Expand Down Expand Up @@ -592,14 +592,14 @@ void FFmpegReader::Close() {
if (info.has_video) {
avcodec_flush_buffers(pCodecCtx);
AV_FREE_CONTEXT(pCodecCtx);
#if IS_FFMPEG_3_2
#if HAVE_HW_ACCEL
if (hw_de_on) {
if (hw_device_ctx) {
av_buffer_unref(&hw_device_ctx);
hw_device_ctx = NULL;
}
}
#endif
#endif // HAVE_HW_ACCEL
}
if (info.has_audio) {
avcodec_flush_buffers(aCodecCtx);
Expand Down Expand Up @@ -1100,19 +1100,22 @@ bool FFmpegReader::GetAVFrame() {

ret = avcodec_send_packet(pCodecCtx, packet);

#if HAVE_HW_ACCEL
// Get the format from the variables set in get_hw_dec_format
hw_de_av_pix_fmt = hw_de_av_pix_fmt_global;
hw_de_av_device_type = hw_de_av_device_type_global;

#endif // HAVE_HW_ACCEL
if (ret < 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (Packet not sent)");
}
else {
AVFrame *next_frame2;
#if HAVE_HW_ACCEL
if (hw_de_on && hw_de_supported) {
next_frame2 = AV_ALLOCATE_FRAME();
}
else
#endif // HAVE_HW_ACCEL
{
next_frame2 = next_frame;
}
Expand All @@ -1125,6 +1128,7 @@ bool FFmpegReader::GetAVFrame() {
if (ret != 0) {
ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (invalid return frame received)");
}
#if HAVE_HW_ACCEL
if (hw_de_on && hw_de_supported) {
int err;
if (next_frame2->format == hw_de_av_pix_fmt) {
Expand All @@ -1138,6 +1142,7 @@ bool FFmpegReader::GetAVFrame() {
}
}
else
#endif // HAVE_HW_ACCEL
{ // No hardware acceleration used -> no copy from GPU memory needed
next_frame = next_frame2;
}
Expand All @@ -1151,9 +1156,11 @@ bool FFmpegReader::GetAVFrame() {
(AVPixelFormat)(pStream->codecpar->format), info.width, info.height);
}
}
#if HAVE_HW_ACCEL
if (hw_de_on && hw_de_supported) {
AV_FREE_FRAME(&next_frame2);
}
#endif // HAVE_HW_ACCEL
}
#else
avcodec_decode_video2(pCodecCtx, next_frame, &frameFinished, packet);
Expand All @@ -1169,7 +1176,7 @@ bool FFmpegReader::GetAVFrame() {
av_picture_copy((AVPicture *) pFrame, (AVPicture *) next_frame, pCodecCtx->pix_fmt, info.width,
info.height);
}
#endif
#endif // IS_FFMPEG_3_2
}

// deallocate the frame
Expand Down
Loading

0 comments on commit fe8ea21

Please sign in to comment.