diff --git a/include/Timeline.h b/include/Timeline.h index 0ef6741b..fd330bf0 100644 --- a/include/Timeline.h +++ b/include/Timeline.h @@ -172,6 +172,9 @@ namespace openshot { /// @param include Include or Exclude intersecting clips vector find_intersecting_clips(long int requested_frame, int number_of_frames, bool include); + /// Get or generate a blank frame + tr1::shared_ptr GetOrCreateFrame(Clip* clip, long int number); + /// Apply effects to the source frame (if any) tr1::shared_ptr apply_effects(tr1::shared_ptr frame, long int timeline_frame_number, int layer); diff --git a/src/FrameMapper.cpp b/src/FrameMapper.cpp index 942f85e8..5b1ac2ac 100644 --- a/src/FrameMapper.cpp +++ b/src/FrameMapper.cpp @@ -713,7 +713,7 @@ void FrameMapper::ResampleMappedAudio(tr1::shared_ptr 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, 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)); diff --git a/src/Qt/AudioPlaybackThread.cpp b/src/Qt/AudioPlaybackThread.cpp index 390280cc..689b4ef7 100644 --- a/src/Qt/AudioPlaybackThread.cpp +++ b/src/Qt/AudioPlaybackThread.cpp @@ -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") { diff --git a/src/Timeline.cpp b/src/Timeline.cpp index 092570e7..ee0c59fe 100644 --- a/src/Timeline.cpp +++ b/src/Timeline.cpp @@ -192,12 +192,42 @@ tr1::shared_ptr Timeline::apply_effects(tr1::shared_ptr frame, lon return frame; } +// Get or generate a blank frame +tr1::shared_ptr Timeline::GetOrCreateFrame(Clip* clip, long int number) +{ + tr1::shared_ptr 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(clip->GetFrame(number)); + new_frame = tr1::shared_ptr(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(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 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 source_frame; - source_frame = tr1::shared_ptr(source_clip->GetFrame(clip_frame_number)); + tr1::shared_ptr source_frame = GetOrCreateFrame(source_clip, clip_frame_number); // No frame found... so bail if (!source_frame) @@ -603,6 +633,29 @@ tr1::shared_ptr 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