]> git.sesse.net Git - casparcg/commitdiff
## Refactoring of rendering pipeline and mixer.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 25 Jan 2012 01:00:00 +0000 (01:00 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 25 Jan 2012 01:00:00 +0000 (01:00 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.1.0@2156 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

63 files changed:
casparcg.sln
common/common.vcxproj
common/common.vcxproj.filters
common/concurrency/executor.h
common/concurrency/target.h [deleted file]
common/reactive.h [new file with mode: 0644]
core/consumer/frame_consumer.cpp
core/consumer/frame_consumer.h
core/consumer/output.cpp
core/consumer/output.h
core/core.vcxproj
core/core.vcxproj.filters
core/frame.h [new file with mode: 0644]
core/mixer/audio/audio_mixer.cpp
core/mixer/audio/audio_mixer.h
core/mixer/gpu/accelerator.cpp [moved from core/mixer/gpu/ogl_device.cpp with 76% similarity]
core/mixer/gpu/accelerator.h [moved from core/mixer/gpu/ogl_device.h with 88% similarity]
core/mixer/gpu/device_buffer.cpp [deleted file]
core/mixer/gpu/host_buffer.cpp [deleted file]
core/mixer/gpu/host_buffer.h [deleted file]
core/mixer/gpu/image/blending_glsl.h [moved from core/mixer/image/shader/blending_glsl.h with 100% similarity]
core/mixer/gpu/image/image_kernel.cpp [moved from core/mixer/image/image_kernel.cpp with 93% similarity]
core/mixer/gpu/image/image_kernel.h [moved from core/mixer/image/image_kernel.h with 88% similarity]
core/mixer/gpu/image/image_mixer.cpp [moved from core/mixer/image/image_mixer.cpp with 88% similarity]
core/mixer/gpu/image/image_mixer.h [moved from core/mixer/gpu/device_buffer.h with 60% similarity]
core/mixer/gpu/image/image_shader.cpp [moved from core/mixer/image/shader/image_shader.cpp with 95% similarity]
core/mixer/gpu/image/image_shader.h [moved from core/mixer/image/shader/image_shader.h with 83% similarity]
core/mixer/gpu/shader.cpp [deleted file]
core/mixer/gpu/shader.h [deleted file]
core/mixer/image/blend_modes.cpp [deleted file]
core/mixer/image/blend_modes.h [deleted file]
core/mixer/image/image_mixer.h
core/mixer/mixer.cpp
core/mixer/mixer.h
core/mixer/read_frame.cpp
core/mixer/read_frame.h
core/mixer/write_frame.cpp
core/mixer/write_frame.h
core/producer/channel/channel_producer.cpp [deleted file]
core/producer/frame/frame_factory.h
core/producer/frame_producer.cpp
core/producer/playlist/playlist_producer.cpp [deleted file]
core/producer/playlist/playlist_producer.h [deleted file]
core/producer/stage.cpp
core/producer/stage.h
core/video_channel.cpp
core/video_channel.h
modules/bluefish/consumer/bluefish_consumer.cpp
modules/decklink/consumer/decklink_consumer.cpp
modules/ffmpeg/consumer/ffmpeg_consumer.cpp
modules/ffmpeg/producer/util/util.cpp
modules/image/consumer/image_consumer.cpp
modules/oal/consumer/oal_consumer.cpp
modules/ogl/consumer/ogl_consumer.cpp
modules/reroute/producer/reroute_producer.cpp [new file with mode: 0644]
modules/reroute/producer/reroute_producer.h [moved from core/producer/channel/channel_producer.h with 68% similarity]
modules/reroute/reroute.vcxproj.filters [new file with mode: 0644]
modules/reroute/stdafx.cpp [new file with mode: 0644]
modules/reroute/stdafx.h [new file with mode: 0644]
protocol/amcp/AMCPCommandsImpl.cpp
protocol/protocol.vcxproj
shell/server.cpp
shell/shell.vcxproj

index d9841e1b11f0ec0d2beb22911e2c156672ba8919..07e2669498156e7edd3fc0254df40e7a47c96cec 100644 (file)
@@ -31,60 +31,142 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "image", "modules\image\imag
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "common", "common\common.vcxproj", "{02308602-7FE0-4253-B96E-22134919F56A}"\r
 EndProject\r
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "reroute", "modules\reroute\reroute.vcxproj", "{7D58BD57-FDD5-46E6-A23B-ED14B5314A0E}"\r
+EndProject\r
 Global\r
        GlobalSection(SubversionScc) = preSolution\r
                Svn-Managed = True\r
                Manager = AnkhSVN - Subversion Support for Visual Studio\r
        EndGlobalSection\r
        GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+               Debug|Mixed Platforms = Debug|Mixed Platforms\r
+               Debug|Win32 = Debug|Win32\r
                Debug|x64 = Debug|x64\r
