]> git.sesse.net Git - casparcg/blobdiff - core/thumbnail_generator.cpp
Fix a few Clang warnings.
[casparcg] / core / thumbnail_generator.cpp
index 61cce95fc4eba00de88c8d3781e9d49e2407be2c..09b61de6cdb82b9fae38fc1bf6fd1ff775b6c0bf 100644 (file)
@@ -19,7 +19,7 @@
 * Author: Helge Norberg, helge.norberg@svt.se
 */
 
-#include "stdafx.h"
+#include "StdAfx.h"
 
 #include "thumbnail_generator.h"
 
 #include <iterator>
 #include <set>
 #include <future>
+#include <thread>
 
-#include <boost/thread.hpp>
-#include <boost/range/algorithm/transform.hpp>
 #include <boost/algorithm/string/predicate.hpp>
 #include <boost/filesystem.hpp>
+#include <boost/thread.hpp>
 
 #include <tbb/atomic.h>
 
 #include <common/diagnostics/graph.h>
+#include <common/filesystem.h>
 
 #include "producer/frame_producer.h"
+#include "producer/cg_proxy.h"
 #include "consumer/frame_consumer.h"
 #include "mixer/mixer.h"
 #include "mixer/image/image_mixer.h"
 #include "frame/frame.h"
 #include "frame/draw_frame.h"
 #include "frame/frame_transform.h"
+#include "frame/audio_channel_layout.h"
+#include "producer/media_info/media_info.h"
+#include "producer/media_info/media_info_repository.h"
 
 namespace caspar { namespace core {
 
-std::wstring get_relative_without_extension(
-               const boost::filesystem::wpath& file,
-               const boost::filesystem::wpath& relative_to)
-{
-       auto result = file.stem();
-
-       boost::filesystem::wpath current_path = file;
-
-       while (true)
-       {
-               current_path = current_path.parent_path();
-
-               if (boost::filesystem::equivalent(current_path, relative_to))
-                       break;
-
-               if (current_path.empty())
-                       throw std::runtime_error("File not relative to folder");
-
-               result = current_path.filename() / result;
-       }
-
-       return result.wstring();
-}
-
 struct thumbnail_output
 {
        tbb::atomic<int> sleep_millis;
@@ -87,7 +68,7 @@ struct thumbnail_output
                int current_sleep = sleep_millis;
 
                if (current_sleep > 0)
-                       boost::this_thread::sleep(boost::posix_time::milliseconds(current_sleep));
+                       std::this_thread::sleep_for(std::chrono::milliseconds(current_sleep));
 
                on_send(std::move(frame));
                on_send = nullptr;
@@ -97,28 +78,36 @@ struct thumbnail_output
 struct thumbnail_generator::impl
 {
 private:
-       boost::filesystem::wpath media_path_;
-       boost::filesystem::wpath thumbnails_path_;
-       int width_;
-       int height_;
-       spl::shared_ptr<image_mixer> image_mixer_;
-       spl::shared_ptr<diagnostics::graph> graph_;
-       video_format_desc format_desc_;
-       spl::unique_ptr<thumbnail_output> output_;
-       mixer mixer_;
-       thumbnail_creator thumbnail_creator_;
-       filesystem_monitor::ptr monitor_;
+       boost::filesystem::path                                                 media_path_;
+       boost::filesystem::path                                                 thumbnails_path_;
+       int                                                                                             width_;
+       int                                                                                             height_;
+       spl::shared_ptr<image_mixer>                                    image_mixer_;
+       spl::shared_ptr<diagnostics::graph>                             graph_;
+       video_format_desc                                                               format_desc_;
+       spl::unique_ptr<thumbnail_output>                               output_;
+       mixer                                                                                   mixer_;
+       thumbnail_creator                                                               thumbnail_creator_;
+       spl::shared_ptr<media_info_repository>                  media_info_repo_;
+       spl::shared_ptr<const frame_producer_registry>  producer_registry_;
+       spl::shared_ptr<const cg_producer_registry>             cg_registry_;
+       bool                                                                                    mipmap_;
+       filesystem_monitor::ptr                                                 monitor_;
 public:
        impl(
                        filesystem_monitor_factory& monitor_factory,
-                       const boost::filesystem::wpath& media_path,
-                       const boost::filesystem::wpath& thumbnails_path,
+                       const boost::filesystem::path& media_path,
+                       const boost::filesystem::path& thumbnails_path,
                        int width,
                        int height,
                        const video_format_desc& render_video_mode,
                        std::unique_ptr<image_mixer> image_mixer,
                        int generate_delay_millis,
-                       const thumbnail_creator& thumbnail_creator)
+                       const thumbnail_creator& thumbnail_creator,
+                       spl::shared_ptr<media_info_repository> media_info_repo,
+                       spl::shared_ptr<const frame_producer_registry> producer_registry,
+                       spl::shared_ptr<const cg_producer_registry> cg_registry,
+                       bool mipmap)
                : media_path_(media_path)
                , thumbnails_path_(thumbnails_path)
                , width_(width)
@@ -126,17 +115,21 @@ public:
                , image_mixer_(std::move(image_mixer))
                , format_desc_(render_video_mode)
                , output_(spl::make_unique<thumbnail_output>(generate_delay_millis))
-               , mixer_(graph_, image_mixer_)
+               , mixer_(0, graph_, image_mixer_)
                , thumbnail_creator_(thumbnail_creator)
+               , media_info_repo_(std::move(media_info_repo))
+               , producer_registry_(std::move(producer_registry))
+               , cg_registry_(std::move(cg_registry))
+               , mipmap_(mipmap)
                , monitor_(monitor_factory.create(
                                media_path,
                                filesystem_event::ALL,
                                true,
-                               [this] (filesystem_event event, const boost::filesystem::wpath& file)
+                               [this] (filesystem_event event, const boost::filesystem::path& file)
                                {
                                        this->on_file_event(event, file);
                                },
-                               [this] (const std::set<boost::filesystem::wpath>& initial_files) 
+                               [this] (const std::set<boost::filesystem::path>& initial_files)
                                {
                                        this->on_initial_files(initial_files);
                                }))
@@ -148,7 +141,7 @@ public:
                //output_->sleep_millis = 2000;
        }
 
-       void on_initial_files(const std::set<boost::filesystem::wpath>& initial_files)
+       void on_initial_files(const std::set<boost::filesystem::path>& initial_files)
        {
                using namespace boost::filesystem;
 
@@ -158,7 +151,7 @@ public:
                                std::insert_iterator<std::set<std::wstring>>(
                                                relative_without_extensions,
                                                relative_without_extensions.end()),
-                               boost::bind(&get_relative_without_extension, _1, media_path_));
+                               [&](const path& p) { return get_relative_without_extension(p, media_path_).wstring(); });
 
                for (boost::filesystem::wrecursive_directory_iterator iter(thumbnails_path_); iter != boost::filesystem::wrecursive_directory_iterator(); ++iter)
                {
@@ -168,27 +161,35 @@ public:
                                continue;
 
                        auto relative_without_extension = get_relative_without_extension(path, thumbnails_path_);
-                       bool no_corresponding_media_file = relative_without_extensions.find(relative_without_extension
+                       bool no_corresponding_media_file = relative_without_extensions.find(relative_without_extension.wstring())
                                        == relative_without_extensions.end();
 
                        if (no_corresponding_media_file)
-                               remove(thumbnails_path_ / (relative_without_extension + L".png"));
+                               remove(thumbnails_path_ / (relative_without_extension.wstring() + L".png"));
                }
        }
 
        void generate(const std::wstring& media_file)
        {
                using namespace boost::filesystem;
-               auto base_file = media_path_ / media_file;
-               auto folder = base_file.parent_path();
+
+               auto base_file  = media_path_ / media_file;
+               auto folder             = base_file.parent_path();
+               bool found              = false;
 
                for (boost::filesystem::directory_iterator iter(folder); iter != boost::filesystem::directory_iterator(); ++iter)
                {
                        auto stem = iter->path().stem();
 
                        if (boost::iequals(stem.wstring(), base_file.filename().wstring()))
+                       {
                                monitor_->reemmit(iter->path());
+                               found = true;
+                       }
                }
+
+               if (!found)
+                       CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(L"Media file " + media_file + L" not found"));
        }
 
        void generate_all()
