#include "flash_producer.h"\r
#include "FlashAxContainer.h"\r
\r
+#include "../util/swf.h"\r
+\r
#include <core/video_format.h>\r
\r
#include <core/producer/frame/basic_frame.h>\r
\r
ax_->Tick();\r
if(ax_->InvalidRect())\r
- { \r
+ {\r
fast_memclr(bmp_.data(), width_*height_*4);\r
ax_->DrawControl(bmp_);\r
\r
graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.9f));\r
graph_->set_text(print());\r
diagnostics::register_graph(graph_);\r
+ \r
+ renderer_.reset(new flash_renderer(graph_, frame_factory_, filename_, width_, height_));\r
+\r
+ while(output_buffer_.size() < buffer_size_)\r
+ output_buffer_.push(core::basic_frame::empty());\r
}\r
\r
~flash_producer()\r
next();\r
else\r
graph_->set_tag("late-frame");\r
- \r
+\r
return frame;\r
}\r
\r
make_safe<flash_producer>(frame_factory, filename, template_host.width, template_host.height)));\r
}\r
\r
+safe_ptr<core::frame_producer> create_swf_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params) \r
+{\r
+ auto filename = env::media_folder() + L"\\" + params.at(0) + L".swf";\r
+ \r
+ if(!boost::filesystem::exists(filename))\r
+ return core::frame_producer::empty();\r
+\r
+ swf_t::header_t header(filename);\r
+\r
+ return create_producer_destroy_proxy(\r
+ create_producer_print_proxy(\r
+ make_safe<flash_producer>(frame_factory, filename, header.frame_width, header.frame_height)));\r
+}\r
+\r
std::wstring find_template(const std::wstring& template_name)\r
{\r
if(boost::filesystem::exists(template_name + L".ft")) \r
\r
#include "../StdAfx.h"\r
\r
+#include "swf.h"\r
+\r
#include <common/exception/exceptions.h>\r
\r
#include <zlib.h>\r
return std::string(beg_it, end_it+end_str.size());\r
}\r
\r
+int extractDimensions(const unsigned char* _data);\r
+\r
+swf_t::header_t::header_t(const std::wstring& filename)\r
+ : valid(false)\r
+{\r
+ auto stream = std::fstream();\r
+ stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);\r
+ stream.open(filename, std::ios::in | std::ios::binary);\r
+ stream.read(reinterpret_cast<char*>(this), 8);\r
+ \r
+ const std::array<std::uint8_t, 3> s1 = {'F', 'W', 'S'};\r
+ const std::array<std::uint8_t, 3> s2 = {'C', 'W', 'S'};\r
+\r
+ if(this->signature != s1 && this->signature != s2)\r
+ return;\r
+ \r
+ _byteswap_ulong(this->file_length);\r
+ \r
+ std::vector<char> file_data;\r
+ std::copy((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>(), std::back_inserter(file_data));\r
+\r
+ std::array<char, 32> data;\r
+ uLongf file_size = 32;\r
+ auto ret = uncompress(reinterpret_cast<Bytef*>(data.data()), &file_size, reinterpret_cast<const Bytef*>(file_data.data()), static_cast<uLong>(file_data.size()));\r
+ \r
+ if(ret == Z_DATA_ERROR)\r
+ BOOST_THROW_EXCEPTION(io_error());\r
+\r
+ // http://thenobody.blog.matfyz.sk/p13084-how-to-get-dimensions-of-a-swf-file\r
+\r
+ unsigned char nbits = reinterpret_cast<unsigned char*>(data.data())[0];\r
+\r
+ unsigned int size = nbits >> 3; // remove overlaping 3 bits\r
+\r
+ unsigned long dims[4] = {};\r
+ unsigned long neg_root = 1 << (size-1); // numbers are signed, i.e. leftmost bit denotes -\r
+\r
+ unsigned int bi_offset = (size % 8) ? (8-(size % 8)) : 0; // offset of bit numbers depending on specified size\r
+ unsigned int by_offset = (size + bi_offset) / 8; // offest of bytes\r
+ unsigned int ioffset; // floating byte offset during iteration\r
+ unsigned long ibuf = (unsigned long) (nbits % 8); // actual result - starts with last 3 bits of first byte\r
+\r
+ for(auto i = 0; i < 4; ++i)\r
+ {\r
+ ioffset = by_offset * i;\r
+\r
+ for(unsigned int j = 0; j < by_offset; ++j)\r
+ {\r
+ ibuf <<= 8;\r
+ ibuf += reinterpret_cast<unsigned char*>(data.data())[1+ioffset+j];\r
+ }\r
+\r
+ dims[i] = (ibuf >> (3 + bi_offset + (i * bi_offset))) / 20; // coordinates in twips, so divide by 20 for pixels\r
+\r
+ if(dims[i] >= neg_root) // if the leftmost bit is 1 number is negative \r
+ dims[i] = (-1) * ( neg_root - (dims[i] - neg_root) ); // convert to negative number \r
+\r
+ int expn = 3 + bi_offset + (i * bi_offset); // bit divider for ...\r
+ ibuf = ibuf % (1 << (expn-1)); // ... buffered number \r
+ }\r
+ \r
+ this->frame_width = dims[1] - dims[0]; // max - mix\r
+ this->frame_height = dims[3] - dims[2]; \r
+\r
+ this->valid = true;\r
+}\r
+\r
+swf_t::swf_t(const std::wstring& filename)\r
+ : header(filename)\r
+{\r
+ auto stream = std::fstream();\r
+ stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);\r
+ stream.open(filename, std::ios::in | std::ios::binary); \r
+ stream.seekg(8, std::fstream::beg);\r
+\r
+ this->data.resize(this->header.file_length - 8);\r
+ \r
+ std::vector<char> file_data;\r
+ std::copy((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>(), std::back_inserter(file_data));\r
+\r
+ uLongf file_size = this->header.file_length;\r
+ auto ret = uncompress(reinterpret_cast<Bytef*>(this->data.data()), &file_size, reinterpret_cast<const Bytef*>(file_data.data()), static_cast<uLong>(file_data.size()));\r
+\r
+ if(ret != Z_OK)\r
+ BOOST_THROW_EXCEPTION(io_error());\r
+}\r
+\r
}}
\ No newline at end of file
\r
#pragma once\r
\r
+#include <cstdint>\r
#include <string>\r
\r
namespace caspar { namespace flash {\r
\r
std::string read_template_meta_info(const std::wstring& filename);\r
\r
+struct swf_t\r
+{\r
+ struct header_t\r
+ {\r
+ header_t(const std::wstring& filename);\r
+\r
+ std::array<std::uint8_t, 3> signature;\r
+ std::uint8_t version;\r
+ std::uint32_t file_length;\r
+ std::uint32_t frame_width;\r
+ std::uint32_t frame_height;\r
+ std::uint16_t frame_rate;\r
+ std::uint16_t frame_count;\r
+\r
+ bool valid;\r
+\r
+ } header;\r
+ \r
+ std::vector<char> data;\r
+ \r
+ swf_t(const std::wstring& filename);\r
+};\r
+\r
}}
\ No newline at end of file