]> git.sesse.net Git - casparcg/commitdiff
manually merged 44a5538 from master
authorniklaspandersson <niklas.p.andersson@svt.se>
Mon, 2 Sep 2013 07:49:59 +0000 (09:49 +0200)
committerniklaspandersson <niklas.p.andersson@svt.se>
Mon, 2 Sep 2013 07:49:59 +0000 (09:49 +0200)
common/base64.cpp [new file with mode: 0644]
common/base64.h [new file with mode: 0644]
common/common.vcxproj
common/common.vcxproj.filters
core/producer/frame_producer.cpp
modules/image/producer/image_producer.cpp
protocol/amcp/AMCPCommandsImpl.cpp
protocol/util/strategy_adapters.h

diff --git a/common/base64.cpp b/common/base64.cpp
new file mode 100644 (file)
index 0000000..ddae471
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@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 "base64.h"
+
+#include <vector>
+#include <algorithm>
+
+#include <boost/archive/iterators/insert_linebreaks.hpp>
+#include <boost/archive/iterators/base64_from_binary.hpp>
+#include <boost/archive/iterators/binary_from_base64.hpp>
+#include <boost/archive/iterators/transform_width.hpp>
+#include <boost/archive/iterators/remove_whitespace.hpp>
+#include <boost/range/join.hpp>
+#include <boost/range/adaptor/sliced.hpp>
+
+#include "except.h"
+
+namespace caspar {
+
+std::string to_base64(const char* data, size_t length)
+{
+       using namespace boost::archive::iterators;
+
+       // From http://www.webbiscuit.co.uk/2012/04/02/base64-encoder-and-boost/
+               
+       typedef
+               insert_linebreaks<         // insert line breaks every 76 characters
+                       base64_from_binary<    // convert binary values to base64 characters
+                               transform_width<   // retrieve 6 bit integers from a sequence of 8 bit bytes
+                                       const unsigned char *,
+                                       6,
+                                       8
+                               >
+                       >,
+                       76
+               >
+               base64_iterator; // compose all the above operations in to a new iterator
+       std::vector<char> bytes;
+       bytes.resize(length);
+       std::memcpy(bytes.data(), data, length);
+
+       int padding = 0;
+
+       while (bytes.size() % 3 != 0)
+       {
+               ++padding;
+               bytes.push_back(0x00);
+       }
+
+       std::string result(base64_iterator(bytes.data()), base64_iterator(bytes.data() + length - padding));
+       result.insert(result.end(), padding, '=');
+
+       return std::move(result);
+}
+
+std::vector<unsigned char> from_base64(const std::string& data)
+{
+       int padding = 0;
+       std::string zero_padding;
+
+       // binary_from_base64 does not support padding characters so we have to append base64 0 -> 'A' and then remove it after decoding
+       if (data.length() >= 2)
+       {
+               if (data[data.length() - 1] == '=')
+               {
+                       ++padding;
+                       zero_padding += 'A';
+               }
+
+               if (data[data.length() - 2] == '=')
+               {
+                       ++padding;
+                       zero_padding += 'A';
+               }
+       }
+
+       if (padding > 0)
+       {
+               auto concatenated = boost::join(
+                               data | boost::adaptors::sliced(0, data.length() - padding),
+                               boost::make_iterator_range(zero_padding.cbegin(), zero_padding.cend()));
+
+               // From https://svn.boost.org/trac/boost/ticket/5624
+               typedef boost::archive::iterators::transform_width<
+                               boost::archive::iterators::binary_from_base64<
+                                       boost::archive::iterators::remove_whitespace<decltype(concatenated.begin())>
+                               >,
+                               8,
+                               6
+                       > base64_iterator;
+
+               std::vector<unsigned char> result(base64_iterator(concatenated.begin()), base64_iterator(concatenated.end()));
+
+               result.resize(result.size() - padding);
+
+               return std::move(result);
+       }
+       else
+       {
+               // From https://svn.boost.org/trac/boost/ticket/5624
+               typedef boost::archive::iterators::transform_width<
+                               boost::archive::iterators::binary_from_base64<
+                                       boost::archive::iterators::remove_whitespace<std::string::const_iterator>
+                               >,
+                               8,
+                               6
+                       > base64_iterator;
+               std::vector<unsigned char> result(base64_iterator(data.begin()), base64_iterator(data.end()));
+
+               return std::move(result);
+       }
+}
+
+}
\ No newline at end of file
diff --git a/common/base64.h b/common/base64.h
new file mode 100644 (file)
index 0000000..518774e
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+* Copyright (c) 2011 Sveriges Television AB <info@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
+*/
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+namespace caspar {
+
+std::string to_base64(const char* data, size_t length);
+std::vector<unsigned char> from_base64(const std::string& data);
+
+}
\ No newline at end of file
index 8be47e5badcfa59f7a5271599804aa1f19b948b0..ddef5762f25ccf1c0d184770624b601f2092fb67 100644 (file)
   <ItemGroup>\r
     <ClInclude Include="array.h" />\r
     <ClInclude Include="assert.h" />\r
