32 image_format = format;
33 image_quality = quality;
48 image_format = format;
49 image_quality = quality;
57void CacheDisk::InitPath(std::string cache_path) {
60 if (!cache_path.empty()) {
62 qpath = QString(cache_path.c_str());
66 qpath = QDir::tempPath() + QString(
"/preview-cache/");
91 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
92 int64_t frame_number = frame->number;
95 if (frames.count(frame_number))
102 frames[frame_number] = frame_number;
103 frame_numbers.push_front(frame_number);
108 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(frame_number) + QString(image_format.c_str()).toLower());
109 frame->Save(frame_path.toStdString(), image_scale, image_format, image_quality);
110 if (frame_size_bytes == 0) {
112 QFile image_file(frame_path);
113 frame_size_bytes = image_file.size();
117 if (frame->has_audio_data) {
118 QString audio_path(path.path() +
"/" + QString(
"%1").arg(frame_number) +
".audio");
119 QFile audio_file(audio_path);
121 if (audio_file.open(QIODevice::WriteOnly)) {
122 QTextStream audio_stream(&audio_file);
123 audio_stream << frame->SampleRate() << Qt::endl;
124 audio_stream << frame->GetAudioChannelsCount() << Qt::endl;
125 audio_stream << frame->GetAudioSamplesCount() << Qt::endl;
126 audio_stream << frame->ChannelsLayout() << Qt::endl;
129 for (
int channel = 0; channel < frame->GetAudioChannelsCount(); channel++)
132 float *samples = frame->GetAudioSamples(channel);
133 for (
int sample = 0; sample < frame->GetAudioSamplesCount(); sample++)
134 audio_stream << samples[sample] << Qt::endl;
148 if (frames.count(frame_number) > 0) {
159 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
162 if (frames.count(frame_number)) {
164 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(frame_number) + QString(image_format.c_str()).toLower());
165 if (path.exists(frame_path)) {
168 auto image = std::make_shared<QImage>();
169 image->load(frame_path);
172 image = std::make_shared<QImage>(image->convertToFormat(QImage::Format_RGBA8888_Premultiplied));
175 auto frame = std::make_shared<Frame>();
176 frame->number = frame_number;
177 frame->AddImage(image);
180 QString audio_path(path.path() +
"/" + QString(
"%1").arg(frame_number) +
".audio");
181 QFile audio_file(audio_path);
182 if (audio_file.exists()) {
184 QTextStream in(&audio_file);
185 if (audio_file.open(QIODevice::ReadOnly)) {
186 int sample_rate = in.readLine().toInt();
187 int channels = in.readLine().toInt();
188 int sample_count = in.readLine().toInt();
189 int channel_layout = in.readLine().toInt();
192 frame->ResizeAudio(channels, sample_count, sample_rate, (
ChannelLayout) channel_layout);
195 int current_channel = 0;
196 int current_sample = 0;
197 float *channel_samples =
new float[sample_count];
198 while (!in.atEnd()) {
200 channel_samples[current_sample] = in.readLine().toFloat();
203 if (current_sample == sample_count) {
205 frame->AddAudio(
true, current_channel, 0, channel_samples, sample_count, 1.0);
222 return std::shared_ptr<Frame>();
229 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
231 std::vector<std::shared_ptr<openshot::Frame>> all_frames;
232 std::vector<int64_t>::iterator itr_ordered;
235 int64_t frame_number = *itr_ordered;
236 all_frames.push_back(
GetFrame(frame_number));
246 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
249 std::deque<int64_t>::iterator itr;
250 int64_t smallest_frame = -1;
251 for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
253 if (*itr < smallest_frame || smallest_frame == -1)
254 smallest_frame = *itr;
258 if (smallest_frame != -1) {
269 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
271 int64_t total_bytes = 0;
274 std::deque<int64_t>::reverse_iterator itr;
275 for(itr = frame_numbers.rbegin(); itr != frame_numbers.rend(); ++itr)
276 total_bytes += frame_size_bytes;
284 Remove(frame_number, frame_number);
291 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
294 std::deque<int64_t>::iterator itr;
295 for(itr = frame_numbers.begin(); itr != frame_numbers.end();)
298 if (*itr >= start_frame_number && *itr <= end_frame_number)
301 itr = frame_numbers.erase(itr);
307 std::vector<int64_t>::iterator itr_ordered;
310 if (*itr_ordered >= start_frame_number && *itr_ordered <= end_frame_number)
313 frames.erase(*itr_ordered);
316 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(*itr_ordered) + QString(image_format.c_str()).toLower());
317 QFile image_file(frame_path);
318 if (image_file.exists())
322 QString audio_path(path.path() +
"/" + QString(
"%1").arg(*itr_ordered) +
".audio");
323 QFile audio_file(audio_path);
324 if (audio_file.exists())
340 if (frames.count(frame_number))
343 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
346 std::deque<int64_t>::iterator itr;
347 for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
349 if (*itr == frame_number)
352 frame_numbers.erase(itr);
355 frame_numbers.push_front(frame_number);
366 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
370 frame_numbers.clear();
371 frame_numbers.shrink_to_fit();
375 frame_size_bytes = 0;
378 QString current_path = path.path();
379 path.removeRecursively();
382 InitPath(current_path.toStdString());
389 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
392 return frames.size();
396void CacheDisk::CleanUp()
402 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
407 int64_t frame_to_remove = frame_numbers.back();
431 root[
"path"] = path.path().toStdString();
434 std::stringstream range_version_str;
436 root[
"version"] = range_version_str.str();
442 root[
"ranges"] = ranges;
459 catch (
const std::exception& e)
462 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
475 if (!root[
"type"].isNull())
477 if (!root[
"path"].isNull())
479 InitPath(root[
"path"].asString());
Header file for CacheDisk class.
Header file for all Exception classes.
Header file for Frame class.
Header file for QtUtilities (compatibiity overlay)
All cache managers in libopenshot are based on this CacheBase class.
int64_t range_version
The version of the JSON range data (incremented with each change)
virtual Json::Value JsonValue()=0
Generate Json::Value for this object.
std::string cache_type
This is a friendly type name of the derived cache instance.
void CalculateRanges()
Calculate ranges of frames.
virtual void SetJsonValue(const Json::Value root)=0
Load Json::Value into this object.
bool needs_range_processing
Something has changed, and the range data needs to be re-calculated.
int64_t max_bytes
This is the max number of bytes to cache (0 = no limit)
std::recursive_mutex * cacheMutex
Mutex for multiple threads.
std::string json_ranges
JSON ranges of frame numbers.
std::vector< int64_t > ordered_frame_numbers
Ordered list of frame numbers used by cache.
std::vector< std::shared_ptr< openshot::Frame > > GetFrames()
Get an array of all Frames.
std::shared_ptr< openshot::Frame > GetFrame(int64_t frame_number)
Get a frame from the cache.
CacheDisk(std::string cache_path, std::string format, float quality, float scale)
Default constructor, no max bytes.
void MoveToFront(int64_t frame_number)
Move frame to front of queue (so it lasts longer)
bool Contains(int64_t frame_number)
Check if frame is already contained in cache.
std::string Json()
Generate JSON string of this object.
void Add(std::shared_ptr< openshot::Frame > frame)
Add a Frame to the cache.
std::shared_ptr< openshot::Frame > GetSmallestFrame()
Get the smallest frame number.
Json::Value JsonValue()
Generate Json::Value for this object.
void Clear()
Clear the cache of all frames.
void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
void SetJson(const std::string value)
Load JSON string into this object.
int64_t GetBytes()
Gets the maximum bytes value.
int64_t Count()
Count the frames in the queue.
void Remove(int64_t frame_number)
Remove a specific frame.
Exception for invalid JSON.
This namespace is the default namespace for all code in the openshot library.
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround,...
const Json::Value stringToJson(const std::string value)