Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move FFmpeg hwaccel checks to CMake, eliminate #pragma messages #645

Merged
merged 5 commits into from
Jun 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 4 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,6 @@ include(FeatureSummary)

################ 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_TESTS "Build unit tests (requires Catch2)" ON)
Expand All @@ -83,8 +80,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
Original file line number Diff line number Diff line change
Expand Up @@ -299,9 +299,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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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