OpenShot Library | libopenshot  0.1.1
Cache.cpp
Go to the documentation of this file.
1 /**
2  * @file
3  * @brief Source file for Cache class
4  * @author Jonathan Thomas <jonathan@openshot.org>
5  *
6  * @section LICENSE
7  *
8  * Copyright (c) 2008-2014 OpenShot Studios, LLC
9  * <http://www.openshotstudios.com/>. This file is part of
10  * OpenShot Library (libopenshot), an open-source project dedicated to
11  * delivering high quality video editing and animation solutions to the
12  * world. For more information visit <http://www.openshot.org/>.
13  *
14  * OpenShot Library (libopenshot) is free software: you can redistribute it
15  * and/or modify it under the terms of the GNU Lesser General Public License
16  * as published by the Free Software Foundation, either version 3 of the
17  * License, or (at your option) any later version.
18  *
19  * OpenShot Library (libopenshot) is distributed in the hope that it will be
20  * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22  * GNU Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public License
25  * along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
26  */
27 
28 #include "../include/Cache.h"
29 
30 using namespace std;
31 using namespace openshot;
32 
33 // Default constructor, no max frames
34 Cache::Cache() : max_bytes(0) {
35  // Init the critical section
36  cacheCriticalSection = new CriticalSection();
37 };
38 
39 // Constructor that sets the max frames to cache
40 Cache::Cache(int64 max_bytes) : max_bytes(max_bytes) {
41  // Init the critical section
42  cacheCriticalSection = new CriticalSection();
43 };
44 
45 // Default destructor
47 {
48  frames.clear();
49  frame_numbers.clear();
50 
51  // remove critical section
52  delete cacheCriticalSection;
53  cacheCriticalSection = NULL;
54 }
55 
56 // Add a Frame to the cache
57 void Cache::Add(long int frame_number, tr1::shared_ptr<Frame> frame)
58 {
59  // Create a scoped lock, to protect the cache from multiple threads
60  const GenericScopedLock<CriticalSection> lock(*cacheCriticalSection);
61 
62  // Remove frame if it already exists
63  if (frames.count(frame_number))
64  // Move frame to front of queue
65  MoveToFront(frame_number);
66 
67  else
68  {
69  // Add frame to queue and map
70  frames[frame_number] = frame;
71  frame_numbers.push_front(frame_number);
72 
73  // Clean up old frames
74  CleanUp();
75  }
76 }
77 
78 // Get a frame from the cache (or NULL shared_ptr if no frame is found)
79 tr1::shared_ptr<Frame> Cache::GetFrame(long int frame_number)
80 {
81  // Create a scoped lock, to protect the cache from multiple threads
82  const GenericScopedLock<CriticalSection> lock(*cacheCriticalSection);
83 
84  // Does frame exists in cache?
85  if (frames.count(frame_number))
86  // return the Frame object
87  return frames[frame_number];
88 
89  else
90  // no Frame found
91  return tr1::shared_ptr<Frame>();
92 }
93 
94 // Return a deque of all frame numbers in this queue (returns just a copy of the data)
95 deque<long int> Cache::GetFrameNumbers() {
96 
97  // Create a scoped lock, to protect the cache from multiple threads
98  const GenericScopedLock<CriticalSection> lock(*cacheCriticalSection);
99 
100  // Make copy of deque
101  deque<long int> copy_frame_numbers;
102 
103  // Loop through frame numbers
104  deque<long int>::iterator itr;
105  for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
106  copy_frame_numbers.push_back(*itr);
107 
108  return copy_frame_numbers;
109 }
110 
111 // Get the smallest frame number (or NULL shared_ptr if no frame is found)
112 tr1::shared_ptr<Frame> Cache::GetSmallestFrame()
113 {
114  // Create a scoped lock, to protect the cache from multiple threads
115  const GenericScopedLock<CriticalSection> lock(*cacheCriticalSection);
116  tr1::shared_ptr<openshot::Frame> f;
117 
118  // Loop through frame numbers
119  deque<long int>::iterator itr;
120  long int smallest_frame = -1;
121  for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
122  {
123  if (*itr < smallest_frame || smallest_frame == -1)
124  smallest_frame = *itr;
125  }
126 
127  // Return frame
128  f = GetFrame(smallest_frame);
129 
130  return f;
131 }
132 
133 // Gets the maximum bytes value
135 {
136  // Create a scoped lock, to protect the cache from multiple threads
137  const GenericScopedLock<CriticalSection> lock(*cacheCriticalSection);
138 
139  int64 total_bytes = 0;
140 
141  // Loop through frames, and calculate total bytes
142  deque<long int>::reverse_iterator itr;
143  for(itr = frame_numbers.rbegin(); itr != frame_numbers.rend(); ++itr)
144  {
145  //cout << "get bytes from frame " << *itr << ", frames.count(" << *itr << "): " << frames.count(*itr) << endl;
146  //if (frames.count(*itr) > 0)
147  total_bytes += frames[*itr]->GetBytes();
148  }
149 
150  return total_bytes;
151 }
152 
153 // Remove a specific frame
154 void Cache::Remove(long int frame_number)
155 {
156  // Create a scoped lock, to protect the cache from multiple threads
157  const GenericScopedLock<CriticalSection> lock(*cacheCriticalSection);
158 
159  // Loop through frame numbers
160  deque<long int>::iterator itr;
161  for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
162  {
163  if (*itr == frame_number)
164  {
165  // erase frame number
166  frame_numbers.erase(itr);
167  break;
168  }
169  }
170 
171  // Remove frame from map
172  frames.erase(frame_number);
173 }
174 
175 // Move frame to front of queue (so it lasts longer)
176 void Cache::MoveToFront(long int frame_number)
177 {
178  // Create a scoped lock, to protect the cache from multiple threads
179  const GenericScopedLock<CriticalSection> lock(*cacheCriticalSection);
180 
181  // Does frame exists in cache?
182  if (frames.count(frame_number))
183  {
184  // Loop through frame numbers
185  deque<long int>::iterator itr;
186  for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
187  {
188  if (*itr == frame_number)
189  {
190  // erase frame number
191  frame_numbers.erase(itr);
192 
193  // add frame number to 'front' of queue
194  frame_numbers.push_front(frame_number);
195  break;
196  }
197  }
198  }
199 }
200 
201 // Clear the cache of all frames
203 {
204  // Create a scoped lock, to protect the cache from multiple threads
205  const GenericScopedLock<CriticalSection> lock(*cacheCriticalSection);
206 
207  frames.clear();
208  frame_numbers.clear();
209 }
210 
211 // Count the frames in the queue
212 long int Cache::Count()
213 {
214  // Create a scoped lock, to protect the cache from multiple threads
215  const GenericScopedLock<CriticalSection> lock(*cacheCriticalSection);
216 
217  // Return the number of frames in the cache
218  return frames.size();
219 }
220 
221 // Clean up cached frames that exceed the number in our max_bytes variable
222 void Cache::CleanUp()
223 {
224  // Create a scoped lock, to protect the cache from multiple threads
225  const GenericScopedLock<CriticalSection> lock(*cacheCriticalSection);
226 
227  // Do we auto clean up?
228  if (max_bytes > 0)
229  {
230  while (GetBytes() > max_bytes && frame_numbers.size() > 20)
231  {
232  // Remove the oldest frame
233  long int frame_to_remove = frame_numbers.back();
234 
235  // Remove frame_number and frame
236  Remove(frame_to_remove);
237  }
238  }
239 }
240 
241 // Display a list of cached frame numbers
243 {
244  cout << "----- Cache List (" << frames.size() << ") ------" << endl;
245  deque<long int>::iterator itr;
246 
247  int i = 1;
248  for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
249  {
250  cout << " " << i << ") --- Frame " << *itr << endl;
251  i++;
252  }
253 }
254 
255 // Set maximum bytes to a different amount based on a ReaderInfo struct
256 void Cache::SetMaxBytesFromInfo(long int number_of_frames, int width, int height, int sample_rate, int channels)
257 {
258  // n frames X height X width X 4 colors of chars X audio channels X 4 byte floats
259  int64 bytes = number_of_frames * (height * width * 4 + (sample_rate * channels * 4));
260  SetMaxBytes(bytes);
261 }
262 
void SetMaxBytes(int64 number_of_bytes)
Set maximum bytes to a different amount.
Definition: Cache.h:120
void Add(long int frame_number, tr1::shared_ptr< Frame > frame)
Add a Frame to the cache.
Definition: Cache.cpp:57
void Remove(long int frame_number)
Remove a specific frame.
Definition: Cache.cpp:154
deque< long int > GetFrameNumbers()
Return a deque of all frame numbers in this queue (returns just a copy of the data) ...
Definition: Cache.cpp:95
void SetMaxBytesFromInfo(long int number_of_frames, int width, int height, int sample_rate, int channels)
Set maximum bytes to a different amount based on a ReaderInfo struct.
Definition: Cache.cpp:256
int64 GetBytes()
Gets the maximum bytes value.
Definition: Cache.cpp:134
tr1::shared_ptr< Frame > GetSmallestFrame()
Get the smallest frame number.
Definition: Cache.cpp:112
Cache()
Default constructor, no max bytes.
Definition: Cache.cpp:34
tr1::shared_ptr< Frame > GetFrame(long int frame_number)
Get a frame from the cache.
Definition: Cache.cpp:79
void Clear()
Clear the cache of all frames.
Definition: Cache.cpp:202
void Display()
Display a list of cached frame numbers.
Definition: Cache.cpp:242
void MoveToFront(long int frame_number)
Move frame to front of queue (so it lasts longer)
Definition: Cache.cpp:176
long int Count()
Count the frames in the queue.
Definition: Cache.cpp:212