+               Release|Mixed Platforms = Release|Mixed Platforms\r
+               Release|Win32 = Release|Win32\r
                Release|x64 = Release|x64\r
        EndGlobalSection\r
        GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Debug|Win32.ActiveCfg = Debug|x64\r
                {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Debug|x64.ActiveCfg = Debug|x64\r
                {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Debug|x64.Build.0 = Debug|x64\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Release|Mixed Platforms.Build.0 = Release|x64\r
+               {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Release|Win32.ActiveCfg = Release|x64\r
                {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Release|x64.ActiveCfg = Release|x64\r
                {79388C20-6499-4BF6-B8B9-D8C33D7D4DDD}.Release|x64.Build.0 = Release|x64\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Debug|Win32.ActiveCfg = Debug|x64\r
                {8C26C94F-8092-4769-8D84-DEA479721C5B}.Debug|x64.ActiveCfg = Debug|x64\r
                {8C26C94F-8092-4769-8D84-DEA479721C5B}.Debug|x64.Build.0 = Debug|x64\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Release|Mixed Platforms.Build.0 = Release|x64\r
+               {8C26C94F-8092-4769-8D84-DEA479721C5B}.Release|Win32.ActiveCfg = Release|x64\r
                {8C26C94F-8092-4769-8D84-DEA479721C5B}.Release|x64.ActiveCfg = Release|x64\r
                {8C26C94F-8092-4769-8D84-DEA479721C5B}.Release|x64.Build.0 = Release|x64\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Debug|Win32.ActiveCfg = Debug|x64\r
                {2040B361-1FB6-488E-84A5-38A580DA90DE}.Debug|x64.ActiveCfg = Debug|x64\r
                {2040B361-1FB6-488E-84A5-38A580DA90DE}.Debug|x64.Build.0 = Debug|x64\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Release|Mixed Platforms.Build.0 = Release|x64\r
+               {2040B361-1FB6-488E-84A5-38A580DA90DE}.Release|Win32.ActiveCfg = Release|x64\r
                {2040B361-1FB6-488E-84A5-38A580DA90DE}.Release|x64.ActiveCfg = Release|x64\r
                {2040B361-1FB6-488E-84A5-38A580DA90DE}.Release|x64.Build.0 = Release|x64\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Debug|Win32.ActiveCfg = Debug|x64\r
                {69313D25-9F54-4FC9-9872-628A4DD79464}.Debug|x64.ActiveCfg = Debug|x64\r
                {69313D25-9F54-4FC9-9872-628A4DD79464}.Debug|x64.Build.0 = Debug|x64\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Release|Mixed Platforms.Build.0 = Release|x64\r
+               {69313D25-9F54-4FC9-9872-628A4DD79464}.Release|Win32.ActiveCfg = Release|x64\r
                {69313D25-9F54-4FC9-9872-628A4DD79464}.Release|x64.ActiveCfg = Release|x64\r
                {69313D25-9F54-4FC9-9872-628A4DD79464}.Release|x64.Build.0 = Release|x64\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Debug|Win32.ActiveCfg = Debug|x64\r
                {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Debug|x64.ActiveCfg = Debug|x64\r
                {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Debug|x64.Build.0 = Debug|x64\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Release|Mixed Platforms.Build.0 = Release|x64\r
+               {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Release|Win32.ActiveCfg = Release|x64\r
                {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Release|x64.ActiveCfg = Release|x64\r
                {D3611658-8F54-43CF-B9AF-A5CF8C1102EA}.Release|x64.Build.0 = Release|x64\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Debug|Win32.ActiveCfg = Debug|x64\r
                {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Debug|x64.ActiveCfg = Debug|x64\r
                {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Debug|x64.Build.0 = Debug|x64\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Release|Mixed Platforms.Build.0 = Release|x64\r
+               {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Release|Win32.ActiveCfg = Release|x64\r
                {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Release|x64.ActiveCfg = Release|x64\r
                {F6223AF3-BE0B-4B61-8406-98922CE521C2}.Release|x64.Build.0 = Release|x64\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Debug|Win32.ActiveCfg = Debug|x64\r
                {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Debug|x64.ActiveCfg = Debug|x64\r
                {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Debug|x64.Build.0 = Debug|x64\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Release|Mixed Platforms.Build.0 = Release|x64\r
+               {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Release|Win32.ActiveCfg = Release|x64\r
                {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Release|x64.ActiveCfg = Release|x64\r
                {816DEABA-3757-4306-AFE0-C27CF96C4DEA}.Release|x64.Build.0 = Release|x64\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Debug|Win32.ActiveCfg = Debug|x64\r
                {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Debug|x64.ActiveCfg = Debug|x64\r
                {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Debug|x64.Build.0 = Debug|x64\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Release|Mixed Platforms.Build.0 = Release|x64\r
+               {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Release|Win32.ActiveCfg = Release|x64\r
                {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Release|x64.ActiveCfg = Release|x64\r
                {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68}.Release|x64.Build.0 = Release|x64\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Debug|Win32.ActiveCfg = Debug|x64\r
                {88F974F0-D09F-4788-8CF8-F563209E60C1}.Debug|x64.ActiveCfg = Debug|x64\r
                {88F974F0-D09F-4788-8CF8-F563209E60C1}.Debug|x64.Build.0 = Debug|x64\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Release|Mixed Platforms.Build.0 = Release|x64\r
+               {88F974F0-D09F-4788-8CF8-F563209E60C1}.Release|Win32.ActiveCfg = Release|x64\r
                {88F974F0-D09F-4788-8CF8-F563209E60C1}.Release|x64.ActiveCfg = Release|x64\r
                {88F974F0-D09F-4788-8CF8-F563209E60C1}.Release|x64.Build.0 = Release|x64\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Debug|Win32.ActiveCfg = Debug|x64\r
                {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Debug|x64.ActiveCfg = Debug|x64\r
                {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Debug|x64.Build.0 = Debug|x64\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Release|Mixed Platforms.Build.0 = Release|x64\r
+               {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Release|Win32.ActiveCfg = Release|x64\r
                {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Release|x64.ActiveCfg = Release|x64\r
                {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2}.Release|x64.Build.0 = Release|x64\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Debug|Win32.ActiveCfg = Debug|x64\r
                {02308602-7FE0-4253-B96E-22134919F56A}.Debug|x64.ActiveCfg = Debug|x64\r
                {02308602-7FE0-4253-B96E-22134919F56A}.Debug|x64.Build.0 = Debug|x64\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Release|Mixed Platforms.Build.0 = Release|x64\r
+               {02308602-7FE0-4253-B96E-22134919F56A}.Release|Win32.ActiveCfg = Release|x64\r
                {02308602-7FE0-4253-B96E-22134919F56A}.Release|x64.ActiveCfg = Release|x64\r
                {02308602-7FE0-4253-B96E-22134919F56A}.Release|x64.Build.0 = Release|x64\r
+               {7D58BD57-FDD5-46E6-A23B-ED14B5314A0E}.Debug|Mixed Platforms.ActiveCfg = Debug|x64\r
+               {7D58BD57-FDD5-46E6-A23B-ED14B5314A0E}.Debug|Mixed Platforms.Build.0 = Debug|x64\r
+               {7D58BD57-FDD5-46E6-A23B-ED14B5314A0E}.Debug|Win32.ActiveCfg = Debug|x64\r
+               {7D58BD57-FDD5-46E6-A23B-ED14B5314A0E}.Debug|x64.ActiveCfg = Debug|x64\r
+               {7D58BD57-FDD5-46E6-A23B-ED14B5314A0E}.Debug|x64.Build.0 = Debug|x64\r
+               {7D58BD57-FDD5-46E6-A23B-ED14B5314A0E}.Release|Mixed Platforms.ActiveCfg = Release|x64\r
+               {7D58BD57-FDD5-46E6-A23B-ED14B5314A0E}.Release|Mixed Platforms.Build.0 = Release|x64\r
+               {7D58BD57-FDD5-46E6-A23B-ED14B5314A0E}.Release|Win32.ActiveCfg = Release|x64\r
+               {7D58BD57-FDD5-46E6-A23B-ED14B5314A0E}.Release|x64.ActiveCfg = Release|x64\r
+               {7D58BD57-FDD5-46E6-A23B-ED14B5314A0E}.Release|x64.Build.0 = Release|x64\r
        EndGlobalSection\r
        GlobalSection(SolutionProperties) = preSolution\r
                HideSolutionNode = FALSE\r
@@ -97,5 +179,6 @@ Global
                {82ED7ED6-8A15-40EC-A8AF-F5E712E0DA68} = {C54DA43E-4878-45DB-B76D-35970553672C}\r
                {88F974F0-D09F-4788-8CF8-F563209E60C1} = {C54DA43E-4878-45DB-B76D-35970553672C}\r
                {3E11FF65-A9DA-4F80-87F2-A7C6379ED5E2} = {C54DA43E-4878-45DB-B76D-35970553672C}\r
+               {7D58BD57-FDD5-46E6-A23B-ED14B5314A0E} = {C54DA43E-4878-45DB-B76D-35970553672C}\r
        EndGlobalSection\r
 EndGlobal\r
index 3120fad65cc46d8bd66e00e73fc2170eba10d7f2..55ea0db59b338404ff1259505479388f5f964036 100644 (file)
     <ClInclude Include="concurrency\com_context.h" />\r
     <ClInclude Include="concurrency\executor.h" />\r
     <ClInclude Include="concurrency\lock.h" />\r
-    <ClInclude Include="concurrency\target.h" />\r
     <ClInclude Include="diagnostics\graph.h" />\r
     <ClInclude Include="exception\exceptions.h" />\r
     <ClInclude Include="exception\win32_exception.h" />\r
     <ClInclude Include="os\windows\system_info.h" />\r
     <ClInclude Include="enum_class.h" />\r
     <ClInclude Include="os\windows\windows.h" />\r
+    <ClInclude Include="reactive.h" />\r
     <ClInclude Include="stdafx.h" />\r
     <ClInclude Include="utf.h" />\r
     <ClInclude Include="prec_timer.h" />\r
index 10a5775739c499ac9907a88137283ce56541f30e..8cc31b2e08298878c730750448ec954e739db48d 100644 (file)
     <ClInclude Include="utility\move_on_copy.h">\r
       <Filter>source\utility</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="concurrency\target.h">\r
-      <Filter>source\concurrency</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="utility\param.h">\r
       <Filter>source\utility</Filter>\r
     </ClInclude>\r
     <ClInclude Include="os\windows\windows.h">\r
       <Filter>source\os\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="reactive.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
index dc92fd73b3201b4448d2c48c6da72b8aa9e2c197..2246360d0ff5ad1511d405b59ffbf42aa8da140a 100644 (file)
@@ -209,16 +209,12 @@ public:
                \r
                return begin_invoke(std::forward<Func>(func), prioriy).get();\r
        }\r
-               \r
-       function_queue::size_type capacity() const /*noexcept*/ { return execution_queue_[normal_priority].capacity();  }\r
-       function_queue::size_type size() const /*noexcept*/ { return execution_queue_[normal_priority].size();  }\r
-       bool empty() const /*noexcept*/ { return execution_queue_[normal_priority].empty();     }\r
-       bool is_running() const /*noexcept*/ { return is_running_; }    \r
-               \r
-private:\r
-       \r
-       void execute() // noexcept\r
+\r
+       void yield() // noexcept\r
        {\r
+               if(boost::this_thread::get_id() != thread_.get_id())\r
+                       BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Executor can only yield inside of thread context."));\r
+\r
                std::function<void()> func;\r
                execution_queue_[normal_priority].pop(func);    \r
                \r
@@ -232,6 +228,14 @@ private:
                if(func)\r
                        func();\r
        }\r
+               \r
+       function_queue::size_type capacity() const /*noexcept*/ { return execution_queue_[normal_priority].capacity();  }\r
+       function_queue::size_type size() const /*noexcept*/ { return execution_queue_[normal_priority].size();  }\r
+       bool empty() const /*noexcept*/ { return execution_queue_[normal_priority].empty();     }\r
+       bool is_running() const /*noexcept*/ { return is_running_; }    \r
+               \r
+private:\r
+       \r
 \r
        void run() // noexcept\r
        {\r
@@ -241,7 +245,7 @@ private:
                {\r
                        try\r
                        {\r
-                               execute();\r
+                               yield();\r
                        }\r
                        catch(...)\r
                        {\r
diff --git a/common/concurrency/target.h b/common/concurrency/target.h
deleted file mode 100644 (file)
index 8f5cadc..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#pragma once\r
-\r
-namespace caspar {\r
-\r
-template<typename T>\r
-struct target\r
-{\r
-       virtual void send(const T&) = 0;\r
-};\r
-\r
-}
\ No newline at end of file
diff --git a/common/reactive.h b/common/reactive.h
new file mode 100644 (file)
index 0000000..3cb692d
--- /dev/null
@@ -0,0 +1,387 @@
+#pragma once\r
+\r
+#include <tbb/spin_rw_mutex.h>\r
+#include <tbb/cache_aligned_allocator.h>\r
+\r
+#include <algorithm>\r
+#include <functional>\r
+#include <memory>\r
+#include <vector>\r
+\r
+namespace caspar { namespace reactive {\r
+       \r
+namespace detail {\r
+\r
+// function_traits which works with MSVC2010 lambdas.\r
+       \r
+template<typename FPtr>\r
+struct function_traits_impl;\r
+\r
+template<typename R, typename A1>\r
+struct function_traits_impl<R (*)(A1)>\r
+{\r
+       typedef A1 arg1_type;\r
+};\r
+\r
+template<typename R, typename C, typename A1>\r
+struct function_traits_impl<R (C::*)(A1)>\r
+{\r
+       typedef A1 arg1_type;\r
+};\r
+\r
+template<typename R, typename C, typename A1>\r
+struct function_traits_impl<R (C::*)(A1) const>\r
+{\r
+       typedef A1 arg1_type;\r
+};\r
+\r
+template<typename T>\r
+typename function_traits_impl<T>::arg1_type arg1_type_helper(T);\r
+\r
+template<typename F>\r
+struct function_traits\r
+{\r
+       typedef decltype(detail::arg1_type_helper(&F::operator())) arg1_type;\r
+};\r
+\r
+}\r
+\r
+template<typename T>\r
+class observer\r
+{      \r
+       observer(const observer&);\r
+       observer& operator=(const observer&);\r
+public:\r
+       typedef T value_type;\r
+       \r
+       observer()\r
+       {\r
+       }\r
+\r
+       virtual ~observer()\r
+       {\r
+       }\r
+\r
+       virtual void on_next(const T&) = 0;\r
+};\r
+\r
+template<typename T>\r
+class observable\r
+{\r
+       observable(const observable&);\r
+       observable& operator=(const observable&);\r
+public:\r
+       typedef T                                               value_type;\r
+       typedef observer<T>                             observer;\r
+       typedef std::weak_ptr<observer> observer_ptr;\r
+\r
+       observable()\r
+       {\r
+       }\r
+\r
+       virtual ~observable()\r
+       {\r
+       }\r
+\r
+       virtual void subscribe(const observer_ptr&) = 0;\r
+       virtual void unsubscribe(const observer_ptr&) = 0;\r
+};\r
+\r
+template<typename I, typename O = I>\r
+struct subject : public observer<I>, public observable<O>\r
+{\r
+       typedef typename observable<O>::observer                observer;\r
+       typedef typename observable<O>::observer_ptr    observer_ptr;\r
+\r
+       virtual ~subject()\r
+       {\r
+       }\r
+};\r
+\r
+namespace detail {\r
+\r
+template<typename T>\r
+struct true_func\r
+{\r
+       bool operator()(T)\r
+       {\r
+               return true;\r
+       }\r
+};\r
+\r
+template<typename T>\r
+struct void_func\r
+{\r
+       void operator()(T)\r
+       {\r
+       }\r
+};\r
+\r
+template<typename I, typename O>\r
+struct forward_func\r
+{\r
+       forward_func(std::function<O(const I&)> func)\r
+               : func_(std::move(func))\r
+       {\r
+       }\r
+\r
+       O operator()(const I& value)\r
+       {\r
+               return func_(value);\r
+       }\r
+\r
+       std::function<O(const I&)> func_;\r
+};\r
+\r
+template<typename I>\r
+struct forward_func<I, I>\r
+{\r
+       const I& operator()(const I& value)\r
+       {\r
+               return value;\r
+       }\r
+};\r
+\r
+}\r
+\r
+template<typename T, typename C, typename F = detail::true_func<T>>\r
+class observer_function : public observer<T>\r
+{\r
+public:\r
+       observer_function()\r
+       {\r
+       }\r
+\r
+       observer_function(C func)\r
+               : func_(std::move(func))\r
+       {\r
+       }\r
+\r
+       observer_function(C func, F filter)\r
+               : func_(std::move(func))\r
+               , filter_(std::move(filter))\r
+       {\r
+       }\r
+\r
+       observer_function(const observer_function& other)\r
+               : func_(other.func_)\r
+               , filter_(other.filter_)\r
+       {\r
+       }\r
+\r
+       observer_function(observer_function&& other)\r
+               : func_(std::move(other.func_))\r
+               , filter_(std::move(other.filter_))\r
+       {\r
+       }\r
+\r
+       observer_function& operator=(observer_function other)\r
+       {\r
+               other.swap(*this);\r
+       }\r
+\r
+       void swap(observer_function& other)\r
+       {\r
+               std::swap(func_, other.func_);\r
+               std::swap(filter_, other.filter_);\r
+       }\r
+               \r
+       virtual void on_next(const T& e) override\r
+       {\r
+               if(!filter_(e))\r
+                       return;\r
+\r
+               func_(e);\r
+       }\r
+private:\r
+       C func_;\r
+       F filter_;\r
+};\r
+\r
+template<typename T, typename F>\r
+class observer_function<T, detail::void_func<T>, F> : public observer<T>\r
+{\r
+public:                \r
+       virtual void on_next(const T& e) override\r
+       {\r
+       }\r
+};\r
+\r
+template<typename I, typename O = I, typename F = detail::true_func<const I&>, typename T = detail::forward_func<I, O>>\r
+class basic_subject : public subject<I, O>\r
+{      \r
+    template <typename, typename, typename, typename> friend class basic_subject;\r
+\r
+       basic_subject(const basic_subject&);\r
+       basic_subject& operator=(const basic_subject&);\r
+public:        \r
+       typedef typename subject<I, O>::observer                observer;\r
+       typedef typename subject<I, O>::observer_ptr    observer_ptr;\r
+       typedef F                                                                               filter;\r
+       typedef T                                                                               transform;\r
+\r
+       basic_subject()\r
+       {\r
+       }\r
+       \r
+       basic_subject(F filter)\r
+               : filter_(std::move(filter))\r
+       {\r
+       }\r
+       \r
+       basic_subject(T transform)\r
+               : transform_(std::move(transform))\r
+       {\r
+       }\r
+       \r
+       basic_subject(std::function<O(const I&)> transform)\r
+               : transform_(std::move(transform))\r
+       {\r
+       }\r
+\r
+       basic_subject(F filter, T transform)\r
+               : filter_(std::move(filter))\r
+               , transform_(std::move(transform))\r
+       {\r
+       }\r
+       \r
+       virtual ~basic_subject()\r
+       {\r
+       }\r
+               \r
+       template<typename F1, typename T1>\r
+       basic_subject(basic_subject<typename observer::value_type, typename observable::value_type, F1, T1>&& other)\r
+               : observers_(std::move(other.observers_))\r
+               , filter_(std::move(other.filter_))\r
+               , transform_(std::move(other.transform_))\r
+       {\r
+       }\r
+       \r
+       template<typename F1, typename T1>\r
+       basic_subject& operator=(basic_subject<typename observer::value_type, typename observable::value_type, F1, T1>&& other)\r
+       {\r
+               other.swap(*this);\r
+               return *this;\r
+       }\r
+       \r
+       template<typename F1, typename T1>\r
+       void swap(basic_subject<typename observer::value_type, typename observable::value_type, F1, T1>& other)\r
+       {               \r
+               tbb::spin_rw_mutex::scoped_lock lock(mutex_, true);\r
+               tbb::spin_rw_mutex::scoped_lock other_lock(other.mutex_, true);\r
+\r
+               std::swap(observers_, other.observers_);\r
+               std::swap(filter_, other.filter_);              \r
+       }\r
+\r
+       virtual void clear()\r
+       {\r
+               tbb::spin_rw_mutex::scoped_lock lock(mutex_, true);\r
+\r
+               observers_.clear();\r
+       }\r
+       \r
+       virtual void subscribe(const observer_ptr& o) override\r
+       {                               \r
+               tbb::spin_rw_mutex::scoped_lock lock(mutex_, false);\r
+\r
+               auto it = std::lower_bound(std::begin(observers_), std::end(observers_), o, comp_);\r
+               if (it == std::end(observers_) || comp_(o, *it))\r
+               {\r
+                       lock.upgrade_to_writer();\r
+                       observers_.insert(it, o);\r
+               }               \r
+       }\r
+\r
+       virtual void unsubscribe(const observer_ptr& o) override\r
+       {\r
+               tbb::spin_rw_mutex::scoped_lock lock(mutex_, false);\r
+               \r
+               auto it = std::lower_bound(std::begin(observers_), std::end(observers_), o, comp_);\r
+               if(it != std::end(observers_) && !comp_(o, *it))\r
+               {\r
+                       lock.upgrade_to_writer();\r
+                       observers_.erase(it);\r
+               }               \r
+       }\r
+       \r
+       virtual void on_next(const I& e) override\r
+       {                               \r
+               if(!filter_(e))\r
+                       return;\r
+\r
+               std::vector<std::shared_ptr<observer>> observers;\r
+\r
+               {\r
+                       tbb::spin_rw_mutex::scoped_lock lock(mutex_, false);\r
+               \r
+                       auto expired = std::end(observers_);\r
+\r
+                       for(auto it = std::begin(observers_); it != std::end(observers_); ++it)\r
+                       {\r
+                               auto o = it->lock();\r
+                               if(o)\r
+                                       observers.push_back(std::move(o));\r
+                               else\r
+                                       expired = it;\r
+                       }\r
+\r
+                       if(expired != std::end(observers_))\r
+                       {               \r
+                               lock.upgrade_to_writer();\r
+                               observers_.erase(expired);\r
+                       }       \r
+               }\r
+               \r
+               const auto& e2 = transform_(e);\r
+               for(auto it = std::begin(observers); it != std::end(observers); ++it)\r
+                       (*it)->on_next(e2);\r
+       }\r
+private:\r
+       typedef tbb::cache_aligned_allocator<std::weak_ptr<observer>>   allocator;\r
+\r
+       std::owner_less<std::weak_ptr<observer>>                comp_;\r
+       std::vector<std::weak_ptr<observer>, allocator> observers_;\r
+       mutable tbb::spin_rw_mutex                                              mutex_;\r
+       F                                                                                               filter_;\r
+       T                                                                                               transform_;\r
+};\r
+\r
+template<typename F>\r
+std::shared_ptr<basic_subject<typename std::decay<typename detail::function_traits<F>::arg1_type>::type, typename std::decay<typename detail::function_traits<F>::arg1_type>::type, F>> \r
+make_filter(F filter)\r
+{\r
+       return std::make_shared<basic_subject<std::decay<typename detail::function_traits<F>::arg1_type>::type, typename std::decay<typename detail::function_traits<F>::arg1_type>::type, F>>(std::move(filter));\r
+}\r
+\r
+template<typename F>\r
+std::shared_ptr<observer_function<typename std::decay<typename detail::function_traits<F>::arg1_type>::type, F>> \r
+make_observer(F func)\r
+{\r
+       return std::make_shared<observer_function<std::decay<typename detail::function_traits<F>::arg1_type>::type, F>>(std::move(func));\r
+}\r
+\r
+template<typename F1, typename F2>\r
+std::shared_ptr<observer_function<typename std::decay<typename detail::function_traits<F1>::arg1_type>::type, F1, F2>> \r
+make_observer(F1 func, F2 filter)\r
+{\r
+       return std::make_shared<observer_function<std::decay<typename detail::function_traits<F1>::arg1_type>::type, F1, F2>>(std::move(func), std::move(filter));\r
+}\r
+\r
+}}\r
+\r
+namespace std {\r
+       \r
+template <typename T, typename F1, typename F2>\r
+void swap(caspar::reactive::observer_function<T, F1>& lhs, caspar::reactive::observer_function<T, F2>& rhs) \r
+{\r
+    lhs.swap(rhs);\r
+}\r
+\r
+template <typename I, typename O, typename F1, typename F2, typename T1, typename T2>\r
+void swap(caspar::reactive::basic_subject<I, O, F1, T1>& lhs, caspar::reactive::basic_subject<I, O, F2, T2>& rhs) \r
+{\r
+    lhs.swap(rhs);\r
+}\r
+\r
+} // std\r
index 4e40c513ec44e756c29170f11290051ed2451306..49309380f1df92baa6e0bca9437461b0d281ade5 100644 (file)
@@ -27,7 +27,7 @@
 #include <common/memory/safe_ptr.h>\r
 #include <common/exception/exceptions.h>\r
 #include <core/video_format.h>\r
-#include <core/mixer/read_frame.h>\r
+#include <core/frame.h>\r
 \r
 #include <boost/circular_buffer.hpp>\r
 \r
@@ -84,7 +84,7 @@ public:
                consumer_->initialize(format_desc, channel_index);\r
        }\r
 \r
-       virtual bool send(const safe_ptr<read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<const frame>& frame) override\r
        {               \r
                if(audio_cadence_.size() == 1)\r
                        return consumer_->send(frame);\r
@@ -140,7 +140,7 @@ const safe_ptr<frame_consumer>& frame_consumer::empty()
 {\r
        struct empty_frame_consumer : public frame_consumer\r
        {\r
-               virtual bool send(const safe_ptr<read_frame>&) override {return false;}\r
+               virtual bool send(const safe_ptr<const frame>&) override {return false;}\r
                virtual void initialize(const video_format_desc&, int) override{}\r
                virtual std::wstring print() const override {return L"empty";}\r
                virtual bool has_synchronization_clock() const override {return false;}\r
index 68b3e8ac99bbec5a3011c19dfee20149e85dc2c0..dccf299520a7fe08ed533394efcbc582ad7e1b89 100644 (file)
@@ -37,7 +37,7 @@ struct frame_consumer : boost::noncopyable
        frame_consumer(){}\r
        virtual ~frame_consumer() {}\r
        \r
-       virtual bool send(const safe_ptr<class read_frame>& frame) = 0;\r
+       virtual bool send(const safe_ptr<const struct frame>& frame) = 0;\r
        virtual void initialize(const struct video_format_desc& format_desc, int channel_index) = 0;\r
        virtual std::wstring print() const = 0;\r
        virtual boost::property_tree::wptree info() const = 0;\r
index b690472de40237ddb12f466cf76d4ab50759d788..5868649aec066b57104aa3fd9abb76a55813aaca 100644 (file)
@@ -30,7 +30,7 @@
 #include "frame_consumer.h"\r
 \r
 #include "../video_format.h"\r
-#include "../mixer/gpu/ogl_device.h"\r
+#include "../mixer/gpu/accelerator.h"\r
 #include "../mixer/read_frame.h"\r
 \r
 #include <common/concurrency/executor.h>\r
@@ -51,8 +51,6 @@ namespace caspar { namespace core {
 struct output::impl\r
 {              \r
        const int                                                                               channel_index_;\r
-       const safe_ptr<diagnostics::graph>                              graph_;\r
-       boost::timer                                                                    consume_timer_;\r
 \r
        video_format_desc                                                               format_desc_;\r
 \r
@@ -60,18 +58,17 @@ struct output::impl
        \r
        prec_timer                                                                              sync_timer_;\r
 \r
-       boost::circular_buffer<safe_ptr<read_frame>>    frames_;\r
+       boost::circular_buffer<safe_ptr<const frame>>   frames_;\r
 \r
        executor                                                                                executor_;\r
                \r
 public:\r
-       impl(const safe_ptr<diagnostics::graph>& graph, const video_format_desc& format_desc, int channel_index) \r
+       impl(const video_format_desc& format_desc, int channel_index) \r
                : channel_index_(channel_index)\r
-               , graph_(graph)\r
                , format_desc_(format_desc)\r
                , executor_(L"output")\r
        {\r
-               graph_->set_color("consume-time", diagnostics::color(1.0f, 0.4f, 0.0f, 0.8));\r
+               executor_.set_capacity(1);\r
        }       \r
        \r
        void add(int index, safe_ptr<frame_consumer> consumer)\r
@@ -163,19 +160,18 @@ public:
        {\r
                return boost::range::count_if(consumers_ | boost::adaptors::map_values, [](const safe_ptr<frame_consumer>& x){return x->has_synchronization_clock();}) > 0;\r
        }\r
-\r
-       void send(const std::pair<safe_ptr<read_frame>, std::shared_ptr<void>>& packet)\r
+               \r
+       void operator()(safe_ptr<const frame> input_frame, const video_format_desc& format_desc)\r
        {\r
                executor_.begin_invoke([=]\r
                {\r
                        try\r
-                       {\r
-                               consume_timer_.restart();\r
-\r
-                               auto input_frame = packet.first;\r
-\r
+                       {                               \r
                                if(!has_synchronization_clock())\r
                                        sync_timer_.tick(1.0/format_desc_.fps);\r
+                               \r
+                               if(format_desc_ != format_desc)\r
+                                       set_video_format_desc(format_desc);\r
 \r
                                if(input_frame->image_data().size() != format_desc_.size)\r
                                {\r
@@ -229,8 +225,6 @@ public:
                                                }\r
                                        }\r
                                }\r
-                                               \r
-                               graph_->set_value("consume-time", consume_timer_.elapsed()*format_desc_.fps*0.5);\r
                        }\r
                        catch(...)\r
                        {\r
@@ -259,12 +253,11 @@ public:
        }\r
 };\r
 \r
-output::output(const safe_ptr<diagnostics::graph>& graph, const video_format_desc& format_desc, int channel_index) : impl_(new impl(graph, format_desc, channel_index)){}\r
+output::output(const video_format_desc& format_desc, int channel_index) : impl_(new impl(format_desc, channel_index)){}\r
 void output::add(int index, const safe_ptr<frame_consumer>& consumer){impl_->add(index, consumer);}\r
 void output::add(const safe_ptr<frame_consumer>& consumer){impl_->add(consumer);}\r
 void output::remove(int index){impl_->remove(index);}\r
 void output::remove(const safe_ptr<frame_consumer>& consumer){impl_->remove(consumer);}\r
-void output::send(const std::pair<safe_ptr<read_frame>, std::shared_ptr<void>>& frame) {impl_->send(frame); }\r
-void output::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
 boost::unique_future<boost::property_tree::wptree> output::info() const{return impl_->info();}\r
+void output::operator()(safe_ptr<const frame> frame, const video_format_desc& format_desc){(*impl_)(std::move(frame), format_desc);}\r
 }}
\ No newline at end of file
index 2fdc33aef1af36ace82bf8ca5d52e901a5dbe193..9c8c6309602a56a908ab34d37adef9dc6ef8ec74 100644 (file)
@@ -23,7 +23,7 @@
 \r
 #include <common/forward.h>\r
 #include <common/memory/safe_ptr.h>\r
-#include <common/concurrency/target.h>\r
+#include <common/reactive.h>\r
 \r
 #include <boost/noncopyable.hpp>\r
 #include <boost/property_tree/ptree_fwd.hpp>\r
@@ -33,26 +33,22 @@ FORWARD2(caspar, diagnostics, class graph);
 \r
 namespace caspar { namespace core {\r
        \r
-class output sealed : public target<std::pair<safe_ptr<class read_frame>, std::shared_ptr<void>>>\r
-                                       , boost::noncopyable\r
+class output sealed : boost::noncopyable\r
 {\r
 public:\r
-       explicit output(const safe_ptr<diagnostics::graph>& graph, const struct video_format_desc& format_desc, int channel_index);\r
-\r
-       // target\r
+       explicit output(const struct video_format_desc& format_desc, int channel_index);\r
        \r
-       virtual void send(const std::pair<safe_ptr<class read_frame>, std::shared_ptr<void>>& frame) override;\r
-\r
        // output\r
+\r
+       void operator()(safe_ptr<const struct frame> frame, const struct video_format_desc& format_desc);\r
        \r
        void add(const safe_ptr<struct frame_consumer>& consumer);\r
        void add(int index, const safe_ptr<struct frame_consumer>& consumer);\r
        void remove(const safe_ptr<struct frame_consumer>& consumer);\r
        void remove(int index);\r
        \r
-       void set_video_format_desc(const struct video_format_desc& format_desc);\r
-\r
        boost::unique_future<boost::property_tree::wptree> info() const;\r
+\r
 private:\r
        struct impl;\r
        safe_ptr<impl> impl_;\r
index 550f6e0ab15b2cea3b775d6af8714ebabd943bbf..8b4a435b397c9463baf6db04534586147a88c69b 100644 (file)
     </Lib>\r
   </ItemDefinitionGroup>\r
   <ItemGroup>\r
+    <ClInclude Include="frame.h" />\r
     <ClInclude Include="mixer\audio\audio_util.h" />\r
+    <ClInclude Include="mixer\gpu\device_buffer.h" />\r
+    <ClInclude Include="mixer\gpu\host_buffer.h" />\r
+    <ClInclude Include="mixer\gpu\image\blending_glsl.h" />\r
+    <ClInclude Include="mixer\gpu\image\image_kernel.h" />\r
+    <ClInclude Include="mixer\gpu\image\image_mixer.h" />\r
+    <ClInclude Include="mixer\gpu\image\image_shader.h" />\r
+    <ClInclude Include="mixer\gpu\accelerator.h" />\r
     <ClInclude Include="mixer\gpu\shader.h" />\r
     <ClInclude Include="mixer\image\blend_modes.h" />\r
-    <ClInclude Include="mixer\image\shader\blending_glsl.h" />\r
-    <ClInclude Include="mixer\image\shader\image_shader.h" />\r
-    <ClInclude Include="producer\channel\channel_producer.h" />\r
-    <ClInclude Include="producer\playlist\playlist_producer.h" />\r
     <ClInclude Include="video_channel.h" />\r
     <ClInclude Include="consumer\output.h" />\r
     <ClInclude Include="consumer\frame_consumer.h" />\r
     <ClInclude Include="mixer\audio\audio_mixer.h" />\r
     <ClInclude Include="mixer\mixer.h" />\r
-    <ClInclude Include="mixer\gpu\device_buffer.h" />\r
-    <ClInclude Include="mixer\gpu\host_buffer.h" />\r
-    <ClInclude Include="mixer\gpu\ogl_device.h" />\r
-    <ClInclude Include="mixer\image\image_kernel.h" />\r
     <ClInclude Include="mixer\image\image_mixer.h" />\r
     <ClInclude Include="mixer\read_frame.h" />\r
     <ClInclude Include="mixer\write_frame.h" />\r
     <ClInclude Include="StdAfx.h" />\r
   </ItemGroup>\r
   <ItemGroup>\r
-    <ClCompile Include="mixer\gpu\shader.cpp">\r
+    <ClCompile Include="mixer\gpu\device_buffer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\host_buffer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\image\image_kernel.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="mixer\image\blend_modes.cpp">\r
+    <ClCompile Include="mixer\gpu\image\image_mixer.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\image\image_shader.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\accelerator.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="mixer\image\shader\image_shader.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../../stdafx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../../stdafx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
-    <ClCompile Include="producer\channel\channel_producer.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Profile|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Develop|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+    <ClCompile Include="mixer\gpu\shader.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="producer\playlist\playlist_producer.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../stdafx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../stdafx.h</PrecompiledHeaderFile>\r
+    <ClCompile Include="mixer\image\blend_modes.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
     <ClCompile Include="video_channel.cpp" />\r
     <ClCompile Include="consumer\frame_consumer.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="mixer\gpu\device_buffer.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
-    <ClCompile Include="mixer\gpu\host_buffer.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
-    <ClCompile Include="mixer\gpu\ogl_device.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
-    <ClCompile Include="mixer\image\image_kernel.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
-    <ClCompile Include="mixer\image\image_mixer.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../../StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
     <ClCompile Include="mixer\read_frame.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|x64'">../StdAfx.h</PrecompiledHeaderFile>\r
index 269417ec161184a1840bd553bd3c1387579f78cd..5af851ff2ad0b0bd58ea56e1380351ed68a97621 100644 (file)
@@ -4,6 +4,18 @@
     <Filter Include="source">\r
       <UniqueIdentifier>{cc341f3a-7ea0-424a-bacd-c40aa8e7822b}</UniqueIdentifier>\r
     </Filter>\r
+    <Filter Include="source\mixer">\r
+      <UniqueIdentifier>{e480e128-a351-4dc6-a7ab-f58b480f6afd}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\mixer\audio">\r
+      <UniqueIdentifier>{0951ac32-6cd0-4a9f-865d-6f86600f12f8}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\mixer\image">\r
+      <UniqueIdentifier>{1cca1d41-f9b1-4b7b-b34f-8a88dcb5b904}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\consumer">\r
+      <UniqueIdentifier>{35d7835f-f813-4b4b-8d8d-8a35dfef68d3}</UniqueIdentifier>\r
+    </Filter>\r
     <Filter Include="source\producer">\r
       <UniqueIdentifier>{71accefc-1437-4e1d-9ff7-9de654a32df9}</UniqueIdentifier>\r
     </Filter>\r
     <Filter Include="source\producer\separated">\r
       <UniqueIdentifier>{cf834e89-32d6-47bc-8d5a-10e032f88e15}</UniqueIdentifier>\r
     </Filter>\r
-    <Filter Include="source\mixer">\r
-      <UniqueIdentifier>{e480e128-a351-4dc6-a7ab-f58b480f6afd}</UniqueIdentifier>\r
-    </Filter>\r
-    <Filter Include="source\mixer\audio">\r
-      <UniqueIdentifier>{0951ac32-6cd0-4a9f-865d-6f86600f12f8}</UniqueIdentifier>\r
-    </Filter>\r
-    <Filter Include="source\mixer\image">\r
-      <UniqueIdentifier>{1cca1d41-f9b1-4b7b-b34f-8a88dcb5b904}</UniqueIdentifier>\r
-    </Filter>\r
     <Filter Include="source\mixer\gpu">\r
-      <UniqueIdentifier>{2d2ae7ff-03d7-4e8c-a298-fb41ee42a885}</UniqueIdentifier>\r
+      <UniqueIdentifier>{b2af87a2-9528-4f82-b3f1-b7409ca15acd}</UniqueIdentifier>\r
     </Filter>\r
-    <Filter Include="source\consumer">\r
-      <UniqueIdentifier>{35d7835f-f813-4b4b-8d8d-8a35dfef68d3}</UniqueIdentifier>\r
-    </Filter>\r
-    <Filter Include="source\producer\playlist">\r
-      <UniqueIdentifier>{80ce21ca-5ecd-48c1-97d2-c20ea8e2f2b6}</UniqueIdentifier>\r
-    </Filter>\r
-    <Filter Include="source\mixer\image\shader">\r
-      <UniqueIdentifier>{e0a140f8-e217-465c-a934-163b7ea786be}</UniqueIdentifier>\r
-    </Filter>\r
-    <Filter Include="source\producer\channel">\r
-      <UniqueIdentifier>{e5def302-a2b5-4e1f-8565-d6ef3927b31f}</UniqueIdentifier>\r
+    <Filter Include="source\mixer\gpu\image">\r
+      <UniqueIdentifier>{d8d99a8a-42f9-48a3-b8a5-c07228226eab}</UniqueIdentifier>\r
     </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="producer\frame\frame_factory.h">\r
       <Filter>source\producer\frame</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="mixer\image\image_kernel.h">\r
-      <Filter>source\mixer\image</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="mixer\image\image_mixer.h">\r
       <Filter>source\mixer\image</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="mixer\gpu\host_buffer.h">\r
-      <Filter>source\mixer\gpu</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="mixer\gpu\ogl_device.h">\r
-      <Filter>source\mixer\gpu</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="mixer\gpu\device_buffer.h">\r
-      <Filter>source\mixer\gpu</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="mixer\audio\audio_mixer.h">\r
       <Filter>source\mixer\audio</Filter>\r
     </ClInclude>\r
     <ClInclude Include="video_channel.h">\r
       <Filter>source</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="mixer\gpu\shader.h">\r
-      <Filter>source\mixer\gpu</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="producer\frame\frame_transform.h">\r
       <Filter>source\producer\frame</Filter>\r
     </ClInclude>\r
     <ClInclude Include="mixer\audio\audio_util.h">\r
       <Filter>source\mixer\audio</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="producer\playlist\playlist_producer.h">\r
-      <Filter>source\producer\playlist</Filter>\r
+    <ClInclude Include="producer\separated\separated_producer.h">\r
+      <Filter>source\producer\separated</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\gpu\device_buffer.h">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\gpu\host_buffer.h">\r
+      <Filter>source\mixer\gpu</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="mixer\image\shader\image_shader.h">\r
-      <Filter>source\mixer\image\shader</Filter>\r
+    <ClInclude Include="mixer\gpu\shader.h">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\gpu\image\image_mixer.h">\r
+      <Filter>source\mixer\gpu\image</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\gpu\image\image_kernel.h">\r
+      <Filter>source\mixer\gpu\image</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\gpu\image\blending_glsl.h">\r
+      <Filter>source\mixer\gpu\image</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="mixer\gpu\image\image_shader.h">\r
+      <Filter>source\mixer\gpu\image</Filter>\r
     </ClInclude>\r
     <ClInclude Include="mixer\image\blend_modes.h">\r
       <Filter>source\mixer\image</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="mixer\image\shader\blending_glsl.h">\r
-      <Filter>source\mixer\image\shader</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="producer\channel\channel_producer.h">\r
-      <Filter>source\producer\channel</Filter>\r
+    <ClInclude Include="mixer\gpu\accelerator.h">\r
+      <Filter>source\mixer\gpu</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="producer\separated\separated_producer.h">\r
-      <Filter>source\producer\separated</Filter>\r
+    <ClInclude Include="frame.h">\r
+      <Filter>source</Filter>\r
     </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="producer\frame\basic_frame.cpp">\r
       <Filter>source\producer\frame</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="mixer\image\image_mixer.cpp">\r
-      <Filter>source\mixer\image</Filter>\r
-    </ClCompile>\r
-    <ClCompile Include="mixer\image\image_kernel.cpp">\r
-      <Filter>source\mixer\image</Filter>\r
-    </ClCompile>\r
-    <ClCompile Include="mixer\gpu\host_buffer.cpp">\r
-      <Filter>source\mixer\gpu</Filter>\r
-    </ClCompile>\r
-    <ClCompile Include="mixer\gpu\ogl_device.cpp">\r
-      <Filter>source\mixer\gpu</Filter>\r
-    </ClCompile>\r
-    <ClCompile Include="mixer\gpu\device_buffer.cpp">\r
-      <Filter>source\mixer\gpu</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="mixer\audio\audio_mixer.cpp">\r
       <Filter>source\mixer\audio</Filter>\r
     </ClCompile>\r
     <ClCompile Include="video_format.cpp">\r
       <Filter>source</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="mixer\gpu\shader.cpp">\r
-      <Filter>source\mixer\gpu</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="producer\frame\frame_transform.cpp">\r
       <Filter>source\producer\frame</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="producer\playlist\playlist_producer.cpp">\r
-      <Filter>source\producer\playlist</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="producer\frame_producer.cpp">\r
       <Filter>source\producer</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="mixer\image\shader\image_shader.cpp">\r
-      <Filter>source\mixer\image\shader</Filter>\r
+    <ClCompile Include="mixer\gpu\device_buffer.cpp">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\host_buffer.cpp">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\shader.cpp">\r
+      <Filter>source\mixer\gpu</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\image\image_shader.cpp">\r
+      <Filter>source\mixer\gpu\image</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\image\image_mixer.cpp">\r
+      <Filter>source\mixer\gpu\image</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="mixer\gpu\image\image_kernel.cpp">\r
+      <Filter>source\mixer\gpu\image</Filter>\r
     </ClCompile>\r
     <ClCompile Include="mixer\image\blend_modes.cpp">\r
       <Filter>source\mixer\image</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="producer\channel\channel_producer.cpp">\r
-      <Filter>source\producer\channel</Filter>\r
+    <ClCompile Include="mixer\gpu\accelerator.cpp">\r
+      <Filter>source\mixer\gpu</Filter>\r
     </ClCompile>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
diff --git a/core/frame.h b/core/frame.h
new file mode 100644 (file)
index 0000000..3e40055
--- /dev/null
@@ -0,0 +1,86 @@
+#pragma once\r
+\r
+#include <boost/noncopyable.hpp>\r
+#include <boost/range.hpp>\r
+\r
+#include <stdint.h>\r
+\r
+#include "producer/frame/pixel_format.h"\r
+#include "video_format.h"\r
+\r
+namespace caspar { namespace core {\r
+\r
+struct frame : boost::noncopyable\r
+{\r
+       virtual ~frame()\r
+       {\r
+       }\r
+\r
+       virtual const struct  pixel_format_desc& get_pixel_format_desc() const = 0;\r
+\r
+       virtual const boost::iterator_range<const uint8_t*> image_data() const = 0;\r
+       virtual const boost::iterator_range<const int32_t*> audio_data() const = 0;\r
+       \r
+       virtual const boost::iterator_range<uint8_t*> image_data() = 0;\r
+       virtual const boost::iterator_range<int32_t*> audio_data() = 0;\r
+\r
+       virtual double get_frame_rate() const = 0;\r
+       virtual field_mode get_field_mode() const = 0;\r
+\r
+       virtual int width() const = 0;\r
+       virtual int height() const = 0;\r
+\r
+       static safe_ptr<frame> empty()\r
+       {\r
+               struct empty_frame : public frame\r
+               {\r
+                       virtual const struct  video_format_desc& get_video_format_desc() const\r
+                       {\r
+                               static video_format_desc invalid;\r
+                               return invalid;\r
+                       }\r
+                       virtual const struct  pixel_format_desc& get_pixel_format_desc() const \r
+                       {\r
+                               static pixel_format_desc invalid;\r
+                               return invalid;\r
+                       }\r
+                       virtual const boost::iterator_range<const uint8_t*> image_data() const \r
+                       {\r
+                               return boost::iterator_range<const uint8_t*>();\r
+                       }\r
+                       virtual const boost::iterator_range<const int32_t*> audio_data() const \r
+                       {\r
+                               return boost::iterator_range<const int32_t*>();\r
+                       }\r
+                       const boost::iterator_range<uint8_t*> image_data()\r
+                       {\r
+                               return boost::iterator_range<uint8_t*>();\r
+                       }\r
+                       const boost::iterator_range<int32_t*> audio_data()\r
+                       {\r
+                               return boost::iterator_range<int32_t*>();\r
+                       }\r
+                       virtual double get_frame_rate() const\r
+                       {\r
+                               return 0.0;\r
+                       }\r
+                       virtual field_mode get_field_mode() const\r
+                       {\r
+                               return field_mode::empty;\r
+                       }\r
+                       virtual int width() const\r
+                       {\r
+                               return 0;\r
+                       }\r
+                       virtual int height() const\r
+                       {\r
+                               return 0;\r
+                       }\r
+               };\r
+\r
+               static safe_ptr<empty_frame> empty;\r
+               return empty;\r
+       }\r
+};\r
+\r
+}}
\ No newline at end of file
index 99020283474ff17281fc2b58f80fb3c4134e03c3..47a4aaab22226c1f9b4a1428ae437bc5aaed37bb 100644 (file)
@@ -62,9 +62,8 @@ struct audio_stream
        audio_buffer_ps         audio_data;\r
 };\r
 \r
-struct audio_mixer::impl\r
+struct audio_mixer::impl : boost::noncopyable\r
 {\r
-       safe_ptr<diagnostics::graph>            graph_;\r
        std::stack<core::frame_transform>       transform_stack_;\r
        std::map<const void*, audio_stream>     audio_streams_;\r
        std::vector<audio_item>                         items_;\r
@@ -72,10 +71,8 @@ struct audio_mixer::impl
        video_format_desc                                       format_desc_;\r
        \r
 public:\r
-       impl(const safe_ptr<diagnostics::graph>& graph)\r
-               : graph_(graph)\r
+       impl()\r
        {\r
-               graph_->set_color("volume", diagnostics::color(1.0f, 0.8f, 0.1f));\r
                transform_stack_.push(core::frame_transform());\r
        }\r
        \r
@@ -182,16 +179,12 @@ public:
                audio_buffer result;\r
                result.reserve(result_ps.size());\r
                boost::range::transform(result_ps, std::back_inserter(result), [](float sample){return static_cast<int32_t>(sample);});         \r
-\r
-               auto max = boost::range::max_element(result);\r
-\r
-               graph_->set_value("volume", static_cast<double>(std::abs(*max))/std::numeric_limits<int32_t>::max());\r
-\r
+               \r
                return result;\r
        }\r
 };\r
 \r
-audio_mixer::audio_mixer(const safe_ptr<diagnostics::graph>& graph) : impl_(new impl(graph)){}\r
+audio_mixer::audio_mixer() : impl_(new impl()){}\r
 void audio_mixer::begin(core::basic_frame& frame){impl_->begin(frame);}\r
 void audio_mixer::visit(core::write_frame& frame){impl_->visit(frame);}\r
 void audio_mixer::end(){impl_->end();}\r
index 8cb13876623ad8af18cd0fc88c467f640b6620ca..1cbb0313131cb1474c289cf88b34369c2e00acf5 100644 (file)
@@ -39,7 +39,7 @@ typedef std::vector<int32_t, tbb::cache_aligned_allocator<int32_t>> audio_buffer
 class audio_mixer sealed : public frame_visitor\r
 {\r
 public:\r
-       audio_mixer(const safe_ptr<diagnostics::graph>& graph);\r
+       audio_mixer();\r
 \r
        virtual void begin(core::basic_frame& frame);\r
        virtual void visit(core::write_frame& frame);\r
similarity index 76%
rename from core/mixer/gpu/ogl_device.cpp
rename to core/mixer/gpu/accelerator.cpp
index 8646e57fea515c9acc8678ffdc9c6122624a656f..686f260179676f84370c04baeb0383235d0b045e 100644 (file)
@@ -23,7 +23,7 @@
 \r
 #include "../../stdafx.h"\r
 \r
-#include "ogl_device.h"\r
+#include "accelerator.h"\r
 \r
 #include "shader.h"\r
 \r
 \r
 #include <gl/glew.h>\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar { namespace core { namespace gpu {\r
 \r
-ogl_device::ogl_device() \r
-       : executor_(L"ogl_device")\r
+accelerator::accelerator() \r
+       : executor_(L"accelerator")\r
        , attached_texture_(0)\r
        , attached_fbo_(0)\r
        , active_shader_(0)\r
@@ -71,7 +71,7 @@ ogl_device::ogl_device()
        });\r
 }\r
 \r
-ogl_device::~ogl_device()\r
+accelerator::~accelerator()\r
 {\r
        invoke([=]\r
        {\r
@@ -83,7 +83,7 @@ ogl_device::~ogl_device()
        });\r
 }\r
 \r
-safe_ptr<device_buffer> ogl_device::allocate_device_buffer(int width, int height, int stride)\r
+safe_ptr<device_buffer> accelerator::allocate_device_buffer(int width, int height, int stride)\r
 {\r
        std::shared_ptr<device_buffer> buffer;\r
        try\r
@@ -108,7 +108,7 @@ safe_ptr<device_buffer> ogl_device::allocate_device_buffer(int width, int height
        return make_safe_ptr(buffer);\r
 }\r
                                \r
-safe_ptr<device_buffer> ogl_device::create_device_buffer(int width, int height, int stride)\r
+safe_ptr<device_buffer> accelerator::create_device_buffer(int width, int height, int stride)\r
 {\r
        CASPAR_VERIFY(stride > 0 && stride < 5);\r
        CASPAR_VERIFY(width > 0 && height > 0);\r
@@ -125,7 +125,7 @@ safe_ptr<device_buffer> ogl_device::create_device_buffer(int width, int height,
        });\r
 }\r
 \r
-safe_ptr<host_buffer> ogl_device::allocate_host_buffer(int size, host_buffer::usage usage)\r
+safe_ptr<host_buffer> accelerator::allocate_host_buffer(int size, host_buffer::usage usage)\r
 {\r
        std::shared_ptr<host_buffer> buffer;\r
 \r
@@ -160,7 +160,7 @@ safe_ptr<host_buffer> ogl_device::allocate_host_buffer(int size, host_buffer::us
        return make_safe_ptr(buffer);\r
 }\r
        \r
-safe_ptr<host_buffer> ogl_device::create_host_buffer(int size, host_buffer::usage usage)\r
+safe_ptr<host_buffer> accelerator::create_host_buffer(int size, host_buffer::usage usage)\r
 {\r
        CASPAR_VERIFY(usage == host_buffer::usage::write_only || usage == host_buffer::usage::read_only);\r
        CASPAR_VERIFY(size > 0);\r
@@ -188,12 +188,12 @@ safe_ptr<host_buffer> ogl_device::create_host_buffer(int size, host_buffer::usag
        });\r
 }\r
 \r
-safe_ptr<ogl_device> ogl_device::create()\r
+safe_ptr<accelerator> accelerator::create()\r
 {\r
-       return safe_ptr<ogl_device>(new ogl_device());\r
+       return safe_ptr<accelerator>(new accelerator());\r
 }\r
 \r
-boost::unique_future<void> ogl_device::gc()\r
+boost::unique_future<void> accelerator::gc()\r
 {      \r
        return begin_invoke([=]\r
        {\r
@@ -219,7 +219,7 @@ boost::unique_future<void> ogl_device::gc()
        }, high_priority);\r
 }\r
 \r
-std::wstring ogl_device::version()\r
+std::wstring accelerator::version()\r
 {      \r
        static std::wstring ver = L"Not found";\r
        try\r
@@ -233,7 +233,7 @@ std::wstring ogl_device::version()
 }\r
 \r
 \r
-void ogl_device::enable(GLenum cap)\r
+void accelerator::enable(GLenum cap)\r
 {\r
        auto& val = caps_[cap];\r
        if(!val)\r
@@ -243,7 +243,7 @@ void ogl_device::enable(GLenum cap)
        }\r
 }\r
 \r
-void ogl_device::disable(GLenum cap)\r
+void accelerator::disable(GLenum cap)\r
 {\r
        auto& val = caps_[cap];\r
        if(val)\r
@@ -253,7 +253,7 @@ void ogl_device::disable(GLenum cap)
        }\r
 }\r
 \r
-void ogl_device::viewport(int x, int y, int width, int height)\r
+void accelerator::viewport(int x, int y, int width, int height)\r
 {\r
        std::array<GLint, 4> viewport = {{x, y, width, height}};\r
        if(viewport != viewport_)\r
@@ -263,7 +263,7 @@ void ogl_device::viewport(int x, int y, int width, int height)
        }\r
 }\r
 \r
-void ogl_device::scissor(int x, int y, int width, int height)\r
+void accelerator::scissor(int x, int y, int width, int height)\r
 {\r
        std::array<GLint, 4> scissor = {{x, y, width, height}};\r
        if(scissor != scissor_)\r
@@ -274,7 +274,7 @@ void ogl_device::scissor(int x, int y, int width, int height)
        }\r
 }\r
 \r
-void ogl_device::stipple_pattern(const std::array<GLubyte, 32*32>& pattern)\r
+void accelerator::stipple_pattern(const std::array<GLubyte, 32*32>& pattern)\r
 {\r
        if(pattern_ != pattern)\r
        {               \r
@@ -292,7 +292,7 @@ void ogl_device::stipple_pattern(const std::array<GLubyte, 32*32>& pattern)
        }\r
 }\r
 \r
-void ogl_device::attach(device_buffer& texture)\r
+void accelerator::attach(device_buffer& texture)\r
 {      \r
        if(attached_texture_ != texture.id())\r
        {\r
@@ -308,13 +308,13 @@ void ogl_device::attach(device_buffer& texture)
        }\r
 }\r
 \r
-void ogl_device::clear(device_buffer& texture)\r
+void accelerator::clear(device_buffer& texture)\r
 {      \r
        attach(texture);\r
        GL(glClear(GL_COLOR_BUFFER_BIT));\r
 }\r
 \r
-void ogl_device::use(shader& shader)\r
+void accelerator::use(shader& shader)\r
 {\r
        if(active_shader_ != shader.id())\r
        {               \r
@@ -323,7 +323,7 @@ void ogl_device::use(shader& shader)
        }\r
 }\r
 \r
-void ogl_device::blend_func(int c1, int c2, int a1, int a2)\r
+void accelerator::blend_func(int c1, int c2, int a1, int a2)\r
 {\r
        std::array<int, 4> func = {c1, c2, a1, a2};\r
 \r
@@ -335,10 +335,20 @@ void ogl_device::blend_func(int c1, int c2, int a1, int a2)
        }\r
 }\r
 \r
-void ogl_device::blend_func(int c1, int c2)\r
+void accelerator::blend_func(int c1, int c2)\r
 {\r
        blend_func(c1, c2, c1, c2);\r
 }\r
+       \r
+boost::unique_future<safe_ptr<device_buffer>> accelerator::copy_async(safe_ptr<host_buffer>&& source, int width, int height, int stride)\r
+{\r
+       return executor_.begin_invoke([=]() -> safe_ptr<device_buffer>\r
+       {\r
+               auto result = create_device_buffer(width, height, stride);\r
+               result->copy_from(source);\r
+               return result;\r
+       }, high_priority);\r
+}\r
 \r
-}}\r
+}}}\r
 \r
similarity index 88%
rename from core/mixer/gpu/ogl_device.h
rename to core/mixer/gpu/accelerator.h
index 234c47253c62348bbda19ca05b5b153c29a9d502..c32826ac94f5abf7b6f8e8bcf082845c25f514c6 100644 (file)
@@ -42,7 +42,7 @@
 \r
 FORWARD1(boost, template<typename> class unique_future);\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar { namespace core { namespace gpu {\r
 \r
 class shader;\r
 \r
@@ -60,7 +60,7 @@ struct buffer_pool : boost::noncopyable
        }\r
 };\r
 \r
-class ogl_device : public std::enable_shared_from_this<ogl_device>\r
+class accelerator : public std::enable_shared_from_this<accelerator>\r
                                 , boost::noncopyable\r
 {      \r
        std::array<GLubyte, 32*32>               pattern_;\r
@@ -81,10 +81,10 @@ class ogl_device : public std::enable_shared_from_this<ogl_device>
 \r
        executor executor_;\r
                                \r
-       ogl_device();\r
+       accelerator();\r
 public:                \r
-       static safe_ptr<ogl_device> create();\r
-       ~ogl_device();\r
+       static safe_ptr<accelerator> create();\r
+       ~accelerator();\r
 \r
        // Not thread-safe, must be called inside of context\r
        void enable(GLenum cap);\r
@@ -121,9 +121,11 @@ public:
 \r
        std::wstring version();\r
 \r
+       boost::unique_future<safe_ptr<device_buffer>> copy_async(safe_ptr<host_buffer>&& source, int width, int height, int stride);\r
+\r
 private:\r
        safe_ptr<device_buffer> allocate_device_buffer(int width, int height, int stride);\r
        safe_ptr<host_buffer> allocate_host_buffer(int size, host_buffer::usage usage);\r
 };\r
 \r
-}}
\ No newline at end of file
+}}}
\ No newline at end of file
diff --git a/core/mixer/gpu/device_buffer.cpp b/core/mixer/gpu/device_buffer.cpp
deleted file mode 100644 (file)
index 85821e9..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#include "../../stdafx.h"\r
-\r
-#include "device_buffer.h"\r
-#include "ogl_device.h"\r
-\r
-#include <common/exception/exceptions.h>\r
-#include <common/gl/gl_check.h>\r
-\r
-#include <gl/glew.h>\r
-\r
-#include <tbb/atomic.h>\r
-\r
-#include <boost/thread/future.hpp>\r
-\r
-namespace caspar { namespace core {\r
-       \r
-static GLenum FORMAT[] = {0, GL_RED, GL_RG, GL_BGR, GL_BGRA};\r
-static GLenum INTERNAL_FORMAT[] = {0, GL_R8, GL_RG8, GL_RGB8, GL_RGBA8};       \r
-static GLenum TYPE[] = {0, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT_8_8_8_8_REV}; \r
-\r
-unsigned int format(int stride)\r
-{\r
-       return FORMAT[stride];\r
-}\r
-\r
-static tbb::atomic<int> g_total_count;\r
-\r
-struct device_buffer::impl : boost::noncopyable\r
-{\r
-       std::weak_ptr<ogl_device>       parent_;\r
-       GLuint                                          id_;\r
-\r
-       const int width_;\r
-       const int height_;\r
-       const int stride_;\r
-public:\r
-       impl(std::weak_ptr<ogl_device> parent, int width, int height, int stride) \r
-               : parent_(parent)\r
-               , width_(width)\r
-               , height_(height)\r
-               , stride_(stride)\r
-       {       \r
-               GL(glGenTextures(1, &id_));\r
-               GL(glBindTexture(GL_TEXTURE_2D, id_));\r
-               GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));\r
-               GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));\r
-               GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));\r
-               GL(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));\r
-               GL(glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT[stride_], width_, height_, 0, FORMAT[stride_], TYPE[stride_], NULL));\r
-               GL(glBindTexture(GL_TEXTURE_2D, 0));\r
-               CASPAR_LOG(trace) << "[device_buffer] [" << ++g_total_count << L"] allocated size:" << width*height*stride;     \r
-       }       \r
-\r
-       ~impl()\r
-       {\r
-               try\r
-               {\r
-                       GL(glDeleteTextures(1, &id_));\r
-                       //CASPAR_LOG(trace) << "[device_buffer] [" << --g_total_count << L"] deallocated size:" << width_*height_*stride_;\r
-               }\r
-               catch(...)\r
-               {\r
-                       CASPAR_LOG_CURRENT_EXCEPTION();\r
-               }\r
-       }\r
-       \r
-       void bind()\r
-       {\r
-               GL(glBindTexture(GL_TEXTURE_2D, id_));\r
-       }\r
-\r
-       void bind(int index)\r
-       {\r
-               GL(glActiveTexture(GL_TEXTURE0+index));\r
-               bind();\r
-       }\r
-\r
-       void unbind()\r
-       {\r
-               GL(glBindTexture(GL_TEXTURE_2D, 0));\r
-       }\r
-               \r
-       void copy_from(const safe_ptr<host_buffer>& source)\r
-       {\r
-               auto ogl = parent_.lock();\r
-               if(!ogl)\r
-                       BOOST_THROW_EXCEPTION(invalid_operation());\r
-\r
-               ogl->begin_invoke([=]\r
-               {\r
-                       source->unmap();\r
-                       source->bind();\r
-                       GL(glBindTexture(GL_TEXTURE_2D, id_));\r
-                       GL(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, FORMAT[stride_], TYPE[stride_], NULL));\r
-                       GL(glBindTexture(GL_TEXTURE_2D, 0));\r
-                       source->unbind();\r
-               }, high_priority);\r
-       }\r
-\r
-       void copy_to(const safe_ptr<host_buffer>& dest)\r
-       {\r
-               auto ogl = parent_.lock();\r
-               if(!ogl)\r
-                       BOOST_THROW_EXCEPTION(invalid_operation());\r
-\r
-               ogl->begin_invoke([=]\r
-               {\r
-                       dest->unmap();\r
-                       dest->bind();\r
-                       GL(glBindTexture(GL_TEXTURE_2D, id_));\r
-                       GL(glReadPixels(0, 0, width_, height_, FORMAT[stride_], TYPE[stride_], NULL));\r
-                       GL(glBindTexture(GL_TEXTURE_2D, 0));\r
-                       dest->unbind();\r
-               }, high_priority);\r
-       }\r
-};\r
-\r
-device_buffer::device_buffer(std::weak_ptr<ogl_device> parent, int width, int height, int stride) : impl_(new impl(parent, width, height, stride)){}\r
-int device_buffer::stride() const { return impl_->stride_; }\r
-int device_buffer::width() const { return impl_->width_; }\r
-int device_buffer::height() const { return impl_->height_; }\r
-void device_buffer::bind(int index){impl_->bind(index);}\r
-void device_buffer::unbind(){impl_->unbind();}\r
-void device_buffer::copy_from(const safe_ptr<host_buffer>& source){impl_->copy_from(source);}\r
-void device_buffer::copy_to(const safe_ptr<host_buffer>& dest){impl_->copy_to(dest);}\r
-int device_buffer::id() const{ return impl_->id_;}\r
-\r
-\r
-}}
\ No newline at end of file
diff --git a/core/mixer/gpu/host_buffer.cpp b/core/mixer/gpu/host_buffer.cpp
deleted file mode 100644 (file)
index 303a1f3..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#include "../../stdafx.h"\r
-\r
-#include "host_buffer.h"\r
-\r
-#include "device_buffer.h"\r
-#include "ogl_device.h"\r
-\r
-#include <common/exception/exceptions.h>\r
-#include <common/gl/gl_check.h>\r
-\r
-#include <gl/glew.h>\r
-\r
-#include <tbb/atomic.h>\r
-\r
-namespace caspar { namespace core {\r
-\r
-static tbb::atomic<int> g_w_total_count;\r
-static tbb::atomic<int> g_r_total_count;\r
-                                                                                                                                                                                                                                                                                                                               \r
-struct host_buffer::impl : boost::noncopyable\r
-{      \r
-       GLuint                                          pbo_;\r
-       const int                                       size_;\r
-       tbb::atomic<void*>                      data_;\r
-       GLenum                                          usage_;\r
-       GLenum                                          target_;\r
-       std::weak_ptr<ogl_device>       parent_;\r
-\r
-public:\r
-       impl(std::weak_ptr<ogl_device> parent, int size, host_buffer::usage usage) \r
-               : parent_(parent)\r
-               , size_(size)\r
-               , pbo_(0)\r
-               , target_(usage == host_buffer::usage::write_only ? GL_PIXEL_UNPACK_BUFFER : GL_PIXEL_PACK_BUFFER)\r
-               , usage_(usage == host_buffer::usage::write_only ? GL_STREAM_DRAW : GL_STREAM_READ)\r
-       {\r
-               data_ = nullptr;\r
-               GL(glGenBuffers(1, &pbo_));\r
-               bind();\r
-               if(usage_ != GL_STREAM_DRAW)    \r
-                       GL(glBufferData(target_, size_, NULL, usage_)); \r
-               unbind();\r
-\r
-               if(!pbo_)\r
-                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info("Failed to allocate buffer."));\r
-\r
-               CASPAR_LOG(trace) << "[host_buffer] [" << ++(usage_ == host_buffer::usage::write_only ? g_w_total_count : g_r_total_count) << L"] allocated size:" << size_ << " usage: " << (usage == host_buffer::usage::write_only ? "write_only" : "read_only");\r
-       }       \r
-\r
-       ~impl()\r
-       {\r
-               try\r
-               {\r
-                       GL(glDeleteBuffers(1, &pbo_));\r
-                       //CASPAR_LOG(trace) << "[host_buffer] [" << --(usage_ == write_only ? g_w_total_count : g_r_total_count) << L"] deallocated size:" << size_ << " usage: " << (usage_ == write_only ? "write_only" : "read_only");\r
-               }\r
-               catch(...)\r
-               {\r
-                       CASPAR_LOG_CURRENT_EXCEPTION();\r
-               }\r
-       }\r
-\r
-       void* map()\r
-       {\r
-               if(data_ != nullptr)\r
-                       return data_;\r
-\r
-               GL(glBindBuffer(target_, pbo_));\r
-               if(usage_ == GL_STREAM_DRAW)                    \r
-                       GL(glBufferData(target_, size_, NULL, usage_)); // Notify OpenGL that we don't care about previous data.\r
-               \r
-               data_ = GL2(glMapBuffer(target_, usage_ == GL_STREAM_DRAW ? GL_WRITE_ONLY : GL_READ_ONLY));  \r
-               GL(glBindBuffer(target_, 0));\r
-               if(!data_)\r
-                       BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Failed to map target_ OpenGL Pixel Buffer Object."));\r
-\r
-               return data_;\r
-       }\r
-       \r
-       void unmap()\r
-       {\r
-               if(data_ == nullptr)\r
-                       return;\r
-               \r
-               GL(glBindBuffer(target_, pbo_));\r
-               GL(glUnmapBuffer(target_));     \r
-               if(usage_ == GL_STREAM_READ)                    \r
-                       GL(glBufferData(target_, size_, NULL, usage_)); // Notify OpenGL that we don't care about previous data.\r
-               data_ = nullptr;        \r
-               GL(glBindBuffer(target_, 0));\r
-       }\r
-\r
-       void bind()\r
-       {\r
-               GL(glBindBuffer(target_, pbo_));\r
-       }\r
-\r
-       void unbind()\r
-       {\r
-               GL(glBindBuffer(target_, 0));\r
-       }\r
-       \r
-       void* data()\r
-       {\r
-               if(data_ != nullptr)\r
-                       return data_;\r
-\r
-               auto ogl = parent_.lock();\r
-\r
-               if(!ogl)\r
-                       BOOST_THROW_EXCEPTION(invalid_operation());\r
-               \r
-               return ogl->invoke([&]\r
-               {\r
-                       return map();\r
-               }, high_priority);\r
-       }\r
-};\r
-\r
-host_buffer::host_buffer(std::weak_ptr<ogl_device> parent, int size, usage usage) : impl_(new impl(parent, size, usage)){}\r
-const void* host_buffer::data() const {return impl_->data_;}\r
-void* host_buffer::data() {return impl_->data();}\r
-void host_buffer::map(){impl_->map();}\r
-void host_buffer::unmap(){impl_->unmap();}\r
-void host_buffer::bind(){impl_->bind();}\r
-void host_buffer::unbind(){impl_->unbind();}\r
-int host_buffer::size() const { return impl_->size_; }\r
-\r
-}}
\ No newline at end of file
diff --git a/core/mixer/gpu/host_buffer.h b/core/mixer/gpu/host_buffer.h
deleted file mode 100644 (file)
index 881827a..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#pragma once\r
-\r
-#include <common/memory/safe_ptr.h>\r
-#include <common/enum_class.h>\r
-\r
-#include <boost/noncopyable.hpp>\r
-\r
-namespace caspar { namespace core {\r
-                       \r
-class host_buffer : boost::noncopyable\r
-{\r
-public:\r
-       struct usage_def\r
-       {\r
-               enum type\r
-               {\r
-                       write_only,\r
-                       read_only\r
-               };\r
-       };\r
-       typedef enum_class<usage_def> usage;\r
-       \r
-       const void* data() const;\r
-       void* data();\r
-       int size() const;       \r
-       \r
-private:\r
-       friend class ogl_device;\r
-       friend class device_buffer;\r
-\r
-       void bind();\r
-       void unbind();\r
-\r
-       void map();\r
-       void unmap();\r
-\r
-       host_buffer(std::weak_ptr<ogl_device> parent, int size, usage usage);\r
-\r
-       struct impl;\r
-       safe_ptr<impl> impl_;\r
-};\r
-\r
-}}
\ No newline at end of file
similarity index 93%
rename from core/mixer/image/image_kernel.cpp
rename to core/mixer/gpu/image/image_kernel.cpp
index 7d2ad906b5da4db00b95ecce4a2e67be15b28b9a..32ec1b0642321c385aa0fefa8db0fae0d9e4915e 100644 (file)
 * Author: Robert Nagy, ronag89@gmail.com\r
 */\r
 \r
-#include "../../stdafx.h"\r
+#include "../../../stdafx.h"\r
 \r
 #include "image_kernel.h"\r
 \r
-#include "shader/image_shader.h"\r
-#include "shader/blending_glsl.h"\r
+#include "blending_glsl.h"\r
+#include "image_shader.h"\r
 \r
-#include "../gpu/shader.h"\r
-#include "../gpu/device_buffer.h"\r
-#include "../gpu/ogl_device.h"\r
+#include "../shader.h"\r
+#include "../device_buffer.h"\r
+#include "../accelerator.h"\r
 \r
 #include <common/exception/exceptions.h>\r
 #include <common/gl/gl_check.h>\r
@@ -41,7 +41,7 @@
 #include <boost/noncopyable.hpp>\r
 #include <common/assert.h>\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar { namespace core { namespace gpu {\r
        \r
 __declspec(align(16)) std::array<GLubyte, 32*32> upper_pattern = {{\r
        0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,\r
@@ -63,11 +63,11 @@ __declspec(align(16)) std::array<GLubyte, 32*32> progressive_pattern = {{
 \r
 struct image_kernel::impl : boost::noncopyable\r
 {      \r
-       safe_ptr<ogl_device>    ogl_;\r
+       safe_ptr<accelerator>   ogl_;\r
        safe_ptr<shader>                shader_;\r
        bool                                    blend_modes_;\r
                                                        \r
-       impl(const safe_ptr<ogl_device>& ogl)\r
+       impl(const safe_ptr<accelerator>& ogl)\r
                : ogl_(ogl)\r
                , shader_(ogl_->invoke([&]{return get_image_shader(*ogl, blend_modes_);}))\r
        {\r
@@ -215,10 +215,10 @@ struct image_kernel::impl : boost::noncopyable
        }\r
 };\r
 \r
-image_kernel::image_kernel(const safe_ptr<ogl_device>& ogl) : impl_(new impl(ogl)){}\r
+image_kernel::image_kernel(const safe_ptr<accelerator>& ogl) : impl_(new impl(ogl)){}\r
 void image_kernel::draw(draw_params&& params)\r
 {\r
        impl_->draw(std::move(params));\r
 }\r
 \r
-}}
\ No newline at end of file
+}}}
\ No newline at end of file
similarity index 88%
rename from core/mixer/image/image_kernel.h
rename to core/mixer/gpu/image/image_kernel.h
index b7cb73f41b08ce17b73b5763053f82c816e9a3f4..f56b749d47345c4e6f95bfd364a01d20f9869c6b 100644 (file)
@@ -21,7 +21,7 @@
 \r
 #pragma once\r
 \r
-#include "blend_modes.h"\r
+#include "../../image/blend_modes.h"\r
 \r
 #include <common/enum_class.h>\r
 #include <common/memory/safe_ptr.h>\r
@@ -31,7 +31,7 @@
 \r
 #include <boost/noncopyable.hpp>\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar { namespace core { namespace gpu {\r
        \r
 struct keyer_def\r
 {\r
@@ -64,11 +64,11 @@ struct draw_params sealed
 class image_kernel sealed : boost::noncopyable\r
 {\r
 public:\r
-       image_kernel(const safe_ptr<class ogl_device>& ogl);\r
+       image_kernel(const safe_ptr<class accelerator>& ogl);\r
        void draw(draw_params&& params);\r
 private:\r
        struct impl;\r
        safe_ptr<impl> impl_;\r
 };\r
 \r
-}}
\ No newline at end of file
+}}}
\ No newline at end of file
similarity index 88%
rename from core/mixer/image/image_mixer.cpp
rename to core/mixer/gpu/image/image_mixer.cpp
index 5eda261017e32c7b1b7e91827f99fe696a643a21..4b6cb756b0e42d6c72d653d372fa4a3ad1909e64 100644 (file)
 * Author: Robert Nagy, ronag89@gmail.com\r
 */\r
 \r
