Skip to content

Commit

Permalink
Replacing audio fix implementation with ParentClip(), to access clip …
Browse files Browse the repository at this point in the history
…start and position (if any)
  • Loading branch information
jonoomph authored and ferdnyc committed Oct 19, 2020
1 parent a410941 commit ab49162
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 119 deletions.
12 changes: 5 additions & 7 deletions include/FrameMapper.h
Expand Up @@ -147,16 +147,16 @@ namespace openshot
bool is_dirty; // When this is true, the next call to GetFrame will re-init the mapping
SWRCONTEXT *avr; // Audio resampling context object

float position;
float start;

// Internal methods used by init
void AddField(int64_t frame);
void AddField(Field field);

// Get Frame or Generate Blank Frame
std::shared_ptr<Frame> 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);

// 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.
// This might repeat or skip fields and frames of the original video, depending on
Expand All @@ -169,13 +169,13 @@ namespace openshot
std::vector<MappedFrame> frames; // List of all frames

/// Default constructor for openshot::FrameMapper class
FrameMapper(ReaderBase *reader, Fraction target_fps, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout, float clipPosition, float clipStart);
FrameMapper(ReaderBase *reader, Fraction target_fps, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout);

/// Destructor
virtual ~FrameMapper();

/// Change frame rate or audio mapping details
void ChangeMapping(Fraction target_fps, PulldownType pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout, float clipPosition, float clipStart);
void ChangeMapping(Fraction target_fps, PulldownType pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout);

/// Close the openshot::FrameMapper and internal reader
void Close() override;
Expand Down Expand Up @@ -220,8 +220,6 @@ namespace openshot

/// Resample audio and map channels (if needed)
void ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t original_frame_number);

int64_t ConvPositon(int64_t clip_frame_number);
};
}

Expand Down
85 changes: 48 additions & 37 deletions src/FrameMapper.cpp
Expand Up @@ -29,11 +29,12 @@
*/

#include "../include/FrameMapper.h"
#include "../include/Clip.h"

using namespace std;
using namespace openshot;

