31 #include "../include/CacheDisk.h"
37 CacheDisk::CacheDisk(std::string cache_path, std::string format,
float quality,
float scale) :
CacheBase(0) {
41 needs_range_processing =
false;
43 image_format = format;
44 image_quality = quality;
57 needs_range_processing =
false;
59 image_format = format;
60 image_quality = quality;
68 void CacheDisk::InitPath(std::string cache_path) {
71 if (!cache_path.empty()) {
73 qpath = QString(cache_path.c_str());
77 qpath = QDir::tempPath() + QString(
"/preview-cache/");
90 void CacheDisk::CalculateRanges() {
92 if (needs_range_processing) {
98 std::sort(ordered_frame_numbers.begin(), ordered_frame_numbers.end());
101 Json::Value ranges = Json::Value(Json::arrayValue);
106 int64_t starting_frame = *ordered_frame_numbers.begin();
107 int64_t ending_frame = starting_frame;
110 for (
const auto frame_number : ordered_frame_numbers) {
111 if (frame_number - ending_frame > 1) {
117 range[
"start"] = std::to_string(starting_frame);
118 range[
"end"] = std::to_string(ending_frame);
119 ranges.append(range);
122 starting_frame = frame_number;
126 ending_frame = frame_number;
134 range[
"start"] = std::to_string(starting_frame);
135 range[
"end"] = std::to_string(ending_frame);
136 ranges.append(range);
139 json_ranges = ranges.toStyledString();
142 needs_range_processing =
false;
150 frame_numbers.clear();
151 ordered_frame_numbers.clear();
163 int64_t frame_number = frame->number;
166 if (frames.count(frame_number))
173 frames[frame_number] = frame_number;
174 frame_numbers.push_front(frame_number);
175 ordered_frame_numbers.push_back(frame_number);
176 needs_range_processing =
true;
179 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(frame_number) + QString(image_format.c_str()).toLower());
180 frame->Save(frame_path.toStdString(), image_scale, image_format, image_quality);
181 if (frame_size_bytes == 0) {
183 QFile image_file(frame_path);
184 frame_size_bytes = image_file.size();
188 if (frame->has_audio_data) {
189 QString audio_path(path.path() +
"/" + QString(
"%1").arg(frame_number) +
".audio");
190 QFile audio_file(audio_path);
192 if (audio_file.open(QIODevice::WriteOnly)) {
193 QTextStream audio_stream(&audio_file);
194 audio_stream << frame->SampleRate() << endl;
195 audio_stream << frame->GetAudioChannelsCount() << endl;
196 audio_stream << frame->GetAudioSamplesCount() << endl;
197 audio_stream << frame->ChannelsLayout() << endl;
200 for (
int channel = 0; channel < frame->GetAudioChannelsCount(); channel++)
203 float *samples = frame->GetAudioSamples(channel);
204 for (
int sample = 0; sample < frame->GetAudioSamplesCount(); sample++)
205 audio_stream << samples[sample] << endl;
224 if (frames.count(frame_number)) {
226 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(frame_number) + QString(image_format.c_str()).toLower());
227 if (path.exists(frame_path)) {
230 std::shared_ptr<QImage> image = std::shared_ptr<QImage>(
new QImage());
231 bool success = image->load(QString::fromStdString(frame_path.toStdString()));
234 image = std::shared_ptr<QImage>(
new QImage(image->convertToFormat(QImage::Format_RGBA8888)));
237 std::shared_ptr<Frame> frame(
new Frame());
238 frame->number = frame_number;
239 frame->AddImage(image);
242 QString audio_path(path.path() +
"/" + QString(
"%1").arg(frame_number) +
".audio");
243 QFile audio_file(audio_path);
244 if (audio_file.exists()) {
246 QTextStream in(&audio_file);
247 if (audio_file.open(QIODevice::ReadOnly)) {
248 int sample_rate = in.readLine().toInt();
249 int channels = in.readLine().toInt();
250 int sample_count = in.readLine().toInt();
251 int channel_layout = in.readLine().toInt();
254 frame->ResizeAudio(channels, sample_count, sample_rate, (
ChannelLayout) channel_layout);
257 int current_channel = 0;
258 int current_sample = 0;
259 float *channel_samples =
new float[sample_count];
260 while (!in.atEnd()) {
262 channel_samples[current_sample] = in.readLine().toFloat();
265 if (current_sample == sample_count) {
267 frame->AddAudio(
true, current_channel, 0, channel_samples, sample_count, 1.0);
284 return std::shared_ptr<Frame>();
292 std::shared_ptr<openshot::Frame> f;
295 std::deque<int64_t>::iterator itr;
296 int64_t smallest_frame = -1;
297 for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
299 if (*itr < smallest_frame || smallest_frame == -1)
300 smallest_frame = *itr;
315 int64_t total_bytes = 0;
318 std::deque<int64_t>::reverse_iterator itr;
319 for(itr = frame_numbers.rbegin(); itr != frame_numbers.rend(); ++itr)
320 total_bytes += frame_size_bytes;
328 Remove(frame_number, frame_number);
338 std::deque<int64_t>::iterator itr;
339 for(itr = frame_numbers.begin(); itr != frame_numbers.end();)
342 if (*itr >= start_frame_number && *itr <= end_frame_number)
345 itr = frame_numbers.erase(itr);
351 std::vector<int64_t>::iterator itr_ordered;
352 for(itr_ordered = ordered_frame_numbers.begin(); itr_ordered != ordered_frame_numbers.end();)
354 if (*itr_ordered >= start_frame_number && *itr_ordered <= end_frame_number)
357 frames.erase(*itr_ordered);
360 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(*itr_ordered) + QString(image_format.c_str()).toLower());
361 QFile image_file(frame_path);
362 if (image_file.exists())
366 QString audio_path(path.path() +
"/" + QString(
"%1").arg(*itr_ordered) +
".audio");
367 QFile audio_file(audio_path);
368 if (audio_file.exists())
371 itr_ordered = ordered_frame_numbers.erase(itr_ordered);
377 needs_range_processing =
true;
384 if (frames.count(frame_number))
390 std::deque<int64_t>::iterator itr;
391 for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
393 if (*itr == frame_number)
396 frame_numbers.erase(itr);
399 frame_numbers.push_front(frame_number);
414 frame_numbers.clear();
415 ordered_frame_numbers.clear();
416 needs_range_processing =
true;
417 frame_size_bytes = 0;
420 QString current_path = path.path();
421 path.removeRecursively();
424 InitPath(current_path.toStdString());
434 return frames.size();
438 void CacheDisk::CleanUp()
449 int64_t frame_to_remove = frame_numbers.back();
473 root[
"path"] = path.path().toStdString();
476 std::stringstream range_version_str;
477 range_version_str << range_version;
478 root[
"version"] = range_version_str.str();
484 root[
"ranges"] = ranges;
501 catch (
const std::exception& e)
504 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
517 if (!root[
"type"].isNull())
519 if (!root[
"path"].isNull())
521 InitPath(root[
"path"].asString());
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()
Get and Set JSON methods.
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.
This class represents a single frame of video (i.e. image & audio data)
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)