33 image_format = format;
34 image_quality = quality;
49 image_format = format;
50 image_quality = quality;
58void CacheDisk::InitPath(std::string cache_path) {
61 if (!cache_path.empty()) {
63 qpath = QString(cache_path.c_str());
67 qpath = QDir::tempPath() + QString(
"/preview-cache/");
92 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
93 int64_t frame_number = frame->number;
96 if (frames.count(frame_number))
103 frames[frame_number] = frame_number;
104 frame_numbers.push_front(frame_number);
109 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(frame_number) + QString(image_format.c_str()).toLower());
110 frame->Save(frame_path.toStdString(), image_scale, image_format, image_quality);
111 if (frame_size_bytes == 0) {
113 QFile image_file(frame_path);
114 frame_size_bytes = image_file.size();
118 if (frame->has_audio_data) {
119 QString audio_path(path.path() +
"/" + QString(
"%1").arg(frame_number) +
".audio");
120 QFile audio_file(audio_path);
122 if (audio_file.open(QIODevice::WriteOnly)) {
123 QTextStream audio_stream(&audio_file);
124 audio_stream << frame->SampleRate() << Qt::endl;
125 audio_stream << frame->GetAudioChannelsCount() << Qt::endl;
126 audio_stream << frame->GetAudioSamplesCount() << Qt::endl;
127 audio_stream << frame->ChannelsLayout() << Qt::endl;
130 for (
int channel = 0; channel < frame->GetAudioChannelsCount(); channel++)
133 float *samples = frame->GetAudioSamples(channel);
134 for (
int sample = 0; sample < frame->GetAudioSamplesCount(); sample++)
135 audio_stream << samples[sample] << Qt::endl;
149 if (frames.count(frame_number) > 0) {
160 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
163 if (frames.count(frame_number)) {
165 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(frame_number) + QString(image_format.c_str()).toLower());
166 if (path.exists(frame_path)) {
169 auto image = std::make_shared<QImage>();
170 image->load(frame_path);
173 image = std::make_shared<QImage>(image->convertToFormat(QImage::Format_RGBA8888_Premultiplied));
176 auto frame = std::make_shared<Frame>();
177 frame->number = frame_number;
178 frame->AddImage(image);
181 QString audio_path(path.path() +
"/" + QString(
"%1").arg(frame_number) +
".audio");
182 QFile audio_file(audio_path);
183 if (audio_file.exists()) {
185 QTextStream in(&audio_file);
186 if (audio_file.open(QIODevice::ReadOnly)) {
187 int sample_rate = in.readLine().toInt();
188 int channels = in.readLine().toInt();
189 int sample_count = in.readLine().toInt();
190 int channel_layout = in.readLine().toInt();
193 frame->ResizeAudio(channels, sample_count, sample_rate, (
ChannelLayout) channel_layout);
196 int current_channel = 0;
197 int current_sample = 0;
198 float *channel_samples =
new float[sample_count];
199 while (!in.atEnd()) {
201 channel_samples[current_sample] = in.readLine().toFloat();
204 if (current_sample == sample_count) {
206 frame->AddAudio(
true, current_channel, 0, channel_samples, sample_count, 1.0);
223 return std::shared_ptr<Frame>();
230 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
232 std::vector<std::shared_ptr<openshot::Frame>> all_frames;
233 std::vector<int64_t>::iterator itr_ordered;
236 int64_t frame_number = *itr_ordered;
237 all_frames.push_back(
GetFrame(frame_number));
247 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
250 std::deque<int64_t>::iterator itr;
251 int64_t smallest_frame = -1;
252 for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
254 if (*itr < smallest_frame || smallest_frame == -1)
255 smallest_frame = *itr;
259 if (smallest_frame != -1) {
270 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
272 int64_t total_bytes = 0;
275 std::deque<int64_t>::reverse_iterator itr;
276 for(itr = frame_numbers.rbegin(); itr != frame_numbers.rend(); ++itr)
277 total_bytes += frame_size_bytes;
285 Remove(frame_number, frame_number);
292 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
295 std::deque<int64_t>::iterator itr;
296 for(itr = frame_numbers.begin(); itr != frame_numbers.end();)
299 if (*itr >= start_frame_number && *itr <= end_frame_number)
302 itr = frame_numbers.erase(itr);
308 std::vector<int64_t>::iterator itr_ordered;
311 if (*itr_ordered >= start_frame_number && *itr_ordered <= end_frame_number)
314 frames.erase(*itr_ordered);
317 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(*itr_ordered) + QString(image_format.c_str()).toLower());
318 QFile image_file(frame_path);
319 if (image_file.exists())
323 QString audio_path(path.path() +
"/" + QString(
"%1").arg(*itr_ordered) +
".audio");
324 QFile audio_file(audio_path);
325 if (audio_file.exists())
341 if (frames.count(frame_number))
344 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
347 std::deque<int64_t>::iterator itr;
348 for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
350 if (*itr == frame_number)
353 frame_numbers.erase(itr);
356 frame_numbers.push_front(frame_number);
367 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
371 frame_numbers.clear();
372 frame_numbers.shrink_to_fit();
376 frame_size_bytes = 0;
379 QString current_path = path.path();
380 path.removeRecursively();
383 InitPath(current_path.toStdString());
390 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
393 return frames.size();
397void CacheDisk::CleanUp()
403 const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
408 int64_t frame_to_remove = frame_numbers.back();
432 root[
"path"] = path.path().toStdString();
435 std::stringstream range_version_str;
437 root[
"version"] = range_version_str.str();
443 root[
"ranges"] = ranges;
460 catch (
const std::exception& e)
463 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
476 if (!root[
"type"].isNull())
478 if (!root[
"path"].isNull())
480 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.
bool Contains(int64_t frame_number)
Check if frame is already contained in cache.
void Touch(int64_t frame_number)
Move frame to front of queue (so it lasts longer)
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)