+    <ClInclude Include="base64.h" />\r
     <ClInclude Include="blocking_bounded_queue_adapter.h" />\r
     <ClInclude Include="blocking_priority_queue.h" />\r
     <ClInclude Include="compiler\vs\disable_silly_warnings.h" />\r
     <ClInclude Include="utf.h" />\r
   </ItemGroup>\r
   <ItemGroup>\r
+    <ClCompile Include="base64.cpp">\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Use</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|x64'">Use</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Profile|x64'">Use</PrecompiledHeader>\r
+      <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Use</PrecompiledHeader>\r
+    </ClCompile>\r
     <ClCompile Include="compiler\vs\stack_walker.cpp">\r
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>\r
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Develop|x64'">NotUsing</PrecompiledHeader>\r
index 6392e7af01df4e96281c57a68123439948247782..779d388f80a1c549bab80bf8a097b6ed3edc0d89 100644 (file)
@@ -58,6 +58,9 @@
     <ClCompile Include="polling_filesystem_monitor.cpp">\r
       <Filter>source</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="base64.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="compiler\vs\disable_silly_warnings.h">\r
     <ClInclude Include="polling_filesystem_monitor.h">\r
       <Filter>source</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="base64.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index 572dd7a57e57f1832a4d51117be26be56ba19799..e367316498d80c98c9306f68e09cb14cf0a7f989 100644 (file)
@@ -306,22 +306,22 @@ spl::shared_ptr<core::frame_producer> create_thumbnail_producer(const spl::share
   
   try // to find a key file.
   {
-    auto params_copy = params;
-    if (params_copy.size() > 0)
-    {
-      params_copy[0] += L"_A";
-      key_producer = do_create_producer(my_frame_factory, format_desc, params_copy, g_thumbnail_factories, true);
-      if (key_producer == frame_producer::empty())
-      {
-        params_copy[0] += L"LPHA";
-        key_producer = do_create_producer(my_frame_factory, format_desc, params_copy, g_thumbnail_factories, true);
-      }
-    }
+       auto params_copy = params;
+       if (params_copy.size() > 0)
+       {
+         params_copy[0] += L"_A";
+         key_producer = do_create_producer(my_frame_factory, format_desc, params_copy, g_thumbnail_factories, true);
+         if (key_producer == frame_producer::empty())
+         {
+               params_copy[0] += L"LPHA";
+               key_producer = do_create_producer(my_frame_factory, format_desc, params_copy, g_thumbnail_factories, true);
+         }
+       }
   }
   catch(...){}
 
   if (producer != frame_producer::empty() && key_producer != frame_producer::empty())
-    return create_separated_producer(producer, key_producer);
+       return create_separated_producer(producer, key_producer);
   
   return producer;
 }
index 6b0fd8d2420cc61fddf490f13ef2d8c64c6aa93b..9fb259af3bed2e34ad993c73aed17e3f017807f7 100644 (file)
@@ -36,6 +36,7 @@
 #include <common/env.h>
 #include <common/log.h>
 #include <common/array.h>
+#include <common/base64.h>
 
 #include <boost/assign.hpp>
 #include <boost/filesystem.hpp>
@@ -74,27 +75,48 @@ std::pair<core::draw_frame, core::constraints> load_image(
 struct image_producer : public core::frame_producer_base
 {      
        monitor::basic_subject  event_subject_;
-       const std::wstring              filename_;
+       const std::wstring              description_;
+       const spl::shared_ptr<core::frame_factory> frame_factory_;
        core::draw_frame                frame_;
        core::constraints               constraints_;
        
-       explicit image_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const std::wstring& filename) 
-               : filename_(filename)
+       image_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const std::wstring& description) 
+               : description_(description)
+               , frame_factory_(frame_factory)
                , frame_(core::draw_frame::empty())     
        {
-               auto frame = load_image(frame_factory, filename);
+               load(load_image(description_));
 
-               frame_ = frame.first;
-               constraints_ = frame.second;
+               CASPAR_LOG(info) << print() << L" Initialized";
+       }
+
+       image_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const void* png_data, size_t size) 
+               : description_(L"png from memory")
+               , frame_factory_(frame_factory)
+               , frame_(core::draw_frame::empty())     
+       {
+               load(load_png_from_memory(png_data, size));
 
                CASPAR_LOG(info) << print() << L" Initialized";
        }
