]> git.sesse.net Git - casparcg/commitdiff
Don't persist media info, but generate at server startup in background thread instead...
authorHelge Norberg <helge.norberg@gmail.com>
Thu, 14 Nov 2013 13:37:24 +0000 (14:37 +0100)
committerHelge Norberg <helge.norberg@gmail.com>
Thu, 14 Nov 2013 13:37:24 +0000 (14:37 +0100)
18 files changed:
core/core.vcxproj
core/core.vcxproj.filters
core/producer/frame_producer.cpp
core/producer/frame_producer.h
core/producer/media_info/file_based_media_info_repository.cpp [deleted file]
core/producer/media_info/in_memory_media_info_repository.cpp [new file with mode: 0644]
core/producer/media_info/in_memory_media_info_repository.h [moved from core/producer/media_info/file_based_media_info_repository.h with 89% similarity]
core/producer/media_info/media_info_repository.h
core/producer/separated/separated_producer.cpp
core/thumbnail_generator.cpp
modules/ffmpeg/ffmpeg.cpp
modules/ffmpeg/ffmpeg.h
modules/ffmpeg/producer/ffmpeg_producer.cpp
modules/ffmpeg/producer/util/util.cpp
modules/ffmpeg/producer/util/util.h
modules/image/producer/image_producer.cpp
protocol/amcp/AMCPCommandsImpl.cpp
shell/server.cpp

index 93b8c4f6c5bb7ce7e75b674bd6cc377d079c1e69..6dafa35cfdb0b008b98b90e46420f3f7347b4c8e 100644 (file)
     <ClInclude Include="parameters\parameters.h" />\r
     <ClInclude Include="monitor\monitor.h" />\r
     <ClInclude Include="producer\channel\channel_producer.h" />\r
-    <ClInclude Include="producer\media_info\file_based_media_info_repository.h" />\r
+    <ClInclude Include="producer\media_info\in_memory_media_info_repository.h" />\r
     <ClInclude Include="producer\media_info\media_info.h" />\r
     <ClInclude Include="producer\media_info\media_info_repository.h" />\r
     <ClInclude Include="thumbnail_generator.h" />\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="producer\media_info\file_based_media_info_repository.cpp">\r
+    <ClCompile Include="producer\media_info\in_memory_media_info_repository.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
index ef11a28bfb0ac60f8e5a13db0ef01b902ffbb707..c1bc8689be0ff58a5c583944c686d72783b3339f 100644 (file)
     <ClInclude Include="producer\media_info\media_info_repository.h">\r
       <Filter>source\producer\media_info</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="producer\media_info\file_based_media_info_repository.h">\r
+    <ClInclude Include="producer\media_info\in_memory_media_info_repository.h">\r
       <Filter>source\producer\media_info</Filter>\r
     </ClInclude>\r
   </ItemGroup>\r
     <ClCompile Include="parameters\parameters.cpp">\r
       <Filter>source\parameters</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="producer\media_info\file_based_media_info_repository.cpp">\r
+    <ClCompile Include="producer\media_info\in_memory_media_info_repository.cpp">\r
       <Filter>source\producer\media_info</Filter>\r
     </ClCompile>\r
   </ItemGroup>\r
index 06a34a841264efa97b14061cd847d5628880103b..7abaf1401b34e961bd3b3f7c2df5ba7dbdd0e818 100644 (file)
@@ -29,7 +29,6 @@
 \r
 #include "color/color_producer.h"\r
 #include "separated/separated_producer.h"\r
-#include "media_info/media_info.h"\r
 \r
 #include <common/memory/safe_ptr.h>\r
 #include <common/concurrency/executor.h>\r
@@ -133,7 +132,7 @@ public:
 \r
        virtual safe_ptr<basic_frame>                                                           receive(int hints) override                                                                                             {return (*producer_)->receive(hints);}\r
        virtual safe_ptr<basic_frame>                                                           last_frame() const override                                                                                             {return (*producer_)->last_frame();}\r
