]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2:
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Mon, 25 Oct 2010 23:49:41 +0000 (23:49 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Mon, 25 Oct 2010 23:49:41 +0000 (23:49 +0000)
- GPU based transitions
- GPU and general refactoring

git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@182 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

75 files changed:
common/common.vcxproj
common/common.vcxproj.filters
common/gl/utility.h [new file with mode: 0644]
common/image/image.cpp
common/image/image.h
common/image/lerp.cpp [deleted file]
common/image/lerp.h [deleted file]
common/image/over.cpp [deleted file]
common/image/over.h [deleted file]
common/image/pre_multiply.cpp [deleted file]
common/image/pre_multiply.h [deleted file]
common/image/shuffle.cpp [deleted file]
common/image/shuffle.h [deleted file]
core/caspar.config
core/config.h
core/consumer/bluefish/BlueFishVideoConsumer.cpp
core/consumer/bluefish/BlueFishVideoConsumer.h
core/consumer/bluefish/BluefishFrameManager.h [deleted file]
core/consumer/bluefish/BluefishPlaybackStrategy.cpp
core/consumer/bluefish/BluefishPlaybackStrategy.h
core/consumer/decklink/DecklinkVideoConsumer.cpp
core/consumer/decklink/DecklinkVideoConsumer.h
core/consumer/frame_consumer.h
core/consumer/oal/oal_frame_consumer.cpp
core/consumer/oal/oal_frame_consumer.h
core/consumer/ogl/ogl_frame_consumer.cpp
core/consumer/ogl/ogl_frame_consumer.h
core/core.vcxproj
core/core.vcxproj.filters
core/frame/audio_chunk.cpp [deleted file]
core/frame/audio_chunk.h [deleted file]
core/frame/composite_gpu_frame.cpp [new file with mode: 0644]
core/frame/composite_gpu_frame.h [new file with mode: 0644]
core/frame/frame.h [deleted file]
core/frame/frame_factory.h [new file with mode: 0644]
core/frame/frame_fwd.h
core/frame/gpu_frame.cpp [new file with mode: 0644]
core/frame/gpu_frame.h [new file with mode: 0644]
core/frame/gpu_frame_processor.cpp [new file with mode: 0644]
core/frame/gpu_frame_processor.h [moved from core/frame/system_frame.h with 61% similarity]
core/frame/system_frame.cpp [deleted file]
core/main.cpp
core/producer/color/color_producer.cpp
core/producer/ffmpeg/audio/audio_decoder.cpp
core/producer/ffmpeg/audio/audio_decoder.h
core/producer/ffmpeg/ffmpeg_producer.cpp
core/producer/ffmpeg/input.cpp
core/producer/ffmpeg/input.h
core/producer/ffmpeg/packet.h
core/producer/ffmpeg/video/video_decoder.cpp
core/producer/ffmpeg/video/video_scaler.h [deleted file]
core/producer/ffmpeg/video/video_transformer.cpp [moved from core/producer/ffmpeg/video/video_scaler.cpp with 74% similarity]
core/producer/ffmpeg/video/video_transformer.h [new file with mode: 0644]
core/producer/flash/FlashAxContainer.cpp
core/producer/flash/FlashAxContainer.h
core/producer/flash/bitmap.cpp [moved from core/frame/bitmap_frame.cpp with 52% similarity]
core/producer/flash/bitmap.h [moved from core/frame/bitmap_frame.h with 76% similarity]
core/producer/flash/cg_producer.cpp
core/producer/flash/cg_producer.h
core/producer/flash/ct_producer.cpp
core/producer/flash/flash_producer.cpp
core/producer/flash/flash_producer.h
core/producer/frame_producer.h
core/producer/image/image_loader.cpp
core/producer/image/image_producer.cpp
core/producer/image/image_scroll_producer.cpp
core/producer/transition/transition_producer.cpp
core/producer/transition/transition_producer.h
core/protocol/amcp/AMCPCommandsImpl.cpp
core/protocol/amcp/AMCPCommandsImpl.h
core/renderer/layer.cpp
core/renderer/layer.h
core/renderer/render_device.cpp
core/renderer/render_device.h
core/server.cpp

index e5ce30c830105231749a6ca50a1913079e1ad6fa..ac4fdb01ce4e0067e16677ca2c3359f826f86780 100644 (file)
@@ -57,6 +57,8 @@
       <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <TreatWarningAsError>true</TreatWarningAsError>\r
       <SmallerTypeCheck>true</SmallerTypeCheck>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
     </ClCompile>\r
     <Link>\r
       <SubSystem>Windows</SubSystem>\r
     <ClInclude Include="config.h" />\r
     <ClInclude Include="exception\exceptions.h" />\r
     <ClInclude Include="exception\win32_exception.h" />\r
+    <ClInclude Include="gl\utility.h" />\r
     <ClInclude Include="hardware\cpuid.h" />\r
     <ClInclude Include="image\clear.h" />\r
     <ClInclude Include="image\copy.h" />\r
     <ClInclude Include="image\copy_field.h" />\r
     <ClInclude Include="image\image.h" />\r
-    <ClInclude Include="image\lerp.h" />\r
-    <ClInclude Include="image\over.h" />\r
-    <ClInclude Include="image\pre_multiply.h" />\r
-    <ClInclude Include="image\shuffle.h" />\r
     <ClInclude Include="io\AsyncEventServer.h" />\r
     <ClInclude Include="io\ClientInfo.h" />\r
     <ClInclude Include="io\ProtocolStrategy.h" />\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="image\lerp.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
-    <ClCompile Include="image\over.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
-    <ClCompile Include="image\pre_multiply.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
-    <ClCompile Include="image\shuffle.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
     <ClCompile Include="io\AsyncEventServer.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
index bfc19e9215179ec0f5294e3d7af06ec846c24abf..8f605d951d2c94f5b1f0fba04b027385a337be9e 100644 (file)
@@ -26,6 +26,9 @@
     <Filter Include="Source\hardware">\r
       <UniqueIdentifier>{5115d125-61f1-4fdd-9924-0f1bdced5d27}</UniqueIdentifier>\r
     </Filter>\r
+    <Filter Include="Source\gl">\r
+      <UniqueIdentifier>{0d94bbc2-e196-4618-a90b-19392a3a0a8e}</UniqueIdentifier>\r
+    </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="stdafx.cpp">\r
     <ClCompile Include="image\image.cpp">\r
       <Filter>Source\image</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="image\lerp.cpp">\r
-      <Filter>Source\image</Filter>\r
-    </ClCompile>\r
-    <ClCompile Include="image\over.cpp">\r
-      <Filter>Source\image</Filter>\r
-    </ClCompile>\r
-    <ClCompile Include="image\pre_multiply.cpp">\r
-      <Filter>Source\image</Filter>\r
-    </ClCompile>\r
-    <ClCompile Include="image\shuffle.cpp">\r
-      <Filter>Source\image</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="image\clear.cpp">\r
       <Filter>Source\image</Filter>\r
     </ClCompile>\r
     <ClInclude Include="image\image.h">\r
       <Filter>Source\image</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="image\lerp.h">\r
-      <Filter>Source\image</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="image\over.h">\r
-      <Filter>Source\image</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="image\pre_multiply.h">\r
-      <Filter>Source\image</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="image\shuffle.h">\r
-      <Filter>Source\image</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="image\clear.h">\r
       <Filter>Source\image</Filter>\r
     </ClInclude>\r
     <ClInclude Include="utility\find_file.h">\r
       <Filter>Source\utility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="gl\utility.h">\r
+      <Filter>Source\gl</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file
diff --git a/common/gl/utility.h b/common/gl/utility.h
new file mode 100644 (file)
index 0000000..df5a170
--- /dev/null
@@ -0,0 +1,25 @@
+#pragma once\r
+\r
+#include <Glee.h>\r
+\r
+#include "../exception/exceptions.h"\r
+\r
+#include <boost/lexical_cast.hpp>\r
+\r
+namespace caspar { namespace common { namespace gpu {\r
+\r
+#ifdef _DEBUG\r
+       \r
+#define CASPAR_GL_CHECK(expr) \\r
+       do \\r
+       { \\r
+               expr;  \\r
+               auto error = glGetError(); \\r
+               if(error != GL_NO_ERROR) \\r
+                       BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(boost::lexical_cast<std::string>(glGetError()))); \\r
+       }while(0);\r
+#else\r
+#define CASPAR_GL_CHECK(expr) expr\r
+#endif\r
+\r
+}}}
\ No newline at end of file
index 5d2f2e5a521453b508574b7eb362f0be0983e3c1..4bcdb01ae2fa76b080d7acbb90fb404323d23c45 100644 (file)
 \r
 #include "image.h"\r
 \r
-#include "over.h"\r
-#include "lerp.h"\r
-#include "shuffle.h"\r
-#include "pre_multiply.h"\r
 #include "copy.h"\r
 #include "copy_field.h"\r
 #include "clear.h"\r
