20 #include <QTextStream> 
   26 CacheDisk::CacheDisk(std::string cache_path, std::string format, 
float quality, 
float scale) : 
CacheBase(0) {
 
   32     image_format = format;
 
   33     image_quality = quality;
 
   48     image_format = format;
 
   49     image_quality = quality;
 
   57 void CacheDisk::InitPath(std::string cache_path) {
 
   60     if (!cache_path.empty()) {
 
   62         qpath = QString(cache_path.c_str());
 
   66         qpath = QDir::tempPath() + QString(
"/preview-cache/");
 
   91     const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
 
   92     int64_t frame_number = frame->number;
 
   95     if (frames.count(frame_number))
 
  102         frames[frame_number] = frame_number;
 
  103         frame_numbers.push_front(frame_number);
 
  108         QString frame_path(path.path() + 
"/" + QString(
"%1.").arg(frame_number) + QString(image_format.c_str()).toLower());
 
  109         frame->Save(frame_path.toStdString(), image_scale, image_format, image_quality);
 
  110         if (frame_size_bytes == 0) {
 
  112             QFile image_file(frame_path);
 
  113             frame_size_bytes = image_file.size();
 
  117         if (frame->has_audio_data) {
 
  118             QString audio_path(path.path() + 
"/" + QString(
"%1").arg(frame_number) + 
".audio");
 
  119             QFile audio_file(audio_path);
 
  121             if (audio_file.open(QIODevice::WriteOnly)) {
 
  122                 QTextStream audio_stream(&audio_file);
 
  123                 audio_stream << frame->SampleRate() << Qt::endl;
 
  124                 audio_stream << frame->GetAudioChannelsCount() << Qt::endl;
 
  125                 audio_stream << frame->GetAudioSamplesCount() << Qt::endl;
 
  126                 audio_stream << frame->ChannelsLayout() << Qt::endl;
 
  129                 for (
int channel = 0; channel < frame->GetAudioChannelsCount(); channel++)
 
  132                     float *samples = frame->GetAudioSamples(channel);
 
  133                     for (
int sample = 0; sample < frame->GetAudioSamplesCount(); sample++)
 
  134                         audio_stream << samples[sample] << Qt::endl;
 
  148     if (frames.count(frame_number) > 0) {
 
  159     const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
 
  162     if (frames.count(frame_number)) {
 
  164         QString frame_path(path.path() + 
"/" + QString(
"%1.").arg(frame_number) + QString(image_format.c_str()).toLower());
 
  165         if (path.exists(frame_path)) {
 
  168             auto image = std::make_shared<QImage>();
 
  169             image->load(frame_path);
 
  172             image = std::make_shared<QImage>(image->convertToFormat(QImage::Format_RGBA8888_Premultiplied));
 
  175             auto frame = std::make_shared<Frame>();
 
  176             frame->number = frame_number;
 
  177             frame->AddImage(image);
 
  180             QString audio_path(path.path() + 
"/" + QString(
"%1").arg(frame_number) + 
".audio");
 
  181             QFile audio_file(audio_path);
 
  182             if (audio_file.exists()) {
 
  184                 QTextStream in(&audio_file);
 
  185                 if (audio_file.open(QIODevice::ReadOnly)) {
 
  186                     int sample_rate = in.readLine().toInt();
 
  187                     int channels = in.readLine().toInt();
 
  188                     int sample_count = in.readLine().toInt();
 
  189                     int channel_layout = in.readLine().toInt();
 
  192                     frame->ResizeAudio(channels, sample_count, sample_rate, (
ChannelLayout) channel_layout);
 
  195                     int current_channel = 0;
 
  196                     int current_sample = 0;
 
  197                     float *channel_samples = 
new float[sample_count];
 
  198                     while (!in.atEnd()) {
 
  200                         channel_samples[current_sample] = in.readLine().toFloat();
 
  203                         if (current_sample == sample_count) {
 
  205                             frame->AddAudio(
true, current_channel, 0, channel_samples, sample_count, 1.0);
 
  222     return std::shared_ptr<Frame>();
 
  229     const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
 
  231     std::vector<std::shared_ptr<openshot::Frame>> all_frames;
 
  232     std::vector<int64_t>::iterator itr_ordered;
 
  235         int64_t frame_number = *itr_ordered;
 
  236         all_frames.push_back(
GetFrame(frame_number));
 
  246     const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
 
  249     std::deque<int64_t>::iterator itr;
 
  250     int64_t smallest_frame = -1;
 
  251     for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
 
  253         if (*itr < smallest_frame || smallest_frame == -1)
 
  254             smallest_frame = *itr;
 
  258     if (smallest_frame != -1) {
 
  269     const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
 
  271     int64_t  total_bytes = 0;
 
  274     std::deque<int64_t>::reverse_iterator itr;
 
  275     for(itr = frame_numbers.rbegin(); itr != frame_numbers.rend(); ++itr)
 
  276         total_bytes += frame_size_bytes;
 
  284     Remove(frame_number, frame_number);
 
  291     const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
 
  294     std::deque<int64_t>::iterator itr;
 
  295     for(itr = frame_numbers.begin(); itr != frame_numbers.end();)
 
  298         if (*itr >= start_frame_number && *itr <= end_frame_number)
 
  301             itr = frame_numbers.erase(itr);
 
  307     std::vector<int64_t>::iterator itr_ordered;
 
  310         if (*itr_ordered >= start_frame_number && *itr_ordered <= end_frame_number)
 
  313             frames.erase(*itr_ordered);
 
  316             QString frame_path(path.path() + 
"/" + QString(
"%1.").arg(*itr_ordered) + QString(image_format.c_str()).toLower());
 
  317             QFile image_file(frame_path);
 
  318             if (image_file.exists())
 
  322             QString audio_path(path.path() + 
"/" + QString(
"%1").arg(*itr_ordered) + 
".audio");
 
  323             QFile audio_file(audio_path);
 
  324             if (audio_file.exists())
 
  340     if (frames.count(frame_number))
 
  343         const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
 
  346         std::deque<int64_t>::iterator itr;
 
  347         for(itr = frame_numbers.begin(); itr != frame_numbers.end(); ++itr)
 
  349             if (*itr == frame_number)
 
  352                 frame_numbers.erase(itr);
 
  355                 frame_numbers.push_front(frame_number);
 
  366     const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
 
  370     frame_numbers.clear();
 
  371     frame_numbers.shrink_to_fit();
 
  375     frame_size_bytes = 0;
 
  378     QString current_path = path.path();
 
  379     path.removeRecursively();
 
  382     InitPath(current_path.toStdString());
 
  389     const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
 
  392     return frames.size();
 
  396 void CacheDisk::CleanUp()
 
  402         const std::lock_guard<std::recursive_mutex> lock(*
cacheMutex);
 
  407             int64_t frame_to_remove = frame_numbers.back();
 
  431     root[
"path"] = path.path().toStdString();
 
  434     std::stringstream range_version_str;
 
  436     root[
"version"] = range_version_str.str();
 
  442         root[
"ranges"] = ranges;
 
  459     catch (
const std::exception& e)
 
  462         throw InvalidJSON(
"JSON is invalid (missing keys or invalid data types)");
 
  475     if (!root[
"type"].isNull())
 
  477     if (!root[
"path"].isNull())
 
  479         InitPath(root[
"path"].asString());