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());
juce::CriticalSection * cacheCriticalSection
Section lock for multiple threads.
void Add(std::shared_ptr< openshot::Frame > frame)
Add a Frame to the cache.
int64_t Count()
Count the frames in the queue.
This class represents a single frame of video (i.e. image & audio data)
int64_t GetBytes()
Gets the maximum bytes value.
const Json::Value stringToJson(const std::string value)
std::string Json()
Get and Set JSON methods.
std::shared_ptr< openshot::Frame > GetFrame(int64_t frame_number)
Get a frame from the cache.
void Remove(int64_t frame_number)
Remove a specific frame.
Json::Value JsonValue()
Generate Json::Value for this object.
void MoveToFront(int64_t frame_number)
Move frame to front of queue (so it lasts longer)
void SetJsonValue(const Json::Value root)
Load Json::Value into this object.
All cache managers in libopenshot are based on this CacheBase class.
ChannelLayout
This enumeration determines the audio channel layout (such as stereo, mono, 5 point surround...
virtual Json::Value JsonValue()=0
Generate Json::Value for this object.
void Clear()
Clear the cache of all frames.
std::string cache_type
This is a friendly type name of the derived cache instance.
This namespace is the default namespace for all code in the openshot library.
virtual void SetJsonValue(const Json::Value root)=0
Load Json::Value into this object.
Exception for invalid JSON.
std::shared_ptr< openshot::Frame > GetSmallestFrame()
Get the smallest frame number.
int64_t max_bytes
This is the max number of bytes to cache (0 = no limit)
void SetJson(const std::string value)
Load JSON string into this object.
CacheDisk(std::string cache_path, std::string format, float quality, float scale)
Default constructor, no max bytes.