]> git.sesse.net Git - casparcg/commitdiff
Manually merged 678223b9ae0cc2299f2251c9a3029ed6cf8e441e from master
authorHelge Norberg <helge.norberg@svt.se>
Wed, 10 Apr 2013 08:26:24 +0000 (10:26 +0200)
committerHelge Norberg <helge.norberg@svt.se>
Wed, 10 Apr 2013 08:26:24 +0000 (10:26 +0200)
modules/flash/flash.cpp
modules/flash/producer/cg_proxy.cpp
modules/flash/producer/cg_proxy.h
modules/flash/producer/flash_producer.cpp
modules/flash/producer/flash_producer.h
modules/flash/util/swf.cpp
modules/flash/util/swf.h

index b755a6a77e27bdf435274eb96f769e66d415b4e1..e899f9edc210853f80cb6f08a91ec2267a77b320 100644 (file)
@@ -44,7 +44,7 @@ std::wstring cg_version()
 std::wstring version()
 {              
        std::wstring version = L"Not found";
-#ifdef WIN32
+#ifdef WIN32 
        HKEY   hkey;
  
        DWORD dwType, dwSize;
index 77f81d849d902bbf079d9d135b48d665038bb991..151308921d25f9413050babc74e0205aa7737a3d 100644 (file)
@@ -186,12 +186,6 @@ spl::shared_ptr<core::frame_producer> create_ct_producer(const spl::shared_ptr<c
                frame_factory, format_desc, params, env::media_folder() + L"\\" + params[0] + L".ct");
 }
 
-spl::shared_ptr<core::frame_producer> create_swf_producer(const spl::shared_ptr<core::frame_factory> frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params) 
-{
-       return create_cg_producer_and_autoplay_file(
-               frame_factory, format_desc, params, env::media_folder() + L"\\" + params[0] + L".swf");
-}
-
 cg_proxy::cg_proxy(const spl::shared_ptr<core::frame_producer>& frame_producer) : impl_(new impl(frame_producer)){}
 cg_proxy::cg_proxy(cg_proxy&& other) : impl_(std::move(other.impl_)){}
 void cg_proxy::add(int layer, const std::wstring& template_name,  bool play_on_load, const std::wstring& startFromLabel, const std::wstring& data){impl_->add(layer, template_name, play_on_load, startFromLabel, data);}
index 0448a20b1e1d541e396db402e8e98e05a5d192df..bf9ef35ca437161d87ca54d4ddba26d9bc245be2 100644 (file)
@@ -59,6 +59,5 @@ private:
 cg_proxy create_cg_proxy(const spl::shared_ptr<core::video_channel>& video_channel, int layer_index = cg_proxy::DEFAULT_LAYER);
 
 spl::shared_ptr<core::frame_producer> create_ct_producer(const spl::shared_ptr<core::frame_factory> frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
-spl::shared_ptr<core::frame_producer> create_swf_producer(const spl::shared_ptr<core::frame_factory> frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
 
 }}
index 975d7006401ecfa77db43a542457a4649a66663d..2ccfcdd00e483ab635482663ca8f227e0e1187a5 100644 (file)
@@ -29,6 +29,8 @@
 #include "flash_producer.h"
 #include "FlashAxContainer.h"
 
+#include "../util/swf.h"
+
 #include <core/video_format.h>
 
 #include <core/frame/frame.h>
@@ -511,6 +513,19 @@ spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core
        return create_destroy_proxy(spl::make_shared<flash_producer>(frame_factory, format_desc, filename, template_host.width, template_host.height));
 }
 