-#include "../../stdafx.h"\r
+#include "../../../stdafx.h"\r
 \r
 #include "image_mixer.h"\r
 \r
 #include "image_kernel.h"\r
-#include "../write_frame.h"\r
-#include "../gpu/ogl_device.h"\r
-#include "../gpu/host_buffer.h"\r
-#include "../gpu/device_buffer.h"\r
+#include "../accelerator.h"\r
+#include "../host_buffer.h"\r
+#include "../device_buffer.h"\r
+#include "../../write_frame.h"\r
 \r
 #include <common/gl/gl_check.h>\r
 \r
 \r
 using namespace boost::assign;\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar { namespace core { namespace gpu {\r
        \r
 struct item\r
 {\r
-       pixel_format_desc                                               pix_desc;\r
-       std::vector<safe_ptr<device_buffer>>    textures;\r
-       frame_transform                                                 transform;\r
+       pixel_format_desc                                                                                       pix_desc;\r
+       std::vector<boost::shared_future<safe_ptr<device_buffer>>>      textures;\r
+       frame_transform                                                                                         transform;\r
 };\r
 \r
 typedef std::pair<blend_mode, std::vector<item>> layer;\r
 \r
 class image_renderer\r
 {\r
-       safe_ptr<ogl_device>                    ogl_;\r
+       safe_ptr<accelerator>                   ogl_;\r
        image_kernel                                    kernel_;        \r
 public:\r
-       image_renderer(const safe_ptr<ogl_device>& ogl)\r
+       image_renderer(const safe_ptr<accelerator>& ogl)\r
                : ogl_(ogl)\r
                , kernel_(ogl_)\r
        {\r
@@ -160,7 +160,8 @@ private:
        {                       \r
                draw_params draw_params;\r
                draw_params.pix_desc                            = std::move(item.pix_desc);\r
-               draw_params.textures                            = std::move(item.textures);\r
+               BOOST_FOREACH(auto& future_texture, item.textures)\r
+                       draw_params.textures.push_back(future_texture.get());\r
                draw_params.transform                           = std::move(item.transform);\r
 \r
                if(item.transform.is_key)\r
@@ -225,12 +226,12 @@ private:
                \r
 struct image_mixer::impl : boost::noncopyable\r
 {      \r
-       safe_ptr<ogl_device>                    ogl_;\r
+       safe_ptr<accelerator>                   ogl_;\r
        image_renderer                                  renderer_;\r
        std::vector<frame_transform>    transform_stack_;\r
        std::vector<layer>                              layers_; // layer/stream/items\r
 public:\r
-       impl(const safe_ptr<ogl_device>& ogl) \r
+       impl(const safe_ptr<accelerator>& ogl) \r
                : ogl_(ogl)\r
                , renderer_(ogl)\r
                , transform_stack_(1)   \r
@@ -272,7 +273,7 @@ public:
        }\r
 };\r
 \r
-image_mixer::image_mixer(const safe_ptr<ogl_device>& ogl) : impl_(new impl(ogl)){}\r
+image_mixer::image_mixer(const safe_ptr<accelerator>& ogl) : impl_(new impl(ogl)){}\r
 void image_mixer::begin(basic_frame& frame){impl_->begin(frame);}\r
 void image_mixer::visit(write_frame& frame){impl_->visit(frame);}\r
 void image_mixer::end(){impl_->end();}\r
@@ -280,4 +281,4 @@ boost::unique_future<safe_ptr<host_buffer>> image_mixer::operator()(const video_
 void image_mixer::begin_layer(blend_mode blend_mode){impl_->begin_layer(blend_mode);}\r
 void image_mixer::end_layer(){impl_->end_layer();}\r
 \r
-}}
\ No newline at end of file
+}}}
\ No newline at end of file
similarity index 60%
rename from core/mixer/gpu/device_buffer.h
rename to core/mixer/gpu/image/image_mixer.h
index cb31cb1756f6108a53023513eacc66422e0479c9..557efad6ee0845d3a5803bea1c00aa578f154021 100644 (file)
 \r
 #pragma once\r
 \r
-#include <common/memory/safe_ptr.h>\r
+#include "../../image/blend_modes.h"\r
+#include "../../image/image_mixer.h"\r
+\r
 #include <common/forward.h>\r
+#include <common/memory/safe_ptr.h>\r
 \r
-#include <boost/noncopyable.hpp>\r
+#include <core/producer/frame/frame_visitor.h>\r
 \r
 FORWARD1(boost, template<typename> class unique_future);\r
 \r
-namespace caspar { namespace core {\r
-               \r
-class host_buffer;\r
-class ogl_device;\r
-\r
-class device_buffer : boost::noncopyable\r
+namespace caspar { namespace core { namespace gpu {\r
+       \r
+class image_mixer sealed : public core::image_mixer\r
 {\r
-public:        \r
-       int stride() const;     \r
-       int width() const;\r
-       int height() const;\r
+public:\r
+       image_mixer(const safe_ptr<class accelerator>& ogl);\r
+       \r
+       virtual void begin(class basic_frame& frame);\r
+       virtual void visit(class write_frame& frame);\r
+       virtual void end();\r
+\r
+       void begin_layer(blend_mode blend_mode);\r
+       void end_layer();\r
+               \r
+       virtual boost::unique_future<safe_ptr<class host_buffer>> operator()(const struct video_format_desc& format_desc) override;\r
                \r
-       void copy_from(const safe_ptr<host_buffer>& source);\r
-       void copy_to(const safe_ptr<host_buffer>& dest);\r
 private:\r
-       friend class ogl_device;\r
-       friend class image_kernel;\r
-       device_buffer(std::weak_ptr<ogl_device> parent, int width, int height, int stride);\r
-                       \r
-       void bind(int index);\r
-       void unbind();\r
-       int id() const;\r
-\r
        struct impl;\r
        safe_ptr<impl> impl_;\r
 };\r
-       \r
-unsigned int format(int stride);\r
 \r
-}}
\ No newline at end of file
+}}}
\ No newline at end of file
similarity index 95%
rename from core/mixer/image/shader/image_shader.cpp
rename to core/mixer/gpu/image/image_shader.cpp
index 1f902add587c4631a63db485cc93487fa574e2ee..4b92e367c36e741bc665f2a0b78f730e200ac785 100644 (file)
@@ -24,7 +24,7 @@
 #include "image_shader.h"\r
 \r
 #include "../../gpu/shader.h"\r
-#include "../../gpu/ogl_device.h"\r
+#include "../../gpu/accelerator.h"\r
 \r
 #include "blending_glsl.h"\r
 \r
@@ -33,7 +33,7 @@
 \r
 #include <tbb/mutex.h>\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar { namespace core { namespace gpu {\r
 \r
 std::shared_ptr<shader> g_shader;\r
 tbb::mutex                             g_shader_mutex;\r
@@ -273,7 +273,7 @@ std::string get_fragment(bool blend_modes)
        "}                                                                                                                                                                      \n";\r
 }\r
 \r