+
+       void load(const std::shared_ptr<FIBITMAP>& bitmap)
+       {
+               FreeImage_FlipVertical(bitmap.get());
+               core::pixel_format_desc desc;
+               desc.format = core::pixel_format::bgra;
+               desc.planes.push_back(core::pixel_format_desc::plane(FreeImage_GetWidth(bitmap.get()), FreeImage_GetHeight(bitmap.get()), 4));
+               auto frame = frame_factory_->create_frame(this, desc);
+               std::copy_n(FreeImage_GetBits(bitmap.get()), frame.image_data().size(), frame.image_data().begin());
+               frame_ = core::draw_frame(std::move(frame));
+       }
        
        // frame_producer
 
        core::draw_frame receive_impl() override
        {
-               event_subject_ << monitor::event("file/path") % filename_;
+               event_subject_ << monitor::event("file/path") % description_;
 
                return frame_;
        }
@@ -111,7 +133,7 @@ struct image_producer : public core::frame_producer_base
                        
        std::wstring print() const override
        {
-               return L"image_producer[" + filename_ + L"]";
+               return L"image_producer[" + description_ + L"]";
        }
 
        std::wstring name() const override
@@ -123,7 +145,7 @@ struct image_producer : public core::frame_producer_base
        {
                boost::property_tree::wptree info;
                info.add(L"type", L"image");
-               info.add(L"filename", filename_);
+               info.add(L"location", description_);
                return info;
        }
 
@@ -205,6 +227,15 @@ spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core
 
                return core::create_const_producer(std::move(frames), width, height);
        }
+       else if(boost::iequals(params[0], L"[PNG_BASE64]"))
+       {
+               if (params.size() < 2)
+                       return core::frame_producer::empty();
+
+               auto png_data = from_base64(std::string(params[1].begin(), params[1].end()));
+
+               return spl::make_shared<image_producer>(frame_factory, png_data.data(), png_data.size());
+       }
 
        std::wstring filename = env::media_folder() + params[0];
 
index 4fcf2efeb8be92a2b5881ff99e3250b344b0c029..a0a3e5faccedbdc7bbbb30aae8c0f21e66566794 100644 (file)
@@ -35,6 +35,7 @@
 #include <common/diagnostics/graph.h>
 #include <common/os/windows/current_version.h>
 #include <common/os/windows/system_info.h>
+#include <common/base64.h>
 
 #include <core/producer/frame_producer.h>
 #include <core/video_format.h>
@@ -118,36 +119,12 @@ std::wstring read_file_base64(const boost::filesystem::wpath& file)
        if (!filestream)
                return L"";
 
-       // From http://www.webbiscuit.co.uk/2012/04/02/base64-encoder-and-boost/
-
-       typedef
-               insert_linebreaks<         // insert line breaks every 76 characters
-               base64_from_binary<    // convert binary values to base64 characters
-               transform_width<   // retrieve 6 bit integers from a sequence of 8 bit bytes
-               const unsigned char *,
-               6,
-               8
-               >
-               >,
-               76
-               >
-               base64_iterator; // compose all the above operations in to a new iterator
        auto length = boost::filesystem::file_size(file);
        std::vector<char> bytes;
        bytes.resize(length);
        filestream.read(bytes.data(), length);
 
-       int padding = 0;
-
-       while (bytes.size() % 3 != 0)
-       {
-               ++padding;
-               bytes.push_back(0x00);
-       }
-
-       std::string result(base64_iterator(bytes.data()), base64_iterator(bytes.data() + length - padding));
-       result.insert(result.end(), padding, '=');
-
+       std::string result(to_base64(bytes.data(), length));
        return std::wstring(result.begin(), result.end());
 }
 
index 8e6afd9365af02f1a7fcfc83353e11f166f3f23d..c5f4ccf47de9160384dacf624ef09155033fe019 100644 (file)
@@ -76,16 +76,15 @@ public:
        {\r
                input_ += data;\r
 \r
-               std::vector<std::basic_string<CharT>> split;\r
-               boost::iter_split(split, input_, boost::algorithm::first_finder(delimiter_));   //TODO: check if this splits on all instances of delimiter_ in the input_\r
+               //boost::iter_split(split, input_, boost::algorithm::first_finder(delimiter_)) was painfully slow in debug-build\r
 \r
-               input_ = std::move(split.back());\r
-               split.pop_back();\r
-\r
-               BOOST_FOREACH(auto cmd, split)\r
+               auto delim_pos = input_.find_first_of(delimiter_);\r
+               while(delim_pos != std::string::npos)\r
                {\r
-                       // TODO: perhaps it would be better to not append the delimiter.\r
-                       strategy_->parse(cmd);\r
+                       strategy_->parse(input_.substr(0, delim_pos));\r
+\r
+                       input_ = std::move(input_.substr(delim_pos+delimiter_.size()));\r
+                       delim_pos = input_.find_first_of(delimiter_);\r
                }\r
        }\r
 };\r