You've already forked libopenshot
mirror of
https://github.com/OpenShot/libopenshot.git
synced 2026-03-02 08:53:52 -08:00
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:
@@ -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();
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user