-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#include "../stdafx.h"\r
-\r
-#include "draw_frame.h"\r
-\r
-#include "data_frame.h"\r
-\r
-#include "frame_transform.h"\r
-\r
-#include <boost/foreach.hpp>\r
-\r
-namespace caspar { namespace core {\r
- \r
-struct draw_frame::impl\r
-{ \r
- int tag_;\r
- std::vector<draw_frame> frames_;\r
- std::shared_ptr<spl::unique_ptr<const data_frame>> data_frame_;\r
-\r
- core::frame_transform frame_transform_; \r
-public: \r
- enum tags\r
- {\r
- frame_tag = 0,\r
- empty_tag,\r
- eof_tag,\r
- late_tag\r
- };\r
-\r
- impl(int tag = impl::empty_tag)\r
- : tag_(tag)\r
- {\r
- }\r
-\r
- impl(spl::unique_ptr<const data_frame>&& frame) \r
- : tag_(frame_tag)\r
- , data_frame_(new spl::unique_ptr<const data_frame>(std::move(frame)))\r
- {\r
- }\r
- \r
- impl(std::vector<draw_frame> frames)\r
- : tag_(frame_tag)\r
- , frames_(std::move(frames))\r
- {\r
- }\r
- \r
- void accept(frame_visitor& visitor) const\r
- {\r
- visitor.push(frame_transform_);\r
- if(data_frame_)\r
- {\r
- visitor.visit(**data_frame_);\r
- }\r
- else\r
- {\r
- BOOST_FOREACH(auto frame, frames_)\r
- frame.accept(visitor);\r
- }\r
- visitor.pop();\r
- } \r
-\r
- bool operator==(const impl& other)\r
- {\r
- return tag_ == other.tag_ && \r
- frames_ == other.frames_ && \r
- data_frame_ == other.data_frame_;\r
- }\r
-};\r
- \r
-draw_frame::draw_frame() : impl_(new impl()){}\r
-draw_frame::draw_frame(int tag) : impl_(new impl(std::move(tag))){}\r
-draw_frame::draw_frame(const draw_frame& other) : impl_(new impl(*other.impl_)){}\r
-draw_frame::draw_frame(draw_frame&& other) : impl_(std::move(other.impl_)){}\r
-draw_frame::draw_frame(spl::unique_ptr<const data_frame>&& frame) : impl_(new impl(std::move(frame))){}\r
-draw_frame::draw_frame(std::vector<draw_frame> frames) : impl_(new impl(frames)){}\r
-draw_frame::~draw_frame(){}\r
-draw_frame& draw_frame::operator=(draw_frame other)\r
-{\r
- other.swap(*this);\r
- return *this;\r
-}\r
-void draw_frame::swap(draw_frame& other){impl_.swap(other.impl_);}\r
-\r
-const core::frame_transform& draw_frame::transform() const { return impl_->frame_transform_;}\r
-core::frame_transform& draw_frame::transform() { return impl_->frame_transform_;}\r
-void draw_frame::accept(frame_visitor& visitor) const{impl_->accept(visitor);}\r
-bool draw_frame::operator==(const draw_frame& other)const{return *impl_ == *other.impl_;}\r
-bool draw_frame::operator!=(const draw_frame& other)const{return !(*this == other);}\r
-\r
-draw_frame draw_frame::interlace(draw_frame frame1, draw_frame frame2, core::field_mode mode)\r
-{ \r
- if(frame1 == draw_frame::eof() || frame2 == draw_frame::eof())\r
- return draw_frame::eof();\r
-\r
- if(frame1 == draw_frame::empty() && frame2 == draw_frame::empty())\r
- return draw_frame::empty();\r
- \r
- if(frame1 == frame2 || mode == field_mode::progressive)\r
- return frame2;\r
-\r
- if(mode == field_mode::upper)\r
- {\r
- frame1.transform().image_transform.field_mode = field_mode::upper; \r
- frame2.transform().image_transform.field_mode = field_mode::lower; \r
- } \r
- else \r
- { \r
- frame1.transform().image_transform.field_mode = field_mode::lower; \r
- frame2.transform().image_transform.field_mode = field_mode::upper; \r
- }\r
-\r
- std::vector<draw_frame> frames;\r
- frames.push_back(std::move(frame1));\r
- frames.push_back(std::move(frame2));\r
- return draw_frame(std::move(frames));\r
-}\r
-\r
-draw_frame draw_frame::over(draw_frame frame1, draw_frame frame2)\r
-{ \r
- if(frame1 == draw_frame::eof() || frame2 == draw_frame::eof())\r
- return draw_frame::eof();\r
- \r
- if(frame1 == draw_frame::empty() && frame2 == draw_frame::empty())\r
- return draw_frame::empty();\r
-\r
- std::vector<draw_frame> frames;\r
- frames.push_back(std::move(frame1));\r
- frames.push_back(std::move(frame2));\r
- return draw_frame(std::move(frames));\r
-}\r
-\r
-draw_frame draw_frame::mask(draw_frame fill, draw_frame key)\r
-{ \r
- if(fill == draw_frame::eof() || key == draw_frame::eof())\r
- return draw_frame::eof();\r
-\r
- if(fill == draw_frame::empty() || key == draw_frame::empty())\r
- return draw_frame::empty();\r
-\r
- std::vector<draw_frame> frames;\r
- key.transform().image_transform.is_key = true;\r
- frames.push_back(std::move(key));\r
- frames.push_back(std::move(fill));\r
- return draw_frame(std::move(frames));\r
-}\r
-\r
-draw_frame draw_frame::still(draw_frame frame)\r
-{\r
- frame.transform().image_transform.is_still = true; \r
- frame.transform().audio_transform.volume = 0.0; \r
- return frame;\r
-}\r
-\r
-const draw_frame& draw_frame::eof()\r
-{\r
- static draw_frame frame(impl::eof_tag);\r
- return frame;\r
-}\r
-\r
-const draw_frame& draw_frame::empty()\r
-{\r
- static draw_frame frame(impl::empty_tag);\r
- return frame;\r
-}\r
-\r
-const draw_frame& draw_frame::late()\r
-{\r
- static draw_frame frame(impl::late_tag);\r
- return frame;\r
-}\r
- \r
-\r
-}}
\ No newline at end of file
+/*
+* 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: Robert Nagy, ronag89@gmail.com
+*/
+
+#include "../StdAfx.h"
+
+#include "draw_frame.h"
+#include "frame.h"
+#include "frame_transform.h"
+
+namespace caspar { namespace core {
+
+enum class tags
+{
+ frame_tag = 0,
+ empty_tag,
+ eof_tag,
+ late_tag
+};
+
+struct draw_frame::impl
+{
+ std::shared_ptr<const_frame> frame_;
+ std::vector<draw_frame> frames_;
+ core::frame_transform frame_transform_;
+public:
+
+ impl()
+ {
+ }
+
+ impl(const_frame&& frame)
+ : frame_(new const_frame(std::move(frame)))
+ {
+ }
+
+ impl(mutable_frame&& frame)
+ : frame_(new const_frame(std::move(frame)))
+ {
+ }
+
+ impl(std::vector<draw_frame> frames)
+ : frames_(std::move(frames))
+ {
+ }
+
+ impl(const impl& other)
+ : frames_(other.frames_)
+ , frame_(other.frame_)
+ , frame_transform_(other.frame_transform_)
+ {
+ }
+
+ void accept(frame_visitor& visitor) const
+ {
+ visitor.push(frame_transform_);
+ if(frame_)
+ {
+ visitor.visit(*frame_);
+ }
+ else
+ {
+ for (auto& frame : frames_)
+ frame.accept(visitor);
+ }
+ visitor.pop();
+ }
+
+ bool operator==(const impl& other)
+ {
+ return frames_ == other.frames_ &&
+ frame_ == other.frame_ &&
+ frame_transform_ == other.frame_transform_;
+ }
+
+ int64_t get_and_record_age_millis(const draw_frame& self)
+ {
+ int64_t result = 0;
+
+ for (auto& frame : frames_)
+ {
+ if (frame != self)
+ result = std::max(result, frame.get_and_record_age_millis());
+ }
+
+ if (frame_)
+ result = std::max(result, frame_->get_age_millis());
+
+ return result;
+ }
+};
+
+draw_frame::draw_frame() : impl_(new impl()){}
+draw_frame::draw_frame(const draw_frame& other) : impl_(new impl(*other.impl_)){}
+draw_frame::draw_frame(draw_frame&& other) : impl_(std::move(other.impl_)){}
+draw_frame::draw_frame(const_frame&& frame) : impl_(new impl(std::move(frame))){}
+draw_frame::draw_frame(mutable_frame&& frame) : impl_(new impl(std::move(frame))){}
+draw_frame::draw_frame(std::vector<draw_frame> frames) : impl_(new impl(frames)){}
+draw_frame::~draw_frame(){}
+draw_frame& draw_frame::operator=(draw_frame other)
+{
+ other.swap(*this);
+ return *this;
+}
+void draw_frame::swap(draw_frame& other){impl_.swap(other.impl_);}
+
+const core::frame_transform& draw_frame::transform() const { return impl_->frame_transform_;}
+core::frame_transform& draw_frame::transform() { return impl_->frame_transform_;}
+void draw_frame::accept(frame_visitor& visitor) const{impl_->accept(visitor);}
+int64_t draw_frame::get_and_record_age_millis() { return impl_->get_and_record_age_millis(*this); }
+bool draw_frame::operator==(const draw_frame& other)const{return *impl_ == *other.impl_;}
+bool draw_frame::operator!=(const draw_frame& other)const{return !(*this == other);}
+
+draw_frame draw_frame::interlace(draw_frame frame1, draw_frame frame2, core::field_mode mode)
+{
+ if(frame1 == draw_frame::empty() && frame2 == draw_frame::empty())
+ return draw_frame::empty();
+
+ if(frame1 == frame2 || mode == field_mode::progressive)
+ return frame2;
+
+ if(mode == field_mode::upper)
+ {
+ frame1.transform().image_transform.field_mode = field_mode::upper;
+ frame2.transform().image_transform.field_mode = field_mode::lower;
+ }
+ else
+ {
+ frame1.transform().image_transform.field_mode = field_mode::lower;
+ frame2.transform().image_transform.field_mode = field_mode::upper;
+ }
+
+ std::vector<draw_frame> frames;
+ frames.push_back(std::move(frame1));
+ frames.push_back(std::move(frame2));
+ return draw_frame(std::move(frames));
+}
+
+draw_frame draw_frame::over(draw_frame frame1, draw_frame frame2)
+{
+ if(frame1 == draw_frame::empty() && frame2 == draw_frame::empty())
+ return draw_frame::empty();
+
+ std::vector<draw_frame> frames;
+ frames.push_back(std::move(frame1));
+ frames.push_back(std::move(frame2));
+ return draw_frame(std::move(frames));
+}
+
+draw_frame draw_frame::mask(draw_frame fill, draw_frame key)
+{
+ if(fill == draw_frame::empty() || key == draw_frame::empty())
+ return draw_frame::empty();
+
+ std::vector<draw_frame> frames;
+ key.transform().image_transform.is_key = true;
+ frames.push_back(std::move(key));
+ frames.push_back(std::move(fill));
+ return draw_frame(std::move(frames));
+}
+
+draw_frame draw_frame::push(draw_frame frame)
+{
+ std::vector<draw_frame> frames;
+ frames.push_back(std::move(frame));
+ return draw_frame(std::move(frames));
+}
+
+draw_frame eof_frame(const_frame(0));
+draw_frame empty_frame(const_frame(0));
+draw_frame late_frame(const_frame(0));
+
+draw_frame draw_frame::still(draw_frame frame)
+{
+ frame.transform().image_transform.is_still = true;
+ frame.transform().audio_transform.is_still = true;
+ return frame;
+}
+
+const draw_frame& draw_frame::empty()
+{
+ return empty_frame;
+}
+
+const draw_frame& draw_frame::late()
+{
+ return late_frame;
+}
+
+
+}}