FrameMapper::FrameMapper(ReaderBase *reader, Fraction target, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout, float clipPosition, float clipStart) :
FrameMapper::FrameMapper(ReaderBase *reader, Fraction target, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout) :
reader(reader), target(target), pulldown(target_pulldown), is_dirty(true), avr(NULL)
{
// Set the original frame rate from the reader
Expand All @@ -52,8 +53,6 @@ FrameMapper::FrameMapper(ReaderBase *reader, Fraction target, PulldownType targe
info.width = reader->info.width;
info.height = reader->info.height;

position = clipPosition;
start = clipStart;
// Used to toggle odd / even fields
field_toggle = true;

Expand Down Expand Up @@ -118,6 +117,15 @@ 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) &&
Expand Down Expand Up @@ -259,12 +267,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(ConvPositon(frame_number), target, reader->info.sample_rate, reader->info.channels);
int remaining_samples = Frame::GetSamplesPerFrame(AdjustFrameNumber(frame_number, clipPosition, clipStart), target, reader->info.sample_rate, reader->info.channels);

while (remaining_samples > 0)
{
// get original samples
int original_samples = Frame::GetSamplesPerFrame(ConvPositon(end_samples_frame), original, reader->info.sample_rate, reader->info.channels) - end_samples_position;
int original_samples = Frame::GetSamplesPerFrame(AdjustFrameNumber(end_samples_frame, clipPosition, clipStart), original, reader->info.sample_rate, reader->info.channels) - end_samples_position;

// Enough samples
if (original_samples >= remaining_samples)
Expand All @@ -284,12 +292,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(ConvPositon(frame_number), 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, clipPosition, clipStart), 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(ConvPositon(start_samples_frame), original, reader->info.sample_rate, reader->info.channels))
if (start_samples_position >= Frame::GetSamplesPerFrame(AdjustFrameNumber(start_samples_frame, clipPosition, clipStart), 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
Expand Down Expand Up @@ -355,8 +363,17 @@ std::shared_ptr<Frame> FrameMapper::GetOrCreateFrame(int64_t number)
{
std::shared_ptr<Frame> 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(ConvPositon(number), target, reader->info.sample_rate, reader->info.channels);
int samples_in_frame = Frame::GetSamplesPerFrame(AdjustFrameNumber(number, clipPosition, clipStart), target, reader->info.sample_rate, reader->info.channels);

try {
// Debug output
Expand Down Expand Up @@ -406,6 +423,15 @@ std::shared_ptr<Frame> 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;
Expand All @@ -429,7 +455,7 @@ std::shared_ptr<Frame> 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(ConvPositon(frame_number), target, mapped_frame->SampleRate(), channels_in_frame);
int samples_in_frame = Frame::GetSamplesPerFrame(AdjustFrameNumber(frame_number, clipPosition, clipStart), target, mapped_frame->SampleRate(), channels_in_frame);

// Determine if mapped frame is identical to source frame
// including audio sample distribution according to mapped.Samples,
Expand Down Expand Up @@ -598,21 +624,6 @@ void FrameMapper::PrintMapping()
// Recalculate mappings
Init();

// Get the difference (in frames) between the original and target frame rates
float difference = target.ToInt() - original.ToInt();

int field_interval = 0;
int frame_interval = 0;

if (difference != 0)
{
// Find the number (i.e. interval) of fields that need to be skipped or repeated
field_interval = round(fabs(original.ToInt() / difference));

// Get frame interval (2 fields per frame)
frame_interval = field_interval * 2.0f;
}

// Loop through frame mappings
for (float map = 1; map <= frames.size(); map++)
{
Expand All @@ -623,7 +634,6 @@ void FrameMapper::PrintMapping()

}


// Determine if reader is open or closed
bool FrameMapper::IsOpen() {
if (reader)
Expand All @@ -632,7 +642,6 @@ bool FrameMapper::IsOpen() {
return false;
}


// Open the internal reader
void FrameMapper::Open()
{
Expand Down Expand Up @@ -691,7 +700,6 @@ Json::Value FrameMapper::JsonValue() const {
// Create root json object
Json::Value root = ReaderBase::JsonValue(); // get parent properties
root["type"] = "FrameMapper";
root["position"] = position;

// return JsonValue
return root;
Expand Down Expand Up @@ -720,10 +728,6 @@ void FrameMapper::SetJsonValue(const Json::Value root) {
// Set parent data
ReaderBase::SetJsonValue(root);

if(!root["position"].isNull()){
position = root["position"].asDouble();
}

// Re-Open path, and re-init everything (if needed)
if (reader) {

Expand All @@ -733,7 +737,7 @@ void FrameMapper::SetJsonValue(const Json::Value root) {
}

// Change frame rate or audio mapping details
void FrameMapper::ChangeMapping(Fraction target_fps, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout, float clipPosition, float clipStart)
void FrameMapper::ChangeMapping(Fraction target_fps, PulldownType target_pulldown, int target_sample_rate, int target_channels, ChannelLayout target_channel_layout)
{
ZmqLogger::Instance()->AppendDebugMethod("FrameMapper::ChangeMapping", "target_fps.num", target_fps.num, "target_fps.den", target_fps.den, "target_pulldown", target_pulldown, "target_sample_rate", target_sample_rate, "target_channels", target_channels, "target_channel_layout", target_channel_layout);

Expand All @@ -752,9 +756,6 @@ void FrameMapper::ChangeMapping(Fraction target_fps, PulldownType target_pulldow
info.channels = target_channels;
info.channel_layout = target_channel_layout;

position = clipPosition;
start = clipStart;

// Clear cache
final_cache.Clear();

Expand All @@ -777,6 +778,15 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr<Frame> 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();
Expand Down Expand Up @@ -838,7 +848,7 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t orig
}

// Update total samples & input frame size (due to bigger or smaller data types)
total_frame_samples = Frame::GetSamplesPerFrame(ConvPositon(frame->number), target, info.sample_rate, info.channels);
total_frame_samples = Frame::GetSamplesPerFrame(AdjustFrameNumber(frame->number, clipPosition, clipStart), 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);

Expand Down Expand Up @@ -948,7 +958,8 @@ void FrameMapper::ResampleMappedAudio(std::shared_ptr<Frame> frame, int64_t orig
resampled_samples = NULL;
}

int64_t FrameMapper::ConvPositon(int64_t clip_frame_number){
// 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 clip_start_frame = (start * info.fps.ToDouble()) + 1;
int64_t clip_start_position = round(position * info.fps.ToDouble()) + 1;
Expand Down
4 changes: 2 additions & 2 deletions src/Timeline.cpp
Expand Up @@ -360,14 +360,14 @@ void Timeline::apply_mapper_to_clip(Clip* clip)
} else {

// Create a new FrameMapper to wrap the current reader
FrameMapper* mapper = new FrameMapper(clip->Reader(), info.fps, PULLDOWN_NONE, info.sample_rate, info.channels, info.channel_layout, clip->Position(), clip->Start());
FrameMapper* mapper = new FrameMapper(clip->Reader(), info.fps, PULLDOWN_NONE, info.sample_rate, info.channels, info.channel_layout);
allocated_frame_mappers.insert(mapper);
clip_reader = (ReaderBase*) mapper;
}

// Update the mapping
FrameMapper* clip_mapped_reader = (FrameMapper*) clip_reader;
clip_mapped_reader->ChangeMapping(info.fps, PULLDOWN_NONE, info.sample_rate, info.channels, info.channel_layout, clip->Position(), clip->Start());
clip_mapped_reader->ChangeMapping(info.fps, PULLDOWN_NONE, info.sample_rate, info.channels, info.channel_layout);

// Update clip reader
clip->Reader(clip_reader);
Expand Down

0 comments on commit ab49162

Please sign in to comment.