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);}
#include "flash_producer.h"
#include "FlashAxContainer.h"
+#include "../util/swf.h"
+
#include <core/video_format.h>
#include <core/frame/frame.h>
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"))
#include "../StdAfx.h"
+#include "swf.h"
+
#include <common/except.h>
#include <zlib.h> // Compiled into FreeImage
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));
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());
+}
+
+}}