#include <core/frame/pixel_format.h>\r
#include <core/frame/frame_transform.h>\r
\r
-#include <boost/noncopyable.hpp>\r
+#include <boost/lexical_cast.hpp>\r
\r
namespace caspar { namespace accelerator { namespace ogl {\r
\r
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,\r
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff};\r
\r
-struct image_kernel::impl : boost::noncopyable\r
+struct image_kernel::impl\r
{ \r
spl::shared_ptr<device> ogl_;\r
spl::shared_ptr<shader> shader_;\r
shader_->set("plane[1]", texture_id::plane1);\r
shader_->set("plane[2]", texture_id::plane2);\r
shader_->set("plane[3]", texture_id::plane3);\r
+ for(int n = 0; n < params.textures.size(); ++n)\r
+ shader_->set("plane_size[" + boost::lexical_cast<std::string>(n) + "]", \r
+ static_cast<float>(params.textures[n]->width()), \r
+ static_cast<float>(params.textures[n]->height()));\r
+\r
shader_->set("local_key", texture_id::local_key);\r
shader_->set("layer_key", texture_id::layer_key);\r
shader_->set("is_hd", params.pix_desc.planes.at(0).height > 700 ? 1 : 0);\r
shader_->set("has_layer_key", params.layer_key);\r
shader_->set("pixel_format", params.pix_desc.format.value()); \r
shader_->set("opacity", params.transform.is_key ? 1.0 : params.transform.opacity); \r
- \r
+ \r
+\r
// Setup blend_func\r
\r
if(params.transform.is_key)\r
"#version 130 \n"\r
"uniform sampler2D background; \n"\r
"uniform sampler2D plane[4]; \n"\r
+ "uniform vec2 plane_size[4]; \n"\r
"uniform sampler2D local_key; \n"\r
"uniform sampler2D layer_key; \n"\r
" \n"\r
"uniform int blend_mode; \n"\r
"uniform int keyer; \n"\r
"uniform int pixel_format; \n"\r
+ "uniform int deinterlace; \n"\r
" \n"\r
"uniform float opacity; \n"\r
"uniform bool levels; \n"\r
" return ycbcra_to_rgba_sd(y, cb, cr, a); \n"\r
"} \n"\r
" \n"\r
+ "vec4 get_sample(sampler2D sampler, vec2 coords, vec2 size) \n"\r
+ "{ \n"\r
+ " switch(deinterlace) \n"\r
+ " { \n"\r
+ " case 1: // upper \n"\r
+ " return texture2D(sampler, coords); \n"\r
+ " case 2: // lower \n"\r
+ " return texture2D(sampler, coords); \n"\r
+ " default: \n"\r
+ " return texture2D(sampler, coords); \n"\r
+ " } \n"\r
+ "} \n"\r
+ " \n"\r
"vec4 get_rgba_color() \n"\r
"{ \n"\r
" switch(pixel_format) \n"\r
" { \n"\r
" case 0: //gray \n"\r
- " return vec4(texture2D(plane[0], gl_TexCoord[0].st).rrr, 1.0); \n"\r
+ " return vec4(get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).rrr, 1.0);\n"\r
" case 1: //bgra, \n"\r
- " return texture2D(plane[0], gl_TexCoord[0].st).bgra; \n"\r
+ " return get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).bgra; \n"\r
" case 2: //rgba, \n"\r
- " return texture2D(plane[0], gl_TexCoord[0].st).rgba; \n"\r
+ " return get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).rgba; \n"\r
" case 3: //argb, \n"\r
- " return texture2D(plane[0], gl_TexCoord[0].st).argb; \n"\r
+ " return get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).argb; \n"\r
" case 4: //abgr, \n"\r
- " return texture2D(plane[0], gl_TexCoord[0].st).gbar; \n"\r
+ " return get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).gbar; \n"\r
" case 5: //ycbcr, \n"\r
" { \n"\r
- " float y = texture2D(plane[0], gl_TexCoord[0].st).r; \n"\r
- " float cb = texture2D(plane[1], gl_TexCoord[0].st).r; \n"\r
- " float cr = texture2D(plane[2], gl_TexCoord[0].st).r; \n"\r
+ " float y = get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).r; \n"\r
+ " float cb = get_sample(plane[1], gl_TexCoord[0].st, plane_size[0]).r; \n"\r
+ " float cr = get_sample(plane[2], gl_TexCoord[0].st, plane_size[0]).r; \n"\r
" return ycbcra_to_rgba(y, cb, cr, 1.0); \n"\r
" } \n"\r
" case 6: //ycbcra \n"\r
" { \n"\r
- " float y = texture2D(plane[0], gl_TexCoord[0].st).r; \n"\r
- " float cb = texture2D(plane[1], gl_TexCoord[0].st).r; \n"\r
- " float cr = texture2D(plane[2], gl_TexCoord[0].st).r; \n"\r
- " float a = texture2D(plane[3], gl_TexCoord[0].st).r; \n"\r
+ " float y = get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).r; \n"\r
+ " float cb = get_sample(plane[1], gl_TexCoord[0].st, plane_size[0]).r; \n"\r
+ " float cr = get_sample(plane[2], gl_TexCoord[0].st, plane_size[0]).r; \n"\r
+ " float a = get_sample(plane[3], gl_TexCoord[0].st, plane_size[0]).r; \n"\r
" return ycbcra_to_rgba(y, cb, cr, a); \n"\r
" } \n"\r
" case 7: //luma \n"\r
" { \n"\r
- " vec3 y3 = texture2D(plane[0], gl_TexCoord[0].st).rrr; \n"\r
+ " vec3 y3 = get_sample(plane[0], gl_TexCoord[0].st, plane_size[0]).rrr; \n"\r
" return vec4((y3-0.065)/0.859, 1.0); \n"\r
" } \n"\r
" } \n"\r
{\r
GL(glUniform1f(get_location(name.c_str()), value));\r
}\r
+ \r
+ void set(const std::string& name, float value0, float value1)\r
+ {\r
+ GL(glUniform2f(get_location(name.c_str()), value0, value1));\r
+ }\r
\r
void set(const std::string& name, double value)\r
{\r
void shader::set(const std::string& name, bool value){impl_->set(name, value);}\r
void shader::set(const std::string& name, int value){impl_->set(name, value);}\r
void shader::set(const std::string& name, float value){impl_->set(name, value);}\r
+void shader::set(const std::string& name, float value0, float value1){impl_->set(name, value0, value1);}\r
void shader::set(const std::string& name, double value){impl_->set(name, value);}\r
int shader::id() const{return impl_->program_;}\r
void shader::use()const{impl_->use();}\r
void set(const std::string& name, bool value);\r
void set(const std::string& name, int value);\r
void set(const std::string& name, float value);\r
+ void set(const std::string& name, float value0, float value1);\r
void set(const std::string& name, double value);\r
void use() const;\r
\r
\r
namespace caspar { namespace core {\r
\r
+enum tags\r
+{\r
+ frame_tag = 0,\r
+ empty_tag,\r
+ eof_tag,\r
+ late_tag\r
+};\r
+\r
struct draw_frame::impl\r
{ \r
int tag_;\r
std::vector<draw_frame> frames_;\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
+ impl(int tag = empty_tag)\r
: tag_(tag)\r
{\r
}\r
return draw_frame(std::move(frames));\r
}\r
\r
+draw_frame eof_frame(eof_tag);\r
+draw_frame empty_frame(empty_tag);\r
+draw_frame late_frame(late_tag);\r
+\r
draw_frame draw_frame::still(draw_frame frame)\r
{\r
frame.transform().image_transform.is_still = true; \r
\r
const draw_frame& draw_frame::eof()\r
{\r
- static draw_frame frame(impl::eof_tag);\r
- return frame;\r
+ return eof_frame;\r
}\r
\r
const draw_frame& draw_frame::empty()\r
{\r
- static draw_frame frame(impl::empty_tag);\r
- return frame;\r
+ return empty_frame;\r
}\r
\r
const draw_frame& draw_frame::late()\r
{\r
- static draw_frame frame(impl::late_tag);\r
- return frame;\r
+ return late_frame;\r
}\r
\r
\r
\r
class draw_frame sealed\r
{\r
- draw_frame(int tag);\r
public: \r
// Static Members\r
\r
// Constructors\r
\r
draw_frame();\r
+ draw_frame(int type_tag);\r
draw_frame(const draw_frame& other);\r
draw_frame(draw_frame&& other); \r
explicit draw_frame(class const_frame&& frame);\r