Fixed some major issues with the frame mapper. openshot::FrameMapper is now fully multi-threaded. Fixed a bug in calculating the # of samples on a frame (to always be evenly divisible by the # of channels).

This commit is contained in:
Jonathan Thomas
2015-03-08 21:42:53 -05:00
parent db4a5a7948
commit 591cfbdb5a
8 changed files with 187 additions and 142 deletions

View File

@@ -233,10 +233,10 @@ namespace openshot
int GetHeight();
/// Calculate the # of samples per video frame (for the current frame number)
int GetSamplesPerFrame(Fraction fps, int sample_rate);
int GetSamplesPerFrame(Fraction fps, int sample_rate, int channels);
/// Calculate the # of samples per video frame (for a specific frame number and frame rate)
static int GetSamplesPerFrame(int frame_number, Fraction fps, int sample_rate);
static int GetSamplesPerFrame(int frame_number, Fraction fps, int sample_rate, int channels);
/// Get an audio waveform image
tr1::shared_ptr<Magick::Image> GetWaveform(int width, int height, int Red, int Green, int Blue);

View File

@@ -40,8 +40,11 @@
#include "../include/Exceptions.h"
#include "../include/KeyFrame.h"
// Include FFmpeg headers and macros
#include "FFmpegUtilities.h"
#include "OpenMPUtilities.h"
using namespace std;
@@ -196,7 +199,7 @@ namespace openshot
void PrintMapping();
/// Resample audio and map channels (if needed)
void ResampleMappedAudio(tr1::shared_ptr<Frame> frame);
void ResampleMappedAudio(tr1::shared_ptr<Frame> frame, int original_frame_number);
};
}

View File

@@ -214,7 +214,7 @@ void AudioReaderSource::getNextAudioBlock (const AudioSourceChannelInfo& info)
}
// Adjust estimate frame number (the estimated frame number that is being played)
estimated_samples_per_frame = Frame::GetSamplesPerFrame(estimated_frame, reader->info.fps, reader->info.sample_rate);
estimated_samples_per_frame = Frame::GetSamplesPerFrame(estimated_frame, reader->info.fps, reader->info.sample_rate, buffer_channels);
if (speed == 1)
estimated_frame += double(info.numSamples) / double(estimated_samples_per_frame);
}

View File

