Fixed bugs in new AudioReaderSource class. Also fixed a few small issues in the FFmpegReader class.

This commit is contained in:
Jonathan Thomas
2014-01-29 00:18:40 -06:00
parent 4ee7ef9b6e
commit 74abf40932
4 changed files with 86 additions and 41 deletions

View File

@@ -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> 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();

View File

@@ -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

View File

@@ -1290,7 +1290,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", 0, 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));
f->SetPixelRatio(info.pixel_ratio.num, info.pixel_ratio.den);
working_cache.Add(requested_frame, f);

View File

@@ -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;