-safe_ptr<shader> get_image_shader(ogl_device& ogl, bool& blend_modes)\r
+safe_ptr<shader> get_image_shader(accelerator& ogl, bool& blend_modes)\r
 {\r
        tbb::mutex::scoped_lock lock(g_shader_mutex);\r
 \r
@@ -307,4 +307,4 @@ safe_ptr<shader> get_image_shader(ogl_device& ogl, bool& blend_modes)
        return make_safe_ptr(g_shader);\r
 }\r
 \r
-}}\r
+}}}\r
similarity index 83%
rename from core/mixer/image/shader/image_shader.h
rename to core/mixer/gpu/image/image_shader.h
index 11dc499b19375ae6f4d3b37e133601e7b287a7ae..6c47bc2c093d9097185cdfdac59960f2e3950cca 100644 (file)
 \r
 #include <common/memory/safe_ptr.h>\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar { namespace core { namespace gpu {\r
 \r
 class shader;\r
-class ogl_device;\r
+class accelerator;\r
 \r
 struct texture_id\r
 {\r
@@ -42,7 +42,7 @@ struct texture_id
        };\r
 };\r
 \r
-safe_ptr<shader> get_image_shader(ogl_device& ogl, bool& blend_modes);\r
+safe_ptr<shader> get_image_shader(accelerator& ogl, bool& blend_modes);\r
 \r
 \r
-}}
\ No newline at end of file
+}}}
\ No newline at end of file
diff --git a/core/mixer/gpu/shader.cpp b/core/mixer/gpu/shader.cpp
deleted file mode 100644 (file)
index 5628f82..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#include "../../../stdafx.h"\r
-\r
-#include "shader.h"\r
-\r
-#include <common/gl/gl_check.h>\r
-\r
-#include <gl/glew.h>\r
-\r
-#include <unordered_map>\r
-\r
-namespace caspar { namespace core {\r
-\r
-struct shader::impl : boost::noncopyable\r
-{\r
-       GLuint program_;\r
-       std::unordered_map<std::string, GLint> locations_;\r
-public:\r
-\r
-       impl(const std::string& vertex_source_str, const std::string& fragment_source_str) : program_(0)\r
-       {\r
-               GLint success;\r
-       \r
-               const char* vertex_source = vertex_source_str.c_str();\r
-                                               \r
-               auto vertex_shader = glCreateShaderObjectARB(GL_VERTEX_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
-                       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
-               const char* fragment_source = fragment_source_str.c_str();\r
-                                               \r
-               auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);\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(fragmemt_shader));\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(glLinkProgramARB(program_));\r
-                       \r
-               GL(glDeleteObjectARB(vertex_shader));\r
-               GL(glDeleteObjectARB(fragmemt_shader));\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
-       }\r
-       \r
-       ~impl()\r
-       {\r
-               glDeleteProgram(program_);\r
-       }\r
-\r
-       GLint get_location(const char* name)\r
-       {\r
-               auto it = locations_.find(name);\r
-               if(it == locations_.end())\r
-                       it = locations_.insert(std::make_pair(name, glGetUniformLocation(program_, name))).first;\r
-               return it->second;\r
-       }\r
-       \r
-       void set(const std::string& name, bool value)\r
-       {\r
-               set(name, value ? 1 : 0);\r
-       }\r
-\r
-       void set(const std::string& name, int value)\r
-       {\r
-               GL(glUniform1i(get_location(name.c_str()), value));\r
-       }\r
-       \r
-       void set(const std::string& name, float value)\r
-       {\r
-               GL(glUniform1f(get_location(name.c_str()), value));\r
-       }\r
-\r
-       void set(const std::string& name, double value)\r
-       {\r
-               GL(glUniform1f(get_location(name.c_str()), static_cast<float>(value)));\r
-       }\r
-};\r
-\r
-\r
-shader::shader(const std::string& vertex_source_str, const std::string& fragment_source_str) : impl_(new impl(vertex_source_str, fragment_source_str)){}\r
-void shader::set(const std::string& name, bool value){impl_->set(name, value);}\r
-void shader::set(const std::string& name, int value){impl_->set(name, value);}\r
-void shader::set(const std::string& name, float value){impl_->set(name, value);}\r
-void shader::set(const std::string& name, double value){impl_->set(name, value);}\r
-int shader::id() const{return impl_->program_;}\r
-\r
-}}
\ No newline at end of file
diff --git a/core/mixer/gpu/shader.h b/core/mixer/gpu/shader.h
deleted file mode 100644 (file)
index b0ea0ab..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#pragma once\r
-\r
-#include <common/memory/safe_ptr.h>\r
-\r
-#include <boost/noncopyable.hpp>\r
-\r
-#include <string>\r
-\r
-namespace caspar { namespace core {\r
-               \r
-class shader : boost::noncopyable\r
-{\r
-public:\r
-       shader(const std::string& vertex_source_str, const std::string& fragment_source_str);\r
-       void set(const std::string& name, bool value);\r
-       void set(const std::string& name, int value);\r
-       void set(const std::string& name, float value);\r
-       void set(const std::string& name, double value);\r
-private:\r
-       friend class ogl_device;\r
-       struct impl;\r
-       safe_ptr<impl> impl_;\r
-\r
-       int id() const;\r
-};\r
-\r
-}}
\ No newline at end of file
diff --git a/core/mixer/image/blend_modes.cpp b/core/mixer/image/blend_modes.cpp
deleted file mode 100644 (file)
index 04a51b5..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#include "../../StdAfx.h"\r
-\r
-#include "blend_modes.h"\r
-\r
-#include <boost/algorithm/string.hpp>\r
-\r
-namespace caspar { namespace core {\r
-               \r
-blend_mode get_blend_mode(const std::wstring& str)\r
-{\r
-       if(boost::iequals(str, L"normal"))\r
-               return blend_mode::normal;\r
-       else if(boost::iequals(str, L"lighten"))\r
-               return blend_mode::lighten;\r
-       else if(boost::iequals(str, L"darken"))\r
-               return blend_mode::darken;\r
-       else if(boost::iequals(str, L"multiply"))\r
-               return blend_mode::multiply;\r
-       else if(boost::iequals(str, L"average"))\r
-               return blend_mode::average;\r
-       else if(boost::iequals(str, L"add"))\r
-               return blend_mode::add;\r
-       else if(boost::iequals(str, L"subtract"))\r
-               return blend_mode::subtract;\r
-       else if(boost::iequals(str, L"difference"))\r
-               return blend_mode::difference;\r
-       else if(boost::iequals(str, L"negation"))\r
-               return blend_mode::negation;\r
-       else if(boost::iequals(str, L"exclusion"))\r
-               return blend_mode::exclusion;\r
-       else if(boost::iequals(str, L"screen"))\r
-               return blend_mode::screen;\r
-       else if(boost::iequals(str, L"overlay"))\r
-               return blend_mode::overlay;\r
-       else if(boost::iequals(str, L"soft_light"))\r
-               return blend_mode::soft_light;\r
-       else if(boost::iequals(str, L"hard_light"))\r
-               return blend_mode::hard_light;\r
-       else if(boost::iequals(str, L"color_dodge"))\r
-               return blend_mode::color_dodge;\r
-       else if(boost::iequals(str, L"color_burn"))\r
-               return blend_mode::color_burn;\r
-       else if(boost::iequals(str, L"linear_dodge"))\r
-               return blend_mode::linear_dodge;\r
-       else if(boost::iequals(str, L"linear_burn"))\r
-               return blend_mode::linear_burn;\r
-       else if(boost::iequals(str, L"linear_light"))\r
-               return blend_mode::linear_light;\r
-       else if(boost::iequals(str, L"vivid_light"))\r
-               return blend_mode::vivid_light;\r
-       else if(boost::iequals(str, L"pin_light"))\r
-               return blend_mode::pin_light;\r
-       else if(boost::iequals(str, L"hard_mix"))\r
-               return blend_mode::hard_mix;\r
-       else if(boost::iequals(str, L"reflect"))\r
-               return blend_mode::reflect;\r
-       else if(boost::iequals(str, L"glow"))\r
-               return blend_mode::glow;\r
-       else if(boost::iequals(str, L"phoenix"))\r
-               return blend_mode::phoenix;\r
-       else if(boost::iequals(str, L"contrast"))\r
-               return blend_mode::contrast;\r
-       else if(boost::iequals(str, L"saturation"))\r
-               return blend_mode::saturation;\r
-       else if(boost::iequals(str, L"color"))\r
-               return blend_mode::color;\r
-       else if(boost::iequals(str, L"luminosity"))\r
-               return blend_mode::luminosity;\r
-               \r
-       return blend_mode::normal;\r
-}\r
-\r
-}}
\ No newline at end of file
diff --git a/core/mixer/image/blend_modes.h b/core/mixer/image/blend_modes.h
deleted file mode 100644 (file)
index cdf044f..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#pragma once\r
-\r
-#include <common/enum_class.h>\r
-\r
-namespace caspar { namespace core {\r
-               \r
-struct blend_mode_def\r
-{\r
-       enum type\r
-       {\r
-               normal = 0,\r
-               lighten,\r
-               darken,\r
-               multiply,\r
-               average,\r
-               add,\r
-               subtract,\r
-               difference,\r
-               negation,\r
-               exclusion,\r
-               screen,\r
-               overlay,\r
-               soft_light,\r
-               hard_light,\r
-               color_dodge,\r
-               color_burn,\r
-               linear_dodge,\r
-               linear_burn,\r
-               linear_light,\r
-               vivid_light,\r
-               pin_light,\r
-               hard_mix,\r
-               reflect,\r
-               glow,\r
-               phoenix,\r
-               contrast,\r
-               saturation,\r
-               color,\r
-               luminosity,\r
-               mix,\r
-               blend_mode_count \r
-       };\r
-};\r
-typedef enum_class<blend_mode_def> blend_mode;\r
-\r
-blend_mode get_blend_mode(const std::wstring& str);\r
-\r
-}}
\ No newline at end of file
index 2b950971c4e7bb66898e59c6101575e40f35b752..43c26293b61e45f8ab426f814ab7954906394c38 100644 (file)
 #include <core/producer/frame/frame_visitor.h>\r
 \r
 FORWARD1(boost, template<typename> class unique_future);\r
