#pragma warning (pop)\r
#endif\r
\r
-namespace caspar {\r
+namespace caspar { namespace ogl {\r
\r
enum stretch\r
{\r
uniform_to_fill\r
};\r
\r
+struct configuration\r
+{\r
+ size_t screen_index;\r
+ stretch stretch;\r
+ bool windowed;\r
+ bool auto_deinterlace;\r
+ bool key_only;\r
+\r
+ configuration()\r
+ : screen_index(0)\r
+ , stretch(fill)\r
+ , windowed(true)\r
+ , auto_deinterlace(true)\r
+ , key_only(false)\r
+ {\r
+ }\r
+};\r
+\r
struct ogl_consumer : boost::noncopyable\r
{ \r
+ const configuration config_;\r
core::video_format_desc format_desc_;\r
\r
GLuint texture_;\r
std::vector<GLuint> pbos_;\r
\r
float width_;\r
- float height_;\r
- \r
- const stretch stretch_;\r
-\r
- const bool windowed_;\r
+ float height_; \r
unsigned int screen_x_;\r
unsigned int screen_y_;\r
unsigned int screen_width_;\r
unsigned int screen_height_;\r
- const unsigned int screen_index_;\r
-\r
size_t square_width_;\r
size_t square_height_; \r
\r
sf::Window window_;\r
\r
- safe_ptr<diagnostics::graph> graph_;\r
- boost::timer perf_timer_;\r
+ safe_ptr<diagnostics::graph> graph_;\r
+ boost::timer perf_timer_;\r
\r
boost::circular_buffer<safe_ptr<core::read_frame>> input_buffer_;\r
tbb::concurrent_bounded_queue<safe_ptr<core::read_frame>> frame_buffer_;\r
tbb::atomic<bool> is_running_;\r
\r
\r
- filter filter_;\r
-\r
- const bool key_only_;\r
+ ffmpeg::filter filter_;\r
public:\r
- ogl_consumer(unsigned int screen_index, stretch stretch, bool windowed, const core::video_format_desc& format_desc, bool key_only) \r
- : format_desc_(format_desc)\r
+ ogl_consumer(const configuration& config, const core::video_format_desc& format_desc) \r
+ : config_(config)\r
+ , format_desc_(format_desc)\r
, texture_(0)\r
- , pbos_(2, 0)\r
- , stretch_(stretch)\r
- , windowed_(windowed)\r
- , screen_index_(screen_index) \r
+ , pbos_(2, 0) \r
, screen_width_(format_desc.width)\r
, screen_height_(format_desc.height)\r
- , square_width_(format_desc.width)\r
- , square_height_(format_desc.height)\r
- , graph_(diagnostics::create_graph(narrow(print())))\r
+ , square_width_(format_desc.square_width)\r
+ , square_height_(format_desc.square_height)\r
, input_buffer_(core::consumer_buffer_depth()-1)\r
- , key_only_(key_only)\r
- , filter_(format_desc.field_mode == core::field_mode::progressive ? L"" : L"YADIF=0:-1", boost::assign::list_of(PIX_FMT_BGRA))\r
+ , filter_(format_desc.field_mode == core::field_mode::progressive || !config.auto_deinterlace ? L"" : L"YADIF=0:-1", boost::assign::list_of(PIX_FMT_BGRA))\r
{ \r
- if(format_desc.field_mode != core::field_mode::progressive)\r
- CASPAR_LOG(info) << print() << L" Deinterlacer enabled.";\r
-\r
frame_buffer_.set_capacity(2);\r
\r
graph_->add_guide("frame-time", 0.5);\r
graph_->set_color("frame-time", diagnostics::color(1.0f, 0.0f, 0.0f));\r
graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
- \r
- if(format_desc_.format == core::video_format::pal)\r
- {\r
- square_width_ = 768;\r
- square_height_ = 576;\r
- }\r
- else if(format_desc_.format == core::video_format::ntsc)\r
- {\r
- square_width_ = 720;\r
- square_height_ = 547;\r
- }\r
- \r
- DISPLAY_DEVICE d_device; \r
- memset(&d_device, 0, sizeof(d_device));\r
- d_device.cb = sizeof(d_device);\r
-\r
+ graph_->set_text(print());\r
+ diagnostics::register_graph(graph_);\r
+ \r
+ DISPLAY_DEVICE d_device = {sizeof(d_device), 0}; \r
std::vector<DISPLAY_DEVICE> displayDevices;\r
for(int n = 0; EnumDisplayDevices(NULL, n, &d_device, NULL); ++n)\r
- {\r
displayDevices.push_back(d_device);\r
- memset(&d_device, 0, sizeof(d_device));\r
- d_device.cb = sizeof(d_device);\r
- }\r
\r
- if(screen_index_ >= displayDevices.size())\r
+ if(config_.screen_index >= displayDevices.size())\r
BOOST_THROW_EXCEPTION(out_of_range() << arg_name_info("screen_index_") << msg_info(narrow(print())));\r
\r
- DEVMODE devmode;\r
- memset(&devmode, 0, sizeof(devmode));\r
- \r
- if(!EnumDisplaySettings(displayDevices[screen_index_].DeviceName, ENUM_CURRENT_SETTINGS, &devmode))\r
+ DEVMODE devmode = {};\r
+ if(!EnumDisplaySettings(displayDevices[config_.screen_index].DeviceName, ENUM_CURRENT_SETTINGS, &devmode))\r
BOOST_THROW_EXCEPTION(invalid_operation() << arg_name_info("screen_index") << msg_info(narrow(print()) + " EnumDisplaySettings"));\r
\r
screen_x_ = devmode.dmPosition.x;\r
screen_y_ = devmode.dmPosition.y;\r
- screen_width_ = windowed_ ? square_width_ : devmode.dmPelsWidth;\r
- screen_height_ = windowed_ ? square_height_ : devmode.dmPelsHeight;\r
+ screen_width_ = config_.windowed ? square_width_ : devmode.dmPelsWidth;\r
+ screen_height_ = config_.windowed ? square_height_ : devmode.dmPelsHeight;\r
\r
is_running_ = true;\r
thread_ = boost::thread([this]{run();});\r
if(!GLEW_VERSION_2_1)\r
BOOST_THROW_EXCEPTION(not_supported() << msg_info("Missing OpenGL 2.1 support."));\r
\r
- window_.Create(sf::VideoMode(screen_width_, screen_height_, 32), narrow(print()), windowed_ ? sf::Style::Resize : sf::Style::Fullscreen);\r
+ window_.Create(sf::VideoMode(screen_width_, screen_height_, 32), narrow(print()), config_.windowed ? sf::Style::Resize : sf::Style::Fullscreen);\r
window_.ShowMouseCursor(false);\r
window_.SetPosition(screen_x_, screen_y_);\r
window_.SetSize(screen_width_, screen_height_);\r
return;\r
\r
auto av_frame = get_av_frame();\r
- av_frame->data[0] = const_cast<uint8_t*>(frame->image_data().begin());\r
+ av_frame->data[0] = const_cast<uint8_t*>(frame->image_data().begin());\r
\r
auto frames = filter_.execute(av_frame);\r
\r
\r
auto av_frame2 = get_av_frame();\r
av_image_alloc(av_frame2->data, av_frame2->linesize, av_frame2->width, av_frame2->height, PIX_FMT_BGRA, 16);\r
- av_image_copy(av_frame2->data, av_frame2->linesize, src_data, src_linesizes, PIX_FMT_BGRA, av_frame2->width, av_frame2->height);\r
av_frame = safe_ptr<AVFrame>(av_frame2.get(), [=](AVFrame*)\r
{\r
av_freep(&av_frame2->data[0]);\r
});\r
+\r
+ av_image_copy(av_frame2->data, av_frame2->linesize, src_data, src_linesizes, PIX_FMT_BGRA, av_frame2->width, av_frame2->height);\r
}\r
\r
glBindTexture(GL_TEXTURE_2D, texture_);\r
auto ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);\r
if(ptr)\r
{\r
- if(key_only_)\r
+ if(config_.key_only)\r
fast_memshfl(reinterpret_cast<char*>(ptr), av_frame->data[0], frame->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
else\r
fast_memcpy(reinterpret_cast<char*>(ptr), av_frame->data[0], frame->image_data().size());\r
\r
std::wstring print() const\r
{ \r
- return L"ogl[" + boost::lexical_cast<std::wstring>(screen_index_) + L"|" + format_desc_.name + L"]";\r
+ return L"ogl[" + boost::lexical_cast<std::wstring>(config_.screen_index) + L"|" + format_desc_.name + L"]";\r
}\r
\r
void calculate_aspect()\r
{\r
- if(windowed_)\r
+ if(config_.windowed)\r
{\r
screen_height_ = window_.GetHeight();\r
screen_width_ = window_.GetWidth();\r
GL(glViewport(0, 0, screen_width_, screen_height_));\r
\r
std::pair<float, float> target_ratio = None();\r
- if(stretch_ == fill)\r
+ if(config_.stretch == fill)\r
target_ratio = Fill();\r
- else if(stretch_ == uniform)\r
+ else if(config_.stretch == uniform)\r
target_ratio = Uniform();\r
- else if(stretch_ == uniform_to_fill)\r
+ else if(config_.stretch == uniform_to_fill)\r
target_ratio = UniformToFill();\r
\r
width_ = target_ratio.first;\r
\r
struct ogl_consumer_proxy : public core::frame_consumer\r
{\r
- size_t screen_index_;\r
- caspar::stretch stretch_;\r
- bool windowed_;\r
- bool key_only_;\r
-\r
+ const configuration config_;\r
std::unique_ptr<ogl_consumer> consumer_;\r
\r
public:\r
\r
- ogl_consumer_proxy(size_t screen_index, stretch stretch, bool windowed, bool key_only)\r
- : screen_index_(screen_index)\r
- , stretch_(stretch)\r
- , windowed_(windowed)\r
- , key_only_(key_only){}\r
+ ogl_consumer_proxy(const configuration& config)\r
+ : config_(config){}\r
\r
virtual void initialize(const core::video_format_desc& format_desc)\r
{\r
- consumer_.reset(new ogl_consumer(screen_index_, stretch_, windowed_, format_desc, key_only_));\r
+ consumer_.reset(new ogl_consumer(config_, format_desc));\r
}\r
\r
virtual bool send(const safe_ptr<core::read_frame>& frame)\r
}\r
}; \r
\r
-safe_ptr<core::frame_consumer> create_ogl_consumer(const std::vector<std::wstring>& params)\r
+safe_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>& params)\r
{\r
if(params.size() < 1 || params[0] != L"SCREEN")\r
return core::frame_consumer::empty();\r
\r
- size_t screen_index = 0;\r
- stretch stretch = stretch::fill;\r
- bool windowed = true;\r
- \r
+ configuration config;\r
+ \r
if(params.size() > 1) \r
- screen_index = lexical_cast_or_default<int>(params[2], screen_index);\r
+ config.screen_index = lexical_cast_or_default<int>(params[2], config.screen_index);\r
\r
if(params.size() > 2) \r
- windowed = lexical_cast_or_default<bool>(params[3], windowed);\r
+ config.windowed = lexical_cast_or_default<bool>(params[3], config.windowed);\r
\r
- bool key_only = std::find(params.begin(), params.end(), L"KEY_ONLY") != params.end();\r
+ config.key_only = std::find(params.begin(), params.end(), L"KEY_ONLY") != params.end();\r
\r
- return make_safe<ogl_consumer_proxy>(screen_index, stretch, windowed, key_only);\r
+ return make_safe<ogl_consumer_proxy>(config);\r
}\r
\r
-safe_ptr<core::frame_consumer> create_ogl_consumer(const boost::property_tree::ptree& ptree) \r
+safe_ptr<core::frame_consumer> create_consumer(const boost::property_tree::ptree& ptree) \r
{\r
- size_t screen_index = ptree.get("device", 0);\r
- bool windowed =ptree.get("windowed", true);\r
+ configuration config;\r
+ config.screen_index = ptree.get("device", config.screen_index);\r
+ config.windowed = ptree.get("windowed", config.windowed);\r
+ config.key_only = ptree.get("key-only", config.key_only);\r
+ config.auto_deinterlace = ptree.get("auto-deinterlace", config.auto_deinterlace);\r
\r
- stretch stretch = stretch::fill;\r
- auto key_str = ptree.get("stretch", "default");\r
- if(key_str == "uniform")\r
- stretch = stretch::uniform;\r
- else if(key_str == "uniform_to_fill")\r
- stretch = stretch::uniform_to_fill;\r
-\r
- bool key_only = ptree.get("key-only", false);\r
-\r
- return make_safe<ogl_consumer_proxy>(screen_index, stretch, windowed, key_only);\r
+ auto stretch_str = ptree.get("stretch", "default");\r
+ if(stretch_str == "uniform")\r
+ config.stretch = stretch::uniform;\r
+ else if(stretch_str == "uniform_to_fill")\r
+ config.stretch = stretch::uniform_to_fill;\r
+ \r
+ return make_safe<ogl_consumer_proxy>(config);\r
}\r
\r
-}
\ No newline at end of file
+}}
\ No newline at end of file