@@ -36,35 +32,11 @@ namespace caspar{ namespace common{ namespace image{
 namespace detail\r
 {\r
        cpuid my_cpuid;\r
-       pre_over_fun            pre_over = get_pre_over_fun(my_cpuid.SIMD);\r
-       shuffle_fun                     shuffle = get_shuffle_fun(my_cpuid.SIMD);\r
-       lerp_fun                        lerp = get_lerp_fun(my_cpuid.SIMD);\r
-       pre_multiply_fun        pre_multiply = get_pre_multiply_fun(my_cpuid.SIMD);\r
        copy_fun                        copy = get_copy_fun(my_cpuid.SIMD);\r
        copy_field_fun          copy_field = get_copy_field_fun(my_cpuid.SIMD);\r
        clear_fun                       clear = get_clear_fun(my_cpuid.SIMD);\r
 }\r
 \r
-void shuffle(void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha)\r
-{\r
-       (*detail::shuffle)(dest, source, size, red, green, blue, alpha);\r
-}\r
-\r
-void pre_over(void* dest, const void* source1, const void* source2, size_t size)\r
-{\r
-       (*detail::pre_over)(dest, source1, source2, size);\r
-}\r
-\r
-void lerp(void* dest, const void* source1, const void* source2, float alpha, size_t size)\r
-{\r
-       (*detail::lerp)(dest, source1, source2, alpha, size);\r
-}\r
-\r
-void pre_multiply(void* dest, const void* source, size_t size)\r
-{\r
-       (*detail::pre_multiply)(dest, source, size);\r
-}\r
-\r
 void copy(void* dest, const void* source, size_t size)\r
 {\r
        (*detail::copy)(dest, source, size);\r
index 10bd962596eb9bb439cd5dc0af84d34bea539f5d..d97a4edbbc794d82f605343336bf6787e568576e 100644 (file)
@@ -26,28 +26,16 @@ namespace caspar{ namespace common{ namespace image{
        \r
 void set_version(SIMD simd = AUTO);\r
 \r
-void shuffle(void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha);\r
-void pre_over(void* dest, const void* source1, const void* source2, size_t size);\r
-void lerp(void* dest, const void* source1, const void* source2, float alpha, size_t size);\r
-void pre_multiply(void* dest, const void* source, size_t size);\r
 void copy(void* dest, const void* source, size_t size);\r
 void clear(void* dest, size_t size);\r
 void copy_field(unsigned char* pDest, const unsigned char* pSrc, size_t fieldIndex, size_t width, size_t height);\r
 \r
 namespace detail\r
 {\r
-       typedef void(*pre_over_fun)(void*, const void*, const void*, size_t);\r
-       typedef void(*shuffle_fun)(void*, const void*, size_t, const u8, const u8, const u8, const u8);\r
-       typedef void(*lerp_fun)(void*, const void*, const void*, float, size_t);\r
-       typedef void(*pre_multiply_fun)(void*, const void*, size_t);\r
        typedef void(*copy_fun)(void*, const void*, size_t);\r
        typedef void(*copy_field_fun)(unsigned char* pDest, const unsigned char* pSrc, size_t fieldIndex, size_t width, size_t height);\r
        typedef void(*clear_fun)(void*, size_t);\r
        \r
-       extern pre_over_fun             pre_over;\r
-       extern shuffle_fun              shuffle;\r
-       extern lerp_fun                 lerp;\r
-       extern pre_multiply_fun pre_multiply;\r
        extern copy_fun                 copy;\r
        extern copy_field_fun   copy_field;\r
        extern clear_fun                clear;\r
diff --git a/common/image/lerp.cpp b/common/image/lerp.cpp
deleted file mode 100644 (file)
index e3f6755..0000000
+++ /dev/null
@@ -1,174 +0,0 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
\r
-#include "../stdafx.h"\r
-\r
-#include "lerp.h"\r
-\r
-#include "../utility/types.h"\r
-\r
-#include "tbb/parallel_for.h"\r
-#include "tbb/blocked_range.h"\r
-\r
-#include <cassert>\r
-#include <intrin.h>\r
-#include <functional>\r
-\r
-using namespace std::tr1::placeholders;\r
-\r
-namespace caspar{\r
-namespace common{\r
-namespace image{\r
-\r
-static const size_t STRIDE = sizeof(__m128i)*4;\r
-\r
-void DolerpParallel(const tbb::blocked_range<size_t>& r, const std::tr1::function<void(void*, const void*, const void*, float, size_t)>& func, void* dest, const void* source1, const void* source2, float alpha)\r
-{\r
-       size_t offset = r.begin()*STRIDE;\r
-       size_t size = r.size()*STRIDE;\r
-       func(reinterpret_cast<s8*>(dest) + offset, reinterpret_cast<const s8*>(source1) + offset, reinterpret_cast<const s8*>(source2) + offset, alpha, size);\r
-}\r
-\r
-void lerpParallel(const std::tr1::function<void(void*, const void*, const void*, float, size_t)>& func, void* dest, const void* source1, const void* source2, float alpha, size_t size)\r
-{\r
-       tbb::parallel_for(tbb::blocked_range<size_t>(0, size/STRIDE), std::bind(&DolerpParallel, std::placeholders::_1, func, dest, source1, source2, alpha));  \r
-}\r
-\r
-lerp_fun get_lerp_fun(SIMD simd)\r
-{\r
-       if(simd >= SSE2)\r
-               return lerpParallel_SSE2;\r
-       else\r
-               return lerpParallel_REF;\r
-}\r
-\r
-void lerp_SSE2(void* dest, const void* source1, const void* source2, float alpha, size_t size)\r
-{\r
-       static const u32 PSD = 64;\r
-       \r
-       static const __m128i lomask = _mm_set1_epi32(0x00FF00FF);\r
-       static const __m128i round = _mm_set1_epi16(128);\r
-\r
-       assert(source1 != NULL && source2 != NULL && dest != NULL);\r
-       assert(size % STRIDE == 0);\r
-       assert(alpha >= 0.0 && alpha <= 1.0);\r
-\r
-       const __m128i* source128_1 = reinterpret_cast<const __m128i*>(source1);\r
-       const __m128i* source128_2 = reinterpret_cast<const __m128i*>(source2);\r
-       __m128i* dest128 = reinterpret_cast<__m128i*>(dest);\r
-\r
-       __m128i s = _mm_setzero_si128();\r
-       __m128i d = _mm_setzero_si128();\r
-       const __m128i a = _mm_set1_epi16(static_cast<u8>(alpha*256.0f+0.5f));\r
-       \r
-       __m128i drb, dga, srb, sga;\r
-       \r
-       for (size_t k = 0, length = size/STRIDE; k < length; ++k)\r
-       {               \r
-               _mm_prefetch(reinterpret_cast<const char*>(source128_1 + PSD), _MM_HINT_NTA);   \r
-               _mm_prefetch(reinterpret_cast<const char*>(source128_2 + PSD), _MM_HINT_NTA);\r
-               // TODO: assembly optimization use PSHUFD on moves before calculations, lower latency than MOVDQA (R.N) http://software.intel.com/en-us/articles/fast-simd-integer-move-for-the-intel-pentiumr-4-processor/\r
-\r
-               for(int n = 0; n < 4; ++n, ++dest128, ++source128_1, ++source128_2)\r
-               {\r
-                       // r = d + (s-d)*alpha/256\r
-                       s = _mm_load_si128(source128_1);        // AABBGGRR\r
-                       d = _mm_load_si128(source128_2);        // AABBGGRR\r
-\r
-                       srb = _mm_and_si128(lomask, s);         // 00BB00RR             // unpack\r
-                       sga = _mm_srli_epi16(s, 8);                     // AA00GG00             // unpack\r
-                       \r
-                       drb = _mm_and_si128(lomask, d);         // 00BB00RR             // unpack\r
-                       dga = _mm_srli_epi16(d, 8);                     // AA00GG00             // unpack\r
-\r
-                       srb = _mm_sub_epi16(srb, drb);          // BBBBRRRR             // sub\r
-                       srb = _mm_mullo_epi16(srb, a);          // BBBBRRRR             // mul\r
-                       srb = _mm_add_epi16(srb, round);\r
-                       \r
-                       sga = _mm_sub_epi16(sga, dga);          // AAAAGGGG             // sub\r
-                       sga = _mm_mullo_epi16(sga, a);          // AAAAGGGG             // mul\r
-                       sga = _mm_add_epi16(sga, round);\r
-\r
-                       srb = _mm_srli_epi16(srb, 8);           // 00BB00RR             // prepack and div\r
-                       sga = _mm_andnot_si128(lomask, sga);// AA00GG00         // prepack and div\r
-\r
-                       srb = _mm_or_si128(srb, sga);           // AABBGGRR             // pack\r
-\r
-                       srb = _mm_add_epi8(srb, d);                     // AABBGGRR             // add          there is no overflow(R.N)\r
-\r
-                       _mm_stream_si128(dest128, srb);\r
-               }\r
-       }\r
-       _mm_mfence();   //ensure last WC buffers get flushed to memory\r
-}\r
-\r
-void lerpParallel_SSE2(void* dest, const void* source1, const void* source2, float alpha, size_t size)\r
-{\r
-       lerpParallel(&lerp_SSE2, dest, source1, source2, alpha, size);\r
-}\r
-\r
-void lerp_REF(void* dest, const void* source1, const void* source2, float alpha, size_t size)\r
-{\r
-       assert(source1 != NULL && source2 != NULL && dest != NULL);\r
-       assert(size % 4 == 0);\r
-       assert(alpha >= 0.0f && alpha <= 1.0f);\r
-\r
-       const u8* source8_1 = reinterpret_cast<const u8*>(source1);\r
-       const u8* source8_2 = reinterpret_cast<const u8*>(source2);\r
-       u8* dest8 = reinterpret_cast<u8*>(dest);\r
-\r
-       u8 a = static_cast<u8>(alpha*256.0f);\r
-       for(size_t n = 0; n < size; n+=4)\r
-       {\r
-               // s\r
-               u32 sr = source8_1[n+0];\r
-               u32 sg = source8_1[n+1];\r
-               u32 sb = source8_1[n+2];\r
-               u32 sa = source8_1[n+3];\r
-\r
-               // d\r
-               u32 dr = source8_2[n+0];\r
-               u32 dg = source8_2[n+1];\r
-               u32 db = source8_2[n+2];\r
-               u32 da = source8_2[n+3];\r
-\r
-               //dest8[n+0] = dr + ((sr-dr)*a)/256;\r
-               //dest8[n+1] = dg + ((sg-dg)*a)/256;\r
-               //dest8[n+2] = db + ((sb-db)*a)/256;\r
-               //dest8[n+3] = da + ((sa-da)*a)/256;\r
-\r
-               dest8[n+0] = static_cast<u8>( dr + int(float((sr-dr)*a)/256.0f+0.5f));\r
-               dest8[n+1] = static_cast<u8>( dg + int(float((sg-dg)*a)/256.0f+0.5f));\r
-               dest8[n+2] = static_cast<u8>( db + int(float((sb-db)*a)/256.0f+0.5f));\r
-               dest8[n+3] = static_cast<u8>(da + int(float((sa-da)*a)/256.0f+0.5f));\r
-\r
-       }\r
-}\r
-\r
-void lerpParallel_REF(void* dest, const void* source1, const void* source2, float alpha, size_t size)\r
-{\r
-       lerpParallel(&lerp_REF, dest, source1, source2, alpha, size);\r
-}\r
-\r
-} // namespace image\r
-} // namespace common\r
-} // namespace caspar\r
-\r
-\r
diff --git a/common/image/lerp.h b/common/image/lerp.h
deleted file mode 100644 (file)
index 0712629..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
-#pragma once\r
-\r
-#include "../hardware/cpuid.h"\r
-\r
-namespace caspar{ namespace common{ namespace image{\r
-               \r
-void lerp_SSE2(void* dest, const void* source1, const void* source2, float alpha, size_t size);\r
-void lerp_REF (void* dest, const void* source1, const void* source2, float alpha, size_t size);\r
-void lerpParallel_SSE2(void* dest, const void* source1, const void* source2, float alpha, size_t size);\r
-void lerpParallel_REF (void* dest, const void* source1, const void* source2, float alpha, size_t size);\r
-void lerp_OLD (void* dest, const void* source1, const void* source2, float alpha, size_t size);\r
-\r
-typedef void(*lerp_fun)(void*, const void*, const void*, float, size_t);\r
-lerp_fun get_lerp_fun(SIMD simd = REF);\r
-\r
-}}}\r
-\r
-\r
diff --git a/common/image/over.cpp b/common/image/over.cpp
deleted file mode 100644 (file)
index d6488ea..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
\r
-#include "../stdafx.h"\r
-\r
-#include "over.h"\r
-\r
-#include "../hardware/cpuid.h"\r
-#include "../utility/types.h"\r
-\r
-#include "tbb/parallel_for.h"\r
-#include "tbb/blocked_range.h"\r
-\r
-#include <cassert>\r
-#include <intrin.h>\r
-#include <functional>\r
-\r
-using namespace std::placeholders;\r
-\r
-namespace caspar{ namespace common{ namespace image    {\r
-\r
-static const size_t STRIDE = sizeof(__m128i)*4;\r
-\r
-void Dopre_overParallel(const tbb::blocked_range<size_t>& r, const std::tr1::function<void(void*, const void*, const void*, size_t)>& func, void* dest, const void* source1, const void* source2)\r
-{\r
-       size_t offset = r.begin()*STRIDE;\r
-       size_t size = r.size()*STRIDE;\r
-       func(reinterpret_cast<s8*>(dest) + offset, reinterpret_cast<const s8*>(source1) + offset, reinterpret_cast<const s8*>(source2) + offset, size);\r
-}\r
-\r
-void pre_overParallel(const std::tr1::function<void(void*, const void*, const void*, size_t)>& func, void* dest, const void* source1, const void* source2, size_t size)\r
-{\r
-       tbb::parallel_for(tbb::blocked_range<size_t>(0, size/STRIDE), std::bind(&Dopre_overParallel, std::placeholders::_1, func, dest, source1, source2));     \r
-}\r
-\r
-pre_over_fun get_pre_over_fun(SIMD simd)\r
-{\r
-       if(simd >= SSE2)\r
-               return pre_overParallel_SSE2;\r
-       else\r
-               return pre_overParallel_REF;\r
-}\r
-\r
-// this function performs precise calculations\r
-void pre_over_SSE2(void* dest, const void* source1, const void* source2, size_t size)\r
-{\r
-       static const u32 PSD = 64;\r
-\r
-       static const __m128i round = _mm_set1_epi16(128);\r
-       static const __m128i lomask = _mm_set1_epi32(0x00FF00FF);\r
-\r
-       assert(source1 != NULL && source2 != NULL && dest != NULL);\r
-       assert(size % STRIDE == 0);\r
-\r
-       const __m128i* source128_1 = reinterpret_cast<const __m128i*>(source1);\r
-       const __m128i* source128_2 = reinterpret_cast<const __m128i*>(source2);\r
-       __m128i*           dest128 = reinterpret_cast<__m128i*>(dest);  \r
-       \r
-       __m128i d, s, a, rb, ag, t;\r
-\r
-       // TODO: dynamic prefetch schedluing distance? needs to be optimized (R.N)\r
-\r
-       for(size_t k = 0, length = size/STRIDE; k < length; ++k)        \r
-       {\r
-               // TODO: put prefetch between calculations?(R.N)\r
-               _mm_prefetch(reinterpret_cast<const s8*>(source128_1+PSD), _MM_HINT_NTA);\r
-               _mm_prefetch(reinterpret_cast<const s8*>(source128_2+PSD), _MM_HINT_NTA);       \r
-\r
-               // work on entire cacheline before next prefetch\r
-               for(int n = 0; n < 4; ++n, ++dest128, ++source128_1, ++source128_2)\r
-               {\r
-                       // TODO: assembly optimization use PSHUFD on moves before calculations, lower latency than MOVDQA (R.N) http://software.intel.com/en-us/articles/fast-simd-integer-move-for-the-intel-pentiumr-4-processor/\r
-\r
-                       // TODO: load entire cacheline at the same time? are there enough registers? 32 bit mode (special compile for 64bit?) (R.N)\r
-                       s = _mm_load_si128(source128_1);                // AABGGRR\r
-                       d = _mm_load_si128(source128_2);                // AABGGRR\r
-                                               \r
-                       // PRELERP(S, D) = S+D - ((S*D[A]+0x80)>>8)+(S*D[A]+0x80))>>8\r
-                       // T = S*D[A]+0x80 => PRELERP(S,D) = S+D - ((T>>8)+T)>>8\r
-\r
-                       // set alpha to lo16 from dest_\r
-                       a = _mm_srli_epi32(d, 24);                      // 000000AA     \r
-                       rb = _mm_slli_epi32(a, 16);                     // 00AA0000\r
-                       a = _mm_or_si128(rb, a);                        // 00AA00AA\r
-\r
-                       rb = _mm_and_si128(lomask, s);          // 00BB00RR             \r
-                       rb = _mm_mullo_epi16(rb, a);            // BBBBRRRR     \r
-                       rb = _mm_add_epi16(rb, round);          // BBBBRRRR\r
-                       t = _mm_srli_epi16(rb, 8);                      \r
-                       t = _mm_add_epi16(t, rb);\r
-                       rb = _mm_srli_epi16(t, 8);                      // 00BB00RR     \r
-\r
-                       ag = _mm_srli_epi16(s, 8);                      // 00AA00GG             \r
-                       ag = _mm_mullo_epi16(ag, a);            // AAAAGGGG             \r
-                       ag = _mm_add_epi16(ag, round);\r
-                       t = _mm_srli_epi16(ag, 8);\r
-                       t = _mm_add_epi16(t, ag);\r
-                       ag = _mm_andnot_si128(lomask, t);       // AA00GG00             \r
-                                       \r
-                       rb = _mm_or_si128(rb, ag);                      // AABGGRR              pack\r
-                                       \r
-                       rb = _mm_sub_epi8(s, rb);                       // sub S-[(D[A]*S)/255]\r
-                       d = _mm_add_epi8(d, rb);                        // add D+[S-(D[A]*S)/255]\r
-\r
-                       _mm_stream_si128(dest128, d);\r
-               }\r
-       }       \r
-       _mm_mfence();   //ensure last WC buffers get flushed to memory          \r
-}\r
-\r
-void pre_overParallel_SSE2(void* dest, const void* source1, const void* source2, size_t size)\r
-{\r
-       pre_overParallel(&pre_over_SSE2, dest, source1, source2, size); \r
-}\r
-\r
-// TODO: optimize\r
-void pre_over_REF(void* dest, const void* source1, const void* source2, size_t size)\r
-{      \r
-       assert(source1 != NULL && source2 != NULL && dest != NULL);\r
-       assert(size % 4 == 0);\r
-\r
-       const u8* source8_1 = reinterpret_cast<const u8*>(source1);\r
-       const u8* source8_2 = reinterpret_cast<const u8*>(source2);\r
-       u8* dest8 = reinterpret_cast<u8*>(dest);\r
-\r
-       for(size_t n = 0; n < size; n+=4)\r
-       {\r
-               u32 r1 = source8_1[n+0];\r
-               u32 g1 = source8_1[n+1];\r
-               u32 b1 = source8_1[n+2];\r
-               u32 a1 = source8_1[n+3];\r
-\r
-               u32 r2 = source8_2[n+0];\r
-               u32 g2 = source8_2[n+1];\r
-               u32 b2 = source8_2[n+2];\r
-               u32 a2 = source8_2[n+3];\r
-\r
-               dest8[n+0] = static_cast<u8>(r2 + r1 - (a2*r1)/255);\r
-               dest8[n+1] = static_cast<u8>(g2 + g1 - (a2*g1)/255);\r
-               dest8[n+2] = static_cast<u8>(b2 + b1 - (a2*b1)/255);\r
-               dest8[n+3] = static_cast<u8>(a2 + a1 - (a2*a1)/255);\r
-\r
-               // PRECISE\r
-               //if(a2 > 0)\r
-               //{\r
-               //      dest8[n+0] = r2 + r1 - int(float(a2*r1)/255.0f+0.5f);\r
-               //      dest8[n+1] = g2 + g1 - int(float(a2*g1)/255.0f+0.5f);\r
-               //      dest8[n+2] = b2 + b1 - int(float(a2*b1)/255.0f+0.5f);\r
-               //      dest8[n+3] = a2 + a1 - int(float(a2*a1)/255.0f+0.5f);\r
-               //}\r
-               //else\r
-               //{\r
-               //      dest8[n+0] = r1;\r
-               //      dest8[n+1] = g1;\r
-               //      dest8[n+2] = b1;\r
-               //      dest8[n+3] = a1;\r
-               //}\r
-       }\r
-}\r
-\r
-void pre_overParallel_REF(void* dest, const void* source1, const void* source2, size_t size)\r
-{\r
-       pre_overParallel(&pre_over_REF, dest, source1, source2, size);  \r
-}\r
-\r
-}}}\r
-\r
-\r
diff --git a/common/image/over.h b/common/image/over.h
deleted file mode 100644 (file)
index 782d8fc..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
-#pragma once\r
-\r
-#include "../hardware/cpuid.h"\r
-\r
-namespace caspar{ namespace common{ namespace image{\r
-               \r
-void pre_over_SSE2(void* dest, const void* source1, const void* source2, size_t size);\r
-void pre_overParallel_SSE2(void* dest, const void* source1, const void* source2, size_t size);\r
-void pre_over_FastSSE2(void* dest, const void* source1, const void* source2, size_t size);\r
-void pre_over_REF(void* dest, const void* source1, const void* source2, size_t size);\r
-void pre_overParallel_REF(void* dest, const void* source1, const void* source2, size_t size);\r
-\r
-typedef void(*pre_over_fun)(void*, const void*, const void*, size_t);\r
-pre_over_fun get_pre_over_fun(SIMD simd = REF);\r
-\r
-}}}
\ No newline at end of file
diff --git a/common/image/pre_multiply.cpp b/common/image/pre_multiply.cpp
deleted file mode 100644 (file)
index 71276d2..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
\r
-#include "../stdafx.h"\r
-\r
-#include "pre_multiply.h"\r
-\r
-#include "../utility/types.h"\r
-\r
-#include "tbb/parallel_for.h"\r
-#include "tbb/blocked_range.h"\r
-\r
-#include <cassert>\r
-#include <intrin.h>\r
-#include <functional>\r
-\r
-using namespace std::tr1::placeholders;\r
-\r
-namespace caspar{ namespace common{ namespace image{\r
-\r
-static const size_t STRIDE = sizeof(__m128i)*4;\r
-\r
-void Dopre_multiplyParallel(const tbb::blocked_range<size_t>& r, const std::tr1::function<void(void*, const void*, size_t)>& func, void* dest, const void* source)\r
-{\r
-       size_t offset = r.begin()*STRIDE;\r
-       size_t size = r.size()*STRIDE;\r
-       func(reinterpret_cast<s8*>(dest) + offset, reinterpret_cast<const s8*>(source) + offset, size);\r
-}\r
-\r
-void pre_multiplyParallel(const std::tr1::function<void(void*, const void*, size_t)>& func, void* dest, const void* source, size_t size)\r
-{\r
-       tbb::parallel_for(tbb::blocked_range<size_t>(0, size/STRIDE), std::bind(&Dopre_multiplyParallel, std::placeholders::_1, func, dest, source));   \r
-}\r
-\r
-pre_multiply_fun get_pre_multiply_fun(SIMD simd)\r
-{\r
-       if(simd >= SSE2)\r
-               return pre_multiplyParallel_SSE2;\r
-       else\r
-               return pre_multiplyParallel_REF;\r
-}\r
-\r
-// this function performs precise calculations\r
-void pre_multiply_SSE2(void* dest, const void* source, size_t size)\r
-{\r
-       static const u32 PSD = 64;\r
-\r
-       static const __m128i lomask = _mm_set1_epi32(0x00FF00FF);\r
-       static const __m128i amask = _mm_set1_epi32(0xFF000000);\r
-       static const __m128i round = _mm_set1_epi16(128);       \r
-\r
-       assert(source != NULL && dest != NULL);\r
-       assert(size % STRIDE == 0);\r
-       \r
-       const __m128i* source128 = reinterpret_cast<const __m128i*>(source);\r
-       __m128i*           dest128 = reinterpret_cast<__m128i*>(dest);  \r
-\r
-       __m128i s, rb, ag, a, t;                \r
-       \r
-       for(size_t k = 0, length = size/STRIDE; k != length; ++k)       \r
-       {\r
-               // TODO: put prefetch between calculations?(R.N)\r
-               _mm_prefetch(reinterpret_cast<const s8*>(source128 + PSD), _MM_HINT_NTA);\r
-\r
-               // prefetch fetches entire cacheline (512bit). work on entire cacheline before next prefetch. 512/128 = 4, unroll four times = 16 pixels\r
-\r
-               // TODO: assembly optimization use PSHUFD on moves before calculations, lower latency than MOVDQA (R.N) http://software.intel.com/en-us/articles/fast-simd-integer-move-for-the-intel-pentiumr-4-processor/\r
-\r
-               for(int n = 0; n < 4; ++n, ++dest128, ++source128)\r
-               {\r
-                       s = _mm_load_si128(source128);          // AABBGGRR\r
-\r
-                       // set alpha to lo16 from source\r
-                       rb = _mm_srli_epi32(s, 24);                     // 000000AA\r
-                       a = _mm_slli_epi32(rb, 16);                     // 00AA0000\r
-                       a = _mm_or_si128(rb, a);                        // 00AA00AA\r
-\r
-                       rb = _mm_and_si128(lomask, s);          // 00BB00RR             \r
-                       rb = _mm_mullo_epi16(rb, a);            // BBBBRRRR     \r
-                       rb = _mm_add_epi16(rb, round);          // BBBBRRRR\r
-                       t = _mm_srli_epi16(rb, 8);                      // 00BB00RR     \r
-                       t = _mm_add_epi16(t, rb);\r
-                       rb = _mm_srli_epi16(t, 8);\r
-\r
-                       ag = _mm_srli_epi16(s, 8);                      // 00AA00GG             \r
-                       ag = _mm_mullo_epi16(ag, a);            // AAAAGGGG             \r
-                       ag = _mm_add_epi16(ag, round);\r
-                       t = _mm_srli_epi16(ag, 8);\r
-                       t = _mm_add_epi16(t, ag);\r
-                       ag = _mm_andnot_si128(lomask, t);       // AA00GG00             \r
-                                       \r
-                       a = _mm_or_si128(rb, ag);                       // XXBBGGRR\r
-                       a = _mm_andnot_si128(amask, a);         // 00BBGGRR\r
-\r
-                       s = _mm_and_si128(amask, s);            // AA000000\r
-\r
-                       s = _mm_or_si128(a, s);                         // AABBGGRR             pack\r
-\r
-                       // TODO: store entire cache line at the same time (write-combining => burst)? are there enough registers? 32 bit mode (special compile for 64bit?) (R.N)\r
-                       _mm_stream_si128(dest128, s);\r
-               }               \r
-       }\r
-       _mm_mfence();   //ensure last WC buffers get flushed to memory\r
-}\r
-\r
-void pre_multiplyParallel_SSE2(void* dest, const void* source1, size_t size)\r
-{\r
-       pre_multiplyParallel(&pre_multiply_SSE2, dest, source1, size);\r
-}\r
-\r
-void pre_multiply_REF(void* dest, const void* source, size_t size)\r
-{\r
-       assert(source != NULL && dest != NULL);\r
-       assert(size % 4 == 0);\r
-\r
-       const u8* source8 = reinterpret_cast<const u8*>(source);\r
-       u8* dest8 = reinterpret_cast<u8*>(dest);\r
-\r
-       for(size_t n = 0; n < size; n+=4)\r
-       {\r
-               u32 r = source8[n+0];\r
-               u32 g = source8[n+1];\r
-               u32 b = source8[n+2];\r
-               u32 a = source8[n+3];\r
-\r
-               dest8[n+0] = static_cast<u8>((r*a)/255);\r
-               dest8[n+1] = static_cast<u8>((g*a)/255);\r
-               dest8[n+2] = static_cast<u8>((b*a)/255);\r
-               dest8[n+3] = static_cast<u8>(a);\r
-       }\r
-}\r
-\r
-void pre_multiplyParallel_REF(void* dest, const void* source1,  size_t size)\r
-{\r
-       pre_multiplyParallel(&pre_multiply_REF, dest, source1, size);\r
-}\r
-\r
-}}}\r
diff --git a/common/image/pre_multiply.h b/common/image/pre_multiply.h
deleted file mode 100644 (file)
index 8fd04ae..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
-#pragma once\r
-\r
-#include "../hardware/cpuid.h"\r
-\r
-namespace caspar{ namespace common{ namespace image{\r
-       \r
-void pre_multiply_SSE2  (void* dest, const void* source, size_t size);\r
-void pre_multiplyParallel_SSE2  (void* dest, const void* source, size_t size);\r
-void pre_multiply_FastSSE2(void* dest, const void* source, size_t size);\r
-void pre_multiply_REF   (void* dest, const void* source, size_t size);\r
-void pre_multiplyParallel_REF   (void* dest, const void* source, size_t size);\r
-\r
-typedef void(*pre_multiply_fun)(void*, const void*, size_t);\r
-pre_multiply_fun get_pre_multiply_fun(SIMD simd = REF);\r
-\r
-}}}\r
-\r
-\r
diff --git a/common/image/shuffle.cpp b/common/image/shuffle.cpp
deleted file mode 100644 (file)
index eea9af3..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
\r
-#include "../stdafx.h"\r
-\r
-#include "shuffle.h"\r
-\r
-#include "../utility/types.h"\r
-\r
-#include "tbb/parallel_for.h"\r
-#include "tbb/blocked_range.h"\r
-\r
-#include <cassert>\r
-#include <intrin.h>\r
-#include <functional>\r
-\r
-using namespace std::tr1::placeholders;\r
-\r
-namespace caspar{ namespace common{ namespace image{\r
-\r
-static const size_t STRIDE = sizeof(__m128i)*4;\r
-\r
-void DoshuffleParallel(const tbb::blocked_range<size_t>& r, const std::tr1::function<void(void*, const void*, size_t, const u8, const u8, const u8, const u8)>& func, void* dest, const void* source, const u8 red, const u8 green, const u8 blue, const u8 alpha)\r
-{\r
-       size_t offset = r.begin()*STRIDE;\r
-       size_t size = r.size()*STRIDE;\r
-       func(reinterpret_cast<s8*>(dest) + offset, reinterpret_cast<const s8*>(source) + offset, size, red, green, blue, alpha);\r
-}\r
-\r
-void shuffleParallel(const std::tr1::function<void(void*, const void*, size_t, const u8, const u8, const u8, const u8)>& func, void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha)\r
-{\r
-       tbb::parallel_for(tbb::blocked_range<size_t>(0, size/STRIDE), std::bind(&DoshuffleParallel, std::placeholders::_1, func, dest, source, red, green, blue, alpha));       \r
-}\r
-\r
-shuffle_fun get_shuffle_fun(SIMD simd)\r
-{\r
-       if(simd >= SSSE3)\r
-               return shuffleParallel_SSSE3;\r
-       else if(simd >= SSE2)\r
-               return shuffleParallel_SSE2;\r
-       else\r
-               return shuffleParallel_REF;\r
-}\r
-\r
-void shuffle_SSSE3(void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha)\r
-{\r
-       static const unsigned int PSD = 64;     \r
-\r
-       assert(source != NULL && dest != NULL);\r
-       assert(red > -1 && red < 4 && green > -1 && green < 4 && blue > -1 && blue < 4 && alpha > -1 && alpha < 4 && "Invalid mask");\r
-       assert(size % STRIDE == 0);\r
-\r
-       const __m128i* source128 = reinterpret_cast<const __m128i*>(source);\r
-       __m128i*           dest128 = reinterpret_cast<__m128i*>(dest);  \r
-\r
-       __m128i reg0 = _mm_setzero_si128();     \r
-       __m128i reg1 = _mm_setzero_si128();     \r
-       __m128i reg2 = _mm_setzero_si128();     \r
-       __m128i reg3 = _mm_setzero_si128();     \r
-\r
-       const __m128i mask128 = _mm_set_epi8(alpha+12, blue+12, green+12, red+12, alpha+8, blue+8, green+8, red+8, alpha+4, blue+4, green+4, red+4, alpha, blue, green, red);\r
-\r
-       for(size_t k = 0, length = size/STRIDE; k < length; ++k)        \r
-       {\r
-               // TODO: put prefetch between calculations?(R.N)\r
-               _mm_prefetch(reinterpret_cast<const s8*>(source128 + PSD), _MM_HINT_NTA);\r
-\r
-               // work on entire cacheline before next prefetch\r
-\r
-               // TODO: assembly optimization use PSHUFD on moves before calculations, lower latency than MOVDQA (R.N) http://software.intel.com/en-us/articles/fast-simd-integer-move-for-the-intel-pentiumr-4-processor/\r
-\r
-               reg0 = _mm_load_si128(source128++);     \r
-               reg1 = _mm_load_si128(source128++);     \r
-\r
-               _mm_stream_si128(dest128++, _mm_shuffle_epi8(reg0, mask128));\r
-\r
-               reg2 = _mm_load_si128(source128++);     \r
-\r
-               _mm_stream_si128(dest128++, _mm_shuffle_epi8(reg1, mask128));\r
-\r
-               reg3 = _mm_load_si128(source128++);     \r
-               \r
-               _mm_stream_si128(dest128++, _mm_shuffle_epi8(reg2, mask128));   \r
-               _mm_stream_si128(dest128++, _mm_shuffle_epi8(reg3, mask128));           \r
-       }\r
-       _mm_mfence();   //ensure last WC buffers get flushed to memory\r
-}\r
-\r
-void shuffleParallel_SSSE3(void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha)\r
-{\r
-       shuffleParallel(&shuffle_SSSE3, dest, source, size, red, green, blue, alpha);\r
-}\r
-\r
-// TODO: should be optimized for different combinations (R.N)\r
-void shuffle_SSE2(void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha)\r
-{\r
-       static const size_t stride = sizeof(__m128i)*4;\r
-       static const u32 PSD = 64;\r
-\r
-       static const __m128i himask     = _mm_set1_epi32(0xFF000000);   \r
-       static const __m128i lomask     = _mm_set1_epi32(0x000000FF);\r
-       \r
-       assert(source != NULL && dest != NULL);\r
-       assert(red > -1 && red < 4 && green > -1 && green < 4 && blue > -1 && blue < 4 && alpha > -1 && alpha < 4);\r
-       assert(size % stride == 0);\r
-\r
-       const __m128i* source128 = reinterpret_cast<const __m128i*>(source);\r
-       __m128i*           dest128 = reinterpret_cast<__m128i*>(dest);  \r
-\r
-       __m128i s, m0, m1, r;\r
-\r
-       const int shft0 = (red)*8;\r
-       const int shft1 = (green)*8;\r
-       const int shft2 = (3-blue)*8;\r
-       const int shft3 = (3-alpha)*8;\r
-\r
-       for(int k = 0, length = size/stride; k < length; ++k)   \r
-       {\r
-               // TODO: dynamic prefetch schedluing distance? needs to be optimized (R.N)              \r
-               // TODO: put prefetch between calculations?(R.N)\r
-               _mm_prefetch(reinterpret_cast<const s8*>(source128 + PSD), _MM_HINT_NTA);\r
-\r
-               // work on entire cacheline before next prefetch\r
-\r
-               // TODO: assembly optimization use PSHUFD on moves before calculations, lower latency than MOVDQA (R.N) http://software.intel.com/en-us/articles/fast-simd-integer-move-for-the-intel-pentiumr-4-processor/\r
-\r
-               for(int n = 0; n < 4; ++n, ++dest128, ++source128)\r
-               {\r
-                       s = _mm_load_si128(source128);\r
-                       \r
-                       m0 = _mm_srli_epi32(s, shft0);\r
-                       m0 = _mm_and_si128(m0, lomask);\r
-\r
-                       m1 = _mm_srli_epi32(s, shft1);\r
-                       m1 = _mm_and_si128(m1, lomask);\r
-                       m1 = _mm_slli_epi32(m1, 8);\r
-                       \r
-                       r = _mm_or_si128(m0, m1);\r
-\r
-                       m0 = _mm_slli_epi32(s, shft2);\r
-                       m0 = _mm_and_si128(m0, himask);\r
-                       m0 = _mm_srli_epi32(m0, 8);                     \r
-\r
-                       m1 = _mm_slli_epi32(s, shft3);\r
-                       m1 = _mm_and_si128(m1, himask);\r
-                       \r
-                       m0 = _mm_or_si128(m0, m1);\r
-\r
-                       r = _mm_or_si128(r, m0);\r
-\r
-                       _mm_stream_si128(dest128, r);\r
-               }\r
-       }\r
-       _mm_mfence();   //ensure last WC buffers get flushed to memory\r
-}\r
-\r
-void shuffleParallel_SSE2(void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha)\r
-{\r
-       shuffleParallel(&shuffle_SSE2, dest, source, size, red, green, blue, alpha);\r
-}\r
-\r
-void shuffle_REF(void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha)\r
-{\r
-       assert(source != NULL && dest != NULL);\r
-       assert(red > -1 && red < 4 && green > -1 && green < 4 && blue > -1 && blue < 4 && alpha > -1 && alpha < 4);\r
-       assert(size % 4 == 0);\r
-\r
-       const u8* source8 = reinterpret_cast<const u8*>(source);\r
-       u8*               dest8 = reinterpret_cast<u8*>(dest);  \r
-\r
-       for(size_t n = 0; n < size; n+=4)\r
-       {\r
-               u8 r = source8[n+red];\r
-               u8 g = source8[n+green];\r
-               u8 b = source8[n+blue];\r
-               u8 a = source8[n+alpha];\r
-\r
-               dest8[n+0] = r;\r
-               dest8[n+1] = g;\r
-               dest8[n+2] = b;\r
-               dest8[n+3] = a;\r
-       }\r
-}\r
-\r
-void shuffleParallel_REF(void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha)\r
-{\r
-       shuffleParallel(&shuffle_REF, dest, source, size, red, green, blue, alpha);\r
-}\r
-\r
-}}}\r
diff --git a/common/image/shuffle.h b/common/image/shuffle.h
deleted file mode 100644 (file)
index 45e4650..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
-#pragma once\r
-\r
-#include "../hardware/cpuid.h"\r
-#include "../utility/types.h"\r
-\r
-namespace caspar{ namespace common{ namespace image{\r
-\r
-void shuffle_SSSE3(void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha);\r
-void shuffle_SSE2 (void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha);\r
-void shuffle_REF  (void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha);\r
-void shuffleParallel_SSSE3(void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha);\r
-void shuffleParallel_SSE2 (void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha);\r
-void shuffleParallel_REF  (void* dest, const void* source, size_t size, const u8 red, const u8 green, const u8 blue, const u8 alpha);\r
-\r
-typedef void(*shuffle_fun)(void*, const void*, size_t, const u8, const u8, const u8, const u8);\r
-shuffle_fun get_shuffle_fun(SIMD simd = REF);\r
-\r
-}}}
\ No newline at end of file
index 8a97e18b46245761886a71c084090a82b1189b93..ebd79ce2fb688730354856318de22e70eb859be4 100644 (file)
@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>\r
 <configuration>\r
   <paths>\r
-    <media-path>C:\\casparcg\\Repository\\media\\</media-path>\r
-    <log-path>C:\\casparcg\\Repository\\log\\</log-path>\r
-    <template-path>C:\\casparcg\\Repository\\templates\\</template-path>\r
-    <data-path>C:\\casparcg\\Repository\\data\\</data-path>\r
+    <media-path>C:\\Casparcg\\_media\\</media-path>\r
+    <log-path>C:\\Casparcg\\_log\\</log-path>\r
+    <template-path>C:\\Casparcg\\_templates\\</template-path>\r
+    <data-path>C:\\Casparcg\\_data\\</data-path>\r
   </paths>\r
        <channels>\r
     <channel>\r
index 64d1694722fd67e5c20308505826289b0a5e676c..a9705eaaafb563d89d4fcf3468464d4ed45719f9 100644 (file)
@@ -20,4 +20,4 @@
 \r
 #define TBB_USE_THREADING_TOOLS 1\r
 \r
-//#define DISABLE_BLUEFISH\r
+#define DISABLE_BLUEFISH\r
index bedaaa8040ad4138222a1def9ce458e382646031..1c02aea1e5e740e9d3471d9054d9faba9f044e7d 100644 (file)
@@ -436,7 +436,7 @@ void BlueFishVideoConsumer::DisableVideoOutput()
        }\r
 }\r
 \r
-void BlueFishVideoConsumer::display(const frame_ptr& frame)\r
+void BlueFishVideoConsumer::display(const gpu_frame_ptr& frame)\r
 {\r
        if(frame == nullptr)\r
                return;\r
@@ -453,7 +453,7 @@ void BlueFishVideoConsumer::Run()
        {\r
                try\r
                {\r
-                       frame_ptr frame;\r
+                       gpu_frame_ptr frame;\r
                        frameBuffer_.pop(frame);\r
                        if(frame == nullptr)\r
                                return;\r
index e62e0aad409fdf16f559abb922a3e1a037c45a8e..88d53f48c47dae75f644214665bd25827c001d6e 100644 (file)
@@ -51,7 +51,7 @@ public:
        static int EnumerateDevices();\r
        static frame_consumer_ptr Create(const frame_format_desc& format_desc, unsigned int deviceIndex);\r
        \r
-       void display(const frame_ptr&);\r
+       void display(const gpu_frame_ptr&);\r
                \r
        const frame_format_desc& get_frame_format_desc() const { return format_desc_; }\r
 \r
@@ -83,7 +83,7 @@ private:
        \r
        std::exception_ptr pException_;\r
        boost::thread thread_;\r
-       tbb::concurrent_bounded_queue<frame_ptr> frameBuffer_;\r
+       tbb::concurrent_bounded_queue<gpu_frame_ptr> frameBuffer_;\r
 };\r
 typedef std::tr1::shared_ptr<BlueFishVideoConsumer> BlueFishFrameConsumerPtr;\r
 \r
diff --git a/core/consumer/bluefish/BluefishFrameManager.h b/core/consumer/bluefish/BluefishFrameManager.h
deleted file mode 100644 (file)
index e52d146..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
\r
-#ifndef _CASPAR_BLUEFISHVIDEOFRAMEFACTORY_H__\r
-#define _CASPAR_BLUEFISHVIDEOFRAMEFACTORY_H__\r
-\r
-#pragma once\r
-\r
-#include "..\..\frame\system_frame.h"\r
-#include "..\..\frame\frame_format.h"\r
-#include <list>\r
-#include <memory>\r
-#include "BluefishException.h"\r
-\r
-#include <tbb\mutex.h>\r
-\r
-class CBlueVelvet4;\r
-\r
-namespace caspar {\r
-namespace bluefish {\r
-\r
-typedef std::tr1::shared_ptr<CBlueVelvet4> BlueVelvetPtr;\r
-\r
-class VideoFrameInfo\r
-{\r
-public:\r
-       VideoFrameInfo() {}\r
-       virtual ~VideoFrameInfo() {}\r
-\r
-       virtual unsigned char* GetPtr() const = 0;\r
-       virtual int GetBufferID() const = 0;\r
-       virtual int size() const = 0;\r
-};\r
-typedef std::tr1::shared_ptr<VideoFrameInfo> VideoFrameInfoPtr;\r
-\r
-class CardFrameInfo : public VideoFrameInfo\r
-{\r
-public:\r
-       CardFrameInfo(BlueVelvetPtr pSDK, int dataSize, int bufferID);\r
-       ~CardFrameInfo();\r
-\r
-       unsigned char* GetPtr() const {\r
-               return pData_;\r
-       }\r
-       int GetBufferID() const {\r
-               return bufferID_;\r
-       }\r
-       int size() const {\r
-               return dataSize_;\r
-       }\r
-\r
-private:\r
-       BlueVelvetPtr pSDK_;\r
-       unsigned char* pData_;\r
-       int bufferID_;\r
-       int dataSize_;\r
-};\r
-\r
-class SystemFrameInfo : public VideoFrameInfo\r
-{\r
-public:\r
-       SystemFrameInfo(int dataSize, int bufferID);\r
-       ~SystemFrameInfo();\r
-\r
-       unsigned char* GetPtr() const {\r
-               return pData_;\r
-       }\r
-       int GetBufferID() const {\r
-               return bufferID_;\r
-       }\r
-       int size() const {\r
-               return dataSize_;\r
-       }\r
-\r
-private:\r
-       unsigned char* pData_;\r
-       int bufferID_;\r
-       int dataSize_;\r
-};\r
-\r
-class BluefishFrameManager\r
-{\r
-       friend class BluefishVideoFrame;\r
-       typedef std::list<VideoFrameInfoPtr> FrameInfoList;\r
-\r
-       BluefishFrameManager(const BluefishFrameManager&);\r
-       const BluefishFrameManager& operator=(const BluefishFrameManager&);\r
-\r
-public:\r
-       BluefishFrameManager(BlueVelvetPtr pSDK, frame_format fmt, unsigned long optimalLength);\r
-       virtual ~BluefishFrameManager();\r
-\r
-       virtual std::shared_ptr<BluefishVideoFrame> CreateFrame();\r
-       virtual const frame_format_desc& get_frame_format_desc() const;\r
-\r
-private:\r
-       VideoFrameInfoPtr GetBuffer();\r
-       void ReturnBuffer(VideoFrameInfoPtr);\r
-\r
-       BlueVelvetPtr pSDK_;\r
-       frame_format format_;\r
-       FrameInfoList frameBuffers_;\r
-       tbb::mutex mutex_;\r
-};\r
-typedef std::tr1::shared_ptr<BluefishFrameManager> BluefishFrameManagerPtr;\r
-\r
-\r
-class BluefishVideoFrame : public frame\r
-{\r
-public:\r
-       explicit BluefishVideoFrame(BluefishFrameManager* pFrameManager);\r
-\r
-       virtual ~BluefishVideoFrame();\r
-\r
-       unsigned char* data() { return data_;   }\r
-\r
-       unsigned int size() const { return size_; }\r
-       \r
-       long meta_data() const { return buffer_id_; }\r
-\r
-       void* tag() const\r
-       {\r
-               return pFrameManager_;\r
-       }\r
-private:\r
-       unsigned char* data_;\r
-       long buffer_id_;\r
-       size_t size_;\r
-       VideoFrameInfoPtr pInfo_;\r
-       BluefishFrameManager* pFrameManager_;\r
-};\r
-\r
-\r
-}      //namespace bluefish\r
-}      //namespace caspar\r
-\r
-#endif //_CASPAR_BLUEFISHVIDEOFRAMEFACTORY_H__
\ No newline at end of file
index 9969662274ddb21e6c4432743e1610f8ebb6200c..013b0ce93a09616403399805b295ed87fe8e5aa4 100644 (file)
@@ -60,7 +60,7 @@ struct BluefishPlaybackStrategy::Implementation
                return frame;\r
        }\r
 \r
-       void DisplayFrame(const frame_ptr& frame)\r
+       void DisplayFrame(const gpu_frame_ptr& frame)\r
        {\r
                if(frame != nullptr) {\r
                        if(pConsumer_->pFrameManager_.get() == reinterpret_cast<BluefishFrameManager*>(frame->tag())) {\r
@@ -122,11 +122,11 @@ BluefishPlaybackStrategy::~BluefishPlaybackStrategy()
 //     return pImpl_->pConsumer_;\r
 //}\r
 //\r
-//frame_ptr BluefishPlaybackStrategy::GetReservedFrame() {\r
+//gpu_frame_ptr BluefishPlaybackStrategy::GetReservedFrame() {\r
 //     return pImpl_->GetReservedFrame();\r
 //}\r
 \r
-void BluefishPlaybackStrategy::display(const frame_ptr& frame) \r
+void BluefishPlaybackStrategy::display(const gpu_frame_ptr& frame) \r
 {\r
        return pImpl_->DisplayFrame(frame);\r
 }\r
index 271e0c1ad4bde4f841ab2e28d3662a924f242919..781a115676ccc996a50fcfa0ff0bb41998dda172 100644 (file)
@@ -20,7 +20,7 @@
  \r
 #pragma once\r
 \r
-#include "../../frame/frame.h"\r
+#include "../../frame/gpu_frame.h"\r
 #include "../../consumer/frame_consumer.h"\r
 \r
 namespace caspar {\r
@@ -37,7 +37,7 @@ public:
        explicit BluefishPlaybackStrategy(BlueFishVideoConsumer* pConsumer);\r
        virtual ~BluefishPlaybackStrategy();\r
 \r
-       void display(const frame_ptr&);\r
+       void display(const gpu_frame_ptr&);\r
 };\r
 \r
 }      //namespace bluefish\r
index f13a40f0625b1ed138659f189ea9f7b1871165ba..dea018a1baab4e6e84c9e5118b7c3f75914b31e4 100644 (file)
@@ -28,7 +28,6 @@
 #include "DecklinkVideoConsumer.h"\r
 #include "DeckLinkAPI_h.h"\r
 \r
-#include "../../frame/system_frame.h"\r
 #include "../../frame/frame_format.h"\r
 #include "../../../common/image/image.h"\r
 \r
@@ -52,7 +51,7 @@ namespace caspar{ namespace decklink{
 struct DecklinkVideoConsumer::Implementation : public IDeckLinkVideoOutputCallback\r
 {\r
        struct DecklinkFrameManager;\r
-       struct DecklinkVideoFrame : public frame\r
+       struct DecklinkVideoFrame\r
        {\r
                explicit DecklinkVideoFrame(DecklinkFrameManager* pFactory)\r
                {\r
@@ -73,6 +72,9 @@ struct DecklinkVideoConsumer::Implementation : public IDeckLinkVideoOutputCallba
                {\r
                        return pBytes_;\r
                }\r
+               \r
+               size_t width() const { return 0; }\r
+               size_t height() const { return 0; }\r
 \r
                bool valid() const \r
                {\r
@@ -120,25 +122,18 @@ struct DecklinkVideoConsumer::Implementation : public IDeckLinkVideoOutputCallba
                        return pResult;\r
                }\r
 \r
-               void DisplayFrame(const frame_ptr& frame)\r
+               void DisplayFrame(const gpu_frame_ptr& frame)\r
                {\r
                        if(frame != NULL) \r
                        {\r
-                               if(pConsumerImpl_->pFrameManager_.get() == reinterpret_cast<DecklinkFrameManager*>(frame->tag()))\r
-                               {\r
-                                       DoRender(std::static_pointer_cast<DecklinkVideoFrame>(frame));\r
-                               }\r
-                               else \r
+                               std::shared_ptr<DecklinkVideoFrame> pTempFrame = GetReservedFrame();\r
+                               if(pTempFrame && frame->size() == pTempFrame->size())\r
                                {\r
-                                       std::shared_ptr<DecklinkVideoFrame> pTempFrame = GetReservedFrame();\r
-                                       if(pTempFrame && frame->size() == pTempFrame->size())\r
-                                       {\r
-                                               common::image::copy(pTempFrame->data(), frame->data(), pTempFrame->size());\r
-                                               DoRender(pTempFrame);\r
-                                       }\r
-                                       else\r
-                                               CASPAR_LOG(error) << "DECKLINK: Failed to get reserved frame";\r
+                                       common::image::copy(pTempFrame->data(), frame->data(), pTempFrame->size());\r
+                                       DoRender(pTempFrame);\r
                                }\r
+                               else\r
+                                       CASPAR_LOG(error) << "DECKLINK: Failed to get reserved frame";                          \r
                        }\r
                        else \r
                        {\r
@@ -177,11 +172,7 @@ struct DecklinkVideoConsumer::Implementation : public IDeckLinkVideoOutputCallba
                explicit DecklinkFrameManager(Implementation* pConsumerImpl) : pConsumerImpl_(pConsumerImpl)\r
                {\r
                }\r
-\r
-               frame_ptr CreateFrame() {\r
-                       return std::make_shared<system_frame>(pConsumerImpl_->get_frame_format_desc().size);\r
-               }\r
-\r
+               \r
                std::shared_ptr<DecklinkVideoFrame>  CreateReservedFrame() {\r
                        return std::make_shared<DecklinkVideoFrame>(this);\r
                }\r
@@ -207,7 +198,7 @@ struct DecklinkVideoConsumer::Implementation : public IDeckLinkVideoOutputCallba
 \r
        std::exception_ptr pException_;\r
        boost::thread thread_;\r
-       tbb::concurrent_bounded_queue<frame_ptr> frameBuffer_;\r
+       tbb::concurrent_bounded_queue<gpu_frame_ptr> frameBuffer_;\r
 \r
 //     IDeckLinkMutableVideoFrame* pNextFrame_;\r
 \r
@@ -251,7 +242,7 @@ struct DecklinkVideoConsumer::Implementation : public IDeckLinkVideoOutputCallba
                ReleaseDevice();\r
        }\r
        \r
-       void DisplayFrame(const frame_ptr& frame)\r
+       void DisplayFrame(const gpu_frame_ptr& frame)\r
        {\r
                if(frame == nullptr)\r
                        return;         \r
@@ -270,7 +261,7 @@ struct DecklinkVideoConsumer::Implementation : public IDeckLinkVideoOutputCallba
                {\r
                        try\r
                        {       \r
-                               frame_ptr frame;\r
+                               gpu_frame_ptr frame;\r
                                frameBuffer_.pop(frame);\r
                                if(frame == nullptr)\r
                                        return;\r
@@ -453,7 +444,7 @@ struct DecklinkVideoConsumer::Implementation : public IDeckLinkVideoOutputCallba
 DecklinkVideoConsumer::DecklinkVideoConsumer(const caspar::frame_format_desc& format_desc, bool internalKey) : pImpl_(new Implementation(format_desc, internalKey))\r
 {}\r
 \r
-void DecklinkVideoConsumer::display(const frame_ptr& frame)\r
+void DecklinkVideoConsumer::display(const gpu_frame_ptr& frame)\r
 {\r
        pImpl_->DisplayFrame(frame);\r
 }\r
index ecdd83fc3c8e4632d8d4e71ff3be765ce8c62480..f1d9beeef75eee3fe4972f1865c1be448a8c34f8 100644 (file)
@@ -30,7 +30,7 @@ class DecklinkVideoConsumer : public frame_consumer
 public:\r
        explicit DecklinkVideoConsumer(const caspar::frame_format_desc& format_desc, bool internalKey = false);\r
        \r
-       void display(const frame_ptr&);\r
+       void display(const gpu_frame_ptr&);\r
        const frame_format_desc& get_frame_format_desc() const;\r
 private:\r
        struct Implementation;\r
index daeeae74958e4148328021b0db84ec2f38a3c3b8..27dae150f199209c070bfd33d78b2287afa13854 100644 (file)
@@ -33,8 +33,8 @@ public:
        virtual ~frame_consumer() {}\r
 \r
        virtual const frame_format_desc& get_frame_format_desc() const = 0;\r
-       virtual void prepare(const frame_ptr&){};\r
-       virtual void display(const frame_ptr&){};\r
+       virtual void prepare(const gpu_frame_ptr&){};\r
+       virtual void display(const gpu_frame_ptr&){};\r
 };\r
 typedef std::shared_ptr<frame_consumer> frame_consumer_ptr;\r
 typedef std::shared_ptr<const frame_consumer> frame_consumer_const_ptr;\r
index a746fc495602fb6e4bc05c2d66f035197545fc43..9e1322a5be645757f2f016a439af8e358df10633 100644 (file)
@@ -22,8 +22,7 @@
 \r
 #include "oal_frame_consumer.h"\r
 \r
-#include "../../frame/audio_chunk.h"\r
-#include "../../frame/frame.h"\r
+#include "../../frame/gpu_frame.h"\r
 #include "../../frame/frame_format.h"\r
 \r
 #include <SFML/Audio.hpp>\r
@@ -38,9 +37,10 @@ namespace caspar{ namespace audio{
 class sound_channel : public sf::SoundStream\r
 {\r
 public:\r
-       sound_channel() : internal_chunks_(5)\r
+       sound_channel() : internal_chunks_(5), silence_(1920*2, 0)\r
        {\r
                external_chunks_.set_capacity(3);\r
+               sf::SoundStream::Initialize(2, 48000);\r
        }\r
 \r
        ~sound_channel()\r
@@ -49,20 +49,17 @@ public:
                external_chunks_.push(nullptr);\r
                Stop();\r
        }\r
-\r
-       void Initialize(const sound_channel_info_ptr& info)\r
+       \r
+       void push(const gpu_frame_ptr& frame)\r
        {\r
-               sf::SoundStream::Initialize(info->channels_count, info->sample_rate);\r
-               assert(info->bits_per_sample/(8*sizeof(char)) == sizeof(sf::Int16));\r
-       }\r
+               if(frame->audio_data().empty())\r
+                       frame->audio_data() = silence_;\r
 \r
-       void Push(const audio_chunk_ptr& paudio_chunk)\r
-       {\r
-               if(!external_chunks_.try_push(paudio_chunk))\r
-               {\r
+               //if(!external_chunks_.try_push(frame))\r
+               //{\r
                        //CASPAR_LOG(debug) << "Sound Buffer Overrun";\r
-                       external_chunks_.push(paudio_chunk);\r
-               }\r
+                       external_chunks_.push(frame);\r
+               //}\r
 \r
                if(GetStatus() != Playing && external_chunks_.size() >= 3)\r
                        Play();\r
@@ -78,28 +75,29 @@ private:
 \r
        bool OnGetData(sf::SoundStream::Chunk& data)\r
     {\r
-               audio_chunk_ptr pChunk;\r
-               if(!external_chunks_.try_pop(pChunk))\r
-               {\r
-                       CASPAR_LOG(trace) << "Sound Buffer Underrun";\r
-                       external_chunks_.pop(pChunk);\r
-               }\r
+               gpu_frame_ptr frame;\r
+               //if(!external_chunks_.try_pop(frame))\r
+               //{\r
+                       //CASPAR_LOG(trace) << "Sound Buffer Underrun";\r
+                       external_chunks_.pop(frame);\r
+               //}\r
 \r
-               if(pChunk == nullptr)\r
+               if(frame == nullptr)\r
                {\r
                        external_chunks_.clear();\r
                        return false;\r
                }\r
 \r
-               internal_chunks_.push_back(pChunk);\r
-               SetVolume(pChunk->volume());\r
-               data.Samples = reinterpret_cast<sf::Int16*>(pChunk->data());\r
-               data.NbSamples = pChunk->size()/sizeof(sf::Int16);\r
+               internal_chunks_.push_back(frame);\r
+               //SetVolume(pChunk->volume());\r
+               data.Samples = reinterpret_cast<sf::Int16*>(frame->audio_data().data());\r
+               data.NbSamples = frame->audio_data().size();\r
         return true;\r
     }\r
 \r
-       boost::circular_buffer<audio_chunk_ptr> internal_chunks_;\r
-       tbb::concurrent_bounded_queue<audio_chunk_ptr> external_chunks_;\r
+       std::vector<short> silence_;\r
+       boost::circular_buffer<gpu_frame_ptr> internal_chunks_;\r
+       tbb::concurrent_bounded_queue<gpu_frame_ptr> external_chunks_;\r
 };\r
 typedef std::shared_ptr<sound_channel> sound_channelPtr;\r
 \r
@@ -107,53 +105,19 @@ struct oal_frame_consumer::implementation : boost::noncopyable
 {      \r
        implementation(const frame_format_desc& format_desc) : format_desc_(format_desc)\r
        {\r
-               for(int n = 0; n < 3; ++n)\r
-                       channel_pool_.push(std::make_shared<sound_channel>());\r
        }\r
        \r
-       void push(const frame_ptr& frame)\r
+       void push(const gpu_frame_ptr& frame)\r
        {\r
-               if(frame == nullptr)\r
-                       return;\r
-\r
-               decltype(channels_) active_channels;\r
-               BOOST_FOREACH(const audio_chunk_ptr& pChunk, frame->audio_data())\r
-               {\r
-                       auto info = pChunk->sound_channel_info();\r
-                       auto it = channels_.find(info);\r
-                       sound_channelPtr channel;\r
-                       if(it == channels_.end())\r
-                       {\r
-                               if(channel_pool_.size() <= 1)\r
-                                       channel_pool_.push(std::make_shared<sound_channel>());\r
-                               \r
-                               sound_channelPtr pNewChannel;\r
-                               channel_pool_.pop(pNewChannel);\r
-\r
-                               channel = sound_channelPtr(pNewChannel.get(), [=](sound_channel*)\r
-                               {\r
-                                       channel_pool_.push(pNewChannel);\r
-                                       pNewChannel->Push(nullptr);\r
-                               });\r
-                               channel->Initialize(info);\r
-                       }\r
-                       else\r
-                               channel = it->second;\r
-\r
-                       active_channels.insert(std::make_pair(info, channel));\r
-                       channel->Push(pChunk); // Could Block\r
-               }\r
-\r
-               channels_ = std::move(active_channels);\r
+               channel_.push(frame);\r
        }\r
                \r
-       tbb::concurrent_bounded_queue<sound_channelPtr> channel_pool_;\r
-       std::map<sound_channel_info_ptr, sound_channelPtr> channels_;\r
+       sound_channel channel_;\r
 \r
        caspar::frame_format_desc format_desc_;\r
 };\r
 \r
 oal_frame_consumer::oal_frame_consumer(const caspar::frame_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
 const caspar::frame_format_desc& oal_frame_consumer::get_frame_format_desc() const{return impl_->format_desc_;}\r
-void oal_frame_consumer::prepare(const frame_ptr& frame){impl_->push(frame);}\r
+void oal_frame_consumer::prepare(const gpu_frame_ptr& frame){impl_->push(frame);}\r
 }}\r
index 4a2e3687df048891214f5615fb54fd9add7afd82..083ee3453d94c8ae1926be64ea2e8c4971835df4 100644 (file)
@@ -29,7 +29,7 @@ public:
        explicit oal_frame_consumer(const frame_format_desc& format_desc);\r
        \r
        const frame_format_desc& get_frame_format_desc() const; \r
-       void prepare(const frame_ptr& frame);\r
+       void prepare(const gpu_frame_ptr& frame);\r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index 126f19d211155a79c9f95ddb7487f84981b8df02..4fc0fc2c12d0a94424349c4f382a52cf19fed9ba 100644 (file)
@@ -26,8 +26,8 @@
 \r
 #include "ogl_frame_consumer.h"\r
 \r
-#include "../../frame/system_frame.h"\r
 #include "../../frame/frame_format.h"\r
+#include "../../frame/gpu_frame.h"\r
 #include "../../../common/image/image.h"\r
 \r
 #include <boost/thread.hpp>\r
@@ -203,7 +203,7 @@ struct ogl_frame_consumer::implementation : boost::noncopyable
                return std::make_pair(width, height);\r
        }\r
 \r
-       void render(const frame_ptr& frame)\r
+       void render(const gpu_frame_ptr& frame)\r
        {                                       \r
                // Render\r
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\r
@@ -234,7 +234,7 @@ struct ogl_frame_consumer::implementation : boost::noncopyable
                pbo_index_ = nextPboIndex;\r
        }\r
                        \r
-       void display(const frame_ptr& frame)\r
+       void display(const gpu_frame_ptr& frame)\r
        {\r
                if(frame == nullptr)\r
                        return;         \r
@@ -252,7 +252,7 @@ struct ogl_frame_consumer::implementation : boost::noncopyable
                auto period = boost::posix_time::microseconds(static_cast<long>(get_frame_format_period(format_desc_)*1000000.0));\r
                auto time = boost::posix_time::microsec_clock::local_time();\r
                \r
-               frame_ptr frame;\r
+               gpu_frame_ptr frame;\r
                do\r
                {\r
                        try\r
@@ -299,11 +299,11 @@ struct ogl_frame_consumer::implementation : boost::noncopyable
 \r
        std::exception_ptr exception_;\r
        boost::thread thread_;\r
-       tbb::concurrent_bounded_queue<frame_ptr> frame_buffer_;\r
+       tbb::concurrent_bounded_queue<gpu_frame_ptr> frame_buffer_;\r
 };\r
 \r
 ogl_frame_consumer::ogl_frame_consumer(const caspar::frame_format_desc& format_desc, unsigned int screen_index, stretch stretch, bool windowed)\r
 : impl_(new implementation(format_desc, screen_index, stretch, windowed)){}\r
 const caspar::frame_format_desc& ogl_frame_consumer::get_frame_format_desc() const{return impl_->format_desc_;}\r
-void ogl_frame_consumer::display(const frame_ptr& frame){impl_->display(frame);}\r
+void ogl_frame_consumer::display(const gpu_frame_ptr& frame){impl_->display(frame);}\r
 }}\r
index 44fe7eab1cc23793bcd599a800ab4b71722ca3df..eacaa6556d8b485e1b14c615696240213a295409 100644 (file)
@@ -39,7 +39,7 @@ public:
        explicit ogl_frame_consumer(const frame_format_desc& format_desc, unsigned int screen_index = 0, stretch stretch = stretch::fill, bool windowed = false);\r
        \r
        const frame_format_desc& get_frame_format_desc() const; \r
-       void display(const frame_ptr& frame);\r
+       void display(const gpu_frame_ptr& frame);\r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index 857344bf175a5d5ce0b6c6f2c5b636e2502772cc..bb369d01140c71f6c9649f56040e4a2957e7d7f5 100644 (file)
@@ -61,7 +61,7 @@
     <ClCompile>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <MinimalRebuild>true</MinimalRebuild>\r
+      <MinimalRebuild>false</MinimalRebuild>\r
       <ExceptionHandling>Async</ExceptionHandling>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <SmallerTypeCheck>true</SmallerTypeCheck>\r
@@ -74,6 +74,7 @@
       <DebugInformationFormat>EditAndContinue</DebugInformationFormat>\r
       <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;TBB_USE_THREADING_TOOLS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <TreatWarningAsError>true</TreatWarningAsError>\r
+      <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
     </ClCompile>\r
     <Link>\r
       <AdditionalDependencies>sfml-audio-d.lib;sfml-window-d.lib;OpenGL32.lib;FreeImage.lib;GLee.lib;Winmm.lib;Ws2_32.lib;BlueVelvet3_d.lib;avformat-52.lib;avcodec-52.lib;avutil-50.lib;swscale-0.lib;%(AdditionalDependencies)</AdditionalDependencies>\r
@@ -93,8 +94,8 @@
       <TargetMachine>MachineX86</TargetMachine>\r
     </Link>\r
     <PostBuildEvent>\r
-      <Command>copy "$(TargetPath)" "$(SolutionDir)build\"\r
-copy "$(ProjectDir)caspar.config" "$(SolutionDir)build\"</Command>\r
+      <Command>\r
+      </Command>\r
     </PostBuildEvent>\r
   </ItemDefinitionGroup>\r
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">\r
@@ -143,14 +144,13 @@ copy "$(ProjectDir)caspar.config" "$(SolutionDir)build\"</Command>
       <TargetMachine>MachineX86</TargetMachine>\r
     </Link>\r
     <PostBuildEvent>\r
-      <Command>copy "$(TargetPath)" "$(SolutionDir)build\"\r
-copy "$(ProjectDir)caspar.config" "$(SolutionDir)build\"</Command>\r
+      <Command>\r
+      </Command>\r
     </PostBuildEvent>\r
   </ItemDefinitionGroup>\r
   <ItemGroup>\r
     <ClInclude Include="config.h" />\r
     <ClInclude Include="consumer\bluefish\BluefishException.h" />\r
-    <ClInclude Include="consumer\bluefish\BluefishFrameManager.h" />\r
     <ClInclude Include="consumer\bluefish\BluefishPlaybackStrategy.h" />\r
     <ClInclude Include="consumer\bluefish\BlueFishVideoConsumer.h" />\r
     <ClInclude Include="consumer\decklink\DeckLinkAPI_h.h" />\r
@@ -158,10 +158,12 @@ copy "$(ProjectDir)caspar.config" "$(SolutionDir)build\"</Command>
     <ClInclude Include="consumer\frame_consumer.h" />\r
     <ClInclude Include="consumer\oal\oal_frame_consumer.h" />\r
     <ClInclude Include="consumer\ogl\ogl_frame_consumer.h" />\r
-    <ClInclude Include="frame\frame.h" />\r
+    <ClInclude Include="frame\composite_gpu_frame.h" />\r
+    <ClInclude Include="frame\frame_factory.h" />\r
     <ClInclude Include="frame\frame_format.h" />\r
-    <ClInclude Include="frame\audio_chunk.h" />\r
     <ClInclude Include="frame\frame_fwd.h" />\r
+    <ClInclude Include="frame\gpu_frame.h" />\r
+    <ClInclude Include="frame\gpu_frame_processor.h" />\r
     <ClInclude Include="producer\color\color_producer.h" />\r
     <ClInclude Include="producer\ffmpeg\audio\audio_decoder.h" />\r
     <ClInclude Include="producer\ffmpeg\ffmpeg_producer.h" />\r
@@ -169,13 +171,15 @@ copy "$(ProjectDir)caspar.config" "$(SolutionDir)build\"</Command>
     <ClInclude Include="producer\ffmpeg\packet.h" />\r
     <ClInclude Include="producer\ffmpeg\video\video_decoder.h" />\r
     <ClInclude Include="producer\ffmpeg\video\video_deinterlacer.h" />\r
-    <ClInclude Include="producer\ffmpeg\video\video_scaler.h" />\r
+    <ClInclude Include="producer\ffmpeg\video\video_transformer.h" />\r
     <ClInclude Include="producer\flash\axflash.h" />\r
+    <ClInclude Include="producer\flash\bitmap.h" />\r
     <ClInclude Include="producer\flash\cg_producer.h" />\r
     <ClInclude Include="producer\flash\ct_producer.h" />\r
     <ClInclude Include="producer\flash\FlashAxContainer.h" />\r
     <ClInclude Include="producer\flash\flash_producer.h" />\r
     <ClInclude Include="producer\flash\TimerHelper.h" />\r
+    <ClInclude Include="producer\frame_producer.h" />\r
     <ClInclude Include="producer\image\image_loader.h" />\r
     <ClInclude Include="producer\image\image_producer.h" />\r
     <ClInclude Include="producer\image\image_scroll_producer.h" />\r
@@ -190,7 +194,6 @@ copy "$(ProjectDir)caspar.config" "$(SolutionDir)build\"</Command>
     <ClInclude Include="protocol\clk\CLKCommand.h" />\r
     <ClInclude Include="protocol\clk\CLKProtocolStrategy.h" />\r
     <ClInclude Include="protocol\media.h" />\r
-    <ClInclude Include="protocol\monitor\Monitor.h" />\r
     <ClInclude Include="renderer\renderer_fwd.h" />\r
     <ClInclude Include="renderer\render_device.h" />\r
     <ClInclude Include="renderer\layer.h" />\r
@@ -199,23 +202,21 @@ copy "$(ProjectDir)caspar.config" "$(SolutionDir)build\"</Command>
     <CustomBuildStep Include="consumers\bluefish\BluefishFrameManager.h" />\r
     <CustomBuildStep Include="consumers\bluefish\BluefishPlaybackStrategy.h" />\r
     <CustomBuildStep Include="consumers\bluefish\BlueFishVideoConsumer.h" />\r
-    <ClInclude Include="frame\bitmap_frame.h" />\r
-    <ClInclude Include="frame\system_frame.h" />\r
     <CustomBuildStep Include="PlaybackControl.h" />\r
     <ClInclude Include="StdAfx.h" />\r
   </ItemGroup>\r
   <ItemGroup>\r
-    <ClCompile Include="consumer\bluefish\BluefishFrameManager.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
     <ClCompile Include="consumer\bluefish\BluefishPlaybackStrategy.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="consumer\bluefish\BlueFishVideoConsumer.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>\r
+      <ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="consumer\decklink\DeckLinkAPI_i.c">\r
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>\r
@@ -233,7 +234,7 @@ copy "$(ProjectDir)caspar.config" "$(SolutionDir)build\"</Command>
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="frame\audio_chunk.cpp">\r
+    <ClCompile Include="frame\composite_gpu_frame.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
@@ -241,6 +242,14 @@ copy "$(ProjectDir)caspar.config" "$(SolutionDir)build\"</Command>
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\stdafx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\stdafx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
+    <ClCompile Include="frame\gpu_frame.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
+    <ClCompile Include="frame\gpu_frame_processor.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../stdafx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
     <ClCompile Include="producer\color\color_producer.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
@@ -265,10 +274,14 @@ copy "$(ProjectDir)caspar.config" "$(SolutionDir)build\"</Command>
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="producer\ffmpeg\video\video_scaler.cpp">\r
+    <ClCompile Include="producer\ffmpeg\video\video_transformer.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
+    <ClCompile Include="producer\flash\bitmap.cpp">\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
+      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"../../StdAfx.h</PrecompiledHeaderFile>\r
+    </ClCompile>\r
     <ClCompile Include="producer\flash\cg_producer.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../../StdAfx.h</PrecompiledHeaderFile>\r
@@ -337,10 +350,6 @@ copy "$(ProjectDir)caspar.config" "$(SolutionDir)build\"</Command>
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
     </ClCompile>\r
-    <ClCompile Include="protocol\monitor\Monitor.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\..\StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\..\StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
     <ClCompile Include="renderer\render_device.cpp">\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
       <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
@@ -353,14 +362,6 @@ copy "$(ProjectDir)caspar.config" "$(SolutionDir)build\"</Command>
       <ExpandAttributedSource Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ExpandAttributedSource>\r
       <PreprocessToFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</PreprocessToFile>\r
     </ClCompile>\r
-    <ClCompile Include="frame\bitmap_frame.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
-    <ClCompile Include="frame\system_frame.cpp">\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">..\StdAfx.h</PrecompiledHeaderFile>\r
-      <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">..\StdAfx.h</PrecompiledHeaderFile>\r
-    </ClCompile>\r
     <ClCompile Include="main.cpp" />\r
     <ClCompile Include="StdAfx.cpp">\r
       <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
index bb1671a817cc5bae40ebe9ae89cc9243929b99c5..acf0135158685d1f8e74c86571da565c945652f6 100644 (file)
     <Filter Include="Source\protocol\amcp">\r
       <UniqueIdentifier>{d33e8ddc-ccb4-4f4f-ad20-e788a796bb7b}</UniqueIdentifier>\r
     </Filter>\r
-    <Filter Include="Source\protocol\monitor">\r
-      <UniqueIdentifier>{300c491b-4f95-4b15-8d77-eff22fb4cd60}</UniqueIdentifier>\r
-    </Filter>\r
     <Filter Include="Source\protocol\clk">\r
       <UniqueIdentifier>{8355a891-c4db-4a0e-8ecc-795314127cdc}</UniqueIdentifier>\r
     </Filter>\r
     <Filter Include="Source\protocol\osc">\r
       <UniqueIdentifier>{23166bfa-06eb-4da9-8a0d-1ae5eac4348b}</UniqueIdentifier>\r
     </Filter>\r
+    <Filter Include="Source\frame\gpu">\r
+      <UniqueIdentifier>{91076088-a8dc-43e2-b401-ca2b8462fd06}</UniqueIdentifier>\r
+    </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="StdAfx.h">\r
     <ClInclude Include="protocol\clk\CLKProtocolStrategy.h">\r
       <Filter>Source\protocol\clk</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="protocol\monitor\Monitor.h">\r
-      <Filter>Source\protocol\monitor</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="renderer\render_device.h">\r
       <Filter>Source\renderer</Filter>\r
     </ClInclude>\r
     <ClInclude Include="frame\frame_format.h">\r
       <Filter>Source\frame</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="frame\bitmap_frame.h">\r
-      <Filter>Source\frame</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="frame\system_frame.h">\r
-      <Filter>Source\frame</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="frame\audio_chunk.h">\r
-      <Filter>Source\frame</Filter>\r
-    </ClInclude>\r
-    <ClInclude Include="frame\frame.h">\r
-      <Filter>Source\frame</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="config.h">\r
       <Filter>Source</Filter>\r
     </ClInclude>\r
     <ClInclude Include="consumer\bluefish\BluefishException.h">\r
       <Filter>Source\consumer\bluefish</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="consumer\bluefish\BluefishFrameManager.h">\r
-      <Filter>Source\consumer\bluefish</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="consumer\decklink\DecklinkVideoConsumer.h">\r
       <Filter>Source\consumer\decklink</Filter>\r
     </ClInclude>\r
     <ClInclude Include="producer\ffmpeg\video\video_deinterlacer.h">\r
       <Filter>Source\producer\ffmpeg\video</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="producer\ffmpeg\video\video_scaler.h">\r
-      <Filter>Source\producer\ffmpeg\video</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="producer\flash\ct_producer.h">\r
       <Filter>Source\producer\flash</Filter>\r
     </ClInclude>\r
     <ClInclude Include="protocol\media.h">\r
       <Filter>Source\protocol</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="frame\gpu_frame.h">\r
+      <Filter>Source\frame\gpu</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="frame\gpu_frame_processor.h">\r
+      <Filter>Source\frame\gpu</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="frame\frame_factory.h">\r
+      <Filter>Source\frame</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\frame_producer.h">\r
+      <Filter>Source\producer</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\ffmpeg\video\video_transformer.h">\r
+      <Filter>Source\producer\ffmpeg\video</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="producer\flash\bitmap.h">\r
+      <Filter>Source\producer\flash</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="frame\composite_gpu_frame.h">\r
+      <Filter>Source\frame\gpu</Filter>\r
+    </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="StdAfx.cpp">\r
     <ClCompile Include="protocol\clk\CLKCommand.cpp">\r
       <Filter>Source\protocol\clk</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="protocol\monitor\Monitor.cpp">\r
-      <Filter>Source\protocol\monitor</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="renderer\render_device.cpp">\r
       <Filter>Source\renderer</Filter>\r
     </ClCompile>\r
     <ClCompile Include="renderer\layer.cpp">\r
       <Filter>Source\renderer</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="frame\system_frame.cpp">\r
-      <Filter>Source\frame</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="frame\frame_format.cpp">\r
       <Filter>Source\frame</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="frame\bitmap_frame.cpp">\r
-      <Filter>Source\frame</Filter>\r
-    </ClCompile>\r
-    <ClCompile Include="frame\audio_chunk.cpp">\r
-      <Filter>Source\frame</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="main.cpp">\r
       <Filter>Source</Filter>\r
     </ClCompile>\r
     <ClCompile Include="consumer\bluefish\BlueFishVideoConsumer.cpp">\r
       <Filter>Source\consumer\bluefish</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="consumer\bluefish\BluefishFrameManager.cpp">\r
-      <Filter>Source\consumer\bluefish</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="consumer\decklink\DecklinkVideoConsumer.cpp">\r
       <Filter>Source\consumer\decklink</Filter>\r
     </ClCompile>\r
     <ClCompile Include="producer\ffmpeg\video\video_deinterlacer.cpp">\r
       <Filter>Source\producer\ffmpeg\video</Filter>\r
     </ClCompile>\r
-    <ClCompile Include="producer\ffmpeg\video\video_scaler.cpp">\r
-      <Filter>Source\producer\ffmpeg\video</Filter>\r
-    </ClCompile>\r
     <ClCompile Include="producer\ffmpeg\video\video_decoder.cpp">\r
       <Filter>Source\producer\ffmpeg\video</Filter>\r
     </ClCompile>\r
     <ClCompile Include="protocol\media.cpp">\r
       <Filter>Source\protocol</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="frame\gpu_frame_processor.cpp">\r
+      <Filter>Source\frame\gpu</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="frame\gpu_frame.cpp">\r
+      <Filter>Source\frame\gpu</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\ffmpeg\video\video_transformer.cpp">\r
+      <Filter>Source\producer\ffmpeg\video</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="producer\flash\bitmap.cpp">\r
+      <Filter>Source\producer\flash</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="frame\composite_gpu_frame.cpp">\r
+      <Filter>Source\frame\gpu</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <Midl Include="consumer\decklink\DeckLinkAPI_v7_3.idl">\r
diff --git a/core/frame/audio_chunk.cpp b/core/frame/audio_chunk.cpp
deleted file mode 100644 (file)
index b0c7abe..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "../StdAfx.h"\r
-\r
-#include "audio_chunk.h"\r
-\r
-#include <tbb/scalable_allocator.h>\r
-\r
-namespace caspar{\r
-\r
-audio_chunk::audio_chunk(size_t dataSize, const sound_channel_info_ptr& snd_channel_info) \r
-       : size_(dataSize), snd_channel_info_(snd_channel_info), data_(static_cast<unsigned char*>(scalable_aligned_malloc(dataSize, 16))), volume_(100.0f)\r
-{}\r
-\r
-audio_chunk::~audio_chunk() \r
-{\r
-       scalable_aligned_free(data_);\r
-}\r
-\r
-const unsigned char* audio_chunk::data() const\r
-{\r
-       return data_;\r
-}\r
-\r
-unsigned char* audio_chunk::data()\r
-{\r
-       return data_;\r
-}\r
-\r
-size_t audio_chunk::size() const\r
-{\r
-       return size_;\r
-}\r
-\r
-float audio_chunk::volume() const\r
-{\r
-       return volume_;\r
-}\r
-\r
-void audio_chunk::set_volume(float volume)\r
-{\r
-       assert(volume_ > 0.0f);\r
-       assert(volume_ < (100.0f + std::numeric_limits<float>::epsilon()));\r
-       volume_ = volume;\r
-}\r
-       \r
-const sound_channel_info_ptr& audio_chunk::sound_channel_info() const\r
-{\r
-       return snd_channel_info_;\r
-}\r
-\r
-}
\ No newline at end of file
diff --git a/core/frame/audio_chunk.h b/core/frame/audio_chunk.h
deleted file mode 100644 (file)
index 2dbd19b..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
-#pragma once\r
-\r
-#include <boost/noncopyable.hpp>\r
-\r
-#include <memory>\r
-\r
-namespace caspar{\r
-       \r
-struct sound_channel_info : boost::noncopyable\r
-{\r
-public:\r
-       sound_channel_info(size_t channels_count, size_t bits_per_sample, size_t sample_rate)\r
-               : channels_count(channels_count), bits_per_sample(bits_per_sample), sample_rate(sample_rate){}\r
-       const size_t channels_count;\r
-       const size_t bits_per_sample;\r
-       const size_t sample_rate;\r
-};\r
-typedef std::shared_ptr<sound_channel_info> sound_channel_info_ptr;\r
-typedef std::unique_ptr<sound_channel_info> sound_channel_info_uptr;\r
-\r
-class audio_chunk : boost::noncopyable\r
-{\r
-public:\r
-       audio_chunk(size_t dataSize, const sound_channel_info_ptr& snd_channel_info);\r
-       ~audio_chunk();\r
-\r
-       const unsigned char* data() const;\r
-       unsigned char* data();\r
-       size_t size() const;\r
-       float volume() const;\r
-       void set_volume(float volume);\r
-       const sound_channel_info_ptr& sound_channel_info() const;\r
-\r
-private:\r
-       float volume_;\r
-       const sound_channel_info_ptr snd_channel_info_;\r
-       unsigned char* const data_;\r
-       const int size_;\r
-};\r
-typedef std::shared_ptr<audio_chunk> audio_chunk_ptr;\r
-typedef std::unique_ptr<audio_chunk> audio_chunk_uptr;\r
-\r
-}
\ No newline at end of file
diff --git a/core/frame/composite_gpu_frame.cpp b/core/frame/composite_gpu_frame.cpp
new file mode 100644 (file)
index 0000000..36c9014
--- /dev/null
@@ -0,0 +1,75 @@
+#include "../StdAfx.h"\r
+\r
+#include "composite_gpu_frame.h"\r
+#include "../../common/image/copy.h"\r
+#include "../../common/gl/utility.h"\r
+\r
+#include <algorithm>\r
+#include <numeric>\r
+\r
+namespace caspar {\r
+       \r
+struct composite_gpu_frame::implementation\r
+{\r
+       implementation(composite_gpu_frame* self) : self_(self){}\r
+\r
+       void write_lock()\r
+       {\r
+               std::for_each(frames_.begin(), frames_.end(), std::mem_fn(&gpu_frame::write_lock));             \r
+       }\r
+\r
+       bool write_unlock()\r
+       {\r
+               return std::all_of(frames_.begin(), frames_.end(), std::mem_fn(&gpu_frame::write_unlock));                      \r
+       }\r
+       \r
+       void read_lock(GLenum mode)\r
+       {       \r
+               std::for_each(frames_.begin(), frames_.end(), std::bind(&gpu_frame::read_lock, std::placeholders::_1, mode));           \r
+       }\r
+\r
+       bool read_unlock()\r
+       {\r
+               return std::all_of(frames_.begin(), frames_.end(), std::mem_fn(&gpu_frame::read_unlock));               \r
+       }\r
+\r
+       void draw()\r
+       {\r
+               glPushMatrix();\r
+               glTranslatef(self_->x()*2.0f, self_->y()*2.0f, 0.0f);\r
+               std::for_each(frames_.begin(), frames_.end(), std::mem_fn(&gpu_frame::draw));\r
+               glPopMatrix();\r
+       }\r
+               \r
+       void add(const gpu_frame_ptr& frame)\r
+       {\r
+               frames_.push_back(frame);\r
+               mix_audio_safe(audio_data_, frame->audio_data());\r
+       }\r
+\r
+       unsigned char* data()\r
+       {\r
+               BOOST_THROW_EXCEPTION(invalid_operation());\r
+       }\r
+\r
+       composite_gpu_frame* self_;\r
+       std::vector<gpu_frame_ptr> frames_;\r
+       size_t size_;\r
+       std::vector<short> audio_data_;\r
+};\r
+\r
+#pragma warning (disable : 4355)\r
+\r
+composite_gpu_frame::composite_gpu_frame(size_t width, size_t height) : gpu_frame(width, height), impl_(new implementation(this)){}\r
+void composite_gpu_frame::write_lock(){impl_->write_lock();}\r
+bool composite_gpu_frame::write_unlock(){return impl_->write_unlock();}        \r
+void composite_gpu_frame::read_lock(GLenum mode){impl_->read_lock(mode);}\r
+bool composite_gpu_frame::read_unlock(){return impl_->read_unlock();}\r
+void composite_gpu_frame::draw(){impl_->draw();}\r
+unsigned char* composite_gpu_frame::data(){return impl_->data();}\r
+const std::vector<short>& composite_gpu_frame::audio_data() const { return impl_->audio_data_; }       \r
+std::vector<short>& composite_gpu_frame::audio_data() { return impl_->audio_data_; }\r
+void composite_gpu_frame::reset(){impl_->audio_data_.clear();}\r
+void composite_gpu_frame::add(const gpu_frame_ptr& frame){impl_->add(frame);}\r
+\r
+}
\ No newline at end of file
diff --git a/core/frame/composite_gpu_frame.h b/core/frame/composite_gpu_frame.h
new file mode 100644 (file)
index 0000000..ebe585b
--- /dev/null
@@ -0,0 +1,36 @@
+#pragma once\r
+\r
+#include <memory>\r
+\r
+#include <Glee.h>\r
+\r
+#include "gpu_frame.h"\r
+\r
+namespace caspar {\r
+       \r
+class composite_gpu_frame : public gpu_frame\r
+{\r
+public:\r
+       composite_gpu_frame(size_t width, size_t height);\r
+\r
+       void write_lock();\r
+       bool write_unlock();\r
+       void read_lock(GLenum mode);\r
+       bool read_unlock();\r
+       void draw();\r
+       void reset();\r
+               \r
+       unsigned char* data();\r
+                                       \r
+       const std::vector<short>& audio_data() const;   \r
+       std::vector<short>& audio_data();\r
+\r
+       void add(const gpu_frame_ptr& frame);\r
+       \r
+private:\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
+};\r
+typedef std::shared_ptr<composite_gpu_frame> composite_gpu_frame_ptr;\r
+       \r
+}
\ No newline at end of file
diff --git a/core/frame/frame.h b/core/frame/frame.h
deleted file mode 100644 (file)
index 998792a..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
-#pragma once\r
-\r
-#include <memory>\r
-#include <vector>\r
-\r
-#include "audio_chunk.h"\r
-#include "frame_format.h"\r
-\r
-#include "../../common/image/image.h"\r
-\r
-#include <tbb/parallel_invoke.h>\r
-\r
-#include <boost/range/algorithm.hpp>\r
-\r
-namespace caspar {\r
-\r
-// NOTE: audio data is ALWAYS shallow copy\r
-class frame : boost::noncopyable\r
-{\r
-public:\r
-       virtual ~frame(){}\r
-       \r
-       virtual const unsigned char* data() const { return const_cast<frame&>(*this).data(); }\r
-       virtual unsigned char* data() = 0;\r
-       virtual size_t size() const = 0;\r
-       virtual void* tag() const { return nullptr; }\r
-       virtual const std::vector<audio_chunk_ptr>& audio_data() const { return audioData_; }   \r
-       virtual std::vector<audio_chunk_ptr>& audio_data() { return audioData_; }                       \r
-\r
-       static std::shared_ptr<frame> null()\r
-       {\r
-               class null_frame : public frame\r
-               {\r
-                       unsigned char* data() { return nullptr; };\r
-                       size_t size() const { return 0; };\r
-               };\r
-               static auto my_null_frame = std::make_shared<null_frame>();\r
-               return my_null_frame;\r
-       }\r
-private:       \r
-       std::vector<audio_chunk_ptr> audioData_;\r
-};\r
-typedef std::shared_ptr<frame> frame_ptr;\r
-typedef std::shared_ptr<const frame> frame_const_ptr;\r
-typedef std::unique_ptr<frame> frame_uptr;\r
-typedef std::unique_ptr<const frame> frame_const_uptr;\r
-\r
-inline bool operator==(const frame& lhs, const frame& rhs)\r
-{\r
-       return lhs.data() == rhs.data() && (lhs.data() == nullptr || lhs.size() == rhs.size());\r
-}\r
-\r
-template<typename frame_ptr_type>\r
-frame_ptr_type& set_frame_volume(frame_ptr_type& result_frame, float volume)\r
-{\r
-       assert(result_frame != nullptr);\r
-       assert(boost::range::find(result_frame->audio_data(), nullptr) == result_frame->audio_data().end());\r
-       boost::range::for_each(result_frame->audio_data(), std::bind(&audio_chunk::set_volume, std::placeholders::_1, volume));\r
-       return result_frame;\r
-}\r
-\r
-template<typename frame_ptr_type>\r
-frame_ptr_type& clear_frame(frame_ptr_type& result_frame)\r
-{\r
-       assert(result_frame != nullptr);\r
-       common::image::clear(result_frame->data(), result_frame->size());\r
-       result_frame->audio_data().clear();\r
-       return result_frame;\r
-}\r
-\r
-template<typename frame_ptr_type>\r
-frame_ptr_type& pre_over_frame(frame_ptr_type& result_frame, const frame_const_ptr& frame1, const frame_const_ptr& frame2)\r
-{\r
-       assert(result_frame != nullptr && frame1 != nullptr && frame2 != nullptr);\r
-       assert(result_frame->size() == frame1->size());\r
-       assert(result_frame->size() == frame2->size());\r
-       assert(boost::range::find(frame1->audio_data(), nullptr) == frame1->audio_data().end());\r
-       assert(boost::range::find(frame2->audio_data(), nullptr) == frame2->audio_data().end());\r
-       tbb::parallel_invoke(\r
-       [&]{common::image::pre_over(result_frame->data(), frame1->data(), frame2->data(), result_frame->size());},\r
-       [&]\r
-       {\r
-               if(result_frame != frame1)\r
-                       boost::range::copy(frame1->audio_data(), std::back_inserter(result_frame->audio_data()));\r
-               if(result_frame != frame2)\r
-                       boost::range::copy(frame2->audio_data(), std::back_inserter(result_frame->audio_data()));\r
-       });\r
-       return result_frame;\r
-}\r
-\r
-template<typename frame_ptr_type>\r
-frame_ptr_type& copy_frame(frame_ptr_type& result_frame, const frame_const_ptr& frame)\r
-{      \r
-       assert(result_frame != nullptr && frame != nullptr);\r
-       assert(result_frame->size() == frame->size());\r
-       if(result_frame == frame)\r
-               return result_frame;\r
-       tbb::parallel_invoke(\r
-       [&]{common::image::copy(result_frame->data(), frame->data(), result_frame->size());},\r
-       [&]{boost::range::copy(frame->audio_data(), std::back_inserter(result_frame->audio_data()));});\r
-       return result_frame;\r
-} \r
-\r
-template<typename frame_ptr_type>\r
-frame_ptr_type& copy_frame(frame_ptr_type& result_frame, const frame_const_ptr& frame, const frame_format_desc& format_desc)\r
-{      \r
-       assert(result_frame != nullptr && frame != nullptr);\r
-       assert(result_frame->size() == format_desc.size);\r
-       assert(frame->size() == format_desc.size);\r
-       if(result_frame == frame)\r
-               return result_frame;\r
-       tbb::parallel_invoke(\r
-       [&]\r
-       {\r
-               if(format_desc.mode == video_mode::progressive)\r
-                       common::image::copy(result_frame->data(), frame->data(), result_frame->size());\r
-               else\r
-                       common::image::copy_field(result_frame->data(), frame->data(), format_desc.mode == video_mode::upper ? 1 : 0, format_desc.width, format_desc.height);\r
-       },\r
-       [&]{boost::range::copy(frame->audio_data(), std::back_inserter(result_frame->audio_data()));});\r
-       return result_frame;\r
-} \r
-\r
-template<typename frame_ptr_type, typename frame_container>\r
-frame_ptr_type& compose_frames(frame_ptr_type& result_frame, const frame_container& frames)\r
-{\r
-       assert(boost::range::find(frames, nullptr) == frames.end());\r
-       assert(boost::range::find_if(frames, [&](const frame_ptr& frame) { return frame->size() != result_frame->size();}) == frames.end());\r
-       if(frames.empty())      \r
-               clear_frame(result_frame);      \r
-       else if(frames.size() == 1)     \r
-               copy_frame(result_frame, frames[0]);    \r
-       else if(frames.size() == 2)     \r
-               pre_over_frame(result_frame, frames[0], frames[1]);     \r
-       else\r
-       {\r
-               for(size_t n = 0; n < frames.size() - 2; ++n)\r
-                       pre_over_frame(frames[0], frames[n], frames[n+1]);\r
-               pre_over_frame(result_frame, frames[0], frames[frames.size()-1]);\r
-       }\r
-       return result_frame;\r
-}\r
-\r
-}
\ No newline at end of file
diff --git a/core/frame/frame_factory.h b/core/frame/frame_factory.h
new file mode 100644 (file)
index 0000000..3c571f7
--- /dev/null
@@ -0,0 +1,21 @@
+#pragma once\r
+\r
+#include "gpu_frame.h"\r
+#include "frame_format.h"\r
+\r
+#include <memory>\r
+\r
+namespace caspar { \r
+\r
+struct frame_factory\r
+{\r
+       virtual gpu_frame_ptr create_frame(size_t width, size_t height) = 0;\r
+       gpu_frame_ptr create_frame(const frame_format_desc format_desc)\r
+       {\r
+               return create_frame(format_desc.width, format_desc.height);\r
+       }\r
+};\r
+\r
+typedef std::shared_ptr<frame_factory> frame_factory_ptr;\r
+\r
+}
\ No newline at end of file
index fac407c0efbf8f0143fd2e6c274c08f9b3220916..db32e0562473409b41c47aaefc33fbb7b5fe52c2 100644 (file)
@@ -4,11 +4,11 @@
 \r
 namespace caspar{\r
        \r
-class frame;\r
-typedef std::shared_ptr<frame> frame_ptr;\r
-typedef std::shared_ptr<const frame> frame_const_ptr;\r
-typedef std::unique_ptr<frame> frame_uptr;\r
-typedef std::unique_ptr<const frame> frame_const_uptr;\r
+class gpu_frame;\r
+typedef std::shared_ptr<gpu_frame> gpu_frame_ptr;\r
+\r
+struct frame_factory;\r
+typedef std::shared_ptr<frame_factory> frame_factory_ptr;\r
 \r
 struct frame_format_desc;\r
        \r
diff --git a/core/frame/gpu_frame.cpp b/core/frame/gpu_frame.cpp
new file mode 100644 (file)
index 0000000..ddb085b
--- /dev/null
@@ -0,0 +1,164 @@
+#include "../StdAfx.h"\r
+\r
+#include "gpu_frame.h"\r
+#include "../../common/image/copy.h"\r
+#include "../../common/gl/utility.h"\r
+\r
+namespace caspar {\r
+       \r
+struct gpu_frame::implementation\r
+{\r
+       implementation(size_t width, size_t height) \r
+               : pbo_(0), data_(nullptr), width_(width), height_(height), size_(width*height*4), reading_(false), texture_(0), alpha_(1.0f)\r
+       {       \r
+       }\r
+\r
+       ~implementation()\r
+       {\r
+               if(pbo_ != 0)\r
+                       glDeleteBuffers(1, &pbo_);\r
+               if(texture_ != 0)\r
+                       glDeleteTextures(1, &texture_);\r
+       }\r
+\r
+       GLuint pbo()\r
+       {               \r
+               if(pbo_ == 0)\r
+                       CASPAR_GL_CHECK(glGenBuffers(1, &pbo_));\r
+               return pbo_;\r
+       }\r
+\r
+       void write_lock()\r
+       {\r
+               if(texture_ == 0)\r
+               {\r
+                       CASPAR_GL_CHECK(glGenTextures(1, &texture_));\r
+\r
+                       CASPAR_GL_CHECK(glBindTexture(GL_TEXTURE_2D, texture_));\r
+\r
+                       CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));\r
+                       CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));\r
+                       CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));\r
+                       CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));\r
+\r
+                       CASPAR_GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width_, height_, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL));\r
+               }\r
+\r
+               CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo()));\r
+               if(data_ != nullptr)\r
+               {\r
+                       CASPAR_GL_CHECK(glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER));\r
+                       data_ = nullptr;\r
+               }\r
+               CASPAR_GL_CHECK(glBindTexture(GL_TEXTURE_2D, texture_));\r
+               CASPAR_GL_CHECK(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, NULL));\r
+               CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));\r
+       }\r
+\r
+       bool write_unlock()\r
+       {\r
+               if(data_ != nullptr)\r
+                       return false;\r
+               CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo()));\r
+               CASPAR_GL_CHECK(glBufferData(GL_PIXEL_UNPACK_BUFFER, size_, NULL, GL_STREAM_DRAW));\r
+               void* ptr = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);\r
+               CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));\r
+               data_ = reinterpret_cast<unsigned char*>(ptr);\r
+               if(!data_)\r
+                       BOOST_THROW_EXCEPTION(std::bad_alloc());\r
+               return true;\r
+       }\r
+       \r
+       void read_lock(GLenum mode)\r
+       {       \r
+               CASPAR_GL_CHECK(glReadBuffer(mode));\r
+               CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo()));\r
+               if(data_ != nullptr)    \r
+               {       \r
+                       CASPAR_GL_CHECK(glUnmapBuffer(GL_PIXEL_PACK_BUFFER));   \r
+                       data_ = nullptr;\r
+               }\r
+               CASPAR_GL_CHECK(glBufferData(GL_PIXEL_PACK_BUFFER, size_, NULL, GL_STREAM_READ));       \r
+               CASPAR_GL_CHECK(glReadPixels(0, 0, width_, height_, GL_BGRA, GL_UNSIGNED_BYTE, NULL));\r
+               CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0));\r
+               reading_ = true;\r
+       }\r
+\r
+       bool read_unlock()\r
+       {\r
+               if(data_ != nullptr || !reading_)\r
+                       return false;\r
+               CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo()));\r
+               void* ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);   \r
+               CASPAR_GL_CHECK(glBindBuffer(GL_PIXEL_PACK_BUFFER, 0));\r
+               data_ = reinterpret_cast<unsigned char*>(ptr);\r
+               if(!data_)\r
+                       BOOST_THROW_EXCEPTION(std::bad_alloc());\r
+               reading_ = false;\r
+               return true;\r
+       }\r
+\r
+       void draw()\r
+       {\r
+               glPushMatrix();\r
+               glTranslatef(x_*2.0f, y_*2.0f, 0.0f);\r
+               glColor4f(1.0f, 1.0f, 1.0f, alpha_);\r
+               CASPAR_GL_CHECK(glBindTexture(GL_TEXTURE_2D, texture_));\r
+               glBegin(GL_QUADS);\r
+                       glTexCoord2f(0.0f, 0.0f); glVertex2f(-1.0f, -1.0f);\r
+                       glTexCoord2f(1.0f, 0.0f); glVertex2f( 1.0f, -1.0f);\r
+                       glTexCoord2f(1.0f, 1.0f); glVertex2f( 1.0f,  1.0f);\r
+                       glTexCoord2f(0.0f, 1.0f); glVertex2f(-1.0f,  1.0f);\r
+               glEnd();\r
+               glPopMatrix();\r
+       }\r
+               \r
+       unsigned char* data()\r
+       {\r
+               if(data_ == nullptr)\r
+                       BOOST_THROW_EXCEPTION(invalid_operation());\r
+               return data_;\r
+       }\r
+\r
+       void reset()\r
+       {\r
+               audio_data_.clear();\r
+               alpha_ = 1.0f;\r
+               x_ = 0.0f;\r
+               y_ = 0.0f;\r
+       }\r
+\r
+       gpu_frame* self_;\r
+       GLuint pbo_;\r
+       GLuint texture_;\r
+       unsigned char* data_;\r
+       size_t width_;\r
+       size_t height_;\r
+       size_t size_;\r
+       bool reading_;\r
+       std::vector<short> audio_data_;\r
+\r
+       float alpha_;\r
+       float x_;\r
+       float y_;\r
+};\r
+\r
+gpu_frame::gpu_frame(size_t width, size_t height) : impl_(new implementation(width, height)){}\r
+void gpu_frame::write_lock(){impl_->write_lock();}\r
+bool gpu_frame::write_unlock(){return impl_->write_unlock();}  \r
+void gpu_frame::read_lock(GLenum mode){impl_->read_lock(mode);}\r
+bool gpu_frame::read_unlock(){return impl_->read_unlock();}\r
+void gpu_frame::draw(){impl_->draw();}\r
+unsigned char* gpu_frame::data(){return impl_->data();}\r
+size_t gpu_frame::size() const { return impl_->size_; }\r
+size_t gpu_frame::width() const { return impl_->width_;}\r
+size_t gpu_frame::height() const { return impl_->height_;}\r
+const std::vector<short>& gpu_frame::audio_data() const { return impl_->audio_data_; } \r
+std::vector<short>& gpu_frame::audio_data() { return impl_->audio_data_; }\r
+void gpu_frame::reset(){impl_->reset();}\r
+float gpu_frame::alpha() const{ return impl_->alpha_;}\r
+void gpu_frame::alpha(float value){ impl_->alpha_ = value;}\r
+float gpu_frame::x() const { return impl_->x_;}\r
+float gpu_frame::y() const { return impl_->y_;}\r
+void gpu_frame::translate(float x, float y) { impl_->x_ += x; impl_->y_ += y; }\r
+}
\ No newline at end of file
diff --git a/core/frame/gpu_frame.h b/core/frame/gpu_frame.h
new file mode 100644 (file)
index 0000000..c362d70
--- /dev/null
@@ -0,0 +1,67 @@
+#pragma once\r
+\r
+#include <memory>\r
+\r
+#include <Glee.h>\r
+\r
+namespace caspar {\r
+       \r
+class gpu_frame\r
+{\r
+public:\r
+       gpu_frame(size_t width, size_t height);\r
+\r
+       virtual void write_lock();\r
+       virtual bool write_unlock();\r
+       virtual void read_lock(GLenum mode);\r
+       virtual bool read_unlock();\r
+       virtual void draw();\r
+               \r
+       virtual unsigned char* data();\r
+       virtual size_t size() const;\r
+       virtual size_t width() const;\r
+       virtual size_t height() const;\r
+       \r
+       virtual void reset();\r
+                       \r
+       virtual const std::vector<short>& audio_data() const;   \r
+       virtual std::vector<short>& audio_data();\r
+\r
+       virtual float alpha() const;\r
+       virtual void alpha(float value);\r
+\r
+       virtual float x() const;\r
+       virtual float y() const;\r
+       virtual void translate(float x, float y);\r
+\r
+       static std::shared_ptr<gpu_frame> null()\r
+       {\r
+               static auto my_null_frame = std::make_shared<gpu_frame>(0,0);\r
+               return my_null_frame;\r
+       }\r
+               \r
+private:\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
+};\r
+typedef std::shared_ptr<gpu_frame> gpu_frame_ptr;\r
+       \r
+inline void mix_audio_safe(std::vector<short>& frame1, const std::vector<short>& frame2)\r
+{\r
+       if(frame1.empty())\r
+               frame1 = std::move(frame2);\r
+       else if(!frame2.empty())\r
+       {\r
+               for(size_t n = 0; n < frame1.size(); ++n)\r
+                       frame1[n] = static_cast<short>(static_cast<int>(frame1[n]) + static_cast<int>(frame2[n]) & 0xFFFF);                             \r
+       }\r
+}\r
+\r
+template<typename frame_ptr_type>\r
+frame_ptr_type& mix_audio_safe(frame_ptr_type& frame1, const gpu_frame_ptr& frame2)\r
+{\r
+       mix_audio_safe(frame1->audio_data(), frame2->audio_data());\r
+       return frame1;\r
+}\r
+\r
+}
\ No newline at end of file
diff --git a/core/frame/gpu_frame_processor.cpp b/core/frame/gpu_frame_processor.cpp
new file mode 100644 (file)
index 0000000..9162d4f
--- /dev/null
@@ -0,0 +1,235 @@
+#include "../StdAfx.h"\r
+\r
+#include "gpu_frame_processor.h"\r
+\r
+#include "gpu_frame.h"\r
+#include "frame_format.h"\r
+\r
+#include "../../common/exception/exceptions.h"\r
+#include "../../common/concurrency/executor.h"\r
+#include "../../common/image/image.h"\r
+#include "../../common/gl/utility.h"\r
+\r
+#include <Glee.h>\r
+#include <SFML/Window.hpp>\r
+\r
+#include <tbb/concurrent_queue.h>\r
+#include <tbb/concurrent_unordered_map.h>\r
+\r
+#include <boost/lexical_cast.hpp>\r
+#include <boost/thread/once.hpp>\r
+#include <boost/thread.hpp>\r
+#include <boost/range.hpp>\r
+#include <boost/foreach.hpp>\r
+#include <boost/range/algorithm_ext/erase.hpp>\r
+#include <boost/range/algorithm.hpp>\r
+\r
+#include <functional>\r
+#include <unordered_map>\r
+#include <numeric>\r
+\r
+namespace caspar {\r
+       \r
+class frame_buffer\r
+{\r
+public:\r
+       frame_buffer(size_t width, size_t height)\r
+       {\r
+               CASPAR_GL_CHECK(glGenTextures(1, &texture_));   \r
+\r
+               CASPAR_GL_CHECK(glBindTexture(GL_TEXTURE_2D, texture_));\r
+\r
+               CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));\r
+               CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));\r
+               CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));\r
+               CASPAR_GL_CHECK(glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));\r
+\r
+               CASPAR_GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL));\r
+\r
+               glGenFramebuffersEXT(1, &fbo_);\r
+               \r
+               glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_);\r
+               glBindTexture(GL_TEXTURE_2D, texture_);\r
+               glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture_, 0);\r
+       }\r
+\r
+       ~frame_buffer()\r
+       {\r
+               glDeleteFramebuffersEXT(1, &fbo_);\r
+       }\r
+               \r
+       GLuint handle() { return fbo_; }\r
+       GLenum attachement() { return GL_COLOR_ATTACHMENT0_EXT; }\r
+       \r
+private:\r
+       GLuint texture_;\r
+       GLuint fbo_;\r
+};\r
+typedef std::shared_ptr<frame_buffer> frame_buffer_ptr;\r
+\r
+struct gpu_frame_processor::implementation\r
+{      \r
+       implementation(const frame_format_desc& format_desc) : format_desc_(format_desc)\r
+       {               \r
+               executor_.start();\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       context_.reset(new sf::Context());\r
+                       context_->SetActive(true);\r
+                       glEnable(GL_TEXTURE_2D);\r
+                       glEnable(GL_BLEND);\r
+                       glDisable(GL_DEPTH_TEST);\r
+                       glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);                      \r
+                       glClearColor(0.0, 0.0, 0.0, 0.0);\r
+                       glViewport(0, 0, format_desc_.width, format_desc_.height);\r
+                       glLoadIdentity();\r
+\r
+                       input_.resize(2);\r
+                       writing_.resize(2);\r
+                       fbo_ = std::make_shared<frame_buffer>(format_desc_.width, format_desc_.height);\r
+                       output_frame_ = std::make_shared<gpu_frame>(format_desc_.width, format_desc_.height);\r
+                       index_ = 0;\r
+               });\r
+\r
+               empty_frame_ = create_frame(format_desc.width, format_desc.height);\r
+               common::image::clear(empty_frame_->data(), empty_frame_->size());\r
+               // Fill pipeline length\r
+               for(int n = 0; n < 3; ++n)\r
+                       finished_frames_.push(empty_frame_);\r
+       }\r
+\r
+       ~implementation()\r
+       {\r
+               finished_frames_.push(nullptr);\r
+               executor_.stop();\r
+       }\r
+               \r
+       void pop(gpu_frame_ptr& frame)\r
+       {\r
+               finished_frames_.pop(frame);\r
+       }       \r
+       \r
+       void composite(std::vector<gpu_frame_ptr> frames)\r
+       {\r
+               boost::range::remove_erase(frames, nullptr);\r
+               boost::range::remove_erase(frames, gpu_frame::null());\r
+\r
+               executor_.begin_invoke([=]\r
+               {\r
+                       try\r
+                       {\r
+                               index_ = (index_ + 1) % 2;\r
+                               int next_index = (index_ + 1) % 2;\r
+\r
+                               // 2. Start asynchronous DMA transfer to video memory\r
+                               // Lock frames and give pointer ownership to OpenGL                     \r
+                               boost::range::for_each(input_[index_], std::mem_fn(&gpu_frame::write_lock));\r
+                               writing_[index_] = input_[index_];      \r
+                               input_[index_].clear();\r
+                               \r
+                               // 1. Copy to page-locked memory\r
+                               input_[next_index] = frames;\r
+                                                               \r
+                               // 4. Output to external buffer\r
+                               if(output_frame_->read_unlock())\r
+                                       finished_frames_.push(output_frame_);\r
+                               output_frame_ = nullptr;\r
+               \r
+                               // 3. Draw to framebuffer and start asynchronous DMA transfer to page-locked memory                             \r
+                               // Clear framebuffer\r
+                               glClear(GL_COLOR_BUFFER_BIT);   \r
+\r
+                               // Draw all frames to framebuffer\r
+                               glLoadIdentity();\r
+                               boost::range::for_each(writing_[next_index], std::mem_fn(&gpu_frame::draw));\r
+                               \r
+                               // Create an output frame\r
+                               output_frame_ = create_output_frame();\r
+                       \r
+                               // Read from framebuffer into page-locked memory\r
+                               output_frame_->read_lock(GL_COLOR_ATTACHMENT0_EXT);\r
+\r
+                               // Unlock frames and give back pointer ownership\r
+                               boost::range::for_each(writing_[next_index], std::mem_fn(&gpu_frame::write_unlock));\r
+                               \r
+                               // Mix audio from composite frames into output frame\r
+                               std::accumulate(writing_[next_index].begin(), writing_[next_index].end(), output_frame_, mix_audio_safe<gpu_frame_ptr>);        \r
+\r
+                               // Return frames to pool\r
+                               writing_[next_index].clear();\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       }\r
+               });     \r
+       }\r
+\r
+       gpu_frame_ptr create_output_frame()\r
+       {       \r
+               gpu_frame_ptr frame;\r
+               if(!out_frame_pool_.try_pop(frame))                             \r
+                       frame = std::make_shared<gpu_frame>(format_desc_.width, format_desc_.height);\r
+\r
+               return gpu_frame_ptr(frame.get(), [=](gpu_frame*)\r
+               {\r
+                       frame->reset();\r
+                       out_frame_pool_.push(frame);\r
+               });\r
+       }\r
+               \r
+       gpu_frame_ptr create_frame(size_t width, size_t height)\r
+       {\r
+               size_t key = width | (height << 16);\r
+               auto& pool = input_frame_pools_[key];\r
+               \r
+               gpu_frame_ptr frame;\r
+               if(!pool.try_pop(frame))\r
+               {\r
+                       frame = executor_.invoke([=]() -> gpu_frame_ptr\r
+                       {\r
+                               auto frame = std::make_shared<gpu_frame>(width, height);\r
+                               frame->write_unlock();\r
+                               return frame;\r
+                       });\r
+               }\r
+               \r
+               auto destructor = [=]\r
+               {\r
+                       frame->reset();\r
+                       input_frame_pools_[key].push(frame);\r
+               };\r
+\r
+               return gpu_frame_ptr(frame.get(), [=](gpu_frame*)\r
+               {\r
+                       executor_.begin_invoke(destructor);\r
+               });\r
+       }\r
+                       \r
+       tbb::concurrent_unordered_map<size_t, tbb::concurrent_bounded_queue<gpu_frame_ptr>> input_frame_pools_;\r
+\r
+       tbb::concurrent_bounded_queue<gpu_frame_ptr> out_frame_pool_;\r
+               \r
+       frame_buffer_ptr fbo_;\r
+\r
+       int index_;\r
+       std::vector<std::vector<gpu_frame_ptr>>                 input_;\r
+       std::vector<std::vector<gpu_frame_ptr>>                 writing_;\r
+\r
+       gpu_frame_ptr                                                                   output_frame_;\r
+       tbb::concurrent_bounded_queue<gpu_frame_ptr>    finished_frames_;\r
+                       \r
+       frame_format_desc format_desc_;\r
+       \r
+       std::unique_ptr<sf::Context> context_;\r
+       common::executor executor_;\r
+\r
+       gpu_frame_ptr empty_frame_;\r
+};\r
+       \r
+gpu_frame_processor::gpu_frame_processor(const frame_format_desc& format_desc) : impl_(new implementation(format_desc)){}\r
+void gpu_frame_processor::push(const std::vector<gpu_frame_ptr>& frames){ impl_->composite(frames);}\r
+void gpu_frame_processor::pop(gpu_frame_ptr& frame){ impl_->pop(frame);}\r
+gpu_frame_ptr gpu_frame_processor::create_frame(size_t width, size_t height){return impl_->create_frame(width, height);}\r
+\r
+}
\ No newline at end of file
similarity index 61%
rename from core/frame/system_frame.h
rename to core/frame/gpu_frame_processor.h
index e63b2e7c7c8021860d603160ab59491fb2a9be2f..0c1f6b50286bb7ce3c4bef8785ea5cededf44479 100644 (file)
 */\r
 #pragma once\r
 \r
