Skip to content

Commit

Permalink
Move FFmpeg hwaccel checks to CMake, eliminate #pragma messages (#645)
Browse files Browse the repository at this point in the history
* Rename HAVE_HW_ACCEL to USE_HW_ACCEL
* CMake: Add USE_HW_ACCEL option, default on
* CMake: #define USE_HW_ACCEL, display as build feature
  • Loading branch information
ferdnyc committed Jun 5, 2021
1 parent 5cca6d1 commit 8a81452
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 65 deletions.
7 changes: 4 additions & 3 deletions CMakeLists.txt
Expand Up @@ -74,9 +74,6 @@ include(CTest)

################ OPTIONS ##################
# Optional build settings for libopenshot
option(USE_SYSTEM_JSONCPP "Use system installed JsonCpp, if found" ON)
option(DISABLE_BUNDLED_JSONCPP "Don't fall back to bundled JsonCpp" OFF)

option(ENABLE_IWYU "Enable 'Include What You Use' scanner (CMake 3.3+)" OFF)

option(ENABLE_PARALLEL_CTEST "Run CTest using multiple processors" ON)
Expand All @@ -86,8 +83,12 @@ option(ENABLE_COVERAGE "Scan test coverage using gcov and report" OFF)
option(ENABLE_DOCS "Build API documentation (requires Doxygen)" ON)

option(APPIMAGE_BUILD "Build to install in an AppImage (Linux only)" OFF)

option(USE_SYSTEM_JSONCPP "Use system installed JsonCpp, if found" ON)
option(DISABLE_BUNDLED_JSONCPP "Don't fall back to bundled JsonCpp" OFF)
option(ENABLE_MAGICK "Use ImageMagick, if available" ON)
option(ENABLE_OPENCV "Build with OpenCV algorithms (requires Boost, Protobuf 3)" ON)
option(USE_HW_ACCEL "Enable hardware-accelerated encoding-decoding with FFmpeg 3.4+" ON)

# Legacy commandline override
if (DISABLE_TESTS)
Expand Down
24 changes: 23 additions & 1 deletion src/CMakeLists.txt
Expand Up @@ -308,9 +308,31 @@ foreach(ff_comp IN LISTS all_comps)
mark_as_advanced(${v_name}_VERSION_STR)
endif()
endif()

endforeach()

# Version check for hardware-acceleration code
if(TARGET FFmpeg::avcodec AND USE_HW_ACCEL)
if(${avcodec_VERSION} VERSION_GREATER 57.107.100)
set(HAVE_HW_ACCEL TRUE)
endif()
endif()

# Hwaccel preprocessor define (for source #ifdefs)
if (NOT USE_HW_ACCEL)
target_compile_definitions(openshot PUBLIC USE_HW_ACCEL=0)
elseif (HAVE_HW_ACCEL)
target_compile_definitions(openshot PUBLIC USE_HW_ACCEL=1)
endif()

# Include in feature summary
if(USE_HW_ACCEL AND HAVE_HW_ACCEL)
set(FFMPEG_HARDWARE_ACCELERATION TRUE)
else()
set(FFMPEG_HARDWARE_ACCELERATION FALSE)
endif()
set(_hwaccel_help "GPU-accelerated routines (FFmpeg 3.4+)")
add_feature_info("FFmpeg hwaccel" FFMPEG_HARDWARE_ACCELERATION ${_hwaccel_help})

################### OPENMP #####################
# Check for OpenMP (used for multi-core processing)

Expand Down
46 changes: 20 additions & 26 deletions src/FFmpegReader.cpp
Expand Up @@ -39,13 +39,7 @@

#define ENABLE_VAAPI 0

#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 HAVE_HW_ACCEL
#if USE_HW_ACCEL
#define MAX_SUPPORTED_WIDTH 1950
#define MAX_SUPPORTED_HEIGHT 1100

Expand Down Expand Up @@ -76,13 +70,13 @@ typedef struct VAAPIDecodeContext {
int surface_count;
} VAAPIDecodeContext;
#endif // ENABLE_VAAPI
#endif // HAVE_HW_ACCEL
#endif // USE_HW_ACCEL


using namespace openshot;

int hw_de_on = 0;
#if HAVE_HW_ACCEL
#if USE_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 @@ -135,7 +129,7 @@ bool AudioLocation::is_near(AudioLocation location, int samples_per_frame, int64
return false;
}

#if HAVE_HW_ACCEL
#if USE_HW_ACCEL

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

