Laying the ground work for audio mapping (resampling and changing channel layouts) for the openshot::FrameMapper. This is important for use with the Timeline, that all clips have a common frame rate, sample rate, and channel layout.

This commit is contained in:
Jonathan Thomas
2015-02-26 17:33:09 -06:00
parent 770b1ddb06
commit ea9885f9a9
5 changed files with 58 additions and 36 deletions

View File

@@ -30,8 +30,9 @@
using namespace std;
using namespace openshot;
FrameMapper::FrameMapper(ReaderBase *reader, Fraction target, PulldownType pulldown) :
reader(reader), target(target), pulldown(pulldown), final_cache(820 * 1024)
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), sample_rate(target_sample_rate), channels(target_channels), channel_layout(target_channel_layout),
final_cache(820 * 1024), is_dirty(true)
{
// Set the original frame rate from the reader
original = Fraction(reader->info.fps.num, reader->info.fps.den);
@@ -80,6 +81,12 @@ void FrameMapper::Init()
fields.clear();
frames.clear();
// Mark as not dirty
is_dirty = false;
// Clear cache
final_cache.Clear();
// Some framerates are handled special, and some use a generic Keyframe curve to
// map the framerates. These are the special framerates:
if ((original.ToInt() == 24 || original.ToInt() == 25 || original.ToInt() == 30) &&
@@ -290,6 +297,11 @@ MappedFrame FrameMapper::GetMappedFrame(int TargetFrameNumber) throw(OutOfBounds
// Get an openshot::Frame object for a specific frame number of this reader.
tr1::shared_ptr<Frame> FrameMapper::GetFrame(int requested_frame) throw(ReaderClosed)
{
// Check if mappings are dirty (and need to be recalculated)
if (is_dirty)
// Recalculate mappings
Init();
// Check final cache, and just return the frame (if it's available)
if (final_cache.Exists(requested_frame))
return final_cache.GetFrame(requested_frame);
@@ -297,6 +309,14 @@ tr1::shared_ptr<Frame> FrameMapper::GetFrame(int requested_frame) throw(ReaderCl
// Get the mapped frame
MappedFrame mapped = GetMappedFrame(requested_frame);
// Return the original frame if no mapping is needed
if (reader->info.fps.num == target.num && reader->info.fps.den == target.den &&
reader->info.sample_rate == sample_rate && reader->info.channels == channels &&
reader->info.channel_layout == channel_layout)
// Return original frame (performance optimization)
return reader->GetFrame(mapped.Odd.Frame);
// Init some basic properties about this frame
int samples_in_frame = Frame::GetSamplesPerFrame(requested_frame, target, info.sample_rate);
@@ -484,3 +504,18 @@ void FrameMapper::SetJsonValue(Json::Value root) throw(InvalidFile) {
Open();
}
}
// 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)
{
// Mark as dirty
is_dirty = true;
// Update mapping details
target = target_fps;
pulldown = target_pulldown;
sample_rate = target_sample_rate;
channels = target_channels;
channel_layout = target_channel_layout;
}