-#include "frame.h"\r
-\r
 #include <memory>\r
+#include <vector>\r
+\r
+#include "frame_fwd.h"\r
+#include "frame_factory.h"\r
 \r
 namespace caspar {\r
 \r
-class system_frame : public frame\r
+class gpu_frame_processor : public frame_factory,  boost::noncopyable\r
 {\r
 public:\r
-       explicit system_frame(unsigned int dataSize);\r
-       ~system_frame();\r
+       gpu_frame_processor(const frame_format_desc& format_desc);\r
+\r
+       void push(const std::vector<gpu_frame_ptr>& frames);\r
+       void pop(gpu_frame_ptr& frame);\r
 \r
-       unsigned char* data();\r
-       unsigned int size() const;\r
+       gpu_frame_ptr create_frame(size_t width, size_t height);\r
 private:\r
-       unsigned char* const data_;\r
-       const size_t size_;\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
 };\r
+typedef std::shared_ptr<gpu_frame_processor> gpu_frame_processor_ptr;\r
 \r
 }
\ No newline at end of file
diff --git a/core/frame/system_frame.cpp b/core/frame/system_frame.cpp
deleted file mode 100644 (file)
index d9b2123..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
\r
-#include "../stdafx.h"\r
-\r
-#include "system_frame.h"\r
-\r
-#include <tbb/scalable_allocator.h>\r
-\r
-namespace caspar {\r
-\r
-system_frame::system_frame(unsigned int dataSize) \r
-       : size_(dataSize), data_(static_cast<unsigned char*>(scalable_aligned_malloc(dataSize, 16))){}\r
-system_frame::~system_frame(){scalable_aligned_free(data_);}\r
-unsigned char* system_frame::data() {return data_;}    \r
-unsigned int system_frame::size() const{return size_;}\r
-\r
-}\r
-\r
index 53edc383182c645d0dfc291e585476d5fa22d1a1..7f8b8810c27eaa835845a2594c40d82948d1c5ad 100644 (file)
@@ -82,8 +82,16 @@ int _tmain(int argc, _TCHAR* argv[])
                        std::getline(std::wcin, wcmd); // TODO: It's blocking...\r
                        is_running = wcmd != L"exit" && wcmd != L"q";\r
                        if(wcmd == L"1")\r