@@ -305,7 +305,7 @@ tr1::shared_ptr<Frame> Clip::get_time_mapped_frame(tr1::shared_ptr<Frame> frame,
int new_frame_number = time.GetInt(frame_number);
// Create a new frame
int samples_in_frame = Frame::GetSamplesPerFrame(new_frame_number, reader->info.fps, reader->info.sample_rate);
int samples_in_frame = Frame::GetSamplesPerFrame(new_frame_number, reader->info.fps, reader->info.sample_rate, frame->GetAudioChannelsCount());
new_frame = tr1::shared_ptr<Frame>(new Frame(new_frame_number, 1, 1, "#000000", samples_in_frame, frame->GetAudioChannelsCount()));
// Copy the image from the new frame

View File

@@ -937,7 +937,7 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
while (pts_remaining_samples)
{
// Get Samples per frame (for this frame number)
int samples_per_frame = Frame::GetSamplesPerFrame(previous_packet_location.frame, info.fps, info.sample_rate);
int samples_per_frame = Frame::GetSamplesPerFrame(previous_packet_location.frame, info.fps, info.sample_rate, info.channels);
// Calculate # of samples to add to this frame
int samples = samples_per_frame - previous_packet_location.sample_start;
@@ -980,8 +980,11 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
audio_converted->nb_samples = audio_frame->nb_samples;
av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_frame->nb_samples, AV_SAMPLE_FMT_S16, 0);
AVAudioResampleContext *avr = NULL;
#pragma ordered
{
// setup resample context
AVAudioResampleContext *avr = avresample_alloc_context();
avr = avresample_alloc_context();
av_opt_set_int(avr, "in_channel_layout", aCodecCtx->channel_layout, 0);
av_opt_set_int(avr, "out_channel_layout", aCodecCtx->channel_layout, 0);
av_opt_set_int(avr, "in_sample_fmt", aCodecCtx->sample_fmt, 0);
@@ -1001,6 +1004,7 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
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
memcpy(audio_buf, audio_converted->data[0], audio_converted->nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * info.channels);
@@ -1061,7 +1065,7 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
while (remaining_samples > 0)
{
// Get Samples per frame (for this frame number)
int samples_per_frame = Frame::GetSamplesPerFrame(starting_frame_number, info.fps, info.sample_rate);
int samples_per_frame = Frame::GetSamplesPerFrame(starting_frame_number, info.fps, info.sample_rate, info.channels);
// Calculate # of samples to add to this frame
int samples = samples_per_frame - start;
@@ -1355,7 +1359,7 @@ AudioLocation FFmpegReader::GetAudioPTSLocation(int pts)
double sample_start_percentage = frame - double(whole_frame);
// Get Samples per frame
int samples_per_frame = Frame::GetSamplesPerFrame(whole_frame, info.fps, info.sample_rate);
int samples_per_frame = Frame::GetSamplesPerFrame(whole_frame, info.fps, info.sample_rate, info.channels);
// Calculate the sample # to start on
int sample_start = round(double(samples_per_frame) * sample_start_percentage);
@@ -1415,7 +1419,7 @@ tr1::shared_ptr<Frame> FFmpegReader::CreateFrame(int requested_frame)
else
{
// Create a new frame on the working cache
tr1::shared_ptr<Frame> f(new Frame(requested_frame, info.width, info.height, "#000000", Frame::GetSamplesPerFrame(requested_frame, info.fps, info.sample_rate), info.channels));
tr1::shared_ptr<Frame> f(new Frame(requested_frame, info.width, info.height, "#000000", Frame::GetSamplesPerFrame(requested_frame, info.fps, info.sample_rate, info.channels), info.channels));
f->SetPixelRatio(info.pixel_ratio.num, info.pixel_ratio.den); // update pixel ratio
f->ChannelsLayout(info.channel_layout); // update audio channel layout from the parent reader
f->SampleRate(info.sample_rate); // update the frame's sample rate of the parent reader

View File

@@ -454,23 +454,31 @@ void Frame::SetFrameNumber(int new_number)
}
// Calculate the # of samples per video frame (for a specific frame number and frame rate)
int Frame::GetSamplesPerFrame(int number, Fraction fps, int sample_rate)
int Frame::GetSamplesPerFrame(int number, Fraction fps, int sample_rate, int channels)
{
// Get the total # of samples for the previous frame, and the current frame (rounded)
double fps_rate = fps.Reciprocal().ToDouble();
double previous_samples = round((sample_rate * fps_rate) * (number - 1));
double total_samples = round((sample_rate * fps_rate) * number);
// Determine previous samples total, and make sure it's evenly divisible by the # of channels
double previous_samples = (sample_rate * fps_rate) * (number - 1);
double previous_samples_remainder = fmod(previous_samples, (double)channels); // subtract the remainder to the total (to make it evenly divisible)
previous_samples -= previous_samples_remainder;
// Determine the current samples total, and make sure it's evenly divisible by the # of channels
double total_samples = (sample_rate * fps_rate) * number;
double total_samples_remainder = fmod(total_samples, (double)channels); // subtract the remainder to the total (to make it evenly divisible)
total_samples -= total_samples_remainder;
// Subtract the previous frame's total samples with this frame's total samples. Not all sample rates can
// be evenly divided into frames, so each frame can have have different # of samples.
double samples_per_frame = total_samples - previous_samples;
int samples_per_frame = round(total_samples - previous_samples);
return samples_per_frame;
}
// Calculate the # of samples per video frame (for the current frame number)
int Frame::GetSamplesPerFrame(Fraction fps, int sample_rate)
int Frame::GetSamplesPerFrame(Fraction fps, int sample_rate, int channels)
{
return GetSamplesPerFrame(number, fps, sample_rate);
return GetSamplesPerFrame(number, fps, sample_rate, channels);
}
// Get height of image

View File

@@ -230,12 +230,12 @@ void FrameMapper::Init()
// the original sample rate.
int end_samples_frame = start_samples_frame;
int end_samples_position = start_samples_position;
int remaining_samples = Frame::GetSamplesPerFrame(frame_number, target, reader->info.sample_rate);
int remaining_samples = Frame::GetSamplesPerFrame(frame_number, target, reader->info.sample_rate, reader->info.channels);
while (remaining_samples > 0)
{
// get original samples
int original_samples = Frame::GetSamplesPerFrame(end_samples_frame, original, reader->info.sample_rate) - end_samples_position;
int original_samples = Frame::GetSamplesPerFrame(end_samples_frame, original, reader->info.sample_rate, reader->info.channels) - end_samples_position;
// Enough samples
if (original_samples >= remaining_samples)
@@ -255,12 +255,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(frame_number, target, reader->info.sample_rate)};
SampleRange Samples = {start_samples_frame, start_samples_position, end_samples_frame, end_samples_position, Frame::GetSamplesPerFrame(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(start_samples_frame, original, reader->info.sample_rate))
if (start_samples_position >= Frame::GetSamplesPerFrame(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
@@ -311,100 +311,128 @@ tr1::shared_ptr<Frame> FrameMapper::GetFrame(int requested_frame) throw(ReaderCl
if (final_cache.Exists(requested_frame))
return final_cache.GetFrame(requested_frame);
// Get the mapped frame
MappedFrame mapped = GetMappedFrame(requested_frame);
tr1::shared_ptr<Frame> mapped_frame = reader->GetFrame(mapped.Odd.Frame);
int channels_in_frame = mapped_frame->GetAudioChannelsCount();
// Return the original frame if no mapping is needed
if (original.num == info.fps.num && original.den == info.fps.den &&
info.sample_rate == mapped_frame->SampleRate() && info.channels == mapped_frame->GetAudioChannelsCount() &&
info.channel_layout == mapped_frame->ChannelsLayout())
// Return original frame (performance optimization)
return mapped_frame;
// Minimum number of frames to process (for performance reasons)
int minimum_frames = OPEN_MP_NUM_PROCESSORS;
// Set the number of threads in OpenMP
omp_set_num_threads(OPEN_MP_NUM_PROCESSORS);
// Allow nested OpenMP sections
omp_set_nested(true);
// Init some basic properties about this frame
int samples_in_frame = Frame::GetSamplesPerFrame(requested_frame, target, mapped_frame->SampleRate());
// Create a new frame
tr1::shared_ptr<Frame> frame(new Frame(requested_frame, 1, 1, "#000000", samples_in_frame, channels_in_frame));
frame->SampleRate(mapped_frame->SampleRate());
#pragma omp critical (debug_output)
AppendDebugMethod("FrameMapper::GetFrame", "requested_frame", requested_frame, "target.num", target.num, "target.den", target.den, "mapped_frame->SampleRate()", mapped_frame->SampleRate(), "samples_in_frame", samples_in_frame, "mapped_frame->GetAudioSamplesCount()", mapped_frame->GetAudioSamplesCount());
// Copy the image from the odd field
frame->AddImage(reader->GetFrame(mapped.Odd.Frame)->GetImage(), true);
if (mapped.Odd.Frame != mapped.Even.Frame)
// Add even lines (if different than the previous image)
frame->AddImage(reader->GetFrame(mapped.Even.Frame)->GetImage(), false);
// Copy the samples
int samples_copied = 0;
int starting_frame = mapped.Samples.frame_start;
while (samples_copied < mapped.Samples.total)
#pragma omp parallel
{
// Init number of samples to copy this iteration
int remaining_samples = mapped.Samples.total - samples_copied;
int number_to_copy = 0;
// Loop through each channel
for (int channel = 0; channel < channels_in_frame; channel++)
#pragma omp single
{
// number of original samples on this frame
tr1::shared_ptr<Frame> original_frame = reader->GetFrame(starting_frame);
int original_samples = original_frame->GetAudioSamplesCount();
// Debug output
#pragma omp critical (debug_output)
AppendDebugMethod("FrameMapper::GetFrame (Loop through frames)", "requested_frame", requested_frame, "minimum_frames", minimum_frames, "", -1, "", -1, "", -1, "", -1);
if (starting_frame == mapped.Samples.frame_start)
// Loop through all requested frames
for (int frame_number = requested_frame; frame_number < requested_frame + minimum_frames; frame_number++)
{
// Starting frame (take the ending samples)
number_to_copy = original_samples - mapped.Samples.sample_start;
if (number_to_copy > remaining_samples)
number_to_copy = remaining_samples;
#pragma omp task firstprivate(frame_number)
{
// Add samples to new frame
frame->AddAudio(true, channel, samples_copied, original_frame->GetAudioSamples(channel) + mapped.Samples.sample_start, number_to_copy, 1.0);
}
else if (starting_frame > mapped.Samples.frame_start && starting_frame < mapped.Samples.frame_end)
// Get the mapped frame
MappedFrame mapped = GetMappedFrame(frame_number);
tr1::shared_ptr<Frame> mapped_frame = reader->GetFrameSafe(mapped.Odd.Frame);
int channels_in_frame = mapped_frame->GetAudioChannelsCount();
// Init some basic properties about this frame
int samples_in_frame = Frame::GetSamplesPerFrame(frame_number, target, mapped_frame->SampleRate(), channels_in_frame);
// Create a new frame
tr1::shared_ptr<Frame> frame(new Frame(frame_number, 1, 1, "#000000", samples_in_frame, channels_in_frame));
frame->SampleRate(mapped_frame->SampleRate());
// Copy the image from the odd field
frame->AddImage(reader->GetFrameSafe(mapped.Odd.Frame)->GetImage(), true);
if (mapped.Odd.Frame != mapped.Even.Frame)
// Add even lines (if different than the previous image)
frame->AddImage(reader->GetFrameSafe(mapped.Even.Frame)->GetImage(), false);
// Copy the samples
int samples_copied = 0;
int starting_frame = mapped.Samples.frame_start;
while (samples_copied < mapped.Samples.total)
{
// Middle frame (take all samples)
number_to_copy = original_samples;
if (number_to_copy > remaining_samples)
number_to_copy = remaining_samples;
// Init number of samples to copy this iteration
int remaining_samples = mapped.Samples.total - samples_copied;
int number_to_copy = 0;
// Add samples to new frame
frame->AddAudio(true, channel, samples_copied, original_frame->GetAudioSamples(channel), number_to_copy, 1.0);
// Loop through each channel
for (int channel = 0; channel < channels_in_frame; channel++)
{
// number of original samples on this frame
tr1::shared_ptr<Frame> original_frame = reader->GetFrameSafe(starting_frame);
int original_samples = original_frame->GetAudioSamplesCount();
if (starting_frame == mapped.Samples.frame_start)
{
// Starting frame (take the ending samples)
number_to_copy = original_samples - mapped.Samples.sample_start;
if (number_to_copy > remaining_samples)
number_to_copy = remaining_samples;
// Add samples to new frame
#pragma omp critical (openshot_adding_audio)
frame->AddAudio(true, channel, samples_copied, original_frame->GetAudioSamples(channel) + mapped.Samples.sample_start, number_to_copy, 1.0);
}
else if (starting_frame > mapped.Samples.frame_start && starting_frame < mapped.Samples.frame_end)
{
// Middle frame (take all samples)
number_to_copy = original_samples;
if (number_to_copy > remaining_samples)
number_to_copy = remaining_samples;
// Add samples to new frame
#pragma omp critical (openshot_adding_audio)
frame->AddAudio(true, channel, samples_copied, original_frame->GetAudioSamples(channel), number_to_copy, 1.0);
}
else
{
// Ending frame (take the beginning samples)
number_to_copy = mapped.Samples.sample_end;
if (number_to_copy > remaining_samples)
number_to_copy = remaining_samples;
// Add samples to new frame
#pragma omp critical (openshot_adding_audio)
frame->AddAudio(false, channel, samples_copied, original_frame->GetAudioSamples(channel), number_to_copy, 1.0);
}
}
// increment frame
samples_copied += number_to_copy;
starting_frame++;
}
else
{
// Ending frame (take the beginning samples)
number_to_copy = mapped.Samples.sample_end;
if (number_to_copy > remaining_samples)
number_to_copy = remaining_samples;
// Add samples to new frame
frame->AddAudio(false, channel, samples_copied, original_frame->GetAudioSamples(channel), number_to_copy, 1.0);
}
}
// increment frame
samples_copied += number_to_copy;
starting_frame++;
}
// Resample audio on frame (if needed)
if (info.sample_rate != frame->SampleRate() || info.channels != frame->GetAudioChannelsCount() ||
info.channel_layout != frame->ChannelsLayout())
// Resample audio and correct # of channels if needed
ResampleMappedAudio(frame);
// Resample audio on frame (if needed)
if (info.sample_rate != frame->SampleRate() || info.channels != frame->GetAudioChannelsCount() ||
info.channel_layout != frame->ChannelsLayout())
// Resample audio and correct # of channels if needed
#pragma ordered
ResampleMappedAudio(frame, mapped.Odd.Frame);
// Add frame to final cache
final_cache.Add(frame->number, frame);
// Add frame to final cache
#pragma omp critical (openshot_cache)
final_cache.Add(frame->number, frame);
} // omp task
// TODO: Fix this bug. Wait on the task to complete. This is not ideal, but solves an issue with the
// audio_frame being modified by the next call to this method. I think this is a scope issue with OpenMP.
#pragma omp taskwait
} // for loop
} // omp single
} // omp parallel
// Return processed 'frame'
return final_cache.GetFrame(frame->number);
return final_cache.GetFrame(requested_frame);
}
void FrameMapper::PrintMapping()
@@ -465,15 +493,15 @@ void FrameMapper::Close()
#pragma omp critical (debug_output)
AppendDebugMethod("FrameMapper::Open", "", -1, "", -1, "", -1, "", -1, "", -1, "", -1);
// Close internal reader
reader->Close();
// Deallocate resample buffer
if (avr) {
avresample_close(avr);
avresample_free(&avr);
avr = NULL;
}
// Close internal reader
reader->Close();
}
}
@@ -549,20 +577,11 @@ void FrameMapper::ChangeMapping(Fraction target_fps, PulldownType target_pulldow
info.channels = target_channels;
info.channel_layout = target_channel_layout;
// Deallocate resample buffer
if (avr) {
avresample_close(avr);
avresample_free(&avr);
avr = NULL;
}
}
// Resample audio and map channels (if needed)
void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame)
void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame, int original_frame_number)
{
#pragma omp critical (debug_output)
AppendDebugMethod("FrameMapper::ResampleMappedAudio", "frame->number", frame->number, "", -1, "", -1, "", -1, "", -1, "", -1);
// Init audio buffers / variables
int total_frame_samples = 0;
int channels_in_frame = frame->GetAudioChannelsCount();
@@ -570,6 +589,9 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame)
int samples_in_frame = frame->GetAudioSamplesCount();
ChannelLayout channel_layout_in_frame = frame->ChannelsLayout();
#pragma omp critical (debug_output)
AppendDebugMethod("FrameMapper::ResampleMappedAudio", "frame->number", frame->number, "channels_in_frame", channels_in_frame, "samples_in_frame", samples_in_frame, "sample_rate_in_frame", sample_rate_in_frame, "", -1, "", -1);
// Get audio sample array
float* frame_samples_float = NULL;
// Get samples interleaved together (c1 c2 c1 c2 c1 c2)
@@ -610,41 +632,47 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame)
}
// Update total samples & input frame size (due to bigger or smaller data types)
total_frame_samples *= (float(info.sample_rate) / sample_rate_in_frame); // adjust for different byte sizes
total_frame_samples *= (float(info.channels) / channels_in_frame); // adjust for different # of channels
//total_frame_samples = round((float)total_frame_samples * (float(info.sample_rate) / sample_rate_in_frame) * (float(info.channels) / channels_in_frame)) + 1; // adjust for different byte sizes and channels
total_frame_samples = Frame::GetSamplesPerFrame(original_frame_number, target, info.sample_rate, info.channels);
#pragma omp critical (debug_output)
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);
// Create output frame (and allocate arrays)
AVFrame *audio_converted = avcodec_alloc_frame();
avcodec_get_frame_defaults(audio_converted);
audio_converted->nb_samples = audio_frame->nb_samples;
av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, audio_frame->nb_samples, AV_SAMPLE_FMT_S16, 0);
audio_converted->nb_samples = total_frame_samples;
av_samples_alloc(audio_converted->data, audio_converted->linesize, info.channels, total_frame_samples, AV_SAMPLE_FMT_S16, 0);
#pragma omp critical (debug_output)
AppendDebugMethod("FrameMapper::ResampleMappedAudio (preparing for resample)", "in_sample_fmt", AV_SAMPLE_FMT_S16, "out_sample_fmt", AV_SAMPLE_FMT_S16, "in_sample_rate", sample_rate_in_frame, "out_sample_rate", info.sample_rate, "in_channels", channels_in_frame, "out_channels", info.channels);
// setup resample context
if (!avr) {
avr = avresample_alloc_context();
av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
av_opt_set_int(avr, "out_channels", info.channels, 0);
avresample_open(avr);
}
int nb_samples = 0;
#pragma omp critical (openshot_audio_resample)
{
// setup resample context
if (!avr) {
avr = avresample_alloc_context();
av_opt_set_int(avr, "in_channel_layout", channel_layout_in_frame, 0);
av_opt_set_int(avr, "out_channel_layout", info.channel_layout, 0);
av_opt_set_int(avr, "in_sample_fmt", AV_SAMPLE_FMT_S16, 0);
av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
av_opt_set_int(avr, "in_sample_rate", sample_rate_in_frame, 0);
av_opt_set_int(avr, "out_sample_rate", info.sample_rate, 0);
av_opt_set_int(avr, "in_channels", channels_in_frame, 0);
av_opt_set_int(avr, "out_channels", info.channels, 0);
avresample_open(avr);
}
// Convert audio samples
nb_samples = avresample_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
// Convert audio samples
nb_samples = avresample_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
}
// Create a new array (to hold all resampled S16 audio samples)
int16_t* resampled_samples = new int16_t[nb_samples * info.channels];
@@ -661,6 +689,7 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame)
// Resize the frame to hold the right # of channels and samples
int channel_buffer_size = nb_samples;
#pragma omp critical (openshot_adding_audio)
frame->ResizeAudio(info.channels, channel_buffer_size, info.sample_rate, info.channel_layout);
#pragma omp critical (debug_output)
@@ -702,10 +731,11 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame)
}
// Add samples to frame for this channel
frame->AddAudio(true, channel_filter, 0, channel_buffer, position - 1, 1.0f);
#pragma omp critical (openshot_adding_audio)
frame->AddAudio(true, channel_filter, 0, channel_buffer, position, 1.0f);
#pragma omp critical (debug_output)
AppendDebugMethod("FrameMapper::ResampleMappedAudio (Add audio to channel)", "number of samples", position - 1, "channel_filter", channel_filter, "", -1, "", -1, "", -1, "", -1);
AppendDebugMethod("FrameMapper::ResampleMappedAudio (Add audio to channel)", "number of samples", position, "channel_filter", channel_filter, "", -1, "", -1, "", -1, "", -1);
}
// clear channel buffer

