42CacheDisk::CacheDisk(std::string cache_path, std::string format,
float quality,
float scale) :
CacheBase(0) {
46 needs_range_processing =
false;
48 image_format = format;
49 image_quality = quality;
62 needs_range_processing =
false;
64 image_format = format;
65 image_quality = quality;
73void CacheDisk::InitPath(std::string cache_path) {
76 if (!cache_path.empty()) {
78 qpath = QString(cache_path.c_str());
82 qpath = QDir::tempPath() + QString(
"/preview-cache/");
95void CacheDisk::CalculateRanges() {
97 if (needs_range_processing) {
103 std::sort(ordered_frame_numbers.begin(), ordered_frame_numbers.end());
106 Json::Value ranges = Json::Value(Json::arrayValue);
111 int64_t starting_frame = *ordered_frame_numbers.begin();
112 int64_t ending_frame = starting_frame;
115 for (
const auto frame_number : ordered_frame_numbers) {
116 if (frame_number - ending_frame > 1) {
122 range[
"start"] = std::to_string(starting_frame);
123 range[
"end"] = std::to_string(ending_frame);
124 ranges.append(range);
127 starting_frame = frame_number;
131 ending_frame = frame_number;
139 range[
"start"] = std::to_string(starting_frame);
140 range[
"end"] = std::to_string(ending_frame);
141 ranges.append(range);
144 json_ranges = ranges.toStyledString();
147 needs_range_processing =
false;
155 frame_numbers.clear();
156 ordered_frame_numbers.clear();
168 int64_t frame_number = frame->number;
171 if (frames.count(frame_number))
178 frames[frame_number] = frame_number;
179 frame_numbers.push_front(frame_number);
180 ordered_frame_numbers.push_back(frame_number);
181 needs_range_processing =
true;
184 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(frame_number) + QString(image_format.c_str()).toLower());
185 frame->Save(frame_path.toStdString(), image_scale, image_format, image_quality);
186 if (frame_size_bytes == 0) {
188 QFile image_file(frame_path);
189 frame_size_bytes = image_file.size();
193 if (frame->has_audio_data) {
194 QString audio_path(path.path() +
"/" + QString(
"%1").arg(frame_number) +
".audio");
195 QFile audio_file(audio_path);
197 if (audio_file.open(QIODevice::WriteOnly)) {
198 QTextStream audio_stream(&audio_file);
199 audio_stream << frame->SampleRate() << Qt::endl;
200 audio_stream << frame->GetAudioChannelsCount() << Qt::endl;
201 audio_stream << frame->GetAudioSamplesCount() << Qt::endl;
202 audio_stream << frame->ChannelsLayout() << Qt::endl;
205 for (
int channel = 0; channel < frame->GetAudioChannelsCount(); channel++)
208 float *samples = frame->GetAudioSamples(channel);
209 for (
int sample = 0; sample < frame->GetAudioSamplesCount(); sample++)
210 audio_stream << samples[sample] << Qt::endl;
229 if (frames.count(frame_number)) {
231 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(frame_number) + QString(image_format.c_str()).toLower());
232 if (path.exists(frame_path)) {
235 auto image = std::make_shared<QImage>();
236 image->load(frame_path);
239 image = std::make_shared<QImage>(image->convertToFormat(QImage::Format_RGBA8888_Premultiplied));
242 auto frame = std::make_shared<Frame>();
243 frame->number = frame_number;
244 frame->AddImage(image);
247 QString audio_path(path.path() +
"/" + QString(
"%1").arg(frame_number) +
".audio");
248 QFile audio_file(audio_path);
249 if (audio_file.exists()) {
251 QTextStream in(&audio_file);
252 if (audio_file.open(QIODevice::ReadOnly)) {
253 int sample_rate = in.readLine().toInt();
254 int channels = in.readLine().toInt();
255 int sample_count = in.readLine().toInt();
256 int channel_layout = in.readLine().toInt();
259 frame->ResizeAudio(channels, sample_count, sample_rate, (
ChannelLayout) channel_layout);
262 int current_channel = 0;
263 int current_sample = 0;
264 float *channel_samples =
new float[sample_count];
265 while (!in.atEnd()) {
267 channel_samples[current_sample] = in.readLine().toFloat();
270 if (current_sample == sample_count) {
272 frame->AddAudio(
true, current_channel, 0, channel_samples, sample_count, 1.0);
289 return std::shared_ptr<Frame>();
297 std::shared_ptr<openshot::Frame> f;
300 std::deque<int64_t>::iterator itr;
301 int64_t smallest_frame = -1;
302 for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
304 if (*itr < smallest_frame || smallest_frame == -1)
305 smallest_frame = *itr;
320 int64_t total_bytes = 0;
323 std::deque<int64_t>::reverse_iterator itr;
324 for(itr = frame_numbers.rbegin(); itr != frame_numbers.rend(); ++itr)
325 total_bytes += frame_size_bytes;
333 Remove(frame_number, frame_number);
343 std::deque<int64_t>::iterator itr;
344 for(itr = frame_numbers.begin(); itr != frame_numbers.end();)
347 if (*itr >= start_frame_number && *itr <= end_frame_number)
350 itr = frame_numbers.erase(itr);
356 std::vector<int64_t>::iterator itr_ordered;
357 for(itr_ordered = ordered_frame_numbers.begin(); itr_ordered != ordered_frame_numbers.end();)
359 if (*itr_ordered >= start_frame_number && *itr_ordered <= end_frame_number)
362 frames.erase(*itr_ordered);
365 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(*itr_ordered) + QString(image_format.c_str()).toLower());
366 QFile image_file(frame_path);
367 if (image_file.exists())
371 QString audio_path(path.path() +
"/" + QString(
"%1").arg(*itr_ordered) +
".audio");
372 QFile audio_file(audio_path);
373 if (audio_file.exists())
376 itr_ordered = ordered_frame_numbers.erase(itr_ordered);
382 needs_range_processing =
true;
389 if (frames.count(frame_number))
395 std::deque<int64_t>::iterator itr;
396 for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
398 if (*itr == frame_number)
401 frame_numbers.erase(itr);
404 frame_numbers.push_front(frame_number);
419 frame_numbers.clear();
420 ordered_frame_numbers.clear();
421 needs_range_processing =
true;
422 frame_size_bytes = 0;
425 QString current_path = path.path();
426 path.removeRecursively();
429 InitPath(current_path.toStdString());
439 return frames.size();
443void CacheDisk::CleanUp()
454 int64_t frame_to_remove = frame_numbers.back();
478 root[
"path"] = path.path().toStdString();
481 std::stringstream range_version_str;
482 range_version_str << range_version;
483 root[
"version"] = range_version_str.str();
489 root[
"ranges"] = ranges;
506 catch (
const std::exception& e)
509 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
522 if (!root[
"type"].isNull())
524 if (!root[
"path"].isNull())
526 InitPath(root[
"path"].asString());
Header file for CacheDisk class.
Header file for all Exception classes.
Header file for QtUtilities (compatibiity overlay)
All cache managers in libopenshot are based on this CacheBase class.
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.
virtual void SetJsonValue(const Json::Value root)=0
Load Json::Value into this object.
juce::CriticalSection * cacheCriticalSection
Section lock for multiple threads.
int64_t max_bytes
This is the max number of bytes to cache (0 = no limit)
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)
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)