@@ -196,7 +197,7 @@ public:
                monitor_->reemmit_all();
        }
 
-       void on_file_event(filesystem_event event, const boost::filesystem::wpath& file)
+       void on_file_event(filesystem_event event, const boost::filesystem::path& file)
        {
                switch (event)
                {
@@ -211,17 +212,18 @@ public:
                        break;
                case filesystem_event::REMOVED:
                        auto relative_without_extension = get_relative_without_extension(file, media_path_);
-                       boost::filesystem::remove(thumbnails_path_ / (relative_without_extension + L".png"));
+                       boost::filesystem::remove(thumbnails_path_ / (relative_without_extension.wstring() + L".png"));
+                       media_info_repo_->remove(file.wstring());
 
                        break;
                }
        }
 
-       bool needs_to_be_generated(const boost::filesystem::wpath& file)
+       bool needs_to_be_generated(const boost::filesystem::path& file)
        {
                using namespace boost::filesystem;
 
-               auto png_file = thumbnails_path_ / (get_relative_without_extension(file, media_path_) + L".png");
+               auto png_file = thumbnails_path_ / (get_relative_without_extension(file, media_path_).wstring() + L".png");
 
                if (!exists(png_file))
                        return true;
@@ -249,35 +251,14 @@ public:
                }
        }
 
