diff --git a/src/Clip.cpp b/src/Clip.cpp index de0aa014..5f8fb365 100644 --- a/src/Clip.cpp +++ b/src/Clip.cpp @@ -1267,7 +1267,6 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) float origin_x_value = origin_x.GetValue(frame->number); float origin_y_value = origin_y.GetValue(frame->number); - bool transformed = false; QTransform transform; // Transform source image (if needed) @@ -1276,7 +1275,6 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) if (!isEqual(x, 0) || !isEqual(y, 0)) { // TRANSLATE/MOVE CLIP transform.translate(x, y); - transformed = true; } if (!isEqual(r, 0) || !isEqual(shear_x_value, 0) || !isEqual(shear_y_value, 0)) { @@ -1287,7 +1285,6 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) transform.rotate(r); transform.shear(shear_x_value, shear_y_value); transform.translate(-origin_x_offset,-origin_y_offset); - transformed = true; } // SCALE CLIP (if needed) @@ -1296,11 +1293,10 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) if (!isEqual(source_width_scale, 1.0) || !isEqual(source_height_scale, 1.0)) { transform.scale(source_width_scale, source_height_scale); - transformed = true; } // Debug output - ZmqLogger::Instance()->AppendDebugMethod("Clip::apply_keyframes (Transform: Composite Image Layer: Prepare)", "frame->number", frame->number, "transformed", transformed); + ZmqLogger::Instance()->AppendDebugMethod("Clip::apply_keyframes (Transform: Composite Image Layer: Prepare)", "frame->number", frame->number); /* COMPOSITE SOURCE IMAGE (LAYER) ONTO FINAL IMAGE */ auto new_image = std::make_shared(QSize(width, height), source_image->format()); @@ -1310,9 +1306,8 @@ void Clip::apply_keyframes(std::shared_ptr frame, int width, int height) QPainter painter(new_image.get()); painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing, true); - // Apply transform (translate, rotate, scale)... if any - if (transformed) - painter.setTransform(transform); + // Apply transform (translate, rotate, scale) + painter.setTransform(transform); // Composite a new layer onto the image painter.setCompositionMode(QPainter::CompositionMode_SourceOver); diff --git a/src/ClipBase.h b/src/ClipBase.h index bc37833b..ac2c0237 100644 --- a/src/ClipBase.h +++ b/src/ClipBase.h @@ -39,12 +39,10 @@ #include "Point.h" #include "KeyFrame.h" #include "Json.h" +#include "TimelineBase.h" + namespace openshot { - - // Forward declaration - class TimelineBase; - /** * @brief This abstract class is the base class, used by all clips in libopenshot. * diff --git a/src/FrameMapper.cpp b/src/FrameMapper.cpp index 096976cf..b7e18daf 100644 --- a/src/FrameMapper.cpp +++ b/src/FrameMapper.cpp @@ -117,15 +117,6 @@ void FrameMapper::Init() // Clear cache final_cache.Clear(); - // Get clip position from parent clip (if any) - float clipPosition = 0.0; - float clipStart = 0.0; - Clip *parent = (Clip *) ParentClip(); - if (parent) { - clipPosition = parent->Position(); - clipStart = parent->Start(); - } - // Some framerates are handled special, and some use a generic Keyframe curve to // map the framerates. These are the special framerates: if ((fabs(original.ToFloat() - 24.0) < 1e-7 || fabs(original.ToFloat() - 25.0) < 1e-7 || fabs(original.ToFloat() - 30.0) < 1e-7) && @@ -267,12 +258,12 @@ void FrameMapper::Init() // the original sample rate. int64_t end_samples_frame = start_samples_frame; int end_samples_position = start_samples_position; - int remaining_samples = Frame::GetSamplesPerFrame(AdjustFrameNumber(frame_number, clipPosition, clipStart), target, reader->info.sample_rate, reader->info.channels); + int remaining_samples = Frame::GetSamplesPerFrame(AdjustFrameNumber(frame_number), target, reader->info.sample_rate, reader->info.channels); while (remaining_samples > 0) { // get original samples - int original_samples = Frame::GetSamplesPerFrame(AdjustFrameNumber(end_samples_frame, clipPosition, clipStart), original, reader->info.sample_rate, reader->info.channels) - end_samples_position; + int original_samples = Frame::GetSamplesPerFrame(AdjustFrameNumber(end_samples_frame), original, reader->info.sample_rate, reader->info.channels) - end_samples_position; // Enough samples if (original_samples >= remaining_samples) @@ -292,12 +283,12 @@ void FrameMapper::Init() // Create the sample mapping struct - SampleRange Samples = {start_samples_frame, start_samples_position, end_samples_frame, end_samples_position, Frame::GetSamplesPerFrame(AdjustFrameNumber(frame_number, clipPosition, clipStart), target, reader->info.sample_rate, reader->info.channels)}; + SampleRange Samples = {start_samples_frame, start_samples_position, end_samples_frame, end_samples_position, Frame::GetSamplesPerFrame(AdjustFrameNumber(frame_number), target, reader->info.sample_rate, reader->info.channels)}; // Reset the audio variables start_samples_frame = end_samples_frame; start_samples_position = end_samples_position + 1; - if (start_samples_position >= Frame::GetSamplesPerFrame(AdjustFrameNumber(start_samples_frame, clipPosition, clipStart), original, reader->info.sample_rate, reader->info.channels)) + if (start_samples_position >= Frame::GetSamplesPerFrame(AdjustFrameNumber(start_samples_frame), original, reader->info.sample_rate, reader->info.channels)) { start_samples_frame += 1; // increment the frame (since we need to wrap onto the next one) start_samples_position = 0; // reset to 0, since we wrapped @@ -363,17 +354,8 @@ std::shared_ptr FrameMapper::GetOrCreateFrame(int64_t number) { std::shared_ptr new_frame; - // Get clip position from parent clip (if any) - float clipPosition = 0.0; - float clipStart = 0.0; - Clip *parent = (Clip *) ParentClip(); - if (parent) { - clipPosition = parent->Position(); - clipStart = parent->Start(); - } - // Init some basic properties about this frame (keep sample rate and # channels the same as the original reader for now) - int samples_in_frame = Frame::GetSamplesPerFrame(AdjustFrameNumber(number, clipPosition, clipStart), target, reader->info.sample_rate, reader->info.channels); + int samples_in_frame = Frame::GetSamplesPerFrame(AdjustFrameNumber(number), target, reader->info.sample_rate, reader->info.channels); try { // Debug output @@ -423,15 +405,6 @@ std::shared_ptr FrameMapper::GetFrame(int64_t requested_frame) final_frame = final_cache.GetFrame(requested_frame); if (final_frame) return final_frame; - // Get clip position from parent clip (if any) - float clipPosition = 0.0; - float clipStart = 0.0; - Clip *parent = (Clip *) ParentClip(); - if (parent) { - clipPosition = parent->Position(); - clipStart = parent->Start(); - } - // Minimum number of frames to process (for performance reasons) // Dialing this down to 1 for now, as it seems to improve performance, and reduce export crashes int minimum_frames = 1; @@ -455,7 +428,7 @@ std::shared_ptr FrameMapper::GetFrame(int64_t requested_frame) // Get # of channels in the actual frame int channels_in_frame = mapped_frame->GetAudioChannelsCount(); - int samples_in_frame = Frame::GetSamplesPerFrame(AdjustFrameNumber(frame_number, clipPosition, clipStart), target, mapped_frame->SampleRate(), channels_in_frame); + int samples_in_frame = Frame::GetSamplesPerFrame(AdjustFrameNumber(frame_number), target, mapped_frame->SampleRate(), channels_in_frame); // Determine if mapped frame is identical to source frame // including audio sample distribution according to mapped.Samples, @@ -778,15 +751,6 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig // Recalculate mappings Init(); - // Get clip position from parent clip (if any) - float clipPosition = 0.0; - float clipStart = 0.0; - Clip *parent = (Clip *) ParentClip(); - if (parent) { - clipPosition = parent->Position(); - clipStart = parent->Start(); - } - // Init audio buffers / variables int total_frame_samples = 0; int channels_in_frame = frame->GetAudioChannelsCount(); @@ -848,7 +812,7 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig } // Update total samples & input frame size (due to bigger or smaller data types) - total_frame_samples = Frame::GetSamplesPerFrame(AdjustFrameNumber(frame->number, clipPosition, clipStart), target, info.sample_rate, info.channels); + total_frame_samples = Frame::GetSamplesPerFrame(AdjustFrameNumber(frame->number), target, info.sample_rate, info.channels); ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ResampleMappedAudio (adjust # of samples)", "total_frame_samples", total_frame_samples, "info.sample_rate", info.sample_rate, "sample_rate_in_frame", sample_rate_in_frame, "info.channels", info.channels, "channels_in_frame", channels_in_frame, "original_frame_number", original_frame_number); @@ -959,13 +923,23 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr frame, int64_t orig } // Adjust frame number for Clip position and start (which can result in a different number) -int64_t FrameMapper::AdjustFrameNumber(int64_t clip_frame_number, float position, float start) { +int64_t FrameMapper::AdjustFrameNumber(int64_t clip_frame_number) { + // Get clip position from parent clip (if any) + float position = 0.0; + float start = 0.0; + Clip *parent = (Clip *) ParentClip(); + if (parent) { + position = parent->Position(); + start = parent->Start(); + } + + // Adjust start frame and position based on parent clip. This prevents ensures the same + // frame # is used by mapped readers and clips, when calculating samples per frame. Thus, + // this prevents gaps and mismatches in # of samples. int64_t clip_start_frame = (start * info.fps.ToDouble()) + 1; int64_t clip_start_position = round(position * info.fps.ToDouble()) + 1; - int64_t frame_number = clip_frame_number + clip_start_position - clip_start_frame; - ///std::cout << "Conv Position " << round(position * info.fps.ToDouble()) << " position: " << position << " info::fps: " << info.fps.ToDouble() << std::endl; return frame_number; } diff --git a/src/FrameMapper.h b/src/FrameMapper.h index 7f6c9c16..5b3e00e3 100644 --- a/src/FrameMapper.h +++ b/src/FrameMapper.h @@ -155,7 +155,7 @@ namespace openshot std::shared_ptr GetOrCreateFrame(int64_t number); /// Adjust frame number for Clip position and start (which can result in a different number) - int64_t AdjustFrameNumber(int64_t clip_frame_number, float position, float start); + int64_t AdjustFrameNumber(int64_t clip_frame_number); // Use the original and target frame rates and a pull-down technique to create // a mapping between the original fields and frames or a video to a new frame rate.