</ItemDefinitionGroup>\r
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
<ClCompile>\r
- <WarningLevel>Level3</WarningLevel>\r
+ <WarningLevel>Level4</WarningLevel>\r
<PrecompiledHeader>Use</PrecompiledHeader>\r
<Optimization>MaxSpeed</Optimization>\r
<FunctionLevelLinking>\r
</Link>\r
</ItemDefinitionGroup>\r
<ItemGroup>\r
+ <ClInclude Include="compiler\vs\disable_silly_warnings.h" />\r
<ClInclude Include="concurrency\executor.h" />\r
<ClInclude Include="concurrency\Thread.h" />\r
<ClInclude Include="config.h" />\r
<ClInclude Include="exception\exceptions.h" />\r
<ClInclude Include="exception\win32_exception.h" />\r
<ClInclude Include="gl\frame_buffer_object.h" />\r
- <ClInclude Include="gl\gl_check.h" />\r
+ <ClInclude Include="gl\utility.h" />\r
<ClInclude Include="gl\pixel_buffer_object.h" />\r
<ClInclude Include="io\AsyncEventServer.h" />\r
<ClInclude Include="io\ClientInfo.h" />\r
<Filter Include="Source\gl">\r
<UniqueIdentifier>{0d94bbc2-e196-4618-a90b-19392a3a0a8e}</UniqueIdentifier>\r
</Filter>\r
+ <Filter Include="Source\compiler">\r
+ <UniqueIdentifier>{63471750-a430-4167-9b49-31b7a068a913}</UniqueIdentifier>\r
+ </Filter>\r
+ <Filter Include="Source\compiler\vs">\r
+ <UniqueIdentifier>{28c25c8a-1277-4d2c-9e85-5af33f9938ea}</UniqueIdentifier>\r
+ </Filter>\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="stdafx.cpp">\r
<ClInclude Include="utility\memory.h">\r
<Filter>Source\utility</Filter>\r
</ClInclude>\r
- <ClInclude Include="gl\gl_check.h">\r
- <Filter>Source\gl</Filter>\r
- </ClInclude>\r
<ClInclude Include="gl\pixel_buffer_object.h">\r
<Filter>Source\gl</Filter>\r
</ClInclude>\r
<ClInclude Include="gl\frame_buffer_object.h">\r
<Filter>Source\gl</Filter>\r
</ClInclude>\r
+ <ClInclude Include="gl\utility.h">\r
+ <Filter>Source\gl</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="compiler\vs\disable_silly_warnings.h">\r
+ <Filter>Source\compiler\vs</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
</Project>
\ No newline at end of file
--- /dev/null
+#pragma once\r
+\r
+#if defined(_MSC_VER)\r
+#pragma warning (disable : 4482) // nonstandard extension used: enum 'enum' used in qualified name\r
+#pragma warning (disable : 4127) // conditional expression is constant\r
+#pragma warning (disable : 4714) // marked as __forceinline not inlined\r
+#endif\r
#pragma once\r
\r
#include "../exception/exceptions.h"\r
+#include "../exception/win32_exception.h"\r
\r
#include <boost/thread.hpp>\r
\r
class executor\r
{\r
public:\r
- explicit executor(const std::function<void()>& run_func = nullptr) : is_running_()\r
+ explicit executor(const std::function<void()>& run_func = nullptr)\r
{\r
+ is_running_ = false;\r
run_func_ = run_func != nullptr ? run_func : [=]{run();};\r
}\r
\r
\r
virtual void run()\r
{\r
+ win32_exception::install_handler();\r
while(is_running_)\r
execute();\r
}\r
\r
#include "frame_buffer_object.h"\r
\r
-#include "../../common/gl/gl_check.h"\r
+#include "../../common/gl/utility.h"\r
\r
#include <Glee.h>\r
\r
#include "pixel_buffer_object.h"\r
\r
#include "../../common/exception/exceptions.h"\r
-#include "../../common/gl/gl_check.h"\r
+#include "../../common/gl/utility.h"\r
#include "../../common/utility/memory.h"\r
\r
namespace caspar { namespace common { namespace gl {\r
size_ = width*height*1;\r
break;\r
default:\r
- BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("format"));\r
+ BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("Unsupported format.") << arg_name_info("format"));\r
}\r
+ if(width < 2 || height < 2)\r
+ BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("Invalid dimensions.") << arg_name_info("width/height"));\r
}\r
\r
~implementation()\r
--- /dev/null
+////////////////////////////////////////////////////////////\r
+//\r
+// SFML - Simple and Fast Multimedia Library\r
+// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)\r
+//\r
+// This software is provided 'as-is', without any express or implied warranty.\r
+// In no event will the authors be held liable for any damages arising from the use of this software.\r
+//\r
+// Permission is granted to anyone to use this software for any purpose,\r
+// including commercial applications, and to alter it and redistribute it freely,\r
+// subject to the following restrictions:\r
+//\r
+// 1. The origin of this software must not be misrepresented;\r
+// you must not claim that you wrote the original software.\r
+// If you use this software in a product, an acknowledgment\r
+// in the product documentation would be appreciated but is not required.\r
+//\r
+// 2. Altered source versions must be plainly marked as such,\r
+// and must not be misrepresented as being the original software.\r
+//\r
+// 3. This notice may not be removed or altered from any source distribution.\r
+//\r
+////////////////////////////////////////////////////////////\r
+\r
+#pragma once\r
+\r
+#include <Glee.h>\r
+\r
+#include "../exception/exceptions.h"\r
+#include "../log/log.h"\r
+\r
+#include <boost/lexical_cast.hpp>\r
+\r
+namespace caspar { namespace common { namespace gl {\r
+ \r
+inline void SMFL_GLCheckError(const std::string& expr, const std::string& File, unsigned int Line)\r
+{\r
+ // Get the last error\r
+ GLenum ErrorCode = glGetError();\r
+\r
+ if (ErrorCode != GL_NO_ERROR)\r
+ {\r
+ std::string Error = "unknown error";\r
+ std::string Desc = "no description";\r
+\r
+ // Decode the error code\r
+ switch (ErrorCode)\r
+ {\r
+ case GL_INVALID_ENUM :\r
+ {\r
+ Error = "GL_INVALID_ENUM";\r
+ Desc = "an unacceptable value has been specified for an enumerated argument";\r
+ break;\r
+ }\r
+\r
+ case GL_INVALID_VALUE :\r
+ {\r
+ Error = "GL_INVALID_VALUE";\r
+ Desc = "a numeric argument is out of range";\r
+ break;\r
+ }\r
+\r
+ case GL_INVALID_OPERATION :\r
+ {\r
+ Error = "GL_INVALID_OPERATION";\r
+ Desc = "the specified operation is not allowed in the current state";\r
+ break;\r
+ }\r
+\r
+ case GL_STACK_OVERFLOW :\r
+ {\r
+ Error = "GL_STACK_OVERFLOW";\r
+ Desc = "this command would cause a stack overflow";\r
+ break;\r
+ }\r
+\r
+ case GL_STACK_UNDERFLOW :\r
+ {\r
+ Error = "GL_STACK_UNDERFLOW";\r
+ Desc = "this command would cause a stack underflow";\r
+ break;\r
+ }\r
+\r
+ case GL_OUT_OF_MEMORY :\r
+ {\r
+ Error = "GL_OUT_OF_MEMORY";\r
+ Desc = "there is not enough memory left to execute the command";\r
+ break;\r
+ }\r
+\r
+ case GL_INVALID_FRAMEBUFFER_OPERATION_EXT :\r
+ {\r
+ Error = "GL_INVALID_FRAMEBUFFER_OPERATION_EXT";\r
+ Desc = "the object bound to FRAMEBUFFER_BINDING_EXT is not \"framebuffer complete\"";\r
+ break;\r
+ }\r
+ }\r
+\r
+ // Log the error\r
+ CASPAR_LOG(error) << "An internal OpenGL call failed in "\r
+ << File.substr(File.find_last_of("\\/") + 1).c_str() << " (" << Line << ") : "\r
+ << Error.c_str() << ", " << Desc.c_str()\r
+ << ", " << expr.c_str()\r
+ << std::endl;\r
+ }\r
+}\r
+\r
+#ifdef _DEBUG\r
+ \r
+#define CASPAR_GL_EXPR_STR(expr) #expr\r
+\r
+#define GL(expr) \\r
+ do \\r
+ { \\r
+ (expr); \\r
+ caspar::common::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FILE__, __LINE__);\\r
+ }while(0);\r
+#else\r
+#define GL(expr) expr\r
+#endif\r
+\r
+}}}
\ No newline at end of file
#include "../stdafx.h"\r
\r
#if defined(_MSC_VER)\r
-#pragma warning (disable : 4100)\r
-#pragma warning (disable : 4127) // conditional expression is constant\r
-#pragma warning (disable : 4512)\r
-#pragma warning (disable : 4714) // marked as __forceinline not inlined\r
+#pragma warning (disable : 4100) // 'identifier' : unreferenced formal parameter\r
+#pragma warning (disable : 4512) // 'class' : assignment operator could not be generated\r
#endif\r
\r
#include "log.h"\r
\r
#include "../utility/string_convert.h"\r
\r
-namespace caspar{ namespace log{\r
+namespace caspar { namespace log {\r
\r
namespace internal{\r
-\r
void init();\r
-\r
}\r
\r
void add_file_sink(const std::wstring& folder);\r
#define NOMINMAX\r
#define WIN32_LEAN_AND_MEAN\r
\r
-#if (defined(_MSC_VER) && _MSC_VER > 1000)\r
-#pragma warning (disable : 4482)\r
-#endif\r
+#include "compiler\vs\disable_silly_warnings.h"\r
\r
#include "config.h"\r
\r
\r
void* aligned_memcpy(void* dest, const void* source, size_t num)\r
{ \r
+ if(num < 128)\r
+ return memcpy(dest, source, num);\r
+\r
+ size_t r = num % 128;\r
+ num -= r;\r
+\r
__asm\r
{\r
mov esi, source; \r
\r
jnz cpy;\r
}\r
- return dest;\r
+\r
+ return r == 0 ? dest : memcpy(reinterpret_cast<char*>(dest) + num, reinterpret_cast<const char*>(source) + num, r);\r
}\r
\r
void* aligned_parallel_memcpy(void* dest, const void* source, size_t num)\r
tbb::parallel_for(tbb::blocked_range<size_t>(0, num/128), [&](const tbb::blocked_range<size_t>& r)\r
{\r
aligned_memcpy(reinterpret_cast<char*>(dest) + r.begin()*128, reinterpret_cast<const char*>(source) + r.begin()*128, r.size()*128);\r
- }, tbb::affinity_partitioner());\r
+ });\r
\r
return dest;\r
}\r
return str;\r
}\r
\r
+#if defined(_MSC_VER)\r
#pragma warning(push)\r
#pragma warning(disable : 4244)\r
+#endif\r
\r
inline std::string narrow(const std::wstring& str, const std::locale& locale = std::locale())\r
{\r
return str ;\r
}\r
\r
+#if defined(_MSC_VER)\r
#pragma warning(pop)\r
+#endif\r
//\r
//inline std::string narrow_to_latin1(const std::wstring& wideString)\r
//{\r
\r
#pragma once\r
\r
-#ifdef _MSC_VER\r
-#pragma warning (disable : 4482)\r
-#endif\r
+#include "../common/compiler/vs/disable_silly_warnings.h"\r
\r
#if !defined(AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_)\r
#define AFX_STDAFX_H__A9DB83DB_A9FD_11D0_BFD1_444553540000__INCLUDED_\r
#include <tbb/atomic.h>\r
#include <tbb/concurrent_queue.h>\r
#include <tbb/parallel_invoke.h>\r
+#include <tbb/parallel_for.h>\r
\r
#include <boost/assign.hpp>\r
#include <boost/filesystem.hpp>\r
#include <boost/foreach.hpp>\r
\r
+#include <GLee.h>\r
+\r
+#include <SFML/Window.hpp>\r
+#include <SFML/Audio.hpp>\r
+\r
#include "../common/utility/string_convert.h"\r
\r
#include "../common/log/Log.h"\r
//blue_set_connector_property(pBlueDevice, 1, video_routing);\r
//blue_detach_from_device(&pBlueDevice);\r
\r
- vid_fmt_ = ULONG_MAX;\r
+ vid_fmt_ = VID_FMT_INVALID;\r
auto desiredVideoFormat = vid_fmt_from_frame_format(format_desc_.format);\r
int videoModeCount = sdk_->count_video_mode();\r
for(int videoModeIndex=1; videoModeIndex <= videoModeCount; ++videoModeIndex) \r
if(videoMode == desiredVideoFormat) \r
vid_fmt_ = videoMode; \r
}\r
- if(vid_fmt_ == ULONG_MAX)\r
+ if(vid_fmt_ == VID_FMT_INVALID)\r
BOOST_THROW_EXCEPTION(bluefish_exception() << msg_info("BLUECARD ERROR: Failed to set videomode."));\r
\r
// Set default video output channel\r
boost::thread thread_;\r
tbb::concurrent_bounded_queue<gpu_frame_ptr> frame_buffer_;\r
\r
- unsigned long mem_fmt_;\r
- unsigned long upd_fmt_;\r
- unsigned long vid_fmt_; \r
- unsigned long res_fmt_; \r
- unsigned long engine_mode_;\r
+ unsigned long mem_fmt_;\r
+ unsigned long upd_fmt_;\r
+ EVideoMode vid_fmt_; \r
+ unsigned long res_fmt_; \r
+ unsigned long engine_mode_;\r
\r
gpu_frame_ptr transferring_frame_;\r
\r
card_type == CRD_BLUE_EPOCH_ULTRA;\r
}\r
\r
-inline unsigned long vid_fmt_from_frame_format(const frame_format& fmt) \r
+inline EVideoMode vid_fmt_from_frame_format(const frame_format& fmt) \r
{\r
switch(fmt)\r
{\r
case frame_format::pal: return VID_FMT_PAL;\r
case frame_format::ntsc: return VID_FMT_NTSC;\r
- case frame_format::x576p2500: return ULONG_MAX; //not supported\r
+ case frame_format::x576p2500: return VID_FMT_INVALID; //not supported\r
case frame_format::x720p5000: return VID_FMT_720P_5000;\r
case frame_format::x720p5994: return VID_FMT_720P_5994;\r
case frame_format::x720p6000: return VID_FMT_720P_6000;\r
case frame_format::x1080p2500: return VID_FMT_1080P_2500;\r
case frame_format::x1080p2997: return VID_FMT_1080P_2997;\r
case frame_format::x1080p3000: return VID_FMT_1080P_3000;\r
- default: return ULONG_MAX;\r
+ default: return VID_FMT_INVALID;\r
}\r
}\r
\r
\r
#include "../../StdAfx.h"\r
\r
-#if defined(_MSC_VER)\r
-#pragma warning (disable : 4244)\r
-#endif\r
-\r
#include "ogl_consumer.h"\r
\r
#include "../../frame/frame_format.h"\r
#include "../../frame/gpu_frame.h"\r
#include "../../../common/utility/memory.h"\r
-#include "../../../common/gl/gl_check.h"\r
+#include "../../../common/gl/utility.h"\r
#include "../../../common/gl/pixel_buffer_object.h"\r
\r
#include <boost/thread.hpp>\r
int next_index = (index_ + 1) % 2;\r
\r
auto ptr = pbos_[index_].end_write();\r
- common::aligned_parallel_memcpy(ptr, frame->data(), frame->size());\r
+ common::aligned_parallel_memcpy(ptr, frame->data(), format_desc_.size);\r
\r
GL(glClear(GL_COLOR_BUFFER_BIT)); \r
pbos_[next_index].bind_texture(); \r
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
<PrecompiledHeader>Use</PrecompiledHeader>\r
- <WarningLevel>Level3</WarningLevel>\r
+ <WarningLevel>Level4</WarningLevel>\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<PreprocessorDefinitions>NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
<ClInclude Include="frame\frame_format.h" />\r
<ClInclude Include="frame\frame_fwd.h" />\r
<ClInclude Include="frame\gpu_frame.h" />\r
- <ClInclude Include="frame\gpu_frame_processor.h" />\r
- <ClInclude Include="frame\gpu_frame_transform.h" />\r
+ <ClInclude Include="frame\gpu_frame_device.h" />\r
+ <ClInclude Include="frame\gpu_frame_renderer.h" />\r
+ <ClInclude Include="frame\gpu_frame_shader.h" />\r
+ <ClInclude Include="frame\gpu_frame_desc.h" />\r
<ClInclude Include="producer\color\color_producer.h" />\r
<ClInclude Include="producer\ffmpeg\audio\audio_decoder.h" />\r
<ClInclude Include="producer\ffmpeg\ffmpeg_producer.h" />\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
</ClCompile>\r
- <ClCompile Include="frame\gpu_frame_processor.cpp">\r
+ <ClCompile Include="frame\gpu_frame_device.cpp">\r
+ <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
+ <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
+ </ClCompile>\r
+ <ClCompile Include="frame\gpu_frame_renderer.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
</ClCompile>\r
- <ClCompile Include="frame\gpu_frame_transform.cpp">\r
+ <ClCompile Include="frame\gpu_frame_shader.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
</ClCompile>\r
<ClInclude Include="frame\gpu_frame.h">\r
<Filter>Source\frame\gpu</Filter>\r
</ClInclude>\r
- <ClInclude Include="frame\gpu_frame_processor.h">\r
- <Filter>Source\frame\gpu</Filter>\r
- </ClInclude>\r
<ClInclude Include="frame\frame_factory.h">\r
<Filter>Source\frame</Filter>\r
</ClInclude>\r
<ClInclude Include="config.h">\r
<Filter>Source</Filter>\r
</ClInclude>\r
- <ClInclude Include="frame\gpu_frame_transform.h">\r
- <Filter>Source\frame\gpu</Filter>\r
- </ClInclude>\r
<ClInclude Include="consumer\frame_consumer.h">\r
<Filter>Source\consumer</Filter>\r
</ClInclude>\r
+ <ClInclude Include="frame\gpu_frame_desc.h">\r
+ <Filter>Source\frame\gpu</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="frame\gpu_frame_device.h">\r
+ <Filter>Source\frame\gpu</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="frame\gpu_frame_renderer.h">\r
+ <Filter>Source\frame\gpu</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="frame\gpu_frame_shader.h">\r
+ <Filter>Source\frame\gpu</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="StdAfx.cpp">\r
<ClCompile Include="protocol\media.cpp">\r
<Filter>Source\protocol</Filter>\r
</ClCompile>\r
- <ClCompile Include="frame\gpu_frame_processor.cpp">\r
- <Filter>Source\frame\gpu</Filter>\r
- </ClCompile>\r
<ClCompile Include="frame\gpu_frame.cpp">\r
<Filter>Source\frame\gpu</Filter>\r
</ClCompile>\r
<ClCompile Include="renderer\display_device.cpp">\r
<Filter>Source\renderer</Filter>\r
</ClCompile>\r
- <ClCompile Include="frame\gpu_frame_transform.cpp">\r
+ <ClCompile Include="frame\gpu_frame_device.cpp">\r
+ <Filter>Source\frame\gpu</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="frame\gpu_frame_renderer.cpp">\r
+ <Filter>Source\frame\gpu</Filter>\r
+ </ClCompile>\r
+ <ClCompile Include="frame\gpu_frame_shader.cpp">\r
<Filter>Source\frame\gpu</Filter>\r
</ClCompile>\r
</ItemGroup>\r
#include <array>\r
\r
namespace caspar { namespace core { \r
- \r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/// \struct frame_factory\r
+///\r
+/// \brief Factory interface used to create frames.\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
struct frame_factory\r
{\r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ /// \fn virtual ~frame_factory()\r
+ ///\r
+ /// \brief Destructor. \r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
virtual ~frame_factory(){}\r
+\r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ /// \fn virtual void release_frames(void* tag) = 0;\r
+ ///\r
+ /// \brief Releases the frame pool associated with the provided tag. \r
+ ///\r
+ /// \param tag Tag associated with the source frame pool. \r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
virtual void release_frames(void* tag) = 0;\r
+\r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ /// \fn virtual gpu_frame_ptr create_frame(size_t width, size_t height, void* tag) = 0;\r
+ ///\r
+ /// \brief Creates a frame from a pool associated with the provided tag. \r
+ /// Frames are pooled on destruction and need to be released with *release_frames*. \r
+ ///\r
+ /// \param width The width. \r
+ /// \param height The height. \r
+ /// \param tag Tag associated with the source frame pool. \r
+ ///\r
+ /// \return . \r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
virtual gpu_frame_ptr create_frame(size_t width, size_t height, void* tag) = 0;\r
- virtual gpu_frame_ptr create_frame(const planar_frame_dimension& data_size, void* tag) = 0;\r
+\r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ /// \fn virtual gpu_frame_ptr create_frame(const gpu_frame_desc& desc, void* tag) = 0;\r
+ ///\r
+ /// \brief Creates a frame from a pool associated with the provided tag. \r
+ /// Frames are pooled on destruction and need to be released with *release_frames*. \r
+ ///\r
+ /// \param desc Information describing the frame. \r
+ /// \param tag Tag associated with the source frame pool. \r
+ ///\r
+ /// \return . \r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ virtual gpu_frame_ptr create_frame(const gpu_frame_desc& desc, void* tag) = 0;\r
+\r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ /// \fn gpu_frame_ptr create_frame(const frame_format_desc format_desc, void* tag)\r
+ ///\r
+ /// \brief Creates a frame from a pool associated with the provided tag. \r
+ /// Frames are pooled on destruction and need to be released with *release_frames*. \r
+ ///\r
+ /// \param format_desc Information describing the frame format. \r
+ /// \param tag Tag associated with the source frame pool. \r
+ ///\r
+ /// \return . \r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
gpu_frame_ptr create_frame(const frame_format_desc format_desc, void* tag)\r
{\r
return create_frame(format_desc.width, format_desc.height, tag);\r
DEFINE_VIDEOFORMATDESC(1920, 1080,video_mode:: progressive, 30, TEXT("1080p3000"), frame_format::x1080p3000)\r
};\r
\r
-frame_format get_video_format(const std::wstring& str)\r
+frame_format get_video_format(const std::wstring& name)\r
{\r
for(int n = 0; n < frame_format::count; ++n)\r
{\r
- if(boost::iequals(frame_format_desc::format_descs[n].name, str))\r
+ if(boost::iequals(frame_format_desc::format_descs[n].name, name))\r
return static_cast<frame_format>(n);\r
}\r
\r
\r
#include <string>\r
\r
-#ifdef _MSC_VER\r
-#pragma warning (disable : 4482)\r
-#endif\r
+#include "../../common/compiler/vs/disable_silly_warnings.h"\r
\r
namespace caspar { namespace core {\r
- \r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/// \enum video_mode\r
+///\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
enum video_mode\r
{\r
progressive,\r
upper\r
};\r
\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/// \enum frame_format\r
+///\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
enum frame_format\r
{\r
pal = 0,\r
invalid\r
};\r
\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/// \struct frame_format_desc\r
+///\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
struct frame_format_desc\r
{\r
- size_t width;\r
- size_t height;\r
- video_mode mode;\r
- double fps;\r
- size_t size;\r
- std::wstring name;\r
- frame_format format;\r
+ size_t width;\r
+ size_t height;\r
+ video_mode mode;\r
+ double fps;\r
+ size_t size;\r
+ std::wstring name;\r
+ frame_format format;\r
\r
static const frame_format_desc format_descs[frame_format::count];\r
};\r
return !(rhs == lhs);\r
}\r
\r
-frame_format get_video_format(const std::wstring& strVideoMode);\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/// \fn frame_format get_video_format(const std::wstring& strVideoMode);\r
+///\r
+/// \brief Gets the *frame_format* associated with the specified name.\r
+///\r
+/// \param name Name of the *frame_format*.. \r
+///\r
+/// \return The video format. \r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+frame_format get_video_format(const std::wstring& name);\r
\r
-inline frame_format_desc get_video_format_desc(const std::wstring& strVideoMode, frame_format defaultFormat = frame_format::x576p2500)\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/// \fn frame_format get_video_format_desc(const std::wstring& strVideoMode);\r
+///\r
+/// \brief Gets the *frame_format_desc* associated with the specified name.\r
+///\r
+/// \param name Name of the *frame_format_desc*.. \r
+///\r
+/// \return The video format. \r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+inline frame_format_desc get_video_format_desc(const std::wstring& name, frame_format default_format = frame_format::x576p2500)\r
{ \r
- auto casparVideoFormat = defaultFormat;\r
- if(!strVideoMode.empty())\r
- casparVideoFormat = get_video_format(std::wstring(strVideoMode.begin(), strVideoMode.end()));\r
+ auto casparVideoFormat = default_format;\r
+ if(!name.empty())\r
+ casparVideoFormat = get_video_format(name);\r
return frame_format_desc::format_descs[casparVideoFormat];\r
}\r
\r
-inline double get_frame_format_period(const frame_format_desc& format_desc)\r
+inline double render_frame_format_period(const frame_format_desc& format_desc)\r
{\r
return 1.0/(format_desc.mode == video_mode::progressive ? format_desc.fps : format_desc.fps/2.0);\r
}\r
#include "../StdAfx.h"\r
\r
#include "gpu_composite_frame.h"\r
-#include "../../common/gl/gl_check.h"\r
+#include "../../common/gl/utility.h"\r
#include "../../common/utility/memory.h"\r
\r
#include <boost/range/algorithm.hpp>\r
boost::range::for_each(frames_, std::mem_fn(&gpu_frame::end_read)); \r
}\r
\r
- void draw(const gpu_frame_transform_ptr& transform)\r
+ void draw(const gpu_frame_shader_ptr& shader)\r
{\r
glPushMatrix();\r
glTranslated(self_->x()*2.0, self_->y()*2.0, 0.0);\r
- boost::range::for_each(frames_, std::bind(&gpu_frame::draw, std::placeholders::_1, transform));\r
+ boost::range::for_each(frames_, std::bind(&gpu_frame::draw, std::placeholders::_1, shader));\r
glPopMatrix();\r
}\r
\r
void add(const gpu_frame_ptr& frame)\r
{\r
+ if(frame == nullptr || frame == gpu_frame::null())\r
+ return;\r
+\r
frames_.push_back(frame);\r
\r
if(self_->audio_data().empty())\r
}\r
}\r
\r
- unsigned char* data(size_t index)\r
+ unsigned char* data(size_t)\r
{\r
BOOST_THROW_EXCEPTION(invalid_operation());\r
}\r
size_t size_;\r
};\r
\r
-#pragma warning (disable : 4355)\r
+#if defined(_MSC_VER)\r
+#pragma warning (disable : 4355) // 'this' : used in base member initializer list\r
+#endif\r
\r
gpu_composite_frame::gpu_composite_frame() \r
: gpu_frame(0, 0), impl_(new implementation(this)){}\r
void gpu_composite_frame::end_write(){impl_->end_write();} \r
void gpu_composite_frame::begin_read(){impl_->begin_read();}\r
void gpu_composite_frame::end_read(){impl_->end_read();}\r
-void gpu_composite_frame::draw(const gpu_frame_transform_ptr& transform){impl_->draw(transform);}\r
+void gpu_composite_frame::draw(const gpu_frame_shader_ptr& shader){impl_->draw(shader);}\r
unsigned char* gpu_composite_frame::data(size_t index){return impl_->data(index);}\r
void gpu_composite_frame::add(const gpu_frame_ptr& frame){impl_->add(frame);}\r
\r
virtual void end_write();\r
virtual void begin_read();\r
virtual void end_read();\r
- virtual void draw(const gpu_frame_transform_ptr& transform);\r
+ virtual void draw(const gpu_frame_shader_ptr& shader);\r
\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
#include "../StdAfx.h"\r
\r
#include "gpu_frame.h"\r
+#include "gpu_frame_desc.h"\r
#include "../../common/utility/memory.h"\r
-#include "../../common/gl/gl_check.h"\r
+#include "../../common/gl/utility.h"\r
#include "../../common/gl/pixel_buffer_object.h"\r
\r
+#include <boost/range/algorithm.hpp>\r
+\r
namespace caspar { namespace core {\r
\r
GLubyte progressive_pattern[] = {\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xFF, 0xff, 0xff, 0xff, 0xff, 0xff,\r
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,\r
+ 0xff, 0xff, 0xFF, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
\r
GLubyte upper_pattern[] = {\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};\r
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
+ 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00};\r
\r
GLubyte lower_pattern[] = {\r
- 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
- 0xff, 0xff, 0xff, 0xff};\r
+ 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, \r
+ 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,\r
+ 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,\r
+ 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};\r
\r
struct gpu_frame::implementation : boost::noncopyable\r
{\r
implementation(size_t width, size_t height)\r
- : reading_(false), alpha_(1.0f), x_(0.0f), y_(0.0f), mode_(video_mode::progressive), \r
- texcoords_(0.0, 1.0, 1.0, 0.0), writing_(false), mapped_(false), pix_format_(pixel_format::bgra)\r
- { \r
- data_.resize(1, 0);\r
- pbo_.push_back(std::make_shared<common::gl::pixel_buffer_object>(width, height, GL_BGRA));\r
- if(width > 0 && height > 0)\r
+ : alpha_(1.0f), x_(0.0f), y_(0.0f), mode_(video_mode::progressive), texcoords_(0.0, 1.0, 1.0, 0.0)\r
+ { \r
+ desc_.planes[0] = plane(width, height, 4);\r
+ desc_.plane_count = 1;\r
+ desc_.pix_fmt = pixel_format::bgra;\r
+ if(width >= 2 && height >= 2)\r
+ {\r
+ pbo_.push_back(std::make_shared<common::gl::pixel_buffer_object>(width, height, GL_BGRA));\r
+ pixel_data_.resize(pbo_.size(), 0);\r
end_write();\r
+ }\r
}\r
\r
- implementation(const planar_frame_dimension& data_size)\r
- : reading_(false), alpha_(1.0f), x_(0.0f), y_(0.0f), mode_(video_mode::progressive), \r
- texcoords_(0.0, 1.0, 1.0, 0.0), writing_(false), mapped_(false), pix_format_(pixel_format::bgra)\r
+ implementation(const gpu_frame_desc& desc)\r
+ : alpha_(1.0f), x_(0.0f), y_(0.0f), mode_(video_mode::progressive), texcoords_(0.0, 1.0, 1.0, 0.0)\r
{ \r
- data_.resize(data_size.size(), 0);\r
- for(size_t n = 0; n < data_size.size() && data_size[n].first > 0 && data_size[n].second > 0; ++n)\r
- pbo_.push_back(std::make_shared<common::gl::pixel_buffer_object>(data_size[n].first, data_size[n].second, GL_LUMINANCE));\r
+ desc_ = desc;\r
+\r
+ for(size_t n = 0; n < desc_.plane_count; ++n)\r
+ {\r
+ GLuint format = [&]() -> GLuint\r
+ {\r
+ switch(desc_.planes[n].channels)\r
+ {\r
+ case 1: return GL_LUMINANCE;\r
+ case 2: return GL_LUMINANCE_ALPHA;\r
+ case 3: return GL_BGR;\r
+ case 4: return GL_BGRA;\r
+ default: BOOST_THROW_EXCEPTION(out_of_range() << msg_info("1-4 channels are supported") << arg_name_info("desc.planes.channels")); \r
+ }\r
+ }();\r
+\r
+ pbo_.push_back(std::make_shared<common::gl::pixel_buffer_object>(desc_.planes[n].width, desc_.planes[n].height, format));\r
+ }\r
+ pixel_data_.resize(pbo_.size(), 0);\r
end_write();\r
}\r
\r
void begin_write()\r
{\r
- data_ = std::vector<unsigned char*>(4, 0);\r
- for(size_t n = 0; n < pbo_.size(); ++n)\r
- pbo_[n]->begin_write(); \r
+ pixel_data_ = std::vector<void*>(4, 0);\r
+ boost::range::for_each(pbo_, std::mem_fn(&common::gl::pixel_buffer_object::begin_write));\r
}\r
\r
void end_write()\r
{\r
- for(size_t n = 0; n < pbo_.size(); ++n)\r
- data_[n] = static_cast<unsigned char*>(pbo_[n]->end_write());\r
+ boost::range::transform(pbo_, pixel_data_.begin(), std::mem_fn(&common::gl::pixel_buffer_object::end_write));\r
}\r
\r
void begin_read()\r
{ \r
- data_ = std::vector<unsigned char*>(4, 0);\r
- for(size_t n = 0; n < pbo_.size(); ++n)\r
- pbo_[n]->begin_read(); \r
+ pixel_data_ = std::vector<void*>(4, 0);\r
+ boost::range::for_each(pbo_, std::mem_fn(&common::gl::pixel_buffer_object::begin_read));\r
}\r
\r
void end_read()\r
{\r
- for(size_t n = 0; n < pbo_.size(); ++n)\r
- data_[n] = static_cast<unsigned char*>(pbo_[n]->end_read());\r
+ boost::range::transform(pbo_, pixel_data_.begin(), std::mem_fn(&common::gl::pixel_buffer_object::end_read));\r
}\r
\r
- void draw(const gpu_frame_transform_ptr& transform)\r
+ void draw(const gpu_frame_shader_ptr& shader)\r
{\r
- transform->set_pixel_format(pix_format_);\r
+ shader->use(desc_);\r
glPushMatrix();\r
glTranslated(x_*2.0, y_*2.0, 0.0);\r
glColor4d(1.0, 1.0, 1.0, alpha_);\r
glEnd();\r
glPopMatrix();\r
}\r
- \r
+\r
unsigned char* data(size_t index)\r
{\r
- if(pbo_.size() < index || data_[index] == nullptr)\r
- BOOST_THROW_EXCEPTION(invalid_operation());\r
- return data_[index];\r
+ if(pbo_.size() < index)\r
+ BOOST_THROW_EXCEPTION(out_of_range());\r
+ return static_cast<unsigned char*>(pixel_data_[index]);\r
}\r
\r
void reset()\r
}\r
\r
std::vector<common::gl::pixel_buffer_object_ptr> pbo_;\r
- std::vector<unsigned char*> data_;\r
-\r
- gpu_frame* self_;\r
-\r
- bool reading_;\r
- bool writing_;\r
- bool mapped_;\r
-\r
+ std::vector<void*> pixel_data_; \r
std::vector<short> audio_data_;\r
\r
double alpha_;\r
double y_;\r
video_mode mode_;\r
rectangle texcoords_;\r
- pixel_format pix_format_;\r
+\r
+ gpu_frame_desc desc_;\r
};\r
\r
gpu_frame::gpu_frame(size_t width, size_t height) \r
: impl_(new implementation(width, height)){}\r
-gpu_frame::gpu_frame(const planar_frame_dimension& data_size)\r
- : impl_(new implementation(data_size)){}\r
+gpu_frame::gpu_frame(const gpu_frame_desc& desc)\r
+ : impl_(new implementation(desc)){}\r
+void gpu_frame::draw(const gpu_frame_shader_ptr& shader){impl_->draw(shader);}\r
void gpu_frame::begin_write(){impl_->begin_write();}\r
void gpu_frame::end_write(){impl_->end_write();} \r
void gpu_frame::begin_read(){impl_->begin_read();}\r
void gpu_frame::end_read(){impl_->end_read();}\r
-void gpu_frame::draw(const gpu_frame_transform_ptr& transform){impl_->draw(transform);}\r
-void gpu_frame::set_pixel_format(pixel_format format) {impl_->pix_format_ = format;}\r
+void gpu_frame::pix_fmt(pixel_format format) {impl_->desc_.pix_fmt = format;}\r
unsigned char* gpu_frame::data(size_t index){return impl_->data(index);}\r
-size_t gpu_frame::size(size_t index) const { return impl_->pbo_.at(index)->size(); }\r
-size_t gpu_frame::width(size_t index) const { return impl_->pbo_.at(index)->width();}\r
-size_t gpu_frame::height(size_t index) const { return impl_->pbo_.at(index)->height();}\r
+size_t gpu_frame::size(size_t index) const { return impl_->desc_.planes[index].size; }\r
std::vector<short>& gpu_frame::audio_data() { return impl_->audio_data_; }\r
void gpu_frame::reset(){impl_->reset();}\r
-double gpu_frame::alpha() const{ return impl_->alpha_;}\r
void gpu_frame::alpha(double value){ impl_->alpha_ = value;}\r
-double gpu_frame::x() const { return impl_->x_;}\r
-double gpu_frame::y() const { return impl_->y_;}\r
void gpu_frame::translate(double x, double y) { impl_->x_ += x; impl_->y_ += y; }\r
void gpu_frame::texcoords(const rectangle& texcoords){impl_->texcoords_ = texcoords;}\r
void gpu_frame::mode(video_mode mode){ impl_->mode_ = mode;}\r
-video_mode gpu_frame::mode() const{ return impl_->mode_;}\r
+double gpu_frame::x() const { return impl_->x_;}\r
+double gpu_frame::y() const { return impl_->y_;}\r
}}
\ No newline at end of file
\r
#include "frame_format.h"\r
\r
-#include "gpu_frame_transform.h"\r
+#include "gpu_frame_shader.h"\r
+#include "gpu_frame_desc.h"\r
\r
#include <memory>\r
#include <array>\r
\r
namespace caspar { namespace core {\r
\r
-typedef std::array<std::pair<size_t, size_t>, 4> planar_frame_dimension;\r
-\r
struct rectangle\r
{\r
rectangle(double left, double top, double right, double bottom)\r
double bottom;\r
};\r
\r
-class gpu_frame : boost::noncopyable\r
+class gpu_frame : boost::noncopyable\r
{\r
public:\r
virtual ~gpu_frame(){}\r
\r
virtual unsigned char* data(size_t index = 0);\r
virtual size_t size(size_t index = 0) const;\r
- virtual size_t width(size_t index = 0) const;\r
- virtual size_t height(size_t index = 0) const;\r
\r
virtual std::vector<short>& audio_data();\r
\r
- virtual double alpha() const;\r
virtual void alpha(double value);\r
-\r
- virtual double x() const;\r
- virtual double y() const;\r
virtual void translate(double x, double y);\r
virtual void texcoords(const rectangle& texcoords);\r
-\r
- virtual void mode(video_mode mode);\r
- virtual video_mode mode() const;\r
-\r
- virtual void set_pixel_format(pixel_format format);\r
+ virtual void mode(video_mode mode); \r
+ virtual void pix_fmt(pixel_format format);\r
+ \r
+ virtual double x() const;\r
+ virtual double y() const;\r
\r
static std::shared_ptr<gpu_frame> null()\r
{\r
return my_null_frame;\r
}\r
\r
-protected:\r
- gpu_frame(size_t width, size_t height);\r
- gpu_frame(const planar_frame_dimension& data_size);\r
-\r
- friend class gpu_frame_processor;\r
- \r
virtual void begin_write();\r
virtual void end_write();\r
virtual void begin_read();\r
virtual void end_read();\r
- virtual void draw(const gpu_frame_transform_ptr& transform);\r
+ virtual void draw(const gpu_frame_shader_ptr& shader);\r
+\r
+protected:\r
+ gpu_frame(size_t width, size_t height);\r
+ gpu_frame(const gpu_frame_desc& desc);\r
+\r
+ friend class gpu_frame_device;\r
+\r
virtual void reset();\r
\r
private:\r
--- /dev/null
+#pragma once\r
+\r
+#include <memory>\r
+#include <array>\r
+\r
+enum pixel_format\r
+{\r
+ invalid_pixel_format = 0,\r
+ bgra,\r
+ rgba,\r
+ argb,\r
+ abgr,\r
+ ycbcr,\r
+ ycbcra,\r
+ pixel_format_count,\r
+};\r
+\r
+namespace caspar { namespace core {\r
+ \r
+struct plane\r
+{\r
+ plane(){}\r
+ plane(size_t width, size_t height, size_t channels)\r
+ : width(width), height(height), size(width*height*channels), channels(channels)\r
+ {}\r
+ size_t width;\r
+ size_t height;\r
+ size_t size;\r
+ size_t channels;\r
+};\r
+\r
+struct gpu_frame_desc\r
+{\r
+ gpu_frame_desc(){memset(this, sizeof(gpu_frame_desc), 0);}\r
+ pixel_format pix_fmt;\r
+ std::array<plane, 4> planes;\r
+ size_t plane_count;\r
+};\r
+ \r
+}}
\ No newline at end of file
--- /dev/null
+#include "../StdAfx.h"\r
+\r
+#include "gpu_frame_device.h"\r
+\r
+#include "gpu_frame_renderer.h"\r
+#include "gpu_frame.h"\r
+#include "gpu_composite_frame.h"\r
+\r
+#include "frame_format.h"\r
+\r
+#include "../../common/exception/exceptions.h"\r
+#include "../../common/concurrency/executor.h"\r
+#include "../../common/gl/utility.h"\r
+\r
+#include <Glee.h>\r
+#include <SFML/Window.hpp>\r
+\r
+#include <tbb/concurrent_queue.h>\r
+#include <tbb/concurrent_unordered_map.h>\r
+\r
+#include <boost/thread.hpp>\r
+#include <boost/range/algorithm.hpp>\r
+\r
+#include <functional>\r
+\r
+namespace caspar { namespace core {\r
+ \r
+struct gpu_frame_device::implementation : boost::noncopyable\r
+{ \r
+ implementation(gpu_frame_device* self, const frame_format_desc& format_desc) \r
+ { \r
+ input_.set_capacity(2);\r
+ executor_.start();\r
+ executor_.invoke([=]\r
+ {\r
+ ogl_context_.reset(new sf::Context());\r
+ ogl_context_->SetActive(true);\r
+ GL(glEnable(GL_POLYGON_STIPPLE));\r
+ GL(glEnable(GL_TEXTURE_2D));\r
+ GL(glEnable(GL_BLEND));\r
+ GL(glDisable(GL_DEPTH_TEST));\r
+ GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); \r
+ GL(glClearColor(0.0, 0.0, 0.0, 0.0));\r
+ GL(glViewport(0, 0, format_desc.width, format_desc.height));\r
+ glLoadIdentity(); \r
+\r
+ renderer_ = std::make_shared<gpu_frame_renderer>(*self, format_desc);\r
+ });\r
+ }\r
+\r
+ ~implementation()\r
+ {\r
+ executor_.stop();\r
+ }\r
+ \r
+ void push(const std::vector<gpu_frame_ptr>& frames)\r
+ {\r
+ auto composite_frame = std::make_shared<gpu_composite_frame>();\r
+ boost::range::for_each(frames, std::bind(&gpu_composite_frame::add, composite_frame, std::placeholders::_1));\r
+\r
+ input_.push(composite_frame);\r
+ executor_.begin_invoke([=]\r
+ {\r
+ try\r
+ {\r
+ gpu_frame_ptr frame;\r
+ input_.pop(frame);\r
+ output_.push(renderer_->render(frame));\r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ }\r
+ }); \r
+ }\r
+ \r
+ gpu_frame_ptr pop()\r
+ {\r
+ gpu_frame_ptr frame;\r
+ output_.pop(frame);\r
+ return frame;\r
+ }\r
+ \r
+ gpu_frame_ptr do_create_frame(size_t key, const std::function<gpu_frame*()>& constructor)\r
+ {\r
+ auto& pool = writing_pools_[key];\r
+ \r
+ gpu_frame_ptr frame;\r
+ if(!pool.try_pop(frame))\r
+ {\r
+ frame = executor_.invoke([&]\r
+ {\r
+ return std::shared_ptr<gpu_frame>(constructor());\r
+ });\r
+ }\r
+ \r
+ auto destructor = [=]\r
+ {\r
+ frame->reset();\r
+ writing_pools_[key].push(frame);\r
+ };\r
+\r
+ return gpu_frame_ptr(frame.get(), [=](gpu_frame*) \r
+ {\r
+ executor_.begin_invoke(destructor);\r
+ });\r
+ }\r
+\r
+ gpu_frame_ptr create_frame(size_t width, size_t height, void* tag)\r
+ {\r
+ return do_create_frame(reinterpret_cast<size_t>(tag), [&]\r
+ {\r
+ return new gpu_frame(width, height);\r
+ });\r
+ }\r
+ \r
+ gpu_frame_ptr create_frame(const gpu_frame_desc& desc, void* tag)\r
+ {\r
+ return do_create_frame(reinterpret_cast<size_t>(tag), [&]\r
+ {\r
+ return new gpu_frame(desc);\r
+ });\r
+ }\r
+\r
+ void release_frames(void* tag)\r
+ {\r
+ writing_pools_[reinterpret_cast<size_t>(tag)].clear();\r
+ }\r
+ \r
+ typedef tbb::concurrent_bounded_queue<gpu_frame_ptr> gpu_frame_queue;\r
+ tbb::concurrent_unordered_map<size_t, gpu_frame_queue> writing_pools_;\r
+ gpu_frame_queue reading_pool_; \r
+\r
+ gpu_frame_queue input_;\r
+ gpu_frame_queue output_; \r
+ \r
+ std::unique_ptr<sf::Context> ogl_context_;\r
+ \r
+ common::executor executor_;\r
+\r
+ gpu_frame_renderer_ptr renderer_;\r
+};\r
+ \r
+#if defined(_MSC_VER)\r
+#pragma warning (disable : 4355) // 'this' : used in base member initializer list\r
+#endif\r
+\r
+gpu_frame_device::gpu_frame_device(const frame_format_desc& format_desc) : impl_(new implementation(this, format_desc)){}\r
+void gpu_frame_device::push(const std::vector<gpu_frame_ptr>& frames){ impl_->push(frames);}\r
+gpu_frame_ptr gpu_frame_device::pop(){return impl_->pop();}\r
+gpu_frame_ptr gpu_frame_device::create_frame(size_t width, size_t height, void* tag){return impl_->create_frame(width, height, tag);}\r
+gpu_frame_ptr gpu_frame_device::create_frame(const gpu_frame_desc& desc, void* tag){return impl_->create_frame(desc, tag);}\r
+void gpu_frame_device::release_frames(void* tag){impl_->release_frames(tag);}\r
+}}
\ No newline at end of file
\r
namespace caspar { namespace core {\r
\r
-class gpu_frame_processor : public frame_factory, boost::noncopyable\r
+class gpu_frame_device : public frame_factory, boost::noncopyable\r
{\r
public:\r
- gpu_frame_processor(const frame_format_desc& format_desc);\r
+ gpu_frame_device(const frame_format_desc& format_desc);\r
\r
void push(const std::vector<gpu_frame_ptr>& frames);\r
- void pop(gpu_frame_ptr& frame);\r
+ gpu_frame_ptr pop();\r
\r
void release_frames(void* tag);\r
gpu_frame_ptr create_frame(size_t width, size_t height, void* tag);\r
- gpu_frame_ptr create_frame(const planar_frame_dimension& data_size, void* tag);\r
+ gpu_frame_ptr create_frame(const gpu_frame_desc& desc, void* tag);\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
};\r
-typedef std::shared_ptr<gpu_frame_processor> gpu_frame_processor_ptr;\r
+typedef std::shared_ptr<gpu_frame_device> gpu_frame_device_ptr;\r
\r
}}
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "gpu_frame_processor.h"\r
-\r
-#include "gpu_frame_transform.h"\r
-#include "gpu_frame.h"\r
-#include "gpu_composite_frame.h"\r
-#include "frame_format.h"\r
-\r
-#include "../../common/exception/exceptions.h"\r
-#include "../../common/concurrency/executor.h"\r
-#include "../../common/utility/memory.h"\r
-#include "../../common/gl/gl_check.h"\r
-#include "../../common/gl/frame_buffer_object.h"\r
-\r
-#include <Glee.h>\r
-#include <SFML/Window.hpp>\r
-\r
-#include <tbb/concurrent_queue.h>\r
-#include <tbb/concurrent_unordered_map.h>\r
-\r
-#include <boost/lexical_cast.hpp>\r
-#include <boost/thread/once.hpp>\r
-#include <boost/thread.hpp>\r
-#include <boost/range.hpp>\r
-#include <boost/foreach.hpp>\r
-#include <boost/range/algorithm_ext/erase.hpp>\r
-#include <boost/range/algorithm.hpp>\r
-\r
-#include <functional>\r
-#include <unordered_map>\r
-#include <numeric>\r
-#include <math.h>\r
-\r
-namespace caspar { namespace core {\r
- \r
-struct gpu_frame_processor::implementation : boost::noncopyable\r
-{ \r
- implementation(const frame_format_desc& format_desc) \r
- : format_desc_(format_desc), index_(0)\r
- { \r
- input_.set_capacity(2);\r
- executor_.start();\r
- executor_.begin_invoke([=]\r
- {\r
- ogl_context_.reset(new sf::Context());\r
- ogl_context_->SetActive(true);\r
- GL(glEnable(GL_POLYGON_STIPPLE));\r
- GL(glEnable(GL_TEXTURE_2D));\r
- GL(glEnable(GL_BLEND));\r
- GL(glDisable(GL_DEPTH_TEST));\r
- GL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); \r
- GL(glClearColor(0.0, 0.0, 0.0, 0.0));\r
- GL(glViewport(0, 0, format_desc_.width, format_desc_.height));\r
- glLoadIdentity(); \r
-\r
- fbo_.create(format_desc_.width, format_desc_.height);\r
- fbo_.bind_pixel_source();\r
-\r
- writing_.resize(2, std::make_shared<gpu_composite_frame>());\r
-\r
- // Fill pipeline\r
- for(int n = 0; n < 2; ++n)\r
- composite(std::vector<gpu_frame_ptr>());\r
-\r
- transform_ = std::make_shared<gpu_frame_transform>();\r
- });\r
- }\r
-\r
- ~implementation()\r
- {\r
- executor_.stop();\r
- }\r
- \r
- void composite(std::vector<gpu_frame_ptr> frames)\r
- {\r
- boost::range::remove_erase(frames, nullptr);\r
- boost::range::remove_erase(frames, gpu_frame::null());\r
- auto composite_frame = std::make_shared<gpu_composite_frame>();\r
- boost::range::for_each(frames, std::bind(&gpu_composite_frame::add, \r
- composite_frame, \r
- std::placeholders::_1));\r
-\r
- input_.push(composite_frame);\r
- executor_.begin_invoke([=]\r
- {\r
- try\r
- {\r
- gpu_frame_ptr frame;\r
- input_.pop(frame);\r
-\r
- index_ = (index_ + 1) % 2;\r
- int next_index = (index_ + 1) % 2;\r
-\r
- // 1. Start asynchronous DMA transfer to video memory.\r
- writing_[index_] = std::move(frame); \r
- // Lock frame and give pointer ownership to OpenGL.\r
- writing_[index_]->begin_write();\r
- \r
- // 3. Output to external buffer.\r
- if(output_frame_)\r
- { \r
- output_frame_->end_read();\r
- output_.push(output_frame_);\r
- }\r
-\r
- // Clear framebuffer.\r
- GL(glClear(GL_COLOR_BUFFER_BIT)); \r
-\r
- // 2. Draw to framebuffer and start asynchronous DMA transfer \r
- // to page-locked memory.\r
- writing_[next_index]->draw(transform_);\r
- \r
- // Create an output frame\r
- auto temp_frame = create_output_frame();\r
- \r
- // Read from framebuffer into page-locked memory.\r
- temp_frame->begin_read();\r
- temp_frame->audio_data() = std::move(writing_[next_index]->audio_data());\r
-\r
- output_frame_ = temp_frame;\r
-\r
- // Return frames to pool.\r
- writing_[next_index]->end_write();\r
- writing_[next_index] = nullptr;\r
- }\r
- catch(...)\r
- {\r
- CASPAR_LOG_CURRENT_EXCEPTION();\r
- }\r
- }); \r
- }\r
-\r
- gpu_frame_ptr create_output_frame()\r
- {\r
- gpu_frame_ptr frame;\r
- if(!reading_pool_.try_pop(frame))\r
- frame.reset(new gpu_frame(format_desc_.width, format_desc_.height));\r
-\r
- return gpu_frame_ptr(frame.get(), [=](gpu_frame*)\r
- {\r
- frame->reset();\r
- reading_pool_.push(frame);\r
- });\r
- }\r
- \r
- gpu_frame_ptr do_create_frame(size_t key, const std::function<gpu_frame*()>& constructor)\r
- {\r
- auto& pool = writing_pools_[key];\r
- \r
- gpu_frame_ptr frame;\r
- if(!pool.try_pop(frame))\r
- {\r
- frame = executor_.invoke([&]\r
- {\r
- return std::shared_ptr<gpu_frame>(constructor());\r
- });\r
- }\r
- \r
- auto destructor = [=]\r
- {\r
- frame->reset();\r
- writing_pools_[key].push(frame);\r
- };\r
-\r
- return gpu_frame_ptr(frame.get(), [=](gpu_frame*) \r
- {\r
- executor_.begin_invoke(destructor);\r
- });\r
- }\r
-\r
- gpu_frame_ptr create_frame(size_t width, size_t height, void* tag)\r
- {\r
- size_t key = reinterpret_cast<size_t>(tag);\r
- return do_create_frame(key, [&]\r
- {\r
- return new gpu_frame(width, height);\r
- });\r
- }\r
- \r
- gpu_frame_ptr create_frame(const planar_frame_dimension& data_size, void* tag)\r
- {\r
- size_t key = reinterpret_cast<size_t>(tag);\r
- return do_create_frame(key, [&]\r
- {\r
- return new gpu_frame(data_size);\r
- });\r
- }\r
- \r
- void pop(gpu_frame_ptr& frame)\r
- {\r
- output_.pop(frame);\r
- }\r
-\r
- void release_frames(void* tag)\r
- {\r
- writing_pools_[reinterpret_cast<size_t>(tag)].clear();\r
- }\r
- \r
- typedef tbb::concurrent_bounded_queue<gpu_frame_ptr> gpu_frame_queue;\r
- tbb::concurrent_unordered_map<size_t, gpu_frame_queue> writing_pools_;\r
- gpu_frame_queue reading_pool_; \r
-\r
- gpu_frame_queue input_;\r
- std::vector<gpu_frame_ptr> writing_;\r
- gpu_frame_queue output_; \r
-\r
- size_t index_;\r
-\r
- gpu_frame_ptr output_frame_; \r
- frame_format_desc format_desc_;\r
- \r
- std::unique_ptr<sf::Context> ogl_context_;\r
- \r
- common::executor executor_;\r
-\r
- common::gl::frame_buffer_object fbo_;\r
-\r
- gpu_frame_transform_ptr transform_;\r
-};\r
- \r
-gpu_frame_processor::gpu_frame_processor(const frame_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
-void gpu_frame_processor::push(const std::vector<gpu_frame_ptr>& frames){ impl_->composite(frames);}\r
-void gpu_frame_processor::pop(gpu_frame_ptr& frame){impl_->pop(frame);}\r
-gpu_frame_ptr gpu_frame_processor::create_frame(size_t width, size_t height, void* tag){return impl_->create_frame(width, height, tag);}\r
-gpu_frame_ptr gpu_frame_processor::create_frame(const planar_frame_dimension& data_size, void* tag){return impl_->create_frame(data_size, tag);}\r
-void gpu_frame_processor::release_frames(void* tag){impl_->release_frames(tag);}\r
-}}
\ No newline at end of file
--- /dev/null
+#include "../StdAfx.h"\r
+\r
+#include "gpu_frame_renderer.h"\r
+\r
+#include "gpu_frame.h"\r
+\r
+#include "frame_format.h"\r
+#include "frame_factory.h"\r
+\r
+#include "../../common/exception/exceptions.h"\r
+#include "../../common/gl/utility.h"\r
+#include "../../common/gl/frame_buffer_object.h"\r
+\r
+#include <Glee.h>\r
+\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include <boost/range/algorithm_ext/erase.hpp>\r
+#include <boost/range/algorithm.hpp>\r
+\r
+#include <functional>\r
+\r
+namespace caspar { namespace core {\r
+ \r
+struct gpu_frame_renderer::implementation : boost::noncopyable\r
+{ \r
+ implementation(frame_factory& factory, const frame_format_desc& format_desc) \r
+ : factory_(factory), format_desc_(format_desc), index_(0), shader_(std::make_shared<gpu_frame_shader>(format_desc)), \r
+ writing_(2, gpu_frame::null()), output_frame_(gpu_frame::null())\r
+ { \r
+ fbo_.create(format_desc_.width, format_desc_.height);\r
+ fbo_.bind_pixel_source();\r
+ }\r
+ \r
+ gpu_frame_ptr render(const gpu_frame_ptr& frame)\r
+ {\r
+ gpu_frame_ptr result;\r
+ try\r
+ {\r
+ index_ = (index_ + 1) % 2;\r
+ int next_index = (index_ + 1) % 2;\r
+\r
+ // 1. Start asynchronous DMA transfer to video memory.\r
+ writing_[index_] = std::move(frame); \r
+ // Lock frame and give pointer ownership to OpenGL.\r
+ writing_[index_]->begin_write();\r
+ \r
+ // 3. Output to external buffer.\r
+ output_frame_->end_read();\r
+ result = output_frame_;\r
+ \r
+ // Clear framebuffer.\r
+ GL(glClear(GL_COLOR_BUFFER_BIT)); \r
+\r
+ // 2. Draw to framebuffer and start asynchronous DMA transfer \r
+ // to page-locked memory.\r
+ writing_[next_index]->draw(shader_);\r
+ \r
+ // Create an output frame\r
+ auto temp_frame = factory_.create_frame(format_desc_, this);\r
+ \r
+ // Read from framebuffer into page-locked memory.\r
+ temp_frame->begin_read();\r
+ temp_frame->audio_data() = std::move(writing_[next_index]->audio_data());\r
+\r
+ output_frame_ = temp_frame;\r
+\r
+ // Return frames to pool.\r
+ writing_[next_index]->end_write();\r
+ writing_[next_index] = nullptr;\r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ }\r
+ return result == gpu_frame::null() ? nullptr : result;;\r
+ }\r
+\r
+ size_t index_;\r
+\r
+ gpu_frame_ptr output_frame_; \r
+ frame_format_desc format_desc_;\r
+ frame_factory& factory_;\r
+\r
+ std::vector<gpu_frame_ptr> writing_;\r
+ \r
+ common::gl::frame_buffer_object fbo_;\r
+ gpu_frame_shader_ptr shader_;\r
+};\r
+ \r
+gpu_frame_renderer::gpu_frame_renderer(frame_factory& factory, const frame_format_desc& format_desc) : impl_(new implementation(factory, format_desc)){}\r
+gpu_frame_ptr gpu_frame_renderer::render(const gpu_frame_ptr& frames){ return impl_->render(frames);}\r
+}}
\ No newline at end of file
--- /dev/null
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG.\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
+*/\r
+#pragma once\r
+\r
+#include <memory>\r
+#include <vector>\r
+\r
+#include "frame_fwd.h"\r
+\r
+namespace caspar { namespace core {\r
+\r
+class gpu_frame_renderer : boost::noncopyable\r
+{\r
+public:\r
+ gpu_frame_renderer(frame_factory& factory, const frame_format_desc& format_desc_);\r
+ \r
+ gpu_frame_ptr render(const gpu_frame_ptr& frames);\r
+private:\r
+ struct implementation;\r
+ std::shared_ptr<implementation> impl_;\r
+};\r
+typedef std::shared_ptr<gpu_frame_renderer> gpu_frame_renderer_ptr;\r
+\r
+}}
\ No newline at end of file
--- /dev/null
+#include "../StdAfx.h"\r
+\r
+#include "gpu_frame_shader.h"\r
+\r
+#include "../../common/exception/exceptions.h"\r
+#include "../../common/gl/utility.h"\r
+\r
+#include <Glee.h>\r
+\r
+#include <boost/noncopyable.hpp>\r
+\r
+#include <unordered_map>\r
+\r
+namespace caspar { namespace core {\r
+ \r
+class shader_program : boost::noncopyable\r
+{\r
+public:\r
+ shader_program() : program_(0){}\r
+ shader_program(shader_program&& other) : program_(other.program_){}\r
+ shader_program& operator=(shader_program&& other) \r
+ {\r
+ program_ = other.program_; \r
+ other.program_ = 0; \r
+ return *this;\r
+ }\r
+\r
+ shader_program(const std::string& fragment_source_str) : program_(0)\r
+ {\r
+ GLint success;\r
+\r
+ try\r
+ { \r
+ const char* fragment_source = fragment_source_str.c_str();\r
+ static const char* vertex_source = \r
+ "void main()"\r
+ "{"\r
+ "gl_TexCoord[0] = gl_MultiTexCoord0;"\r
+ "gl_FrontColor = gl_Color;"\r
+ "gl_Position = ftransform();"\r
+ "}";\r
+ \r
+ auto vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);\r
+ auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);\r
+\r
+ GL(glShaderSourceARB(vertex_shader, 1, &vertex_source, NULL));\r
+ GL(glCompileShaderARB(vertex_shader));\r
+\r
+ GL(glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
+ if (success == GL_FALSE)\r
+ {\r
+ char info[2048];\r
+ GL(glGetInfoLogARB(vertex_shader, sizeof(info), 0, info));\r
+ GL(glDeleteObjectARB(vertex_shader));\r
+ GL(glDeleteObjectARB(fragmemt_shader));\r
+ GL(glDeleteObjectARB(program_));\r
+ std::stringstream str;\r
+ str << "Failed to compile vertex shader:" << std::endl << info << std::endl;\r
+ BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
+ }\r
+\r
+ GL(glShaderSourceARB(fragmemt_shader, 1, &fragment_source, NULL));\r
+ GL(glCompileShaderARB(fragmemt_shader));\r
+\r
+ GL(glGetObjectParameterivARB(fragmemt_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
+ if (success == GL_FALSE)\r
+ {\r
+ char info[2048];\r
+ GL(glGetInfoLogARB(fragmemt_shader, sizeof(info), 0, info));\r
+ GL(glDeleteObjectARB(vertex_shader));\r
+ GL(glDeleteObjectARB(fragmemt_shader));\r
+ GL(glDeleteObjectARB(program_));\r
+ std::stringstream str;\r
+ str << "Failed to compile fragment shader:" << std::endl << info << std::endl;\r
+ BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
+ }\r
+ \r
+ program_ = glCreateProgramObjectARB();\r
+\r
+ GL(glAttachObjectARB(program_, vertex_shader));\r
+ GL(glAttachObjectARB(program_, fragmemt_shader));\r
+\r
+ GL(glDeleteObjectARB(vertex_shader));\r
+ GL(glDeleteObjectARB(fragmemt_shader));\r
+\r
+ GL(glLinkProgramARB(program_));\r
+\r
+ GL(glGetObjectParameterivARB(program_, GL_OBJECT_LINK_STATUS_ARB, &success));\r
+ if (success == GL_FALSE)\r
+ {\r
+ char info[2048];\r
+ GL(glGetInfoLogARB(program_, sizeof(info), 0, info));\r
+ GL(glDeleteObjectARB(program_));\r
+ std::stringstream str;\r
+ str << "Failed to link shader program:" << std::endl << info << std::endl;\r
+ BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
+ }\r
+ GL(glUseProgramObjectARB(program_));\r
+ glUniform1i(glGetUniformLocation(program_, "plane[0]"), 0);\r
+ glUniform1i(glGetUniformLocation(program_, "plane[1]"), 1);\r
+ glUniform1i(glGetUniformLocation(program_, "plane[2]"), 2);\r
+ glUniform1i(glGetUniformLocation(program_, "plane[3]"), 3);\r
+ }\r
+ catch(...)\r
+ {\r
+ CASPAR_LOG_CURRENT_EXCEPTION();\r
+ throw;\r
+ }\r
+ }\r
+\r
+ ~shader_program()\r
+ {\r
+ glDeleteProgram(program_);\r
+ }\r
+\r
+ void use()\r
+ { \r
+ GL(glUseProgramObjectARB(program_)); \r
+ }\r
+\r
+ GLuint get_location(const std::string& name)\r
+ {\r
+ return glGetUniformLocation(program_, name.c_str());\r
+ }\r
+ \r
+private:\r
+ GLuint program_;\r
+};\r
+typedef std::shared_ptr<shader_program> shader_program_ptr;\r
+\r
+struct gpu_frame_shader::implementation\r
+{\r
+ implementation(const frame_format_desc& format_desc) \r
+ : current_(pixel_format::invalid_pixel_format), format_desc_(format_desc)\r
+ {\r
+ std::string common = \r
+ "uniform sampler2D plane[4]; "\r
+ "uniform vec4 plane_size[4]; "\r
+ \r
+ // NOTE: YCbCr, ITU-R, http://www.intersil.com/data/an/an9717.pdf \r
+ // TODO: Support for more yuv formats might be needed. \r
+ "vec4 ycbcra_to_bgra(float y, float cb, float cr, float a) "\r
+ "{ "\r
+ " vec4 color; "\r
+ " "\r
+ " cb -= 0.5; "\r
+ " cr -= 0.5; "\r
+ " y = 1.164*(y-0.0625); "\r
+ " "\r
+ " color.r = y + 1.596 * cr; "\r
+ " color.g = y - 0.813 * cr - 0.337633 * cb; "\r
+ " color.b = y + 2.017 * cb; "\r
+ " color.a = a; "\r
+ " "\r
+ " return color; "\r
+ "} ";\r
+ \r
+ shaders_[pixel_format::abgr] = common +\r
+\r
+ "void main() "\r
+ "{ "\r
+ "vec4 abgr = texture2D(plane[0], gl_TexCoord[0].st); "\r
+ "gl_FragColor = abgr.argb * gl_Color; "\r
+ "} ";\r
+ \r
+ shaders_[pixel_format::argb] = common +\r
+\r
+ "void main() " \r
+ "{ "\r
+ "vec4 argb = texture2D(plane[0], gl_TexCoord[0].st); "\r
+ "gl_FragColor = argb.grab * gl_Color; " \r
+ "} ";\r
+ \r
+ shaders_[pixel_format::bgra] = common +\r
+\r
+ "void main() "\r
+ "{ "\r
+ "vec4 bgra = texture2D(plane[0], gl_TexCoord[0].st); "\r
+ "gl_FragColor = bgra.rgba * gl_Color; "\r
+ "} ";\r
+ \r
+ shaders_[pixel_format::rgba] = common +\r
+\r
+ "void main() "\r
+ "{ "\r
+ "vec4 rgba = texture2D(plane[0], gl_TexCoord[0].st); "\r
+ "gl_FragColor = rgba.bgra * gl_Color; "\r
+ "} ";\r
+ \r
+ shaders_[pixel_format::ycbcr] = common +\r
+\r
+ "void main() "\r
+ "{ "\r
+ "float y = texture2D(plane[0], gl_TexCoord[0].st).r; "\r
+ "float cb = texture2D(plane[1], gl_TexCoord[0].st).r; "\r
+ "float cr = texture2D(plane[2], gl_TexCoord[0].st).r; "\r
+ "float a = 1.0; " \r
+ "gl_FragColor = ycbcra_to_bgra(y, cb, cr, a) * gl_Color; "\r
+ "} ";\r
+ \r
+ shaders_[pixel_format::ycbcra] = common +\r
+\r
+ "void main() "\r
+ "{ "\r
+ "float y = texture2D(plane[0], gl_TexCoord[0].st).r; "\r
+ "float cb = texture2D(plane[1], gl_TexCoord[0].st).r; "\r
+ "float cr = texture2D(plane[2], gl_TexCoord[0].st).r; "\r
+ "float a = texture2D(plane[3], gl_TexCoord[0].st).r; "\r
+ "gl_FragColor = ycbcra_to_bgra(y, cb, cr, a) * gl_Color; "\r
+ "} ";\r
+ }\r
+\r
+ void use(gpu_frame_desc& desc)\r
+ {\r
+ set_pixel_format(desc.pix_fmt);\r
+// set_size(desc);\r
+ }\r
+\r
+ void set_pixel_format(pixel_format format)\r
+ {\r
+ if(current_ == format)\r
+ return;\r
+ current_ = format;\r
+ shaders_[format].use();\r
+ }\r
+\r
+ //void set_size(gpu_frame_desc& desc)\r
+ //{\r
+ // for(int n = 0; n < 4; ++n)\r
+ // {\r
+ // std::string name = std::string("plane_size[") + boost::lexical_cast<std::string>(n) + "]";\r
+ // GL(glUniform4f(shaders_[current_].get_location(name), \r
+ // static_cast<float>(desc.planes[n].width), \r
+ // static_cast<float>(desc.planes[n].height),\r
+ // 1.0f/static_cast<float>(desc.planes[n].width),\r
+ // 1.0f/static_cast<float>(desc.planes[n].height)));\r
+ // }\r
+ //} \r
+\r
+ frame_format_desc format_desc_;\r
+ pixel_format current_;\r
+ std::unordered_map<pixel_format, shader_program> shaders_;\r
+};\r
+\r
+gpu_frame_shader::gpu_frame_shader(const frame_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
+void gpu_frame_shader::use(gpu_frame_desc& desc){impl_->use(desc);}\r
+\r
+}}
\ No newline at end of file
--- /dev/null
+#pragma once\r
+\r
+#include "frame_format.h"\r
+#include "gpu_frame_desc.h"\r
+\r
+#include <memory>\r
+#include <array>\r
+\r
+namespace caspar { namespace core {\r
+ \r
+class gpu_frame_shader\r
+{\r
+public:\r
+ gpu_frame_shader(const frame_format_desc& format_desc);\r
+ void use(gpu_frame_desc& image);\r
+\r
+private:\r
+ struct implementation;\r
+ std::shared_ptr<implementation> impl_;\r
+};\r
+typedef std::shared_ptr<gpu_frame_shader> gpu_frame_shader_ptr;\r
+\r
+}}
\ No newline at end of file
+++ /dev/null
-#include "../StdAfx.h"\r
-\r
-#include "gpu_frame_transform.h"\r
-\r
-#include "../../common/exception/exceptions.h"\r
-#include "../../common/gl/gl_check.h"\r
-\r
-#include <Glee.h>\r
-\r
-#include <fstream>\r
-#include <unordered_map>\r
-\r
-namespace caspar { namespace core {\r
- \r
-class shader_program\r
-{\r
-public:\r
- shader_program(const std::string& fragment_source_str)\r
- {\r
- try\r
- { \r
- const char* fragment_source = fragment_source_str.c_str();\r
- static const char* vertex_source = \r
- "void main()"\r
- "{"\r
- "gl_TexCoord[0] = gl_MultiTexCoord0;"\r
- "gl_FrontColor = gl_Color;"\r
- "gl_Position = ftransform();"\r
- "}";\r
-\r
- program_ = glCreateProgramObjectARB();\r
-\r
- auto vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);\r
- auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);\r
-\r
- GL(glShaderSourceARB(vertex_shader, 1, &vertex_source, NULL));\r
- GL(glShaderSourceARB(fragmemt_shader, 1, &fragment_source, NULL));\r
- GL(glCompileShaderARB(vertex_shader));\r
- GL(glCompileShaderARB(fragmemt_shader));\r
-\r
- GLint success;\r
- GL(glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
- if (success == GL_FALSE)\r
- {\r
- char log[1024];\r
- GL(glGetInfoLogARB(vertex_shader, sizeof(log), 0, log));\r
- GL(glDeleteObjectARB(vertex_shader));\r
- GL(glDeleteObjectARB(fragmemt_shader));\r
- GL(glDeleteObjectARB(program_));\r
- std::stringstream str;\r
- str << "Failed to compile vertex shader:" << std::endl << log << std::endl;\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
- }\r
- GL(glGetObjectParameterivARB(fragmemt_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\r
- if (success == GL_FALSE)\r
- {\r
- char log[1024];\r
- GL(glGetInfoLogARB(fragmemt_shader, sizeof(log), 0, log));\r
- GL(glDeleteObjectARB(vertex_shader));\r
- GL(glDeleteObjectARB(fragmemt_shader));\r
- GL(glDeleteObjectARB(program_));\r
- std::stringstream str;\r
- str << "Failed to compile fragment shader:" << std::endl << log << std::endl;\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\r
- }\r
-\r
- GL(glAttachObjectARB(program_, vertex_shader));\r
- GL(glAttachObjectARB(program_, fragmemt_shader));\r
-\r
- GL(glDeleteObjectARB(vertex_shader));\r
- GL(glDeleteObjectARB(fragmemt_shader));\r
-\r
- GL(glLinkProgramARB(program_));\r
-\r
- GL(glGetObjectParameterivARB(program_, GL_OBJECT_LINK_STATUS_ARB, &success));\r
- if (success == GL_FALSE)\r
- {\r
- char log[1024];\r
- GL(glGetInfoLogARB(program_, sizeof(log), 0, log));\r
- CASPAR_LOG(warning) << "Failed to link shader:" << std::endl\r
- << log << std::endl;\r
- GL(glDeleteObjectARB(program_));\r
- BOOST_THROW_EXCEPTION(caspar_exception());\r
- }\r
- GL(glUseProgramObjectARB(program_));\r
- glUniform1i(glGetUniformLocation(program_, "tex0"), 0);\r
- glUniform1i(glGetUniformLocation(program_, "tex1"), 1);\r
- glUniform1i(glGetUniformLocation(program_, "tex2"), 2);\r
- glUniform1i(glGetUniformLocation(program_, "tex3"), 3);\r
- }\r
- catch(...)\r
- {\r
- CASPAR_LOG_CURRENT_EXCEPTION();\r
- throw;\r
- }\r
- }\r
-\r
- void use()\r
- {\r
- GL(glUseProgramObjectARB(program_));\r
- }\r
-\r
-private:\r
- GLuint program_;\r
-};\r
-typedef std::shared_ptr<shader_program> shader_program_ptr;\r
-\r
-struct gpu_frame_transform::implementation\r
-{\r
- implementation() : current_(pixel_format::invalid_pixel_format)\r
- {\r
- std::string common = \r
- "uniform sampler2D tex0;"\r
- "uniform sampler2D tex1;"\r
- "uniform sampler2D tex2;"\r
- "uniform sampler2D tex3;"\r
-\r
- "vec4 yuva_to_bgra(float y, float u, float v, float a)"\r
- "{"\r
- "vec4 color;"\r
- \r
- "u -= 0.5;"\r
- "v -= 0.5;"\r
-\r
- "color.r = clamp(y + 1.370705 * v, 0.0 , 1.0);"\r
- "color.g = clamp(y - 0.698001 * v - 0.337633 * u, 0.0 , 1.0);"\r
- "color.b = clamp(y + 1.732446 * u, 0.0 , 1.0);"\r
- "color.a = a;"\r
-\r
- " return color;"\r
- "}";\r
-\r
- shaders_[pixel_format::abgr] = std::make_shared<shader_program>\r
- (\r
- common +\r
-\r
- "void main()"\r
- "{"\r
- "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).argb * gl_Color;"\r
- "}"\r
- );\r
- shaders_[pixel_format::argb] = std::make_shared<shader_program>\r
- (\r
- common +\r
-\r
- "void main()"\r
- "{"\r
- "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).grab * gl_Color;"\r
- "}"\r
- );\r
- shaders_[pixel_format::bgra] = std::make_shared<shader_program>\r
- (\r
- common +\r
-\r
- "void main()"\r
- "{"\r
- "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).rgba * gl_Color;"\r
- "}"\r
- );\r
- shaders_[pixel_format::rgba] = std::make_shared<shader_program>\r
- (\r
- common +\r
-\r
- "void main()"\r
- "{"\r
- "gl_FragColor = texture2D(tex0, gl_TexCoord[0].st).bgra * gl_Color;"\r
- "}"\r
- );\r
- shaders_[pixel_format::yuv] = std::make_shared<shader_program>\r
- (\r
- common +\r
-\r
- "void main()"\r
- "{"\r
- "float y = texture2D(tex0, gl_TexCoord[0].st).r;"\r
- "float u = texture2D(tex1, gl_TexCoord[0].st).r;"\r
- "float v = texture2D(tex2, gl_TexCoord[0].st).r;"\r
- "gl_FragColor = yuva_to_bgra(y, u , v, 1.0) * gl_Color;"\r
- "}"\r
- );\r
- shaders_[pixel_format::yuva] = std::make_shared<shader_program>\r
- (\r
- common +\r
-\r
- "void main()"\r
- "{"\r
- "float y = texture2D(tex0, gl_TexCoord[0].st).r;"\r
- "float u = texture2D(tex1, gl_TexCoord[0].st).r;"\r
- "float v = texture2D(tex2, gl_TexCoord[0].st).r;"\r
- "float a = texture2D(tex3, gl_TexCoord[0].st).r;"\r
- "gl_FragColor = yuva_to_bgra(y, u, v, a) * gl_Color;"\r
- "}"\r
- );\r
- }\r
-\r
- void set_pixel_format(pixel_format format)\r
- {\r
- if(current_ == format)\r
- return;\r
- current_ = format;\r
- shaders_[format]->use();\r
- }\r
-\r
- pixel_format current_;\r
- std::map<pixel_format, shader_program_ptr> shaders_;\r
-};\r
-\r
-gpu_frame_transform::gpu_frame_transform() : impl_(new implementation()){}\r
-void gpu_frame_transform::set_pixel_format(pixel_format format){impl_->set_pixel_format(format);}\r
-\r
-}}
\ No newline at end of file
+++ /dev/null
-#pragma once\r
-\r
-#include <memory>\r
-\r
-enum pixel_format\r
-{\r
- bgra = 1,\r
- rgba,\r
- argb,\r
- abgr,\r
- yuv,\r
- yuva,\r
- invalid_pixel_format,\r
-};\r
-\r
-namespace caspar { namespace core {\r
- \r
-class gpu_frame_transform\r
-{\r
-public:\r
- gpu_frame_transform();\r
- void set_pixel_format(pixel_format format);\r
-private:\r
- struct implementation;\r
- std::shared_ptr<implementation> impl_;\r
-};\r
-typedef std::shared_ptr<gpu_frame_transform> gpu_frame_transform_ptr;\r
-\r
-}}
\ No newline at end of file
factory_->release_frames(this);\r
}\r
\r
- gpu_frame_ptr get_frame()\r
+ gpu_frame_ptr render_frame()\r
{ \r
return frame_;\r
}\r
{\r
factory_ = factory;\r
frame_ = factory->create_frame(format_desc_, this);\r
- __stosd(reinterpret_cast<unsigned long*>(frame_->data()), color_value_, frame_->size() / sizeof(unsigned long));\r
+ __stosd(reinterpret_cast<unsigned long*>(frame_->data()), color_value_, format_desc_.size / sizeof(unsigned long));\r
}\r
\r
frame_factory_ptr factory_;\r
video_transformer_->initialize(factory);\r
}\r
\r
- gpu_frame_ptr get_frame()\r
+ gpu_frame_ptr render_frame()\r
{\r
while(ouput_channel_.empty() && !input_->is_eof())\r
{ \r
\r
#include <errno.h>\r
#include <system_error>\r
-\r
-#pragma warning(disable : 4482)\r
\r
namespace caspar { namespace core { namespace ffmpeg{\r
\r
\r
#include <unordered_map>\r
\r
-#if defined(_MSC_VER)\r
-#pragma warning (push)\r
-#pragma warning (disable : 4244)\r
-#endif\r
extern "C" \r
{\r
#define __STDC_CONSTANT_MACROS\r
#define __STDC_LIMIT_MACROS\r
#include <libswscale/swscale.h>\r
}\r
-#if defined(_MSC_VER)\r
-#pragma warning (pop)\r
-#endif\r
\r
namespace caspar { namespace core { namespace ffmpeg{\r
\r
case PIX_FMT_ARGB: return pixel_format::argb;\r
case PIX_FMT_RGBA: return pixel_format::rgba;\r
case PIX_FMT_ABGR: return pixel_format::abgr;\r
- case PIX_FMT_YUV444P: return pixel_format::yuv;\r
- case PIX_FMT_YUV422P: return pixel_format::yuv;\r
- case PIX_FMT_YUV420P: return pixel_format::yuv;\r
- case PIX_FMT_YUV411P: return pixel_format::yuv;\r
- case PIX_FMT_YUV410P: return pixel_format::yuv;\r
- case PIX_FMT_YUVA420P: return pixel_format::yuva;\r
+ case PIX_FMT_YUV444P: return pixel_format::ycbcr;\r
+ case PIX_FMT_YUV422P: return pixel_format::ycbcr;\r
+ case PIX_FMT_YUV420P: return pixel_format::ycbcr;\r
+ case PIX_FMT_YUV411P: return pixel_format::ycbcr;\r
+ case PIX_FMT_YUV410P: return pixel_format::ycbcr;\r
+ case PIX_FMT_YUVA420P: return pixel_format::ycbcra;\r
default: return pixel_format::invalid_pixel_format;\r
}\r
}\r
\r
struct video_transformer::implementation : boost::noncopyable\r
{\r
+ implementation() : sw_warning_(false){}\r
+\r
~implementation()\r
{\r
if(factory_)\r
video_packet->decoded_frame->data[0] + y*video_packet->decoded_frame->linesize[0], \r
width*4); \r
});\r
- video_packet->frame->set_pixel_format(get_pixel_format(pix_fmt));\r
+ video_packet->frame->pix_fmt(get_pixel_format(pix_fmt));\r
\r
break;\r
}\r
size_t size2 = dummy_pict.data[2] - dummy_pict.data[1];\r
size_t h2 = size2/dummy_pict.linesize[1];\r
\r
- planar_frame_dimension data_size;\r
- data_size[0] = std::make_pair(dummy_pict.linesize[0], height);\r
- data_size[1] = std::make_pair(dummy_pict.linesize[1], h2);\r
- data_size[2] = std::make_pair(dummy_pict.linesize[2], h2);\r
- data_size[3] = std::make_pair(0, 0);\r
+ gpu_frame_desc desc;\r
+ desc.planes[0] = plane(dummy_pict.linesize[0], height, 1);\r
+ desc.planes[1] = plane(dummy_pict.linesize[1], h2, 1);\r
+ desc.planes[2] = plane(dummy_pict.linesize[2], h2, 1);\r
+ desc.plane_count = 3;\r
\r
if(pix_fmt == PIX_FMT_YUVA420P) \r
- data_size[3] = std::make_pair(dummy_pict.linesize[3], height);\r
+ {\r
+ desc.planes[3] = plane(dummy_pict.linesize[3], height, 1);\r
+ desc.plane_count = 4;\r
+ }\r
\r
- video_packet->frame = factory_->create_frame(data_size, this);\r
- video_packet->frame->set_pixel_format(get_pixel_format(pix_fmt));\r
+ desc.pix_fmt = get_pixel_format(pix_fmt);\r
+ video_packet->frame = factory_->create_frame(desc, this);\r
\r
- tbb::parallel_for(0, static_cast<int>(data_size.size()), 1, [&](int n)\r
+ tbb::parallel_for(0, static_cast<int>(desc.plane_count), 1, [&](int n)\r
{\r
- tbb::parallel_for(0, static_cast<int>(data_size[n].second), 1, [&](int y)\r
+ tbb::parallel_for(0, static_cast<int>(desc.planes[n].height), 1, [&](int y)\r
{\r
memcpy(\r
video_packet->frame->data(n)+y*dummy_pict.linesize[n], \r
} \r
default: \r
{\r
+ if(!sw_warning_)\r
+ {\r
+ CASPAR_LOG(warning) << "Hardware accelerated color transform not supported.";\r
+ sw_warning_ = true;\r
+ }\r
video_packet->frame = factory_->create_frame(width, height, this);\r
- video_packet->frame->set_pixel_format(pixel_format::bgra);\r
\r
AVFrame av_frame; \r
avcodec_get_frame_defaults(&av_frame);\r
\r
frame_factory_ptr factory_;\r
std::shared_ptr<SwsContext> sws_context_;\r
+ bool sw_warning_;\r
};\r
\r
video_transformer::video_transformer() : impl_(new implementation()){}\r
virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Movie( \r
/* [in] */ BSTR pVal) = 0;\r
\r
- virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_FrameNum( \r
+ virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE render_frameNum( \r
/* [retval][out] */ long *pVal) = 0;\r
\r
virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_FrameNum( \r
IShockwaveFlash * This,\r
/* [in] */ BSTR pVal);\r
\r
- /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *get_FrameNum )( \r
+ /* [helpstring][propget][id] */ HRESULT ( STDMETHODCALLTYPE *render_frameNum )( \r
IShockwaveFlash * This,\r
/* [retval][out] */ long *pVal);\r
\r
#define IShockwaveFlash_put_Movie(This,pVal) \\r
(This)->lpVtbl -> put_Movie(This,pVal)\r
\r
-#define IShockwaveFlash_get_FrameNum(This,pVal) \\r
- (This)->lpVtbl -> get_FrameNum(This,pVal)\r
+#define IShockwaveFlash_render_frameNum(This,pVal) \\r
+ (This)->lpVtbl -> render_frameNum(This,pVal)\r
\r
#define IShockwaveFlash_put_FrameNum(This,pVal) \\r
(This)->lpVtbl -> put_FrameNum(This,pVal)\r
DWORD *_pdwStubPhase);\r
\r
\r
-/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_get_FrameNum_Proxy( \r
+/* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_render_frameNum_Proxy( \r
IShockwaveFlash * This,\r
/* [retval][out] */ long *pVal);\r
\r
\r
-void __RPC_STUB IShockwaveFlash_get_FrameNum_Stub(\r
+void __RPC_STUB IShockwaveFlash_render_frameNum_Stub(\r
IRpcStubBuffer *This,\r
IRpcChannelBuffer *_pRpcChannelBuffer,\r
PRPC_MESSAGE _pRpcMessage,\r
bitmapInfo.bmiHeader.biClrImportant = 0;\r
bitmapInfo.bmiHeader.biClrUsed = 0;\r
bitmapInfo.bmiHeader.biCompression = BI_RGB;\r
+#ifdef _MSC_VER\r
#pragma warning(disable:4146)\r
+#endif\r
bitmapInfo.bmiHeader.biHeight = -height;\r
+#ifdef _MSC_VER\r
#pragma warning(default:4146)\r
+#endif\r
bitmapInfo.bmiHeader.biPlanes = 1;\r
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFO);\r
bitmapInfo.bmiHeader.biWidth = width;\r
flash_producer_->param(proxy_->invoke(layer, label));\r
}\r
\r
- gpu_frame_ptr get_frame()\r
+ gpu_frame_ptr render_frame()\r
{\r
- return flash_producer_ ? flash_producer_->get_frame() : nullptr;\r
+ return flash_producer_ ? flash_producer_->render_frame() : nullptr;\r
}\r
\r
void initialize(const frame_factory_ptr& factory)\r
}\r
\r
cg_producer::cg_producer(const frame_format_desc& fmtDesc) : impl_(new implementation(fmtDesc)){}\r
-gpu_frame_ptr cg_producer::get_frame(){return impl_->get_frame();}\r
+gpu_frame_ptr cg_producer::render_frame(){return impl_->render_frame();}\r
void cg_producer::clear(){impl_->clear();}\r
void cg_producer::add(int layer, const std::wstring& templateName, bool playOnLoad, const std::wstring& startFromLabel, const std::wstring& data){impl_->add(layer, templateName, playOnLoad, startFromLabel, data);}\r
void cg_producer::remove(int layer){impl_->remove(layer);}\r
public:\r
cg_producer(const frame_format_desc& format_desc);\r
\r
- gpu_frame_ptr get_frame();\r
+ gpu_frame_ptr render_frame();\r
\r
void clear();\r
void add(int layer, const std::wstring& template_name, bool play_on_load, const std::wstring& start_from_label = TEXT(""), const std::wstring& data = TEXT(""));\r
\r
using namespace boost::assign;\r
\r
-// NOTE: This is needed in order to make CComObject work since this is not a real ATL project\r
+// NOTE: This is needed in order to make CComObject work since this is not a real ATL project.\r
CComModule _AtlModule;\r
extern __declspec(selectany) CAtlModule* _pAtlModule = &_AtlModule;\r
\r
: flashax_container_(nullptr), filename_(filename), self_(self), format_desc_(format_desc),\r
bitmap_pool_(new bitmap_pool), executor_([=]{run();}), invalid_count_(0)\r
{ \r
- if(!boost::filesystem::exists(filename))\r
- BOOST_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(common::narrow(filename)));\r
+ if(!boost::filesystem::exists(filename))\r
+ BOOST_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(common::narrow(filename)));\r
\r
frame_buffer_.set_capacity(flash_producer::DEFAULT_BUFFER_SIZE); \r
}\r
gpu_frame_ptr result;\r
\r
if(is_progressive) \r
- result = render_frame(); \r
+ result = do_render_frame(); \r
else\r
{\r
- gpu_frame_ptr frame1 = render_frame();\r
- gpu_frame_ptr frame2 = render_frame();\r
+ gpu_frame_ptr frame1 = do_render_frame();\r
+ gpu_frame_ptr frame2 = do_render_frame();\r
result = gpu_composite_frame::interlace(frame1, frame2, format_desc_.mode);\r
}\r
\r
}\r
}\r
\r
- gpu_frame_ptr render_frame()\r
+ gpu_frame_ptr do_render_frame()\r
{\r
flashax_container_->Tick();\r
invalid_count_ = !flashax_container_->InvalidRectangle() ? std::min(2, invalid_count_+1) : 0;\r
return frame;\r
}\r
\r
- gpu_frame_ptr get_frame()\r
+ gpu_frame_ptr render_frame()\r
{\r
if(!frame_buffer_.try_pop(last_frame_) && is_empty_)\r
return gpu_frame::null();\r
};\r
\r
flash_producer::flash_producer(const std::wstring& filename, const frame_format_desc& format_desc) : impl_(new implementation(this, filename, format_desc)){}\r
-gpu_frame_ptr flash_producer::get_frame(){return impl_->get_frame();}\r
+gpu_frame_ptr flash_producer::render_frame(){return impl_->render_frame();}\r
void flash_producer::param(const std::wstring& param){impl_->param(param);}\r
const frame_format_desc& flash_producer::get_frame_format_desc() const { return impl_->format_desc_; } \r
void flash_producer::initialize(const frame_factory_ptr& factory) { impl_->initialize(factory);}\r
\r
std::wstring flash_producer::find_template(const std::wstring& template_name)\r
{\r
- if(boost::filesystem::exists(template_name + TEXT(".ft"))) \r
- return template_name + TEXT(".ft");\r
+ if(boost::filesystem::exists(template_name + L".ft")) \r
+ return template_name + L".ft";\r
\r
- if(boost::filesystem::exists(template_name + TEXT(".ct")))\r
- return template_name + TEXT(".ct");\r
+ if(boost::filesystem::exists(template_name + L".ct"))\r
+ return template_name + L".ct";\r
\r
- return TEXT("");\r
+ return L"";\r
}\r
\r
flash_producer_ptr create_flash_producer(const std::vector<std::wstring>& params, const frame_format_desc& format_desc)\r
{\r
// TODO: Check for flash support\r
auto filename = params[0];\r
- std::wstring result_filename = common::find_file(server::media_folder() + filename, \r
- list_of(L"swf"));\r
+ std::wstring result_filename = common::find_file(server::media_folder() + filename, list_of(L"swf"));\r
\r
return result_filename.empty() ? nullptr : std::make_shared<flash_producer>(result_filename, format_desc);\r
}\r
static const int STOP_TIMEOUT = 2000;\r
\r
flash_producer(const std::wstring& filename, const frame_format_desc& format_desc);\r
- gpu_frame_ptr get_frame();\r
+ gpu_frame_ptr render_frame();\r
const frame_format_desc& get_frame_format_desc() const;\r
void initialize(const frame_factory_ptr& factory);\r
\r
{\r
public:\r
virtual ~frame_producer(){} \r
- virtual gpu_frame_ptr get_frame() = 0;\r
+\r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ /// \fn virtual gpu_frame_ptr :::render_frame() = 0;\r
+ ///\r
+ /// \brief Renders a frame.\r
+ /// \r
+ /// \note This function is run in through the tbb task_schedular and shall be *non blocking*.\r
+ ///\r
+ /// \return The frame. \r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ virtual gpu_frame_ptr render_frame() = 0;\r
+\r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ /// \fn virtual std::shared_ptr<frame_producer> :::get_following_producer() const\r
+ ///\r
+ /// \brief Gets the producer which will replace the current producer on EOF. \r
+ ///\r
+ /// \return The following producer, or nullptr if there is no following producer. \r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
virtual std::shared_ptr<frame_producer> get_following_producer() const { return nullptr; }\r
- virtual void set_leading_producer(const std::shared_ptr<frame_producer>&) {}\r
+\r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ /// \fn virtual void :::set_leading_producer(const std::shared_ptr<frame_producer>& producer)\r
+ ///\r
+ /// \brief Sets the producer which was run before the current producer. \r
+ ///\r
+ /// \param producer The leading producer.\r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ virtual void set_leading_producer(const std::shared_ptr<frame_producer>& /*producer*/) {}\r
+\r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ /// \fn virtual const frame_format_desc& :::get_frame_format_desc() const = 0;\r
+ ///\r
+ /// \brief Gets the frame format description. \r
+ ///\r
+ /// \return The frame format description. \r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
virtual const frame_format_desc& get_frame_format_desc() const = 0;\r
+\r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ /// \fn virtual void :::initialize(const frame_factory_ptr& factory) = 0;\r
+ ///\r
+ /// \brief Provides the frame factory used to create frames and initializes the producer. \r
+ ///\r
+ /// \param factory The frame factory. \r
+ ////////////////////////////////////////////////////////////////////////////////////////////////////\r
virtual void initialize(const frame_factory_ptr& factory) = 0;\r
};\r
typedef std::shared_ptr<frame_producer> frame_producer_ptr;\r
factory_->release_frames(this);\r
}\r
\r
- gpu_frame_ptr get_frame(){return frame_;}\r
+ gpu_frame_ptr render_frame(){return frame_;}\r
\r
void initialize(const frame_factory_ptr& factory)\r
{\r
\r
FreeImage_FlipVertical(bitmap.get());\r
frame_ = factory->create_frame(format_desc_, this);\r
- common::aligned_parallel_memcpy(frame_->data(), FreeImage_GetBits(bitmap.get()), frame_->size());\r
+ common::aligned_parallel_memcpy(frame_->data(), FreeImage_GetBits(bitmap.get()), format_desc_.size);\r
}\r
\r
const frame_format_desc& get_frame_format_desc() const { return format_desc_; } \r
common::aligned_parallel_memcpy(&image_.get()[i * image_width_ * 4], &pBits[i* width * 4], width * 4);\r
}\r
\r
- gpu_frame_ptr render_frame()\r
+ gpu_frame_ptr do_render_frame()\r
{\r
gpu_frame_ptr frame = factory_->create_frame(format_desc_, this);\r
- common::clear(frame->data(), frame->size());\r
+ common::clear(frame->data(), format_desc_.size);\r
\r
const int delta_x = direction_ == direction::Left ? speed_ : -speed_;\r
const int delta_y = direction_ == direction::Up ? speed_ : -speed_;\r
return frame;\r
}\r
\r
- gpu_frame_ptr get_frame()\r
+ gpu_frame_ptr render_frame()\r
{ \r
if(format_desc_.mode != video_mode::progressive) \r
{\r
gpu_frame_ptr frame1;\r
gpu_frame_ptr frame2;\r
- tbb::parallel_invoke([&]{ frame1 = render_frame(); }, [&]{ frame2 = render_frame(); });\r
+ tbb::parallel_invoke([&]{ frame1 = do_render_frame(); }, [&]{ frame2 = do_render_frame(); });\r
return gpu_composite_frame::interlace(frame1, frame2, format_desc_.mode);\r
} \r
\r
source_producer_ = producer;\r
}\r
\r
- gpu_frame_ptr get_frame()\r
+ gpu_frame_ptr render_frame()\r
{\r
if(current_frame_++ >= info_.duration)\r
return nullptr;\r
\r
tbb::parallel_invoke\r
(\r
- [&]{dest = get_frame(dest_producer_);},\r
- [&]{source = get_frame(source_producer_);}\r
+ [&]{dest = render_frame(dest_producer_);},\r
+ [&]{source = render_frame(source_producer_);}\r
);\r
\r
return compose(dest, source);\r
}\r
\r
- gpu_frame_ptr get_frame(frame_producer_ptr& producer)\r
+ gpu_frame_ptr render_frame(frame_producer_ptr& producer)\r
{\r
if(producer == nullptr)\r
return nullptr;\r
gpu_frame_ptr frame;\r
try\r
{\r
- frame = producer->get_frame();\r
+ frame = producer->render_frame();\r
}\r
catch(...)\r
{\r
following->initialize(factory_);\r
following->set_leading_producer(producer);\r
producer = following;\r
- return get_frame(producer);\r
+ return render_frame(producer);\r
}\r
return frame;\r
}\r
\r
transition_producer::transition_producer(const frame_producer_ptr& dest, const transition_info& info, const frame_format_desc& format_desc) \r
: impl_(new implementation(dest, info, format_desc)){}\r
-gpu_frame_ptr transition_producer::get_frame(){return impl_->get_frame();}\r
+gpu_frame_ptr transition_producer::render_frame(){return impl_->render_frame();}\r
frame_producer_ptr transition_producer::get_following_producer() const{return impl_->get_following_producer();}\r
void transition_producer::set_leading_producer(const frame_producer_ptr& producer) { impl_->set_leading_producer(producer); }\r
const frame_format_desc& transition_producer::get_frame_format_desc() const { return impl_->format_desc_; } \r
public:\r
transition_producer(const frame_producer_ptr& destination, const transition_info& info, const frame_format_desc& fmt);\r
\r
- gpu_frame_ptr get_frame();\r
+ gpu_frame_ptr render_frame();\r
\r
frame_producer_ptr get_following_producer() const;\r
void set_leading_producer(const frame_producer_ptr& producer);\r
public:\r
video_sync_clock(const frame_format_desc& format_desc)\r
{\r
- period_ = static_cast<long>(get_frame_format_period(format_desc)*1000000.0);\r
+ period_ = static_cast<long>(render_frame_format_period(format_desc)*1000000.0);\r
time_ = boost::posix_time::microsec_clock::local_time();\r
}\r
\r
auto remaining = boost::posix_time::microseconds(period_) - \r
(boost::posix_time::microsec_clock::local_time() - time_);\r
if(remaining > boost::posix_time::microseconds(5000))\r
- boost::this_thread::sleep(remaining - \r
- boost::posix_time::microseconds(5000));\r
+ boost::this_thread::sleep(remaining - boost::posix_time::microseconds(5000));\r
time_ = boost::posix_time::microsec_clock::local_time();\r
}\r
private:\r
{\r
if(consumers.empty())\r
BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("consumer") \r
- << msg_info("display_device requires atleast one consumer"));\r
+ << msg_info("display_device requires atleast one consumer."));\r
\r
if(std::any_of(consumers.begin(), consumers.end(), \r
[&](const frame_consumer_ptr& pConsumer)\r
\r
void run()\r
{\r
- CASPAR_LOG(info) << L"Started display_device thread";\r
+ CASPAR_LOG(info) << L"Started display_device thread.";\r
win32_exception::install_handler();\r
\r
video_sync_clock clock(fmt_);\r
gpu_frame_ptr frame;\r
if(!frame_buffer_.try_pop(frame))\r
{\r
- CASPAR_LOG(trace) << "Display Buffer Underrun";\r
+ CASPAR_LOG(trace) << "Display Buffer Underrun.";\r
frame_buffer_.pop(frame);\r
}\r
if(frame != nullptr) \r
display_frame(frame); \r
}\r
\r
- CASPAR_LOG(info) << L"Ended display_device thread";\r
+ CASPAR_LOG(info) << L"Ended display_device thread.";\r
}\r
\r
void display_frame(const gpu_frame_ptr& frame)\r
{\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
boost::range::remove_erase(consumers_, consumer);\r
- CASPAR_LOG(warning) << "Removed consumer from render-device.";\r
+ CASPAR_LOG(warning) << "Removed consumer from display_device.";\r
if(consumers_.empty())\r
{\r
- CASPAR_LOG(warning) \r
- << "No consumers available. Shutting down display-device.";\r
+ CASPAR_LOG(warning) << "No consumers available. Shutting down display_device.";\r
is_running_ = false;\r
}\r
}\r
background_ = frame_producer;\r
if(option == load_option::preview) \r
{\r
- last_frame_ = frame_producer->get_frame();\r
+ last_frame_ = frame_producer->render_frame();\r
if(last_frame_ != nullptr)\r
last_frame_->audio_data().clear(); // No audio\r
active_ = nullptr; \r
last_frame_ = nullptr;\r
}\r
\r
- gpu_frame_ptr get_frame()\r
+ gpu_frame_ptr render_frame()\r
{ \r
if(!active_ || is_paused_)\r
return last_frame_;\r
\r
try\r
{\r
- last_frame_ = active_->get_frame();\r
+ last_frame_ = active_->render_frame();\r
+\r
+ if(last_frame_ == nullptr)\r
+ {\r
+ active_ = active_->get_following_producer();\r
+ last_frame_ = render_frame();\r
+ }\r
}\r
catch(...)\r
{\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
active_ = nullptr;\r
- last_frame_ = nullptr;\r
CASPAR_LOG(warning) << "Removed producer from layer.";\r
}\r
\r
- if(last_frame_ == nullptr && active_ != nullptr)\r
- {\r
- active_ = active_->get_following_producer();\r
- last_frame_ = get_frame();\r
- }\r
return last_frame_;\r
} \r
\r
void layer::pause(){impl_->pause();}\r
void layer::stop(){impl_->stop();}\r
void layer::clear(){impl_->clear();}\r
-gpu_frame_ptr layer::get_frame() {return impl_->get_frame();}\r
+gpu_frame_ptr layer::render_frame() {return impl_->render_frame();}\r
frame_producer_ptr layer::active() const { return impl_->active_;}\r
frame_producer_ptr layer::background() const { return impl_->background_;}\r
}}}
\ No newline at end of file
frame_producer_ptr active() const;\r
frame_producer_ptr background() const;\r
\r
- gpu_frame_ptr get_frame();\r
+ gpu_frame_ptr render_frame();\r
private:\r
struct implementation;\r
std::shared_ptr<implementation> impl_;\r
#include "..\StdAfx.h"\r
\r
-#ifdef _MSC_VER\r
-#pragma warning (disable : 4244)\r
-#endif\r
-\r
#include "render_device.h"\r
\r
#include "display_device.h"\r
#include "layer.h"\r
\r
#include "../frame/frame_format.h"\r
-#include "../frame/gpu_frame_processor.h"\r
+#include "../frame/gpu_frame_device.h"\r
\r
#include "../../common/utility/scope_exit.h"\r
#include "../../common/utility/memory.h"\r
auto it = layers.begin();\r
std::advance(it, r.begin());\r
for(size_t i = r.begin(); i != r.end(); ++i, ++it)\r
- frames[i] = it->second.get_frame();\r
+ frames[i] = it->second.render_frame();\r
}); \r
return frames;\r
}\r
\r
struct render_device::implementation : boost::noncopyable\r
{ \r
- implementation(const frame_format_desc& format_desc, unsigned int index, \r
- const std::vector<frame_consumer_ptr>& consumers) \r
- : display_device_(new display_device(format_desc, consumers)), \r
- fmt_(format_desc), \r
- frame_processor_(new gpu_frame_processor(format_desc))\r
+ implementation(const frame_format_desc& format_desc, const std::vector<frame_consumer_ptr>& consumers) \r
+ : display_device_(new display_device(format_desc, consumers)), fmt_(format_desc), frame_processor_(new gpu_frame_device(format_desc))\r
{ \r
is_running_ = true;\r
\r
}\r
frame_processor_->push(next_frames);\r
\r
- gpu_frame_ptr frame; \r
- frame_processor_->pop(frame);\r
+ gpu_frame_ptr frame = frame_processor_->pop(); \r
display_device_->display(frame);\r
}\r
catch(...)\r
{\r
CASPAR_LOG_CURRENT_EXCEPTION();\r
layers_.clear();\r
- CASPAR_LOG(error) \r
- << "Unexpected exception. Cleared layers in render-device";\r
+ CASPAR_LOG(error) << "Unexpected exception. Cleared layers in render-device";\r
}\r
}\r
\r
void load(int render_layer, const frame_producer_ptr& producer, load_option option)\r
{\r
if(producer->get_frame_format_desc() != fmt_)\r
- BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("pProducer") \r
- << msg_info("Invalid frame format"));\r
+ BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("producer") << msg_info("Invalid frame format"));\r
\r
producer->initialize(frame_processor_);\r
tbb::mutex::scoped_lock lock(layers_mutex_);\r
\r
tbb::atomic<bool> is_running_; \r
\r
- gpu_frame_processor_ptr frame_processor_;\r
+ gpu_frame_device_ptr frame_processor_;\r
};\r
\r
-render_device::render_device(const frame_format_desc& format_desc, unsigned int index, const std::vector<frame_consumer_ptr>& consumers) \r
- : impl_(new implementation(format_desc, index, consumers)){}\r
+render_device::render_device(const frame_format_desc& format_desc, const std::vector<frame_consumer_ptr>& consumers) \r
+ : impl_(new implementation(format_desc, consumers)){}\r
void render_device::load(int render_layer, const frame_producer_ptr& pProducer, load_option option){impl_->load(render_layer, pProducer, option);}\r
void render_device::pause(int render_layer){impl_->pause(render_layer);}\r
void render_device::play(int render_layer){impl_->play(render_layer);}\r
class render_device : boost::noncopyable\r
{ \r
public:\r
- render_device(const frame_format_desc& format_desc, unsigned int index, \r
- const std::vector<frame_consumer_ptr>& consumers);\r
+ render_device(const frame_format_desc& format_desc, const std::vector<frame_consumer_ptr>& consumers);\r
\r
- void load(int render_layer, const frame_producer_ptr& producer, \r
- load_option option = load_option::none); \r
+ void load(int render_layer, const frame_producer_ptr& producer, load_option option = load_option::none); \r
void pause(int render_layer);\r
void play(int render_layer);\r
void stop(int render_layer);\r
}\r
}\r
\r
- channels_.push_back(std::make_shared<renderer::render_device>(format_desc, channels_.size() + 1, consumers));\r
+ channels_.push_back(std::make_shared<renderer::render_device>(format_desc, consumers));\r
}\r
}\r
\r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<root>\r
- <rdmgr>\r
- <buildNumber type="s32_t">114808</buildNumber>\r
- <hostname>vaxtestcaspar</hostname>\r
- <os>windows</os>\r
- <product>Intel® Parallel Amplifier 2011</product>\r
- <timestamp type="u64_t">1288973781</timestamp>\r
- <variables>\r
- <at>hs</at>\r
- </variables>\r
- </rdmgr>\r
-</root>\r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<root>\r
- <rdmgr>\r
- <buildNumber type="s32_t">114808</buildNumber>\r
- <hostname>vaxtestcaspar</hostname>\r
- <os>windows</os>\r
- <product>Intel® Parallel Amplifier 2011</product>\r
- <timestamp type="u64_t">1289002710</timestamp>\r
- <variables>\r
- <at>hs</at>\r
- </variables>\r
- </rdmgr>\r
-</root>\r
+++ /dev/null
-<?xml version="1.0" encoding="UTF-8"?>\r
-<root>\r
- <rdmgr>\r
- <buildNumber type="s32_t">114808</buildNumber>\r
- <hostname>vaxtestcaspar</hostname>\r
- <os>windows</os>\r
- <product>Intel® Parallel Amplifier 2011</product>\r
- <timestamp type="u64_t">1289002916</timestamp>\r
- <variables>\r
- <at>hs</at>\r
- </variables>\r
- </rdmgr>\r
-</root>\r
<None Include="caspar.config">\r
<SubType>Designer</SubType>\r
</None>\r
- <None Include="My Amplifier Results\r000hs\r000hs.ampl" />\r
- <None Include="My Amplifier Results\r001hs\r001hs.ampl" />\r
- <None Include="My Amplifier Results\r002hs\r002hs.ampl" />\r
</ItemGroup>\r
<PropertyGroup Label="Globals">\r
<ProjectGuid>{8C26C94F-8092-4769-8D84-DEA479721C5B}</ProjectGuid>\r
<DataExecutionPrevention>\r
</DataExecutionPrevention>\r
<TargetMachine>MachineX86</TargetMachine>\r
+ <LinkTimeCodeGeneration>\r
+ </LinkTimeCodeGeneration>\r
</Link>\r
<PostBuildEvent>\r
<Command>\r
</ItemGroup>\r
<ItemGroup>\r
<None Include="caspar.config" />\r
- <None Include="My Amplifier Results\r000hs\r000hs.ampl">\r
- <Filter>My Amplifier Results</Filter>\r
- </None>\r
- <None Include="My Amplifier Results\r001hs\r001hs.ampl">\r
- <Filter>My Amplifier Results</Filter>\r
- </None>\r
- <None Include="My Amplifier Results\r002hs\r002hs.ampl">\r
- <Filter>My Amplifier Results</Filter>\r
- </None>\r
</ItemGroup>\r
<ItemGroup>\r
<Filter Include="My Amplifier Results">\r
mock_frame_producer(bool null = false, bool throws = false) \r
: null_(null), throws_(throws), initialized_(false), volume_(100){}\r
void set_volume(short volume) { volume_ = volume;}\r
- gpu_frame_ptr get_frame()\r
+ gpu_frame_ptr render_frame()\r
{ \r
if(throws_)\r
BOOST_THROW_EXCEPTION(caspar_exception());\r
if(leading_)\r
- return leading_->get_frame();\r
+ return leading_->render_frame();\r
if(!null_)\r
return std::make_shared<mock_frame>(this, volume_);\r
return nullptr;\r
transition_producer producer(nullptr, transition_info(), test_format);\r
producer.set_leading_producer(source);\r
\r
- ASSERT_TRUE(producer.get_frame() == nullptr);\r
+ ASSERT_TRUE(producer.render_frame() == nullptr);\r
}\r
\r
TEST(transition_producer, null_source_get_frame_cut) \r
\r
transition_producer producer(dest, info, test_format);\r
\r
- ASSERT_TRUE(producer.get_frame() == nullptr);\r
+ ASSERT_TRUE(producer.render_frame() == nullptr);\r
}\r
\r
TEST(transition_producer, initialize)\r
\r
for(int n = 0; n < info.duration; ++n)\r
{\r
- auto frame = producer.get_frame();\r
+ auto frame = producer.render_frame();\r
ASSERT_TRUE(std::static_pointer_cast<mock_frame>(frame)->tag == source.get());\r
}\r
- ASSERT_TRUE(producer.get_frame() == nullptr);\r
+ ASSERT_TRUE(producer.render_frame() == nullptr);\r
}
\ No newline at end of file