28 #include "../include/CacheDisk.h" 34 CacheDisk::CacheDisk(
string cache_path,
string format,
float quality,
float scale) :
CacheBase(0) {
38 needs_range_processing =
false;
40 image_format = format;
41 image_quality = quality;
54 needs_range_processing =
false;
56 image_format = format;
57 image_quality = quality;
65 void CacheDisk::InitPath(
string cache_path) {
68 if (!cache_path.empty()) {
70 qpath = QString(cache_path.c_str());
74 qpath = QDir::tempPath() + QString(
"/preview-cache/");
87 void CacheDisk::CalculateRanges() {
89 if (needs_range_processing) {
95 std::sort(ordered_frame_numbers.begin(), ordered_frame_numbers.end());
98 Json::Value ranges = Json::Value(Json::arrayValue);
103 vector<long int>::iterator itr_ordered;
104 long int starting_frame = *ordered_frame_numbers.begin();
105 long int ending_frame = *ordered_frame_numbers.begin();
108 for (itr_ordered = ordered_frame_numbers.begin(); itr_ordered != ordered_frame_numbers.end(); ++itr_ordered) {
109 long int frame_number = *itr_ordered;
110 if (frame_number - ending_frame > 1) {
116 stringstream start_str;
117 start_str << starting_frame;
118 stringstream end_str;
119 end_str << ending_frame;
120 range[
"start"] = start_str.str();
121 range[
"end"] = end_str.str();
122 ranges.append(range);
125 starting_frame = frame_number;
129 ending_frame = frame_number;
137 stringstream start_str;
138 start_str << starting_frame;
139 stringstream end_str;
140 end_str << ending_frame;
141 range[
"start"] = start_str.str();
142 range[
"end"] = end_str.str();
143 ranges.append(range);
146 json_ranges = ranges.toStyledString();
149 needs_range_processing =
false;
157 frame_numbers.clear();
158 ordered_frame_numbers.clear();
170 long int frame_number = frame->number;
173 if (frames.count(frame_number))
180 frames[frame_number] = frame_number;
181 frame_numbers.push_front(frame_number);
182 ordered_frame_numbers.push_back(frame_number);
183 needs_range_processing =
true;
186 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(frame_number) + QString(image_format.c_str()).toLower());
187 frame->Save(frame_path.toStdString(), image_scale, image_format, image_quality);
188 if (frame_size_bytes == 0) {
190 QFile image_file(frame_path);
191 frame_size_bytes = image_file.size();
195 if (frame->has_audio_data) {
196 QString audio_path(path.path() +
"/" + QString(
"%1").arg(frame_number) +
".audio");
197 QFile audio_file(audio_path);
199 if (audio_file.open(QIODevice::WriteOnly)) {
200 QTextStream audio_stream(&audio_file);
201 audio_stream << frame->SampleRate() << endl;
202 audio_stream << frame->GetAudioChannelsCount() << endl;
203 audio_stream << frame->GetAudioSamplesCount() << endl;
204 audio_stream << frame->ChannelsLayout() << endl;
207 for (
int channel = 0; channel < frame->GetAudioChannelsCount(); channel++)
210 float *samples = frame->GetAudioSamples(channel);
211 for (
int sample = 0; sample < frame->GetAudioSamplesCount(); sample++)
212 audio_stream << samples[sample] << endl;
231 if (frames.count(frame_number)) {
233 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(frame_number) + QString(image_format.c_str()).toLower());
234 if (path.exists(frame_path)) {
237 std::shared_ptr<QImage> image = std::shared_ptr<QImage>(
new QImage());
238 bool success = image->load(QString::fromStdString(frame_path.toStdString()));
241 image = std::shared_ptr<QImage>(
new QImage(image->convertToFormat(QImage::Format_RGBA8888)));
244 std::shared_ptr<Frame> frame(
new Frame());
245 frame->number = frame_number;
246 frame->AddImage(image);
249 QString audio_path(path.path() +
"/" + QString(
"%1").arg(frame_number) +
".audio");
250 QFile audio_file(audio_path);
251 if (audio_file.exists()) {
253 QTextStream in(&audio_file);
254 if (audio_file.open(QIODevice::ReadOnly)) {
255 int sample_rate = in.readLine().toInt();
256 int channels = in.readLine().toInt();
257 int sample_count = in.readLine().toInt();
258 int channel_layout = in.readLine().toInt();
261 frame->ResizeAudio(channels, sample_count, sample_rate, (
ChannelLayout) channel_layout);
264 int current_channel = 0;
265 int current_sample = 0;
266 float *channel_samples =
new float[sample_count];
267 while (!in.atEnd()) {
269 channel_samples[current_sample] = in.readLine().toFloat();
272 if (current_sample == sample_count) {
274 frame->AddAudio(
true, current_channel, 0, channel_samples, sample_count, 1.0);
291 return std::shared_ptr<Frame>();
299 std::shared_ptr<openshot::Frame> f;
302 deque<long int>::iterator itr;
303 long int smallest_frame = -1;
304 for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
306 if (*itr < smallest_frame || smallest_frame == -1)
307 smallest_frame = *itr;
322 long long int total_bytes = 0;
325 deque<long int>::reverse_iterator itr;
326 for(itr = frame_numbers.rbegin(); itr != frame_numbers.rend(); ++itr)
327 total_bytes += frame_size_bytes;
335 Remove(frame_number, frame_number);
345 deque<long int>::iterator itr;
346 for(itr = frame_numbers.begin(); itr != frame_numbers.end();)
349 if (*itr >= start_frame_number && *itr <= end_frame_number)
352 itr = frame_numbers.erase(itr);
358 vector<long int>::iterator itr_ordered;
359 for(itr_ordered = ordered_frame_numbers.begin(); itr_ordered != ordered_frame_numbers.end();)
361 if (*itr_ordered >= start_frame_number && *itr_ordered <= end_frame_number)
364 frames.erase(*itr_ordered);
367 QString frame_path(path.path() +
"/" + QString(
"%1.").arg(*itr_ordered) + QString(image_format.c_str()).toLower());
368 QFile image_file(frame_path);
369 if (image_file.exists())
373 QString audio_path(path.path() +
"/" + QString(
"%1").arg(*itr_ordered) +
".audio");
374 QFile audio_file(audio_path);
375 if (audio_file.exists())
378 itr_ordered = ordered_frame_numbers.erase(itr_ordered);
384 needs_range_processing =
true;
391 if (frames.count(frame_number))
397 deque<long int>::iterator itr;
398 for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
400 if (*itr == frame_number)
403 frame_numbers.erase(itr);
406 frame_numbers.push_front(frame_number);
421 frame_numbers.clear();
422 ordered_frame_numbers.clear();
423 needs_range_processing =
true;
424 frame_size_bytes = 0;
427 QString current_path = path.path();
428 path.removeRecursively();
431 InitPath(current_path.toStdString());
441 return frames.size();
445 void CacheDisk::CleanUp()
456 long int frame_to_remove = frame_numbers.back();
480 root[
"path"] = path.path().toStdString();
483 stringstream range_version_str;
484 range_version_str << range_version;
485 root[
"version"] = range_version_str.str();
490 bool success = reader.parse( json_ranges, ranges );
492 root[
"ranges"] = ranges;
504 bool success = reader.parse( value, root );
507 throw InvalidJSON(
"JSON could not be parsed (or is invalid)",
"");
517 throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)",
"");
530 if (!root[
"type"].isNull())
532 if (!root[
"path"].isNull())
534 InitPath(root[
"path"].asString());
CriticalSection * cacheCriticalSection
Section lock for multiple threads.
string cache_type
This is a friendly type name of the derived cache instance.
void Add(std::shared_ptr< Frame > frame)
Add a Frame to the cache.
This class represents a single frame of video (i.e. image & audio data)
long long int max_bytes
This is the max number of bytes to cache (0 = no limit)
long int Count()
Count the frames in the queue.
std::shared_ptr< Frame > GetFrame(long int frame_number)
Get a frame from the cache.
void SetJsonValue(Json::Value root)
Load Json::JsonValue into this object.
void MoveToFront(long int frame_number)
Move frame to front of queue (so it lasts longer)
long long int GetBytes()
Gets the maximum bytes value.
Exception when a reader is closed, and a frame is requested.
Exception for files that can not be found or opened.
Json::Value JsonValue()
Generate Json::JsonValue for 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...
void Remove(long int frame_number)
Remove a specific frame.
virtual Json::Value JsonValue()=0
Generate Json::JsonValue for this object.
void Clear()
Clear the cache of all frames.
This namespace is the default namespace for all code in the openshot library.
CacheDisk(string cache_path, string format, float quality, float scale)
Default constructor, no max bytes.
Exception for invalid JSON.
std::shared_ptr< Frame > GetSmallestFrame()
Get the smallest frame number.
void SetJson(string value)
Load JSON string into this object.
virtual void SetJsonValue(Json::Value root)=0
Load Json::JsonValue into this object.
string Json()
Get and Set JSON methods.