+FORWARD3(caspar, core, gpu, class host_buffer);\r
 \r
 namespace caspar { namespace core {\r
        \r
-class image_mixer sealed : public frame_visitor\r
+struct image_mixer : public frame_visitor\r
 {\r
-public:\r
-       image_mixer(const safe_ptr<class ogl_device>& ogl);\r
+       virtual ~image_mixer(){}\r
        \r
-       virtual void begin(class basic_frame& frame);\r
-       virtual void visit(class write_frame& frame);\r
-       virtual void end();\r
+       virtual void begin(class basic_frame& frame) = 0;\r
+       virtual void visit(class write_frame& frame) = 0;\r
+       virtual void end() = 0;\r
 \r
-       void begin_layer(blend_mode blend_mode);\r
-       void end_layer();\r
+       virtual void begin_layer(blend_mode blend_mode) = 0;\r
+       virtual void end_layer() = 0;\r
                \r
-       boost::unique_future<safe_ptr<class host_buffer>> operator()(const struct video_format_desc& format_desc);\r
-               \r
-private:\r
-       struct impl;\r
-       safe_ptr<impl> impl_;\r
+       virtual boost::unique_future<safe_ptr<gpu::host_buffer>> operator()(const struct video_format_desc& format_desc) = 0;\r
 };\r
 \r
 }}
\ No newline at end of file
index 39f2f3a947535796036eb23b84c1fd919e347a33..e9b96200f86715b97298a402ef3e56afcb5961ac 100644 (file)
@@ -28,6 +28,8 @@
 \r
 #include "audio/audio_mixer.h"\r
 #include "image/image_mixer.h"\r
+#include "gpu/image/image_mixer.h"\r
+#include "gpu/accelerator.h"\r
 \r
 #include <common/env.h>\r
 #include <common/concurrency/executor.h>\r
@@ -36,8 +38,6 @@
 #include <common/gl/gl_check.h>\r
 #include <common/utility/tweener.h>\r
 \r
-#include <core/mixer/read_frame.h>\r
-#include <core/mixer/write_frame.h>\r
 #include <core/producer/frame/basic_frame.h>\r
 #include <core/producer/frame/frame_factory.h>\r
 #include <core/producer/frame/frame_transform.h>\r
 namespace caspar { namespace core {\r
                \r
 struct mixer::impl : boost::noncopyable\r
-{              \r
-       safe_ptr<mixer::target_t>               target_;\r
-\r
-       safe_ptr<diagnostics::graph>    graph_;\r
-       boost::timer                                    mix_timer_;     \r
-\r
-       video_format_desc                               format_desc_;\r
-       safe_ptr<ogl_device>                    ogl_;\r
+{                      \r
+       safe_ptr<gpu::accelerator>                      ogl_;\r
        \r
-       audio_mixer                                             audio_mixer_;\r
-       image_mixer                                             image_mixer_;\r
+       audio_mixer                                                     audio_mixer_;\r
+       safe_ptr<image_mixer>                           image_mixer_;\r
        \r
        std::unordered_map<int, blend_mode>     blend_modes_;\r
                        \r
        executor executor_;\r
 \r
 public:\r
-       impl(const safe_ptr<mixer::target_t>& target, const safe_ptr<diagnostics::graph>& graph, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) \r
-               : target_(target)\r
-               , graph_(graph)\r
-               , format_desc_(format_desc)\r
-               , ogl_(ogl)\r
-               , image_mixer_(ogl)\r
-               , audio_mixer_(graph_)\r
+       impl(const safe_ptr<gpu::accelerator>& ogl) \r
+               : ogl_(ogl)\r
+               , audio_mixer_()\r
+               , image_mixer_(make_safe<gpu::image_mixer>(ogl_))\r
                , executor_(L"mixer")\r
        {                       \r
-               graph_->set_color("mix-time", diagnostics::color(1.0f, 0.0f, 0.9f, 0.8));\r
-       }\r
+       }       \r
        \r
-       void send(const std::pair<std::map<int, safe_ptr<core::basic_frame>>, std::shared_ptr<void>>& packet)\r
-       {                       \r
-               executor_.begin_invoke([=]\r
+       safe_ptr<const frame> operator()(std::map<int, safe_ptr<basic_frame>> frames, const video_format_desc& format_desc)\r
+       {               \r
+               return executor_.invoke([=]() mutable -> safe_ptr<const struct frame>\r
                {               \r
                        try\r
-                       {\r
-                               mix_timer_.restart();\r
-\r
-                               auto frames = packet.first;\r
-                               \r
+                       {                               \r
                                BOOST_FOREACH(auto& frame, frames)\r
                                {\r
                                        auto blend_it = blend_modes_.find(frame.first);\r
-                                       image_mixer_.begin_layer(blend_it != blend_modes_.end() ? blend_it->second : blend_mode::normal);\r
+                                       image_mixer_->begin_layer(blend_it != blend_modes_.end() ? blend_it->second : blend_mode::normal);\r
                                                                                                        \r
                                        frame.second->accept(audio_mixer_);                                     \r
-                                       frame.second->accept(image_mixer_);\r
+                                       frame.second->accept(*image_mixer_);\r
 \r
-                                       image_mixer_.end_layer();\r
+                                       image_mixer_->end_layer();\r
                                }\r
 \r
-                               auto image = image_mixer_(format_desc_);\r
-                               auto audio = audio_mixer_(format_desc_);\r
+                               auto image = (*image_mixer_)(format_desc);\r
+                               auto audio = audio_mixer_(format_desc);\r
 \r
-                               graph_->set_value("mix-time", mix_timer_.elapsed()*format_desc_.fps*0.5);\r
-                               \r
-                               target_->send(std::make_pair(make_safe<read_frame>(format_desc_.width, format_desc_.height, std::move(image), std::move(audio)), packet.second));       \r
+                               return read_frame::create(std::move(image), std::move(audio), format_desc);     \r
                        }\r
                        catch(...)\r
                        {\r
                                CASPAR_LOG_CURRENT_EXCEPTION();\r
+                               return frame::empty();\r
                        }       \r
                });             \r
        }\r
@@ -134,14 +119,6 @@ public:
                }, high_priority);\r
        }\r
        \r
-       void set_video_format_desc(const video_format_desc& format_desc)\r
-       {\r
-               executor_.begin_invoke([=]\r
-               {\r
-                       format_desc_ = format_desc;\r
-               });\r
-       }\r
-\r
        boost::unique_future<boost::property_tree::wptree> info() const\r
        {\r
                boost::promise<boost::property_tree::wptree> info;\r
@@ -150,10 +127,9 @@ public:
        }\r
 };\r
        \r
-mixer::mixer(const safe_ptr<target_t>& target, const safe_ptr<diagnostics::graph>& graph, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) \r
-       : impl_(new impl(target, graph, format_desc, ogl)){}\r
-void mixer::send(const std::pair<std::map<int, safe_ptr<core::basic_frame>>, std::shared_ptr<void>>& frames){ impl_->send(frames);}\r
+mixer::mixer(const safe_ptr<gpu::accelerator>& ogl) \r
+       : impl_(new impl(ogl)){}\r
 void mixer::set_blend_mode(int index, blend_mode value){impl_->set_blend_mode(index, value);}\r
-void mixer::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
 boost::unique_future<boost::property_tree::wptree> mixer::info() const{return impl_->info();}\r
+safe_ptr<const frame> mixer::operator()(std::map<int, safe_ptr<basic_frame>> frames, const struct video_format_desc& format_desc){return (*impl_)(std::move(frames), format_desc);}\r
 }}
\ No newline at end of file
index 519b546de4b0e5594842f5e1400fd09c83fc7da4..99e5617f416105d7607559d5d466cb6c1ca7496a 100644 (file)
 \r
 #include <common/forward.h>\r
 #include <common/memory/safe_ptr.h>\r
-#include <common/concurrency/target.h>\r
+#include <common/reactive.h>\r
 \r
 #include <boost/noncopyable.hpp>\r
 #include <boost/property_tree/ptree_fwd.hpp>\r
+#include <boost/thread/future.hpp>\r
 \r
 #include <map>\r
 \r
-FORWARD2(caspar, diagnostics, class graph);\r
 FORWARD1(boost, template<typename> class unique_future);\r