+spl::shared_ptr<core::frame_producer> create_swf_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params)
+{
+       auto filename = env::media_folder() + L"\\" + params.at(0) + L".swf";
+
+       if (!boost::filesystem::exists(filename))
+               return core::frame_producer::empty();
+
+       swf_t::header_t header(filename);
+
+       return create_destroy_proxy(
+               spl::make_shared<flash_producer>(frame_factory, format_desc, filename, header.frame_width, header.frame_height));
+}
+
 std::wstring find_template(const std::wstring& template_name)
 {
        if(boost::filesystem::exists(template_name + L".ft")) 
index 650909b640b36f5b66d68e16a4f31f5eb1572ab3..eb0bbc3419574263da702f28b029f01e61cfb87c 100644 (file)
@@ -31,6 +31,7 @@
 namespace caspar { namespace flash {
 
 spl::shared_ptr<core::frame_producer> create_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
+spl::shared_ptr<core::frame_producer> create_swf_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, const std::vector<std::wstring>& params);
 
 std::wstring find_template(const std::wstring& templateName);
 
index 6a52bbbf49afb19b273ff41cbafbbdb2cc695ff0..54bed2067dab8c79fb76831b54569a366f91adf7 100644 (file)
@@ -21,6 +21,8 @@
 
 #include "../StdAfx.h"
 
+#include "swf.h"
+
 #include <common/except.h>
 
 #include <zlib.h> // Compiled into FreeImage
@@ -66,7 +68,7 @@ std::string read_template_meta_info(const std::wstring& filename)
        data.reserve(static_cast<size_t>(file.tellg()));
        file.seekg(0, std::ios::beg);
 
-       if(strcmp(head, "CWS") == 0)
+       if (strcmp(head, "CWS") == 0)
        {
                file.seekg(8, std::ios::beg);
                std::copy((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>(), std::back_inserter(data));
@@ -86,10 +88,95 @@ std::string read_template_meta_info(const std::wstring& filename)
        auto beg_it = std::find_end(data.begin(), data.end(), beg_str.begin(), beg_str.end());
        auto end_it = std::find_end(beg_it, data.end(), end_str.begin(), end_str.end());
        
-       if(beg_it == data.end() || end_it == data.end())
+       if (beg_it == data.end() || end_it == data.end())
                CASPAR_THROW_EXCEPTION(file_read_error());
                        
        return std::string(beg_it, end_it+end_str.size());
 }
 
-}}
\ No newline at end of file
+swf_t::header_t::header_t(const std::wstring& filename)
+       : valid(false)
+{
+       auto stream = std::fstream();
+       stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+       stream.open(filename, std::ios::in | std::ios::binary);
+       stream.read(reinterpret_cast<char*>(this), 8);
+
+       const std::array<std::uint8_t, 3> s1 = {'F', 'W', 'S'};
+       const std::array<std::uint8_t, 3> s2 = {'C', 'W', 'S'};
+
+       if (this->signature != s1 && this->signature != s2)
+               return;
+
+       _byteswap_ulong(this->file_length);
+
+       std::vector<char> file_data;
+       std::copy((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>(), std::back_inserter(file_data));
+
+       std::array<char, 32> data;
+       uLongf file_size = 32;
+       auto ret = uncompress(reinterpret_cast<Bytef*>(data.data()), &file_size, reinterpret_cast<const Bytef*>(file_data.data()), static_cast<uLong>(file_data.size()));
+
+       if (ret == Z_DATA_ERROR)
+               BOOST_THROW_EXCEPTION(io_error());
+       
+       // http://thenobody.blog.matfyz.sk/p13084-how-to-get-dimensions-of-a-swf-file
+
+       unsigned char nbits = reinterpret_cast<unsigned char*>(data.data())[0];
+
+       unsigned int size = nbits >> 3;                    // remove overlaping 3 bits
+
+       unsigned long dims[4] = {};
+       unsigned long neg_root = 1 << (size-1);                // numbers are signed, i.e. leftmost bit denotes -
+
+       unsigned int bi_offset = (size % 8) ? (8-(size % 8)) : 0;      // offset of bit numbers depending on specified size
+       unsigned int by_offset = (size + bi_offset) / 8;          // offest of bytes
+       unsigned int ioffset;                        // floating byte offset during iteration
+       unsigned long ibuf = (unsigned long) (nbits % 8);          // actual result - starts with last 3 bits of first byte
+       
+       for (auto i = 0; i < 4; ++i)
+       {
+               ioffset = by_offset * i;
+               
+               for (unsigned int j = 0; j < by_offset; ++j)
+               {
+                       ibuf <<= 8;
+                       ibuf +=  reinterpret_cast<unsigned char*>(data.data())[1+ioffset+j];
+               }
+
+               dims[i] = (ibuf >> (3 + bi_offset + (i * bi_offset))) / 20;    // coordinates in twips, so divide by 20 for pixels
+
+               if(dims[i] >= neg_root)                      // if the leftmost bit is 1 number is negative
+                       dims[i] = (-1) * ( neg_root - (dims[i] - neg_root) );    // convert to negative number
+
+               int expn = 3 + bi_offset + (i * bi_offset);            // bit divider for ...
+               ibuf = ibuf % (1 << (expn-1));                  // ... buffered number
+       }
+
+       this->frame_width  = dims[1] - dims[0];                // max - mix
+       this->frame_height = dims[3] - dims[2];
+
+       this->valid = true;
+}
+
+swf_t::swf_t(const std::wstring& filename)
+       : header(filename)
+{
+       auto stream = std::fstream();
+       stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
+       stream.open(filename, std::ios::in | std::ios::binary);
+       stream.seekg(8, std::fstream::beg);
+
+       this->data.resize(this->header.file_length - 8);
+
+       std::vector<char> file_data;
+       std::copy((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>(), std::back_inserter(file_data));
+
+       uLongf file_size = this->header.file_length;
+       auto ret = uncompress(reinterpret_cast<Bytef*>(this->data.data()), &file_size, reinterpret_cast<const Bytef*>(file_data.data()), static_cast<uLong>(file_data.size()));
+
+       if (ret != Z_OK)
+               BOOST_THROW_EXCEPTION(io_error());
+}
+
+}}
index f15293950793cc7cd67c2dc9928de11c3367711f..c22d2da7e2ad914691a272b851b04de4ac026a41 100644 (file)
 
 #pragma once
 
+#include <cstdint>
 #include <string>
+#include <array>
 
 namespace caspar { namespace flash {
 
 std::string read_template_meta_info(const std::wstring& filename);
 
+struct swf_t
+{
+       struct header_t
+       {
+               header_t(const std::wstring& filename);
+
+               std::array<std::uint8_t, 3>     signature;
+               std::uint8_t                            version;
+               std::uint32_t                           file_length;
+               std::uint32_t                           frame_width;
+               std::uint32_t                           frame_height;
+               std::uint16_t                           frame_rate;
+               std::uint16_t                           frame_count;
+
+               bool                                            valid;
+
+       } header;
+
+       std::vector<char>                               data;
+
+       swf_t(const std::wstring& filename);
+};
+
 }}
\ No newline at end of file