Reworked the cache object to use a double sided queue, so I can iterate through it to find the smallest frame, and remove specific frames from the cache. Also, fixed some additional audio bugs, and I finally have the audio being correctly distributed between frame objects.

This commit is contained in:
Jonathan Thomas
2011-10-26 00:34:48 -05:00
parent fa62b307c3
commit e4f95d8a99
5 changed files with 85 additions and 69 deletions

View File

@@ -8,7 +8,7 @@
*/
#include <map>
#include <queue>
#include <deque>
#include "Frame.h"
#include "Exceptions.h"
@@ -26,7 +26,7 @@ namespace openshot {
private:
int max_frames; ///< This is the max number of frames to cache
map<int, Frame> frames; ///< This map holds the frame number and Frame objects
queue<int> frame_numbers; ///< This queue holds a sequential list of cached Frame numbers
deque<int> frame_numbers; ///< This queue holds a sequential list of cached Frame numbers
/// Clean up cached frames that exceed the number in our max_frames variable
void CleanUp();
@@ -44,14 +44,14 @@ namespace openshot {
/// Check for the existance of a frame in the cache
bool Exists(int frame_number);
/// Return the front frame and remove it
Frame Pop();
/// Get a frame from the cache
Frame GetFrame(int frame_number);
/// Get the front frame in this cache
Frame GetFront();
/// Get the smallest frame number
Frame GetSmallestFrame();
/// Remove a specific frame
void Remove(int frame_number);
/// Clear the cache of all frames
void Clear();

View File

@@ -23,7 +23,7 @@ void Cache::Add(int frame_number, Frame frame)
{
// Add frame to queue and map
frames[frame_number] = frame;
frame_numbers.push(frame_number);
frame_numbers.push_front(frame_number);
// Clean up older frames (that exceed the max frames)
CleanUp();
@@ -46,23 +46,6 @@ bool Cache::Exists(int frame_number)
return false;
}
// Return the front frame and remove it
Frame Cache::Pop()
{
// Remove the oldest frame
int frame_to_remove = frame_numbers.front();
// Get the front frame
Frame f = GetFrame(frame_to_remove);
// Remove frame_number and frame
frame_numbers.pop();
frames.erase(frame_to_remove);
// Return the frame
return f;
}
// Get a frame from the cache
Frame Cache::GetFrame(int frame_number)
{
@@ -77,11 +60,42 @@ Frame Cache::GetFrame(int frame_number)
throw OutOfBoundsFrame("Frame not found in the cache", frame_number, -1);
}
// Get the front frame in this cache
Frame Cache::GetFront()
// Get the smallest frame number
Frame Cache::GetSmallestFrame()
{
// Return oldest frame in the cache
return GetFrame(frame_numbers.front());
// Loop through frame numbers
deque<int>::iterator itr;
int smallest_frame = -1;
for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
{
if (*itr < smallest_frame || smallest_frame == -1)
smallest_frame = *itr;
}
// Return frame (or error if no frame found)
return GetFrame(smallest_frame);
}
// Remove a specific frame
void Cache::Remove(int frame_number)
{
// Get the frame (or throw exception)
Frame f = GetFrame(frame_number);
// Loop through frame numbers
deque<int>::iterator itr;
for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
{
if (*itr == frame_number)
{
// erase frame number
frame_numbers.erase(itr);
break;
}
}
// Remove frame from map
frames.erase(frame_number);
}
// Clear the cache of all frames
@@ -91,7 +105,7 @@ void Cache::Clear()
frames.clear();
// pop each of the frames from the queue... which emptys the queue
while(!frame_numbers.empty()) frame_numbers.pop();
while(!frame_numbers.empty()) frame_numbers.pop_back();
}
// Count the frames in the queue
@@ -108,11 +122,10 @@ void Cache::CleanUp()
if (frame_numbers.size() > max_frames)
{
// Remove the oldest frame
int frame_to_remove = frame_numbers.front();
int frame_to_remove = frame_numbers.back();
// Remove frame_number and frame
frame_numbers.pop();
frames.erase(frame_to_remove);
Remove(frame_to_remove);
}
}
@@ -124,12 +137,11 @@ void Cache::DisplayAndClear()
while(!frame_numbers.empty())
{
// Print the frame number
int frame_number = frame_numbers.front();
int frame_number = frame_numbers.back();
cout << " " << i << ") --- Frame " << frame_number << endl;
// Remove this frame
frame_numbers.pop();
frames.erase(frame_number);
Remove(frame_number);
// increment counter
i++;

View File

@@ -290,7 +290,8 @@ Frame FFmpegReader::ReadStream(int requested_frame)
av_free(pFrame);
// End of stream? Mark the any other working frames as 'finished'
CheckWorkingFrames(true);
if (end_of_stream)
CheckWorkingFrames(end_of_stream);
// Return requested frame (if found)
if (final_cache.Exists(requested_frame))
@@ -428,16 +429,12 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
packet.size -= used;
}
cout << "Samples Added to Frame " << target_frame << ": " << packet_samples << " (starting at sample: " << starting_sample << ")" << endl;
for (int channel_filter = 0; channel_filter < info.channels; channel_filter++)
{
// Array of floats (to hold samples for each channel)
int starting_frame_number = target_frame;
int channel_buffer_size = (packet_samples / info.channels) + 1;
float *channel_buffer = new float[channel_buffer_size];
int position = 0;
// Init buffer array
for (int z = 0; z < channel_buffer_size; z++)
@@ -446,7 +443,7 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
// Loop through all samples and add them to our Frame based on channel.
// Toggle through each channel number, since channel data is stored like (left right left right)
int channel = 0;
int position = 0;
for (int sample = 0; sample < packet_samples; sample++)
{
// Only add samples for current channel
@@ -460,7 +457,7 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
}
// increment channel (if needed)
if (channel < info.channels)
if ((channel + 1) < info.channels)
// move to next channel
channel ++;
else
@@ -468,13 +465,6 @@ void FFmpegReader::ProcessAudioPacket(int requested_frame, int target_frame, int
channel = 0;
}
// Add channel buffer to Frame object
// if (packet_samples > 0) // DEBUG to prevent overwriting samples with multiple audio packets
// {
// //cout << " *** ADDED AUDIO FOR FRAME " << current_frame << " *** (" << channel_buffer_size << " samples)" << endl;
// new_frame.AddAudio(channel_filter, audio_position, channel_buffer, channel_buffer_size, 1.0f);
// }
// Get Samples per frame
int samples_per_frame = GetSamplesPerFrame();
@@ -769,7 +759,7 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream)
break;
// Get the front frame of working cache
Frame f = working_cache.GetFront();
Frame f = working_cache.GetSmallestFrame();
// Check if working frame is final
if ((!end_of_stream && f.number <= last_video_frame && f.number < last_audio_frame) || end_of_stream)
@@ -778,7 +768,7 @@ void FFmpegReader::CheckWorkingFrames(bool end_of_stream)
final_cache.Add(f.number, f);
// Remove frame from working cache
working_cache.Pop();
working_cache.Remove(f.number);
}
else
// Stop looping