+FORWARD2(caspar, diagnostics, class graph);\r
+FORWARD3(caspar, core, gpu, class accelerator);\r
 \r
 namespace caspar { namespace core {\r
        \r
-class mixer sealed : public target<std::pair<std::map<int, safe_ptr<class basic_frame>>, std::shared_ptr<void>>>\r
-                                  , boost::noncopyable\r
+class mixer sealed : boost::noncopyable\r
 {\r
 public:        \r
-       typedef target<std::pair<safe_ptr<class read_frame>, std::shared_ptr<void>>> target_t;\r
-\r
-       explicit mixer(const safe_ptr<target_t>& target, const safe_ptr<diagnostics::graph>& graph, const struct video_format_desc& format_desc, const safe_ptr<class ogl_device>& ogl);\r
-               \r
-       // target\r
-\r
-       virtual void send(const std::pair<std::map<int, safe_ptr<class basic_frame>>, std::shared_ptr<void>>& frames) override; \r
-               \r
+       explicit mixer(const safe_ptr<gpu::accelerator>& ogl);\r
+                               \r
        // mixer\r
-               \r
-       void set_video_format_desc(const struct video_format_desc& format_desc);\r
-       \r
+                       \r
        void set_blend_mode(int index, blend_mode value);\r
 \r
        boost::unique_future<boost::property_tree::wptree> info() const;\r
        \r
+       // subject\r
+\r
+       safe_ptr<const struct frame> operator()(std::map<int, safe_ptr<class basic_frame>> frames, const struct video_format_desc& format_desc);\r
+\r
 private:\r
        struct impl;\r
        safe_ptr<impl> impl_;\r
index 1d51b903a0c02c11150a7247c9b5b613f1927bc3..bc61667271bd96dbdd4cfc9b36d44fb9e5fd6322 100644 (file)
@@ -22,6 +22,8 @@
 #include "../stdafx.h"\r
 \r
 #include "read_frame.h"\r
+#include "../video_format.h"\r
+#include "../producer/frame/pixel_format.h"\r
 \r
 #include "gpu/host_buffer.h"   \r
 \r
@@ -31,17 +33,20 @@ namespace caspar { namespace core {
                                                                                                                                                                                                                                                                                                                        \r
 struct read_frame::impl : boost::noncopyable\r
 {\r
-       int                                                                                     width_;\r
-       int                                                                                     height_;\r
-       boost::unique_future<safe_ptr<host_buffer>>     image_data_;\r
-       audio_buffer                                                            audio_data_;\r
+       boost::unique_future<safe_ptr<gpu::host_buffer>>        image_data_;\r
+       const audio_buffer                                                                      audio_data_;\r
+       const video_format_desc                                                         video_desc_;\r
+       pixel_format_desc                                                                       pixel_desc_;\r
 \r
 public:\r
-       impl( int width, int height, boost::unique_future<safe_ptr<host_buffer>>&& image_data, audio_buffer&& audio_data) \r
-               : width_(width)\r
-               , height_(height)\r
-               , image_data_(std::move(image_data))\r
-               , audio_data_(std::move(audio_data)){}  \r
+       impl(boost::unique_future<safe_ptr<gpu::host_buffer>>&& image_data, audio_buffer&& audio_data, const video_format_desc& format_desc) \r
+               : image_data_(std::move(image_data))\r
+               , audio_data_(std::move(audio_data))\r
+               , video_desc_(format_desc)\r
+       {\r
+               pixel_desc_.pix_fmt = core::pixel_format::bgra;\r
+               pixel_desc_.planes.push_back(core::pixel_format_desc::plane(format_desc.width, format_desc.height, 4));\r
+       }       \r
        \r
        const boost::iterator_range<const uint8_t*> image_data()\r
        {\r
@@ -54,22 +59,21 @@ public:
        }\r
 };\r
 \r
-read_frame::read_frame(int width, int height, boost::unique_future<safe_ptr<host_buffer>>&& image_data, audio_buffer&& audio_data) \r
-       : impl_(new impl(width, height, std::move(image_data), std::move(audio_data))){}\r
-read_frame::read_frame(){}\r
-const boost::iterator_range<const uint8_t*> read_frame::image_data()\r
-{\r
-       return impl_ ? impl_->image_data() : boost::iterator_range<const uint8_t*>();\r
-}\r
+read_frame::read_frame(boost::unique_future<safe_ptr<gpu::host_buffer>>&& image_data, audio_buffer&& audio_data, const video_format_desc& format_desc) \r
+       : impl_(new impl(std::move(image_data), std::move(audio_data), format_desc)){}\r
+const boost::iterator_range<const uint8_t*> read_frame::image_data() const{    return impl_->image_data();}\r
+const boost::iterator_range<const int32_t*> read_frame::audio_data() const{    return impl_->audio_data();}\r
+const pixel_format_desc& read_frame::get_pixel_format_desc() const{    return impl_->pixel_desc_;}\r
+double read_frame::get_frame_rate() const {return impl_->video_desc_.fps;}\r
+field_mode read_frame::get_field_mode() const {return impl_->video_desc_.field_mode;}\r
+int read_frame::width() const {return impl_->video_desc_.width;}\r
+int read_frame::height() const {return impl_->video_desc_.height;}\r
 \r
-const boost::iterator_range<const int32_t*> read_frame::audio_data()\r
+safe_ptr<const read_frame> read_frame::create(boost::unique_future<safe_ptr<gpu::host_buffer>>&& image_data, audio_buffer&& audio_data, const struct video_format_desc& format_desc)\r
 {\r
-       return impl_ ? impl_->audio_data() : boost::iterator_range<const int32_t*>();\r
+       return safe_ptr<const read_frame>(new read_frame(std::move(image_data), std::move(audio_data), format_desc));\r
 }\r
 \r
-int read_frame::width() const{return impl_ ? impl_->width_ : 0;}\r
-int read_frame::height() const{return impl_ ? impl_->height_ : 0;}\r
-\r
 //#include <tbb/scalable_allocator.h>\r
 //#include <tbb/parallel_for.h>\r
 //#include <tbb/enumerable_thread_specific.h>\r
@@ -85,7 +89,7 @@ int read_frame::height() const{return impl_ ? impl_->height_ : 0;}
 //\r
 //void CopyFrame( void * pSrc, void * pDest, UINT width, UINT height, UINT pitch );\r
 //\r
-//void* copy_frame(void* dest, const safe_ptr<read_frame>& frame)\r
+//void* copy_frame(void* dest, const safe_ptr<const frame>& frame)\r
 //{\r
 //     auto src                = frame->image_data().begin();\r
 //     auto height             = 720;\r
index 36b56dd4a9ff492752f9c5ee572716f2bd2262ab..8f13bd9bb8669c527bdc6c8faf0ab85541f70978 100644 (file)
 \r
 #pragma once\r
 \r
+#include "../frame.h"\r
+\r
 #include <common/memory/safe_ptr.h>\r
 #include <common/forward.h>\r
+#include <common/exception/exceptions.h>\r
 \r
 #include <core/mixer/audio/audio_mixer.h>\r
 \r
 #include <vector>\r
 \r
 FORWARD1(boost, template<typename> class unique_future);\r
+FORWARD3(caspar, core, gpu, class host_buffer);\r
 \r
 namespace caspar { namespace core {\r
        \r
-class read_frame sealed : boost::noncopyable\r
+class read_frame sealed : public frame\r
 {\r
+       read_frame(boost::unique_future<safe_ptr<gpu::host_buffer>>&& image_data, audio_buffer&& audio_data, const struct video_format_desc& format_desc);\r
 public:\r
-       read_frame();\r
-       read_frame(int width, int height, boost::unique_future<safe_ptr<class host_buffer>>&& image_data, audio_buffer&& audio_data);\r
+       static safe_ptr<const read_frame> create(boost::unique_future<safe_ptr<gpu::host_buffer>>&& image_data, audio_buffer&& audio_data, const struct video_format_desc& format_desc);\r
+               \r
+       virtual const struct  pixel_format_desc& get_pixel_format_desc() const override;\r
 \r
-       const boost::iterator_range<const uint8_t*> image_data();\r
-       const boost::iterator_range<const int32_t*> audio_data();\r
+       virtual const boost::iterator_range<const uint8_t*> image_data() const override;\r
+       virtual const boost::iterator_range<const int32_t*> audio_data() const override;\r
+       \r
+       virtual double     get_frame_rate() const override;\r
+       virtual field_mode get_field_mode() const override;\r
 \r
-       int width() const;\r
-       int height() const;\r
-               \r
+       virtual int width() const override;\r
+       virtual int height() const override;\r
+\r
+       virtual const boost::iterator_range<uint8_t*> image_data() override\r
+       {\r
+               BOOST_THROW_EXCEPTION(invalid_operation());\r
+       }\r
+       virtual const boost::iterator_range<int32_t*> audio_data() override\r
+       {\r
+               BOOST_THROW_EXCEPTION(invalid_operation());\r
+       }\r
+                       \r
 private:\r
        struct impl;\r
        std::shared_ptr<impl> impl_;\r
index 232c096578f132f3eb9e03d0bfc3754d156d8e41..7291ef3094db379fc79feebd09cd75d1b0193dd1 100644 (file)
 \r
 #include "write_frame.h"\r
 \r
-#include "gpu/ogl_device.h"\r
+#include "gpu/accelerator.h"\r
 #include "gpu/host_buffer.h"\r
 #include "gpu/device_buffer.h"\r
 \r
+#include <common/exception/exceptions.h>\r
 #include <core/producer/frame/frame_visitor.h>\r
 #include <core/producer/frame/pixel_format.h>\r
 \r
@@ -36,13 +37,13 @@ namespace caspar { namespace core {
                                                                                                                                                                                                                                                                                                                        \r
 struct write_frame::impl : boost::noncopyable\r
 {                      \r
-       std::shared_ptr<ogl_device>                                     ogl_;\r
-       std::vector<std::shared_ptr<host_buffer>>       buffers_;\r
-       std::vector<safe_ptr<device_buffer>>            textures_;\r
-       audio_buffer                                                            audio_data_;\r
-       const core::pixel_format_desc                           desc_;\r
-       const void*                                                                     tag_;\r
-       core::field_mode                                                        mode_;\r
+       std::shared_ptr<gpu::accelerator>                               ogl_;\r
+       std::vector<std::shared_ptr<gpu::host_buffer>>  buffers_;\r
+       std::vector<boost::shared_future<safe_ptr<gpu::device_buffer>>>         textures_;\r
+       audio_buffer                                                                    audio_data_;\r
+       const core::pixel_format_desc                                   desc_;\r
+       const void*                                                                             tag_;\r
+       core::field_mode                                                                mode_;\r
 \r
        impl(const void* tag)\r
                : tag_(tag)\r
@@ -50,7 +51,7 @@ struct write_frame::impl : boost::noncopyable
        {\r
        }\r
 \r
-       impl(const safe_ptr<ogl_device>& ogl, const void* tag, const core::pixel_format_desc& desc, const field_mode& mode) \r
+       impl(const safe_ptr<gpu::accelerator>& ogl, const void* tag, const core::pixel_format_desc& desc, const field_mode& mode) \r
                : ogl_(ogl)\r
                , desc_(desc)\r
                , tag_(tag)\r
@@ -58,12 +59,9 @@ struct write_frame::impl : boost::noncopyable
        {\r
                std::transform(desc.planes.begin(), desc.planes.end(), std::back_inserter(buffers_), [&](const core::pixel_format_desc::plane& plane)\r
                {\r
-                       return ogl_->create_host_buffer(plane.size, host_buffer::usage::write_only);\r
-               });\r
-               std::transform(desc.planes.begin(), desc.planes.end(), std::back_inserter(textures_), [&](const core::pixel_format_desc::plane& plane)\r
-               {\r
-                       return ogl_->create_device_buffer(plane.width, plane.height, plane.channels);   \r
+                       return ogl_->create_host_buffer(plane.size, gpu::host_buffer::usage::write_only);\r
                });\r
+               textures_.resize(desc.planes.size());\r
        }\r
                        \r
        void accept(write_frame& self, core::frame_visitor& visitor)\r
@@ -76,7 +74,7 @@ struct write_frame::impl : boost::noncopyable
        boost::iterator_range<uint8_t*> image_data(int index)\r
        {\r
                if(index >= buffers_.size() || !buffers_[index]->data())\r
-                       return boost::iterator_range<uint8_t*>();\r
+                       BOOST_THROW_EXCEPTION(out_of_range());\r
                auto ptr = static_cast<uint8_t*>(buffers_[index]->data());\r
                return boost::iterator_range<uint8_t*>(ptr, ptr+buffers_[index]->size());\r
        }\r
@@ -97,12 +95,13 @@ struct write_frame::impl : boost::noncopyable
                if(!buffer)\r
                        return;\r
                                \r
-               textures_.at(plane_index)->copy_from(make_safe_ptr(buffer));\r
+               auto plane = desc_.planes.at(plane_index);\r
+               textures_.at(plane_index) = ogl_->copy_async(make_safe_ptr(std::move(buffer)), plane.width, plane.height, plane.channels);\r
        }\r
 };\r
        \r
 write_frame::write_frame(const void* tag) : impl_(new impl(tag)){}\r
-write_frame::write_frame(const safe_ptr<ogl_device>& ogl, const void* tag, const core::pixel_format_desc& desc, const field_mode& mode) \r
+write_frame::write_frame(const safe_ptr<gpu::accelerator>& ogl, const void* tag, const core::pixel_format_desc& desc, const field_mode& mode) \r
        : impl_(new impl(ogl, tag, desc, mode)){}\r
 write_frame::write_frame(write_frame&& other) : impl_(std::move(other.impl_)){}\r
 write_frame& write_frame::operator=(write_frame&& other)\r
@@ -116,10 +115,10 @@ boost::iterator_range<uint8_t*> write_frame::image_data(int index){return impl_-
 audio_buffer& write_frame::audio_data() { return impl_->audio_data_; }\r
 const void* write_frame::tag() const {return impl_->tag_;}\r
 const core::pixel_format_desc& write_frame::get_pixel_format_desc() const{return impl_->desc_;}\r
-const std::vector<safe_ptr<device_buffer>>& write_frame::get_textures() const{return impl_->textures_;}\r
+const std::vector<boost::shared_future<safe_ptr<gpu::device_buffer>>>& write_frame::get_textures() const{return impl_->textures_;}\r
 void write_frame::commit(int plane_index){impl_->commit(plane_index);}\r
 void write_frame::commit(){impl_->commit();}\r
-core::field_mode write_frame::get_type() const{return impl_->mode_;}\r
+core::field_mode write_frame::get_field_mode() const{return impl_->mode_;}\r
 void write_frame::accept(core::frame_visitor& visitor){impl_->accept(*this, visitor);}\r
 \r
 }}
\ No newline at end of file
index 0d1b604077c4791ad3025a8912afb020ef01d407..2b7685ee3087287039ea7ebdde94953371586924 100644 (file)
@@ -22,6 +22,7 @@
 #pragma once\r
 \r
 #include <common/memory/safe_ptr.h>\r
+#include <common/forward.h>\r
 \r
 #include <core/producer/frame/basic_frame.h>\r
 #include <core/video_format.h>\r
 #include <stdint.h>\r
 #include <vector>\r
 \r
+FORWARD1(boost, template<typename> class shared_future);\r
+FORWARD3(caspar, core, gpu, class accelerator);\r
+FORWARD3(caspar, core, gpu, class device_buffer);\r
+\r
 namespace caspar { namespace core {\r
        \r
 class write_frame sealed : public core::basic_frame\r
 {\r
 public:        \r
        explicit write_frame(const void* tag);\r
-       explicit write_frame(const safe_ptr<class ogl_device>& ogl, const void* tag, const struct pixel_format_desc& desc, const field_mode& mode = field_mode::progressive);\r
+       explicit write_frame(const safe_ptr<gpu::accelerator>& ogl, const void* tag, const struct pixel_format_desc& desc, const field_mode& mode = field_mode::progressive);\r
 \r
        write_frame(write_frame&& other);\r
        write_frame& operator=(write_frame&& other);\r
@@ -57,17 +62,14 @@ public:
        void commit(int plane_index);\r
        void commit();\r
        \r
-       field_mode get_type() const;\r
+       field_mode get_field_mode() const;\r
        \r
        const void* tag() const;\r
 \r
        const struct pixel_format_desc& get_pixel_format_desc() const;\r
        \r
+       const std::vector<boost::shared_future<safe_ptr<gpu::device_buffer>>>& get_textures() const;\r
 private:\r
-       friend class image_mixer;\r
-       \r
-       const std::vector<safe_ptr<class device_buffer>>& get_textures() const;\r
-\r
        struct impl;\r
        safe_ptr<impl> impl_;\r
 };\r
diff --git a/core/producer/channel/channel_producer.cpp b/core/producer/channel/channel_producer.cpp
deleted file mode 100644 (file)
index 34d19f5..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#include "../../stdafx.h"\r
-\r
-#include "channel_producer.h"\r
-\r
-#include "../../consumer/frame_consumer.h"\r
-#include "../../consumer/output.h"\r
-#include "../../video_channel.h"\r
-\r
-#include "../frame_producer.h"\r
-#include "../frame/basic_frame.h"\r
-#include "../frame/frame_factory.h"\r
-#include "../frame/pixel_format.h"\r
-#include "../../mixer/write_frame.h"\r
-#include "../../mixer/read_frame.h"\r
-\r
-#include <common/exception/exceptions.h>\r
-\r
-#include <asmlib.h>\r
-\r
-#include <tbb/concurrent_queue.h>\r
-\r
-namespace caspar { namespace core {\r
-\r
-class channel_consumer : public frame_consumer\r
-{      \r
-       tbb::concurrent_bounded_queue<std::shared_ptr<read_frame>>      frame_buffer_;\r
-       core::video_format_desc                                                                         format_desc_;\r
-       int                                                                                                                     channel_index_;\r
-       tbb::atomic<bool>                                                                                       is_running_;\r
-\r
-public:\r
-       channel_consumer() \r
-       {\r
-               is_running_ = true;\r
-               frame_buffer_.set_capacity(3);\r
-       }\r
-\r
-       ~channel_consumer()\r
-       {\r
-               stop();\r
-       }\r
-\r
-       // frame_consumer\r
-\r
-       virtual bool send(const safe_ptr<read_frame>& frame) override\r
-       {\r
-               frame_buffer_.try_push(frame);\r
-               return is_running_;\r
-       }\r
-\r
-       virtual void initialize(const core::video_format_desc& format_desc, int channel_index) override\r
-       {\r
-               format_desc_    = format_desc;\r
-               channel_index_  = channel_index;\r
-       }\r
-\r
-       virtual std::wstring print() const override\r
-       {\r
-               return L"[channel-consumer|" + boost::lexical_cast<std::wstring>(channel_index_) + L"]";\r
-       }\r
-\r
-       virtual boost::property_tree::wptree info() const override\r
-       {\r
-               boost::property_tree::wptree info;\r
-               info.add(L"type", L"channel-consumer");\r
-               info.add(L"channel-index", channel_index_);\r
-               return info;\r
-       }\r
-       \r
-       virtual bool has_synchronization_clock() const override\r
-       {\r
-               return false;\r
-       }\r
-\r
-       virtual int buffer_depth() const override\r
-       {\r
-               return 1;\r
-       }\r
-\r
-       virtual int index() const override\r
-       {\r
-               return 78500 + channel_index_;\r
-       }\r
-\r
-       // channel_consumer\r
-\r
-       void stop()\r
-       {\r
-               is_running_ = false;\r
-               frame_buffer_.try_push(make_safe<read_frame>());\r
-       }\r
-       \r
-       const core::video_format_desc& get_video_format_desc()\r
-       {\r
-               return format_desc_;\r
-       }\r
-\r
-       std::shared_ptr<read_frame> receive()\r
-       {\r
-               if(!is_running_)\r
-                       return make_safe<read_frame>();\r
-               std::shared_ptr<read_frame> frame;\r
-               frame_buffer_.try_pop(frame);\r
-               return frame;\r
-       }\r
-};\r
-       \r
-class channel_producer : public frame_producer\r
-{\r
-       const safe_ptr<frame_factory>           frame_factory_;\r
-       const safe_ptr<channel_consumer>        consumer_;\r
-\r
-       std::queue<safe_ptr<basic_frame>>       frame_buffer_;\r
-       safe_ptr<basic_frame>                           last_frame_;\r
-       uint64_t                                                        frame_number_;\r
-\r
-public:\r
-       explicit channel_producer(const safe_ptr<frame_factory>& frame_factory, const safe_ptr<video_channel>& channel) \r
-               : frame_factory_(frame_factory)\r
-               , consumer_(make_safe<channel_consumer>())\r
-               , last_frame_(basic_frame::empty())\r
-               , frame_number_(0)\r
-       {\r
-               channel->output()->add(consumer_);\r
-               CASPAR_LOG(info) << print() << L" Initialized";\r
-       }\r
-\r
-       ~channel_producer()\r
-       {\r
-               consumer_->stop();\r
-               CASPAR_LOG(info) << print() << L" Uninitialized";\r
-       }\r
-\r
-       // frame_producer\r
-                       \r
-       virtual safe_ptr<basic_frame> receive(int) override\r
-       {\r
-               auto format_desc = consumer_->get_video_format_desc();\r
-\r
-               if(frame_buffer_.size() > 1)\r
-               {\r
-                       auto frame = frame_buffer_.front();\r
-                       frame_buffer_.pop();\r
-                       return last_frame_ = frame;\r
-               }\r
-               \r
-               auto read_frame = consumer_->receive();\r
-               if(!read_frame || read_frame->image_data().empty())\r
-                       return basic_frame::late();             \r
-\r
-               frame_number_++;\r
-               \r
-               core::pixel_format_desc desc;\r
-               bool double_speed       = std::abs(frame_factory_->get_video_format_desc().fps / 2.0 - format_desc.fps) < 0.01;         \r
-               bool half_speed         = std::abs(format_desc.fps / 2.0 - frame_factory_->get_video_format_desc().fps) < 0.01;\r
-\r
-               if(half_speed && frame_number_ % 2 == 0) // Skip frame\r
-                       return receive(0);\r
-\r
-               desc.pix_fmt = core::pixel_format::bgra;\r
-               desc.planes.push_back(core::pixel_format_desc::plane(format_desc.width, format_desc.height, 4));\r
-               auto frame = frame_factory_->create_frame(this, desc);\r
-\r
-               A_memcpy(frame->image_data().begin(), read_frame->image_data().begin(), read_frame->image_data().size());\r
-               frame->commit();\r
-\r
-               frame_buffer_.push(frame);      \r
-               \r
-               if(double_speed)        \r
-                       frame_buffer_.push(frame);\r
-\r
-               return receive(0);\r
-       }       \r
-\r
-       virtual safe_ptr<basic_frame> last_frame() const override\r
-       {\r
-               return last_frame_; \r
-       }       \r
-\r
-       virtual std::wstring print() const override\r
-       {\r
-               return L"channel[]";\r
-       }\r
-\r
-       virtual boost::property_tree::wptree info() const override\r
-       {\r
-               boost::property_tree::wptree info;\r
-               info.add(L"type", L"channel-producer");\r
-               return info;\r
-       }\r
-};\r
-\r
-safe_ptr<core::frame_producer> create_channel_producer(const safe_ptr<core::frame_factory>& frame_factory, const safe_ptr<core::video_channel>& channel)\r
-{\r
-       return create_producer_print_proxy(\r
-                       make_safe<channel_producer>(frame_factory, channel));\r
-}\r
-\r
-}}
\ No newline at end of file
index 831da21f4e719944eabe7cf30f0fbc6c5d526828..40f501d4a795167f8d81aedb7e5aa0069e7cec23 100644 (file)
@@ -23,6 +23,8 @@
 \r
 #include <common/memory/safe_ptr.h>\r
 \r
+#include <core/video_format.h>\r
+\r
 #include <boost/noncopyable.hpp>\r
 \r
 namespace caspar { namespace core {\r
index 07d0d3a6d4fca7ca51b756bea671804d7a489ddf..4ef2f5295bee41b57994b89ef6a8b7320523561b 100644 (file)
@@ -26,7 +26,6 @@
 #include "frame/frame_transform.h"\r
 \r
 #include "color/color_producer.h"\r
-#include "playlist/playlist_producer.h"\r
 #include "separated/separated_producer.h"\r
 \r
 #include <common/memory/safe_ptr.h>\r
@@ -241,10 +240,7 @@ safe_ptr<core::frame_producer> do_create_producer(const safe_ptr<frame_factory>&
 \r
        if(producer == frame_producer::empty())\r
                producer = create_color_producer(my_frame_factory, params);\r
-       \r
-       if(producer == frame_producer::empty())\r
-               producer = create_playlist_producer(my_frame_factory, params);\r
-       \r
+               \r
        return producer;\r
 }\r
 \r
diff --git a/core/producer/playlist/playlist_producer.cpp b/core/producer/playlist/playlist_producer.cpp
deleted file mode 100644 (file)
index 9972279..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#include "../../stdafx.h"\r
-\r
-#include "playlist_producer.h"\r
-\r
-#include "../frame_producer.h"\r
-#include "../frame_producer.h"\r
-#include "../frame/basic_frame.h"\r
-\r
-#include <boost/regex.hpp>\r
-#include <boost/property_tree/ptree.hpp>\r
-#include <boost/thread/future.hpp>\r
-\r
-#include <deque>\r
-\r
-namespace caspar { namespace core {    \r
-\r
-struct playlist_producer : public frame_producer\r
-{                              \r
-       safe_ptr<frame_factory>                         factory_;\r
-       safe_ptr<basic_frame>                           last_frame_;\r
-       safe_ptr<frame_producer>                        current_;\r
-       bool                                                            loop_;\r
-\r
-       std::deque<safe_ptr<frame_producer>> producers_;\r
-\r
-       playlist_producer(const safe_ptr<frame_factory>& factory, bool loop) \r
-               : factory_(factory)\r
-               , last_frame_(basic_frame::empty())\r
-               , current_(frame_producer::empty())\r
-               , loop_(loop)\r
-       {\r
-       }\r
-\r
-       // frame_producer\r
-       \r
-       virtual safe_ptr<basic_frame> receive(int flags) override\r
-       {\r
-               if(current_ == frame_producer::empty() && !producers_.empty())\r
-                       next();\r
-\r
-               auto frame = current_->receive(flags);\r
-               if(frame == basic_frame::eof())\r
-               {\r
-                       current_ = frame_producer::empty();\r
-                       return receive(flags);\r
-               }\r
-\r
-               return last_frame_ = frame;\r
-       }\r
-\r
-       virtual safe_ptr<core::basic_frame> last_frame() const override\r
-       {\r
-               return last_frame_;\r
-       }\r
-\r
-       virtual std::wstring print() const override\r
-       {\r
-               return L"playlist[" + current_->print() + L"]";\r
-       }       \r
-\r
-       virtual boost::property_tree::wptree info() const override\r
-       {\r
-               boost::property_tree::wptree info;\r
-               info.add(L"type", L"playlist-producer");\r
-               return info;\r
-       }\r
-\r
-       virtual uint32_t nb_frames() const  override\r
-       {\r
-               return std::numeric_limits<uint32_t>::max();\r
-       }\r
-       \r
-       virtual boost::unique_future<std::wstring> call(const std::wstring& param) override\r
-       {\r
-               boost::promise<std::wstring> promise;\r
-               promise.set_value(do_call(param));\r
-               return promise.get_future();\r
-       }       \r
-\r
-       // playlist_producer\r
-\r
-       std::wstring do_call(const std::wstring& param)\r
-       {               \r
-               static const boost::wregex push_front_exp       (L"PUSH_FRONT (?<PARAM>.+)");           \r
-               static const boost::wregex push_back_exp        (L"(PUSH_BACK|PUSH) (?<PARAM>.+)");\r
-               static const boost::wregex pop_front_exp        (L"POP_FRONT");         \r
-               static const boost::wregex pop_back_exp         (L"(POP_BACK|POP)");\r
-               static const boost::wregex clear_exp            (L"CLEAR");\r
-               static const boost::wregex next_exp                     (L"NEXT");\r
-               static const boost::wregex insert_exp           (L"INSERT (?<POS>\\d+) (?<PARAM>.+)");  \r
-               static const boost::wregex remove_exp           (L"REMOVE (?<POS>\\d+) (?<PARAM>.+)");  \r
-               static const boost::wregex list_exp                     (L"LIST");                      \r
-               static const boost::wregex loop_exp                     (L"LOOP\\s*(?<VALUE>\\d?)");\r
-               \r
-               boost::wsmatch what;\r
-\r
-               if(boost::regex_match(param, what, push_front_exp))\r
-                       return push_front(what["PARAM"].str()); \r
-               else if(boost::regex_match(param, what, push_back_exp))\r
-                       return push_back(what["PARAM"].str()); \r
-               if(boost::regex_match(param, what, pop_front_exp))\r
-                       return pop_front(); \r
-               else if(boost::regex_match(param, what, pop_back_exp))\r
-                       return pop_back(); \r
-               else if(boost::regex_match(param, what, clear_exp))\r
-                       return clear();\r
-               else if(boost::regex_match(param, what, next_exp))\r
-                       return next(); \r
-               else if(boost::regex_match(param, what, insert_exp))\r
-                       return insert(boost::lexical_cast<size_t>(what["POS"].str()), what["PARAM"].str());\r
-               else if(boost::regex_match(param, what, remove_exp))\r
-                       return erase(boost::lexical_cast<size_t>(what["POS"].str()));\r
-               else if(boost::regex_match(param, what, list_exp))\r
-                       return list();\r
-               else if(boost::regex_match(param, what, loop_exp))\r
-               {\r
-                       if(!what["VALUE"].str().empty())\r
-                               loop_ = boost::lexical_cast<bool>(what["VALUE"].str());\r
-                       return boost::lexical_cast<std::wstring>(loop_);\r
-               }\r
-\r
-               BOOST_THROW_EXCEPTION(invalid_argument());\r
-       }\r
-       \r
-       std::wstring push_front(const std::wstring& str)\r
-       {\r
-               producers_.push_front(create_producer(factory_, str)); \r
-               return L"";\r
-       }\r
-\r
-       std::wstring  push_back(const std::wstring& str)\r
-       {\r
-               producers_.push_back(create_producer(factory_, str)); \r
-               return L"";\r
-       }\r
-\r
-       std::wstring pop_front()\r
-       {\r
-               producers_.pop_front();\r
-               return L"";\r
-       }\r
-\r
-       std::wstring pop_back()\r
-       {\r
-               producers_.pop_back();\r
-               return L"";\r
-       }\r
-       \r
-       std::wstring clear()\r
-       {\r
-               producers_.clear();\r
-               return L"";\r
-       }\r
-\r
-       std::wstring next()\r
-       {\r
-               if(!producers_.empty())\r
-               {\r
-                       current_ = producers_.front();\r
-                       producers_.pop_front();\r
-                       //if(loop_)\r
-                       //      producers_.push_back(current_);\r
-               }\r
-               return L"";\r
-       }\r
-       \r
-       std::wstring  insert(size_t pos, const std::wstring& str)\r
-       {\r
-               if(pos >= producers_.size())\r
-                       BOOST_THROW_EXCEPTION(out_of_range());\r
-               producers_.insert(std::begin(producers_) + pos, create_producer(factory_, str));\r
-               return L"";\r
-       }\r
-\r
-       std::wstring  erase(size_t pos)\r
-       {\r
-               if(pos >= producers_.size())\r
-                       BOOST_THROW_EXCEPTION(out_of_range());\r
-               producers_.erase(std::begin(producers_) + pos);\r
-               return L"";\r
-       }\r
-\r
-       std::wstring list() const\r
-       {\r
-               std::wstring result = L"<playlist>\n";\r
-               BOOST_FOREACH(auto& producer, producers_)               \r
-                       result += L"\t<producer>" + producer->print() + L"</producer>\n";\r
-               return result + L"</playlist>";\r
-       }\r
-};\r
-\r
-safe_ptr<frame_producer> create_playlist_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& params)\r
-{\r
-       if(boost::range::find(params, L"[PLAYLIST]") == params.end())\r
-               return core::frame_producer::empty();\r
-\r
-       bool loop = boost::range::find(params, L"LOOP") != params.end();\r
-\r
-       return make_safe<playlist_producer>(frame_factory, loop);\r
-}\r
-\r
-}}\r
-\r
diff --git a/core/producer/playlist/playlist_producer.h b/core/producer/playlist/playlist_producer.h
deleted file mode 100644 (file)
index b03d39d..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*\r
-* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
-*\r
-* This file is part of CasparCG (www.casparcg.com).\r
-*\r
-* CasparCG is free software: you can redistribute it and/or modify\r
-* it under the terms of the GNU General Public License as published by\r
-* the Free Software Foundation, either version 3 of the License, or\r
-* (at your option) any later version.\r
-*\r
-* CasparCG is distributed in the hope that it will be useful,\r
-* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-* GNU General Public License for more details.\r
-*\r
-* You should have received a copy of the GNU General Public License\r
-* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-* Author: Robert Nagy, ronag89@gmail.com\r
-*/\r
-\r
-#pragma once\r
-\r
-#include <common/memory/safe_ptr.h>\r
-\r
-#include <string>\r
-#include <vector>\r
-\r
-namespace caspar { namespace core {\r
-               \r
-safe_ptr<struct frame_producer> create_playlist_producer(const safe_ptr<struct frame_factory>& frame_factory, const std::vector<std::wstring>& params);\r
-\r
-}}
\ No newline at end of file
index 31e061b9e9c0de988f7a84aac021e864cbead766..6b50ed96db0d31f75e77b437cb162fa310916aee 100644 (file)
@@ -79,96 +79,67 @@ public:
 \r
 struct stage::impl : public std::enable_shared_from_this<impl>\r
                                   , boost::noncopyable\r
-{              \r
-       safe_ptr<stage::target_t>                                                               target_;\r
-       video_format_desc                                                                               format_desc_;\r
-       \r
-       safe_ptr<diagnostics::graph>                                                    graph_;\r
-\r
-       boost::timer                                                                                    produce_timer_;\r
-       boost::timer                                                                                    tick_timer_;\r
-\r
+{                      \r
        std::map<int, layer>                                                                    layers_;        \r
        std::map<int, tweened_transform<core::frame_transform>> transforms_;    \r
 \r
        executor                                                                                                executor_;\r
 public:\r
-       impl(const safe_ptr<stage::target_t>& target, const safe_ptr<diagnostics::graph>& graph, const video_format_desc& format_desc)  \r
-               : target_(target)\r
-               , graph_(graph)\r
-               , format_desc_(format_desc)\r
-               , executor_(L"stage")\r
-       {\r
-               graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));   \r
-               graph_->set_color("produce-time", diagnostics::color(0.0f, 1.0f, 0.0f));\r
-       }\r
-\r
-       void start(int tokens)\r
+       impl()  \r
+               : executor_(L"stage")\r
        {\r
-               std::weak_ptr<impl> self = shared_from_this();\r
-               for(int n = 0; n < tokens; ++n)\r
-                       executor_.begin_invoke([=]{tick(self);});\r
        }\r
-       \r
-       void tick(const std::weak_ptr<impl>& self)\r
+               \r
+       std::map<int, safe_ptr<basic_frame>> operator()(const struct video_format_desc& format_desc)\r
        {               \r
-               try\r
+               return executor_.invoke([=]() -> std::map<int, safe_ptr<basic_frame>>\r
                {\r
-                       produce_timer_.restart();\r
+                       std::map<int, safe_ptr<class basic_frame>> result;\r
 \r
-                       std::map<int, safe_ptr<basic_frame>> frames;\r
-               \r
-                       BOOST_FOREACH(auto& layer, layers_)                     \r
-                               frames[layer.first] = basic_frame::empty();     \r
+                       try\r
+                       {                                       \r
+                               BOOST_FOREACH(auto& layer, layers_)                     \r
+                                       result[layer.first] = basic_frame::empty();     \r
 \r
-                       tbb::parallel_for_each(layers_.begin(), layers_.end(), [&](std::map<int, layer>::value_type& layer) \r
-                       {\r
-                               auto transform = transforms_[layer.first].fetch_and_tick(1);\r
+                               auto format_desc2 = format_desc;\r
 \r
-                               int flags = frame_producer::flags::none;\r
-                               if(format_desc_.field_mode != field_mode::progressive)\r
+                               tbb::parallel_for_each(layers_.begin(), layers_.end(), [&](std::map<int, layer>::value_type& layer)\r
                                {\r
-                                       flags |= std::abs(transform.fill_scale[1]  - 1.0) > 0.0001 ? frame_producer::flags::deinterlace : frame_producer::flags::none;\r
-                                       flags |= std::abs(transform.fill_translation[1])  > 0.0001 ? frame_producer::flags::deinterlace : frame_producer::flags::none;\r
-                               }\r
+                                       auto transform = transforms_[layer.first].fetch_and_tick(1);\r
+\r
+                                       int flags = frame_producer::flags::none;\r
+                                       if(format_desc2.field_mode != field_mode::progressive)\r
+                                       {\r
+                                               flags |= std::abs(transform.fill_scale[1]  - 1.0) > 0.0001 ? frame_producer::flags::deinterlace : frame_producer::flags::none;\r
+                                               flags |= std::abs(transform.fill_translation[1])  > 0.0001 ? frame_producer::flags::deinterlace : frame_producer::flags::none;\r
+                                       }\r
 \r
-                               if(transform.is_key)\r
-                                       flags |= frame_producer::flags::alpha_only;\r
+                                       if(transform.is_key)\r
+                                               flags |= frame_producer::flags::alpha_only;\r
 \r
-                               auto frame = layer.second.receive(flags);       \r
+                                       auto frame = layer.second.receive(flags);       \r
                                \r
-                               auto frame1 = make_safe<core::basic_frame>(frame);\r
-                               frame1->get_frame_transform() = transform;\r
-\r
-                               if(format_desc_.field_mode != core::field_mode::progressive)\r
-                               {                               \r
-                                       auto frame2 = make_safe<core::basic_frame>(frame);\r
-                                       frame2->get_frame_transform() = transforms_[layer.first].fetch_and_tick(1);\r
-                                       frame1 = core::basic_frame::interlace(frame1, frame2, format_desc_.field_mode);\r
-                               }\r
-\r
-                               frames[layer.first] = frame1;\r
-                       });\r
-                       \r
-                       graph_->set_value("produce-time", produce_timer_.elapsed()*format_desc_.fps*0.5);\r
-                       \r
-                       std::shared_ptr<void> ticket(nullptr, [self](void*)\r
+                                       auto frame1 = make_safe<core::basic_frame>(frame);\r
+                                       frame1->get_frame_transform() = transform;\r
+\r
+                                       if(format_desc2.field_mode != core::field_mode::progressive)\r
+                                       {                               \r
+                                               auto frame2 = make_safe<core::basic_frame>(frame);\r
+                                               frame2->get_frame_transform() = transforms_[layer.first].fetch_and_tick(1);\r
+                                               frame1 = core::basic_frame::interlace(frame1, frame2, format_desc2.field_mode);\r
+                                       }\r
+\r
+                                       result[layer.first] = frame1;\r
+                               });             \r
+                       }\r
+                       catch(...)\r
                        {\r
-                               auto self2 = self.lock();\r
-                               if(self2)                               \r
-                                       self2->executor_.begin_invoke([=]{tick(self);});                                \r
-                       });\r
-                                               \r
-                       target_->send(std::make_pair(frames, ticket));\r
+                               layers_.clear();\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       }       \r
 \r
-                       graph_->set_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);\r
-                       tick_timer_.restart();\r
-               }\r
-               catch(...)\r
-               {\r
-                       layers_.clear();\r
-                       CASPAR_LOG_CURRENT_EXCEPTION();\r
-               }               \r
+                       return result;\r
+               });\r
        }\r
                \r
        void apply_transforms(const std::vector<std::tuple<int, stage::transform_func_t, unsigned int, std::wstring>>& transforms)\r
@@ -321,14 +292,6 @@ public:
                        return layers_[index].background();\r
                }, high_priority);\r
        }\r
-       \r
-       void set_video_format_desc(const video_format_desc& format_desc)\r
-       {\r
-               executor_.begin_invoke([=]\r
-               {\r
-                       format_desc_ = format_desc;\r
-               }, high_priority);\r
-       }\r
 \r
        boost::unique_future<boost::property_tree::wptree> info()\r
        {\r
@@ -348,11 +311,10 @@ public:
                {\r
                        return layers_[index].info();\r
                }, high_priority));\r
-       }\r
+       }               \r
 };\r
 \r