-                               wcmd = L"LOADBG 1-1 DV SLIDE 50 LOOP AUTOPLAY";\r
+                               wcmd = L"LOADBG 1-1 DV SLIDE 100 LOOP AUTOPLAY";\r
                        else if(wcmd == L"2")\r
+                               wcmd = L"LOADBG 1-1 DV PUSH 100 LOOP AUTOPLAY";\r
+                       else if(wcmd == L"3")\r
+                               wcmd = L"LOADBG 1-1 DV MIX 100 LOOP AUTOPLAY";\r
+                       else if(wcmd == L"4")\r
+                               wcmd = L"LOADBG 1-1 DV WIPE 100 LOOP AUTOPLAY";\r
+                       else if(wcmd == L"5")\r
+                               wcmd = L"LOADBG 1-1 DV CUT 100 LOOP AUTOPLAY";\r
+                       else if(wcmd == L"6")\r
                                wcmd = L"CG 1-2 ADD 1 BBTELEFONARE 1";\r
 \r
                        wcmd += L"\r\n";\r
index 0d08b29f26499785e709ab0adccfd8ac6d940601..d8fc55ed513ce3b008804ee2678d0786bcf68a81 100644 (file)
@@ -22,7 +22,6 @@
 \r
 #include "color_producer.h"\r
 \r
