From 4db2217f0d94dfce07359d6e526efe34389c87af Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Tue, 11 Sep 2018 20:18:11 -0700 Subject: [PATCH] Fallback for hardware accelerated decode to software decode in case the GPU can noy handle the dimensions of the frame. Not yet working, va_config not yet set. --- src/FFmpegReader.cpp | 131 ++++++++++++++++++++++++++++--------------- src/FFmpegWriter.cpp | 6 -- 2 files changed, 86 insertions(+), 51 deletions(-) diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 4dabce7e..caa33de1 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -29,6 +29,7 @@ */ #include "../include/FFmpegReader.h" +#include "libavutil/hwcontext_vaapi.h" using namespace openshot; @@ -111,7 +112,6 @@ bool AudioLocation::is_near(AudioLocation location, int samples_per_frame, int64 } #if IS_FFMPEG_3_2 -#pragma message "You are compiling with experimental hardware decode" static enum AVPixelFormat get_hw_dec_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_fmts) { @@ -226,55 +226,96 @@ void FFmpegReader::Open() // Get codec and codec context from stream AVCodec *pCodec = avcodec_find_decoder(codecId); - pCodecCtx = AV_GET_CODEC_CONTEXT(pStream, pCodec); - #if IS_FFMPEG_3_2 - if (hw_de_on) { - hw_de_supported = is_hardware_decode_supported(pCodecCtx->codec_id); - } - #endif - // Set number of threads equal to number of processors (not to exceed 16) - pCodecCtx->thread_count = min(FF_NUM_PROCESSORS, 16); - - if (pCodec == NULL) { - throw InvalidCodec("A valid video codec could not be found for this file.", path); - } - - // Init options AVDictionary *opts = NULL; - av_dict_set(&opts, "strict", "experimental", 0); + int retry_decode_open = 2; + // If hw accel is selected but hardware connot handle repeat with software decoding + do { + pCodecCtx = AV_GET_CODEC_CONTEXT(pStream, pCodec); + #if IS_FFMPEG_3_2 + if (hw_de_on && (retry_decode_open==2)) { + // Up to here no decision is made if hardware or software decode + hw_de_supported = is_hardware_decode_supported(pCodecCtx->codec_id); + } + #endif + retry_decode_open = 0; + // Set number of threads equal to number of processors (not to exceed 16) + pCodecCtx->thread_count = min(FF_NUM_PROCESSORS, 16); - #if IS_FFMPEG_3_2 - if (hw_de_on && hw_de_supported) { - // Open Hardware Acceleration - // Use the hw device given in the environment variable HW_DE_DEVICE_SET or the default if not set - char *dev_hw = NULL; - dev_hw = getenv( "HW_DE_DEVICE_SET" ); - // Check if it is there and writable - if( dev_hw != NULL && access( dev_hw, W_OK ) == -1 ) { - dev_hw = NULL; // use default - } - hw_device_ctx = NULL; - pCodecCtx->get_format = get_hw_dec_format; - if (av_hwdevice_ctx_create(&hw_device_ctx, hw_de_av_device_type, dev_hw, NULL, 0) >= 0) { - if (!(pCodecCtx->hw_device_ctx = av_buffer_ref(hw_device_ctx))) { - throw InvalidCodec("Hardware device reference create failed.", path); + if (pCodec == NULL) { + throw InvalidCodec("A valid video codec could not be found for this file.", path); + } + + // Init options + av_dict_set(&opts, "strict", "experimental", 0); + #if IS_FFMPEG_3_2 + if (hw_de_on && hw_de_supported) { + // Open Hardware Acceleration + // Use the hw device given in the environment variable HW_DE_DEVICE_SET or the default if not set + char *dev_hw = NULL; + dev_hw = getenv( "HW_DE_DEVICE_SET" ); + // Check if it is there and writable + if( dev_hw != NULL && access( dev_hw, W_OK ) == -1 ) { + dev_hw = NULL; // use default + } + hw_device_ctx = NULL; + // Here the first hardware initialisations are made + pCodecCtx->get_format = get_hw_dec_format; + if (av_hwdevice_ctx_create(&hw_device_ctx, hw_de_av_device_type, dev_hw, NULL, 0) >= 0) { + if (!(pCodecCtx->hw_device_ctx = av_buffer_ref(hw_device_ctx))) { + throw InvalidCodec("Hardware device reference create failed.", path); + } + } + else { + throw InvalidCodec("Hardware device create failed.", path); } } - else { - throw InvalidCodec("Hardware device create failed.", path); - } - } -/* // Check to see if the hardware supports that file (size!) - AVHWFramesConstraints *constraints = NULL; - constraints = av_hwdevice_get_hwframe_constraints(hw_device_ctx->device_ref,hwconfig); - if (constraints) - av_hwframe_constraints_free(&constraints); -*/ - #endif - // Open video codec - if (avcodec_open2(pCodecCtx, pCodec, &opts) < 0) - throw InvalidCodec("A video codec was found, but could not be opened.", path); + #endif + // 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 (hw_de_on && hw_de_supported) { + AVHWFramesConstraints *constraints = NULL; + // NOT WORKING needs hwconfig config_id !!!!!!!!!!!!!!!!!!!!!!!!!!! + //AVVAAPIHWConfig *hwconfig = NULL; + // void *hwconfig = NULL; + // hwconfig = av_hwdevice_hwconfig_alloc(hw_device_ctx); + //hwconfig->config_id = ((VAAPIDecodeContext *)pCodecCtx->priv_data)->va_config; + // constraints = av_hwdevice_get_hwframe_constraints(hw_device_ctx,(void*)hwconfig); + constraints = av_hwdevice_get_hwframe_constraints(hw_device_ctx,NULL); // No usable information! + if (constraints) { +// constraints->max_height = 1100; // Just for testing +// constraints->max_width = 1950; // Just for testing + if (pCodecCtx->coded_width < constraints->min_width || + pCodecCtx->coded_height < constraints->min_height || + pCodecCtx->coded_width > constraints->max_width || + pCodecCtx->coded_height > constraints->max_height) { + cerr << "DIMENSIONS ARE TOO LARGE for hardware acceleration\n"; + hw_de_supported = 0; + retry_decode_open = 1; + AV_FREE_CONTEXT(pCodecCtx); + if (hw_device_ctx) { + av_buffer_unref(&hw_device_ctx); + hw_device_ctx = NULL; + } + } + else { + // All is just peachy + cerr << "MinWidth : " << constraints->min_width << "MinHeight : " << constraints->min_height << "MaxWidth : " << constraints->max_width << "MaxHeight : " << constraints->max_height << "\n"; + cerr << "Frame width :" << pCodecCtx->coded_width << "Frame height :" << pCodecCtx->coded_height << "\n"; + retry_decode_open = 0; + } + av_hwframe_constraints_free(&constraints); + } + else { + cerr << "Constraints could not be found\n"; + } + } // if hw_de_on && hw_de_supported + #else + retry_decode_open = 0; + #endif + } while (retry_decode_open); // retry_decode_open // Free options av_dict_free(&opts); diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 924f3490..c16ce7a8 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -71,12 +71,6 @@ static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int6 } #endif -#if IS_FFMPEG_3_2 -//#if defined(__linux__) -#pragma message "You are compiling with experimental hardware encode" -//#endif -#endif - FFmpegWriter::FFmpegWriter(string path) : path(path), fmt(NULL), oc(NULL), audio_st(NULL), video_st(NULL), audio_pts(0), video_pts(0), samples(NULL), audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0),