-stage::stage(const safe_ptr<stage::target_t>& target, const safe_ptr<diagnostics::graph>& graph, const struct video_format_desc& format_desc) : impl_(new impl(target, graph, format_desc)){}\r
-void stage::start(int tokens){impl_->start(tokens);}\r
+stage::stage() : impl_(new impl()){}\r
 void stage::apply_transforms(const std::vector<stage::transform_tuple_t>& transforms){impl_->apply_transforms(transforms);}\r
 void stage::apply_transform(int index, const std::function<core::frame_transform(core::frame_transform)>& transform, unsigned int mix_duration, const std::wstring& tween){impl_->apply_transform(index, transform, mix_duration, tween);}\r
 void stage::clear_transforms(int index){impl_->clear_transforms(index);}\r
@@ -369,7 +331,7 @@ void stage::swap_layer(int index, int other_index, const safe_ptr<stage>& other)
 boost::unique_future<safe_ptr<frame_producer>> stage::foreground(int index) {return impl_->foreground(index);}\r
 boost::unique_future<safe_ptr<frame_producer>> stage::background(int index) {return impl_->background(index);}\r
 boost::unique_future<std::wstring> stage::call(int index, bool foreground, const std::wstring& param){return impl_->call(index, foreground, param);}\r
-void stage::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
 boost::unique_future<boost::property_tree::wptree> stage::info() const{return impl_->info();}\r
 boost::unique_future<boost::property_tree::wptree> stage::info(int index) const{return impl_->info(index);}\r
+std::map<int, safe_ptr<class basic_frame>> stage::operator()(const video_format_desc& format_desc){return (*impl_)(format_desc);}\r
 }}
\ No newline at end of file
index 5c81990409c2dddfd46fdb6fd7a72da85ac2eecf..0b5a2bbe873cadbbfa7504746220e710e0b0800d 100644 (file)
@@ -23,7 +23,6 @@
 \r
 #include "frame_producer.h"\r
 \r
-#include <common/concurrency/target.h>\r
 #include <common/forward.h>\r
 #include <common/memory/safe_ptr.h>\r
 \r
@@ -42,13 +41,12 @@ namespace caspar { namespace core {
 class stage sealed : boost::noncopyable\r
 {\r
 public:        \r
-       typedef std::function<struct frame_transform(struct frame_transform)>                                                   transform_func_t;\r
-       typedef std::tuple<int, transform_func_t, unsigned int, std::wstring>                                                   transform_tuple_t;\r
-       typedef target<std::pair<std::map<int, safe_ptr<class basic_frame>>, std::shared_ptr<void>>>    target_t;\r
+       typedef std::function<struct frame_transform(struct frame_transform)> transform_func_t;\r
+       typedef std::tuple<int, transform_func_t, unsigned int, std::wstring> transform_tuple_t;\r
 \r
-       explicit stage(const safe_ptr<target_t>& target, const safe_ptr<diagnostics::graph>& graph, const struct video_format_desc& format_desc);\r
+       stage();\r
                \r
-       void start(int tokens);\r
+       std::map<int, safe_ptr<class basic_frame>> operator()(const struct video_format_desc& format_desc);\r
 \r
        void apply_transforms(const std::vector<transform_tuple_t>& transforms);\r
        void apply_transform(int index, const transform_func_t& transform, unsigned int mix_duration = 0, const std::wstring& tween = L"linear");\r
@@ -72,7 +70,6 @@ public:
        boost::unique_future<boost::property_tree::wptree> info() const;\r
        boost::unique_future<boost::property_tree::wptree> info(int layer) const;\r
        \r
-       void set_video_format_desc(const struct video_format_desc& format_desc);\r
 private:\r
        struct impl;\r
        safe_ptr<impl> impl_;\r
index afc544b948c346aea01a71244782a7ff34e337d6..17171b54b09593559d692a24930eb2d6810d85cd 100644 (file)
 \r
 #include "consumer/output.h"\r
 #include "mixer/mixer.h"\r
-#include "mixer/gpu/ogl_device.h"\r
 #include "mixer/write_frame.h"\r
+#include "mixer/gpu/accelerator.h"\r
+#include "frame.h"\r
 #include "producer/stage.h"\r
 #include "producer/frame/frame_factory.h"\r
 \r
 #include <common/diagnostics/graph.h>\r
 #include <common/env.h>\r
+#include <common/concurrency/lock.h>\r
+\r
+#include <tbb/spin_mutex.h>\r
 \r
 #include <boost/property_tree/ptree.hpp>\r
 \r
@@ -43,31 +47,47 @@ namespace caspar { namespace core {
 \r
 struct video_channel::impl sealed : public frame_factory\r
 {\r
+       reactive::basic_subject<safe_ptr<const frame>> frame_subject_;\r
        const int                                                               index_;\r
+\r
+       mutable tbb::spin_mutex                                 format_desc_mutex_;\r
        video_format_desc                                               format_desc_;\r
-       const safe_ptr<ogl_device>                              ogl_;\r
+       \r
+       const safe_ptr<gpu::accelerator>                ogl_;\r
        const safe_ptr<diagnostics::graph>              graph_;\r
 \r
        const safe_ptr<caspar::core::output>    output_;\r
        const safe_ptr<caspar::core::mixer>             mixer_;\r
        const safe_ptr<caspar::core::stage>             stage_; \r
+\r
+       boost::timer                                                    tick_timer_;\r
+       boost::timer                                                    produce_timer_;\r
+       boost::timer                                                    mix_timer_;\r
+       boost::timer                                                    consume_timer_;\r
+\r
+       executor                                                                executor_;\r
 public:\r
-       impl(int index, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl)  \r
-               : index_(index)\r
+       impl(int index, const video_format_desc& format_desc, const safe_ptr<gpu::accelerator>& ogl)  \r
+               :  index_(index)\r
                , format_desc_(format_desc)\r
                , ogl_(ogl)\r
-               , output_(new caspar::core::output(graph_, format_desc, index))\r
-               , mixer_(new caspar::core::mixer(output_, graph_, format_desc, ogl))\r
-               , stage_(new caspar::core::stage(mixer_, graph_, format_desc))  \r
+               , output_(new caspar::core::output(format_desc, index))\r
+               , mixer_(new caspar::core::mixer(ogl))\r
+               , stage_(new caspar::core::stage())     \r
+               , executor_(L"video_channel")\r
        {\r
+               graph_->set_color("mix-time", diagnostics::color(1.0f, 0.0f, 0.9f, 0.8));\r
+               graph_->set_color("produce-time", diagnostics::color(0.0f, 1.0f, 0.0f));\r
+               graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));   \r
+               graph_->set_color("consume-time", diagnostics::color(1.0f, 0.4f, 0.0f, 0.8));\r
                graph_->set_text(print());\r
                diagnostics::register_graph(graph_);\r
 \r
-               stage_->start(std::max(1, env::properties().get(L"configuration.pipeline-tokens", 2)));\r
+               executor_.begin_invoke([=]{tick();});\r
 \r
                CASPAR_LOG(info) << print() << " Successfully Initialized.";\r
        }\r
-\r
+       \r
        // frame_factory\r
                                                \r
        virtual safe_ptr<write_frame> create_frame(const void* tag, const core::pixel_format_desc& desc, field_mode mode) override\r
@@ -77,31 +97,56 @@ public:
        \r
        virtual core::video_format_desc get_video_format_desc() const override\r
        {\r
-               return format_desc_;\r
+               return lock(format_desc_mutex_, [&]\r
+               {\r
+                       return format_desc_;\r
+               });\r
        }\r
        \r
        // video_channel\r
 \r
-       void set_video_format_desc(const video_format_desc& format_desc)\r
+       void tick()\r
        {\r
-               if(format_desc.format == core::video_format::invalid)\r
-                       BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("Invalid video-format"));\r
+               tick_timer_.restart();\r
 \r
-               try\r
-               {\r
-                       output_->set_video_format_desc(format_desc);\r
-                       mixer_->set_video_format_desc(format_desc);\r
-                       stage_->set_video_format_desc(format_desc);\r
-                       ogl_->gc();\r
-               }\r
-               catch(...)\r
+               // Produce\r
+\r
+               produce_timer_.restart();\r
+\r
+               auto stage_frames = (*stage_)(format_desc_);\r
+               \r
+               graph_->set_value("produce-time", produce_timer_.elapsed()*format_desc_.fps*0.5);\r
+\r
+               // Mix\r
+\r
+               mix_timer_.restart();\r
+\r
+               auto mixed_frame  = (*mixer_)(std::move(stage_frames), format_desc_);\r
+               \r
+               graph_->set_value("mix-time", mix_timer_.elapsed()*format_desc_.fps*0.5);\r
+\r
+               // Consume\r
+\r
+               consume_timer_.restart();\r
+\r
+               frame_subject_.on_next(mixed_frame);\r
+\r
+               graph_->set_value("consume-time", consume_timer_.elapsed()*format_desc_.fps*0.5);\r
+\r
+               (*output_)(std::move(mixed_frame), format_desc_);\r
+               \r
+               graph_->set_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);\r
+\r
+               executor_.begin_invoke([=]{tick();});\r
+       }\r
+\r
+       void set_video_format_desc(const video_format_desc& format_desc)\r
+       {\r
+               ogl_->gc();\r
+               lock(format_desc_mutex_, [&]\r
                {\r
-                       output_->set_video_format_desc(format_desc_);\r
-                       mixer_->set_video_format_desc(format_desc_);\r
-                       stage_->set_video_format_desc(format_desc_);\r
-                       throw;\r
-               }\r
-               format_desc_ = format_desc;\r
+                       format_desc_ = format_desc;\r
+               });\r
        }\r
                \r
        std::wstring print() const\r
@@ -130,7 +175,7 @@ public:
        }\r
 };\r
 \r
-video_channel::video_channel(int index, const video_format_desc& format_desc, const safe_ptr<ogl_device>& ogl) : impl_(new impl(index, format_desc, ogl)){}\r
+video_channel::video_channel(int index, const video_format_desc& format_desc, const safe_ptr<gpu::accelerator>& ogl) : impl_(new impl(index, format_desc, ogl)){}\r
 safe_ptr<stage> video_channel::stage() { return impl_->stage_;} \r
 safe_ptr<mixer> video_channel::mixer() { return impl_->mixer_;} \r
 safe_ptr<frame_factory> video_channel::frame_factory() { return impl_;} \r
@@ -138,5 +183,7 @@ safe_ptr<output> video_channel::output() { return impl_->output_;}
 video_format_desc video_channel::get_video_format_desc() const{return impl_->format_desc_;}\r
 void video_channel::set_video_format_desc(const video_format_desc& format_desc){impl_->set_video_format_desc(format_desc);}\r
 boost::property_tree::wptree video_channel::info() const{return impl_->info();}\r
+void video_channel::subscribe(const observer_ptr& o) {impl_->frame_subject_.subscribe(o);}\r
+void video_channel::unsubscribe(const observer_ptr& o) {impl_->frame_subject_.unsubscribe(o);}\r
 \r
 }}
\ No newline at end of file
index 9ee7959c904fbd0cd402d4ebc4ff3b62a6411c73..e6a1eb3ac217a0dda703d69798d63f9edea0c575 100644 (file)
 #pragma once\r
 \r
 #include <common/memory/safe_ptr.h>\r
+#include <common/reactive.h>\r
+#include <common/forward.h>\r
 \r
 #include <boost/noncopyable.hpp>\r
 #include <boost/property_tree/ptree_fwd.hpp>\r
 \r
+FORWARD3(caspar, core, gpu, class accelerator);\r
+\r
 namespace caspar { namespace core {\r
        \r
-class video_channel sealed : boost::noncopyable\r
+class video_channel sealed : public reactive::observable<safe_ptr<const struct frame>>\r
+                                                  , boost::noncopyable\r
 {\r
 public:\r
-       explicit video_channel(int index, const struct video_format_desc& format_desc, const safe_ptr<class ogl_device>& ogl);\r
+       explicit video_channel(int index, const struct video_format_desc& format_desc, const safe_ptr<gpu::accelerator>& ogl);\r
 \r
        safe_ptr<class stage>                   stage();\r
        safe_ptr<class mixer>                   mixer();\r
@@ -43,7 +48,10 @@ public:
        \r
        boost::property_tree::wptree info() const;\r
 \r
-       //int index() const;\r
+       // observable\r
+       \r
+       virtual void subscribe(const observer_ptr& o) override;\r
+       virtual void unsubscribe(const observer_ptr& o) override;\r
 private:\r
        struct impl;\r
        safe_ptr<impl> impl_;\r
index 3be523adb39b781d717a6b5f24f21adb38cc51b2..204449d32a30a698d3698c16ece0b23465709e21 100644 (file)
@@ -26,7 +26,7 @@
 #include "../util/memory.h"\r
 \r
 #include <core/video_format.h>\r
-#include <core/mixer/read_frame.h>\r
+#include <core/frame.h>\r
 \r
 #include <common/concurrency/executor.h>\r
 #include <common/diagnostics/graph.h>\r
@@ -67,7 +67,7 @@ struct bluefish_consumer : boost::noncopyable
        unsigned int                                            vid_fmt_;\r
 \r
        std::array<blue_dma_buffer_ptr, 4>      reserved_frames_;       \r
-       tbb::concurrent_bounded_queue<std::shared_ptr<core::read_frame>> frame_buffer_;\r
+       tbb::concurrent_bounded_queue<std::shared_ptr<const core::frame>> frame_buffer_;\r
        \r
        const bool                                                      embedded_audio_;\r
        const bool                                                      key_only_;\r
@@ -185,7 +185,7 @@ public:
                        CASPAR_LOG(error)<< print() << TEXT(" Failed to disable video output.");                \r
        }\r
        \r
-       void send(const safe_ptr<core::read_frame>& frame)\r
+       void send(const safe_ptr<const core::frame>& frame)\r
        {                                       \r
                executor_.begin_invoke([=]\r
                {\r
@@ -202,7 +202,7 @@ public:
                });\r
        }\r
 \r
-       void display_frame(const safe_ptr<core::read_frame>& frame)\r
+       void display_frame(const safe_ptr<const core::frame>& frame)\r
        {\r
                // Sync\r
 \r
@@ -328,7 +328,7 @@ public:
                CASPAR_LOG(info) << print() << L" Successfully Initialized.";   \r
        }\r
        \r
-       virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<const core::frame>& frame) override\r
        {\r
                CASPAR_VERIFY(audio_cadence_.front() == static_cast<size_t>(frame->audio_data().size()));\r
                boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
index f3241e3cdc33bd3fe03a1e263d5617e3f58415c4..34bb8224842e5d4743c9c1f3d2196574814c7097 100644 (file)
@@ -27,7 +27,8 @@
 \r
 #include "../interop/DeckLinkAPI_h.h"\r
 \r
-#include <core/mixer/read_frame.h>\r
+#include <core/frame.h>\r
+#include <core/mixer/audio/audio_mixer.h>\r
 \r
 #include <common/concurrency/executor.h>\r
 #include <common/concurrency/lock.h>\r
@@ -76,13 +77,13 @@ struct configuration
 class decklink_frame : public IDeckLinkVideoFrame\r
 {\r
        tbb::atomic<int>                                                                                        ref_count_;\r
-       std::shared_ptr<core::read_frame>                                                       frame_;\r
+       std::shared_ptr<const core::frame>                                                              frame_;\r
        const core::video_format_desc                                                           format_desc_;\r
 \r
        const bool                                                                                                      key_only_;\r
        std::vector<uint8_t, tbb::cache_aligned_allocator<uint8_t>> data_;\r
 public:\r
-       decklink_frame(const safe_ptr<core::read_frame>& frame, const core::video_format_desc& format_desc, bool key_only)\r
+       decklink_frame(const safe_ptr<const core::frame>& frame, const core::video_format_desc& format_desc, bool key_only)\r
                : frame_(frame)\r
                , format_desc_(format_desc)\r
                , key_only_(key_only)\r
@@ -175,17 +176,17 @@ struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLink
                \r
        const std::wstring                                      model_name_;\r
        const core::video_format_desc           format_desc_;\r
-       const int                                               buffer_size_;\r
+       const int                                                       buffer_size_;\r
 \r
        long long                                                       video_scheduled_;\r
        long long                                                       audio_scheduled_;\r
 \r
-       int                                                             preroll_count_;\r
+       int                                                                     preroll_count_;\r
                \r
        boost::circular_buffer<std::vector<int32_t>>    audio_container_;\r
 \r
-       tbb::concurrent_bounded_queue<std::shared_ptr<core::read_frame>> video_frame_buffer_;\r
-       tbb::concurrent_bounded_queue<std::shared_ptr<core::read_frame>> audio_frame_buffer_;\r
+       tbb::concurrent_bounded_queue<std::shared_ptr<const core::frame>> video_frame_buffer_;\r
+       tbb::concurrent_bounded_queue<std::shared_ptr<const core::frame>> audio_frame_buffer_;\r
        \r
        safe_ptr<diagnostics::graph> graph_;\r
        boost::timer tick_timer_;\r
@@ -232,7 +233,7 @@ public:
                        output_->BeginAudioPreroll();           \r
                \r
                for(int n = 0; n < buffer_size_; ++n)\r
-                       schedule_next_video(make_safe<core::read_frame>());\r
+                       schedule_next_video(core::frame::empty());\r
 \r
                if(!config.embedded_audio)\r
                        start_playback();\r
@@ -241,8 +242,8 @@ public:
        ~decklink_consumer()\r
        {               \r
                is_running_ = false;\r
-               video_frame_buffer_.try_push(std::make_shared<core::read_frame>());\r
-               audio_frame_buffer_.try_push(std::make_shared<core::read_frame>());\r
+               video_frame_buffer_.try_push(core::frame::empty());\r
+               audio_frame_buffer_.try_push(core::frame::empty());\r
 \r
                if(output_ != nullptr) \r
                {\r
@@ -349,7 +350,7 @@ public:
                        else if(result == bmdOutputFrameFlushed)\r
                                graph_->set_tag("flushed-frame");\r
 \r
-                       std::shared_ptr<core::read_frame> frame;        \r
+                       std::shared_ptr<const core::frame> frame;       \r
                        video_frame_buffer_.pop(frame);                                 \r
                        schedule_next_video(make_safe_ptr(frame));      \r
                        \r
@@ -388,7 +389,7 @@ public:
                        }\r
                        else\r
                        {\r
-                               std::shared_ptr<core::read_frame> frame;\r
+                               std::shared_ptr<const core::frame> frame;\r
                                audio_frame_buffer_.pop(frame);\r
                                schedule_next_audio(frame->audio_data());\r
                        }\r
@@ -420,7 +421,7 @@ public:
                audio_scheduled_ += sample_frame_count;\r
        }\r
                        \r
-       void schedule_next_video(const safe_ptr<core::read_frame>& frame)\r
+       void schedule_next_video(const safe_ptr<const core::frame>& frame)\r
        {\r
                CComPtr<IDeckLinkVideoFrame> frame2(new decklink_frame(frame, format_desc_, config_.key_only));\r
                if(FAILED(output_->ScheduleVideoFrame(frame2, video_scheduled_, format_desc_.duration, format_desc_.time_scale)))\r
@@ -432,7 +433,7 @@ public:
                tick_timer_.restart();\r
        }\r
 \r
-       void send(const safe_ptr<core::read_frame>& frame)\r
+       void send(const safe_ptr<const core::frame>& frame)\r
        {\r
                auto exception = lock(exception_mutex_, [&]\r
                {\r
@@ -502,7 +503,7 @@ public:
                });\r
        }\r
        \r
-       virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<const core::frame>& frame) override\r
        {\r
                CASPAR_VERIFY(audio_cadence_.front() == static_cast<int>(frame->audio_data().size()));\r
                boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
index 88cd2e15b994405f656c09fff86846a3777022ae..ff7c68a21bf62e9046ae4baae1fb3aa9738b6856 100644 (file)
@@ -25,7 +25,7 @@
 \r
 #include "ffmpeg_consumer.h"\r
 \r
-#include <core/mixer/read_frame.h>\r
+#include <core/frame.h>\r
 #include <core/mixer/audio/audio_util.h>\r
 #include <core/consumer/frame_consumer.h>\r
 #include <core/video_format.h>\r
@@ -280,7 +280,7 @@ public:
                });\r
        }\r
 \r