-#include "../../frame/system_frame.h"\r
 #include "../../frame/frame_format.h"\r
 \r
 #include <intrin.h>\r
@@ -33,17 +32,19 @@ namespace caspar {
 class color_producer : public frame_producer\r
 {\r
 public:\r
-       explicit color_producer(unsigned long color_value, const frame_format_desc& format_desc) : format_desc_(format_desc)\r
+       explicit color_producer(unsigned long color_value, const frame_format_desc& format_desc) : format_desc_(format_desc){}\r
+\r
+       gpu_frame_ptr get_frame() { return frame_; }\r
+       const frame_format_desc& get_frame_format_desc() const { return format_desc_; }\r
+       \r
+       void initialize(const frame_factory_ptr& factory)\r
        {\r
-               frame_ = std::make_shared<system_frame>(format_desc.size);\r
+               frame_ = factory->create_frame(format_desc_);\r
                __stosd(reinterpret_cast<unsigned long*>(frame_->data()), color_value_, frame_->size() / sizeof(unsigned long));\r
        }\r
 \r
-       frame_ptr get_frame() { return frame_; }\r
-       const frame_format_desc& get_frame_format_desc() const { return format_desc_; }\r
-\r
        frame_format_desc format_desc_;\r
-       frame_ptr frame_;\r
+       gpu_frame_ptr frame_;\r
        unsigned long color_value_;\r
 };\r
 \r
index 139606c16728f5785a74bbe106938eb14a5ed90a..381f846d7c6a81ac150108ca9bbcd6993174d309 100644 (file)
@@ -10,7 +10,7 @@ namespace caspar{ namespace ffmpeg{
 \r
 struct audio_decoder::implementation : boost::noncopyable\r
 {\r
-       implementation(const sound_channel_info_ptr& snd_channel_info) : discard_bytes_(0), current_audio_chunk_offset_(0), snd_channel_info_(snd_channel_info)\r
+       implementation() : discard_bytes_(0), current_audio_chunk_offset_(0), current_chunk_(1920*2), current_chunk_data_(reinterpret_cast<char*>(current_chunk_.data()))\r
        {\r
                audio_decomp_buffer_.resize(audio_decoder::AUDIO_DECOMP_BUFFER_SIZE);\r
                int alignment_offset_ = static_cast<unsigned char>(audio_decoder::ALIGNMENT - (reinterpret_cast<size_t>(&audio_decomp_buffer_.front()) % audio_decoder::ALIGNMENT));\r
@@ -41,16 +41,9 @@ struct audio_decoder::implementation : boost::noncopyable
 \r
                while(written_bytes > 0)\r
                {\r
-                       //if we're starting on a new chunk, allocate it\r
-                       if(current_chunk_ == nullptr) \r
-                       {\r
-                               current_chunk_ = std::make_shared<audio_chunk>(audio_packet->audio_frame_size, snd_channel_info_);\r
-                               current_audio_chunk_offset_ = 0;\r
-                       }\r
-\r
                        //either fill what's left of the chunk or copy all written_bytes that are left\r
                        int targetLength = std::min((max_chunk_length - current_audio_chunk_offset_), written_bytes);\r
-                       common::image::copy(current_chunk_->data() + current_audio_chunk_offset_, pDecomp, targetLength);\r
+                       common::image::copy(current_chunk_data_ + current_audio_chunk_offset_, pDecomp, targetLength);\r
                        written_bytes -= targetLength;\r
 \r
                        current_audio_chunk_offset_ += targetLength;\r
@@ -59,12 +52,12 @@ struct audio_decoder::implementation : boost::noncopyable
                        if(current_audio_chunk_offset_ >= max_chunk_length) \r
                        {\r
                                if(max_chunk_length < static_cast<int>(audio_packet->audio_frame_size)) \r
-                                       common::image::clear(current_chunk_->data() + max_chunk_length, audio_packet->audio_frame_size-max_chunk_length);                                       \r
+                                       common::image::clear(current_chunk_data_ + max_chunk_length, audio_packet->audio_frame_size-max_chunk_length);                                  \r
                                else if(audio_packet->audio_frame_size < audio_packet->src_audio_frame_size) \r
                                        discard_bytes_ = audio_packet->src_audio_frame_size-audio_packet->audio_frame_size;\r
-\r
+                               \r
+                               current_audio_chunk_offset_ = 0;\r
                                audio_packet->audio_chunks.push_back(current_chunk_);\r
-                               current_chunk_.reset();\r
                        }\r
                }\r
 \r
@@ -75,12 +68,12 @@ struct audio_decoder::implementation : boost::noncopyable
                \r
        std::vector<unsigned char>                      audio_decomp_buffer_;\r
        unsigned char*                                          aligned_audio_decomp_addr_;\r
-\r
-       audio_chunk_ptr                                         current_chunk_;\r
+       \r
+       std::vector<short>                                      current_chunk_;\r
+       char*                                                           current_chunk_data_;\r
        int                                                                     current_audio_chunk_offset_;\r
-       sound_channel_info_ptr                                  snd_channel_info_;\r
 };\r
 \r
-audio_decoder::audio_decoder(const sound_channel_info_ptr& snd_channel_info) : impl_(new implementation(snd_channel_info)){}\r
+audio_decoder::audio_decoder() : impl_(new implementation()){}\r
 audio_packet_ptr audio_decoder::execute(const audio_packet_ptr& audio_packet){return impl_->execute(audio_packet);}\r
 }}
\ No newline at end of file
index 5cda54d9740316d2ed706a6abf22b4b98a093ea6..67a3811ff11b2c1d0e8ae6e3b9edfc1ed79700cb 100644 (file)
@@ -1,14 +1,13 @@
 #pragma once\r
 \r
 #include "../packet.h"\r
-#include "../../../frame/audio_chunk.h"\r
 \r
 namespace caspar{ namespace ffmpeg     {\r
 \r
 class audio_decoder : boost::noncopyable\r
 {\r
 public:\r
-       audio_decoder(const sound_channel_info_ptr& snd_channel_info);\r
+       audio_decoder();\r
        audio_packet_ptr execute(const audio_packet_ptr& audio_packet);\r
        \r
        /// <summary> The alignment </summary>\r
index 20a0d03988f2d46d64cfd482833b85680bedb2f6..5def640f47db85b694b7ed308c14e6448376fd2c 100644 (file)
@@ -26,7 +26,7 @@ extern "C"
 #include "audio/audio_decoder.h"\r
 #include "video/video_decoder.h"\r
 #include "video/video_deinterlacer.h"\r
-#include "video/video_scaler.h"\r
+#include "video/video_transformer.h"\r
 \r
 #include "../../frame/frame_format.h"\r
 #include "../../../common/utility/find_file.h"\r
@@ -65,26 +65,22 @@ public:
                \r
                static boost::once_flag flag = BOOST_ONCE_INIT;\r
                boost::call_once(av_register_all, flag);        \r
-               \r
-               input_.reset(new input(format_desc));\r
+                               \r
+               input_.reset(new input(format_desc_));\r
                input_->set_loop(std::find(params.begin(), params.end(), L"LOOP") != params.end());\r
                input_->load(common::narrow(filename_));\r
-\r
-               sound_channel_info_ptr snd_channel_info = input_->get_audio_codec_context() != nullptr ? \r
-                               std::make_shared<sound_channel_info>\r
-                               (\r
-                                       input_->get_audio_codec_context()->channels, \r
-                                       input_->get_audio_codec_context()->bits_per_coded_sample, \r
-                                       input_->get_audio_codec_context()->sample_rate\r
-                               ) : nullptr;\r
-               \r
                video_decoder_.reset(new video_decoder());\r
-               video_scaler_.reset(new video_scaler());\r
-               audio_decoder_.reset(new audio_decoder(snd_channel_info));\r
+               video_transformer_.reset(new video_transformer());\r
+               audio_decoder_.reset(new audio_decoder());\r
                has_audio_ = input_->get_audio_codec_context() != nullptr;\r
        }\r
                \r
-       frame_ptr get_frame()\r
+       void initialize(const frame_factory_ptr& factory)\r
+       {\r
+               video_transformer_->initialize(factory);\r
+       }\r
+               \r
+       gpu_frame_ptr get_frame()\r
        {\r
                while(ouput_channel_.empty() && !input_->is_eof())\r
                {                                                                               \r
@@ -95,7 +91,7 @@ public:
                                if(video_packet)\r
                                {\r
                                        video_packet = video_decoder_->execute(video_packet);\r
-                                       auto frame = video_scaler_->execute(video_packet)->frame;\r
+                                       auto frame = video_transformer_->execute(video_packet)->frame;\r
                                        video_frame_channel_.push_back(std::move(frame));       \r
                                }\r
                        }, \r
@@ -104,8 +100,9 @@ public:
                                auto audio_packet = input_->get_audio_packet();\r
                                if(audio_packet)\r
                                {\r
-                                       auto audio_chunks = audio_decoder_->execute(audio_packet);\r
-                                       audio_chunk_channel_.insert(audio_chunk_channel_.end(), audio_packet->audio_chunks.begin(), audio_packet->audio_chunks.end());\r
+                                       audio_decoder_->execute(audio_packet);\r
+                                       for(size_t n = 0; n < audio_packet->audio_chunks.size(); ++n)\r
+                                               audio_chunk_channel_.push_back(std::move(audio_packet->audio_chunks[n]));\r
                                }\r
                        });\r
 \r
@@ -113,17 +110,17 @@ public:
                        {\r
                                if(has_audio_)\r
                                {\r
-                                       video_frame_channel_.front()->audio_data().push_back(audio_chunk_channel_.front());\r
+                                       video_frame_channel_.front()->audio_data() = std::move(audio_chunk_channel_.front());\r
                                        audio_chunk_channel_.pop_front();\r
                                }\r
                                \r
-                               frame_ptr frame = video_frame_channel_.front();\r
+                               gpu_frame_ptr frame = video_frame_channel_.front();\r
                                video_frame_channel_.pop_front();\r
                                ouput_channel_.push(std::move(frame));\r
                        }                               \r
                }\r
 \r
-               frame_ptr frame;\r
+               gpu_frame_ptr frame;\r
                if(!ouput_channel_.empty())\r
                {\r
                        frame = ouput_channel_.front();\r
@@ -137,23 +134,23 @@ public:
        bool has_audio_;\r
 \r
        // Filter 1 : Input\r
-       input_uptr                                              input_;         \r
+       input_uptr                                                      input_;         \r
 \r
        // Filter 2 : Video Decoding and Scaling\r
-       video_decoder_uptr                              video_decoder_;\r
-       video_scaler_uptr                               video_scaler_;\r
-       //std::deque<video_packet_ptr>                                  videoDecodedPacketChannel_;\r
-       std::deque<frame_ptr>                   video_frame_channel_;\r
+       video_decoder_uptr                                      video_decoder_;\r
+       video_transformer_uptr                          video_transformer_;\r
+       //std::deque<video_packet_ptr>          videoDecodedPacketChannel_;\r
+       std::deque<gpu_frame_ptr>                       video_frame_channel_;\r
        \r
        // Filter 3 : Audio Decoding\r
-       audio_decoder_uptr                              audio_decoder_;\r
-       std::deque<audio_chunk_ptr>             audio_chunk_channel_;\r
+       audio_decoder_uptr                                      audio_decoder_;\r
+       std::deque<std::vector<short>>          audio_chunk_channel_;\r
 \r
        // Filter 4 : Merge Video and Audio\r
-       std::queue<frame_ptr>                   ouput_channel_;\r
+       std::queue<gpu_frame_ptr>                       ouput_channel_;\r
        \r
-       std::wstring                                    filename_;\r
-       frame_format_desc                       format_desc_;\r
+       std::wstring                                            filename_;\r
+       frame_format_desc                                       format_desc_;\r
 };\r
 \r
 frame_producer_ptr create_ffmpeg_producer(const  std::vector<std::wstring>& params, const frame_format_desc& format_desc)\r
index 48d9a1c8bff2c4f589f09db3681fde615b407811..6cf6f5b7f7e89583c8896bb2dbd3ae52b3882c66 100644 (file)
@@ -2,7 +2,6 @@
 \r
 #include "input.h"\r
 \r
-#include "../../frame/system_frame.h"\r
 #include "../../frame/frame_format.h"\r
 #include "../../../common/image/image.h"\r
 #include "../../../common/utility/scope_exit.h"\r
@@ -159,7 +158,7 @@ struct input::implementation : boost::noncopyable
                                if (av_read_frame(format_context.get(), packet.get()) >= 0) // NOTE: Packet is only valid until next call of av_read_frame or av_close_input_file\r
                                {\r
                                        if(packet->stream_index == video_s_index_)                              \r
-                                               video_packet_buffer_.push(std::make_shared<video_packet>(packet, std::make_shared<system_frame>(format_desc_.size), format_desc_, video_codec_context_.get(), video_codec_));            // NOTE: video_packet makes a copy of AVPacket\r
+                                               video_packet_buffer_.push(std::make_shared<video_packet>(packet, nullptr, format_desc_, video_codec_context_.get(), video_codec_));              // NOTE: video_packet makes a copy of AVPacket\r
                                        else if(packet->stream_index == audio_s_index_)         \r
                                                audio_packet_buffer_.push(std::make_shared<audio_packet>(packet, audio_codex_context.get(), audio_codec_a, video_frame_rate_));                 \r
                                }\r
index 19462793e5037e0e167bf9b0fe6fa198bbcd0881..b5c431b71b208a62e2a016752455d96d2fdd7e21 100644 (file)
@@ -3,6 +3,7 @@
 #include "packet.h"\r
 \r
 #include <system_error>\r
+#include "../../frame/frame_fwd.h"\r
 \r
 namespace caspar{ namespace ffmpeg{    \r
        \r
@@ -19,6 +20,8 @@ public:
        video_packet_ptr get_video_packet();\r
        audio_packet_ptr get_audio_packet();\r
 \r
+       void initialize(const frame_factory_ptr& factory);\r
+\r
        bool is_eof() const;\r
        void set_loop(bool value);\r
 private:\r
index 2238a848df45a5d88c1bbeb2c65d9bbf343613ba..a2ce499ce612c9185263f4ded76955a21800b63f 100644 (file)
@@ -1,7 +1,7 @@
 #pragma once\r
 \r
-#include "../../frame/audio_chunk.h"\r
-#include "../../frame/frame.h"\r
+#include "../../frame/gpu_frame.h"\r
+#include "../../frame/frame_format.h"\r
 \r
 #include <tbb/scalable_allocator.h>\r
 #include <type_traits>\r
@@ -29,7 +29,7 @@ struct ffmpeg_error: virtual boost::exception, virtual std::exception { };
 \r
 struct video_packet : boost::noncopyable\r
 {\r
-       video_packet(const AVPacketPtr& packet, frame_ptr&& frame, const frame_format_desc& format_desc, AVCodecContext* codec_context, AVCodec* codec) \r
+       video_packet(const AVPacketPtr& packet, gpu_frame_ptr&& frame, const frame_format_desc& format_desc, AVCodecContext* codec_context, AVCodec* codec) \r
                :  size(packet->size), codec_context(codec_context), codec(codec), frame(std::move(frame)), format_desc(format_desc), \r
                        data(static_cast<uint8_t*>(scalable_aligned_malloc(packet->size, 16)))\r
        {\r
@@ -45,7 +45,7 @@ struct video_packet : boost::noncopyable
        const uint8_t* const                    data;\r
        AVCodecContext* const                   codec_context;\r
        const AVCodec* const                    codec;\r
-       const frame_ptr                                 frame;\r
+       gpu_frame_ptr                                           frame;\r
        AVFramePtr                                              decoded_frame;\r
        const frame_format_desc&                format_desc;\r
 };     \r
@@ -86,7 +86,7 @@ struct audio_packet : boost::noncopyable
        const size_t                    size;\r
        const uint8_t* const    data;\r
 \r
-       std::vector<audio_chunk_ptr> audio_chunks;\r
+       std::vector<std::vector<short>> audio_chunks;\r
 };\r
 typedef std::shared_ptr<audio_packet> audio_packet_ptr;\r
 \r
index 09c0dbc4d3d10ecf6216c5450134f6fd5787b272..2f31d04df04a8deb855011b072b0353d663c5085 100644 (file)
@@ -7,18 +7,13 @@ namespace caspar{ namespace ffmpeg{
 struct video_decoder::implementation : boost::noncopyable\r
 {\r
        video_packet_ptr execute(const video_packet_ptr& video_packet)\r
-       {                               \r
-               if(video_packet->codec->id == CODEC_ID_RAWVIDEO) // TODO: doesnt sws_scale do this?\r
-                       common::image::shuffle(video_packet->frame->data(), video_packet->data, video_packet->size, 3, 2, 1, 0);\r
-               else\r
-               {\r
-                       video_packet->decoded_frame.reset(avcodec_alloc_frame(), av_free);\r
-\r
-                       int frame_finished = 0;\r
-                       if((-avcodec_decode_video(video_packet->codec_context, video_packet->decoded_frame.get(), &frame_finished, video_packet->data, video_packet->size)) > 0)                                                \r
-                               video_packet->decoded_frame.reset();                    \r
-               }\r
+       {               \r
+               video_packet->decoded_frame.reset(avcodec_alloc_frame(), av_free);\r
 \r
+               int frame_finished = 0;\r
+               if((-avcodec_decode_video(video_packet->codec_context, video_packet->decoded_frame.get(), &frame_finished, video_packet->data, video_packet->size)) > 0)                                                \r
+                       video_packet->decoded_frame.reset();                    \r
+               \r
                return video_packet;            \r
        }\r
 };\r
diff --git a/core/producer/ffmpeg/video/video_scaler.h b/core/producer/ffmpeg/video/video_scaler.h
deleted file mode 100644 (file)
index 03aa8a7..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma once\r
-\r
-#include "../packet.h"\r
-\r
-namespace caspar{ namespace ffmpeg{\r
-\r
-class video_scaler : boost::noncopyable\r
-{\r
-public:\r
-       video_scaler();\r
-       video_packet_ptr execute(const video_packet_ptr& video_packet);\r
-private:\r
-       struct implementation;\r
-       std::shared_ptr<implementation> impl_;\r
-};\r
-typedef std::shared_ptr<video_scaler> video_scaler_ptr;\r
-typedef std::unique_ptr<video_scaler> video_scaler_uptr;\r
-\r
-}}
\ No newline at end of file
similarity index 74%
rename from core/producer/ffmpeg/video/video_scaler.cpp
rename to core/producer/ffmpeg/video/video_transformer.cpp
index 0222f59b29a7eac4b4d75cd64c917a41a398eac0..d88a7347d29483e2e170b4f9572dc4a0b79c44b8 100644 (file)
@@ -1,9 +1,12 @@
 #include "../../../stdafx.h"\r
 \r
-#include "video_scaler.h"\r
+#include "video_transformer.h"\r
 \r
 #include "../../../frame/frame_format.h"\r
 #include "../../../../common/image/image.h"\r
+#include "../../../frame/gpu_frame.h"\r
+#include "../../../frame/gpu_frame.h"\r
+#include "../../../frame/frame_factory.h"\r
 \r
 #include <tbb/parallel_for.h>\r
 #include <tbb/atomic.h>\r
@@ -42,7 +45,7 @@ struct fill_frame
 };\r
 typedef std::shared_ptr<fill_frame> fill_frame_ptr;\r
 \r
-struct video_scaler::implementation : boost::noncopyable\r
+struct video_transformer::implementation : boost::noncopyable\r
 {\r
        video_packet_ptr execute(const video_packet_ptr video_packet)\r
        {                               \r
@@ -59,14 +62,17 @@ struct video_scaler::implementation : boost::noncopyable
                //avcodec_get_frame_defaults(avFrame);\r
                //avpicture_fill(reinterpret_cast<AVPicture*>(&avFrame), video_packet->frame->data(), PIX_FMT_BGRA, video_packet->frameFormat.width, video_packet->frameFormat.height);\r
                \r
-               fill_frame fill_frame(video_packet->format_desc.width, video_packet->format_desc.height);\r
+               auto format_desc = video_packet->format_desc;\r
+\r
+               fill_frame fill_frame(format_desc.width, format_desc.height);\r
+               video_packet->frame = factory_->create_frame(format_desc.width, format_desc.height);\r
                int result = sws_scale(sws_context_.get(), video_packet->decoded_frame->data, video_packet->decoded_frame->linesize, 0, video_packet->codec_context->height, fill_frame.frame->data, fill_frame.frame->linesize);\r
                video_packet->decoded_frame.reset(); // Free memory\r
                \r
                if(video_packet->codec->id == CODEC_ID_DVVIDEO) // Move up one field\r
                {\r
-                       size_t size = video_packet->format_desc.width * video_packet->format_desc.height * 4;\r
-                       size_t linesize = video_packet->format_desc.width * 4;\r
+                       size_t size = format_desc.width * format_desc.height * 4;\r
+                       size_t linesize = format_desc.width * 4;\r
                        common::image::copy(video_packet->frame->data(), fill_frame.buffer.get() + linesize, size - linesize);\r
                        common::image::clear(video_packet->frame->data() + size - linesize, linesize);\r
                }\r
@@ -79,10 +85,11 @@ struct video_scaler::implementation : boost::noncopyable
                return video_packet;    \r
        }\r
 \r
-private:\r
+       frame_factory_ptr factory_;\r
        SwsContextPtr sws_context_;\r
 };\r
 \r
-video_scaler::video_scaler() : impl_(new implementation()){}\r
-video_packet_ptr video_scaler::execute(const video_packet_ptr& video_packet){return impl_->execute(video_packet);}\r
+video_transformer::video_transformer() : impl_(new implementation()){}\r
+video_packet_ptr video_transformer::execute(const video_packet_ptr& video_packet){return impl_->execute(video_packet);}\r
+void video_transformer::initialize(const frame_factory_ptr& factory){impl_->factory_ = factory; }\r
 }}
\ No newline at end of file
diff --git a/core/producer/ffmpeg/video/video_transformer.h b/core/producer/ffmpeg/video/video_transformer.h
new file mode 100644 (file)
index 0000000..ecbad02
--- /dev/null
@@ -0,0 +1,22 @@
+#pragma once\r
+\r
+#include "../packet.h"\r
+\r
+#include "../../../frame/frame_fwd.h"\r
+\r
+namespace caspar{ namespace ffmpeg{\r
+\r
+class video_transformer : boost::noncopyable\r
+{\r
+public:\r
+       video_transformer();\r
+       video_packet_ptr execute(const video_packet_ptr& video_packet); \r
+       void initialize(const frame_factory_ptr& factory);\r
+private:\r
+       struct implementation;\r
+       std::shared_ptr<implementation> impl_;\r
+};\r
+typedef std::shared_ptr<video_transformer> video_transformer_ptr;\r
+typedef std::unique_ptr<video_transformer> video_transformer_uptr;\r
+\r
+}}
\ No newline at end of file
index c8b0bb162fb7ce561f5795d9158d973519055c62..6eabb597f326b28ef3eeb5d604062a652881df02 100644 (file)
@@ -22,7 +22,6 @@
 \r
 #include "FlashAxContainer.h"\r
 #include "..\..\frame\frame_format.h"\r
-#include "..\..\protocol\monitor\Monitor.h"\r
 #include "flash_producer.h"\r
 #include "TimerHelper.h"\r
 \r
index 2c1119edc02269626fbea005b7f1effff54f137c..e95a7f0ee854accc77f56c1f085618362ff11718 100644 (file)
@@ -35,7 +35,8 @@
 \r
 #pragma warning(push)\r
 \r
-#include "..\..\frame\frame.h"\r
+#include "..\..\frame\gpu_frame.h"\r
+#include "..\..\frame\frame_format.h"\r
 \r
 #include <ocmm.h>\r
 #include <vector>\r
similarity index 52%
rename from core/frame/bitmap_frame.cpp
rename to core/producer/flash/bitmap.cpp
index 3c1ca7b5da1e7d69470c91fc9229a96b0d321e27..dc8b215ca247ebfc68965edfb829ab8cd07043a7 100644 (file)
 *\r
 */\r
  \r
-#include "../StdAfx.h"\r
+#include "../../StdAfx.h"\r
 \r
-#include "bitmap_frame.h"\r
+#include "bitmap.h"\r
 \r
 #include <windows.h>\r
 \r
 namespace caspar{\r
        \r
-class scoped_hdc : boost::noncopyable\r
-{ \r
-public:\r
-       scoped_hdc(HDC hdc) : hdc_(hdc){}\r
-       void operator=(scoped_hdc&& other) \r
-       { \r
-               hdc_ = other.hdc_;\r
-               other.hdc_ = nullptr; \r
-       }\r
-       ~scoped_hdc()\r
-       { \r
-               if(hdc_ != nullptr)\r
-                       DeleteDC(hdc_);\r
-       }\r
-       operator HDC() { return hdc_; }\r
-private:\r
-       HDC hdc_;\r
-};\r
-\r
-class scoped_bitmap : boost::noncopyable\r
-{ \r
-public:\r
-       scoped_bitmap(HBITMAP bmp) : bmp_(bmp){}\r
-       void operator=(scoped_bitmap&& other) \r
-       { \r
-               bmp_ = other.bmp_;\r
-               other.bmp_ = nullptr; \r
-       }\r
-       ~scoped_bitmap() \r
-       { \r
-               if(bmp_ != nullptr) \r
-                       DeleteObject(bmp_);\r
-       }\r
-       operator HBITMAP() const { return bmp_; }\r
-private:\r
-       HBITMAP bmp_;\r
-};\r
-\r
-struct bitmap_frame::implementation : boost::noncopyable\r
+struct bitmap::implementation : boost::noncopyable\r
 {\r
-       implementation(size_t width, size_t height) : size_(width*height*4), hdc_(CreateCompatibleDC(nullptr)), bitmap_(nullptr)\r
+       implementation(size_t width, size_t height) \r
+               : size_(width*height*4), width_(width), height_(height), hdc_(CreateCompatibleDC(nullptr)), bitmap_handle_(nullptr)\r
        {       \r
                if(hdc_ == nullptr)\r
                        throw std::bad_alloc();\r
-\r
+               \r
                BITMAPINFO bitmapInfo;\r
                bitmapInfo.bmiHeader.biBitCount = 32;\r
                bitmapInfo.bmiHeader.biClrImportant = 0;\r
@@ -86,19 +49,31 @@ struct bitmap_frame::implementation : boost::noncopyable
                bitmapInfo.bmiHeader.biXPelsPerMeter = 0;\r
                bitmapInfo.bmiHeader.biYPelsPerMeter = 0;\r
 \r
-               bitmap_ = std::move(CreateDIBSection(hdc_, &bitmapInfo, DIB_RGB_COLORS, reinterpret_cast<void**>(&bitmap_data_), NULL, 0));\r
-               SelectObject(hdc_, bitmap_);    \r
+               bitmap_handle_ = CreateDIBSection(hdc_, &bitmapInfo, DIB_RGB_COLORS, reinterpret_cast<void**>(&bitmap_data_), NULL, 0);\r
+               SelectObject(hdc_, bitmap_handle_);     \r
+       }\r
+       \r
+       ~implementation()\r
+       {\r
+               if(bitmap_handle_ != nullptr) \r
+                       DeleteObject(bitmap_handle_);\r
+               if(hdc_ != nullptr)\r
+                       DeleteDC(hdc_);\r
        }\r
        \r
        const size_t size_;\r
+       const size_t width_;\r
+       const size_t height_;\r
        unsigned char* bitmap_data_;\r
-       scoped_hdc hdc_;\r
-       scoped_bitmap bitmap_;\r
+       HDC hdc_;\r
+       HBITMAP bitmap_handle_;\r
 };\r
 \r
-bitmap_frame::bitmap_frame(size_t width, size_t height) : impl_(new implementation(width, height)){}\r
-unsigned int bitmap_frame::size() const { return impl_->size_; }\r
-unsigned char* bitmap_frame::data() { return impl_->bitmap_data_; }\r
-HDC bitmap_frame::hdc() { return impl_->hdc_; }\r
+bitmap::bitmap(size_t width, size_t height) : impl_(new implementation(width, height)){}\r
+size_t bitmap::size() const { return impl_->size_; }\r
+size_t bitmap::width() const { return impl_->width_; }\r
+size_t bitmap::height() const { return impl_->height_; }\r
+unsigned char* bitmap::data() { return impl_->bitmap_data_; }\r
+HDC bitmap::hdc() { return impl_->hdc_; }\r
 \r
 }
\ No newline at end of file
similarity index 76%
rename from core/frame/bitmap_frame.h
rename to core/producer/flash/bitmap.h
index e6601d10727a8fb2c509daf3abacb7fea8e1f5fd..dfe7b2900e4fb05c234fc0cace5e33165db8b357 100644 (file)
 */\r
 #pragma once\r
 \r
-#include "frame.h"\r
-\r
 #include <memory>\r
 \r
 namespace caspar{\r
 \r
-class bitmap_frame : public frame\r
+class bitmap\r
 {\r
 public:\r
-       bitmap_frame(size_t width, size_t height);\r
+       bitmap(size_t width, size_t height);\r
 \r
        unsigned char* data();\r
-       unsigned int size() const;      \r
+       size_t size() const;    \r
+       size_t width() const;\r
+       size_t height() const;\r
        HDC hdc();\r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
 };\r
-typedef std::shared_ptr<bitmap_frame> bitmap_frame_ptr;\r
-typedef std::unique_ptr<bitmap_frame> bitmap_frame_uptr;\r
+typedef std::shared_ptr<bitmap> bitmap_ptr;\r
+typedef std::unique_ptr<bitmap> bitmap_uptr;\r
 \r
 }\r
 \r
index 94d544d6d40d844235a94f1a764bba681c26a3d1..871647940f596b2471adee639463241122004ba2 100644 (file)
@@ -9,7 +9,7 @@
 \r
 #include "../../renderer/render_device.h"\r
 #include "../../frame/frame_format.h"\r
-#include "../../frame/frame.h"\r
+#include "../../frame/gpu_frame.h"\r
 #include "../../Server.h"\r
 \r
 #include <boost/filesystem.hpp>\r
@@ -153,23 +153,23 @@ struct cg_producer::implementation : boost::noncopyable
 {\r
 public:\r
 \r
-       implementation(const frame_format_desc& fmtDesc, Monitor* pMonitor) : format_desc_(fmtDesc)\r
+       implementation(const frame_format_desc& fmtDesc) : format_desc_(fmtDesc)\r
        {\r
                if(boost::filesystem::exists(server::template_folder()+TEXT("cg.fth.18")))\r
                {\r
-                       flash_producer_ = std::make_shared<flash_producer>(server::template_folder()+TEXT("cg.fth.18"), fmtDesc, pMonitor);\r
+                       flash_producer_ = std::make_shared<flash_producer>(server::template_folder()+TEXT("cg.fth.18"), fmtDesc);\r
                        proxy_.reset(new flash_cg_proxy18());\r
                        CASPAR_LOG(info) << L"Running version 1.8 template graphics.";\r
                }\r
                else if(boost::filesystem::exists(server::template_folder()+TEXT("cg.fth.17")))\r
                {\r
-                       flash_producer_ = std::make_shared<flash_producer>(server::template_folder()+TEXT("cg.fth.17"), fmtDesc, pMonitor);\r
+                       flash_producer_ = std::make_shared<flash_producer>(server::template_folder()+TEXT("cg.fth.17"), fmtDesc);\r
                        proxy_.reset(new flash_cg_proxy17());\r
                        CASPAR_LOG(info) << L"Running version 1.7 template graphics.";\r
                }\r
                else if(boost::filesystem::exists(server::template_folder()+TEXT("cg.fth"))) \r
                {\r
-                       flash_producer_ = std::make_shared<flash_producer>(server::template_folder()+TEXT("cg.fth"), fmtDesc, pMonitor);\r
+                       flash_producer_ = std::make_shared<flash_producer>(server::template_folder()+TEXT("cg.fth"), fmtDesc);\r
                        proxy_.reset(new flash_cg_proxy16());\r
                        CASPAR_LOG(info) << L"Running version 1.6 template graphics.";\r
                }\r
@@ -239,14 +239,23 @@ public:
                flash_producer_->param(proxy_->invoke(layer, label));\r
        }\r
 \r
-       frame_ptr get_frame()\r
+       gpu_frame_ptr get_frame()\r
        {\r
                return flash_producer_ ? flash_producer_->get_frame() : nullptr;\r
        }\r
 \r
+       \r
+       void initialize(const frame_factory_ptr& factory)\r
+       {\r
+               factory_ = factory;\r
+               if(flash_producer_)\r
+                       flash_producer_->initialize(factory_);\r
+       }\r
+\r
        frame_format_desc format_desc_;\r
        flash_producer_ptr flash_producer_;\r
        std::unique_ptr<flash_cg_proxy> proxy_;\r
+       frame_factory_ptr factory_;\r
 };\r
        \r
 \r
@@ -259,15 +268,15 @@ cg_producer_ptr get_default_cg_producer(const renderer::render_device_ptr& prend
        auto pProducer = std::dynamic_pointer_cast<cg_producer>(prender_device->active(exLayer));\r
        if(!pProducer)  \r
        {\r
-               pProducer = std::make_shared<cg_producer>(prender_device->frame_format_desc(), &prender_device->monitor());             \r
+               pProducer = std::make_shared<cg_producer>(prender_device->frame_format_desc());         \r
                prender_device->load(exLayer, pProducer, renderer::load_option::auto_play); \r
        }\r
        \r
        return pProducer;\r
 }\r
 \r
-cg_producer::cg_producer(const frame_format_desc& fmtDesc, Monitor* pMonitor) : impl_(new implementation(fmtDesc, pMonitor)){}\r
-frame_ptr cg_producer::get_frame(){return impl_->get_frame();}\r
+cg_producer::cg_producer(const frame_format_desc& fmtDesc) : impl_(new implementation(fmtDesc)){}\r
+gpu_frame_ptr cg_producer::get_frame(){return impl_->get_frame();}\r
 void cg_producer::clear(){impl_->clear();}\r
 void cg_producer::add(int layer, const std::wstring& templateName,  bool playOnLoad, const std::wstring& startFromLabel, const std::wstring& data){impl_->add(layer, templateName, playOnLoad, startFromLabel, data);}\r
 void cg_producer::remove(int layer){impl_->remove(layer);}\r
@@ -277,4 +286,5 @@ void cg_producer::next(int layer){impl_->next(layer);}
 void cg_producer::update(int layer, const std::wstring& data){impl_->update(layer, data);}\r
 void cg_producer::invoke(int layer, const std::wstring& label){impl_->invoke(layer, label);}\r
 const frame_format_desc& cg_producer::get_frame_format_desc() const { return impl_->format_desc_; }\r
+void cg_producer::initialize(const caspar::frame_factory_ptr& factory){impl_->initialize(factory);}\r
 }}
\ No newline at end of file
index 857181b67b3ad7bc27cb275b59915e10ee6fd677..e4e9b920108a29c83da874197c082b30fd57ba48 100644 (file)
@@ -9,9 +9,9 @@ namespace caspar{ namespace flash{
 class cg_producer : public frame_producer\r
 {\r
 public:\r
-       cg_producer(const frame_format_desc& format_desc, Monitor* pMonitor);\r
+       cg_producer(const frame_format_desc& format_desc);\r
        \r
-       frame_ptr get_frame();\r
+       gpu_frame_ptr get_frame();\r
 \r
        void clear();\r
        void add(int layer, const std::wstring& template_name,  bool play_on_load, const std::wstring& start_from_label = TEXT(""), const std::wstring& data = TEXT(""));\r
@@ -23,6 +23,7 @@ public:
        void invoke(int layer, const std::wstring& label);\r
 \r
        const frame_format_desc& get_frame_format_desc() const;\r
+       void initialize(const caspar::frame_factory_ptr& factory);\r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index b7c519360e5a16227d7643f5014c3151c2b33c95..732954449b82bae300a39f8eb8ddb25d8adcfb36 100644 (file)
@@ -25,7 +25,7 @@
 #include "cg_producer.h"\r
 \r
 #include "../../../common/utility/find_file.h"\r
-#include "../../frame/frame.h"\r
+#include "../../frame/gpu_frame.h"\r
 #include "../../server.h"\r
 \r
 #include <boost/assign/list_of.hpp>\r
@@ -46,7 +46,7 @@ frame_producer_ptr create_ct_producer(const std::vector<std::wstring>& params, c
        while((pos = fixed_filename.find(TEXT('\\'), pos)) != std::wstring::npos) \r
                fixed_filename[pos] = TEXT('/');\r
        \r
-       cg_producer_ptr cg_producer(new cg_producer(format_desc, nullptr));\r
+       cg_producer_ptr cg_producer(new cg_producer(format_desc));\r
        cg_producer->add(0, filename, 1);\r
        return cg_producer;\r
 }\r
index 6b6ef3e670ac594d55503b464d56d60add1314bc..e64ae7ceb8e8f0a224f01a8becb1f54ec57e04a1 100644 (file)
 #include "flash_producer.h"\r
 #include "FlashAxContainer.h"\r
 #include "TimerHelper.h"\r
+#include "bitmap.h"\r
 \r
-#include "../../frame/bitmap_frame.h"\r
 #include "../../frame/frame_format.h"\r
-#include "../../frame/system_frame.h"\r
 #include "../../../common/utility/find_file.h"\r
 #include "../../server.h"\r
 #include "../../../common/concurrency/executor.h"\r
@@ -57,15 +56,15 @@ extern __declspec(selectany) CAtlModule* _pAtlModule = &_AtlModule;
 \r
 struct flash_producer::implementation\r
 {      \r
-       implementation(flash_producer* self, const std::wstring& filename, const frame_format_desc& format_desc, Monitor* monitor\r
-               : flashax_container_(nullptr), filename_(filename), self_(self), format_desc_(format_desc), monitor_(monitor),\r
+       implementation(flash_producer* self, const std::wstring& filename, const frame_format_desc& format_desc) \r
+               : flashax_container_(nullptr), filename_(filename), self_(self), format_desc_(format_desc),\r
                        bitmap_pool_(new bitmap_pool), executor_([=]{run();}), invalid_count_(0)\r
        {       \r
        if(!boost::filesystem::exists(filename))\r
                BOOST_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(common::narrow(filename)));\r
 \r
                frame_buffer_.set_capacity(flash_producer::DEFAULT_BUFFER_SIZE);\r
-               last_frame_ = std::make_shared<bitmap_frame>(format_desc_.width, format_desc_.height);\r
+               last_frame_ = std::make_shared<bitmap>(format_desc_.width, format_desc_.height);\r
 \r
                start();\r
        }\r
@@ -230,63 +229,83 @@ struct flash_producer::implementation
                }\r
        }\r
 \r
-       frame_ptr render_interlace_frame()\r
+       bitmap_ptr render_interlace_frame()\r
        {               \r
-               return copy_frame(render_frame(), render_frame(), format_desc_);\r
+               bitmap_ptr frame1 = render_frame();\r
+               bitmap_ptr frame2 = render_frame();\r
+               common::image::copy(frame1->data(), frame2->data(), frame1->size());\r
+               return frame1;\r
        }\r
        \r
-       frame_ptr render_frame()\r
+       bitmap_ptr render_frame()\r
        {\r
                flashax_container_->Tick();\r
                invalid_count_ = !flashax_container_->InvalidRectangle() ? std::min(2, invalid_count_+1) : 0;\r
                if(current_frame_ == nullptr || invalid_count_ < 2)\r
                {               \r
-                       bitmap_frame_ptr frame;         \r
+                       bitmap_ptr frame;               \r
                        if(!bitmap_pool_->try_pop(frame))                                       \r
                        {       \r
-                               CASPAR_LOG(trace) << "Allocated bitmap_frame";\r
-                               frame = clear_frame(std::make_shared<bitmap_frame>(format_desc_.width, format_desc_.height));                   \r
+                               CASPAR_LOG(trace) << "Allocated bitmap";\r
+                               frame = std::make_shared<bitmap>(format_desc_.width, format_desc_.height);                                      \r
+                               common::image::clear(frame->data(), frame->size());\r
                        }\r
                        flashax_container_->DrawControl(frame->hdc());\r
 \r
                        auto pool = bitmap_pool_;\r
-                       current_frame_.reset(frame.get(), [=](bitmap_frame*)\r
+                       current_frame_.reset(frame.get(), [=](bitmap*)\r
                        {\r
-                               common::function_task::enqueue([=]{pool->try_push(clear_frame(frame));});\r
+                               common::function_task::enqueue([=]\r
+                               {\r
+                                       if(pool->try_push(frame))\r
+                                               common::image::clear(frame->data(), frame->size());\r
+                               });\r
                        });\r
                }       \r
                return current_frame_;\r
        }\r
                \r
-       frame_ptr get_frame()\r
+       gpu_frame_ptr get_frame()\r
        {\r
-               return frame_buffer_.try_pop(last_frame_) || !is_empty_ ? last_frame_ : frame::null();\r
+               if(!frame_buffer_.try_pop(last_frame_) && is_empty_)\r
+                       return gpu_frame::null();\r
+               \r
+               auto frame = factory_->create_frame(format_desc_);\r
+               common::image::copy(frame->data(), last_frame_->data(), last_frame_->size());   \r
+               \r
+               return frame;\r
+       }\r
+\r
+       void initialize(const frame_factory_ptr& factory)\r
+       {\r
+               factory_ = factory;\r
        }\r
        \r
-       typedef tbb::concurrent_bounded_queue<bitmap_frame_ptr> bitmap_pool;\r
+       typedef tbb::concurrent_bounded_queue<bitmap_ptr> bitmap_pool;\r
        std::shared_ptr<bitmap_pool> bitmap_pool_;\r
        frame_format_desc format_desc_;\r
 \r
        CComObject<caspar::flash::FlashAxContainer>* flashax_container_;\r
                \r
-       tbb::concurrent_bounded_queue<frame_ptr> frame_buffer_;\r
-       frame_ptr last_frame_;\r
-       frame_ptr current_frame_;\r
+       tbb::concurrent_bounded_queue<bitmap_ptr> frame_buffer_;\r
+       bitmap_ptr last_frame_;\r
+       bitmap_ptr current_frame_;\r
        \r
        std::wstring filename_;\r
        flash_producer* self_;\r
-       Monitor* monitor_;\r
 \r
        tbb::atomic<bool> is_empty_;\r
        common::executor executor_;\r
        int invalid_count_;\r
+\r
+       frame_factory_ptr factory_;\r
 };\r
 \r
-flash_producer::flash_producer(const std::wstring& filename, const frame_format_desc& format_desc, Monitor* monitor) : impl_(new implementation(this, filename, format_desc, monitor)){}\r
-frame_ptr flash_producer::get_frame(){return impl_->get_frame();}\r
-Monitor* flash_producer::get_monitor(){return impl_->monitor_; }\r
+flash_producer::flash_producer(const std::wstring& filename, const frame_format_desc& format_desc) : impl_(new implementation(this, filename, format_desc)){}\r
+gpu_frame_ptr flash_producer::get_frame(){return impl_->get_frame();}\r
 void flash_producer::param(const std::wstring& param){impl_->param(param);}\r
 const frame_format_desc& flash_producer::get_frame_format_desc() const { return impl_->format_desc_; } \r
+void flash_producer::initialize(const frame_factory_ptr& factory) { impl_->initialize(factory);}\r
 \r
 std::wstring flash_producer::find_template(const std::wstring& template_name)\r
 {\r
index 0a815af5cd7e67980b80c1b27957772c7562b6e1..df10bcc6c9f3547022b686b8cd56e6f0e963e9ce 100644 (file)
@@ -42,9 +42,10 @@ public:
        /// <summary> Timeout for blocking while trying to stop the producer. </summary>\r
        static const int STOP_TIMEOUT = 2000;\r
 \r
-       flash_producer(const std::wstring& filename, const frame_format_desc& format_desc, Monitor* monitor = nullptr);\r
-       frame_ptr get_frame();\r
+       flash_producer(const std::wstring& filename, const frame_format_desc& format_desc);\r
+       gpu_frame_ptr get_frame();\r
        const frame_format_desc& get_frame_format_desc() const;\r
+       void initialize(const frame_factory_ptr& factory);\r
 \r
        void param(const std::wstring& param);\r
        \r
@@ -53,8 +54,6 @@ public:
 private:       \r
        friend class flash::FlashAxContainer;\r
 \r
-       Monitor* get_monitor();\r
-\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
 \r
index bdd4cc12b844e06a79c7c2dff04d8285a1a46d64..b85b516a32cc3c42eb381814fae2e9dcd06b39e4 100644 (file)
 #pragma once\r
 \r
 #include "../frame/frame_fwd.h"\r
+#include "../frame/gpu_frame.h"\r
+#include "../frame/frame_factory.h"\r
 \r
 #include <boost/noncopyable.hpp>\r
 \r
 #include <memory>\r
 \r
 namespace caspar {\r
-\r
-class Monitor;\r
-\r
+       \r
 class frame_producer : boost::noncopyable\r
 {\r
 public:\r
        virtual ~frame_producer(){}     \r
-       virtual frame_ptr get_frame() = 0;\r
+       virtual gpu_frame_ptr get_frame() = 0;\r
        virtual std::shared_ptr<frame_producer> get_following_producer() const { return nullptr; }\r
        virtual void set_leading_producer(const std::shared_ptr<frame_producer>&) {}\r
        virtual const frame_format_desc& get_frame_format_desc() const = 0;\r
+       virtual void initialize(const frame_factory_ptr& factory) = 0;\r
 };\r
 typedef std::shared_ptr<frame_producer> frame_producer_ptr;\r
 \r
index 9513186abd9f26a1a09844c1d0e57184e1f6af2e..0bf56306f5c2a8274d3e77ce64a29a83b566b985 100644 (file)
@@ -4,8 +4,7 @@
 \r
 #include "../../../common/exception/Exceptions.h"\r
 \r
-#include "../../frame/frame.h"\r
-#include "../../frame/system_frame.h"\r
+#include "../../frame/gpu_frame.h"\r
 #include "../../../common/image/image.h"\r
 \r
 #if defined(_MSC_VER)\r
index 17acabe895adc8cfe2fd5546edcb8f37a24bcd7a..4b945ffa4e2dd78c80394697aa9c0c2778c9d2fb 100644 (file)
@@ -3,7 +3,7 @@
 #include "image_producer.h"\r
 #include "image_loader.h"\r
 \r
-#include "../../frame/system_frame.h"\r
+#include "../../frame/frame_factory.h"\r
 #include "../../frame/frame_format.h"\r
 #include "../../server.h"\r
 #include "../../../common/utility/find_file.h"\r
@@ -17,32 +17,30 @@ namespace caspar{ namespace image{
 \r
 struct image_producer : public frame_producer\r
 {\r
-       image_producer(const std::wstring& filename, const frame_format_desc& format_desc) : format_desc_(format_desc)\r
-       {\r
-               auto bitmap = load_image(filename);\r
+       image_producer(const std::wstring& filename, const frame_format_desc& format_desc) : format_desc_(format_desc), filename_(filename)     {}\r
+\r
+       gpu_frame_ptr get_frame(){return frame_;}\r
 \r
-               if(FreeImage_GetWidth(bitmap.get()) != format_desc.width || FreeImage_GetHeight(bitmap.get()) == format_desc.height)\r
+       void initialize(const frame_factory_ptr& factory)\r
+       {\r
+               auto bitmap = load_image(filename_);\r
+               if(FreeImage_GetWidth(bitmap.get()) != format_desc_.width || FreeImage_GetHeight(bitmap.get()) == format_desc_.height)\r
                {\r
-                       bitmap = std::shared_ptr<FIBITMAP>(FreeImage_Rescale(bitmap.get(), format_desc.width, format_desc.width, FILTER_BICUBIC), FreeImage_Unload);\r
+                       bitmap = std::shared_ptr<FIBITMAP>(FreeImage_Rescale(bitmap.get(), format_desc_.width, format_desc_.width, FILTER_BICUBIC), FreeImage_Unload);\r
                        if(!bitmap)\r
                                BOOST_THROW_EXCEPTION(invalid_argument() << msg_info("Unsupported image format."));\r
                }\r
 \r
                FreeImage_FlipVertical(bitmap.get());\r
-\r
-               frame_ = std::make_shared<system_frame>(format_desc.size);\r
+               frame_ = factory->create_frame(format_desc_);\r
                common::image::copy(frame_->data(), FreeImage_GetBits(bitmap.get()), frame_->size());\r
        }\r
 \r
-       frame_ptr get_frame()\r
-       {\r
-               return frame_;\r
-       }\r
-\r
        const frame_format_desc& get_frame_format_desc() const { return format_desc_; } \r
 \r
+       std::wstring filename_;\r
        frame_format_desc format_desc_;\r
-       frame_ptr frame_;\r
+       gpu_frame_ptr frame_;\r
 };\r
 \r
 frame_producer_ptr create_image_producer(const  std::vector<std::wstring>& params, const frame_format_desc& format_desc)\r
index 764432c2af9972133bb7eb260b6d24f26d0d99f8..0bd071cd428ee2701e88bc733f7ceb948f3d549d 100644 (file)
@@ -5,7 +5,7 @@
 #include "image_loader.h"\r
 \r
 #include "../../frame/frame_format.h"\r
-#include "../../frame/system_frame.h"\r
+#include "../../frame/frame_factory.h"\r
 #include "../../server.h"\r
 #include "../../../common/utility/find_file.h"\r
 #include "../../../common/image/image.h"\r
@@ -81,9 +81,9 @@ struct image_scroll_producer : public frame_producer
                        common::image::copy(&image_.get()[i * image_width_ * 4], &pBits[i* width * 4], width * 4);\r
        }\r
 \r
-       frame_ptr render_frame()\r
+       gpu_frame_ptr render_frame()\r
        {\r
-               frame_ptr frame = std::make_shared<system_frame>(format_desc_.size);\r
+               gpu_frame_ptr frame = factory_->create_frame(format_desc_);\r
                common::image::clear(frame->data(), frame->size());\r
 \r
                const int delta_x = direction_ == direction::Left ? speed_ : -speed_;\r
@@ -126,20 +126,27 @@ struct image_scroll_producer : public frame_producer
                return frame;\r
        }\r
 \r
-       frame_ptr render_interlaced_frame()\r
+       gpu_frame_ptr render_interlaced_frame()\r
        {\r
-               frame_ptr next_frame1;\r
-               frame_ptr next_frame2;\r
+               gpu_frame_ptr next_frame1;\r
+               gpu_frame_ptr next_frame2;\r
                tbb::parallel_invoke([&]{ next_frame1 = render_frame(); }, [&]{ next_frame2 = render_frame(); });\r
                \r
-               return copy_frame(next_frame1, next_frame2, format_desc_);\r
+               common::image::copy_field(next_frame1->data(), next_frame2->data(), format_desc_.mode == video_mode::upper ? 1 : 0, format_desc_.width, format_desc_.height);\r
+               return next_frame1;\r
        }\r
        \r
-       frame_ptr get_frame()\r
+       gpu_frame_ptr get_frame()\r
        {\r
                return format_desc_.mode == video_mode::progressive ? render_frame() : render_interlaced_frame();\r
        }\r
 \r
+       \r
+       void initialize(const frame_factory_ptr& factory)\r
+       {\r
+               factory_ = factory;\r
+       }\r
+\r
        const frame_format_desc& get_frame_format_desc() const { return format_desc_; } \r
        \r
        int image_width_;\r
@@ -151,6 +158,8 @@ struct image_scroll_producer : public frame_producer
        tbb::atomic<bool> loop_;\r
        std::shared_ptr<unsigned char> image_;\r
        frame_format_desc format_desc_;\r
+\r
+       frame_factory_ptr factory_;\r
 };\r
 \r
 frame_producer_ptr create_image_scroll_producer(const std::vector<std::wstring>& params, const frame_format_desc& format_desc)\r
index 5ecb7b2e31051af31127255da01b7008b56a38ad..7d71f5f4a3f16b5cb173b8e50ea75c684d76256f 100644 (file)
 #include "transition_producer.h"\r
 \r
 #include "../../frame/frame_format.h"\r
+#include "../../frame/gpu_frame.h"\r
+#include "../../frame/composite_gpu_frame.h"\r
+#include "../../frame/frame_factory.h"\r
 \r
 #include "../../../common/image/image.h"\r
-#include "../../frame/system_frame.h"\r
-#include "../../frame/audio_chunk.h"\r
 #include "../../renderer/render_device.h"\r
 \r
 #include <boost/range/algorithm/copy.hpp>\r
 \r
 namespace caspar{      \r
-       \r
-class empty_producer : public frame_producer\r
-{\r
-public:\r
-       explicit empty_producer(const frame_format_desc& format_desc) \r
-               : format_desc_(format_desc), frame_(clear_frame(std::make_shared<system_frame>(format_desc_.size)))\r
-       {}      \r
-\r
-       frame_ptr get_frame() { return frame_; }\r
-       const frame_format_desc& get_frame_format_desc() const { return format_desc_; }\r
-private:\r
-       frame_format_desc format_desc_;\r
-       frame_ptr frame_;\r
-};\r
 \r
 struct transition_producer::implementation : boost::noncopyable\r
 {\r
        implementation(const frame_producer_ptr& dest, const transition_info& info, const frame_format_desc& format_desc) \r
-               : current_frame_(0), info_(info), border_color_(0), format_desc_(format_desc), \r
-                       empty_(std::make_shared<empty_producer>(format_desc)), source_(empty_), dest_(dest)\r
+               : current_frame_(0), info_(info), border_color_(0), format_desc_(format_desc), dest_(dest)\r
        {\r
                if(!dest)\r
                        BOOST_THROW_EXCEPTION(null_argument() << arg_name_info("dest"));\r
@@ -63,10 +49,10 @@ struct transition_producer::implementation : boost::noncopyable
        \r
        void set_leading_producer(const frame_producer_ptr& producer)\r
        {\r
-               source_ = producer != nullptr ? producer : empty_;\r
+               source_ = producer;\r
        }\r
                \r
-       frame_ptr get_frame()\r
+       gpu_frame_ptr get_frame()\r
        {\r
                if(++current_frame_ >= info_.duration)\r
                        return nullptr;\r
@@ -74,11 +60,16 @@ struct transition_producer::implementation : boost::noncopyable
                return compose(get_producer_frame(dest_), get_producer_frame(source_));\r
        }\r
 \r
-       frame_ptr get_producer_frame(frame_producer_ptr& producer)\r
+       gpu_frame_ptr get_producer_frame(frame_producer_ptr& producer)\r
        {\r
-               assert(producer != nullptr);\r
+               if(producer == nullptr)\r
+               {       \r
+                       auto frame = factory_->create_frame(format_desc_);\r
+                       common::image::clear(frame->data(), frame->size());\r
+                       return frame;\r
+               }\r
 \r
-               frame_ptr frame;\r
+               gpu_frame_ptr frame;\r
                try\r
                {\r
                        frame = producer->get_frame();\r
@@ -99,157 +90,48 @@ struct transition_producer::implementation : boost::noncopyable
                return frame;\r
        }\r
                        \r
-       frame_ptr compose(const frame_ptr& dest_frame, const frame_ptr& src_frame) \r
+       gpu_frame_ptr compose(const gpu_frame_ptr& dest_frame, const gpu_frame_ptr& src_frame) \r
        {               \r
-               frame_ptr result_frame = dest_frame;            \r
-               if(src_frame != nullptr && dest_frame != nullptr)\r
-               {\r
-                       result_frame = std::make_shared<system_frame>(format_desc_.size);\r
-                       tbb::parallel_invoke(\r
-                       [&]\r
-                       {\r
-                               GenerateFrame(result_frame->data(), src_frame->data(), dest_frame->data());\r
-                       },\r
-                       [&]\r
-                       {\r
-                               float delta = static_cast<float>(current_frame_)/static_cast<float>(info_.duration);\r
-                               set_frame_volume(dest_frame, delta*100.0f);\r
-                               set_frame_volume(src_frame, (1.0f-delta)*100.0f);               \r
-\r
-                               boost::range::copy(src_frame->audio_data(), std::back_inserter(result_frame->audio_data()));                            \r
-                               boost::range::copy(dest_frame->audio_data(), std::back_inserter(result_frame->audio_data()));;\r
-                       });\r
-               }\r
-               return result_frame;\r
-       }\r
-       \r
-       void GenerateFrame(unsigned char* pResultData, const unsigned char* pSourceData, const unsigned char* pDestData)\r
-       {\r
-               if(info_.type == transition_type::cut)\r
-               {\r
-                       common::image::copy(pResultData, pSourceData, format_desc_.size);\r
-                       return;\r
-               }\r
-\r
-               if(current_frame_ >= info_.duration)                    \r
-               {\r
-                       common::image::copy(pResultData, pDestData, format_desc_.size);\r
-                       return;\r
-               }\r
-\r
+               if(info_.type == transition_type::cut)          \r
+                       return src_frame;\r
+               \r
+               int volume = static_cast<int>(static_cast<float>(current_frame_)/static_cast<float>(info_.duration)*256.0f);\r
+                               \r
+               for(size_t n = 0; n < dest_frame->audio_data().size(); ++n)\r
+                       dest_frame->audio_data()[n] = static_cast<short>((static_cast<int>(dest_frame->audio_data()[n])*volume)>>8);\r
+\r
+               for(size_t n = 0; n < src_frame->audio_data().size(); ++n)\r
+                       src_frame->audio_data()[n] = static_cast<short>((static_cast<int>(src_frame->audio_data()[n])*(256-volume))>>8);\r
+                               \r
+               float alpha = static_cast<float>(current_frame_)/static_cast<float>(info_.duration);\r
+               auto composite = std::make_shared<composite_gpu_frame>(format_desc_.width, format_desc_.height);\r
+               composite->add(src_frame);\r
+               composite->add(dest_frame);\r
                if(info_.type == transition_type::mix)\r
                {\r
-                       common::image::lerp(pResultData, pSourceData, pDestData, 1.0f-static_cast<float>(current_frame_)/static_cast<float>(info_.duration), format_desc_.size);\r
-                       return;\r
+                       src_frame->alpha(1.0f-alpha);\r
+                       dest_frame->alpha(alpha);\r
                }\r
-\r
-               size_t totalWidth = format_desc_.width + info_.border_width;\r
-                       \r
-               float fStep   = totalWidth / static_cast<float>(info_.duration);\r
-               float fOffset = fStep * static_cast<float>(current_frame_);\r
-\r
-               size_t halfStep = static_cast<size_t>(fStep/2.0);\r
-               size_t offset   = static_cast<size_t>(fOffset+0.5f);\r
-                       \r
-               //read source to buffer\r
-               for(size_t row = 0, even = 0; row < format_desc_.height; ++row, even ^= 1)\r
+               else if(info_.type == transition_type::slide)\r
                {\r
-                       size_t fieldCorrectedOffset = offset + (halfStep*even);\r
-                       if(fieldCorrectedOffset < format_desc_.width)\r
-                       {\r
-                               if(info_.direction != transition_direction::from_left)\r
-                               {\r
-                                       if(info_.type == transition_type::push)\r
-                                               memcpy(&(pResultData[4*row*format_desc_.width]), &(pSourceData[4*(row*format_desc_.width+fieldCorrectedOffset)]), (format_desc_.width-fieldCorrectedOffset)*4);\r
-                                       else    //Slide | Wipe\r
-                                               memcpy(&(pResultData[4*row*format_desc_.width]), &(pSourceData[4*row*format_desc_.width]), (format_desc_.width-fieldCorrectedOffset)*4);\r
-                               }\r
-                               else // if (direction == LEFT)\r
-                               {                               \r
-                                       if(info_.type == transition_type::push)\r
-                                               memcpy(&(pResultData[4*(row*format_desc_.width+fieldCorrectedOffset)]), &(pSourceData[4*(row*format_desc_.width)]), (format_desc_.width-fieldCorrectedOffset)*4);\r
-                                       else    //slide eller wipe\r
-                                               memcpy(&(pResultData[4*(row*format_desc_.width+fieldCorrectedOffset)]), &(pSourceData[4*(row*format_desc_.width+fieldCorrectedOffset)]), (format_desc_.width-fieldCorrectedOffset)*4);\r
-                               }\r
-                       }\r
+                       dest_frame->translate(-1.0f+alpha, 0.0f);\r
                }\r
-\r
-               //write border to buffer\r
-               if(info_.border_width > 0)\r
+               else if(info_.type == transition_type::push)\r
                {\r
-                       for(size_t row = 0, even = 0; row < format_desc_.height; ++row, even ^= 1)\r
-                       {\r
-                               size_t fieldCorrectedOffset = offset + (halfStep*even);\r
-                               size_t length = info_.border_width;\r
-                               size_t start = 0;\r
-\r
-                               if(info_.direction != transition_direction::from_left)\r
-                               {\r
-                                       if(fieldCorrectedOffset > format_desc_.width)\r
-                                       {\r
-                                               length -= fieldCorrectedOffset-format_desc_.width;\r
-                                               start += fieldCorrectedOffset-format_desc_.width;\r
-                                               fieldCorrectedOffset = format_desc_.width;\r
-                                       }\r
-                                       else if(fieldCorrectedOffset < length)\r
-                                       {\r
-                                               length = fieldCorrectedOffset;\r
-                                       }\r
-\r
-                                       for(size_t i = 0; i < length; ++i)\r
-                                               memcpy(&(pResultData[4*(row*format_desc_.width+format_desc_.width-fieldCorrectedOffset+i)]), &border_color_, 4);\r
-                                               \r
-                               }\r
-                               else // if (direction == LEFT)\r
-                               {\r
-                                       if(fieldCorrectedOffset > format_desc_.width)\r
-                                       {\r
-                                               length -= fieldCorrectedOffset-format_desc_.width;\r
-                                               start = 0;\r
-                                               fieldCorrectedOffset -= info_.border_width-length;\r
-                                       }\r
-                                       else if(fieldCorrectedOffset < length)\r
-                                       {\r
-                                               length = fieldCorrectedOffset;\r
-                                               start = info_.border_width-fieldCorrectedOffset;\r
-                                       }\r
-\r
-                                       for(size_t i = 0; i < length; ++i)\r
-                                               memcpy(&(pResultData[4*(row*format_desc_.width+fieldCorrectedOffset-length+i)]), &border_color_, 4);                                            \r
-                               }\r
-\r
-                       }\r
-               }\r
-\r
-               //read dest to buffer\r
-               offset -= info_.border_width;\r
-               if(offset > 0)\r
-               {\r
-                       for(size_t row = 0, even = 0; row < format_desc_.height; ++row, even ^= 1)\r
-                       {\r
-                               int fieldCorrectedOffset = offset + (halfStep*even);\r
-\r
-                               if(info_.direction != transition_direction::from_left)\r
-                               {\r
-                                       if(info_.type == transition_type::wipe)\r
-                                               memcpy(&(pResultData[4*(row*format_desc_.width+format_desc_.width-fieldCorrectedOffset)]), &(pDestData[4*(row*format_desc_.width+format_desc_.width-fieldCorrectedOffset)]), fieldCorrectedOffset*4);\r
-                                       else\r
-                                               memcpy(&(pResultData[4*(row*format_desc_.width+format_desc_.width-fieldCorrectedOffset)]), &(pDestData[4*row*format_desc_.width]), fieldCorrectedOffset*4);\r
-                               }\r
-                               else // if (direction == LEFT)\r
-                               {                               \r
-                                       if(info_.type == transition_type::wipe)\r
-                                               memcpy(&(pResultData[4*(row*format_desc_.width)]), &(pDestData[4*(row*format_desc_.width)]), fieldCorrectedOffset*4);\r
-                                       else\r
-                                               memcpy(&(pResultData[4*(row*format_desc_.width)]), &(pDestData[4*(row*format_desc_.width+format_desc_.width-fieldCorrectedOffset)]), fieldCorrectedOffset*4);   \r
-                               }\r
-                       }\r
+                       dest_frame->translate(-1.0f+alpha, 0.0f);\r
+                       src_frame->translate(alpha, 0.0f);\r
                }\r
+               return composite;\r
+       }\r
+               \r
+       void initialize(const frame_factory_ptr& factory)\r
+       {\r
+               dest_->initialize(factory);\r
+               factory_ = factory;\r
        }\r
 \r
        const frame_format_desc format_desc_;\r
 \r
-       frame_producer_ptr              empty_;\r
        frame_producer_ptr              source_;\r
        frame_producer_ptr              dest_;\r
        \r
@@ -257,13 +139,16 @@ struct transition_producer::implementation : boost::noncopyable
        \r
        const transition_info   info_;\r
        const unsigned long             border_color_;\r
+       frame_factory_ptr               factory_;\r
 };\r
 \r
 transition_producer::transition_producer(const frame_producer_ptr& dest, const transition_info& info, const frame_format_desc& format_desc) \r
        : impl_(new implementation(dest, info, format_desc)){}\r
-frame_ptr transition_producer::get_frame(){return impl_->get_frame();}\r
+gpu_frame_ptr transition_producer::get_frame(){return impl_->get_frame();}\r
 frame_producer_ptr transition_producer::get_following_producer() const{return impl_->get_following_producer();}\r
 void transition_producer::set_leading_producer(const frame_producer_ptr& producer) { impl_->set_leading_producer(producer); }\r
 const frame_format_desc& transition_producer::get_frame_format_desc() const { return impl_->format_desc_; } \r
+void transition_producer::initialize(const frame_factory_ptr& factory) { impl_->initialize(factory);}\r
+\r
+}\r
 \r
-}
\ No newline at end of file
index 6acd3ae7a19834c27e706ee71e823e8fde7cbe97..f49617465c4a7153ff8197bbd869277963356966 100644 (file)
@@ -60,11 +60,12 @@ class transition_producer : public frame_producer
 public:\r
        transition_producer(const frame_producer_ptr& destination, const transition_info& info, const frame_format_desc& fmt);\r
 \r
-       frame_ptr get_frame();\r
+       gpu_frame_ptr get_frame();\r
 \r
        frame_producer_ptr get_following_producer() const;\r
        void set_leading_producer(const frame_producer_ptr& producer);\r
        const frame_format_desc& get_frame_format_desc() const;\r
+       virtual void initialize(const frame_factory_ptr& factory);\r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index d95c8dd1c5528a546ddcea2930fd330ddbb4bb1e..ba6b620d45d34dac961d70c8265852c3c6ec4c36 100644 (file)
@@ -27,7 +27,6 @@
 #include "../../producer/flash/flash_producer.h"\r
 #include "../../producer/transition/transition_producer.h"\r
 #include <boost/lexical_cast.hpp>\r
-#include "../monitor/Monitor.h"\r
 #include "../../producer/flash/cg_producer.h"\r
 #include "../media.h"\r
 #include "../../Server.h"\r
@@ -179,7 +178,6 @@ bool LoadCommand::DoExecute()
 \r
                SetReplyString(TEXT("202 LOAD OK\r\n"));\r
 \r
-               GetChannel()->monitor().Inform(LOAD, _parameters[0]);\r
                return true;\r
        }\r
        catch(file_not_found&)\r
@@ -273,7 +271,6 @@ bool LoadbgCommand::DoExecute()
                CASPAR_LOG(info) << "Loaded " << _parameters[0] << TEXT(" successfully to background");\r
                SetReplyString(TEXT("202 LOADBG OK\r\n"));\r
 \r
-               GetChannel()->monitor().Inform(LOADBG, _parameters[0]);\r
                return true;\r
        }\r
        catch(file_not_found&)\r
@@ -327,7 +324,6 @@ bool ClearCommand::DoExecute()
        GetChannel()->clear(GetLayerIndex());\r
        SetReplyString(TEXT("202 CLEAR OK\r\n"));\r
 \r
-       GetChannel()->monitor().Inform(CLEAR);\r
        return true;\r
 }\r
 \r
@@ -454,8 +450,6 @@ bool CGCommand::DoExecuteAdd() {
 \r
                flash::get_default_cg_producer(GetChannel(), GetLayerIndex(flash::CG_DEFAULT_LAYER))->add(layer, filename, bDoStart, label, (pDataString!=0) ? pDataString : TEXT(""));\r
                SetReplyString(TEXT("202 CG OK\r\n"));\r
-\r
-               GetChannel()->monitor().Inform(CG_ADD, _parameters[2]);\r
        }\r
        else\r
        {\r
@@ -557,7 +551,6 @@ bool CGCommand::DoExecuteClear()
 {\r
        flash::get_default_cg_producer(GetChannel(), GetLayerIndex(flash::CG_DEFAULT_LAYER))->clear();\r
        SetReplyString(TEXT("202 CG OK\r\n"));\r
-       GetChannel()->monitor().Inform(CG_CLEAR);\r
        return true;\r
 }\r
 \r
@@ -837,23 +830,6 @@ bool SetCommand::DoExecute()
        return true;\r
 }\r
 \r
-bool MonitorCommand::DoExecute()\r
-{\r
-       std::wstring cmd = _parameters[0];\r
-\r
-       if(cmd == TEXT("START")) {\r
-               GetChannel()->monitor().AddListener(GetClientInfo());\r
-               SetReplyString(TEXT("202 MONITOR START OK\r\n"));\r
-       }\r
-       else if(cmd == TEXT("STOP")) {\r
-               GetChannel()->monitor().RemoveListener(GetClientInfo());\r
-               SetReplyString(TEXT("202 MONITOR STOP OK\r\n"));\r
-       }\r
-       else\r
-               SetReplyString(TEXT("403 MONITOR ERROR\r\n"));\r
-\r
-       return true;\r
-}\r
 \r
 }      //namespace amcp\r
 }      //namespace caspar
\ No newline at end of file
index 677e7be7bee9353cbae854a977b722b198d3b20e..4aef6a0a0eefb4615d53f5c49b396fa0a75c7346 100644 (file)
@@ -118,11 +118,6 @@ class SetCommand : public AMCPCommandBase<true, AddToQueue, 2>
        bool DoExecute();\r
 };\r
 \r
-class MonitorCommand : public AMCPCommandBase<true, AddToQueue, 1>\r
-{\r
-       bool DoExecute();\r
-};\r
-\r
 //class KillCommand : public AMCPCommand\r
 //{\r
 //public:\r
index ab5b36f780421bc29ef96e6f640010c10900bce4..74057b713fb1209164c37ecab0293015c64cf3e2 100644 (file)
@@ -4,7 +4,6 @@
 \r
 #include "../producer/frame_producer.h"\r
 \r
-#include "../frame/system_frame.h"\r
 #include "../frame/frame_format.h"\r
 \r
 namespace caspar { namespace renderer {\r
@@ -58,12 +57,12 @@ struct layer::implementation
                background_ = nullptr;\r
        }\r
        \r
-       frame_ptr get_frame()\r
+       gpu_frame_ptr get_frame()\r
        {               \r
                if(!active_)\r
                        return preview_frame_;\r
 \r
-               frame_ptr frame;\r
+               gpu_frame_ptr frame;\r
                try\r
                {\r
                        frame = active_->get_frame();\r
@@ -83,7 +82,7 @@ struct layer::implementation
                return frame;\r
        }       \r
                        \r
-       frame_ptr preview_frame_;\r
+       gpu_frame_ptr preview_frame_;\r
        frame_producer_ptr active_;\r
        frame_producer_ptr background_;\r
 };\r
@@ -107,7 +106,7 @@ void layer::load(const frame_producer_ptr& frame_producer, load_option option){r
 void layer::play(){impl_->play();}\r
 void layer::stop(){impl_->stop();}\r
 void layer::clear(){impl_->clear();}\r
-frame_ptr layer::get_frame() {return impl_->get_frame();}\r
+gpu_frame_ptr layer::get_frame() {return impl_->get_frame();}\r
 frame_producer_ptr layer::active() const { return impl_->active_;}\r
 frame_producer_ptr layer::background() const { return impl_->background_;}\r
 }}
\ No newline at end of file
index a770ceff56a4770c2ff2cd87cf1140146ef45e20..866d8326e649c2a55d6fd3c014acc976a762c5d8 100644 (file)
@@ -28,7 +28,7 @@ public:
        frame_producer_ptr active() const;\r
        frame_producer_ptr background() const;\r
 \r
-       frame_ptr get_frame();\r
+       gpu_frame_ptr get_frame();\r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index dcecc613b3b20bd91d5b31551f0a7fc7dcf3eabe..b5550936df9d719aebfda49125d49f287c3c2e7f 100644 (file)
@@ -3,11 +3,10 @@
 #include "render_device.h"\r
 #include "layer.h"\r
 \r
-#include "../protocol/monitor/Monitor.h"\r
 #include "../consumer/frame_consumer.h"\r
 \r
-#include "../frame/system_frame.h"\r
 #include "../frame/frame_format.h"\r
+#include "../frame/gpu_frame_processor.h"\r
 \r
 #include "../../common/utility/scope_exit.h"\r
 #include "../../common/image/image.h"\r
@@ -30,9 +29,9 @@ using namespace boost::assign;
        \r
 namespace caspar{ namespace renderer{\r
        \r
-std::vector<frame_ptr> render_frames(std::map<int, layer>& layers)\r
+std::vector<gpu_frame_ptr> render_frames(std::map<int, layer>& layers)\r
 {      \r
-       std::vector<frame_ptr> frames(layers.size(), nullptr);\r
+       std::vector<gpu_frame_ptr> frames(layers.size(), nullptr);\r
        tbb::parallel_for(tbb::blocked_range<size_t>(0, frames.size()), [&](const tbb::blocked_range<size_t>& r)\r
        {\r
                auto it = layers.begin();\r
@@ -40,15 +39,13 @@ std::vector<frame_ptr> render_frames(std::map<int, layer>& layers)
                for(size_t i = r.begin(); i != r.end(); ++i, ++it)\r
                        frames[i] = it->second.get_frame();\r
        });                                     \r
-       boost::range::remove_erase(frames, nullptr);\r
-       boost::range::remove_erase_if(frames, [](const frame_const_ptr& frame) { return *frame == *frame::null();});\r
        return frames;\r
 }\r
 \r
 struct render_device::implementation : boost::noncopyable\r
 {      \r
        implementation(const caspar::frame_format_desc& format_desc, unsigned int index, const std::vector<frame_consumer_ptr>& consumers)  \r
-               : consumers_(consumers), monitor_(index), fmt_(format_desc)\r
+               : consumers_(consumers), fmt_(format_desc), frame_processor_(new gpu_frame_processor(format_desc))\r
        {       \r
                is_running_ = true;\r
                if(consumers.empty())\r
@@ -80,23 +77,19 @@ struct render_device::implementation : boost::noncopyable
                CASPAR_LOG(info) << L"Started render_device::render Thread";\r
                win32_exception::install_handler();\r
                \r
-               std::vector<frame_ptr> current_frames;\r
-\r
                while(is_running_)\r
                {\r
                        try\r
                        {       \r
-                               std::vector<frame_ptr> next_frames;\r
-                               frame_ptr composite_frame;              \r
+                               std::vector<gpu_frame_ptr> next_frames;\r
+                               gpu_frame_ptr composite_frame;          \r
 \r
                                {\r
                                        tbb::mutex::scoped_lock lock(layers_mutex_);    \r
-                                       tbb::parallel_invoke(\r
-                                               [&]{next_frames = render_frames(layers_);}, \r
-                                               [&]{composite_frame = compose_frames(current_frames.empty() ? std::make_shared<system_frame>(fmt_.size) : current_frames[0], current_frames);});\r
+                                       next_frames = render_frames(layers_);\r
                                }\r
-\r
-                               current_frames = std::move(next_frames);                \r
+                               frame_processor_->push(next_frames);\r
+                               frame_processor_->pop(composite_frame); \r
                                frame_buffer_.push(std::move(composite_frame));\r
                        }\r
                        catch(...)\r
@@ -115,8 +108,9 @@ struct render_device::implementation : boost::noncopyable
                CASPAR_LOG(info) << L"Started render_device::display Thread";\r
                win32_exception::install_handler();\r
                                \r
-               frame_ptr frame = clear_frame(std::make_shared<system_frame>(fmt_.size));\r
-               std::deque<frame_ptr> prepared(3, frame);\r
+               gpu_frame_ptr frame = frame_processor_->create_frame(fmt_.width, fmt_.height);\r
+               common::image::clear(frame->data(), frame->size());\r
+               std::deque<gpu_frame_ptr> prepared(3, frame);\r
                                \r
                while(is_running_)\r
                {\r
@@ -136,14 +130,14 @@ struct render_device::implementation : boost::noncopyable
                CASPAR_LOG(info) << L"Ended render_device::display Thread";\r
        }\r
 \r
-       void send_frame(const frame_ptr& pPreparedFrame, const frame_ptr& pNextFrame)\r
+       void send_frame(const gpu_frame_ptr& prepared_frame, const gpu_frame_ptr& next_frame)\r
        {\r
                BOOST_FOREACH(const frame_consumer_ptr& consumer, consumers_)\r
                {\r
                        try\r
                        {\r
-                               consumer->prepare(pNextFrame); // Could block\r
-                               consumer->display(pPreparedFrame); // Could block\r
+                               consumer->prepare(next_frame); // Could block\r
+                               consumer->display(prepared_frame); // Could block\r
                        }\r
                        catch(...)\r
                        {\r
@@ -164,6 +158,7 @@ struct render_device::implementation : boost::noncopyable
                if(producer->get_frame_format_desc() != fmt_)\r
                        BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("pProducer") << msg_info("Invalid frame format"));\r
 \r
+               producer->initialize(frame_processor_);\r
                tbb::mutex::scoped_lock lock(layers_mutex_);\r
                layers_[exLayer].load(producer, option);\r
        }\r
@@ -216,7 +211,7 @@ struct render_device::implementation : boost::noncopyable
        boost::thread display_thread_;\r
                \r
        caspar::frame_format_desc fmt_;\r
-       tbb::concurrent_bounded_queue<frame_ptr> frame_buffer_;\r
+       tbb::concurrent_bounded_queue<gpu_frame_ptr> frame_buffer_;\r
        \r
        std::vector<frame_consumer_ptr> consumers_;\r
        \r
@@ -225,7 +220,7 @@ struct render_device::implementation : boost::noncopyable
        \r
        tbb::atomic<bool> is_running_;  \r
 \r
-       caspar::Monitor monitor_;\r
+       gpu_frame_processor_ptr frame_processor_;\r
 };\r
 \r
 render_device::render_device(const caspar::frame_format_desc& format_desc, unsigned int index, const std::vector<frame_consumer_ptr>& consumers) \r
@@ -238,6 +233,5 @@ void render_device::clear(){impl_->clear();}
 frame_producer_ptr render_device::active(int exLayer) const {return impl_->active(exLayer);}\r
 frame_producer_ptr render_device::background(int exLayer) const {return impl_->background(exLayer);}\r
 const frame_format_desc& render_device::frame_format_desc() const{return impl_->fmt_;}\r
-caspar::Monitor& render_device::monitor(){return impl_->monitor_;}\r
 }}\r
 \r
index 60c78644ebef8c78c020109a78ed82d173c75343..4f7fff016032a04d26dca1702924e959652714ce 100644 (file)
@@ -25,8 +25,7 @@ public:
        frame_producer_ptr active(int exLayer) const;\r
        frame_producer_ptr background(int exLayer) const;\r
 \r
-       const frame_format_desc& frame_format_desc() const;                     \r
-       Monitor& monitor();\r
+       const frame_format_desc& frame_format_desc() const;             \r
 private:\r
        struct implementation;\r
        std::shared_ptr<implementation> impl_;\r
index e0d4dcc9f1332a5aedeeacc5cfc4de87b7d124f2..7312db42f67649cb4a1332f0eb4b946dd1b8adae 100644 (file)
@@ -15,7 +15,6 @@
 #include "protocol/cii/CIIProtocolStrategy.h"\r
 #include "protocol/CLK/CLKProtocolStrategy.h"\r
 #include "producer/flash/FlashAxContainer.h"\r
-#include "protocol/monitor/Monitor.h"\r
 \r
 #include "../common/io/AsyncEventServer.h"\r
 #include "../common/io/SerialPort.h"\r
@@ -138,7 +137,6 @@ struct server::implementation : boost::noncopyable
                                        unsigned int port = xml_controller.second.get<unsigned int>("port");\r
                                        port = port != 0 ? port : 5250;\r
                                        auto asyncserver = std::make_shared<caspar::IO::AsyncEventServer>(create_protocol(protocol), port);\r
-                                       asyncserver->SetClientDisconnectHandler(std::tr1::bind(&Monitor::ClearListener, std::tr1::placeholders::_1));\r
                                        asyncserver->Start();\r
                                        async_servers_.push_back(asyncserver);\r
                                }\r