void FFmpegReader::Open() {
// Open reader if not already open
Expand Down Expand Up @@ -269,7 +263,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 HAVE_HW_ACCEL
#if USE_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 @@ -286,7 +280,7 @@ void FFmpegReader::Open() {

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

// Disable per-frame threading for album arts
// Using FF_THREAD_FRAME adds one frame decoding delay per thread,
Expand All @@ -429,7 +423,7 @@ void FFmpegReader::Open() {
if (avcodec_open2(pCodecCtx, pCodec, &opts) < 0)
throw InvalidCodec("A video codec was found, but could not be opened.", path);

#if HAVE_HW_ACCEL
#if USE_HW_ACCEL
if (hw_de_on && hw_de_supported) {
AVHWFramesConstraints *constraints = NULL;
void *hwconfig = NULL;
Expand Down Expand Up @@ -496,7 +490,7 @@ void FFmpegReader::Open() {
}
#else
retry_decode_open = 0;
#endif // HAVE_HW_ACCEL
#endif // USE_HW_ACCEL
} while (retry_decode_open); // retry_decode_open
// Free options
av_dict_free(&opts);
Expand Down Expand Up @@ -582,14 +576,14 @@ void FFmpegReader::Close() {
if (info.has_video) {
avcodec_flush_buffers(pCodecCtx);
AV_FREE_CONTEXT(pCodecCtx);
#if HAVE_HW_ACCEL
#if USE_HW_ACCEL
if (hw_de_on) {
if (hw_device_ctx) {
av_buffer_unref(&hw_device_ctx);
hw_device_ctx = NULL;
}
}
#endif // HAVE_HW_ACCEL
#endif // USE_HW_ACCEL
}
if (info.has_audio) {
avcodec_flush_buffers(aCodecCtx);
Expand Down Expand Up @@ -1081,22 +1075,22 @@ bool FFmpegReader::GetAVFrame() {
frameFinished = 0;
ret = avcodec_send_packet(pCodecCtx, packet);

#if HAVE_HW_ACCEL
#if USE_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
#endif // USE_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 USE_HW_ACCEL
if (hw_de_on && hw_de_supported) {
next_frame2 = AV_ALLOCATE_FRAME();
}
else
#endif // HAVE_HW_ACCEL
#endif // USE_HW_ACCEL
{
next_frame2 = next_frame;
}
Expand All @@ -1109,7 +1103,7 @@ bool FFmpegReader::GetAVFrame() {
if (ret != 0) {
ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::GetAVFrame (invalid return frame received)");
}
#if HAVE_HW_ACCEL
#if USE_HW_ACCEL
if (hw_de_on && hw_de_supported) {
int err;
if (next_frame2->format == hw_de_av_pix_fmt) {
Expand All @@ -1123,7 +1117,7 @@ bool FFmpegReader::GetAVFrame() {
}
}
else
#endif // HAVE_HW_ACCEL
#endif // USE_HW_ACCEL
{ // No hardware acceleration used -> no copy from GPU memory needed
next_frame = next_frame2;
}
Expand All @@ -1137,11 +1131,11 @@ bool FFmpegReader::GetAVFrame() {
(AVPixelFormat)(pStream->codecpar->format), info.width, info.height);
}
}
#if HAVE_HW_ACCEL
#if USE_HW_ACCEL
if (hw_de_on && hw_de_supported) {
AV_FREE_FRAME(&next_frame2);
}
#endif // HAVE_HW_ACCEL
#endif // USE_HW_ACCEL
}
#else
avcodec_decode_video2(pCodecCtx, next_frame, &frameFinished, packet);
Expand Down
4 changes: 2 additions & 2 deletions src/FFmpegReader.h
Expand Up @@ -97,7 +97,7 @@ namespace openshot {
AVFormatContext *pFormatCtx;
int i, videoStream, audioStream;
AVCodecContext *pCodecCtx, *aCodecCtx;
#if HAVE_HW_ACCEL
#if USE_HW_ACCEL
AVBufferRef *hw_device_ctx = NULL; //PM
#endif
AVStream *pStream, *aStream;
Expand Down Expand Up @@ -147,7 +147,7 @@ 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 HAVE_HW_ACCEL
#if USE_HW_ACCEL
AVPixelFormat hw_de_av_pix_fmt = AV_PIX_FMT_NONE;
AVHWDeviceType hw_de_av_device_type = AV_HWDEVICE_TYPE_NONE;
int IsHardwareDecodeSupported(int codecid);
Expand Down
4 changes: 2 additions & 2 deletions src/FFmpegUtilities.h
Expand Up @@ -41,8 +41,8 @@
#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))
#ifndef USE_HW_ACCEL
#define USE_HW_ACCEL (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 107, 100))
#endif

// Include the FFmpeg headers
Expand Down

0 comments on commit 8a81452

Please sign in to comment.