-       std::shared_ptr<AVFrame> convert_video_frame(const safe_ptr<core::read_frame>& frame, AVCodecContext* c)\r
+       std::shared_ptr<AVFrame> convert_video_frame(const safe_ptr<const core::frame>& frame, AVCodecContext* c)\r
        {\r
                if(!sws_) \r
                {\r
@@ -301,7 +301,7 @@ public:
                return local_av_frame;\r
        }\r
   \r
-       std::shared_ptr<AVPacket> encode_video_frame(const safe_ptr<core::read_frame>& frame)\r
+       std::shared_ptr<AVPacket> encode_video_frame(const safe_ptr<const core::frame>& frame)\r
        { \r
                auto c = video_st_->codec;\r
  \r
@@ -336,7 +336,7 @@ public:
                return nullptr;\r
        }\r
                \r
-       std::shared_ptr<AVPacket> encode_audio_frame(const safe_ptr<core::read_frame>& frame)\r
+       std::shared_ptr<AVPacket> encode_audio_frame(const safe_ptr<const core::frame>& frame)\r
        {                       \r
                auto c = audio_st_->codec;\r
 \r
@@ -361,7 +361,7 @@ public:
                return pkt;\r
        }\r
                 \r
-       void send(const safe_ptr<core::read_frame>& frame)\r
+       void send(const safe_ptr<const core::frame>& frame)\r
        {\r
                executor_.begin_invoke([=]\r
                {               \r
@@ -412,7 +412,7 @@ public:
                consumer_.reset(new ffmpeg_consumer(filename_, format_desc, codec_, options_));\r
        }\r
        \r
-       virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<const core::frame>& frame) override\r
        {\r
                consumer_->send(frame);\r
                return true;\r
index bede25496f4b8b591ecd7ccce0682e545b317b32..e1a9071b4830f01693876efe5f52e007b7e9a543 100644 (file)
@@ -286,9 +286,9 @@ safe_ptr<core::write_frame> make_write_frame(const void* tag, const safe_ptr<AVF
        }\r
        \r
        // Fix field-order if needed\r
-       if(write->get_type() == core::field_mode::lower && frame_factory->get_video_format_desc().field_mode == core::field_mode::upper)\r
+       if(write->get_field_mode() == core::field_mode::lower && frame_factory->get_video_format_desc().field_mode == core::field_mode::upper)\r
                write->get_frame_transform().fill_translation[1] += 1.0/static_cast<double>(frame_factory->get_video_format_desc().height);\r
-       else if(write->get_type() == core::field_mode::upper && frame_factory->get_video_format_desc().field_mode == core::field_mode::lower)\r
+       else if(write->get_field_mode() == core::field_mode::upper && frame_factory->get_video_format_desc().field_mode == core::field_mode::lower)\r
                write->get_frame_transform().fill_translation[1] -= 1.0/static_cast<double>(frame_factory->get_video_format_desc().height);\r
 \r
        return make_safe_ptr(write);\r
index 0dc3ac0ea169f34529a71a9c790de77b5a7d5d2a..c115fb63e1b495b256b6b1b5f2aa12ed014063a9 100644 (file)
@@ -28,7 +28,7 @@
 \r
 #include <core/consumer/frame_consumer.h>\r
 #include <core/video_format.h>\r
-#include <core/mixer/read_frame.h>\r
+#include <core/frame.h>\r
 \r
 #include <boost/date_time/posix_time/posix_time.hpp>\r
 #include <boost/thread.hpp>\r
@@ -53,7 +53,7 @@ public:
        {\r
        }\r
        \r
-       virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<const core::frame>& frame) override\r
        {                               \r
                boost::thread async([frame]\r
                {\r
index 85c11816956b6c422237f977b591e8b841a81aa0..8f88484a1fdcb2e0b2bc111232afe3cfae3b4bec 100644 (file)
 \r
 #include <core/consumer/frame_consumer.h>\r
 #include <core/mixer/audio/audio_util.h>\r
+#include <core/mixer/audio/audio_mixer.h>\r
 #include <core/video_format.h>\r
 \r
-#include <core/mixer/read_frame.h>\r
+#include <core/frame.h>\r
 \r
 #include <SFML/Audio/SoundStream.hpp>\r
 \r
@@ -97,7 +98,7 @@ public:
                CASPAR_LOG(info) << print() << " Sucessfully Initialized.";\r
        }\r
        \r
-       virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<const core::frame>& frame) override\r
        {                       \r
                input_.push(std::make_shared<audio_buffer_16>(core::audio_32_to_16(frame->audio_data())));\r
                return true;\r
index 472a22d29a8a795f01f5ac740faa4243a6a43444..93fafa975310d7457e235b4d35e473d6d36a63c0 100644 (file)
@@ -34,7 +34,7 @@
 #include <ffmpeg/producer/filter/filter.h>\r
 \r
 #include <core/video_format.h>\r
-#include <core/mixer/read_frame.h>\r
+#include <core/frame.h>\r
 #include <core/consumer/frame_consumer.h>\r
 \r
 #include <boost/timer.hpp>\r
@@ -122,8 +122,8 @@ struct ogl_consumer : boost::noncopyable
        unsigned int                    screen_y_;\r
        unsigned int                    screen_width_;\r
        unsigned int                    screen_height_;\r
-       int                                     square_width_;\r
-       int                                     square_height_;                         \r
+       int                                             square_width_;\r
+       int                                             square_height_;                         \r
        \r
        sf::Window                              window_;\r
        \r
@@ -131,7 +131,7 @@ struct ogl_consumer : boost::noncopyable
        boost::timer                                    perf_timer_;\r
        boost::timer                                    tick_timer_;\r
 \r
-       tbb::concurrent_bounded_queue<safe_ptr<core::read_frame>>       frame_buffer_;\r
+       tbb::concurrent_bounded_queue<std::shared_ptr<const core::frame>>       frame_buffer_;\r
 \r
        boost::thread                   thread_;\r
        tbb::atomic<bool>               is_running_;\r
@@ -194,7 +194,7 @@ public:
        ~ogl_consumer()\r
        {\r
                is_running_ = false;\r
-               frame_buffer_.try_push(make_safe<core::read_frame>());\r
+               frame_buffer_.try_push(core::frame::empty());\r
                thread_.join();\r
        }\r
 \r
@@ -268,11 +268,11 @@ public:
                                                        is_running_ = false;\r
                                        }\r
                        \r
-                                       safe_ptr<core::read_frame> frame;\r
+                                       std::shared_ptr<const core::frame> frame;\r
                                        frame_buffer_.pop(frame);\r
                                        \r
                                        perf_timer_.restart();\r
-                                       render(frame);\r
+                                       render(make_safe_ptr(frame));\r
                                        graph_->set_value("frame-time", perf_timer_.elapsed()*format_desc_.fps*0.5);    \r
 \r
                                        window_.Display();\r
@@ -310,7 +310,7 @@ public:
                return av_frame;\r
        }\r
 \r
-       void render(const safe_ptr<core::read_frame>& frame)\r
+       void render(const safe_ptr<const core::frame>& frame)\r
        {                       \r
                if(static_cast<int>(frame->image_data().size()) != format_desc_.size)\r
                        return;\r
@@ -377,7 +377,7 @@ public:
                std::rotate(pbos_.begin(), pbos_.begin() + 1, pbos_.end());\r
        }\r
 \r
-       bool send(const safe_ptr<core::read_frame>& frame)\r
+       bool send(const safe_ptr<const core::frame>& frame)\r
        {\r
                if(!frame_buffer_.try_push(frame))\r
                        graph_->set_tag("dropped-frame");\r
@@ -476,7 +476,7 @@ public:
                CASPAR_LOG(info) << print() << L" Successfully Initialized.";   \r
        }\r
        \r
-       virtual bool send(const safe_ptr<core::read_frame>& frame) override\r
+       virtual bool send(const safe_ptr<const core::frame>& frame) override\r
        {\r
                return consumer_->send(frame);\r
        }\r
diff --git a/modules/reroute/producer/reroute_producer.cpp b/modules/reroute/producer/reroute_producer.cpp
new file mode 100644 (file)
index 0000000..e4bf123
--- /dev/null
@@ -0,0 +1,151 @@
+/*\r
+* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG (www.casparcg.com).\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+* GNU General Public License for more details.\r
+*\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+* Author: Robert Nagy, ronag89@gmail.com\r
+*/\r
+\r
+#include "../stdafx.h"\r
+\r
+#include "reroute_producer.h"\r
+\r
+#include <core/producer/frame_producer.h>\r
+#include <core/producer/frame/basic_frame.h>\r
+#include <core/producer/frame/frame_factory.h>\r
+#include <core/producer/frame/pixel_format.h>\r
+#include <core/mixer/write_frame.h>\r
+#include <core/frame.h>\r
+\r
+#include <common/exception/exceptions.h>\r
+#include <common/diagnostics/graph.h>\r
+#include <common/log.h>\r
+#include <common/reactive.h>\r
+\r
+#include <asmlib.h>\r
+\r
+#include <tbb/concurrent_queue.h>\r
+\r
+#include <boost/property_tree/ptree.hpp>\r
+#include <boost/range/algorithm_ext/push_back.hpp>\r
+\r
+#include <queue>\r
+\r
+namespace caspar { namespace reroute {\r
+               \r
+class reroute_producer : public reactive::observer<safe_ptr<const core::frame>>\r
+                                          , public core::frame_producer\r
+                                          , public enable_safe_from_this<reroute_producer>\r
+{\r
+       const safe_ptr<diagnostics::graph>                                                                      graph_;\r
+       const safe_ptr<core::frame_factory>                                                                     frame_factory_;\r
+       \r
+       tbb::concurrent_bounded_queue<std::shared_ptr<const core::frame>>       input_buffer_;\r
+       std::queue<safe_ptr<core::basic_frame>>                                                         frame_buffer_;\r
+       safe_ptr<core::basic_frame>                                                                                     last_frame_;\r
+       uint64_t                                                                                                                        frame_number_;\r
+\r
+public:\r
+       explicit reroute_producer(const safe_ptr<core::frame_factory>& frame_factory) \r
+               : frame_factory_(frame_factory)\r
+               , last_frame_(core::basic_frame::empty())\r
+               , frame_number_(0)\r
+       {\r
+               graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f));\r
+               graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
+               graph_->set_text(print());\r
+               diagnostics::register_graph(graph_);\r
+\r
+               input_buffer_.set_capacity(1);\r
+       }\r
+       \r
+       // observable\r
+\r
+       void on_next(const safe_ptr<const core::frame>& frame)\r
+       {\r
+               if(!input_buffer_.try_push(frame))\r
+                       graph_->set_tag("dropped-frame");\r
+       }\r
+\r
+       // frame_producer\r
+                       \r
+       virtual safe_ptr<core::basic_frame> receive(int) override\r
+       {\r
+               if(!frame_buffer_.empty())\r
+               {\r
+                       auto frame = frame_buffer_.front();\r
+                       frame_buffer_.pop();\r
+                       return last_frame_ = frame;\r
+               }\r
+               \r
+               std::shared_ptr<const core::frame> read_frame;\r
+               if(input_buffer_.try_pop(read_frame) || read_frame->image_data().empty())\r
+               {\r
+                       graph_->set_tag("late-frame");\r
+                       return core::basic_frame::late();               \r
+               }\r
+               \r
+               frame_number_++;\r
+               \r
+               core::pixel_format_desc desc;\r
+               bool double_speed       = std::abs(frame_factory_->get_video_format_desc().fps / 2.0 - read_frame->get_frame_rate()) < 0.01;            \r
+               bool half_speed         = std::abs(read_frame->get_frame_rate() / 2.0 - frame_factory_->get_video_format_desc().fps) < 0.01;\r
+\r
+               if(half_speed && frame_number_ % 2 == 0) // Skip frame\r
+                       return receive(0);\r
+\r
+               desc.pix_fmt = core::pixel_format::bgra;\r
+               desc.planes.push_back(core::pixel_format_desc::plane(read_frame->width(), read_frame->height(), 4));\r
+               auto frame = frame_factory_->create_frame(this, desc);\r
+\r
+               A_memcpy(frame->image_data().begin(), read_frame->image_data().begin(), read_frame->image_data().size());\r
+               frame->commit();\r
+               boost::push_back(frame->audio_data(), read_frame->audio_data());\r
+\r
+               frame_buffer_.push(frame);      \r
+               \r
+               if(double_speed)        \r
+                       frame_buffer_.push(frame);\r
+\r
+               return receive(0);\r
+       }       \r
+\r
+       virtual safe_ptr<core::basic_frame> last_frame() const override\r
+       {\r
+               return last_frame_; \r
+       }       \r
+\r
+       virtual std::wstring print() const override\r
+       {\r
+               return L"reroute[]";\r
+       }\r
+\r
+       virtual boost::property_tree::wptree info() const override\r
+       {\r
+               boost::property_tree::wptree info;\r
+               info.add(L"type", L"rerotue-producer");\r
+               return info;\r
+       }\r
+};\r
+\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factory>& frame_factory, reactive::observable<safe_ptr<const core::frame>>& o)\r
+{\r
+       auto producer = make_safe<reroute_producer>(frame_factory);\r
+       o.subscribe(producer);\r
+       return create_producer_print_proxy(producer);\r
+}\r
+\r
+}}
\ No newline at end of file
similarity index 68%
rename from core/producer/channel/channel_producer.h
rename to modules/reroute/producer/reroute_producer.h
index 67ed043ede58eb487d10ebb158fd9ff4e69b925c..90ec2ab07f08d3bfb22e88261534003645e98f8d 100644 (file)
 \r
 #pragma once\r
 \r
-#include "../../video_channel.h"\r
-\r
 #include <common/memory/safe_ptr.h>\r
+#include <common/reactive.h>\r
+#include <common/forward.h>\r
 \r
-#include <string>\r
-#include <vector>\r
+#include <core/producer/frame/frame_factory.h>\r
+#include <core/producer/frame_producer.h>\r
+#include <core/frame.h>\r
 \r
-namespace caspar { namespace core {\r
+namespace caspar { namespace reroute {\r
        \r
-safe_ptr<struct frame_producer> create_channel_producer(const safe_ptr<struct frame_factory>& frame_factory, const safe_ptr<video_channel>& channel);\r
+safe_ptr<core::frame_producer> create_producer(const safe_ptr<core::frame_factory>& frame_factory, reactive::observable<safe_ptr<const core::frame>>& o);\r
 \r
 }}\r
diff --git a/modules/reroute/reroute.vcxproj.filters b/modules/reroute/reroute.vcxproj.filters
new file mode 100644 (file)
index 0000000..858b01b
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <Filter Include="source">\r
+      <UniqueIdentifier>{5475f6ab-bba4-49d3-822f-af300d1a550d}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="source\producer">\r
+      <UniqueIdentifier>{4f56d221-1d96-432f-97f8-d2d274a6310f}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClCompile Include="stdafx.cpp">\r
+      <Filter>source</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\reroute_producer.cpp">\r
+      <Filter>source\producer</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="stdafx.h">\r
+      <Filter>source</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\reroute_producer.h">\r
+      <Filter>source\producer</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
diff --git a/modules/reroute/stdafx.cpp b/modules/reroute/stdafx.cpp
new file mode 100644 (file)
index 0000000..a990781
--- /dev/null
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes\r
+// reroute.pch will be the pre-compiled header\r
+// stdafx.obj will contain the pre-compiled type information\r
+\r
+#include "stdafx.h"\r
+\r
+// TODO: reference any additional headers you need in STDAFX.H\r
+// and not in this file\r
diff --git a/modules/reroute/stdafx.h b/modules/reroute/stdafx.h
new file mode 100644 (file)
index 0000000..50e9667
--- /dev/null
@@ -0,0 +1 @@
+#pragma once\r
index 5a4c62b1be6a27633a978f464733daade79f58d0..7b27ec2cf93fafda0cf1baa11d95fe8aa3931c77 100644 (file)
@@ -38,7 +38,6 @@
 #include <core/producer/frame_producer.h>\r
 #include <core/video_format.h>\r
 #include <core/producer/transition/transition_producer.h>\r
-#include <core/producer/channel/channel_producer.h>\r
 #include <core/producer/frame/frame_transform.h>\r
 #include <core/producer/stage.h>\r
 #include <core/producer/layer.h>\r
@@ -55,6 +54,7 @@
 #include <modules/ffmpeg/producer/util/util.h>\r
 #include <modules/image/image.h>\r
 #include <modules/ogl/ogl.h>\r
+#include <modules/reroute/producer/reroute_producer.h>\r
 \r
 #include <algorithm>\r
 #include <locale>\r
@@ -242,7 +242,7 @@ bool ChannelGridCommand::DoExecute()
        {\r
                if(channel != self)\r
                {\r
-                       auto producer = create_channel_producer(self->frame_factory(), channel);                \r
+                       auto producer = reroute::create_producer(self->frame_factory(), *channel);              \r
                        self->stage()->load(index, producer, false);\r
                        self->stage()->play(index);\r
                        index++;\r
index 9c2944f2b38adfe4bf5b68548c15cedc8b885ddc..832969f2ceb321bc7ebf06c7103932699524ffa0 100644 (file)
@@ -23,6 +23,9 @@
     <ProjectReference Include="..\modules\flash\flash.vcxproj">\r
       <Project>{816deaba-3757-4306-afe0-c27cf96c4dea}</Project>\r
     </ProjectReference>\r
+    <ProjectReference Include="..\modules\reroute\reroute.vcxproj">\r
+      <Project>{7d58bd57-fdd5-46e6-a23b-ed14b5314a0e}</Project>\r
+    </ProjectReference>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="amcp\AMCPCommand.h" />\r
index ca0658f371398b951d88c5dea1b76315de783ef4..fc279e050aa76cf4e56dc6b98dffbfe8341768b3 100644 (file)
@@ -26,7 +26,7 @@
 #include <common/exception/exceptions.h>\r
 #include <common/utf.h>\r
 \r
-#include <core/mixer/gpu/ogl_device.h>\r
+#include <core/mixer/gpu/accelerator.h>\r
 #include <core/video_channel.h>\r
 #include <core/video_format.h>\r
 #include <core/producer/stage.h>\r
@@ -64,12 +64,12 @@ using namespace protocol;
 \r
 struct server::impl : boost::noncopyable\r
 {\r
-       safe_ptr<ogl_device>                                            ogl_;\r
+       safe_ptr<gpu::accelerator>                                      ogl_;\r
        std::vector<safe_ptr<IO::AsyncEventServer>> async_servers_;     \r
        std::vector<safe_ptr<video_channel>>            channels_;\r
 \r
        impl()          \r
-               : ogl_(ogl_device::create())\r
+               : ogl_(gpu::accelerator::create())\r
        {                       \r
                ffmpeg::init();\r
                CASPAR_LOG(info) << L"Initialized ffmpeg module.";\r
index 31135a3d1cd206ccf74ef45132764d1c94fb057f..02cfa0f675aa9bee25703c078ef95cb4d5b03f88 100644 (file)
@@ -52,6 +52,9 @@
     <ProjectReference Include="..\modules\ogl\ogl.vcxproj">\r
       <Project>{88f974f0-d09f-4788-8cf8-f563209e60c1}</Project>\r
     </ProjectReference>\r
+    <ProjectReference Include="..\modules\reroute\reroute.vcxproj">\r
+      <Project>{7d58bd57-fdd5-46e6-a23b-ed14b5314a0e}</Project>\r
+    </ProjectReference>\r
     <ProjectReference Include="..\protocol\protocol.vcxproj">\r
       <Project>{2040b361-1fb6-488e-84a5-38a580da90de}</Project>\r
     </ProjectReference>\r