21 #include <QTextStream>
27 CacheDisk::CacheDisk(std::string cache_path, std::string format,
float quality,
float scale) :
CacheBase(0) {
33 image_format = format;
34 image_quality = quality;
49 image_format = format;
50 image_quality = quality;
58 void 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();
397 void 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());