From 403c7e512eb01c3424d9130668319b953d41f294 Mon Sep 17 00:00:00 2001 From: Jonathan Thomas Date: Sun, 26 Feb 2012 16:40:53 -0600 Subject: [PATCH] Fixed 2 bugs related to audio samples. Each frame can now determine it's own # of samples, due to some sample rates not being divisible evenly into some frame rates. Also, a bug was fixed that injected a bad sample into a frame's samples, when a frame received samples from multiple audio packets. --- include/FFmpegReader.h | 4 ++-- src/FFmpegReader.cpp | 36 +++++++++++++++++++++--------------- src/Frame.cpp | 4 +++- src/Main.cpp | 4 ++-- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/include/FFmpegReader.h b/include/FFmpegReader.h index abb5036b..0c0f9a9d 100644 --- a/include/FFmpegReader.h +++ b/include/FFmpegReader.h @@ -116,8 +116,8 @@ namespace openshot /// Get the next packet (if any) int GetNextPacket(); - /// Calculate the # of samples per video frame - int GetSamplesPerFrame(); + /// Calculate the # of samples per video frame (for a specific frame number) + int GetSamplesPerFrame(int frame_number); /// Get the PTS for the current video packet int GetVideoPTS(); diff --git a/src/FFmpegReader.cpp b/src/FFmpegReader.cpp index 86538c79..766ac024 100644 --- a/src/FFmpegReader.cpp +++ b/src/FFmpegReader.cpp @@ -557,15 +557,15 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int channel = 0; } - // Get Samples per frame - int samples_per_frame = GetSamplesPerFrame(); - // Loop through samples, and add them to the correct frames int start = starting_sample; int remaining_samples = channel_buffer_size; - float *iterate_channel_buffer = channel_buffer; + float *iterate_channel_buffer = channel_buffer + 1; // pointer to channel buffer (increment position by 1) while (remaining_samples > 0) { + // Get Samples per frame (for this frame number) + int samples_per_frame = GetSamplesPerFrame(starting_frame_number); + // Create or get frame object Frame f = CreateFrame(starting_frame_number); last_audio_frame = starting_frame_number; @@ -575,11 +575,6 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int if (samples > remaining_samples) samples = remaining_samples; -// cout << "---------------" << last_audio_frame << "---------------" << endl; -// cout << "--- channel_filter: " << channel_filter << endl; -// cout << "--- starting_sample: " << start << endl; -// cout << "--- ending sample: " << (starting_sample + samples) - 1 << endl; - // Add samples for current channel to the frame f.AddAudio(channel_filter, start, iterate_channel_buffer, samples, 1.0f); @@ -843,7 +838,7 @@ audio_packet_location FFmpegReader::GetAudioPTSLocation(int pts) double sample_start_percentage = frame - double(whole_frame); // Get Samples per frame - int samples_per_frame = GetSamplesPerFrame(); + int samples_per_frame = GetSamplesPerFrame(whole_frame); // Calculate the sample # to start on int sample_start = round(double(samples_per_frame) * sample_start_percentage); @@ -855,11 +850,17 @@ audio_packet_location FFmpegReader::GetAudioPTSLocation(int pts) return location; } -// Calculate the # of samples per video frame -int FFmpegReader::GetSamplesPerFrame() +// Calculate the # of samples per video frame (for a specific frame number) +int FFmpegReader::GetSamplesPerFrame(int frame_number) { - // Get the number of samples per video frame (sample rate X reciprocal of frame rate) - return round(double(info.sample_rate) / info.fps.ToDouble()); + // Get the total # of samples for the previous frame, and the current frame (rounded) + double previous_samples = round((info.sample_rate * info.video_timebase.ToDouble()) * (frame_number - 1)); + double total_samples = round((info.sample_rate * info.video_timebase.ToDouble()) * frame_number); + + // 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; + return samples_per_frame; } // Create a new Frame (or return an existing one) and add it to the working queue. @@ -872,7 +873,7 @@ Frame FFmpegReader::CreateFrame(int requested_frame) else { // Get Samples per frame - int samples_per_frame = GetSamplesPerFrame(); + int samples_per_frame = GetSamplesPerFrame(requested_frame); // Create a new frame on the working cache Frame f(requested_frame, info.width, info.height, "#000000", samples_per_frame, info.channels); @@ -981,6 +982,11 @@ void FFmpegReader::CheckFPS() // cout << "FORTH SECOND: " << forth_second_counter << endl; // cout << "FIFTH SECOND: " << fifth_second_counter << endl; + // Double check that all counters have greater than zero (or give up) + if (second_second_counter == 0 || third_second_counter == 0 || forth_second_counter == 0 || fifth_second_counter == 0) + // exit with no changes to FPS (not enough data to calculate) + return; + int sum_fps = second_second_counter + third_second_counter + forth_second_counter + fifth_second_counter; int avg_fps = round(sum_fps / 4.0f); diff --git a/src/Frame.cpp b/src/Frame.cpp index 3df726ee..6186e712 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -182,7 +182,9 @@ void Frame::DisplayWaveform(bool resize) float value = samples[sample] * 100; if (value > 100 || value < -100) - cout << "TOO BIG!!! " << value << endl; + { + cout << "TOO BIG: Sample # " << sample << " on frame " << number << " is TOO BIG: " << samples[sample] << endl; + } // Append a line segment for each sample if (value != 0.0) diff --git a/src/Main.cpp b/src/Main.cpp index f8e6b180..d84c310c 100644 --- a/src/Main.cpp +++ b/src/Main.cpp @@ -16,13 +16,13 @@ int main() // openshot::FFmpegReader r("/home/jonathan/Aptana Studio Workspace/OpenShotLibrary/src/examples/test.mp4"); // openshot::FFmpegReader r("/home/jonathan/Aptana Studio Workspace/OpenShotLibrary/src/examples/test1.mp4"); - openshot::FFmpegReader r("/home/jonathan/Aptana Studio Workspace/OpenShotLibrary/src/examples/piano.wav"); + // openshot::FFmpegReader r("/home/jonathan/Aptana Studio Workspace/OpenShotLibrary/src/examples/piano.wav"); // openshot::FFmpegReader r("/home/jonathan/Videos/sintel-1024-stereo.mp4"); // openshot::FFmpegReader r("/home/jonathan/Videos/00001.mts"); // openshot::FFmpegReader r("/home/jonathan/Videos/sintel_trailer-720p.mp4"); // openshot::FFmpegReader r("/home/jonathan/Aptana Studio Workspace/OpenShotLibrary/src/examples/piano.wav"); // openshot::FFmpegReader r("/home/jonathan/Music/Army of Lovers/Crucified/Army of Lovers - Crucified [Single Version].mp3"); - // openshot::FFmpegReader r("/home/jonathan/Documents/OpenShot Art/vimeo_banner.png"); + openshot::FFmpegReader r("/home/jonathan/Documents/OpenShot Art/vimeo_banner.png"); // openshot::FFmpegReader r("/home/jonathan/Videos/60fps.mp4"); // openshot::FFmpegReader r("/home/jonathan/Aptana Studio Workspace/OpenShotLibrary/src/examples/asdf.wdf");