summaryrefslogtreecommitdiffstats
path: root/libraries/libopenshot/limit-hwaccel.patch
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/libopenshot/limit-hwaccel.patch')
-rw-r--r--libraries/libopenshot/limit-hwaccel.patch480
1 files changed, 480 insertions, 0 deletions
diff --git a/libraries/libopenshot/limit-hwaccel.patch b/libraries/libopenshot/limit-hwaccel.patch
new file mode 100644
index 0000000000..db6724228b
--- /dev/null
+++ b/libraries/libopenshot/limit-hwaccel.patch
@@ -0,0 +1,480 @@
+From e74d71f5451c6f2be9c546d61fac412f2d55f851 Mon Sep 17 00:00:00 2001
+From: "FeRD (Frank Dana)" <ferdnyc@gmail.com>
+Date: Mon, 10 Feb 2020 01:50:31 -0500
+Subject: [PATCH] FFmpegReader/Writer: limit hwaccel to FFmpeg 3.4+
+
+Add a new #define HAVE_HW_ACCEL, which is only set on FFmpeg 3.4+,
+and use that to restrict the use of hw-accel features, leaving
+IS_FFMPEG_3_2 to determine only whether code is compatible with
+FFmpeg 3.2+.
+---
+ include/FFmpegReader.h | 7 ++--
+ include/FFmpegUtilities.h | 4 +++
+ src/FFmpegReader.cpp | 41 +++++++++++++----------
+ src/FFmpegWriter.cpp | 70 +++++++++++++++++++++------------------
+ 4 files changed, 68 insertions(+), 54 deletions(-)
+
+diff --git a/include/FFmpegReader.h b/include/FFmpegReader.h
+index 9faa86a3..cc782cd5 100644
+--- a/include/FFmpegReader.h
++++ b/include/FFmpegReader.h
+@@ -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;
+@@ -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();
+diff --git a/include/FFmpegUtilities.h b/include/FFmpegUtilities.h
+index c673305e..62d64df1 100644
+--- a/include/FFmpegUtilities.h
++++ b/include/FFmpegUtilities.h
+@@ -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" {
+diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp
+index 9234ecfe..b548fa8f 100644
+--- a/src/FFmpegReader.cpp
++++ b/src/FFmpegReader.cpp
+@@ -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
+
+@@ -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
+@@ -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)
+@@ -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
+@@ -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);
+@@ -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;
+@@ -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;
+@@ -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 ||
+@@ -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);
+@@ -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);
+@@ -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;
+ }
+@@ -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) {
+@@ -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;
+ }
+@@ -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);
+@@ -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
+diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp
+index 245bd9bd..8d060d77 100644
+--- a/src/FFmpegWriter.cpp
++++ b/src/FFmpegWriter.cpp
+@@ -35,7 +35,7 @@
+
+ using namespace openshot;
+
+-#if IS_FFMPEG_3_2
++#if HAVE_HW_ACCEL
+ #pragma message "You are compiling with experimental hardware encode"
+ #else
+ #pragma message "You are compiling only with software encode"
+@@ -44,7 +44,7 @@ using namespace openshot;
+ // Multiplexer parameters temporary storage
+ AVDictionary *mux_dict = NULL;
+
+-#if IS_FFMPEG_3_2
++#if HAVE_HW_ACCEL
+ int hw_en_on = 1; // Is set in UI
+ int hw_en_supported = 0; // Is set by FFmpegWriter
+ AVPixelFormat hw_en_av_pix_fmt = AV_PIX_FMT_NONE;
+@@ -81,7 +81,7 @@ static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int6
+ av_buffer_unref(&hw_frames_ref);
+ return err;
+ }
+-#endif
++#endif // HAVE_HW_ACCEL
+
+ FFmpegWriter::FFmpegWriter(std::string path) :
+ path(path), fmt(NULL), oc(NULL), audio_st(NULL), video_st(NULL), audio_pts(0), video_pts(0), samples(NULL),
+@@ -171,7 +171,7 @@ void FFmpegWriter::SetVideoOptions(bool has_video, std::string codec, Fraction f
+ if (codec.length() > 0) {
+ AVCodec *new_codec;
+ // Check if the codec selected is a hardware accelerated codec
+-#if IS_FFMPEG_3_2
++#if HAVE_HW_ACCEL
+ #if defined(__linux__)
+ if (strstr(codec.c_str(), "_vaapi") != NULL) {
+ new_codec = avcodec_find_encoder_by_name(codec.c_str());
+@@ -225,7 +225,7 @@ void FFmpegWriter::SetVideoOptions(bool has_video, std::string codec, Fraction f
+ #endif //__linux__
+ #else // not ffmpeg 3
+ new_codec = avcodec_find_encoder_by_name(codec.c_str());
+-#endif //IS_FFMPEG_3_2
++#endif // HAVE_HW_ACCEL
+ if (new_codec == NULL)
+ throw InvalidCodec("A valid video codec could not be found for this file.", path);
+ else {
+@@ -392,11 +392,11 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va
+ // This might be better in an extra methods as more options
+ // and way to set quality are possible
+ #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 39, 101)
+- #if IS_FFMPEG_3_2
++ #if HAVE_HW_ACCEL
+ if (hw_en_on) {
+ av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); // 0-63
+ } else
+- #endif
++ #endif // HAVE_HW_ACCEL
+ {
+ switch (c->codec_id) {
+ #if (LIBAVCODEC_VERSION_MAJOR >= 58)
+@@ -442,7 +442,7 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va
+ // This might be better in an extra methods as more options
+ // and way to set quality are possible
+ #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 39, 101)
+-#if IS_FFMPEG_3_2
++#if HAVE_HW_ACCEL
+ if (hw_en_on) {
+ double mbs = 15000000.0;
+ if (info.video_bit_rate > 0) {
+@@ -455,7 +455,7 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va
+ }
+ c->bit_rate = (int)(mbs);
+ } else
+-#endif
++#endif // HAVE_HW_ACCEL
+ {
+ switch (c->codec_id) {
+ #if (LIBAVCODEC_VERSION_MAJOR >= 58)
+@@ -955,16 +955,14 @@ void FFmpegWriter::flush_encoders() {
+ // Close the video codec
+ void FFmpegWriter::close_video(AVFormatContext *oc, AVStream *st)
+ {
+-#if IS_FFMPEG_3_2
+- // #if defined(__linux__)
+- if (hw_en_on && hw_en_supported) {
+- if (hw_device_ctx) {
+- av_buffer_unref(&hw_device_ctx);
+- hw_device_ctx = NULL;
+- }
++#if HAVE_HW_ACCEL
++ if (hw_en_on && hw_en_supported) {
++ if (hw_device_ctx) {
++ av_buffer_unref(&hw_device_ctx);
++ hw_device_ctx = NULL;
+ }
+- // #endif
+-#endif
++ }
++#endif // HAVE_HW_ACCEL
+ }
+
+ // Close the audio codec
+@@ -1342,7 +1340,7 @@ void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
+ // Set number of threads equal to number of processors (not to exceed 16)
+ video_codec->thread_count = std::min(FF_NUM_PROCESSORS, 16);
+
+-#if IS_FFMPEG_3_2
++#if HAVE_HW_ACCEL
+ if (hw_en_on && hw_en_supported) {
+ //char *dev_hw = NULL;
+ char adapter[256];
+@@ -1385,7 +1383,7 @@ void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
+ throw InvalidCodec("Could not create hwdevice", path);
+ }
+ }
+-#endif
++#endif // HAVE_HW_ACCEL
+
+ /* find the video encoder */
+ codec = avcodec_find_encoder_by_name(info.vcodec.c_str());
+@@ -1402,7 +1400,7 @@ void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
+ AVDictionary *opts = NULL;
+ av_dict_set(&opts, "strict", "experimental", 0);
+
+-#if IS_FFMPEG_3_2
++#if HAVE_HW_ACCEL
+ if (hw_en_on && hw_en_supported) {
+ video_codec->pix_fmt = hw_en_av_pix_fmt;
+
+@@ -1451,7 +1449,7 @@ void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) {
+ "width", info.width, "height", info.height, av_err2str(err), -1);
+ }
+ }
+-#endif
++#endif // HAVE_HW_ACCEL
+
+ /* open the codec */
+ if (avcodec_open2(video_codec, codec, &opts) < 0)
+@@ -1900,14 +1898,17 @@ void FFmpegWriter::process_video_packet(std::shared_ptr<Frame> frame) {
+ frame_source = allocate_avframe(PIX_FMT_RGBA, source_image_width, source_image_height, &bytes_source, (uint8_t *) pixels);
+ #if IS_FFMPEG_3_2
+ AVFrame *frame_final;
++ #if HAVE_HW_ACCEL
+ if (hw_en_on && hw_en_supported) {
+ frame_final = allocate_avframe(AV_PIX_FMT_NV12, info.width, info.height, &bytes_final, NULL);
+- } else {
++ } else
++ #endif // HAVE_HW_ACCEL
++ {
+ frame_final = allocate_avframe((AVPixelFormat)(video_st->codecpar->format), info.width, info.height, &bytes_final, NULL);
+ }
+ #else
+ AVFrame *frame_final = allocate_avframe(video_codec->pix_fmt, info.width, info.height, &bytes_final, NULL);
+-#endif
++#endif // IS_FFMPEG_3_2
+
+ // Fill with data
+ AV_COPY_PICTURE_DATA(frame_source, (uint8_t *) pixels, PIX_FMT_RGBA, source_image_width, source_image_height);
+@@ -1977,7 +1978,7 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
+
+ // Assign the initial AVFrame PTS from the frame counter
+ frame_final->pts = write_video_count;
+-#if IS_FFMPEG_3_2
++#if HAVE_HW_ACCEL
+ if (hw_en_on && hw_en_supported) {
+ if (!(hw_frame = av_frame_alloc())) {
+ fprintf(stderr, "Error code: av_hwframe_alloc\n");
+@@ -1994,7 +1995,7 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
+ }
+ av_frame_copy_props(hw_frame, frame_final);
+ }
+-#endif
++#endif // HAVE_HW_ACCEL
+ /* encode the image */
+ int got_packet_ptr = 0;
+ int error_code = 0;
+@@ -2003,9 +2004,12 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
+ int frameFinished = 0;
+ int ret;
+
++ #if HAVE_HW_ACCEL
+ if (hw_en_on && hw_en_supported) {
+ ret = avcodec_send_frame(video_codec, hw_frame); //hw_frame!!!
+- } else {
++ } else
++ #endif // HAVE_HW_ACCEL
++ {
+ ret = avcodec_send_frame(video_codec, frame_final);
+ }
+ error_code = ret;
+@@ -2062,8 +2066,8 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
+ // got data back (so encode this frame)
+ got_packet_ptr = 1;
+ }
+-#endif
+-#endif
++#endif // LIBAVFORMAT_VERSION_MAJOR >= 54
++#endif // IS_FFMPEG_3_2
+
+ /* if zero size, it means the image was buffered */
+ if (error_code == 0 && got_packet_ptr) {
+@@ -2095,14 +2099,14 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr<Frame> frame, AVFrame *fra
+
+ // Deallocate packet
+ AV_FREE_PACKET(&pkt);
+-#if IS_FFMPEG_3_2
++#if HAVE_HW_ACCEL
+ if (hw_en_on && hw_en_supported) {
+ if (hw_frame) {
+ av_frame_free(&hw_frame);
+ hw_frame = NULL;
+ }
+ }
+-#endif
++#endif // HAVE_HW_ACCEL
+ }
+
+ // Success
+@@ -2125,11 +2129,11 @@ void FFmpegWriter::InitScalers(int source_width, int source_height) {
+ // Init software rescalers vector (many of them, one for each thread)
+ for (int x = 0; x < num_of_rescalers; x++) {
+ // Init the software scaler from FFMpeg
+-#if IS_FFMPEG_3_2
++#if HAVE_HW_ACCEL
+ if (hw_en_on && hw_en_supported) {
+ img_convert_ctx = sws_getContext(source_width, source_height, PIX_FMT_RGBA, info.width, info.height, AV_PIX_FMT_NV12, scale_mode, NULL, NULL, NULL);
+ } else
+-#endif
++#endif // HAVE_HW_ACCEL
+ {
+ img_convert_ctx = sws_getContext(source_width, source_height, PIX_FMT_RGBA, info.width, info.height, AV_GET_CODEC_PIXEL_FORMAT(video_st, video_st->codec), scale_mode,
+ NULL, NULL, NULL);