-       void generate_thumbnail(const boost::filesystem::wpath& file)
+       void generate_thumbnail(const boost::filesystem::path& file)
        {
+               auto media_file_with_extension = get_relative(file, media_path_);
                auto media_file = get_relative_without_extension(file, media_path_);
-               auto png_file = thumbnails_path_ / (media_file + L".png");
+               auto png_file = thumbnails_path_ / (media_file.wstring() + L".png");
                std::promise<void> thumbnail_ready;
 
                {
-                       auto producer = frame_producer::empty();
-
-                       try
-                       {
-                               producer = create_thumbnail_producer(image_mixer_, format_desc_, media_file);
-                       }
-                       catch (const boost::thread_interrupted&)
-                       {
-                               throw;
-                       }
-                       catch (...)
-                       {
-                               CASPAR_LOG(debug) << L"Thumbnail producer failed to initialize for " << media_file;
-                               return;
-                       }
-
-                       if (producer == frame_producer::empty())
-                       {
-                               CASPAR_LOG(trace) << L"No appropriate thumbnail producer found for " << media_file;
-                               return;
-                       }
-
                        boost::filesystem::create_directories(png_file.parent_path());
                        output_->on_send = [this, &png_file] (const_frame frame)
                        {
@@ -289,7 +270,9 @@ public:
 
                        try
                        {
-                               raw_frame = producer->create_thumbnail_frame();
+                               raw_frame = producer_registry_->create_thumbnail(frame_producer_dependencies(image_mixer_, {}, format_desc_, producer_registry_, cg_registry_), media_file.wstring());
+                               media_info_repo_->remove(file.wstring());
+                               media_info_repo_->get(file.wstring());
                        }
                        catch (const boost::thread_interrupted&)
                        {
@@ -297,25 +280,27 @@ public:
                        }
                        catch (...)
                        {
-                               CASPAR_LOG(debug) << L"Thumbnail producer failed to create thumbnail for " << media_file;
+                               CASPAR_LOG_CURRENT_EXCEPTION_AT_LEVEL(trace);
+                               CASPAR_LOG(info) << L"Thumbnail producer failed to create thumbnail for " << media_file_with_extension << L". Turn on log level trace to see more information.";
                                return;
                        }
 
                        if (raw_frame == draw_frame::empty()
                                        || raw_frame == draw_frame::late())
                        {
-                               CASPAR_LOG(debug) << L"No thumbnail generated for " << media_file;
+                               CASPAR_LOG(debug) << L"No thumbnail producer for " << media_file_with_extension;
                                return;
                        }
 
                        auto transformed_frame = draw_frame(raw_frame);
                        transformed_frame.transform().image_transform.fill_scale[0] = static_cast<double>(width_) / format_desc_.width;
                        transformed_frame.transform().image_transform.fill_scale[1] = static_cast<double>(height_) / format_desc_.height;
+                       transformed_frame.transform().image_transform.use_mipmap = mipmap_;
                        frames.insert(std::make_pair(0, transformed_frame));
 
                        std::shared_ptr<void> ticket(nullptr, [&thumbnail_ready](void*) { thumbnail_ready.set_value(); });
 
-                       auto mixed_frame = mixer_(frames, format_desc_);
+                       auto mixed_frame = mixer_(std::move(frames), format_desc_, audio_channel_layout(2, L"stereo", L""));
 
                        output_->send(std::move(mixed_frame), ticket);
                        ticket.reset();
@@ -328,7 +313,7 @@ public:
                        try
                        {
                                boost::filesystem::last_write_time(png_file, boost::filesystem::last_write_time(file));
-                               CASPAR_LOG(debug) << L"Generated thumbnail for " << media_file;
+                               CASPAR_LOG(info) << L"Generated thumbnail for " << media_file_with_extension;
                        }
                        catch (...)
                        {
@@ -336,20 +321,24 @@ public:
                        }
                }
                else
-                       CASPAR_LOG(debug) << L"No thumbnail generated for " << media_file;
+                       CASPAR_LOG(debug) << L"No thumbnail generated for " << media_file_with_extension;
        }
 };
 
 thumbnail_generator::thumbnail_generator(
                filesystem_monitor_factory& monitor_factory,
-               const boost::filesystem::wpath& media_path,
-               const boost::filesystem::wpath& thumbnails_path,
+               const boost::filesystem::path& media_path,
+               const boost::filesystem::path& thumbnails_path,
                int width,
                int height,
                const video_format_desc& render_video_mode,
                std::unique_ptr<image_mixer> image_mixer,
                int generate_delay_millis,
-               const thumbnail_creator& thumbnail_creator)
+               const thumbnail_creator& thumbnail_creator,
+               spl::shared_ptr<media_info_repository> media_info_repo,
+               spl::shared_ptr<const frame_producer_registry> producer_registry,
+               spl::shared_ptr<const cg_producer_registry> cg_registry,
+               bool mipmap)
                : impl_(new impl(
                                monitor_factory,
                                media_path,
@@ -358,7 +347,11 @@ thumbnail_generator::thumbnail_generator(
                                render_video_mode,
                                std::move(image_mixer),
                                generate_delay_millis,
-                               thumbnail_creator))
+                               thumbnail_creator,
+                               media_info_repo,
+                               producer_registry,
+                               cg_registry,
+                               mipmap))
 {
 }
 
@@ -376,4 +369,4 @@ void thumbnail_generator::generate_all()
        impl_->generate_all();
 }
 
-}}
\ No newline at end of file
+}}