View File

@@ -48,9 +48,9 @@ int main(int argc, char* argv[])
r9.debug = false;
// Mapper
FrameMapper map(&r9, Fraction(24,1), PULLDOWN_NONE, 44100, 2, LAYOUT_STEREO);
FrameMapper map(&r9, Fraction(30,1), PULLDOWN_NONE, 48000, 2, LAYOUT_STEREO);
map.DisplayInfo();
map.debug = false;
map.debug = true;
map.Open();
/* WRITER ---------------- */
@@ -59,7 +59,7 @@ int main(int argc, char* argv[])
//ImageWriter w9("/home/jonathan/output.gif");
// Set options
w9.SetAudioOptions(true, "libmp3lame", r9.info.sample_rate, r9.info.channels, r9.info.channel_layout, 120000);
w9.SetAudioOptions(true, "libmp3lame", map.info.sample_rate, map.info.channels, map.info.channel_layout, 120000);
//w9.SetAudioOptions(true, "libmp3lame", 44100, r9.info.channels, r9.info.channel_layout, 120000);
//w9.SetVideoOptions(true, "libvpx", map.info.fps, map.info.width, map.info.height, map.info.pixel_ratio, false, false, 1500000);
//w9.SetVideoOptions(true, "rawvideo", r9.info.fps, 400, 2, r9.info.pixel_ratio, false, false, 20000000);
@@ -93,7 +93,7 @@ int main(int argc, char* argv[])
int frame_number = ( frame);
cout << "get " << frame << " (frame: " << frame_number << ") " << endl;
tr1::shared_ptr<Frame> f = r9.GetFrame(frame_number);
tr1::shared_ptr<Frame> f = map.GetFrame(frame_number);
cout << "display it (" << f->number << ", " << f << ")" << endl;
//r9.GetFrame(frame_number)->DisplayWaveform();
//if (frame == 49)