-       virtual safe_ptr<basic_frame>                                                           create_thumbnail_frame(media_info& additional_info) override                    {return (*producer_)->create_thumbnail_frame(additional_info);}\r
+       virtual safe_ptr<basic_frame>                                                           create_thumbnail_frame() override                                                                               {return (*producer_)->create_thumbnail_frame();}\r
        virtual std::wstring                                                                            print() const override                                                                                                  {return (*producer_)->print();}\r
        virtual boost::property_tree::wptree                                            info() const override                                                                                                   {return (*producer_)->info();}\r
        virtual boost::unique_future<std::wstring>                                      call(const std::wstring& str) override                                                                  {return (*producer_)->call(str);}\r
@@ -168,7 +167,7 @@ public:
 \r
        virtual safe_ptr<basic_frame>                                                           receive(int hints) override                                                                                             {return (producer_)->receive(hints);}\r
        virtual safe_ptr<basic_frame>                                                           last_frame() const override                                                                                             {return (producer_)->last_frame();}\r
-       virtual safe_ptr<basic_frame>                                                           create_thumbnail_frame(media_info& additional_info) override                    {return (producer_)->create_thumbnail_frame(additional_info);}\r
+       virtual safe_ptr<basic_frame>                                                           create_thumbnail_frame() override                                                                               {return (producer_)->create_thumbnail_frame();}\r
        virtual std::wstring                                                                            print() const override                                                                                                  {return (producer_)->print();}\r
        virtual boost::property_tree::wptree                                            info() const override                                                                                                   {return (producer_)->info();}\r
        virtual boost::unique_future<std::wstring>                                      call(const std::wstring& str) override                                                                  {return (producer_)->call(str);}\r
@@ -198,7 +197,7 @@ public:
        \r
        virtual safe_ptr<basic_frame> receive(int){return frame_;}\r
        virtual safe_ptr<core::basic_frame> last_frame() const{return frame_;}\r
-       virtual safe_ptr<core::basic_frame> create_thumbnail_frame(media_info&) {return frame_;}\r
+       virtual safe_ptr<core::basic_frame> create_thumbnail_frame() {return frame_;}\r
        virtual std::wstring print() const{return L"dummy[" + print_ + L"]";}\r
        virtual uint32_t nb_frames() const {return nb_frames_;} \r
        virtual boost::property_tree::wptree info() const override\r
@@ -242,7 +241,7 @@ const safe_ptr<frame_producer>& frame_producer::empty() // nothrow
        return producer;\r
 }\r
 \r
-safe_ptr<basic_frame> frame_producer::create_thumbnail_frame(media_info&)\r
+safe_ptr<basic_frame> frame_producer::create_thumbnail_frame()\r
 {\r
        return basic_frame::empty();\r
 }\r
