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<int64_t>::iterator itr_ordered;
104 int64_t starting_frame = *ordered_frame_numbers.begin();
105 int64_t ending_frame = *ordered_frame_numbers.begin();
108 for (itr_ordered = ordered_frame_numbers.begin(); itr_ordered != ordered_frame_numbers.end(); ++itr_ordered) {
109 int64_t 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 int64_t 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<int64_t>::iterator itr;
303 int64_t 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 int64_t total_bytes = 0;
325 deque<int64_t>::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<int64_t>::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<int64_t>::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<int64_t>::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 int64_t 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.
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.
void SetJsonValue(Json::Value root)
Load Json::JsonValue into this object.
std::shared_ptr< 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::JsonValue for this object.
void MoveToFront(int64_t frame_number)
Move frame to front of queue (so it lasts longer)
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::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.
int64_t max_bytes
This is the max number of bytes to cache (0 = no limit)
virtual void SetJsonValue(Json::Value root)=0
Load Json::JsonValue into this object.
string Json()
Get and Set JSON methods.