Fixed some audio popping issues related to audio buffer size and also resampling issues inside the FrameMapper class. Also made the Timeline more hardened, if a reader returns an error requesting a frame.

This commit is contained in:
Jonathan Thomas
2016-01-30 17:12:41 -06:00
parent 43fd4fccb1
commit 054175ddaa
4 changed files with 61 additions and 5 deletions

View File

@@ -172,6 +172,9 @@ namespace openshot {
/// @param include Include or Exclude intersecting clips
vector<Clip*> find_intersecting_clips(long int requested_frame, int number_of_frames, bool include);
/// Get or generate a blank frame
tr1::shared_ptr<Frame> GetOrCreateFrame(Clip* clip, long int number);
/// Apply effects to the source frame (if any)
tr1::shared_ptr<Frame> apply_effects(tr1::shared_ptr<Frame> frame, long int timeline_frame_number, int layer);

View File

@@ -713,7 +713,7 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame, long int ori
}
// Update total samples & input frame size (due to bigger or smaller data types)
total_frame_samples = Frame::GetSamplesPerFrame(frame->number, target, info.sample_rate, info.channels) + FF_INPUT_BUFFER_PADDING_SIZE;
total_frame_samples = Frame::GetSamplesPerFrame(frame->number, target, info.sample_rate, info.channels);
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);
@@ -755,7 +755,7 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr<Frame> frame, long int ori
}
// Create a new array (to hold all resampled S16 audio samples)
int16_t* resampled_samples = new int16_t[(nb_samples * info.channels) + FF_INPUT_BUFFER_PADDING_SIZE];
int16_t* resampled_samples = new int16_t[(nb_samples * info.channels)];
// Copy audio samples over original samples
memcpy(resampled_samples, audio_converted->data[0], (nb_samples * av_get_bytes_per_sample(AV_SAMPLE_FMT_S16) * info.channels));

View File

@@ -40,7 +40,7 @@ namespace openshot
, source(NULL)
, sampleRate(0.0)
, numChannels(0)
, buffer_size(10000)
, buffer_size(12000)
, is_playing(false)
, time_thread("audio-buffer")
{

View File

@@ -192,12 +192,42 @@ tr1::shared_ptr<Frame> Timeline::apply_effects(tr1::shared_ptr<Frame> frame, lon
return frame;
}
// Get or generate a blank frame
tr1::shared_ptr<Frame> Timeline::GetOrCreateFrame(Clip* clip, long int number)
{
tr1::shared_ptr<Frame> new_frame;
// Init some basic properties about this frame
int samples_in_frame = Frame::GetSamplesPerFrame(number, info.fps, info.sample_rate, info.channels);
try {
// Attempt to get a frame (but this could fail if a reader has just been closed)
//new_frame = tr1::shared_ptr<Frame>(clip->GetFrame(number));
new_frame = tr1::shared_ptr<Frame>(clip->GetFrame(number));
// Return real frame
return new_frame;
} catch (const ReaderClosed & e) {
// ...
} catch (const TooManySeeks & e) {
// ...
} catch (const OutOfBoundsFrame & e) {
// ...
}
// Create blank frame
new_frame = tr1::shared_ptr<Frame>(new Frame(number, info.width, info.height, "#000000", samples_in_frame, info.channels));
new_frame->SampleRate(info.sample_rate);
new_frame->ChannelsLayout(info.channel_layout);
return new_frame;
}
// Process a new layer of video or audio
void Timeline::add_layer(tr1::shared_ptr<Frame> new_frame, Clip* source_clip, long int clip_frame_number, long int timeline_frame_number, bool is_top_clip)
{
// Get the clip's frame & image
tr1::shared_ptr<Frame> source_frame;
source_frame = tr1::shared_ptr<Frame>(source_clip->GetFrame(clip_frame_number));
tr1::shared_ptr<Frame> source_frame = GetOrCreateFrame(source_clip, clip_frame_number);
// No frame found... so bail
if (!source_frame)
@@ -603,6 +633,29 @@ tr1::shared_ptr<Frame> Timeline::GetFrame(long int requested_frame) throw(Reader
// Debug output
AppendDebugMethod("Timeline::GetFrame", "requested_frame", requested_frame, "minimum_frames", minimum_frames, "OPEN_MP_NUM_PROCESSORS", OPEN_MP_NUM_PROCESSORS, "", -1, "", -1, "", -1);
// GENERATE CACHE FOR CLIPS (IN FRAME # SEQUENCE)
// Determine all clip frames, and request them in order (to keep resampled audio in sequence)
for (long int frame_number = requested_frame; frame_number < requested_frame + minimum_frames; frame_number++)
{
// Calculate time of timeline frame
float requested_time = calculate_time(frame_number, info.fps);
// Loop through clips
for (int clip_index = 0; clip_index < nearby_clips.size(); clip_index++)
{
// Get clip object from the iterator
Clip *clip = nearby_clips[clip_index];
bool does_clip_intersect = (clip->Position() <= requested_time && clip->Position() + clip->Duration() >= requested_time);
if (does_clip_intersect)
{
// Get clip frame #
float time_diff = (requested_time - clip->Position()) + clip->Start();
int clip_frame_number = round(time_diff * info.fps.ToFloat()) + 1;
// Cache clip object
clip->GetFrame(clip_frame_number);
}
}
}
#pragma omp parallel
{
// Loop through all requested frames