From 74abf40932fdbdaa225f030da68573fb8d2b6ae8 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Wed, 29 Jan 2014 00:18:40 -0600 Subject: [PATCH] Fixed bugs in new AudioReaderSource class. Also fixed a few small issues in the FFmpegReader class. --- include/AudioReaderSource.h | 13 +++--- src/AudioReaderSource.cpp | 90 +++++++++++++++++++++++++------------ src/FFmpegReader.cpp | 2 +- src/Main.cpp | 22 ++++++--- 4 files changed, 86 insertions(+), 41 deletions(-) diff --git a/include/AudioReaderSource.h b/include/AudioReaderSource.h index b78c5a69..8b70982f 100644 --- a/include/AudioReaderSource.h +++ b/include/AudioReaderSource.h @@ -54,15 +54,16 @@ namespace openshot class AudioReaderSource : public PositionableAudioSource { private: - int position; - int start; - bool repeat; - AudioSampleBuffer *buffer; + int position; /// The position of the audio source (index of buffer) + bool repeat; /// Repeat the audio source when finished + int size; /// The size of the internal buffer + AudioSampleBuffer *buffer; /// The audio sample buffer - int size; /// The size of the buffer ReaderBase *reader; /// The reader to pull samples from - int64 frame_number; /// The current frame to read from + int64 original_frame_number; /// The current frame to read from + int64 frame_number; /// The current frame number tr1::shared_ptr frame; /// The current frame object that is being read + int frame_position; /// The position of the current frame's buffer /// Get more samples from the reader void GetMoreSamplesFromReader(); diff --git a/src/AudioReaderSource.cpp b/src/AudioReaderSource.cpp index 2d2ece8e..c85b927c 100644 --- a/src/AudioReaderSource.cpp +++ b/src/AudioReaderSource.cpp @@ -32,7 +32,8 @@ using namespace openshot; // Constructor that reads samples from a reader AudioReaderSource::AudioReaderSource(ReaderBase *audio_reader, int64 starting_frame_number, int buffer_size) - : reader(audio_reader), frame_number(starting_frame_number), size(buffer_size) { + : reader(audio_reader), frame_number(starting_frame_number), original_frame_number(starting_frame_number), + size(buffer_size), position(0), frame_position(0) { // Initialize an audio buffer (based on reader) buffer = new juce::AudioSampleBuffer(reader->info.channels, size); @@ -51,55 +52,86 @@ AudioReaderSource::~AudioReaderSource() // Get more samples from the reader void AudioReaderSource::GetMoreSamplesFromReader() { + // Determine the amount of samples needed to fill up this buffer - int amount_needed = start; // replace these used samples - int amount_remaining = size - start; + int amount_needed = position; // replace these used samples + int amount_remaining = size - amount_needed; // these are unused samples, and need to be carried forward if (!frame) { // If no frame, load entire buffer amount_needed = size; - amount_remaining = size; + amount_remaining = 0; } // Init new buffer juce::AudioSampleBuffer *new_buffer = new juce::AudioSampleBuffer(reader->info.channels, size); + new_buffer->clear(); // Move the remaining samples into new buffer (if any) - if (start > 0) { + if (amount_remaining > 0) { for (int channel = 0; channel < buffer->getNumChannels(); channel++) - new_buffer->copyFrom(channel, 0, *buffer, channel, start, amount_remaining); - start = amount_remaining; - } + new_buffer->addFrom(channel, 0, *buffer, channel, position, amount_remaining); + position = amount_remaining; + } else + // reset position to 0 + position = 0; // Loop through frames until buffer filled - int fill_start = start; while (amount_needed > 0) { - // Get the next frame - try { - frame = reader->GetFrame(frame_number++); - } catch (const ReaderClosed & e) { - break; - } catch (const TooManySeeks & e) { - break; - } catch (const OutOfBoundsFrame & e) { - break; - } + // Get the next frame (if position is zero) + if (frame_position == 0) { + try { + // Get frame object + frame = reader->GetFrame(frame_number++); - // Is buffer big enough to hold entire frame - if (fill_start + frame->GetAudioSamplesCount() > size) { - // Increase size of buffer - new_buffer->setSize(frame->GetAudioChannelsCount(), fill_start + frame->GetAudioSamplesCount(), true, true, false); - size = new_buffer->getNumSamples(); + } catch (const ReaderClosed & e) { + break; + } catch (const TooManySeeks & e) { + break; + } catch (const OutOfBoundsFrame & e) { + break; + } } - // Load all of its samples into the buffer - for (int channel = 0; channel < new_buffer->getNumChannels(); channel++) - new_buffer->copyFrom(channel, fill_start, *frame->GetAudioSampleBuffer(), channel, 0, frame->GetAudioSamplesCount()); + bool frame_completed = false; + int amount_to_copy = frame->GetAudioSamplesCount(); + if (amount_to_copy > amount_needed) { + // Don't copy too many samples (we don't want to overflow the buffer) + amount_to_copy = amount_needed; + amount_needed = 0; + } else { + // Not enough to fill the buffer (so use the entire frame) + amount_needed -= amount_to_copy; + frame_completed = true; + } + + if (frame->number > 200) { + frame->DisplayWaveform(); + for (int y = 0; y < frame->GetAudioSamplesCount(); y++) + cout << y << ": " << frame->GetAudioSampleBuffer()->getSampleData(0)[y] << endl; + + // Load all of its samples into the buffer + for (int channel = 0; channel < new_buffer->getNumChannels(); channel++) + new_buffer->addFrom(channel, position, *frame->GetAudioSampleBuffer(), channel, frame_position, amount_to_copy); + } // Adjust remaining samples - amount_remaining -= fill_start + frame->GetAudioSamplesCount(); - fill_start += frame->GetAudioSamplesCount(); + position += amount_to_copy; + if (frame_completed) + // Reset frame buffer position (which will load a new frame on the next loop) + frame_position = 0; + else + // Continue tracking the current frame's position + frame_position += amount_to_copy; } + + // Delete old buffer + buffer->clear(); + delete buffer; + + // Replace buffer and reset position + buffer = new_buffer; + position = 0; } // Get the next block of audio samples diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 0b1307ef..d04710d4 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -1290,7 +1290,7 @@ tr1::shared_ptr FFmpegReader::CreateFrame(int requested_frame) else { // Create a new frame on the working cache - tr1::shared_ptr f(new Frame(requested_frame, info.width, info.height, "#000000", 0, info.channels)); + tr1::shared_ptr f(new Frame(requested_frame, info.width, info.height, "#000000", Frame::GetSamplesPerFrame(requested_frame, info.fps, info.sample_rate), info.channels)); f->SetPixelRatio(info.pixel_ratio.num, info.pixel_ratio.den); working_cache.Add(requested_frame, f); diff --git a/src/Main.cpp b/src/Main.cpp index cee22e4b..b23b3196 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -40,11 +40,23 @@ using namespace tr1; int main(int argc, char* argv[]) { - FFmpegReader r99("/home/jonathan/Videos/sintel_trailer-720p.mp4"); - r99.Open(); - for (int count99 = 1; count99 < 10000000; count99++) { - cout << count99 << endl; - r99.GetFrame(count99); + FFmpegReader sinelReader("/home/jonathan/Videos/sintel_trailer-720p.mp4"); + sinelReader.Open(); + + AudioReaderSource readerSource(&sinelReader, 1, 10000); + for (int z = 0; z < 2000; z++) { + // Get audio chunks + int chunk_size = 750; + juce::AudioSampleBuffer *master_buffer = new juce::AudioSampleBuffer(sinelReader.info.channels, chunk_size); + master_buffer->clear(); + const AudioSourceChannelInfo info = {master_buffer, 0, chunk_size}; + + // Get next audio block + readerSource.getNextAudioBlock(info); + + // Delete buffer + master_buffer->clear(); + delete master_buffer; } return 0;