From adeb452e5d47176de82c304c6aab2675bd465d3f Mon Sep 17 00:00:00 2001 From: Markus KARG Date: Mon, 4 Nov 2019 19:56:33 +0100 Subject: [PATCH 01/30] Color-separated Saturation Signed-off-by: Markus KARG --- include/effects/Saturation.h | 5 ++- src/effects/Saturation.cpp | 75 +++++++++++++++++++++++++++++++++++- 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/include/effects/Saturation.h b/include/effects/Saturation.h index de3cc771..08695fd9 100644 --- a/include/effects/Saturation.h +++ b/include/effects/Saturation.h @@ -65,6 +65,9 @@ namespace openshot public: Keyframe saturation; ///< The color saturation: 0.0 = black and white, 1.0 = normal, 2.0 = double saturation + Keyframe saturation_R; ///< Red color saturation + Keyframe saturation_G; ///< Green color saturation + Keyframe saturation_B; ///< Blue color saturation /// Blank constructor, useful when using Json to load the effect properties Saturation(); @@ -72,7 +75,7 @@ namespace openshot /// Default constructor, which takes 1 curve, to adjust the color saturation over time. /// /// @param new_saturation The curve to adjust the saturation of the frame's image (0.0 = black and white, 1.0 = normal, 2.0 = double saturation) - Saturation(Keyframe new_saturation); + Saturation(Keyframe new_saturation, Keyframe new_saturation_R, Keyframe new_saturation_G, Keyframe new_saturation_B); /// @brief This method is required for all derived classes of EffectBase, and returns a /// modified openshot::Frame object diff --git a/src/effects/Saturation.cpp b/src/effects/Saturation.cpp index 06bcb02c..6762b4e7 100644 --- a/src/effects/Saturation.cpp +++ b/src/effects/Saturation.cpp @@ -33,13 +33,13 @@ using namespace openshot; /// Blank constructor, useful when using Json to load the effect properties -Saturation::Saturation() : saturation(1.0) { +Saturation::Saturation() : saturation(1.0), saturation_R(1.0), saturation_G(1.0), saturation_B(1.0) { // Init effect properties init_effect_details(); } // Default constructor -Saturation::Saturation(Keyframe new_saturation) : saturation(new_saturation) +Saturation::Saturation(Keyframe new_saturation, Keyframe new_saturation_R, Keyframe new_saturation_G, Keyframe new_saturation_B) : saturation(new_saturation), saturation_R(new_saturation_R), saturation_G(new_saturation_G), saturation_B(new_saturation_B) { // Init effect properties init_effect_details(); @@ -71,6 +71,9 @@ std::shared_ptr Saturation::GetFrame(std::shared_ptr frame, int64_ // Get keyframe values for this frame float saturation_value = saturation.GetValue(frame_number); + float saturation_value_R = saturation_R.GetValue(frame_number); + float saturation_value_G = saturation_G.GetValue(frame_number); + float saturation_value_B = saturation_B.GetValue(frame_number); // Constants used for color saturation formula double pR = .299; @@ -87,6 +90,10 @@ std::shared_ptr Saturation::GetFrame(std::shared_ptr frame, int64_ int B = pixels[byte_index + 2]; int A = pixels[byte_index + 3]; + /* + * Common saturation adjustment + */ + // Calculate the saturation multiplier double p = sqrt( (R * R * pR) + (G * G * pG) + @@ -102,6 +109,58 @@ std::shared_ptr Saturation::GetFrame(std::shared_ptr frame, int64_ G = constrain(G); B = constrain(B); + /* + * Color-separated saturation adjustment + * + * Splitting each of the three subpixels (R, G and B) into three distincs sub-subpixels (R, G and B in turn) + * which in their optical sum reproduce the original subpixel's color OR produce white light in the brightness + * of the original subpixel (dependening on the color channel's slider value). + */ + + // Three subpixels producing either R or white with brightness of R + int Rr = R; + int Gr = 0; + int Br = 0; + + // Three subpixels producing either G or white with brightness of G + int Rg = 0; + int Gg = G; + int Bg = 0; + + // Three subpixels producing either B or white with brightness of B + int Rb = 0; + int Gb = 0; + int Bb = B; + + // Compute the brightness ("saturation multiplier") of the replaced subpixels + // Actually mathematical no-ops mostly, verbosity is kept just for clarification + const double p_r = sqrt( (Rr * Rr * pR) + (Gr * Gr * pG) + (Br * Br * pB) ); + const double p_g = sqrt( (Rg * Rg * pR) + (Gg * Gg * pG) + (Bg * Bg * pB) ); + const double p_b = sqrt( (Rb * Rb * pR) + (Gb * Gb * pG) + (Bb * Bb * pB) ); + + // Adjust the saturation + Rr = p_r + (Rr - p_r) * saturation_value_R; + Gr = p_r + (Gr - p_r) * saturation_value_R; + Br = p_r + (Br - p_r) * saturation_value_R; + + Rg = p_g + (Rg - p_g) * saturation_value_G; + Gg = p_g + (Gg - p_g) * saturation_value_G; + Bg = p_g + (Bg - p_g) * saturation_value_G; + + Rb = p_b + (Rb - p_b) * saturation_value_B; + Gb = p_b + (Gb - p_b) * saturation_value_B; + Bb = p_b + (Bb - p_b) * saturation_value_B; + + // Recombine brightness of sub-subpixels (Rx, Gx and Bx) into sub-pixels (R, G and B) again + R = Rr + Rg + Rb; + G = Gr + Gg + Gb; + B = Br + Bg + Bb; + + // Constrain the value from 0 to 255 + R = constrain(R); + G = constrain(G); + B = constrain(B); + // Set all pixels to new value pixels[byte_index] = R; pixels[byte_index + 1] = G; @@ -127,6 +186,9 @@ Json::Value Saturation::JsonValue() { Json::Value root = EffectBase::JsonValue(); // get parent properties root["type"] = info.class_name; root["saturation"] = saturation.JsonValue(); + root["saturation_R"] = saturation_R.JsonValue(); + root["saturation_G"] = saturation_G.JsonValue(); + root["saturation_B"] = saturation_B.JsonValue(); // return JsonValue return root; @@ -170,6 +232,12 @@ void Saturation::SetJsonValue(Json::Value root) { // Set data from Json (if key is found) if (!root["saturation"].isNull()) saturation.SetJsonValue(root["saturation"]); + if (!root["saturation_R"].isNull()) + saturation_R.SetJsonValue(root["saturation_R"]); + if (!root["saturation_G"].isNull()) + saturation_G.SetJsonValue(root["saturation_G"]); + if (!root["saturation_B"].isNull()) + saturation_B.SetJsonValue(root["saturation_B"]); } // Get all properties for a specific frame @@ -186,6 +254,9 @@ std::string Saturation::PropertiesJSON(int64_t requested_frame) { // Keyframes root["saturation"] = add_property_json("Saturation", saturation.GetValue(requested_frame), "float", "", &saturation, 0.0, 4.0, false, requested_frame); + root["saturation_R"] = add_property_json("Saturation (Red)", saturation_R.GetValue(requested_frame), "float", "", &saturation_R, 0.0, 4.0, false, requested_frame); + root["saturation_G"] = add_property_json("Saturation (Green)", saturation_G.GetValue(requested_frame), "float", "", &saturation_G, 0.0, 4.0, false, requested_frame); + root["saturation_B"] = add_property_json("Saturation (Blue)", saturation_B.GetValue(requested_frame), "float", "", &saturation_B, 0.0, 4.0, false, requested_frame); // Return formatted string return root.toStyledString(); From ffab5705543b3739e1f4b8bcdef0460eb8947952 Mon Sep 17 00:00:00 2001 From: Markus KARG Date: Sat, 23 Nov 2019 19:10:11 +0100 Subject: [PATCH 02/30] Color-separated Saturation: Enhanced Comment See https://github.com/OpenShot/libopenshot/pull/368#discussion_r349868322. Signed-off-by: Markus KARG --- include/effects/Saturation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/effects/Saturation.h b/include/effects/Saturation.h index 08695fd9..83ee75b2 100644 --- a/include/effects/Saturation.h +++ b/include/effects/Saturation.h @@ -64,7 +64,7 @@ namespace openshot void init_effect_details(); public: - Keyframe saturation; ///< The color saturation: 0.0 = black and white, 1.0 = normal, 2.0 = double saturation + Keyframe saturation; ///< Overall color saturation: 0.0 = black and white, 1.0 = normal, 2.0 = double saturation Keyframe saturation_R; ///< Red color saturation Keyframe saturation_G; ///< Green color saturation Keyframe saturation_B; ///< Blue color saturation From 09435d3e0c0dc4cb92f231ae584e16939eb81c65 Mon Sep 17 00:00:00 2001 From: Markus KARG Date: Sat, 23 Nov 2019 19:21:14 +0100 Subject: [PATCH 03/30] Saturation: Enhanced Comment ("greyscale" vs. "black and white") Signed-off-by: Markus KARG --- include/effects/Saturation.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/effects/Saturation.h b/include/effects/Saturation.h index 83ee75b2..495816f6 100644 --- a/include/effects/Saturation.h +++ b/include/effects/Saturation.h @@ -64,7 +64,7 @@ namespace openshot void init_effect_details(); public: - Keyframe saturation; ///< Overall color saturation: 0.0 = black and white, 1.0 = normal, 2.0 = double saturation + Keyframe saturation; ///< Overall color saturation: 0.0 = greyscale, 1.0 = normal, 2.0 = double saturation Keyframe saturation_R; ///< Red color saturation Keyframe saturation_G; ///< Green color saturation Keyframe saturation_B; ///< Blue color saturation @@ -74,7 +74,7 @@ namespace openshot /// Default constructor, which takes 1 curve, to adjust the color saturation over time. /// - /// @param new_saturation The curve to adjust the saturation of the frame's image (0.0 = black and white, 1.0 = normal, 2.0 = double saturation) + /// @param new_saturation The curve to adjust the saturation of the frame's image (0.0 = greyscale, 1.0 = normal, 2.0 = double saturation) Saturation(Keyframe new_saturation, Keyframe new_saturation_R, Keyframe new_saturation_G, Keyframe new_saturation_B); /// @brief This method is required for all derived classes of EffectBase, and returns a From 9474973c15fb3691eefee2e74a1e7b472342818a Mon Sep 17 00:00:00 2001 From: Markus KARG Date: Sat, 23 Nov 2019 19:33:54 +0100 Subject: [PATCH 04/30] Color-separated Saturation: Enhanced constructor parameter names See https://github.com/OpenShot/libopenshot/pull/368#discussion_r349868437. Signed-off-by: Markus KARG --- include/effects/Saturation.h | 4 ++-- src/effects/Saturation.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/effects/Saturation.h b/include/effects/Saturation.h index 495816f6..7badef0e 100644 --- a/include/effects/Saturation.h +++ b/include/effects/Saturation.h @@ -74,8 +74,8 @@ namespace openshot /// Default constructor, which takes 1 curve, to adjust the color saturation over time. /// - /// @param new_saturation The curve to adjust the saturation of the frame's image (0.0 = greyscale, 1.0 = normal, 2.0 = double saturation) - Saturation(Keyframe new_saturation, Keyframe new_saturation_R, Keyframe new_saturation_G, Keyframe new_saturation_B); + /// @param saturation The curve to adjust the saturation of the frame's image (0.0 = greyscale, 1.0 = normal, 2.0 = double saturation) + Saturation(Keyframe saturation, Keyframe saturation_R, Keyframe saturation_G, Keyframe saturation_B); /// @brief This method is required for all derived classes of EffectBase, and returns a /// modified openshot::Frame object diff --git a/src/effects/Saturation.cpp b/src/effects/Saturation.cpp index 6762b4e7..567db2d1 100644 --- a/src/effects/Saturation.cpp +++ b/src/effects/Saturation.cpp @@ -39,7 +39,7 @@ Saturation::Saturation() : saturation(1.0), saturation_R(1.0), saturation_G(1.0) } // Default constructor -Saturation::Saturation(Keyframe new_saturation, Keyframe new_saturation_R, Keyframe new_saturation_G, Keyframe new_saturation_B) : saturation(new_saturation), saturation_R(new_saturation_R), saturation_G(new_saturation_G), saturation_B(new_saturation_B) +Saturation::Saturation(Keyframe saturation, Keyframe saturation_R, Keyframe saturation_G, Keyframe saturation_B) : saturation(saturation), saturation_R(saturation_R), saturation_G(saturation_G), saturation_B(saturation_B) { // Init effect properties init_effect_details(); From 0d7468b0704df1dc985817c32c47ea9ce0a59e4d Mon Sep 17 00:00:00 2001 From: Markus KARG Date: Sun, 24 Nov 2019 17:12:17 +0100 Subject: [PATCH 05/30] Color-separated saturation: Documented new constructor parameters Signed-off-by: Markus KARG --- include/effects/Saturation.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/effects/Saturation.h b/include/effects/Saturation.h index 7badef0e..afd1c91f 100644 --- a/include/effects/Saturation.h +++ b/include/effects/Saturation.h @@ -75,6 +75,9 @@ namespace openshot /// Default constructor, which takes 1 curve, to adjust the color saturation over time. /// /// @param saturation The curve to adjust the saturation of the frame's image (0.0 = greyscale, 1.0 = normal, 2.0 = double saturation) + /// @param saturation_R The curve to adjust red saturation of the frame's image (0.0 = greyscale, 1.0 = normal, 2.0 = double saturation) + /// @param saturation_G The curve to adjust green saturation of the frame's image (0.0 = greyscale, 1.0 = normal, 2.0 = double saturation) + /// @param saturation_B The curve to adjust blue saturation of the frame's image (0.0 = greyscale, 1.0 = normal, 2.0 = double saturation) Saturation(Keyframe saturation, Keyframe saturation_R, Keyframe saturation_G, Keyframe saturation_B); /// @brief This method is required for all derived classes of EffectBase, and returns a From 88c04944b1d073b3ece17aca3920763cff6edae0 Mon Sep 17 00:00:00 2001 From: Markus KARG Date: Sun, 24 Nov 2019 17:15:49 +0100 Subject: [PATCH 06/30] Color-separated Saturation: Enhanced description of constructor Signed-off-by: Markus KARG --- include/effects/Saturation.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/effects/Saturation.h b/include/effects/Saturation.h index afd1c91f..aba762b4 100644 --- a/include/effects/Saturation.h +++ b/include/effects/Saturation.h @@ -72,7 +72,7 @@ namespace openshot /// Blank constructor, useful when using Json to load the effect properties Saturation(); - /// Default constructor, which takes 1 curve, to adjust the color saturation over time. + /// Default constructor, which takes four curves (one common curve and one curve per color), to adjust the color saturation over time. /// /// @param saturation The curve to adjust the saturation of the frame's image (0.0 = greyscale, 1.0 = normal, 2.0 = double saturation) /// @param saturation_R The curve to adjust red saturation of the frame's image (0.0 = greyscale, 1.0 = normal, 2.0 = double saturation) From 3a987eb044e0d755b4a1ae321fd816572e246e27 Mon Sep 17 00:00:00 2001 From: Markus KARG Date: Sun, 24 Nov 2019 17:21:43 +0100 Subject: [PATCH 07/30] Color-separated Saturation: Line Wrap Signed-off-by: Markus KARG --- src/effects/Saturation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/effects/Saturation.cpp b/src/effects/Saturation.cpp index 567db2d1..407f97af 100644 --- a/src/effects/Saturation.cpp +++ b/src/effects/Saturation.cpp @@ -39,7 +39,8 @@ Saturation::Saturation() : saturation(1.0), saturation_R(1.0), saturation_G(1.0) } // Default constructor -Saturation::Saturation(Keyframe saturation, Keyframe saturation_R, Keyframe saturation_G, Keyframe saturation_B) : saturation(saturation), saturation_R(saturation_R), saturation_G(saturation_G), saturation_B(saturation_B) +Saturation::Saturation(Keyframe saturation, Keyframe saturation_R, Keyframe saturation_G, Keyframe saturation_B) : + saturation(saturation), saturation_R(saturation_R), saturation_G(saturation_G), saturation_B(saturation_B) { // Init effect properties init_effect_details(); From c979f5b0d6655add38016ab058d26569cc49361f Mon Sep 17 00:00:00 2001 From: Markus KARG Date: Sun, 24 Nov 2019 18:16:21 +0100 Subject: [PATCH 08/30] Color-separated Saturation: Optimized math (removed no-ops) Signed-off-by: Markus KARG --- src/effects/Saturation.cpp | 39 ++++++++++++-------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/src/effects/Saturation.cpp b/src/effects/Saturation.cpp index 407f97af..560c4102 100644 --- a/src/effects/Saturation.cpp +++ b/src/effects/Saturation.cpp @@ -118,39 +118,24 @@ std::shared_ptr Saturation::GetFrame(std::shared_ptr frame, int64_ * of the original subpixel (dependening on the color channel's slider value). */ - // Three subpixels producing either R or white with brightness of R - int Rr = R; - int Gr = 0; - int Br = 0; - - // Three subpixels producing either G or white with brightness of G - int Rg = 0; - int Gg = G; - int Bg = 0; - - // Three subpixels producing either B or white with brightness of B - int Rb = 0; - int Gb = 0; - int Bb = B; - // Compute the brightness ("saturation multiplier") of the replaced subpixels // Actually mathematical no-ops mostly, verbosity is kept just for clarification - const double p_r = sqrt( (Rr * Rr * pR) + (Gr * Gr * pG) + (Br * Br * pB) ); - const double p_g = sqrt( (Rg * Rg * pR) + (Gg * Gg * pG) + (Bg * Bg * pB) ); - const double p_b = sqrt( (Rb * Rb * pR) + (Gb * Gb * pG) + (Bb * Bb * pB) ); + const double p_r = sqrt(R * R * pR); + const double p_g = sqrt(G * G * pG); + const double p_b = sqrt(B * B * pB); // Adjust the saturation - Rr = p_r + (Rr - p_r) * saturation_value_R; - Gr = p_r + (Gr - p_r) * saturation_value_R; - Br = p_r + (Br - p_r) * saturation_value_R; + const int Rr = p_r + (R - p_r) * saturation_value_R; + const int Gr = p_r + (0 - p_r) * saturation_value_R; + const int Br = p_r + (0 - p_r) * saturation_value_R; - Rg = p_g + (Rg - p_g) * saturation_value_G; - Gg = p_g + (Gg - p_g) * saturation_value_G; - Bg = p_g + (Bg - p_g) * saturation_value_G; + const int Rg = p_g + (0 - p_g) * saturation_value_G; + const int Gg = p_g + (G - p_g) * saturation_value_G; + const int Bg = p_g + (0 - p_g) * saturation_value_G; - Rb = p_b + (Rb - p_b) * saturation_value_B; - Gb = p_b + (Gb - p_b) * saturation_value_B; - Bb = p_b + (Bb - p_b) * saturation_value_B; + const int Rb = p_b + (0 - p_b) * saturation_value_B; + const int Gb = p_b + (0 - p_b) * saturation_value_B; + const int Bb = p_b + (B - p_b) * saturation_value_B; // Recombine brightness of sub-subpixels (Rx, Gx and Bx) into sub-pixels (R, G and B) again R = Rr + Rg + Rb; From 5764b03544b8a14f9f3669e14db4740c23c9d06e Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 4 Mar 2020 23:52:42 -0500 Subject: [PATCH 09/30] FFmpegWriter: Use std::clog for output - Eliminate fprintf(stderr...) and non-threadsafe std::cerr - Replace with thread-safe std:clog or ZeroMQ calls - Clean up some formatting & ZeroMQ logging --- include/FFmpegWriter.h | 2 -- src/FFmpegWriter.cpp | 53 +++++++++++++++++++----------------------- 2 files changed, 24 insertions(+), 31 deletions(-) diff --git a/include/FFmpegWriter.h b/include/FFmpegWriter.h index 1dfb21a9..252c1c43 100644 --- a/include/FFmpegWriter.h +++ b/include/FFmpegWriter.h @@ -47,8 +47,6 @@ #include #include -#include -#include #include #include "CacheMemory.h" #include "Exceptions.h" diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index e6a1d180..dd36bed0 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -33,6 +33,8 @@ #include "../include/FFmpegWriter.h" +#include + using namespace openshot; #if HAVE_HW_ACCEL @@ -59,7 +61,7 @@ static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int6 int err = 0; if (!(hw_frames_ref = av_hwframe_ctx_alloc(hw_device_ctx))) { - fprintf(stderr, "Failed to create HW frame context.\n"); + std::clog << "Failed to create HW frame context.\n"; return -1; } frames_ctx = (AVHWFramesContext *)(hw_frames_ref->data); @@ -69,8 +71,8 @@ static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int6 frames_ctx->height = height; frames_ctx->initial_pool_size = 20; if ((err = av_hwframe_ctx_init(hw_frames_ref)) < 0) { - fprintf(stderr, "Failed to initialize HW frame context." - "Error code: %s\n",av_err2str(err)); + std::clog << "Failed to initialize HW frame context. " << + "Error code: " << av_err2str(err) << "\n"; av_buffer_unref(&hw_frames_ref); return err; } @@ -1365,7 +1367,7 @@ void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) { int adapter_num; // Use the hw device given in the environment variable HW_EN_DEVICE_SET or the default if not set adapter_num = openshot::Settings::Instance()->HW_EN_DEVICE_SET; - fprintf(stderr, "\n\nEncodiing Device Nr: %d\n", adapter_num); + std::clog << "Encoding Device Nr: " << adapter_num << "\n"; if (adapter_num < 3 && adapter_num >=0) { #if defined(__linux__) snprintf(adapter,sizeof(adapter),"/dev/dri/renderD%d", adapter_num+128); @@ -1392,11 +1394,11 @@ void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) { } else { adapter_ptr = NULL; // use default - ZmqLogger::Instance()->AppendDebugMethod("Encode Device not present using default"); + ZmqLogger::Instance()->AppendDebugMethod("Encode Device not present, using default"); } if (av_hwdevice_ctx_create(&hw_device_ctx, hw_en_av_device_type, adapter_ptr, NULL, 0) < 0) { - ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::open_video : Codec name: ", info.vcodec.c_str(), -1, " ERROR creating\n", -1); + ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::open_video ERROR creating hwdevice, Codec name:", info.vcodec.c_str(), -1); throw InvalidCodec("Could not create hwdevice", path); } } @@ -1817,10 +1819,7 @@ void FFmpegWriter::write_audio_packets(bool is_final) { pkt.flags |= AV_PKT_FLAG_KEY; /* write the compressed frame in the media file */ - int error_code = av_interleaved_write_frame(oc, &pkt); - if (error_code < 0) { - ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets ERROR [" + (std::string) av_err2str(error_code) + "]", "error_code", error_code); - } + error_code = av_interleaved_write_frame(oc, &pkt); } if (error_code < 0) { @@ -1998,17 +1997,17 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra #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"); + std::clog << "Error code: av_hwframe_alloc\n"; } if (av_hwframe_get_buffer(video_codec->hw_frames_ctx, hw_frame, 0) < 0) { - fprintf(stderr, "Error code: av_hwframe_get_buffer\n"); + std::clog << "Error code: av_hwframe_get_buffer\n"; } if (!hw_frame->hw_frames_ctx) { - fprintf(stderr, "Error hw_frames_ctx.\n"); + std::clog << "Error hw_frames_ctx.\n"; } hw_frame->format = AV_PIX_FMT_NV12; if ( av_hwframe_transfer_data(hw_frame, frame_final, 0) < 0) { - fprintf(stderr, "Error while transferring frame data to surface.\n"); + std::clog << "Error while transferring frame data to surface.\n"; } av_frame_copy_props(hw_frame, frame_final); } @@ -2031,13 +2030,7 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra } error_code = ret; if (ret < 0 ) { - ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet (Frame not sent)"); - if (ret == AVERROR(EAGAIN) ) { - std::cerr << "Frame EAGAIN" << "\n"; - } - if (ret == AVERROR_EOF ) { - std::cerr << "Frame AVERROR_EOF" << "\n"; - } + ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet (Frame not sent) ERROR [" + (std::string) av_err2str(ret) + "]", "ret", ret); avcodec_send_frame(video_codec, NULL); } else { @@ -2060,10 +2053,10 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra // Write video packet (older than FFmpeg 3.2) error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr); if (error_code != 0) { - std::cerr << "Frame AVERROR_EOF" << "\n"; + ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet ERROR [" + (std::string) av_err2str(error_code) + "]", "error_code", error_code); } if (got_packet_ptr == 0) { - std::cerr << "Frame gotpacket error" << "\n"; + ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet (Frame gotpacket error)"); } #else // Write video packet (even older versions of FFmpeg) @@ -2103,9 +2096,9 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra pkt.stream_index = video_st->index; /* write the compressed frame in the media file */ - int error_code = av_interleaved_write_frame(oc, &pkt); - if (error_code < 0) { - ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet ERROR [" + (std::string) av_err2str(error_code) + "]", "error_code", error_code); + int result = av_interleaved_write_frame(oc, &pkt); + if (result < 0) { + ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet ERROR [" + (std::string) av_err2str(result) + "]", "result", result); return false; } } @@ -2148,12 +2141,14 @@ void FFmpegWriter::InitScalers(int source_width, int source_height) { // Init the software scaler from FFMpeg #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); + 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 // 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); + 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); } // Add rescaler to vector From 3a88d218662e4487ca3ce5dff036600a02bfc596 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 4 Mar 2020 23:58:16 -0500 Subject: [PATCH 10/30] FFmpegWriter: Drop ancient FFmpeg code - Drop any FFmpeg version checks for versions older than 2.6 - Remove code that was only used in FFmpeg 2.4 or lower - Add human-readable version comments to checks for LIBFOO_VERSION_MAJOR. etc. --- src/FFmpegWriter.cpp | 268 ++++++++++++++++--------------------------- 1 file changed, 97 insertions(+), 171 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index dd36bed0..245b0108 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -222,10 +222,10 @@ void FFmpegWriter::SetVideoOptions(bool has_video, std::string codec, Fraction f hw_en_on = 0; hw_en_supported = 0; } - #else // is FFmpeg 3 but not linux +#else // unknown OS new_codec = avcodec_find_encoder_by_name(codec.c_str()); - #endif //__linux__ -#else // not ffmpeg 3 +#endif //__linux__/_WIN32/__APPLE__ +#else // HAVE_HW_ACCEL new_codec = avcodec_find_encoder_by_name(codec.c_str()); #endif // HAVE_HW_ACCEL if (new_codec == NULL) @@ -410,57 +410,54 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va // encode quality and special settings like lossless // 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 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 // HAVE_HW_ACCEL - { + #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 // HAVE_HW_ACCEL + { switch (c->codec_id) { - #if (LIBAVCODEC_VERSION_MAJOR >= 58) - case AV_CODEC_ID_AV1 : - c->bit_rate = 0; - av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); // 0-63 - break; - #endif - case AV_CODEC_ID_VP8 : - c->bit_rate = 10000000; - av_opt_set_int(c->priv_data, "qp", std::max(std::min(std::stoi(value), 63), 4), 0); // 4-63 - break; - case AV_CODEC_ID_VP9 : - c->bit_rate = 0; // Must be zero! - av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 63), 0); // 0-63 - if (std::stoi(value) == 0) { - av_opt_set(c->priv_data, "preset", "veryslow", 0); - av_opt_set_int(c->priv_data, "lossless", 1, 0); - } - break; - case AV_CODEC_ID_H264 : - av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 51), 0); // 0-51 - if (std::stoi(value) == 0) { - av_opt_set(c->priv_data, "preset", "veryslow", 0); - } - break; - case AV_CODEC_ID_HEVC : - av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 51), 0); // 0-51 - if (std::stoi(value) == 0) { - av_opt_set(c->priv_data, "preset", "veryslow", 0); - av_opt_set_int(c->priv_data, "lossless", 1, 0); - } - break; - default: - // For all other codecs assume a range of 0-63 - av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 63), 0); // 0-63 - c->bit_rate = 0; + #if (LIBAVCODEC_VERSION_MAJOR >= 58) + case AV_CODEC_ID_AV1 : + c->bit_rate = 0; + av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); // 0-63 + break; + #endif + case AV_CODEC_ID_VP8 : + c->bit_rate = 10000000; + av_opt_set_int(c->priv_data, "qp", std::max(std::min(std::stoi(value), 63), 4), 0); // 4-63 + break; + case AV_CODEC_ID_VP9 : + c->bit_rate = 0; // Must be zero! + av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 63), 0); // 0-63 + if (std::stoi(value) == 0) { + av_opt_set(c->priv_data, "preset", "veryslow", 0); + av_opt_set_int(c->priv_data, "lossless", 1, 0); + } + break; + case AV_CODEC_ID_H264 : + av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 51), 0); // 0-51 + if (std::stoi(value) == 0) { + av_opt_set(c->priv_data, "preset", "veryslow", 0); + } + break; + case AV_CODEC_ID_HEVC : + av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 51), 0); // 0-51 + if (std::stoi(value) == 0) { + av_opt_set(c->priv_data, "preset", "veryslow", 0); + av_opt_set_int(c->priv_data, "lossless", 1, 0); + } + break; + default: + // For all other codecs assume a range of 0-63 + av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value), 63), 0); // 0-63 + c->bit_rate = 0; } } - #endif } else if (name == "crf") { // encode quality and special settings like lossless // 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 HAVE_HW_ACCEL if (hw_en_on) { double mbs = 15000000.0; @@ -478,51 +475,50 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va { switch (c->codec_id) { #if (LIBAVCODEC_VERSION_MAJOR >= 58) - case AV_CODEC_ID_AV1 : - c->bit_rate = 0; - av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); - break; + case AV_CODEC_ID_AV1 : + c->bit_rate = 0; + av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); + break; #endif - case AV_CODEC_ID_VP8 : - c->bit_rate = 10000000; - av_opt_set_int(c->priv_data, "crf", std::max(std::min(std::stoi(value), 63), 4), 0); // 4-63 - break; - case AV_CODEC_ID_VP9 : - c->bit_rate = 0; // Must be zero! - av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 63), 0); // 0-63 - if (std::stoi(value) == 0) { - av_opt_set(c->priv_data, "preset", "veryslow", 0); - av_opt_set_int(c->priv_data, "lossless", 1, 0); + case AV_CODEC_ID_VP8 : + c->bit_rate = 10000000; + av_opt_set_int(c->priv_data, "crf", std::max(std::min(std::stoi(value), 63), 4), 0); // 4-63 + break; + case AV_CODEC_ID_VP9 : + c->bit_rate = 0; // Must be zero! + av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 63), 0); // 0-63 + if (std::stoi(value) == 0) { + av_opt_set(c->priv_data, "preset", "veryslow", 0); + av_opt_set_int(c->priv_data, "lossless", 1, 0); + } + break; + case AV_CODEC_ID_H264 : + av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 51), 0); // 0-51 + if (std::stoi(value) == 0) { + av_opt_set(c->priv_data, "preset", "veryslow", 0); + } + break; + case AV_CODEC_ID_HEVC : + av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 51), 0); // 0-51 + if (std::stoi(value) == 0) { + av_opt_set(c->priv_data, "preset", "veryslow", 0); + av_opt_set_int(c->priv_data, "lossless", 1, 0); + } + break; + default: + // If this codec doesn't support crf calculate a bitrate + // TODO: find better formula + double mbs = 15000000.0; + if (info.video_bit_rate > 0) { + if (info.video_bit_rate > 42) { + mbs = 380000.0; + } else { + mbs *= std::pow(0.912, info.video_bit_rate); } - break; - case AV_CODEC_ID_H264 : - av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 51), 0); // 0-51 - if (std::stoi(value) == 0) { - av_opt_set(c->priv_data, "preset", "veryslow", 0); - } - break; - case AV_CODEC_ID_HEVC : - av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value), 51), 0); // 0-51 - if (std::stoi(value) == 0) { - av_opt_set(c->priv_data, "preset", "veryslow", 0); - av_opt_set_int(c->priv_data, "lossless", 1, 0); - } - break; - default: - // If this codec doesn't support crf calculate a bitrate - // TODO: find better formula - double mbs = 15000000.0; - if (info.video_bit_rate > 0) { - if (info.video_bit_rate > 42) { - mbs = 380000.0; - } else { - mbs *= std::pow(0.912, info.video_bit_rate); - } - } - c->bit_rate = (int) (mbs); + } + c->bit_rate = (int) (mbs); } } -#endif } else { // Set AVOption AV_OPTION_SET(st, c->priv_data, name.c_str(), value.c_str(), c); @@ -635,15 +631,8 @@ void FFmpegWriter::WriteFrame(std::shared_ptr frame) { // Write the frames once it reaches the correct cache size if ((int)spooled_video_frames.size() == cache_size || (int)spooled_audio_frames.size() == cache_size) { - // Is writer currently writing? - if (!is_writing) - // Write frames to video file - write_queued_frames(); - - else { - // Write frames to video file - write_queued_frames(); - } + // Write frames to video file + write_queued_frames(); } // Keep track of the last frame added @@ -801,6 +790,7 @@ void FFmpegWriter::flush_encoders() { if (info.has_audio && audio_codec && AV_GET_CODEC_TYPE(audio_st) == AVMEDIA_TYPE_AUDIO && AV_GET_CODEC_ATTRIBUTES(audio_st, audio_codec)->frame_size <= 1) return; #if (LIBAVFORMAT_VERSION_MAJOR < 58) + // FFmpeg < 4.0 if (info.has_video && video_codec && AV_GET_CODEC_TYPE(video_st) == AVMEDIA_TYPE_VIDEO && (oc->oformat->flags & AVFMT_RAWPICTURE) && AV_FIND_DECODER_CODEC_ID(video_st) == AV_CODEC_ID_RAWVIDEO) return; #endif @@ -820,9 +810,6 @@ void FFmpegWriter::flush_encoders() { pkt.data = NULL; pkt.size = 0; - // Pointer for video buffer (if using old FFmpeg version) - uint8_t *video_outbuf = NULL; - /* encode the image */ int got_packet = 0; int error_code = 0; @@ -853,28 +840,9 @@ void FFmpegWriter::flush_encoders() { } #else // IS_FFMPEG_3_2 -#if LIBAVFORMAT_VERSION_MAJOR >= 54 // Encode video packet (older than FFmpeg 3.2) error_code = avcodec_encode_video2(video_codec, &pkt, NULL, &got_packet); -#else - // Encode video packet (even older version of FFmpeg) - int video_outbuf_size = 0; - - /* encode the image */ - int out_size = avcodec_encode_video(video_codec, NULL, video_outbuf_size, NULL); - - /* if zero size, it means the image was buffered */ - if (out_size > 0) { - if(video_codec->coded_frame->key_frame) - pkt.flags |= AV_PKT_FLAG_KEY; - pkt.data= video_outbuf; - pkt.size= out_size; - - // got data back (so encode this frame) - got_packet = 1; - } -#endif // LIBAVFORMAT_VERSION_MAJOR >= 54 #endif // IS_FFMPEG_3_2 if (error_code < 0) { @@ -903,9 +871,6 @@ void FFmpegWriter::flush_encoders() { ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::flush_encoders ERROR [" + (std::string)av_err2str(error_code) + "]", "error_code", error_code); } - // Deallocate memory (if needed) - if (video_outbuf) - av_freep(&video_outbuf); } // FLUSH AUDIO ENCODER @@ -913,12 +878,8 @@ void FFmpegWriter::flush_encoders() { for (;;) { // Increment PTS (in samples and scaled to the codec's timebase) -#if LIBAVFORMAT_VERSION_MAJOR >= 54 // for some reason, it requires me to multiply channels X 2 write_audio_count += av_rescale_q(audio_input_position / (audio_codec->channels * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16)), (AVRational){1, info.sample_rate}, audio_codec->time_base); -#else - write_audio_count += av_rescale_q(audio_input_position / audio_codec->channels, (AVRational){1, info.sample_rate}, audio_codec->time_base); -#endif AVPacket pkt; av_init_packet(&pkt); @@ -1073,11 +1034,7 @@ AVStream *FFmpegWriter::add_audio_stream() { AV_FORMAT_NEW_STREAM(oc, audio_codec, codec, st) c->codec_id = codec->id; -#if LIBAVFORMAT_VERSION_MAJOR >= 53 c->codec_type = AVMEDIA_TYPE_AUDIO; -#else - c->codec_type = CODEC_TYPE_AUDIO; -#endif // Set the sample parameters c->bit_rate = info.audio_bit_rate; @@ -1131,6 +1088,7 @@ AVStream *FFmpegWriter::add_audio_stream() { // some formats want stream headers to be separate if (oc->oformat->flags & AVFMT_GLOBALHEADER) #if (LIBAVCODEC_VERSION_MAJOR >= 57) + // FFmpeg 3.0+ c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; #else c->flags |= CODEC_FLAG_GLOBAL_HEADER; @@ -1156,11 +1114,7 @@ AVStream *FFmpegWriter::add_video_stream() { AV_FORMAT_NEW_STREAM(oc, video_codec, codec, st) c->codec_id = codec->id; -#if LIBAVFORMAT_VERSION_MAJOR >= 53 c->codec_type = AVMEDIA_TYPE_VIDEO; -#else - c->codec_type = CODEC_TYPE_VIDEO; -#endif /* Init video encoder options */ if (info.video_bit_rate >= 1000) { @@ -1174,13 +1128,12 @@ AVStream *FFmpegWriter::add_video_stream() { } else { // Check if codec supports crf switch (c->codec_id) { -#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 39, 101) #if (LIBAVCODEC_VERSION_MAJOR >= 58) + // FFmpeg 4.0+ case AV_CODEC_ID_AV1 : #endif case AV_CODEC_ID_VP9 : case AV_CODEC_ID_HEVC : -#endif case AV_CODEC_ID_VP8 : case AV_CODEC_ID_H264 : if (info.video_bit_rate < 40) { @@ -1217,7 +1170,7 @@ AVStream *FFmpegWriter::add_video_stream() { identically 1. */ c->time_base.num = info.video_timebase.num; c->time_base.den = info.video_timebase.den; -// AVCodecContext->framerate was added in FFmpeg 2.2 +// AVCodecContext->framerate was added in FFmpeg 2.6 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(56, 26, 0) c->framerate = av_inv_q(c->time_base); #endif @@ -1238,6 +1191,7 @@ AVStream *FFmpegWriter::add_video_stream() { // some formats want stream headers to be separate if (oc->oformat->flags & AVFMT_GLOBALHEADER) #if (LIBAVCODEC_VERSION_MAJOR >= 57) + // FFmpeg 3.0+ c->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; #else c->flags |= CODEC_FLAG_GLOBAL_HEADER; @@ -1259,6 +1213,7 @@ AVStream *FFmpegWriter::add_video_stream() { c->pix_fmt = PIX_FMT_RGB24; #if (LIBAVFORMAT_VERSION_MAJOR < 58) + // FFmpeg < 4.0 if (strcmp(fmt->name, "gif") != 0) // If not GIF format, skip the encoding process // Set raw picture flag (so we don't encode this video) @@ -1272,6 +1227,7 @@ AVStream *FFmpegWriter::add_video_stream() { AV_COPY_PARAMS_FROM_CONTEXT(st, c); #if (LIBAVFORMAT_VERSION_MAJOR < 58) + // FFmpeg < 4.0 ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_video_stream (" + (std::string)fmt->name + " : " + (std::string)av_get_pix_fmt_name(c->pix_fmt) + ")", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->pix_fmt", c->pix_fmt, "oc->oformat->flags", oc->oformat->flags, "AVFMT_RAWPICTURE", AVFMT_RAWPICTURE); #else ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::add_video_stream (" + (std::string)fmt->name + " : " + (std::string)av_get_pix_fmt_name(c->pix_fmt) + ")", "c->codec_id", c->codec_id, "c->bit_rate", c->bit_rate, "c->pix_fmt", c->pix_fmt, "oc->oformat->flags", oc->oformat->flags); @@ -1373,9 +1329,7 @@ void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) { snprintf(adapter,sizeof(adapter),"/dev/dri/renderD%d", adapter_num+128); // Maybe 127 is better because the first card would be 1?! adapter_ptr = adapter; -#elif defined(_WIN32) - adapter_ptr = NULL; -#elif defined(__APPLE__) +#elif defined(_WIN32) || defined(__APPLE__) adapter_ptr = NULL; #endif } @@ -1385,9 +1339,7 @@ void FFmpegWriter::open_video(AVFormatContext *oc, AVStream *st) { // Check if it is there and writable #if defined(__linux__) if( adapter_ptr != NULL && access( adapter_ptr, W_OK ) == 0 ) { -#elif defined(_WIN32) - if( adapter_ptr != NULL ) { -#elif defined(__APPLE__) +#elif defined(_WIN32) || defined(__APPLE__) if( adapter_ptr != NULL ) { #endif ZmqLogger::Instance()->AppendDebugMethod("Encode Device present using device", "adapter", adapter_num); @@ -1948,6 +1900,7 @@ void FFmpegWriter::process_video_packet(std::shared_ptr frame) { // write video frame bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *frame_final) { #if (LIBAVFORMAT_VERSION_MAJOR >= 58) + // FFmpeg 4.0+ ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet", "frame->number", frame->number, "oc->oformat->flags", oc->oformat->flags); #else ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet", "frame->number", frame->number, "oc->oformat->flags & AVFMT_RAWPICTURE", oc->oformat->flags & AVFMT_RAWPICTURE); @@ -1977,7 +1930,7 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra AV_FREE_PACKET(&pkt); } else -#endif +#endif // LIBAVFORMAT_VERSION_MAJOR >= 58 { AVPacket pkt; @@ -1986,9 +1939,6 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra pkt.size = 0; pkt.pts = pkt.dts = AV_NOPTS_VALUE; - // Pointer for video buffer (if using old FFmpeg version) - uint8_t *video_outbuf = NULL; - // Increment PTS (in frames and scaled to the codec's timebase) write_video_count += av_rescale_q(1, (AVRational) {info.fps.den, info.fps.num}, video_codec->time_base); @@ -2049,7 +1999,6 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra } } #else -#if LIBAVFORMAT_VERSION_MAJOR >= 54 // Write video packet (older than FFmpeg 3.2) error_code = avcodec_encode_video2(video_codec, &pkt, frame_final, &got_packet_ptr); if (error_code != 0) { @@ -2058,25 +2007,6 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra if (got_packet_ptr == 0) { ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_video_packet (Frame gotpacket error)"); } -#else - // Write video packet (even older versions of FFmpeg) - int video_outbuf_size = 200000; - video_outbuf = (uint8_t*) av_malloc(200000); - - /* encode the image */ - int out_size = avcodec_encode_video(video_codec, video_outbuf, video_outbuf_size, frame_final); - - /* if zero size, it means the image was buffered */ - if (out_size > 0) { - if(video_codec->coded_frame->key_frame) - pkt.flags |= AV_PKT_FLAG_KEY; - pkt.data= video_outbuf; - pkt.size= out_size; - - // got data back (so encode this frame) - got_packet_ptr = 1; - } -#endif // LIBAVFORMAT_VERSION_MAJOR >= 54 #endif // IS_FFMPEG_3_2 /* if zero size, it means the image was buffered */ @@ -2103,10 +2033,6 @@ bool FFmpegWriter::write_video_packet(std::shared_ptr frame, AVFrame *fra } } - // Deallocate memory (if needed) - if (video_outbuf) - delete[] video_outbuf; - // Deallocate packet AV_FREE_PACKET(&pkt); #if HAVE_HW_ACCEL From 92ebd15545c52622dd060d8f693209ac058cd5b6 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Thu, 5 Mar 2020 01:38:25 -0500 Subject: [PATCH 11/30] FFmpegWriter: Code reformatting --- src/FFmpegWriter.cpp | 109 +++++++++++++++++++++++++++++-------------- 1 file changed, 75 insertions(+), 34 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 245b0108..e8e9542c 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -255,10 +255,14 @@ void FFmpegWriter::SetVideoOptions(bool has_video, std::string codec, Fraction f info.pixel_ratio.num = pixel_ratio.num; info.pixel_ratio.den = pixel_ratio.den; } - if (bit_rate >= 1000) // bit_rate is the bitrate in b/s + if (bit_rate >= 1000) { + // bit_rate is the bitrate in b/s info.video_bit_rate = bit_rate; - if ((bit_rate >= 0) && (bit_rate < 64)) // bit_rate is the bitrate in crf + } + if ((bit_rate >= 0) && (bit_rate < 64)) { + // bit_rate is the bitrate in crf info.video_bit_rate = bit_rate; + } info.interlaced_frame = interlaced; info.top_field_first = top_field_first; @@ -282,8 +286,10 @@ void FFmpegWriter::SetVideoOptions(bool has_video, std::string codec, Fraction f // Set video export options (overloaded function) void FFmpegWriter::SetVideoOptions(std::string codec, int width, int height, Fraction fps, int bit_rate) { // Call full signature with some default parameters - FFmpegWriter::SetVideoOptions(true, codec, fps, width, height, - openshot::Fraction(1, 1), false, true, bit_rate); + FFmpegWriter::SetVideoOptions( + true, codec, fps, width, height, + openshot::Fraction(1, 1), false, true, bit_rate + ); } @@ -326,8 +332,10 @@ void FFmpegWriter::SetAudioOptions(bool has_audio, std::string codec, int sample // Set audio export options (overloaded function) void FFmpegWriter::SetAudioOptions(std::string codec, int sample_rate, int bit_rate) { // Call full signature with some default parameters - FFmpegWriter::SetAudioOptions(true, codec, sample_rate, 2, - openshot::LAYOUT_STEREO, bit_rate); + FFmpegWriter::SetAudioOptions( + true, codec, sample_rate, 2, + openshot::LAYOUT_STEREO, bit_rate + ); } @@ -418,6 +426,7 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va { switch (c->codec_id) { #if (LIBAVCODEC_VERSION_MAJOR >= 58) + // FFmpeg 4.0+ case AV_CODEC_ID_AV1 : c->bit_rate = 0; av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),63), 0); // 0-63 @@ -475,6 +484,7 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va { switch (c->codec_id) { #if (LIBAVCODEC_VERSION_MAJOR >= 58) + // FFmpeg 4.0+ case AV_CODEC_ID_AV1 : c->bit_rate = 0; av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); @@ -1570,20 +1580,25 @@ void FFmpegWriter::write_audio_packets(bool is_final) { int nb_samples = 0; // Convert audio samples - nb_samples = SWR_CONVERT(avr, // audio resample context - audio_converted->data, // output data pointers - audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown) - audio_converted->nb_samples, // maximum number of samples that the output buffer can hold - audio_frame->data, // input data pointers - audio_frame->linesize[0], // input plane size, in bytes (0 if unknown) - audio_frame->nb_samples); // number of input samples to convert + nb_samples = SWR_CONVERT( + avr, // audio resample context + audio_converted->data, // output data pointers + audio_converted->linesize[0], // output plane size, in bytes. (0 if unknown) + audio_converted->nb_samples, // maximum number of samples that the output buffer can hold + audio_frame->data, // input data pointers + audio_frame->linesize[0], // input plane size, in bytes (0 if unknown) + audio_frame->nb_samples // number of input samples to convert + ); // Set remaining samples remaining_frame_samples = nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16); // Create a new array (to hold all resampled S16 audio samples) all_resampled_samples = (int16_t *) av_malloc( - sizeof(int16_t) * nb_samples * info.channels * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))); + sizeof(int16_t) * nb_samples * info.channels + * (av_get_bytes_per_sample(output_sample_fmt) / + av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) ) + ); // Copy audio samples over original samples memcpy(all_resampled_samples, audio_converted->data[0], nb_samples * info.channels * av_get_bytes_per_sample(output_sample_fmt)); @@ -1613,8 +1628,14 @@ void FFmpegWriter::write_audio_packets(bool is_final) { // Copy frame samples into the packet samples array if (!is_final) //TODO: Make this more sane - memcpy(samples + (audio_input_position * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))), - all_resampled_samples + samples_position, diff * av_get_bytes_per_sample(output_sample_fmt)); + memcpy( + samples + (audio_input_position + * (av_get_bytes_per_sample(output_sample_fmt) / + av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) ) + ), + all_resampled_samples + samples_position, + diff * av_get_bytes_per_sample(output_sample_fmt) + ); // Increment counters audio_input_position += diff; @@ -1631,7 +1652,14 @@ void FFmpegWriter::write_audio_packets(bool is_final) { AVFrame *frame_final = AV_ALLOCATE_FRAME(); AV_RESET_FRAME(frame_final); if (av_sample_fmt_is_planar(audio_codec->sample_fmt)) { - ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)", "in_sample_fmt", output_sample_fmt, "out_sample_fmt", audio_codec->sample_fmt, "in_sample_rate", info.sample_rate, "out_sample_rate", info.sample_rate, "in_channels", info.channels, "out_channels", info.channels); + ZmqLogger::Instance()->AppendDebugMethod("FFmpegWriter::write_audio_packets (2nd resampling for Planar formats)", + "in_sample_fmt", output_sample_fmt, + "out_sample_fmt", audio_codec->sample_fmt, + "in_sample_rate", info.sample_rate, + "out_sample_rate", info.sample_rate, + "in_channels", info.channels, + "out_channels", info.channels + ); // setup resample context if (!avr_planar) { @@ -1654,31 +1682,38 @@ void FFmpegWriter::write_audio_packets(bool is_final) { // Create a new array final_samples_planar = (int16_t *) av_malloc( - sizeof(int16_t) * audio_frame->nb_samples * info.channels * (av_get_bytes_per_sample(output_sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))); + sizeof(int16_t) * audio_frame->nb_samples * info.channels + * (av_get_bytes_per_sample(output_sample_fmt) / + av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) ) + ); // Copy audio into buffer for frame memcpy(final_samples_planar, samples, audio_frame->nb_samples * info.channels * av_get_bytes_per_sample(output_sample_fmt)); // Fill input frame with sample data - avcodec_fill_audio_frame(audio_frame, info.channels, output_sample_fmt, (uint8_t *) final_samples_planar, - audio_encoder_buffer_size, 0); + avcodec_fill_audio_frame(audio_frame, info.channels, output_sample_fmt, + (uint8_t *) final_samples_planar, audio_encoder_buffer_size, 0); // Create output frame (and allocate arrays) frame_final->nb_samples = audio_input_frame_size; - av_samples_alloc(frame_final->data, frame_final->linesize, info.channels, frame_final->nb_samples, audio_codec->sample_fmt, 0); + av_samples_alloc(frame_final->data, frame_final->linesize, info.channels, + frame_final->nb_samples, audio_codec->sample_fmt, 0); // Convert audio samples - int nb_samples = SWR_CONVERT(avr_planar, // audio resample context - frame_final->data, // output data pointers - frame_final->linesize[0], // output plane size, in bytes. (0 if unknown) - frame_final->nb_samples, // maximum number of samples that the output buffer can hold - audio_frame->data, // input data pointers - audio_frame->linesize[0], // input plane size, in bytes (0 if unknown) - audio_frame->nb_samples); // number of input samples to convert + int nb_samples = SWR_CONVERT( + avr_planar, // audio resample context + frame_final->data, // output data pointers + frame_final->linesize[0], // output plane size, in bytes. (0 if unknown) + frame_final->nb_samples, // maximum number of samples that the output buffer can hold + audio_frame->data, // input data pointers + audio_frame->linesize[0], // input plane size, in bytes (0 if unknown) + audio_frame->nb_samples // number of input samples to convert + ); // Copy audio samples over original samples if (nb_samples > 0) - memcpy(samples, frame_final->data[0], nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) * info.channels); + memcpy(samples, frame_final->data[0], + nb_samples * av_get_bytes_per_sample(audio_codec->sample_fmt) * info.channels); // deallocate AVFrame av_freep(&(audio_frame->data[0])); @@ -1690,7 +1725,10 @@ void FFmpegWriter::write_audio_packets(bool is_final) { } else { // Create a new array final_samples = (int16_t *) av_malloc( - sizeof(int16_t) * audio_input_position * (av_get_bytes_per_sample(audio_codec->sample_fmt) / av_get_bytes_per_sample(AV_SAMPLE_FMT_S16))); + sizeof(int16_t) * audio_input_position + * (av_get_bytes_per_sample(audio_codec->sample_fmt) / + av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) ) + ); // Copy audio into buffer for frame memcpy(final_samples, samples, audio_input_position * av_get_bytes_per_sample(audio_codec->sample_fmt)); @@ -1699,8 +1737,8 @@ void FFmpegWriter::write_audio_packets(bool is_final) { frame_final->nb_samples = audio_input_frame_size; // Fill the final_frame AVFrame with audio (non planar) - avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, (uint8_t *) final_samples, - audio_encoder_buffer_size, 0); + avcodec_fill_audio_frame(frame_final, audio_codec->channels, audio_codec->sample_fmt, + (uint8_t *) final_samples, audio_encoder_buffer_size, 0); } // Increment PTS (in samples) @@ -1872,7 +1910,10 @@ void FFmpegWriter::process_video_packet(std::shared_ptr frame) { } else #endif // HAVE_HW_ACCEL { - frame_final = allocate_avframe((AVPixelFormat)(video_st->codecpar->format), info.width, info.height, &bytes_final, NULL); + 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); @@ -1884,7 +1925,7 @@ void FFmpegWriter::process_video_packet(std::shared_ptr frame) { // Resize & convert pixel format sws_scale(scaler, frame_source->data, frame_source->linesize, 0, - source_image_height, frame_final->data, frame_final->linesize); + source_image_height, frame_final->data, frame_final->linesize); // Add resized AVFrame to av_frames map #pragma omp critical (av_frames_section) From 8c8b535cc9e83e873c5da1092cc4d6cd31d03c19 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 27 Mar 2020 16:28:43 -0400 Subject: [PATCH 12/30] Fix Win64 Gitlab builds --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6b2645d8..925bf020 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -72,7 +72,6 @@ windows-builder-x64: - cd build - cmake -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -D"CMAKE_INSTALL_PREFIX:PATH=$CI_PROJECT_DIR\build\install-x64" -D"PYTHON_MODULE_PATH=python" -D"RUBY_MODULE_PATH=ruby" -G "MSYS Makefiles" -DCMAKE_MAKE_PROGRAM=mingw32-make -D"CMAKE_BUILD_TYPE:STRING=Release" ../ - mingw32-make install - - Move-Item -Force -path "install-x64\lib\python3.7\site-packages\*openshot*" -destination "install-x64\python\" - New-Item -path "install-x64/share/" -Name "$CI_PROJECT_NAME" -Value "CI_PROJECT_NAME:$CI_PROJECT_NAME`nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME`nCI_COMMIT_SHA:$CI_COMMIT_SHA`nCI_JOB_ID:$CI_JOB_ID" -ItemType file -force - $PREV_GIT_LABEL=(git describe --tags --abbrev=0 '@^') - git log "$PREV_GIT_LABEL..@" --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "install-x64/share/$CI_PROJECT_NAME.log" From ff5095c64d061df1041d2ae5242a2f7dd007c956 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 27 Mar 2020 17:30:42 -0400 Subject: [PATCH 13/30] Update release-log formatting on builders --- .gitlab-ci.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 925bf020..87de2e16 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -2,6 +2,9 @@ stages: - build-libopenshot - trigger-openshot-qt +variables: + GIT_LOG_FORMAT: "- %h %ad %s [%aN]" + linux-builder: stage: build-libopenshot artifacts: @@ -22,7 +25,7 @@ linux-builder: - make doc - ~/auto-update-docs "$CI_PROJECT_DIR/build" "$CI_COMMIT_REF_NAME" - echo -e "CI_PROJECT_NAME:$CI_PROJECT_NAME\nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME\nCI_COMMIT_SHA:$CI_COMMIT_SHA\nCI_JOB_ID:$CI_JOB_ID" > "install-x64/share/$CI_PROJECT_NAME" - - git log $(git describe --tags --abbrev=0 @^)..@ --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "install-x64/share/$CI_PROJECT_NAME.log" + - git log $(git describe --tags --abbrev=0 '@^')..@ --oneline --date=short --no-merges --pretty="tformat:$GIT_LOG_FORMAT" > "install-x64/share/$CI_PROJECT_NAME.log" when: always except: - tags @@ -47,7 +50,7 @@ mac-builder: - make - make install - echo -e "CI_PROJECT_NAME:$CI_PROJECT_NAME\nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME\nCI_COMMIT_SHA:$CI_COMMIT_SHA\nCI_JOB_ID:$CI_JOB_ID" > "install-x64/share/$CI_PROJECT_NAME" - - git log $(git describe --tags --abbrev=0 @^)..@ --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "install-x64/share/$CI_PROJECT_NAME.log" + - git log $(git describe --tags --abbrev=0 '@^')..@ --oneline --date=short --no-merges --pretty="tformat:$GIT_LOG_FORMAT" > "install-x64/share/$CI_PROJECT_NAME.log" when: always except: - tags @@ -74,7 +77,7 @@ windows-builder-x64: - mingw32-make install - New-Item -path "install-x64/share/" -Name "$CI_PROJECT_NAME" -Value "CI_PROJECT_NAME:$CI_PROJECT_NAME`nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME`nCI_COMMIT_SHA:$CI_COMMIT_SHA`nCI_JOB_ID:$CI_JOB_ID" -ItemType file -force - $PREV_GIT_LABEL=(git describe --tags --abbrev=0 '@^') - - git log "$PREV_GIT_LABEL..@" --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "install-x64/share/$CI_PROJECT_NAME.log" + - git log "$PREV_GIT_LABEL..@" --oneline --date=short --no-merges --pretty="tformat:$GIT_LOG_FORMAT" > "install-x64/share/$CI_PROJECT_NAME.log" when: always except: - tags @@ -101,7 +104,7 @@ windows-builder-x86: - mingw32-make install - New-Item -path "install-x86/share/" -Name "$CI_PROJECT_NAME" -Value "CI_PROJECT_NAME:$CI_PROJECT_NAME`nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME`nCI_COMMIT_SHA:$CI_COMMIT_SHA`nCI_JOB_ID:$CI_JOB_ID" -ItemType file -force - $PREV_GIT_LABEL=(git describe --tags --abbrev=0 '@^') - - git log "$PREV_GIT_LABEL..@" --oneline --pretty=format:"%C(auto,yellow)%h%C(auto,magenta)% %C(auto,blue)%>(12,trunc)%ad %C(auto,green)%<(25,trunc)%aN%C(auto,reset)%s%C(auto,red)% gD% D" --date=short > "install-x86/share/$CI_PROJECT_NAME.log" + - git log "$PREV_GIT_LABEL..@" --oneline --date=short --no-merges --pretty="tformat:$GIT_LOG_FORMAT" > "install-x86/share/$CI_PROJECT_NAME.log" when: always except: - tags From 7a91ca1d866216e0086d46a430d5666c5525c620 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 8 Jun 2020 15:58:17 -0400 Subject: [PATCH 14/30] FFmpegWriter: Remove unreachable branch --- src/FFmpegWriter.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index e6a7e5ef..3366ac5f 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -552,7 +552,7 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va } else if (strstr(info.vcodec.c_str(), "rav1e") != NULL) { // Set number of tiles to a fixed value - // TODO Let user choose number of tiles + // TODO Let user choose number of tiles av_opt_set_int(c->priv_data, "qp", std::min(std::stoi(value),255), 0); av_opt_set_int(c->priv_data, "speed", 7, 0); av_opt_set_int(c->priv_data, "tile-rows", 2, 0); // number of rows @@ -560,7 +560,7 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va } else if (strstr(info.vcodec.c_str(), "aom") != NULL) { // Set number of tiles to a fixed value - // TODO Let user choose number of tiles + // TODO Let user choose number of tiles // libaom doesn't have qp only crf av_opt_set_int(c->priv_data, "crf", std::min(std::stoi(value),63), 0); av_opt_set_int(c->priv_data, "tile-rows", 1, 0); // log2 of number of rows @@ -691,15 +691,8 @@ void FFmpegWriter::WriteFrame(std::shared_ptr frame) { // Write the frames once it reaches the correct cache size if ((int)spooled_video_frames.size() == cache_size || (int)spooled_audio_frames.size() == cache_size) { - // Is writer currently writing? - if (!is_writing) - // Write frames to video file - write_queued_frames(); - - else { - // Write frames to video file - write_queued_frames(); - } + // Write frames to video file + write_queued_frames(); } // Keep track of the last frame added From c57f8ede3b54776b399b6671f284f7946df757fc Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 8 Jun 2020 16:02:02 -0400 Subject: [PATCH 15/30] FFmpeg: Combine 2 constructors via a default arg, fix docs, const refs --- include/FFmpegReader.h | 15 +++++++-------- include/FFmpegWriter.h | 6 ++++-- src/FFmpegReader.cpp | 23 +---------------------- src/FFmpegWriter.cpp | 2 +- 4 files changed, 13 insertions(+), 33 deletions(-) diff --git a/include/FFmpegReader.h b/include/FFmpegReader.h index ec082965..35e11a42 100644 --- a/include/FFmpegReader.h +++ b/include/FFmpegReader.h @@ -233,14 +233,13 @@ namespace openshot { /// codecs have trouble seeking, and can introduce artifacts or blank images into the video. bool enable_seek; - /// Constructor for FFmpegReader. This automatically opens the media file and loads - /// frame 1, or it throws one of the following exceptions. - FFmpegReader(std::string path); - - /// Constructor for FFmpegReader. This only opens the media file to inspect its properties - /// if inspect_reader=true. When not inspecting the media file, it's much faster, and useful - /// when you are inflating the object using JSON after instantiating it. - FFmpegReader(std::string path, bool inspect_reader); + /// @brief Constructor for FFmpegReader. + /// + /// Sets (and possibly opens) the media file path, + /// or throws an exception. + /// @param path The filesystem location to load + /// @param inspect_reader if true (the default), automatically open the media file and loads frame 1. + FFmpegReader(const std::string& path, bool inspect_reader=true); /// Destructor virtual ~FFmpegReader(); diff --git a/include/FFmpegWriter.h b/include/FFmpegWriter.h index 37fa22dc..f2e28d00 100644 --- a/include/FFmpegWriter.h +++ b/include/FFmpegWriter.h @@ -251,9 +251,11 @@ namespace openshot { public: - /// @brief Constructor for FFmpegWriter. Throws one of the following exceptions. + /// @brief Constructor for FFmpegWriter. + /// Throws an exception on failure to open path. + /// /// @param path The file path of the video file you want to open and read - FFmpegWriter(std::string path); + FFmpegWriter(const std::string& path); /// Close the writer void Close(); diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index c8ce141f..12b9776a 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -83,7 +83,7 @@ int hw_de_on = 0; AVHWDeviceType hw_de_av_device_type_global = AV_HWDEVICE_TYPE_NONE; #endif -FFmpegReader::FFmpegReader(std::string path) +FFmpegReader::FFmpegReader(const std::string& path, bool inspect_reader) : last_frame(0), is_seeking(0), seeking_pts(0), seeking_frame(0), seek_count(0), audio_pts_offset(99999), video_pts_offset(99999), path(path), is_video_seek(true), check_interlace(false), check_fps(false), enable_seek(true), is_open(false), seek_audio_frame_found(0), seek_video_frame_found(0), @@ -91,27 +91,6 @@ FFmpegReader::FFmpegReader(std::string path) current_video_frame(0), has_missing_frames(false), num_packets_since_video_frame(0), num_checks_since_final(0), packet(NULL) { - // Initialize FFMpeg, and register all formats and codecs - AV_REGISTER_ALL - AVCODEC_REGISTER_ALL - - // Init cache - working_cache.SetMaxBytesFromInfo(OPEN_MP_NUM_PROCESSORS * info.fps.ToDouble() * 2, info.width, info.height, info.sample_rate, info.channels); - missing_frames.SetMaxBytesFromInfo(OPEN_MP_NUM_PROCESSORS * 2, info.width, info.height, info.sample_rate, info.channels); - final_cache.SetMaxBytesFromInfo(OPEN_MP_NUM_PROCESSORS * 2, info.width, info.height, info.sample_rate, info.channels); - - // Open and Close the reader, to populate its attributes (such as height, width, etc...) - Open(); - Close(); -} - -FFmpegReader::FFmpegReader(std::string path, bool inspect_reader) - : last_frame(0), is_seeking(0), seeking_pts(0), seeking_frame(0), seek_count(0), - audio_pts_offset(99999), video_pts_offset(99999), path(path), is_video_seek(true), check_interlace(false), - check_fps(false), enable_seek(true), is_open(false), seek_audio_frame_found(0), seek_video_frame_found(0), - prev_samples(0), prev_pts(0), pts_total(0), pts_counter(0), is_duration_known(false), largest_frame_processed(0), - current_video_frame(0), has_missing_frames(false), num_packets_since_video_frame(0), num_checks_since_final(0), - packet(NULL) { // Initialize FFMpeg, and register all formats and codecs AV_REGISTER_ALL diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 3366ac5f..eff2507e 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -83,7 +83,7 @@ static int set_hwframe_ctx(AVCodecContext *ctx, AVBufferRef *hw_device_ctx, int6 } #endif // HAVE_HW_ACCEL -FFmpegWriter::FFmpegWriter(std::string path) : +FFmpegWriter::FFmpegWriter(const std::string& path) : path(path), fmt(NULL), oc(NULL), audio_st(NULL), video_st(NULL), samples(NULL), audio_outbuf(NULL), audio_outbuf_size(0), audio_input_frame_size(0), audio_input_position(0), initial_audio_input_frame_size(0), img_convert_ctx(NULL), cache_size(8), num_of_rescalers(32), From 96d84311c68a3fee3e982ca51fd2951bf5bc4c2a Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 8 Jun 2020 16:07:04 -0400 Subject: [PATCH 16/30] OpenMP: Move off deprecated allow_nested boolean - Replacement openmp_set_max_active_levels() takes an int argument - In OpenMP 5.0 it can be set to openmp_get_supported_active_levels() - Below 5.0, we just set it to our processor count - Move configuration of OpenMP from ad-hoc locations to constructors for FFmpegWriter/Reader and Timeline --- include/OpenMPUtilities.h | 7 +++++++ src/FFmpegReader.cpp | 10 +++++----- src/FFmpegWriter.cpp | 11 ++++++----- src/Timeline.cpp | 18 +++++++++++++----- 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/include/OpenMPUtilities.h b/include/OpenMPUtilities.h index 9810d636..5b5107c1 100644 --- a/include/OpenMPUtilities.h +++ b/include/OpenMPUtilities.h @@ -41,5 +41,12 @@ #define OPEN_MP_NUM_PROCESSORS (std::min(omp_get_num_procs(), std::max(2, openshot::Settings::Instance()->OMP_THREADS) )) #define FF_NUM_PROCESSORS (std::min(omp_get_num_procs(), std::max(2, openshot::Settings::Instance()->FF_THREADS) )) +// Set max-active-levels to the max supported, if possible +// (supported_active_levels is OpenMP 5.0 (November 2018) or later, only.) +#if (_OPENMP >= 201811) + #define OPEN_MP_MAX_ACTIVE openmp_get_supported_active_levels() +#else + #define OPEN_MP_MAX_ACTIVE OPEN_MP_NUM_PROCESSORS +#endif #endif diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 12b9776a..fea4f60b 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -91,6 +91,11 @@ FFmpegReader::FFmpegReader(const std::string& path, bool inspect_reader) current_video_frame(0), has_missing_frames(false), num_packets_since_video_frame(0), num_checks_since_final(0), packet(NULL) { + // Configure OpenMP parallelism + // Default number of threads per section + omp_set_num_threads(OPEN_MP_NUM_PROCESSORS); + // Allow nested parallel sections as deeply as supported + omp_set_max_active_levels(OPEN_MP_MAX_ACTIVE); // Initialize FFMpeg, and register all formats and codecs AV_REGISTER_ALL @@ -877,11 +882,6 @@ std::shared_ptr FFmpegReader::ReadStream(int64_t requested_frame) { int minimum_packets = OPEN_MP_NUM_PROCESSORS; int max_packets = 4096; - // Set the number of threads in OpenMP - omp_set_num_threads(OPEN_MP_NUM_PROCESSORS); - // Allow nested OpenMP sections - omp_set_nested(true); - // Debug output ZmqLogger::Instance()->AppendDebugMethod("FFmpegReader::ReadStream", "requested_frame", requested_frame, "OPEN_MP_NUM_PROCESSORS", OPEN_MP_NUM_PROCESSORS); diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index eff2507e..39a3768f 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -95,6 +95,12 @@ FFmpegWriter::FFmpegWriter(const std::string& path) : info.has_audio = false; info.has_video = false; + // Configure OpenMP parallelism + // Default number of threads per block + omp_set_num_threads(OPEN_MP_NUM_PROCESSORS); + // Allow nested parallel sections as deeply as supported + omp_set_max_active_levels(OPEN_MP_MAX_ACTIVE); + // Initialize FFMpeg, and register all formats and codecs AV_REGISTER_ALL @@ -714,11 +720,6 @@ void FFmpegWriter::write_queued_frames() { spooled_video_frames.clear(); spooled_audio_frames.clear(); - // Set the number of threads in OpenMP - omp_set_num_threads(OPEN_MP_NUM_PROCESSORS); - // Allow nested OpenMP sections - omp_set_nested(true); - // Create blank exception bool has_error_encoding_video = false; diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 124058ac..89f0992c 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -67,7 +67,13 @@ Timeline::Timeline(int width, int height, Fraction fps, int sample_rate, int cha info.acodec = "openshot::timeline"; info.vcodec = "openshot::timeline"; - // Init max image size + // Configure OpenMP parallelism + // Default number of threads per block + omp_set_num_threads(OPEN_MP_NUM_PROCESSORS); + // Allow nested parallel sections as deeply as supported + omp_set_max_active_levels(OPEN_MP_MAX_ACTIVE); + + // Init max image size SetMaxSize(info.width, info.height); // Init cache @@ -194,6 +200,12 @@ Timeline::Timeline(std::string projectPath, bool convert_absolute_paths) : info.has_video = true; info.has_audio = true; + // Configure OpenMP parallelism + // Default number of threads per section + omp_set_num_threads(OPEN_MP_NUM_PROCESSORS); + // Allow nested parallel sections as deeply as supported + omp_set_max_active_levels(OPEN_MP_MAX_ACTIVE); + // Init max image size SetMaxSize(info.width, info.height); @@ -892,10 +904,6 @@ std::shared_ptr Timeline::GetFrame(int64_t requested_frame) #pragma omp critical (T_GetFrame) nearby_clips = find_intersecting_clips(requested_frame, minimum_frames, true); - omp_set_num_threads(OPEN_MP_NUM_PROCESSORS); - // Allow nested OpenMP sections - omp_set_nested(true); - // Debug output ZmqLogger::Instance()->AppendDebugMethod("Timeline::GetFrame", "requested_frame", requested_frame, "minimum_frames", minimum_frames, "OPEN_MP_NUM_PROCESSORS", OPEN_MP_NUM_PROCESSORS); From 3f13ed87f0e18e636376be67847f9993670c0302 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Mon, 8 Jun 2020 16:07:55 -0400 Subject: [PATCH 17/30] Timeline: const-ref path arg in constructor, docs --- include/Timeline.h | 22 +++++++++++++--------- src/Timeline.cpp | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/include/Timeline.h b/include/Timeline.h index 932b04ac..32eac6be 100644 --- a/include/Timeline.h +++ b/include/Timeline.h @@ -202,19 +202,23 @@ namespace openshot { public: - /// @brief Default Constructor for the timeline (which sets the canvas width and height and FPS) - /// @param width The width of the timeline (and thus, the generated openshot::Frame objects) - /// @param height The height of the timeline (and thus, the generated openshot::Frame objects) - /// @param fps The frames rate of the timeline - /// @param sample_rate The sample rate of the timeline's audio - /// @param channels The number of audio channels of the timeline + /// @brief Default Constructor for the timeline (which configures the default frame properties) + /// @param width The image width of generated openshot::Frame objects + /// @param height The image height of generated openshot::Frame objects + /// @param fps The frame rate of the generated video + /// @param sample_rate The audio sample rate + /// @param channels The number of audio channels /// @param channel_layout The channel layout (i.e. mono, stereo, 3 point surround, etc...) Timeline(int width, int height, Fraction fps, int sample_rate, int channels, ChannelLayout channel_layout); - /// @brief Constructor for the timeline (which loads a JSON structure from a file path, and initializes a timeline) + /// @brief Project-file constructor for the timeline + /// + /// Loads a JSON structure from a file path, and + /// initializes the timeline described within. + /// /// @param projectPath The path of the UTF-8 *.osp project file (JSON contents). Contents will be loaded automatically. - /// @param convert_absolute_paths Should all paths be converted to absolute paths (based on the folder of the path provided) - Timeline(std::string projectPath, bool convert_absolute_paths); + /// @param convert_absolute_paths Should all paths be converted to absolute paths (relative to the location of projectPath) + Timeline(const std::string& projectPath, bool convert_absolute_paths); virtual ~Timeline(); diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 89f0992c..bbbc6858 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -82,7 +82,7 @@ Timeline::Timeline(int width, int height, Fraction fps, int sample_rate, int cha } // Constructor for the timeline (which loads a JSON structure from a file path, and initializes a timeline) -Timeline::Timeline(std::string projectPath, bool convert_absolute_paths) : +Timeline::Timeline(const std::string& projectPath, bool convert_absolute_paths) : is_open(false), auto_map_clips(true), managed_cache(true), path(projectPath) { // Create CrashHandler and Attach (incase of errors) From 56736e9505530a4ed5f88da92f803703ddd7aed8 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Tue, 16 Jun 2020 10:22:52 -0700 Subject: [PATCH 18/30] Set the field order when interlace is on --- src/FFmpegWriter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index d960d677..643eb854 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -340,6 +340,12 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va st = video_st; // Get codec context c = AV_GET_CODEC_PAR_CONTEXT(st, video_codec); + // Was a codec / stream found? + if (c) { + if (info.interlaced_frame) { + c->field_order = info.top_field_first ? AV_FIELD_TT : AV_FIELD_BB; + } + } } else if (info.has_audio && stream == AUDIO_STREAM && audio_st) { st = audio_st; // Get codec context From f69aa41127fa03b3804007825b86328eb85b1134 Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Wed, 8 Jul 2020 17:11:47 -0700 Subject: [PATCH 19/30] Add some comment --- src/FFmpegWriter.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 643eb854..6e300bf1 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -344,6 +344,8 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va if (c) { if (info.interlaced_frame) { c->field_order = info.top_field_first ? AV_FIELD_TT : AV_FIELD_BB; + // We only use these two version and ignore AV_FIELD_TB and AV_FIELD_BT + // Otherwise we would need to change the whole export window } } } else if (info.has_audio && stream == AUDIO_STREAM && audio_st) { From 8e6c73449e3450cb6c70d5dd22c9f16c6109bc16 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Fri, 7 Aug 2020 07:46:26 -0400 Subject: [PATCH 20/30] "Ensure full 40-character hashes in changelog" --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 87de2e16..25fcb43a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,7 +25,7 @@ linux-builder: - make doc - ~/auto-update-docs "$CI_PROJECT_DIR/build" "$CI_COMMIT_REF_NAME" - echo -e "CI_PROJECT_NAME:$CI_PROJECT_NAME\nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME\nCI_COMMIT_SHA:$CI_COMMIT_SHA\nCI_JOB_ID:$CI_JOB_ID" > "install-x64/share/$CI_PROJECT_NAME" - - git log $(git describe --tags --abbrev=0 '@^')..@ --oneline --date=short --no-merges --pretty="tformat:$GIT_LOG_FORMAT" > "install-x64/share/$CI_PROJECT_NAME.log" + - git log $(git describe --tags --abbrev=0 '@^')..@ --oneline --no-abbrev --date=short --no-merges --pretty="tformat:$GIT_LOG_FORMAT" > "install-x64/share/$CI_PROJECT_NAME.log" when: always except: - tags @@ -50,7 +50,7 @@ mac-builder: - make - make install - echo -e "CI_PROJECT_NAME:$CI_PROJECT_NAME\nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME\nCI_COMMIT_SHA:$CI_COMMIT_SHA\nCI_JOB_ID:$CI_JOB_ID" > "install-x64/share/$CI_PROJECT_NAME" - - git log $(git describe --tags --abbrev=0 '@^')..@ --oneline --date=short --no-merges --pretty="tformat:$GIT_LOG_FORMAT" > "install-x64/share/$CI_PROJECT_NAME.log" + - git log $(git describe --tags --abbrev=0 '@^')..@ --oneline --no-abbrev --date=short --no-merges --pretty="tformat:$GIT_LOG_FORMAT" > "install-x64/share/$CI_PROJECT_NAME.log" when: always except: - tags @@ -77,7 +77,7 @@ windows-builder-x64: - mingw32-make install - New-Item -path "install-x64/share/" -Name "$CI_PROJECT_NAME" -Value "CI_PROJECT_NAME:$CI_PROJECT_NAME`nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME`nCI_COMMIT_SHA:$CI_COMMIT_SHA`nCI_JOB_ID:$CI_JOB_ID" -ItemType file -force - $PREV_GIT_LABEL=(git describe --tags --abbrev=0 '@^') - - git log "$PREV_GIT_LABEL..@" --oneline --date=short --no-merges --pretty="tformat:$GIT_LOG_FORMAT" > "install-x64/share/$CI_PROJECT_NAME.log" + - git log "$PREV_GIT_LABEL..@" --oneline --no-abbrev --date=short --no-merges --pretty="tformat:$GIT_LOG_FORMAT" > "install-x64/share/$CI_PROJECT_NAME.log" when: always except: - tags @@ -104,7 +104,7 @@ windows-builder-x86: - mingw32-make install - New-Item -path "install-x86/share/" -Name "$CI_PROJECT_NAME" -Value "CI_PROJECT_NAME:$CI_PROJECT_NAME`nCI_COMMIT_REF_NAME:$CI_COMMIT_REF_NAME`nCI_COMMIT_SHA:$CI_COMMIT_SHA`nCI_JOB_ID:$CI_JOB_ID" -ItemType file -force - $PREV_GIT_LABEL=(git describe --tags --abbrev=0 '@^') - - git log "$PREV_GIT_LABEL..@" --oneline --date=short --no-merges --pretty="tformat:$GIT_LOG_FORMAT" > "install-x86/share/$CI_PROJECT_NAME.log" + - git log "$PREV_GIT_LABEL..@" --oneline --no-abbrev --date=short --no-merges --pretty="tformat:$GIT_LOG_FORMAT" > "install-x86/share/$CI_PROJECT_NAME.log" when: always except: - tags From 3c2532b4deb51fee22338f70c094a5f058bf9c7f Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Thu, 20 Aug 2020 16:50:12 -0400 Subject: [PATCH 21/30] Use std::make_shared to allocate shared ptrs std::make_shared does in a single allocation what the constructors for std::shared_ptr usually take at least 2 allocations to do. May give us an infinitesimal performance/memory improvement. https://www.modernescpp.com/index.php/memory-and-performance-overhead-of-smart-pointer --- include/DummyReader.h | 2 +- include/Frame.h | 2 +- src/CacheDisk.cpp | 6 +-- src/ChunkWriter.cpp | 4 +- src/Clip.cpp | 7 +++- src/DecklinkInput.cpp | 8 ++-- src/DecklinkWriter.cpp | 2 +- src/FFmpegReader.cpp | 6 +-- src/Frame.cpp | 84 +++++++++++++++++++++++-------------- src/FrameMapper.cpp | 8 ++-- src/ImageReader.cpp | 6 ++- src/QtHtmlReader.cpp | 9 ++-- src/QtImageReader.cpp | 23 ++++++---- src/QtTextReader.cpp | 8 ++-- src/TextReader.cpp | 11 +++-- src/effects/Bars.cpp | 3 +- src/effects/Crop.cpp | 3 +- src/effects/Deinterlace.cpp | 4 +- src/effects/Mask.cpp | 11 ++--- 19 files changed, 129 insertions(+), 78 deletions(-) diff --git a/include/DummyReader.h b/include/DummyReader.h index 9a75751d..af06656d 100644 --- a/include/DummyReader.h +++ b/include/DummyReader.h @@ -69,7 +69,7 @@ namespace openshot * // Create blank frame (with specific frame #, samples, and channels) * // Sample count should be 44100 / 30 fps = 1470 samples per frame * int sample_count = 1470; - * std::shared_ptr f(new openshot::Frame(frame_number, sample_count, 2)); + * auto f = std::make_shared(frame_number, sample_count, 2); * * // Create test samples with incrementing value * float *audio_buffer = new float[sample_count]; diff --git a/include/Frame.h b/include/Frame.h index f4ff54d4..7e7866c0 100644 --- a/include/Frame.h +++ b/include/Frame.h @@ -99,7 +99,7 @@ namespace openshot * ); * * // Some methods require a shared pointer to an openshot::Frame object. - * std::shared_ptr f(new Frame(1, 720, 480, "#000000", 44100, 2)); + * auto f = std::make_shared(1, 720, 480, "#000000", 44100, 2); * * @endcode */ diff --git a/src/CacheDisk.cpp b/src/CacheDisk.cpp index bb2e12c4..409d8c4e 100644 --- a/src/CacheDisk.cpp +++ b/src/CacheDisk.cpp @@ -227,14 +227,14 @@ std::shared_ptr CacheDisk::GetFrame(int64_t frame_number) if (path.exists(frame_path)) { // Load image file - std::shared_ptr image = std::shared_ptr(new QImage()); + auto image = std::make_shared(); image->load(frame_path); // Set pixel formatimage-> - image = std::shared_ptr(new QImage(image->convertToFormat(QImage::Format_RGBA8888))); + image = std::make_shared(image->convertToFormat(QImage::Format_RGBA8888)); // Create frame object - std::shared_ptr frame(new Frame()); + auto frame = std::make_shared(); frame->number = frame_number; frame->AddImage(image); diff --git a/src/ChunkWriter.cpp b/src/ChunkWriter.cpp index f9d653b0..c7752cd5 100644 --- a/src/ChunkWriter.cpp +++ b/src/ChunkWriter.cpp @@ -134,7 +134,9 @@ void ChunkWriter::WriteFrame(std::shared_ptr frame) writer_thumb->WriteFrame(last_frame); } else { // Write the 1st frame (of the 1st chunk)... since no previous chunk is available - std::shared_ptr blank_frame(new Frame(1, info.width, info.height, "#000000", info.sample_rate, info.channels)); + auto blank_frame = std::make_shared( + 1, info.width, info.height, "#000000", + info.sample_rate, info.channels); blank_frame->AddColor(info.width, info.height, "#000000"); writer_final->WriteFrame(blank_frame); writer_preview->WriteFrame(blank_frame); diff --git a/src/Clip.cpp b/src/Clip.cpp index d9f69440..f20f32fb 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -339,7 +339,10 @@ std::shared_ptr Clip::GetFrame(int64_t requested_frame) original_frame = GetOrCreateFrame(new_frame_number); // Create a new frame - std::shared_ptr frame(new Frame(new_frame_number, 1, 1, "#000000", original_frame->GetAudioSamplesCount(), original_frame->GetAudioChannelsCount())); + auto frame = std::make_shared( + new_frame_number, 1, 1, "#000000", + original_frame->GetAudioSamplesCount(), + original_frame->GetAudioChannelsCount()); { frame->SampleRate(original_frame->SampleRate()); frame->ChannelsLayout(original_frame->ChannelsLayout()); @@ -347,7 +350,7 @@ std::shared_ptr Clip::GetFrame(int64_t requested_frame) // Copy the image from the odd field if (enabled_video) - frame->AddImage(std::shared_ptr(new QImage(*original_frame->GetImage()))); + frame->AddImage(std::make_shared(*original_frame->GetImage())); // Loop through each channel, add audio if (enabled_audio && reader->info.has_audio) diff --git a/src/DecklinkInput.cpp b/src/DecklinkInput.cpp index da5a8d00..b03ad8e4 100644 --- a/src/DecklinkInput.cpp +++ b/src/DecklinkInput.cpp @@ -139,7 +139,7 @@ HRESULT DeckLinkInputDelegate::VideoInputFrameArrived(IDeckLinkVideoInputFrame* { // Handle Video Frame if(videoFrame) - { + { if (videoFrame->GetFlags() & bmdFrameHasNoInputSource) { @@ -245,7 +245,8 @@ omp_set_nested(true); m_rgbFrame->GetBytes(&frameBytes); // *********** CREATE OPENSHOT FRAME ********** - std::shared_ptr f(new openshot::Frame(copy_frameCount, width, height, "#000000", 2048, 2)); + auto f = std::make_shared( + copy_frameCount, width, height, "#000000", 2048, 2); // Add Image data to openshot frame // TODO: Fix Decklink support with QImage Upgrade @@ -289,6 +290,3 @@ HRESULT DeckLinkInputDelegate::VideoInputFormatChanged(BMDVideoInputFormatChange { return S_OK; } - - - diff --git a/src/DecklinkWriter.cpp b/src/DecklinkWriter.cpp index 4ebbd1f0..3eafda1c 100644 --- a/src/DecklinkWriter.cpp +++ b/src/DecklinkWriter.cpp @@ -142,7 +142,7 @@ void DecklinkWriter::Open() // throw DecklinkError("Failed to enable audio output. Is another application using the card?"); // Begin video preroll by scheduling a second of frames in hardware - //std::shared_ptr f(new Frame(1, displayMode->GetWidth(), displayMode->GetHeight(), "Blue")); + //auto f = std::make_shared(1, displayMode->GetWidth(), displayMode->GetHeight(), "Blue"); //f->AddColor(displayMode->GetWidth(), displayMode->GetHeight(), "Blue"); // Preroll 1 second of video diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index c8ce141f..1952e8d6 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -2134,7 +2134,7 @@ bool FFmpegReader::CheckMissingFrame(int64_t requested_frame) { // Add this frame to the processed map (since it's already done) std::shared_ptr parent_image = parent_frame->GetImage(); if (parent_image) { - missing_frame->AddImage(std::shared_ptr(new QImage(*parent_image))); + missing_frame->AddImage(std::make_shared(*parent_image)); processed_video_frames[missing_frame->number] = missing_frame->number; } } @@ -2224,7 +2224,7 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream, int64_t requested_fram if (info.has_video && !is_video_ready && last_video_frame) { // Copy image from last frame - f->AddImage(std::shared_ptr(new QImage(*last_video_frame->GetImage()))); + f->AddImage(std::make_shared(*last_video_frame->GetImage())); is_video_ready = true; } @@ -2246,7 +2246,7 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream, int64_t requested_fram // Add missing image (if needed - sometimes end_of_stream causes frames with only audio) if (info.has_video && !is_video_ready && last_video_frame) // Copy image from last frame - f->AddImage(std::shared_ptr(new QImage(*last_video_frame->GetImage()))); + f->AddImage(std::make_shared(*last_video_frame->GetImage())); // Reset counter since last 'final' frame num_checks_since_final = 0; diff --git a/src/Frame.cpp b/src/Frame.cpp index cf47556a..16f420bc 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -39,7 +39,7 @@ Frame::Frame() : number(1), pixel_ratio(1,1), channels(2), width(1), height(1), max_audio_sample(0) { // Init the image magic and audio buffer - audio = std::shared_ptr(new juce::AudioSampleBuffer(channels, 0)); + audio = std::make_shared(channels, 0); // initialize the audio samples to zero (silence) audio->clear(); @@ -52,7 +52,7 @@ Frame::Frame(int64_t number, int width, int height, std::string color) max_audio_sample(0) { // Init the image magic and audio buffer - audio = std::shared_ptr(new juce::AudioSampleBuffer(channels, 0)); + audio = std::make_shared(channels, 0); // initialize the audio samples to zero (silence) audio->clear(); @@ -65,7 +65,7 @@ Frame::Frame(int64_t number, int samples, int channels) : max_audio_sample(0) { // Init the image magic and audio buffer - audio = std::shared_ptr(new juce::AudioSampleBuffer(channels, samples)); + audio = std::make_shared(channels, samples); // initialize the audio samples to zero (silence) audio->clear(); @@ -78,7 +78,7 @@ Frame::Frame(int64_t number, int width, int height, std::string color, int sampl max_audio_sample(0) { // Init the image magic and audio buffer - audio = std::shared_ptr(new juce::AudioSampleBuffer(channels, samples)); + audio = std::make_shared(channels, samples); // initialize the audio samples to zero (silence) audio->clear(); @@ -117,11 +117,11 @@ void Frame::DeepCopy(const Frame& other) max_audio_sample = other.max_audio_sample; if (other.image) - image = std::shared_ptr(new QImage(*(other.image))); + image = std::make_shared(*(other.image)); if (other.audio) - audio = std::shared_ptr(new juce::AudioSampleBuffer(*(other.audio))); + audio = std::make_shared(*(other.audio)); if (other.wave_image) - wave_image = std::shared_ptr(new QImage(*(other.wave_image))); + wave_image = std::make_shared(*(other.wave_image)); } // Destructor @@ -138,7 +138,7 @@ void Frame::Display() // Only create the QApplication once static int argc = 1; static char* argv[1] = {NULL}; - previewApp = std::shared_ptr(new QApplication(argc, argv)); + previewApp = std::make_shared(argc, argv); } // Get preview image @@ -152,7 +152,8 @@ void Frame::Display() int new_height = previewImage->size().height() * pixel_ratio.Reciprocal().ToDouble(); // Resize to fix DAR - previewImage = std::shared_ptr(new QImage(previewImage->scaled(new_width, new_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation))); + previewImage = std::make_shared(previewImage->scaled( + new_width, new_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); } // Create window @@ -228,7 +229,8 @@ std::shared_ptr Frame::GetWaveform(int width, int height, int Red, int G } // Create blank image - wave_image = std::shared_ptr(new QImage(total_width, total_height, QImage::Format_RGBA8888)); + wave_image = std::make_shared( + total_width, total_height, QImage::Format_RGBA8888); wave_image->fill(QColor(0,0,0,0)); // Load QPainter with wave_image device @@ -253,13 +255,13 @@ std::shared_ptr Frame::GetWaveform(int width, int height, int Red, int G // Resize Image (if requested) if (width != total_width || height != total_height) { QImage scaled_wave_image = wave_image->scaled(width, height, Qt::IgnoreAspectRatio, Qt::FastTransformation); - wave_image = std::shared_ptr(new QImage(scaled_wave_image)); + wave_image = std::make_shared(scaled_wave_image); } } else { // No audio samples present - wave_image = std::shared_ptr(new QImage(width, height, QImage::Format_RGBA8888)); + wave_image = std::make_shared(width, height, QImage::Format_RGBA8888); wave_image->fill(QColor(QString::fromStdString("#000000"))); } @@ -294,7 +296,7 @@ void Frame::DisplayWaveform() // Only create the QApplication once static int argc = 1; static char* argv[1] = {NULL}; - previewApp = std::shared_ptr(new QApplication(argc, argv)); + previewApp = std::make_shared(argc, argv); } // Create window @@ -599,11 +601,15 @@ void Frame::Save(std::string path, float scale, std::string format, int quality) int new_height = previewImage->size().height() * pixel_ratio.Reciprocal().ToDouble(); // Resize to fix DAR - previewImage = std::shared_ptr(new QImage(previewImage->scaled(new_width, new_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation))); + previewImage = std::make_shared(previewImage->scaled( + new_width, new_height, + Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); } // Resize image - previewImage = std::shared_ptr(new QImage(previewImage->scaled(new_width * scale, new_height * scale, Qt::KeepAspectRatio, Qt::SmoothTransformation))); + previewImage = std::make_shared(previewImage->scaled( + new_width * scale, new_height * scale, + Qt::KeepAspectRatio, Qt::SmoothTransformation)); } // Save image @@ -615,7 +621,8 @@ void Frame::Thumbnail(std::string path, int new_width, int new_height, std::stri std::string background_color, bool ignore_aspect, std::string format, int quality, float rotate) { // Create blank thumbnail image & fill background color - std::shared_ptr thumbnail = std::shared_ptr(new QImage(new_width, new_height, QImage::Format_RGBA8888)); + auto thumbnail = std::make_shared( + new_width, new_height, QImage::Format_RGBA8888); thumbnail->fill(QColor(QString::fromStdString(background_color))); // Create painter @@ -633,16 +640,22 @@ void Frame::Thumbnail(std::string path, int new_width, int new_height, std::stri int aspect_height = previewImage->size().height() * pixel_ratio.Reciprocal().ToDouble(); // Resize to fix DAR - previewImage = std::shared_ptr(new QImage(previewImage->scaled(aspect_width, aspect_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation))); + previewImage = std::make_shared(previewImage->scaled( + aspect_width, aspect_height, + Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); } // Resize frame image if (ignore_aspect) // Ignore aspect ratio - previewImage = std::shared_ptr(new QImage(previewImage->scaled(new_width, new_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation))); + previewImage = std::make_shared(previewImage->scaled( + new_width, new_height, + Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); else // Maintain aspect ratio - previewImage = std::shared_ptr(new QImage(previewImage->scaled(new_width, new_height, Qt::KeepAspectRatio, Qt::SmoothTransformation))); + previewImage = std::make_shared(previewImage->scaled( + new_width, new_height, + Qt::KeepAspectRatio, Qt::SmoothTransformation)); // Composite frame image onto background (centered) int x = (new_width - previewImage->size().width()) / 2.0; // center @@ -666,14 +679,16 @@ void Frame::Thumbnail(std::string path, int new_width, int new_height, std::stri // Overlay Image (if any) if (overlay_path != "") { // Open overlay - std::shared_ptr overlay = std::shared_ptr(new QImage()); + auto overlay = std::make_shared(); overlay->load(QString::fromStdString(overlay_path)); // Set pixel format - overlay = std::shared_ptr(new QImage(overlay->convertToFormat(QImage::Format_RGBA8888))); + overlay = std::make_shared( + overlay->convertToFormat(QImage::Format_RGBA8888)); // Resize to fit - overlay = std::shared_ptr(new QImage(overlay->scaled(new_width, new_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation))); + overlay = std::make_shared(overlay->scaled( + new_width, new_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); // Composite onto thumbnail painter.setCompositionMode(QPainter::CompositionMode_SourceOver); @@ -684,14 +699,16 @@ void Frame::Thumbnail(std::string path, int new_width, int new_height, std::stri // Mask Image (if any) if (mask_path != "") { // Open mask - std::shared_ptr mask = std::shared_ptr(new QImage()); + auto mask = std::make_shared(); mask->load(QString::fromStdString(mask_path)); // Set pixel format - mask = std::shared_ptr(new QImage(mask->convertToFormat(QImage::Format_RGBA8888))); + mask = std::make_shared( + mask->convertToFormat(QImage::Format_RGBA8888)); // Resize to fit - mask = std::shared_ptr(new QImage(mask->scaled(new_width, new_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation))); + mask = std::make_shared(mask->scaled( + new_width, new_height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); // Negate mask mask->invertPixels(); @@ -744,7 +761,7 @@ void Frame::AddColor(int new_width, int new_height, std::string new_color) const GenericScopedLock lock(addingImageSection); #pragma omp critical (AddImage) { - image = std::shared_ptr(new QImage(new_width, new_height, QImage::Format_RGBA8888)); + image = std::make_shared(new_width, new_height, QImage::Format_RGBA8888); // Fill with solid color image->fill(QColor(QString::fromStdString(color))); @@ -769,11 +786,12 @@ void Frame::AddImage(int new_width, int new_height, int bytes_per_pixel, QImage: // Create new image object, and fill with pixel data #pragma omp critical (AddImage) { - image = std::shared_ptr(new QImage(qbuffer, new_width, new_height, new_width * bytes_per_pixel, type, (QImageCleanupFunction) &openshot::Frame::cleanUpBuffer, (void*) qbuffer)); + image = std::make_shared( + qbuffer, new_width, new_height, new_width * bytes_per_pixel, type, (QImageCleanupFunction) &openshot::Frame::cleanUpBuffer, (void*) qbuffer); // Always convert to RGBA8888 (if different) if (image->format() != QImage::Format_RGBA8888) - *image = image->convertToFormat(QImage::Format_RGBA8888); + *image = image->convertToFormat(QImage::Format_RGBA8888); // Update height and width width = image->width(); @@ -828,7 +846,8 @@ void Frame::AddImage(std::shared_ptr new_image, bool only_odd_lines) ret = true; } else if (new_image->format() != image->format()) { - new_image = std::shared_ptr(new QImage(new_image->convertToFormat(image->format()))); + new_image = std::make_shared( + new_image->convertToFormat(image->format())); } } if (ret) { @@ -938,7 +957,8 @@ std::shared_ptr Frame::GetMagickImage() const QRgb *tmpBits = (const QRgb*)image->constBits(); // Create new image object, and fill with pixel data - std::shared_ptr magick_image = std::shared_ptr(new Magick::Image(image->width(), image->height(),"RGBA", Magick::CharPixel, tmpBits)); + auto magick_image = std::make_shared( + image->width(), image->height(),"RGBA", Magick::CharPixel, tmpBits); // Give image a transparent background color magick_image->backgroundColor(Magick::Color("none")); @@ -967,7 +987,9 @@ void Frame::AddMagickImage(std::shared_ptr new_image) MagickCore::ExportImagePixels(new_image->constImage(), 0, 0, new_image->columns(), new_image->rows(), "RGBA", Magick::CharPixel, buffer, &exception); // Create QImage of frame data - image = std::shared_ptr(new QImage(qbuffer, width, height, width * BPP, QImage::Format_RGBA8888, (QImageCleanupFunction) &cleanUpBuffer, (void*) qbuffer)); + image = std::make_shared( + qbuffer, width, height, width * BPP, QImage::Format_RGBA8888, + (QImageCleanupFunction) &cleanUpBuffer, (void*) qbuffer); // Update height and width width = image->width(); diff --git a/src/FrameMapper.cpp b/src/FrameMapper.cpp index e1e5700c..4946a5c1 100644 --- a/src/FrameMapper.cpp +++ b/src/FrameMapper.cpp @@ -450,7 +450,8 @@ std::shared_ptr FrameMapper::GetFrame(int64_t requested_frame) } // Create a new frame - std::shared_ptr frame = std::make_shared(frame_number, 1, 1, "#000000", samples_in_frame, channels_in_frame); + auto frame = std::make_shared( + frame_number, 1, 1, "#000000", samples_in_frame, channels_in_frame); frame->SampleRate(mapped_frame->SampleRate()); frame->ChannelsLayout(mapped_frame->ChannelsLayout()); @@ -460,13 +461,14 @@ std::shared_ptr FrameMapper::GetFrame(int64_t requested_frame) odd_frame = GetOrCreateFrame(mapped.Odd.Frame); if (odd_frame) - frame->AddImage(std::shared_ptr(new QImage(*odd_frame->GetImage())), true); + frame->AddImage(std::make_shared(*odd_frame->GetImage()), true); if (mapped.Odd.Frame != mapped.Even.Frame) { // Add even lines (if different than the previous image) std::shared_ptr even_frame; even_frame = GetOrCreateFrame(mapped.Even.Frame); if (even_frame) - frame->AddImage(std::shared_ptr(new QImage(*even_frame->GetImage())), false); + frame->AddImage( + std::make_shared(*even_frame->GetImage()), false); } // Resample audio on frame (if needed) diff --git a/src/ImageReader.cpp b/src/ImageReader.cpp index 9ce3a70f..9a001879 100644 --- a/src/ImageReader.cpp +++ b/src/ImageReader.cpp @@ -61,7 +61,7 @@ void ImageReader::Open() try { // load image - image = std::shared_ptr(new Magick::Image(path)); + image = std::make_shared(path); // Give image a transparent background color image->backgroundColor(Magick::Color("none")); @@ -126,7 +126,9 @@ std::shared_ptr ImageReader::GetFrame(int64_t requested_frame) throw ReaderClosed("The FFmpegReader is closed. Call Open() before calling this method.", path); // Create or get frame object - std::shared_ptr image_frame(new Frame(requested_frame, image->size().width(), image->size().height(), "#000000", 0, 2)); + auto image_frame = std::make_shared( + requested_frame, image->size().width(), image->size().height(), + "#000000", 0, 2); // Add Image data to frame image_frame->AddMagickImage(image); diff --git a/src/QtHtmlReader.cpp b/src/QtHtmlReader.cpp index 6b502fbd..4925d3a8 100644 --- a/src/QtHtmlReader.cpp +++ b/src/QtHtmlReader.cpp @@ -62,7 +62,7 @@ void QtHtmlReader::Open() if (!is_open) { // create image - image = std::shared_ptr(new QImage(width, height, QImage::Format_RGBA8888)); + image = std::make_shared(width, height, QImage::Format_RGBA8888); image->fill(QColor(background_color.c_str())); //start painting @@ -162,7 +162,9 @@ std::shared_ptr QtHtmlReader::GetFrame(int64_t requested_frame) if (image) { // Create or get frame object - std::shared_ptr image_frame(new Frame(requested_frame, image->size().width(), image->size().height(), background_color, 0, 2)); + auto image_frame = std::make_shared( + requested_frame, image->size().width(), image->size().height(), + background_color, 0, 2); // Add Image data to frame image_frame->AddImage(image); @@ -171,7 +173,8 @@ std::shared_ptr QtHtmlReader::GetFrame(int64_t requested_frame) return image_frame; } else { // return empty frame - std::shared_ptr image_frame(new Frame(1, 640, 480, background_color, 0, 2)); + auto image_frame = std::make_shared( + 1, 640, 480, background_color, 0, 2); // return frame object return image_frame; diff --git a/src/QtImageReader.cpp b/src/QtImageReader.cpp index cf64ef93..b6dd7ee0 100644 --- a/src/QtImageReader.cpp +++ b/src/QtImageReader.cpp @@ -82,7 +82,8 @@ void QtImageReader::Open() ResvgRenderer renderer(path); if (renderer.isValid()) { - image = std::shared_ptr(new QImage(renderer.defaultSize(), QImage::Format_ARGB32_Premultiplied)); + image = std::make_shared( + renderer.defaultSize(), QImage::Format_ARGB32_Premultiplied); image->fill(Qt::transparent); QPainter p(image.get()); @@ -95,7 +96,7 @@ void QtImageReader::Open() if (!loaded) { // Attempt to open file using Qt's build in image processing capabilities - image = std::shared_ptr(new QImage()); + image = std::make_shared(); success = image->load(path); } @@ -105,7 +106,8 @@ void QtImageReader::Open() } // Convert to proper format - image = std::shared_ptr(new QImage(image->convertToFormat(QImage::Format_RGBA8888))); + image = std::make_shared( + image->convertToFormat(QImage::Format_RGBA8888)); // Update image properties info.has_audio = false; @@ -238,7 +240,9 @@ std::shared_ptr QtImageReader::GetFrame(int64_t requested_frame) svg_size.scale(max_width, max_height, Qt::KeepAspectRatio); // Create empty QImage - cached_image = std::shared_ptr(new QImage(QSize(svg_size.width(), svg_size.height()), QImage::Format_ARGB32_Premultiplied)); + cached_image = std::make_shared( + QSize(svg_size.width(), svg_size.height()), + QImage::Format_ARGB32_Premultiplied); cached_image->fill(Qt::transparent); // Render SVG into QImage @@ -253,10 +257,12 @@ std::shared_ptr QtImageReader::GetFrame(int64_t requested_frame) if (!rendered) { // We need to resize the original image to a smaller image (for performance reasons) // Only do this once, to prevent tons of unneeded scaling operations - cached_image = std::shared_ptr(new QImage(image->scaled(max_width, max_height, Qt::KeepAspectRatio, Qt::SmoothTransformation))); + cached_image = std::make_shared(image->scaled( + max_width, max_height, Qt::KeepAspectRatio, Qt::SmoothTransformation)); } - cached_image = std::shared_ptr(new QImage(cached_image->convertToFormat(QImage::Format_RGBA8888))); + cached_image = std::make_shared( + cached_image->convertToFormat(QImage::Format_RGBA8888)); // Set max size (to later determine if max_size is changed) max_size.setWidth(max_width); @@ -264,7 +270,10 @@ std::shared_ptr QtImageReader::GetFrame(int64_t requested_frame) } // Create or get frame object - std::shared_ptr image_frame(new Frame(requested_frame, cached_image->width(), cached_image->height(), "#000000", Frame::GetSamplesPerFrame(requested_frame, info.fps, info.sample_rate, info.channels), info.channels)); + auto image_frame = std::make_shared( + requested_frame, cached_image->width(), cached_image->height(), "#000000", + Frame::GetSamplesPerFrame(requested_frame, info.fps, info.sample_rate, info.channels), + info.channels); // Add Image data to frame image_frame->AddImage(cached_image); diff --git a/src/QtTextReader.cpp b/src/QtTextReader.cpp index d91d164e..bd157ebd 100644 --- a/src/QtTextReader.cpp +++ b/src/QtTextReader.cpp @@ -67,7 +67,7 @@ void QtTextReader::Open() if (!is_open) { // create image - image = std::shared_ptr(new QImage(width, height, QImage::Format_RGBA8888)); + image = std::make_shared(width, height, QImage::Format_RGBA8888); image->fill(QColor(background_color.c_str())); QPainter painter; @@ -179,7 +179,9 @@ std::shared_ptr QtTextReader::GetFrame(int64_t requested_frame) if (image) { // Create or get frame object - std::shared_ptr image_frame(new Frame(requested_frame, image->size().width(), image->size().height(), background_color, 0, 2)); + auto image_frame = std::make_shared( + requested_frame, image->size().width(), image->size().height(), + background_color, 0, 2); // Add Image data to frame image_frame->AddImage(image); @@ -188,7 +190,7 @@ std::shared_ptr QtTextReader::GetFrame(int64_t requested_frame) return image_frame; } else { // return empty frame - std::shared_ptr image_frame(new Frame(1, 640, 480, background_color, 0, 2)); + auto image_frame = std::make_shared(1, 640, 480, background_color, 0, 2); // return frame object return image_frame; diff --git a/src/TextReader.cpp b/src/TextReader.cpp index e317700c..be8c7375 100644 --- a/src/TextReader.cpp +++ b/src/TextReader.cpp @@ -66,7 +66,8 @@ void TextReader::Open() if (!is_open) { // create image - image = std::shared_ptr(new Magick::Image(Magick::Geometry(width,height), Magick::Color(background_color))); + image = std::make_shared( + Magick::Geometry(width,height), Magick::Color(background_color)); // Give image a transparent background color image->backgroundColor(Magick::Color("none")); @@ -166,10 +167,12 @@ std::shared_ptr TextReader::GetFrame(int64_t requested_frame) if (image) { // Create or get frame object - std::shared_ptr image_frame(new Frame(requested_frame, image->size().width(), image->size().height(), "#000000", 0, 2)); + auto image_frame = std::make_shared( + requested_frame, image->size().width(), image->size().height(), + "#000000", 0, 2); // Add Image data to frame - std::shared_ptr copy_image(new Magick::Image(*image.get())); + auto copy_image = std::make_shared(*image.get()); copy_image->modifyImage(); // actually copy the image data to this object //TODO: Reimplement this with QImage image_frame->AddMagickImage(copy_image); @@ -178,7 +181,7 @@ std::shared_ptr TextReader::GetFrame(int64_t requested_frame) return image_frame; } else { // return empty frame - std::shared_ptr image_frame(new Frame(1, 640, 480, "#000000", 0, 2)); + auto image_frame = std::make_shared(1, 640, 480, "#000000", 0, 2); // return frame object return image_frame; diff --git a/src/effects/Bars.cpp b/src/effects/Bars.cpp index 3f9aac34..e653b7dd 100644 --- a/src/effects/Bars.cpp +++ b/src/effects/Bars.cpp @@ -68,7 +68,8 @@ std::shared_ptr Bars::GetFrame(std::shared_ptr frame, int64_t fram std::shared_ptr frame_image = frame->GetImage(); // Get bar color (and create small color image) - std::shared_ptr tempColor = std::shared_ptr(new QImage(frame_image->width(), 1, QImage::Format_RGBA8888)); + auto tempColor = std::make_shared( + frame_image->width(), 1, QImage::Format_RGBA8888); tempColor->fill(QColor(QString::fromStdString(color.GetColorHex(frame_number)))); // Get current keyframe values diff --git a/src/effects/Crop.cpp b/src/effects/Crop.cpp index b1c3d38d..f0e0aa95 100644 --- a/src/effects/Crop.cpp +++ b/src/effects/Crop.cpp @@ -68,7 +68,8 @@ std::shared_ptr Crop::GetFrame(std::shared_ptr frame, int64_t fram std::shared_ptr frame_image = frame->GetImage(); // Get transparent color (and create small transparent image) - std::shared_ptr tempColor = std::shared_ptr(new QImage(frame_image->width(), 1, QImage::Format_RGBA8888)); + auto tempColor = std::make_shared( + frame_image->width(), 1, QImage::Format_RGBA8888); tempColor->fill(QColor(QString::fromStdString("transparent"))); // Get current keyframe values diff --git a/src/effects/Deinterlace.cpp b/src/effects/Deinterlace.cpp index 39b3316a..984336aa 100644 --- a/src/effects/Deinterlace.cpp +++ b/src/effects/Deinterlace.cpp @@ -86,7 +86,9 @@ std::shared_ptr Deinterlace::GetFrame(std::shared_ptr frame, int64 } // Resize deinterlaced image back to original size, and update frame's image - image = std::shared_ptr(new QImage(deinterlaced_image.scaled(original_width, original_height, Qt::IgnoreAspectRatio, Qt::FastTransformation))); + image = std::make_shared(deinterlaced_image.scaled( + original_width, original_height, + Qt::IgnoreAspectRatio, Qt::FastTransformation)); // Update image on frame frame->AddImage(image); diff --git a/src/effects/Mask.cpp b/src/effects/Mask.cpp index 11c37f05..f270e410 100644 --- a/src/effects/Mask.cpp +++ b/src/effects/Mask.cpp @@ -84,13 +84,14 @@ std::shared_ptr Mask::GetFrame(std::shared_ptr frame, int64_t fram (original_mask && original_mask->size() != frame_image->size())) { // Only get mask if needed - std::shared_ptr mask_without_sizing = std::shared_ptr( - new QImage(*reader->GetFrame(frame_number)->GetImage())); + auto mask_without_sizing = std::make_shared( + *reader->GetFrame(frame_number)->GetImage()); // Resize mask image to match frame size - original_mask = std::shared_ptr(new QImage( - mask_without_sizing->scaled(frame_image->width(), frame_image->height(), Qt::IgnoreAspectRatio, - Qt::SmoothTransformation))); + original_mask = std::make_shared( + mask_without_sizing->scaled( + frame_image->width(), frame_image->height(), + Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); } } From c14922d57ea8226b2876a822dab9911ae2f1fbf9 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Thu, 20 Aug 2020 20:40:55 -0400 Subject: [PATCH 22/30] Frame.cpp/h: Fix a bunch of wrong comments Best reason not to narrate the code in the comments: The code gets changed, but the documentation doesn't. --- include/Frame.h | 12 ++++++------ src/Frame.cpp | 22 +++++++--------------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/include/Frame.h b/include/Frame.h index 7e7866c0..8987dcb4 100644 --- a/include/Frame.h +++ b/include/Frame.h @@ -73,17 +73,17 @@ namespace openshot * There are many ways to create an instance of an openshot::Frame: * @code * - * // Most basic: a blank frame (300x200 blank image, 48kHz audio silence) + * // Most basic: a blank frame (all default values) * Frame(); * - * // Image only settings (48kHz audio silence) + * // Image only settings * Frame(1, // Frame number * 720, // Width of image * 480, // Height of image * "#000000" // HTML color code of background color * ); * - * // Audio only (300x200 blank image) + * // Audio only * Frame(number, // Frame number * 44100, // Sample rate of audio stream * 2 // Number of audio channels @@ -131,13 +131,13 @@ namespace openshot bool has_image_data; ///< This frame has been loaded with pixel data - /// Constructor - blank frame (300x200 blank image, 48kHz audio silence) + /// Constructor - blank frame Frame(); - /// Constructor - image only (48kHz audio silence) + /// Constructor - image only Frame(int64_t number, int width, int height, std::string color); - /// Constructor - audio only (300x200 blank image) + /// Constructor - audio only Frame(int64_t number, int samples, int channels); /// Constructor - image & audio diff --git a/src/Frame.cpp b/src/Frame.cpp index 16f420bc..54901cc5 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -33,41 +33,35 @@ using namespace std; using namespace openshot; -// Constructor - blank frame (300x200 blank image, 48kHz audio silence) +// Constructor - blank frame Frame::Frame() : number(1), pixel_ratio(1,1), channels(2), width(1), height(1), color("#000000"), channel_layout(LAYOUT_STEREO), sample_rate(44100), qbuffer(NULL), has_audio_data(false), has_image_data(false), max_audio_sample(0) { - // Init the image magic and audio buffer + // Allocate and zero (fill with silence) the audio buffer audio = std::make_shared(channels, 0); - - // initialize the audio samples to zero (silence) audio->clear(); } -// Constructor - image only (48kHz audio silence) +// Constructor - image only Frame::Frame(int64_t number, int width, int height, std::string color) : number(number), pixel_ratio(1,1), channels(2), width(width), height(height), color(color), channel_layout(LAYOUT_STEREO), sample_rate(44100), qbuffer(NULL), has_audio_data(false), has_image_data(false), max_audio_sample(0) { - // Init the image magic and audio buffer + // Allocate and zero (fill with silence) the audio buffer audio = std::make_shared(channels, 0); - - // initialize the audio samples to zero (silence) audio->clear(); } -// Constructor - audio only (300x200 blank image) +// Constructor - audio only Frame::Frame(int64_t number, int samples, int channels) : number(number), pixel_ratio(1,1), channels(channels), width(1), height(1), color("#000000"), channel_layout(LAYOUT_STEREO), sample_rate(44100), qbuffer(NULL), has_audio_data(false), has_image_data(false), max_audio_sample(0) { - // Init the image magic and audio buffer + // Allocate and zero (fill with silence) the audio buffer audio = std::make_shared(channels, samples); - - // initialize the audio samples to zero (silence) audio->clear(); } @@ -77,10 +71,8 @@ Frame::Frame(int64_t number, int width, int height, std::string color, int sampl channel_layout(LAYOUT_STEREO), sample_rate(44100), qbuffer(NULL), has_audio_data(false), has_image_data(false), max_audio_sample(0) { - // Init the image magic and audio buffer + // Allocate and zero (fill with silence) the audio buffer audio = std::make_shared(channels, samples); - - // initialize the audio samples to zero (silence) audio->clear(); } From 47fca0254043f7d3fbf9d9577bac4ba570b10e2c Mon Sep 17 00:00:00 2001 From: eisneinechse <42617957+eisneinechse@users.noreply.github.com> Date: Sun, 13 Sep 2020 09:07:14 -0700 Subject: [PATCH 23/30] video_codec -> video_codec_ctx --- src/FFmpegWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FFmpegWriter.cpp b/src/FFmpegWriter.cpp index 8b89de7f..5dd14200 100644 --- a/src/FFmpegWriter.cpp +++ b/src/FFmpegWriter.cpp @@ -339,7 +339,7 @@ void FFmpegWriter::SetOption(StreamType stream, std::string name, std::string va if (info.has_video && stream == VIDEO_STREAM && video_st) { st = video_st; // Get codec context - c = AV_GET_CODEC_PAR_CONTEXT(st, video_codec); + c = AV_GET_CODEC_PAR_CONTEXT(st, video_codec_ctx); // Was a codec / stream found? if (c) { if (info.interlaced_frame) { From 1c8aea94d0a86985934fb07e28dfdd4ecdf850ee Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 13 Sep 2020 16:28:31 -0400 Subject: [PATCH 24/30] Frame: Put Qt includes where they're used --- include/Frame.h | 12 ++---------- src/Frame.cpp | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/include/Frame.h b/include/Frame.h index 8987dcb4..b3416d38 100644 --- a/include/Frame.h +++ b/include/Frame.h @@ -34,16 +34,8 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include #include #include "ZmqLogger.h" diff --git a/src/Frame.cpp b/src/Frame.cpp index 54901cc5..48af2a28 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -29,6 +29,21 @@ */ #include "../include/Frame.h" +#include "JuceHeader.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace std; using namespace openshot; From 9c83429ab1042a992511a30ede220214c593c31b Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 13 Sep 2020 16:33:36 -0400 Subject: [PATCH 25/30] Frame: Use delegating constructors --- src/Frame.cpp | 54 +++++++++++++++++---------------------------------- 1 file changed, 18 insertions(+), 36 deletions(-) diff --git a/src/Frame.cpp b/src/Frame.cpp index 48af2a28..67371655 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -48,49 +48,31 @@ using namespace std; using namespace openshot; -// Constructor - blank frame -Frame::Frame() : number(1), pixel_ratio(1,1), channels(2), width(1), height(1), color("#000000"), - channel_layout(LAYOUT_STEREO), sample_rate(44100), qbuffer(NULL), has_audio_data(false), has_image_data(false), - max_audio_sample(0) -{ - // Allocate and zero (fill with silence) the audio buffer - audio = std::make_shared(channels, 0); - audio->clear(); -} - -// Constructor - image only -Frame::Frame(int64_t number, int width, int height, std::string color) - : number(number), pixel_ratio(1,1), channels(2), width(width), height(height), color(color), - channel_layout(LAYOUT_STEREO), sample_rate(44100), qbuffer(NULL), has_audio_data(false), has_image_data(false), - max_audio_sample(0) -{ - // Allocate and zero (fill with silence) the audio buffer - audio = std::make_shared(channels, 0); - audio->clear(); -} - -// Constructor - audio only -Frame::Frame(int64_t number, int samples, int channels) : - number(number), pixel_ratio(1,1), channels(channels), width(1), height(1), color("#000000"), - channel_layout(LAYOUT_STEREO), sample_rate(44100), qbuffer(NULL), has_audio_data(false), has_image_data(false), - max_audio_sample(0) -{ - // Allocate and zero (fill with silence) the audio buffer - audio = std::make_shared(channels, samples); - audio->clear(); -} - // Constructor - image & audio Frame::Frame(int64_t number, int width, int height, std::string color, int samples, int channels) - : number(number), pixel_ratio(1,1), channels(channels), width(width), height(height), color(color), - channel_layout(LAYOUT_STEREO), sample_rate(44100), qbuffer(NULL), has_audio_data(false), has_image_data(false), + : audio(std::make_shared(channels, samples)), + number(number), width(width), height(height), + pixel_ratio(1,1), color(color), qbuffer(NULL), + channels(channels), channel_layout(LAYOUT_STEREO), + sample_rate(44100), + has_audio_data(false), has_image_data(false), max_audio_sample(0) { - // Allocate and zero (fill with silence) the audio buffer - audio = std::make_shared(channels, samples); + // zero (fill with silence) the audio buffer audio->clear(); } +// Delegating Constructor - blank frame +Frame::Frame() : Frame::Frame(1, 1, 1, "#000000", 0, 2) {}; + +// Delegating Constructor - image only +Frame::Frame(int64_t number, int width, int height, std::string color) + : Frame::Frame(number, width, height, color, 0, 2) {}; + +// Delegating Constructor - audio only +Frame::Frame(int64_t number, int samples, int channels) + : Frame::Frame(number, 1, 1, "#000000", samples, channels) {}; + // Copy constructor Frame::Frame ( const Frame &other ) From 0974637a3a71a1acd115bac33634ea6d646c7472 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 13 Sep 2020 16:33:16 -0400 Subject: [PATCH 26/30] Pixelate: Fix missing includes --- include/effects/Pixelate.h | 1 - src/effects/Pixelate.cpp | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/effects/Pixelate.h b/include/effects/Pixelate.h index 4cdd440f..793f4d46 100644 --- a/include/effects/Pixelate.h +++ b/include/effects/Pixelate.h @@ -36,7 +36,6 @@ #include #include #include -#include "../Color.h" #include "../Json.h" #include "../KeyFrame.h" diff --git a/src/effects/Pixelate.cpp b/src/effects/Pixelate.cpp index c993915c..41d97c5c 100644 --- a/src/effects/Pixelate.cpp +++ b/src/effects/Pixelate.cpp @@ -29,6 +29,12 @@ */ #include "../../include/effects/Pixelate.h" +#include "Json.h" + +#include +#include +#include +#include using namespace openshot; From 92d33a1ebd5a7da249195db37afb7edb4a3abceb Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 13 Sep 2020 16:38:23 -0400 Subject: [PATCH 27/30] VideoRenderWidget: missing includes --- include/Qt/VideoRenderWidget.h | 6 ++++-- src/Qt/VideoRenderWidget.cpp | 8 +++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/Qt/VideoRenderWidget.h b/include/Qt/VideoRenderWidget.h index 07c61037..4d9ac17f 100644 --- a/include/Qt/VideoRenderWidget.h +++ b/include/Qt/VideoRenderWidget.h @@ -31,11 +31,13 @@ #ifndef OPENSHOT_VIDEO_RENDERER_WIDGET_H #define OPENSHOT_VIDEO_RENDERER_WIDGET_H -#include -#include #include "../Fraction.h" #include "VideoRenderer.h" +#include +#include +#include +#include class VideoRenderWidget : public QWidget { diff --git a/src/Qt/VideoRenderWidget.cpp b/src/Qt/VideoRenderWidget.cpp index 2bfe8fa2..4af1ac6a 100644 --- a/src/Qt/VideoRenderWidget.cpp +++ b/src/Qt/VideoRenderWidget.cpp @@ -29,7 +29,13 @@ */ #include "../../include/Qt/VideoRenderWidget.h" -#include +#include +#include +#include +#include +#include +#include + VideoRenderWidget::VideoRenderWidget(QWidget *parent) : QWidget(parent), renderer(new VideoRenderer(this)) From 0bcf1e49247977e2821e093573d9d64cf7585caf Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Sun, 13 Sep 2020 19:56:40 -0400 Subject: [PATCH 28/30] Frame: Reduce code duplication --- src/Frame.cpp | 41 ++++++++++++++++++++--------------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/Frame.cpp b/src/Frame.cpp index 67371655..c3c50bcd 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -762,31 +762,31 @@ void Frame::AddColor(int new_width, int new_height, std::string new_color) } // Add (or replace) pixel data to the frame -void Frame::AddImage(int new_width, int new_height, int bytes_per_pixel, QImage::Format type, const unsigned char *pixels_) +void Frame::AddImage( + int new_width, int new_height, int bytes_per_pixel, + QImage::Format type, const unsigned char *pixels_) { // Create new buffer - const GenericScopedLock lock(addingImageSection); - int buffer_size = new_width * new_height * bytes_per_pixel; - qbuffer = new unsigned char[buffer_size](); - - // Copy buffer data - memcpy((unsigned char*)qbuffer, pixels_, buffer_size); - - // Create new image object, and fill with pixel data - #pragma omp critical (AddImage) { - image = std::make_shared( - qbuffer, new_width, new_height, new_width * bytes_per_pixel, type, (QImageCleanupFunction) &openshot::Frame::cleanUpBuffer, (void*) qbuffer); + const GenericScopedLock lock(addingImageSection); + int buffer_size = new_width * new_height * bytes_per_pixel; + qbuffer = new unsigned char[buffer_size](); - // Always convert to RGBA8888 (if different) - if (image->format() != QImage::Format_RGBA8888) - *image = image->convertToFormat(QImage::Format_RGBA8888); + // Copy buffer data + memcpy((unsigned char*)qbuffer, pixels_, buffer_size); - // Update height and width - width = image->width(); - height = image->height(); - has_image_data = true; - } + } // Release addingImageSection lock + + // Create new image object from pixel data + auto new_image = std::make_shared( + qbuffer, + new_width, new_height, + new_width * bytes_per_pixel, + type, + (QImageCleanupFunction) &openshot::Frame::cleanUpBuffer, + (void*) qbuffer + ); + AddImage(new_image); } // Add (or replace) pixel data to the frame @@ -826,7 +826,6 @@ void Frame::AddImage(std::shared_ptr new_image, bool only_odd_lines) AddImage(new_image); } else { - // Ignore image of different sizes or formats bool ret=false; #pragma omp critical (AddImage) From 88677a9c3c03d903c82b69fd81365a5329a97960 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Fri, 16 Oct 2020 02:54:54 -0500 Subject: [PATCH 29/30] Update Saturation.cpp Removing alpha channel access (undefined) --- src/effects/Saturation.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/effects/Saturation.cpp b/src/effects/Saturation.cpp index 5ce958a5..25fc51bc 100644 --- a/src/effects/Saturation.cpp +++ b/src/effects/Saturation.cpp @@ -154,7 +154,6 @@ std::shared_ptr Saturation::GetFrame(std::shared_ptr frame, int64_ pixels[byte_index] = R; pixels[byte_index + 1] = G; pixels[byte_index + 2] = B; - pixels[byte_index + 3] = A; // leave the alpha value alone } // return the modified frame From a7fe41cc1a796036a85f4917a7e845285bc64c6c Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Fri, 16 Oct 2020 03:03:26 -0500 Subject: [PATCH 30/30] Update Saturation.cpp Fixing regression after conflict resolution --- src/effects/Saturation.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/effects/Saturation.cpp b/src/effects/Saturation.cpp index 25fc51bc..cad9c08d 100644 --- a/src/effects/Saturation.cpp +++ b/src/effects/Saturation.cpp @@ -151,9 +151,9 @@ std::shared_ptr Saturation::GetFrame(std::shared_ptr frame, int64_ B = constrain(B); // Set all pixels to new value - pixels[byte_index] = R; - pixels[byte_index + 1] = G; - pixels[byte_index + 2] = B; + pixels[pixel * 4] = R; + pixels[pixel * 4 + 1] = G; + pixels[pixel * 4 + 2] = B; } // return the modified frame