View File

@@ -17,8 +17,8 @@ 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/Videos/OpenShot_Now_In_3d.mp4");
// openshot::FFmpegReader r("/home/jonathan/Videos/sintel-1024-stereo.mp4");
openshot::FFmpegReader r("/home/jonathan/Videos/sintel_trailer-720p.mp4");
openshot::FFmpegReader r("/home/jonathan/Videos/sintel-1024-stereo.mp4");
// openshot::FFmpegReader r("/home/jonathan/Videos/sintel_trailer-720p.mp4");
// openshot::FFmpegReader r("/home/jonathan/Aptana Studio Workspace/OpenShotLibrary/src/examples/test.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/bannertemplate.png");
@@ -28,7 +28,7 @@ int main()
// Display debug info
r.DisplayInfo();
for (int frame = 300; frame < 400; frame++)
for (int frame = 1500; frame < 2000; frame++)
{
Frame f = r.GetFrame(frame);
f.Play();

View File

@@ -121,14 +121,14 @@ TEST(Cache_GetFrame)
CHECK_EQUAL(3, c.GetFrame(3).number);
}
TEST(Cache_GetFront)
TEST(Cache_GetSmallest)
{
// Create cache object (with a max of 10 items)
Cache c(10);
// Create 3 frames
Frame red(1, 300, 300, "red");
Frame blue(2, 400, 400, "blue");
Frame red(1, 300, 300, "red");
Frame green(3, 500, 500, "green");
// Add frames to cache
@@ -137,19 +137,19 @@ TEST(Cache_GetFront)
c.Add(green.number, green);
// Check if frame 1 is the front
CHECK_EQUAL(1, c.GetFront().number);
CHECK_EQUAL(1, c.GetSmallestFrame().number);
// Check if frame 1 is STILL the front
CHECK_EQUAL(1, c.GetFront().number);
CHECK_EQUAL(1, c.GetSmallestFrame().number);
// Erase frame 1
c.Pop();
c.Remove(1);
// Check if frame 2 is the front
CHECK_EQUAL(2, c.GetFront().number);
CHECK_EQUAL(2, c.GetSmallestFrame().number);
}
TEST(Cache_Pop)
TEST(Cache_Remove)
{
// Create cache object (with a max of 10 items)
Cache c(10);
@@ -164,13 +164,27 @@ TEST(Cache_Pop)
c.Add(blue.number, blue);
c.Add(green.number, green);
// Check if frame 1 is the front
Frame pop1 = c.Pop();
CHECK_EQUAL(1, pop1.number);
// Check if count is 3
CHECK_EQUAL(3, c.Count());
Frame pop2 = c.Pop();
CHECK_EQUAL(2, pop2.number);
// Check if frame 2 exists
CHECK_EQUAL(true, c.Exists(2));
Frame pop3 = c.Pop();
CHECK_EQUAL(3, pop3.number);
// Remove frame 2
c.Remove(2);
// Check if frame 2 exists
CHECK_EQUAL(false, c.Exists(2));
// Check if count is 2
CHECK_EQUAL(2, c.Count());
// Remove frame 1
c.Remove(1);
// Check if frame 1 exists
CHECK_EQUAL(false, c.Exists(1));
// Check if count is 1
CHECK_EQUAL(1, c.Count());
}