index c13e30fdc481f1df32f8377142c264a4ae000484..c7d62b35be5fd8489259777f4121db0cab2c9818 100644 (file)
@@ -47,7 +47,6 @@ namespace core {
 class basic_frame;\r
 class parameters;\r
 struct frame_factory;\r
-struct media_info;\r
 \r
 struct frame_producer : boost::noncopyable\r
 {\r
@@ -76,7 +75,7 @@ public:
        \r
        virtual safe_ptr<basic_frame> receive(int hints) = 0;\r
        virtual safe_ptr<core::basic_frame> last_frame() const = 0;\r
-       virtual safe_ptr<basic_frame> create_thumbnail_frame(media_info& additional_info);\r
+       virtual safe_ptr<basic_frame> create_thumbnail_frame();\r
 \r
        static const safe_ptr<frame_producer>& empty(); // nothrow\r
 \r
diff --git a/core/producer/media_info/file_based_media_info_repository.cpp b/core/producer/media_info/file_based_media_info_repository.cpp
deleted file mode 100644 (file)
index 69b0e1d..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
-* Copyright 2013 Sveriges Television AB http://casparcg.com/
-*
-* This file is part of CasparCG (www.casparcg.com).
-*
-* CasparCG is free software: you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation, either version 3 of the License, or
-* (at your option) any later version.
-*
-* CasparCG is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
-*
-* Author: Helge Norberg, helge.norberg@svt.se
-*/
-
-#include "../../StdAfx.h"
-
-#include "file_based_media_info_repository.h"
-
-#include <fstream>
-#include <vector>
-
-#include <boost/thread/mutex.hpp>
-#include <boost/algorithm/string/split.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/foreach.hpp>
-#include <boost/filesystem.hpp>
-
-#include "media_info.h"
-#include "media_info_repository.h"
-
-namespace {
-
-static const std::wstring delimeter = L",";
-
-std::map<std::wstring, caspar::core::media_info> load(
-               const std::wstring& csv_file)
-{
-       std::map<std::wstring, caspar::core::media_info> result;
-       std::wifstream stream(csv_file);
-
-       if (!stream)
-               return result;
-
-       wchar_t line[1024];
-
-       while (stream.getline(line, 1024))
-       {
-               std::vector<std::wstring> cells;
-               boost::split(
-                               cells,
-                               line,
-                               boost::is_any_of(delimeter),
-                               boost::token_compress_on);
-
-               if (cells.size() != 4)
-                       continue;
-
-               auto filename = cells.at(0);
-               caspar::core::media_info info;
-
-               try
-               {
-                       info.duration = boost::lexical_cast<int64_t>(cells.at(1));
-                       info.time_base = boost::rational<int64_t>(
-                                       boost::lexical_cast<int64_t>(cells.at(2)),
-                                       boost::lexical_cast<int64_t>(cells.at(3)));
-               }
-               catch (const boost::bad_lexical_cast&)
-               {
-                       continue;
-               }
-
-               result.insert(std::make_pair(std::move(filename), std::move(info)));
-       }
-
-       return result;
-}
-
-void save(
-               const std::map<std::wstring, caspar::core::media_info>& infos,
-               const std::wstring& csv_file)
-{
-       std::wstring tmp_file = csv_file + L".tmp";
-       std::wofstream stream(tmp_file, std::ios::trunc);
-
-       if (!stream)
-               throw std::exception();
-
-       BOOST_FOREACH(const auto& info, infos)
-       {
-               stream
-                       << info.first << delimeter
-                       << info.second.duration << delimeter
-                       << info.second.time_base.numerator() << delimeter
-                       << info.second.time_base.denominator() << L"\n";
-       }
-
-       stream << std::flush;
-       stream.close();
-       
-       // The remove is unfortunately needed by the current version of boost.
-       boost::filesystem::remove(csv_file);
-       boost::filesystem::rename(tmp_file, csv_file);
-}
-
-}
-
-namespace caspar { namespace core {
-
-class file_based_media_info_repository : public media_info_repository
-{
-       mutable boost::mutex mutex_;
-       std::wstring csv_file_;
-       std::map<std::wstring, media_info> info_by_media_file_;
-public:
-       file_based_media_info_repository(std::wstring csv_file)
-               : csv_file_(std::move(csv_file))
-               , info_by_media_file_(load(csv_file_))
-       {
-       }
-       
-       virtual void store(std::wstring media_file, media_info info) override
-       {
-               boost::mutex::scoped_lock lock(mutex_);
-
-               info_by_media_file_[std::move(media_file)] = info;
-
-               save(info_by_media_file_, csv_file_);
-       }
-       
-       virtual bool try_load(
-                       const std::wstring& media_file, media_info& info) const override
-       {
-               boost::mutex::scoped_lock lock(mutex_);
-
-               auto iter = info_by_media_file_.find(media_file);
-
-               if (iter == info_by_media_file_.end())
-                       return false;
-
-               info = iter->second;
-
-               return true;
-       }
-
-       virtual void remove(const std::wstring& media_file) override
-       {
-               boost::mutex::scoped_lock lock(mutex_);
-
-               info_by_media_file_.erase(media_file);
-
-               save(info_by_media_file_, csv_file_);
-       }
-};
-
-safe_ptr<struct media_info_repository> create_file_based_media_info_repository(
-               std::wstring csv_file)
-{
-       return make_safe<file_based_media_info_repository>(std::move(csv_file));
-}
-
-}}
diff --git a/core/producer/media_info/in_memory_media_info_repository.cpp b/core/producer/media_info/in_memory_media_info_repository.cpp
new file mode 100644 (file)
index 0000000..7e57b09
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+* Copyright 2013 Sveriges Television AB http://casparcg.com/
+*
+* This file is part of CasparCG (www.casparcg.com).
+*
+* CasparCG is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* CasparCG is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
+*
+* Author: Helge Norberg, helge.norberg@svt.se
+*/
+
+#include "../../StdAfx.h"
+
+#include "in_memory_media_info_repository.h"
+
+#include <map>
+#include <vector>
+
+#include <boost/thread/mutex.hpp>
+#include <boost/foreach.hpp>
+
+#include "media_info.h"
+#include "media_info_repository.h"
+
+namespace caspar { namespace core {
+
+class in_memory_media_info_repository : public media_info_repository
+{
+       boost::mutex mutex_;
+       std::map<std::wstring, media_info> info_by_file_;
+       std::vector<media_info_extractor> extractors_;
+public:
+       virtual void register_extractor(media_info_extractor extractor) override
+       {
+               boost::mutex::scoped_lock lock(mutex_);
+
+               extractors_.push_back(extractor);
+       }
+
+       virtual media_info get(const std::wstring& file) override
+       {
+               boost::mutex::scoped_lock lock(mutex_);
+
+               auto iter = info_by_file_.find(file);
+
+               if (iter == info_by_file_.end())
+               {
+                       media_info info;
+
+                       BOOST_FOREACH(auto& extractor, extractors_)
+                       {
+                               if (extractor(file, info))
+                               {
+                                       break;
+                               }
+                       }
+
+                       info_by_file_.insert(std::make_pair(file, info));
+
+                       return info;
+               }
+
+               return iter->second;
+       }
+
+       virtual void remove(const std::wstring& file) override
+       {
+               boost::mutex::scoped_lock lock(mutex_);
+
+               info_by_file_.erase(file);
+       }
+};
+
+safe_ptr<struct media_info_repository> create_in_memory_media_info_repository()
+{
+       return make_safe<in_memory_media_info_repository>();
+}
+
+}}
similarity index 89%
rename from core/producer/media_info/file_based_media_info_repository.h
rename to core/producer/media_info/in_memory_media_info_repository.h
index 8b8297c0ce91565bd1811978d71abc2f7b5d0175..af66086325d2a6a407c91761487e8771066f80ca 100644 (file)
@@ -27,7 +27,6 @@
 
 namespace caspar { namespace core {
 
-safe_ptr<struct media_info_repository> create_file_based_media_info_repository(
-               std::wstring csv_file);
+safe_ptr<struct media_info_repository> create_in_memory_media_info_repository();
 
 }}
index c9b93df1eaf7ed68c151c585d0c4a1fb2be785e1..c01fec67cb3da1733646eae4456ea08b27961e42 100644 (file)
 #pragma once
 
 #include <string>
+#include <functional>
 
 namespace caspar { namespace core {
 
 struct media_info;
+typedef std::function<bool (const std::wstring& f, media_info& info)> media_info_extractor;
 
 struct media_info_repository
 {
        virtual ~media_info_repository() { }
-       virtual void store(std::wstring media_file, media_info info) = 0;
-       virtual bool try_load(
-                       const std::wstring& media_file, media_info& info) const = 0;
-       virtual void remove(const std::wstring& media_file) = 0;
+       virtual void register_extractor(media_info_extractor extractor) = 0;
+       virtual media_info get(const std::wstring& file) = 0;
+       virtual void remove(const std::wstring& file) = 0;
 };
 
 }}
index 816ae8abe3feb80c1ce58e60d29a4c46172bead3..f6fba18ae2957038eebe907442af9b9b3982bb2e 100644 (file)
@@ -26,7 +26,6 @@
 #include "separated_producer.h"\r
 \r
 #include <core/producer/frame/basic_frame.h>\r
-#include <core/producer/media_info/media_info.h>\r
 \r
 #include <tbb/parallel_invoke.h>\r
 \r
@@ -92,11 +91,10 @@ struct separated_producer : public frame_producer
                return disable_audio(last_frame_);\r
        }\r
 \r
-       virtual safe_ptr<basic_frame> create_thumbnail_frame(media_info& additional_info) override\r
+       virtual safe_ptr<basic_frame> create_thumbnail_frame() override\r
        {\r
-               auto fill_frame = fill_producer_->create_thumbnail_frame(additional_info);\r
-               media_info dummy;\r
-               auto key_frame = key_producer_->create_thumbnail_frame(dummy);\r
+               auto fill_frame = fill_producer_->create_thumbnail_frame();\r
+               auto key_frame = key_producer_->create_thumbnail_frame();\r
 \r
                if (fill_frame == basic_frame::empty() || key_frame == basic_frame::empty())\r
                        return basic_frame::empty();\r
index cea2593e95a4bfd5d9156183255db68cd20408b8..b76831799a82c8dfd3322f26ca1300eecf85585c 100644 (file)
@@ -177,7 +177,7 @@ public:
                                        == relative_without_extensions.end();\r
 \r
                        if (no_corresponding_media_file)\r
-                               remove_thumbnail(relative_without_extension);\r
+                               remove(thumbnails_path_ / (relative_without_extension + L".png"));\r
                }\r
        }\r
 \r
@@ -215,18 +215,14 @@ public:
 \r
                        break;\r
                case REMOVED:\r
-                       remove_thumbnail(get_relative_without_extension(file, media_path_));\r
+                       auto relative_without_extension = get_relative_without_extension(file, media_path_);\r
+                       boost::filesystem::remove(thumbnails_path_ / (relative_without_extension + L".png"));\r
+                       media_info_repo_->remove(file.file_string());\r
 \r
                        break;\r
                }\r
        }\r
 \r
-       void remove_thumbnail(const std::wstring& relative_without_extension)\r
-       {\r
-               boost::filesystem::remove(thumbnails_path_ / (relative_without_extension + L".png"));\r
-               media_info_repo_->remove(relative_without_extension);\r
-       }\r
-\r
        bool needs_to_be_generated(const boost::filesystem::wpath& file)\r
        {\r
                using namespace boost::filesystem;\r
@@ -296,12 +292,12 @@ public:
 \r
                        std::map<int, safe_ptr<basic_frame>> frames;\r
                        auto raw_frame = basic_frame::empty();\r
-                       media_info additional_info;\r
 \r
                        try\r
                        {\r
-                               raw_frame = producer->create_thumbnail_frame(additional_info);\r
-                               media_info_repo_->store(media_file, additional_info);\r
+                               raw_frame = producer->create_thumbnail_frame();\r
+                               media_info_repo_->remove(file.file_string());\r
+                               media_info_repo_->get(file.file_string());\r
                        }\r
                        catch (const boost::thread_interrupted&)\r
                        {\r
index 68f51c3c94f202d9a8098341442a843a59f61bd7..ef915b9339286dd42c002349fe515b0154774118 100644 (file)
@@ -23,6 +23,7 @@
 \r
 #include "consumer/ffmpeg_consumer.h"\r
 #include "producer/ffmpeg_producer.h"\r
+#include "producer/util/util.h"\r
 \r
 #include <common/log/log.h>\r
 #include <common/exception/win32_exception.h>\r
@@ -30,6 +31,8 @@
 #include <core/parameters/parameters.h>\r
 #include <core/consumer/frame_consumer.h>\r
 #include <core/producer/frame_producer.h>\r
+#include <core/producer/media_info/media_info.h>\r
+#include <core/producer/media_info/media_info_repository.h>\r
 \r
 #include <tbb/recursive_mutex.h>\r
 \r
@@ -239,7 +242,7 @@ void log_for_thread(void* ptr, int level, const char* fmt, va_list vl)
 //}\r
 //#pragma warning (pop)\r
 \r
-void init()\r
+void init(const safe_ptr<core::media_info_repository>& media_info_repo)\r
 {\r
        av_lockmgr_register(ffmpeg_lock_callback);\r
        av_log_set_callback(log_for_thread);\r
@@ -255,6 +258,14 @@ void init()
        core::register_consumer_factory([](const core::parameters& params){return ffmpeg::create_consumer(params);});\r
        core::register_producer_factory(create_producer);\r
        core::register_thumbnail_producer_factory(create_thumbnail_producer);\r
+\r
+       media_info_repo->register_extractor(\r
+                       [](const std::wstring& file, core::media_info& info) -> bool\r
+                       {\r
+                               auto disable_logging = temporary_disable_logging_for_thread(true);\r
+\r
+                               return is_valid_file(file) && try_get_duration(file, info.duration, info.time_base);\r
+                       });\r
 }\r
 \r
 void uninit()\r
index 130683f3ee306683fe3935e2244de0670c7ed308..4162b489e8e814dfacc7f74afed7d556491a7c29 100644 (file)
 #include <string>\r
 #include <memory>\r
 \r
-namespace caspar { namespace ffmpeg {\r
+namespace caspar { \r
+namespace core {\r
 \r
-void init();\r
+struct media_info_repository;\r
+\r
+}\r
+\r
+namespace ffmpeg {\r
+\r
+void init(const safe_ptr<core::media_info_repository>& media_info_repo);\r
 void uninit();\r
 void disable_logging_for_thread();\r
 std::shared_ptr<void> temporary_disable_logging_for_thread(bool disable);\r
index 6e24d80345cab997421d6f081ddf699a370a8fe5..d571307dbd5ccf8c264fc38432431e4828aa63e9 100644 (file)
@@ -44,7 +44,6 @@
 #include <core/producer/frame/frame_factory.h>\r
 #include <core/producer/frame/basic_frame.h>\r
 #include <core/producer/frame/frame_transform.h>\r
-#include <core/producer/media_info/media_info.h>\r
 \r
 #include <boost/algorithm/string.hpp>\r
 #include <boost/assign.hpp>\r
@@ -302,15 +301,13 @@ public:
                return core::basic_frame::empty();\r
        }\r
 \r
-       virtual safe_ptr<core::basic_frame> create_thumbnail_frame(core::media_info& additional_info) override\r
+       virtual safe_ptr<core::basic_frame> create_thumbnail_frame() override\r
        {\r
                auto disable_logging = temporary_disable_logging_for_thread(thumbnail_mode_);\r
 \r
                auto total_frames = nb_frames();\r
                auto grid = env::properties().get(L"configuration.thumbnails.video-grid", 2);\r
 \r
-               try_get_duration(*input_.context(), additional_info.duration, additional_info.time_base);\r
-\r
                if (grid < 1)\r
                {\r
                        CASPAR_LOG(error) << L"configuration/thumbnails/video-grid cannot be less than 1";\r
index 4ebdba65572c3dd584208c7af336dfbe0addb49e..d9a33e7719d1299ba5fcd6e50f80fd40c426c136 100644 (file)
@@ -473,36 +473,32 @@ bool is_valid_file(const std::wstring filename)
        return is_valid_file(filename, invalid_exts);\r
 }\r
 \r
-bool try_get_duration(AVFormatContext& context, std::int64_t& duration, boost::rational<std::int64_t>& time_base)\r
-{              \r
-       const auto fps = read_fps(context, 1.0);\r
-       const auto rational_fps = boost::rational<std::int64_t>(static_cast<int>(fps * AV_TIME_BASE), AV_TIME_BASE);\r
-       \r
-       duration = boost::rational_cast<std::int64_t>(context.duration * rational_fps / AV_TIME_BASE);\r
-\r
-       if (rational_fps == 0)\r
-               return false;\r
-\r
-       time_base = 1/rational_fps;\r
-\r
-       return true;\r
-}\r
-\r
 bool try_get_duration(const std::wstring filename, std::int64_t& duration, boost::rational<std::int64_t>& time_base)\r
-{              \r
+{\r
        AVFormatContext* weak_context = nullptr;\r
        if(avformat_open_input(&weak_context, narrow(filename).c_str(), nullptr, nullptr) < 0)\r
                return false;\r
 \r
        std::shared_ptr<AVFormatContext> context(weak_context, av_close_input_file);\r
-\r
+       \r
        context->probesize = context->probesize / 10;\r
        context->max_analyze_duration = context->probesize / 10;\r
 \r
        if(avformat_find_stream_info(context.get(), nullptr) < 0)\r
                return false;\r
+\r
+       const auto fps = read_fps(*context, 1.0);\r
+               \r
+       const auto rational_fps = boost::rational<std::int64_t>(static_cast<int>(fps * AV_TIME_BASE), AV_TIME_BASE);\r
        \r
-       return try_get_duration(*context, duration, time_base);\r
+       duration = boost::rational_cast<std::int64_t>(context->duration * rational_fps / AV_TIME_BASE);\r
+\r
+       if (rational_fps == 0)\r
+               return false;\r
+\r
+       time_base = 1/rational_fps;\r
+\r
+       return true;\r
 }\r
 \r
 std::wstring probe_stem(const std::wstring stem, const std::vector<std::wstring>& invalid_exts)\r
index 27b98d792284e07924d884b060c61056fef1020f..2e0f4c0384ba49e38bcdd700496051af1083e813 100644 (file)
@@ -82,7 +82,6 @@ std::wstring probe_stem(const std::wstring stem, const std::vector<std::wstring>
 std::wstring probe_stem(const std::wstring stem);\r
 bool is_valid_file(const std::wstring filename, const std::vector<std::wstring>& invalid_exts);\r
 bool is_valid_file(const std::wstring filename);\r
-bool try_get_duration(AVFormatContext& context, std::int64_t& duration, boost::rational<std::int64_t>& time_base);\r
 bool try_get_duration(const std::wstring filename, std::int64_t& duration, boost::rational<std::int64_t>& time_base);\r
 \r
 core::channel_layout get_audio_channel_layout(const AVCodecContext& context, const std::wstring& custom_channel_order);\r
index 2ccb765b0d3f2cc2af1bc4166ee2bc29942f8717..a7ac767628ef5bfddb15e9cbb27bd5c324996be6 100644 (file)
@@ -29,7 +29,6 @@
 #include <core/monitor/monitor.h>\r
 #include <core/producer/frame/basic_frame.h>\r
 #include <core/producer/frame/frame_factory.h>\r
-#include <core/producer/media_info/media_info.h>\r
 #include <core/mixer/write_frame.h>\r
 \r
 #include <common/env.h>\r
@@ -97,7 +96,7 @@ struct image_producer : public core::frame_producer
                return frame_;\r
        }\r
 \r
-       virtual safe_ptr<core::basic_frame> create_thumbnail_frame(core::media_info& additional_info) override\r
+       virtual safe_ptr<core::basic_frame> create_thumbnail_frame() override\r
        {\r
                return frame_;\r
        }\r
index ce95138bb6356399a854f6f889814b6d45d90099..31ce13d49cb3b97a4eb6f2c3cf970b8f4730916a 100644 (file)
@@ -240,8 +240,7 @@ std::wstring MediaInfo(const boost::filesystem::wpath& path, const std::shared_p
                        auto str = relativePath.replace_extension(TEXT("")).external_file_string();\r
                        if(str[0] == '\\' || str[0] == '/')\r
                                str = std::wstring(str.begin() + 1, str.end());\r
-                       core::media_info media_info;\r
-                       media_info_repo->try_load(boost::replace_all_copy(str, "\\", "/"), media_info);\r
+                       auto media_info = media_info_repo->get(path.file_string());\r
                        \r
                        return std::wstring() \r
                                        + L"\""         + str +\r
index 09c5594fdc8dfb972569e4d3f66ebc5133e851df..0310a3a5f3017e22c7afbadc4bee13491fb37b1d 100644 (file)
@@ -37,8 +37,9 @@
 #include <core/consumer/output.h>\r
 #include <core/consumer/synchronizing/synchronizing_consumer.h>\r
 #include <core/thumbnail_generator.h>\r
+#include <core/producer/media_info/media_info.h>\r
 #include <core/producer/media_info/media_info_repository.h>\r
-#include <core/producer/media_info/file_based_media_info_repository.h>\r
+#include <core/producer/media_info/in_memory_media_info_repository.h>\r
 \r
 #include <modules/bluefish/bluefish.h>\r
 #include <modules/decklink/decklink.h>\r
 \r
 #include <boost/algorithm/string.hpp>\r
 #include <boost/lexical_cast.hpp>\r
+#include <boost/filesystem.hpp>\r
 #include <boost/foreach.hpp>\r
 #include <boost/property_tree/ptree.hpp>\r
 #include <boost/property_tree/xml_parser.hpp>\r
 #include <boost/asio.hpp>\r
 \r
+#include <tbb/atomic.h>\r
+\r
 namespace caspar {\r
 \r
 using namespace core;\r
@@ -113,6 +117,8 @@ struct server::implementation : boost::noncopyable
        std::vector<std::shared_ptr<void>>                      predefined_osc_subscriptions_;\r
        std::vector<safe_ptr<video_channel>>            channels_;\r
        safe_ptr<media_info_repository>                         media_info_repo_;\r
+       boost::thread                                                           initial_media_info_thread_;\r
+       tbb::atomic<bool>                                                       running_;\r
        std::shared_ptr<thumbnail_generator>            thumbnail_generator_;\r
 \r
        implementation(boost::promise<bool>& shutdown_server_now)\r
@@ -120,12 +126,12 @@ struct server::implementation : boost::noncopyable
                , shutdown_server_now_(shutdown_server_now)\r
                , ogl_(ogl_device::create())\r
                , osc_client_(io_service_)\r
-               , media_info_repo_(create_file_based_media_info_repository(\r
-                               env::thumbnails_folder() + L"media_info.csv"))\r
+               , media_info_repo_(create_in_memory_media_info_repository())\r
        {\r
+               running_ = true;\r
                setup_audio(env::properties());\r
 \r
-               ffmpeg::init();\r
+               ffmpeg::init(media_info_repo_);\r
                CASPAR_LOG(info) << L"Initialized ffmpeg module.";\r
                                                          \r
                bluefish::init();         \r
@@ -159,10 +165,15 @@ struct server::implementation : boost::noncopyable
 \r
                setup_osc(env::properties());\r
                CASPAR_LOG(info) << L"Initialized osc.";\r
+\r
+               start_initial_media_info_scan();\r
+               CASPAR_LOG(info) << L"Started initial media information retrieval.";\r
        }\r
 \r
        ~implementation()\r
        {\r
+               running_ = false;\r
+               initial_media_info_thread_.join();\r
                thumbnail_generator_.reset();\r
                primary_amcp_server_.reset();\r
                async_servers_.clear();\r
@@ -381,6 +392,25 @@ struct server::implementation : boost::noncopyable
                \r
                BOOST_THROW_EXCEPTION(caspar_exception() << arg_name_info("name") << arg_value_info(narrow(name)) << msg_info("Invalid protocol"));\r
        }\r
+\r
+       void start_initial_media_info_scan()\r
+       {\r
+               initial_media_info_thread_ = boost::thread([this]\r
+               {\r
+                       for (boost::filesystem::wrecursive_directory_iterator iter(env::media_folder()), end; iter != end; ++iter)\r
+                       {\r
+                               if (running_)\r
+                                       media_info_repo_->get(iter->path().file_string());\r
+                               else\r
+                               {\r
+                                       CASPAR_LOG(info) << L"Initial media information retrieval aborted.";\r
+                                       return;\r
+                               }\r
+                       }\r
+\r
+                       CASPAR_LOG(info) << L"Initial media information retrieval finished.";\r
+               });\r
+       }\r
 };\r
 \r
 server::server(boost::promise<bool>& shutdown_server_now) : impl_(new implementation(shutdown_server_now)){}\r