<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>\r
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
<RuntimeTypeInfo>true</RuntimeTypeInfo>\r
- <WholeProgramOptimization>false</WholeProgramOptimization>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
<TreatWarningAsError>true</TreatWarningAsError>\r
</ClCompile>\r
<Link>\r
/// \brief Channel. \r
/// \r
/// |**********| <- empty frame <- |***********| <- frame format <- |**********|\r
-/// CONTROLLER -> | PRODUCER | | PROCESSOR | | CONSUMER | -> DISPLAY DEVICE\r
-/// |**********| -> rendered frames -> |***********| -> processed frame -> |**********|\r
+/// PROTOCOL -> | PRODUCER | | PROCESSOR | | CONSUMER | -> DISPLAY DEVICE\r
+/// |**********| -> rendered frames -> |***********| -> formatted frame -> |**********|\r
/// \r
////////////////////////////////////////////////////////////////////////////////////////////////////\r
class channel : boost::noncopyable\r
*/\r
#pragma once\r
\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "../../consumer/frame_consumer.h"\r
\r
namespace caspar { namespace core { namespace bluefish {\r
#include <Windows.h>\r
\r
#include <BlueVelvet4.h>\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "exception.h"\r
\r
namespace caspar { namespace core { namespace bluefish {\r
#pragma once\r
\r
#include <BlueVelvet4.h>\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
\r
#include <memory>\r
\r
#include "DecklinkVideoConsumer.h"\r
#include "DeckLinkAPI_h.h"\r
\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "../../../common/utility/memory.h"\r
\r
#include "../../producer/frame_producer_device.h"\r
\r
#include "../../consumer/frame_consumer.h"\r
\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
\r
namespace caspar { namespace core { namespace decklink {\r
\r
*/\r
#pragma once\r
\r
-#include "../video/video_format.h"\r
+#include "../format/video_format.h"\r
#include "../processor/frame.h"\r
\r
#include <boost/noncopyable.hpp>\r
\r
#include "frame_consumer_device.h"\r
\r
-#include "../video/video_format.h"\r
+#include "../format/video_format.h"\r
#include "../processor/frame.h"\r
#include "../processor/frame_processor_device.h"\r
\r
clock.synchronize();\r
\r
frame_ptr frame;\r
- while(frame == nullptr && !frame_processor_->try_receive(frame))\r
- {\r
- if(frame != nullptr)\r
- CASPAR_LOG(trace) << "Display Buffer Underrun.";\r
+ while(frame == nullptr && is_running_) \r
frame_processor_->receive(frame);\r
- } \r
+ \r
display_frame(frame); \r
}\r
\r
#include "oal_consumer.h"\r
\r
#include "../../processor/frame.h"\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
\r
#include <SFML/Audio.hpp>\r
\r
\r
#include "ogl_consumer.h"\r
\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "../../processor/frame.h"\r
#include "../../../common/utility/memory.h"\r
#include "../../../common/gl/utility.h"\r
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<PreprocessorDefinitions>NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
- <WholeProgramOptimization>false</WholeProgramOptimization>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
<TreatWarningAsError>true</TreatWarningAsError>\r
</ClCompile>\r
<PreLinkEvent>\r
<ClInclude Include="consumer\frame_consumer.h" />\r
<ClInclude Include="consumer\oal\oal_consumer.h" />\r
<ClInclude Include="consumer\ogl\ogl_consumer.h" />\r
+ <ClInclude Include="format\pixel_format.h" />\r
+ <ClInclude Include="format\video_format.h" />\r
<ClInclude Include="processor\composite_frame.h" />\r
<ClInclude Include="processor\frame.h" />\r
<ClInclude Include="processor\frame_processor_device.h" />\r
<ClInclude Include="protocol\clk\CLKProtocolStrategy.h" />\r
<ClInclude Include="protocol\media.h" />\r
<ClInclude Include="server.h" />\r
- <ClInclude Include="video\pixel_format.h" />\r
- <ClInclude Include="video\video_format.h" />\r
<CustomBuildStep Include="consumers\bluefish\BluefishException.h" />\r
<CustomBuildStep Include="consumers\bluefish\BluefishFrameManager.h" />\r
<CustomBuildStep Include="consumers\bluefish\BluefishPlaybackStrategy.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="format\video_format.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="processor\composite_frame.cpp">\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>\r
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>\r
</ClCompile>\r
- <ClCompile Include="video\video_format.cpp">\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- <PrecompiledHeaderFile Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">../StdAfx.h</PrecompiledHeaderFile>\r
- </ClCompile>\r
</ItemGroup>\r
<ItemGroup>\r
<Midl Include="consumer\decklink\DeckLinkAPI.idl">\r
<Filter Include="Source">\r
<UniqueIdentifier>{0361bd88-1d96-4d86-b3ad-34d40e2319c6}</UniqueIdentifier>\r
</Filter>\r
+ <Filter Include="Source\protocol">\r
+ <UniqueIdentifier>{57f477cb-9cff-4216-aab7-50b06df51f20}</UniqueIdentifier>\r
+ </Filter>\r
+ <Filter Include="Source\protocol\cii">\r
+ <UniqueIdentifier>{a94bc00a-4753-4bce-a777-6a3ea2ceca59}</UniqueIdentifier>\r
+ </Filter>\r
+ <Filter Include="Source\protocol\amcp">\r
+ <UniqueIdentifier>{d33e8ddc-ccb4-4f4f-ad20-e788a796bb7b}</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="My Amplifier Results">\r
+ <UniqueIdentifier>{bb801cd9-8dc8-4300-a5c7-a7f5ee0805fb}</UniqueIdentifier>\r
+ </Filter>\r
<Filter Include="Source\consumer">\r
<UniqueIdentifier>{35d7835f-f813-4b4b-8d8d-8a35dfef68d3}</UniqueIdentifier>\r
</Filter>\r
<Filter Include="Source\consumer\decklink\interop">\r
<UniqueIdentifier>{a5cb89d7-dbbb-4fca-b899-f53a069727b4}</UniqueIdentifier>\r
</Filter>\r
+ <Filter Include="Source\format">\r
+ <UniqueIdentifier>{f19ced4f-4ad2-4c0a-b51f-50e89909d669}</UniqueIdentifier>\r
+ </Filter>\r
+ <Filter Include="Source\processor">\r
+ <UniqueIdentifier>{53e41831-70b4-4214-bc38-77e0d7aa288b}</UniqueIdentifier>\r
+ </Filter>\r
+ <Filter Include="Source\processor\renderer">\r
+ <UniqueIdentifier>{30fe40ca-8bf0-4a46-a882-16d07b2b441e}</UniqueIdentifier>\r
+ </Filter>\r
<Filter Include="Source\producer">\r
<UniqueIdentifier>{71accefc-1437-4e1d-9ff7-9de654a32df9}</UniqueIdentifier>\r
</Filter>\r
<Filter Include="Source\producer\ffmpeg">\r
<UniqueIdentifier>{671d13be-c7e1-4f65-9909-03b7c8adcbde}</UniqueIdentifier>\r
</Filter>\r
+ <Filter Include="Source\producer\ffmpeg\video">\r
+ <UniqueIdentifier>{a6d6bcc9-7ef1-47a3-9800-76e71f2b3f62}</UniqueIdentifier>\r
+ </Filter>\r
+ <Filter Include="Source\producer\ffmpeg\audio">\r
+ <UniqueIdentifier>{4031dc0c-88e9-46b5-b279-955639dca8b7}</UniqueIdentifier>\r
+ </Filter>\r
<Filter Include="Source\producer\color">\r
<UniqueIdentifier>{78b16c14-bf29-4511-9122-684ff513dbf5}</UniqueIdentifier>\r
</Filter>\r
<Filter Include="Source\producer\flash">\r
<UniqueIdentifier>{fc25232a-cab1-4c79-962a-b51dc51161fb}</UniqueIdentifier>\r
</Filter>\r
- <Filter Include="Source\producer\image">\r
- <UniqueIdentifier>{3d4314f3-8a39-44e3-a0c9-9b833bb8f809}</UniqueIdentifier>\r
- </Filter>\r
- <Filter Include="Source\producer\ffmpeg\video">\r
- <UniqueIdentifier>{a6d6bcc9-7ef1-47a3-9800-76e71f2b3f62}</UniqueIdentifier>\r
- </Filter>\r
- <Filter Include="Source\producer\ffmpeg\audio">\r
- <UniqueIdentifier>{4031dc0c-88e9-46b5-b279-955639dca8b7}</UniqueIdentifier>\r
- </Filter>\r
<Filter Include="Source\producer\flash\interop">\r
<UniqueIdentifier>{f99e4727-2b1b-4009-a445-99b11b071e8e}</UniqueIdentifier>\r
</Filter>\r
- <Filter Include="Source\protocol">\r
- <UniqueIdentifier>{57f477cb-9cff-4216-aab7-50b06df51f20}</UniqueIdentifier>\r
- </Filter>\r
- <Filter Include="Source\protocol\cii">\r
- <UniqueIdentifier>{a94bc00a-4753-4bce-a777-6a3ea2ceca59}</UniqueIdentifier>\r
- </Filter>\r
- <Filter Include="Source\protocol\amcp">\r
- <UniqueIdentifier>{d33e8ddc-ccb4-4f4f-ad20-e788a796bb7b}</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="My Amplifier Results">\r
- <UniqueIdentifier>{bb801cd9-8dc8-4300-a5c7-a7f5ee0805fb}</UniqueIdentifier>\r
- </Filter>\r
- <Filter Include="Source\video">\r
- <UniqueIdentifier>{f19ced4f-4ad2-4c0a-b51f-50e89909d669}</UniqueIdentifier>\r
- </Filter>\r
- <Filter Include="Source\processor">\r
- <UniqueIdentifier>{53e41831-70b4-4214-bc38-77e0d7aa288b}</UniqueIdentifier>\r
- </Filter>\r
- <Filter Include="Source\processor\renderer">\r
- <UniqueIdentifier>{30fe40ca-8bf0-4a46-a882-16d07b2b441e}</UniqueIdentifier>\r
+ <Filter Include="Source\producer\image">\r
+ <UniqueIdentifier>{3d4314f3-8a39-44e3-a0c9-9b833bb8f809}</UniqueIdentifier>\r
</Filter>\r
</ItemGroup>\r
<ItemGroup>\r
<ClInclude Include="producer\layer.h">\r
<Filter>Source\producer</Filter>\r
</ClInclude>\r
- <ClInclude Include="video\pixel_format.h">\r
- <Filter>Source\video</Filter>\r
- </ClInclude>\r
- <ClInclude Include="video\video_format.h">\r
- <Filter>Source\video</Filter>\r
- </ClInclude>\r
<ClInclude Include="consumer\frame_consumer_device.h">\r
<Filter>Source\consumer</Filter>\r
</ClInclude>\r
<ClInclude Include="server.h">\r
<Filter>Source</Filter>\r
</ClInclude>\r
- <ClInclude Include="channel.h">\r
- <Filter>Source</Filter>\r
- </ClInclude>\r
<ClInclude Include="processor\frame_processor_device.h">\r
<Filter>Source\processor</Filter>\r
</ClInclude>\r
<ClInclude Include="processor\frame_renderer.h">\r
<Filter>Source\processor\renderer</Filter>\r
</ClInclude>\r
+ <ClInclude Include="format\pixel_format.h">\r
+ <Filter>Source\format</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="format\video_format.h">\r
+ <Filter>Source\format</Filter>\r
+ </ClInclude>\r
+ <ClInclude Include="channel.h">\r
+ <Filter>Source</Filter>\r
+ </ClInclude>\r
</ItemGroup>\r
<ItemGroup>\r
<ClCompile Include="StdAfx.cpp">\r
<ClCompile Include="producer\layer.cpp">\r
<Filter>Source\producer</Filter>\r
</ClCompile>\r
- <ClCompile Include="video\video_format.cpp">\r
- <Filter>Source\video</Filter>\r
- </ClCompile>\r
<ClCompile Include="consumer\frame_consumer_device.cpp">\r
<Filter>Source\consumer</Filter>\r
</ClCompile>\r
<ClCompile Include="processor\frame_shader.cpp">\r
<Filter>Source\processor\renderer</Filter>\r
</ClCompile>\r
+ <ClCompile Include="format\video_format.cpp">\r
+ <Filter>Source\format</Filter>\r
+ </ClCompile>\r
<ClCompile Include="channel.cpp">\r
<Filter>Source</Filter>\r
</ClCompile>\r
--- /dev/null
+#pragma once\r
+\r
+#include <memory>\r
+#include <array>\r
+\r
+namespace caspar { namespace core {\r
+ \r
+struct pixel_format\r
+{\r
+ enum type\r
+ {\r
+ bgra,\r
+ rgba,\r
+ argb,\r
+ abgr,\r
+ ycbcr,\r
+ ycbcra,\r
+ count,\r
+ invalid\r
+ };\r
+};\r
+\r
+struct pixel_format_desc\r
+{\r
+ struct plane\r
+ {\r
+ plane() : linesize(0), width(0), height(0), size(0), channels(0){}\r
+ plane(size_t width, size_t height, size_t channels)\r
+ : linesize(width*channels), width(width), height(height), size(width*height*channels), channels(channels)\r
+ {}\r
+ size_t linesize;\r
+ size_t width;\r
+ size_t height;\r
+ size_t size;\r
+ size_t channels;\r
+ };\r
+\r
+ pixel_format_desc() : pix_fmt(pixel_format::invalid)\r
+ {\r
+ std::fill(planes.begin(), planes.end(), plane());\r
+ }\r
+\r
+ pixel_format::type pix_fmt;\r
+\r
+ std::array<plane, 4> planes;\r
+};\r
+ \r
+}}
\ No newline at end of file
--- /dev/null
+/*\r
+* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
+*\r
+* This file is part of CasparCG.\r
+*\r
+* CasparCG is free software: you can redistribute it and/or modify\r
+* it under the terms of the GNU General Public License as published by\r
+* the Free Software Foundation, either version 3 of the License, or\r
+* (at your option) any later version.\r
+*\r
+* CasparCG is distributed in the hope that it will be useful,\r
+* but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+* GNU General Public License for more details.\r
+\r
+* You should have received a copy of the GNU General Public License\r
+* along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r
+*\r
+*/\r
+ \r
+#include "..\StdAfx.h"\r
+\r
+#include "video_format.h"\r
+\r
+#include <boost/algorithm/string.hpp>\r
+\r
+#define DEFINE_VIDEOFORMATDESC(w, h, m, f, s, fmt) { (fmt), (w), (h), (m), (f), (w)*(h)*4, (s) }\r
+\r
+namespace caspar { namespace core {\r
+\r
+const video_format_desc video_format_desc::format_descs[video_format::count] = \r
+{ \r
+ DEFINE_VIDEOFORMATDESC(720, 576, video_update_format::upper, 50, TEXT("PAL"), video_format::pal ), \r
+ DEFINE_VIDEOFORMATDESC(720, 486, video_update_format::lower, 60/1.001, TEXT("NTSC"), video_format::ntsc ), \r
+ DEFINE_VIDEOFORMATDESC(720, 576, video_update_format::progressive, 25, TEXT("576p2500"), video_format::x576p2500 ),\r
+ DEFINE_VIDEOFORMATDESC(1280, 720, video_update_format::progressive, 25, TEXT("720p2500"), video_format::x720p2500 ), \r
+ DEFINE_VIDEOFORMATDESC(1280, 720, video_update_format::progressive, 50, TEXT("720p5000"), video_format::x720p5000 ), \r
+ DEFINE_VIDEOFORMATDESC(1280, 720, video_update_format::progressive, 60/1.001, TEXT("720p5994"), video_format::x720p5994 ),\r
+ DEFINE_VIDEOFORMATDESC(1280, 720, video_update_format::progressive, 60, TEXT("720p6000"), video_format::x720p6000 ),\r
+ DEFINE_VIDEOFORMATDESC(1920, 1080, video_update_format::progressive, 24/1.001, TEXT("1080p2397"), video_format::x1080p2397),\r
+ DEFINE_VIDEOFORMATDESC(1920, 1080, video_update_format::progressive, 24, TEXT("1080p2400"), video_format::x1080p2400),\r
+ DEFINE_VIDEOFORMATDESC(1920, 1080, video_update_format::upper, 50, TEXT("1080i5000"), video_format::x1080i5000),\r
+ DEFINE_VIDEOFORMATDESC(1920, 1080, video_update_format::upper, 60/1.001, TEXT("1080i5994"), video_format::x1080i5994),\r
+ DEFINE_VIDEOFORMATDESC(1920, 1080, video_update_format::upper, 60, TEXT("1080i6000"), video_format::x1080i6000),\r
+ DEFINE_VIDEOFORMATDESC(1920, 1080, video_update_format::progressive, 25, TEXT("1080p2500"), video_format::x1080p2500),\r
+ DEFINE_VIDEOFORMATDESC(1920, 1080, video_update_format::progressive, 30/1.001, TEXT("1080p2997"), video_format::x1080p2997),\r
+ DEFINE_VIDEOFORMATDESC(1920, 1080, video_update_format:: progressive, 30, TEXT("1080p3000"), video_format::x1080p3000)\r
+};\r
+\r
+video_format::type get_video_format(const std::wstring& name)\r
+{\r
+ for(int n = 0; n < video_format::count; ++n)\r
+ {\r
+ if(boost::iequals(video_format_desc::format_descs[n].name, name))\r
+ return static_cast<video_format::type>(n);\r
+ }\r
+\r
+ return video_format::invalid;\r
+}\r
+\r
+}}\r
+\r
--- /dev/null
+#pragma once\r
+\r
+#include <string>\r
+\r
+#include "../../common/compiler/vs/disable_silly_warnings.h"\r
+\r
+namespace caspar { namespace core {\r
+ \r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/// \enum video_format\r
+///\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+struct video_format \r
+{ \r
+ enum type\r
+ {\r
+ pal = 0,\r
+ ntsc,\r
+ x576p2500,\r
+ x720p2500,\r
+ x720p5000,\r
+ x720p5994,\r
+ x720p6000,\r
+ x1080p2397,\r
+ x1080p2400,\r
+ x1080i5000,\r
+ x1080i5994,\r
+ x1080i6000,\r
+ x1080p2500,\r
+ x1080p2997,\r
+ x1080p3000,\r
+ count,\r
+ invalid\r
+ };\r
+};\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/// \enum video_update_format\r
+///\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+struct video_update_format \r
+{ \r
+ enum type\r
+ {\r
+ progressive,\r
+ lower,\r
+ upper,\r
+ count,\r
+ invalid\r
+ };\r
+};\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/// \struct video_format_desc\r
+///\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+struct video_format_desc\r
+{\r
+ video_format::type format;\r
+\r
+ size_t width;\r
+ size_t height;\r
+ video_update_format::type update;\r
+ double fps;\r
+ size_t size;\r
+ std::wstring name;\r
+\r
+ static const video_format_desc format_descs[video_format::count];\r
+};\r
+\r
+inline bool operator==(const video_format_desc& rhs, const video_format_desc& lhs)\r
+{\r
+ return rhs.format == lhs.format;\r
+}\r
+\r
+inline bool operator!=(const video_format_desc& rhs, const video_format_desc& lhs)\r
+{\r
+ return !(rhs == lhs);\r
+}\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/// \fn video_format get_video_format(const std::wstring& strVideoMode);\r
+///\r
+/// \brief Gets the *video_format* associated with the specified name.\r
+///\r
+/// \param name Name of the *video_format*.. \r
+///\r
+/// \return The video format. \r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+video_format::type get_video_format(const std::wstring& name);\r
+\r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+/// \fn video_format get_video_format_desc(const std::wstring& strVideoMode);\r
+///\r
+/// \brief Gets the *video_format_desc* associated with the specified name.\r
+///\r
+/// \param name Name of the *video_format_desc*.. \r
+///\r
+/// \return The video format. \r
+////////////////////////////////////////////////////////////////////////////////////////////////////\r
+inline video_format_desc get_video_format_desc(const std::wstring& name, video_format::type default_format = video_format::x576p2500)\r
+{ \r
+ auto casparVideoFormat = default_format;\r
+ if(!name.empty())\r
+ casparVideoFormat = get_video_format(name);\r
+ return video_format_desc::format_descs[casparVideoFormat];\r
+}\r
+\r
+inline double render_video_format_period(const video_format_desc& format_desc)\r
+{\r
+ return 1.0/(format_desc.update == video_update_format::progressive ? format_desc.fps : format_desc.fps/2.0);\r
+}\r
+\r
+inline std::wostream& operator<<(std::wostream& out, const video_format_desc& format_desc)\r
+{\r
+ out << format_desc.name.c_str();\r
+ return out;\r
+}\r
+\r
+}}
\ No newline at end of file
#include "../StdAfx.h"\r
\r
#include "frame.h"\r
-#include "../video/pixel_format.h"\r
+#include "../format/pixel_format.h"\r
#include "../../common/utility/memory.h"\r
#include "../../common/gl/utility.h"\r
#include "../../common/gl/pixel_buffer_object.h"\r
\r
#include "frame_shader.h"\r
\r
-#include "../video/video_format.h"\r
-#include "../video/pixel_format.h"\r
+#include "../format/video_format.h"\r
+#include "../format/pixel_format.h"\r
\r
#include <memory>\r
#include <array>\r
#include "frame.h"\r
#include "composite_frame.h"\r
\r
-#include "../video/video_format.h"\r
+#include "../format/video_format.h"\r
\r
#include "../../common/exception/exceptions.h"\r
#include "../../common/concurrency/executor.h"\r
struct frame_processor_device::implementation : boost::noncopyable\r
{ \r
implementation(frame_processor_device* self, const video_format_desc& format_desc) \r
- : fmt_(format_desc)\r
+ : fmt_(format_desc), underrun_count_(0)\r
{ \r
boost::promise<frame_ptr> promise;\r
active_frame_ = promise.get_future();\r
\r
void send(const frame_ptr& input_frame)\r
{ \r
- input_.push(input_frame);\r
+ input_.push(input_frame); // Block if there are too many frames in pipeline\r
executor_.begin_invoke([=]\r
{\r
try\r
{\r
frame_ptr output_frame;\r
input_.pop(output_frame);\r
- output_.push(renderer_->render(output_frame));\r
+ if(output_frame != nullptr)\r
+ output_.push(renderer_->render(output_frame));\r
}\r
catch(...)\r
{\r
\r
void receive(frame_ptr& output_frame)\r
{\r
- output_.pop(output_frame);\r
+ if(!output_.try_pop(output_frame))\r
+ {\r
+ if(underrun_count_ == 0) \r
+ CASPAR_LOG(trace) << "Frame Processor Underrun has STARTED.";\r
+ \r
+ ++underrun_count_;\r
+ output_.pop(output_frame);\r
+ } \r
+ else if(underrun_count_ > 0)\r
+ {\r
+ CASPAR_LOG(trace) << "Frame Processor Underrun has ENDED with " << underrun_count_ << " ticks.";\r
+ underrun_count_ = 0;\r
+ }\r
}\r
\r
- bool try_receive(frame_ptr& output_frame)\r
- {\r
- return output_.try_pop(output_frame);\r
- }\r
- \r
video_format_desc fmt_;\r
\r
typedef tbb::concurrent_bounded_queue<frame_ptr> frame_queue;\r
frame_queue output_; \r
\r
frame_renderer_ptr renderer_;\r
+\r
+ long underrun_count_;\r
};\r
\r
#if defined(_MSC_VER)\r
void frame_processor_device::release_tag(void* tag){impl_->release_tag(tag);}\r
void frame_processor_device::send(const frame_ptr& frame){impl_->send(frame);}\r
void frame_processor_device::receive(frame_ptr& frame){impl_->receive(frame);}\r
-bool frame_processor_device::try_receive(frame_ptr& frame){return impl_->try_receive(frame);}\r
const video_format_desc frame_processor_device::get_video_format_desc() const { return impl_->fmt_;}\r
frame_ptr frame_processor_device::create_frame(size_t width, size_t height, void* tag)\r
{\r
#include <memory>\r
#include <vector>\r
\r
-#include "../video/video_format.h"\r
+#include "../format/video_format.h"\r
#include "../processor/frame.h"\r
#include "../consumer/frame_consumer_device.h"\r
\r
\r
void send(const frame_ptr& frame);\r
void receive(frame_ptr& frame);\r
- bool try_receive(frame_ptr& frame);\r
\r
frame_ptr create_frame(const pixel_format_desc& desc, void* tag); \r
frame_ptr create_frame(size_t width, size_t height, void* tag); \r
\r
#include "../processor/frame.h"\r
\r
-#include "../video/video_format.h"\r
+#include "../format/video_format.h"\r
#include "../processor/frame_processor_device.h"\r
\r
#include "../../common/exception/exceptions.h"\r
\r
#include "frame_processor_device.h"\r
\r
-#include "../video/video_format.h"\r
+#include "../format/video_format.h"\r
\r
#include <boost/noncopyable.hpp>\r
\r
#pragma once\r
\r
-#include "../video/video_format.h"\r
-#include "../video/pixel_format.h"\r
+#include "../format/video_format.h"\r
+#include "../format/pixel_format.h"\r
\r
#include <memory>\r
#include <array>\r
\r
#include "color_producer.h"\r
\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
\r
#include <intrin.h>\r
#pragma intrinsic(__movsd, __stosd)\r
static const int SAMPLE_RATE = 48000;\r
\r
implementation(AVCodecContext* codec_context) \r
- : current_chunk_(), codec_context_(codec_context), audio_buffer_(4*SAMPLE_RATE*2+FF_INPUT_BUFFER_PADDING_SIZE/2){}\r
+ : current_chunk_(), codec_context_(codec_context), audio_resample_buffer_(4*SAMPLE_RATE*2+FF_INPUT_BUFFER_PADDING_SIZE/2),\r
+ audio_buffer_(4*SAMPLE_RATE*2+FF_INPUT_BUFFER_PADDING_SIZE/2)/*, resample_context_(nullptr)*/\r
+ {\r
+ //if(codec_context_->sample_rate != SAMPLE_RATE)\r
+ //{\r
+ // resample_context_ = av_audio_resample_init \r
+ // (\r
+ // 2, \r
+ // codec_context_->channels,\r
+ // SAMPLE_RATE, // out rate\r
+ // codec_context_->sample_rate, // in rate\r
+ // SAMPLE_FMT_S16,\r
+ // codec_context_->sample_fmt,\r
+ // 16, 10, 0, 1.0\r
+ // ); \r
+ //}\r
+ }\r
+\r
+ ~implementation()\r
+ {\r
+ //if(resample_context_ != nullptr)\r
+ // audio_resample_close(resample_context_);\r
+ }\r
\r
std::vector<std::vector<short>> execute(const aligned_buffer& audio_packet)\r
{ \r
- static std::vector<std::vector<short>> silence(1920*2, 0);\r
-\r
- if(codec_context_->sample_rate != SAMPLE_RATE)\r
- return silence;\r
-\r
+ static const std::vector<std::vector<short>> silence(1920*2, 0);\r
+ \r
int written_bytes = audio_buffer_.size()*2 - FF_INPUT_BUFFER_PADDING_SIZE;\r
- int result = avcodec_decode_audio2\r
- (\r
- codec_context_, \r
- audio_buffer_.data(), \r
- &written_bytes, \r
- audio_packet.data(),\r
- audio_packet.size()\r
- );\r
+ const int result = avcodec_decode_audio2(codec_context_, audio_buffer_.data(), &written_bytes, audio_packet.data(), audio_packet.size());\r
\r
if(result <= 0)\r
return silence;\r
-\r
- std::vector<std::vector<short>> chunks_;\r
- \r
- current_chunk_.insert(current_chunk_.end(), audio_buffer_.data(), audio_buffer_.data() + written_bytes/2);\r
- while(current_chunk_.size() >= FRAME_AUDIO_SAMPLES)\r
+ \r
+ if(codec_context_->sample_rate != SAMPLE_RATE)\r
{\r
- auto first = std::make_move_iterator(current_chunk_.begin());\r
- auto last = std::make_move_iterator(current_chunk_.begin() + FRAME_AUDIO_SAMPLES);\r
+ //if(resample_context_ == nullptr)\r
+ return silence;\r
+ \r
+ //int samples_output = audio_resample\r
+ // ( \r
+ // resample_context_,\r
+ // audio_resample_buffer_.data(),\r
+ // audio_buffer_.data(),\r
+ // written_bytes/2 // in samples\r
+ // );\r
+\r
+ //if(samples_output == -1)\r
+ //{ \r
+ // CASPAR_LOG(trace) << "Resampling error";\r
+ // audio_resample_close(resample_context_);\r
+ // resample_context_ = nullptr;\r
+ //}\r
\r
- chunks_.push_back(std::vector<short>(first, last));\r
- current_chunk_ = std::vector<short>(current_chunk_.begin() + FRAME_AUDIO_SAMPLES, current_chunk_.end());\r
+ //current_chunk_.insert(current_chunk_.end(), audio_resample_buffer_.data(), audio_resample_buffer_.data() + samples_output);\r
}\r
+ else\r
+ current_chunk_.insert(current_chunk_.end(), audio_buffer_.data(), audio_buffer_.data() + written_bytes/2);\r
+\r
+ std::vector<std::vector<short>> chunks_;\r
+ \r
+ const auto last = current_chunk_.end() - current_chunk_.size() % FRAME_AUDIO_SAMPLES;\r
+\r
+ for(auto it = current_chunk_.begin(); it != last; it += FRAME_AUDIO_SAMPLES) \r
+ chunks_.push_back(std::vector<short>(it, it + FRAME_AUDIO_SAMPLES)); \r
+\r
+ current_chunk_.erase(current_chunk_.begin(), last);\r
\r
return chunks_;\r
}\r
- \r
- std::vector<short, tbb::cache_aligned_allocator<short>> audio_buffer_; \r
- std::vector<short> current_chunk_;\r
\r
- AVCodecContext* codec_context_;\r
+ //ReSampleContext* resample_context_;\r
+ \r
+ typedef std::vector<short, tbb::cache_aligned_allocator<short>> buffer;\r
+\r
+ buffer audio_buffer_; \r
+ buffer audio_resample_buffer_;\r
+\r
+ std::deque<short, tbb::cache_aligned_allocator<short>> current_chunk_;\r
+\r
+ std::vector<short, tbb::cache_aligned_allocator<short>> current_resample_chunk_;\r
+\r
+ AVCodecContext* codec_context_;\r
};\r
\r
audio_decoder::audio_decoder(AVCodecContext* codec_context) : impl_(new implementation(codec_context)){}\r
#include "video/video_decoder.h"\r
#include "video/video_transformer.h"\r
\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "../../../common/utility/find_file.h"\r
#include "../../../common/utility/memory.h"\r
#include "../../../common/utility/scope_exit.h"\r
{\r
public:\r
ffmpeg_producer(const std::wstring& filename, const std::vector<std::wstring>& params) \r
- : filename_(filename)\r
+ : filename_(filename), underrun_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
- static boost::once_flag flag = BOOST_ONCE_INIT;\r
- boost::call_once(av_register_all, flag); \r
+ static boost::once_flag av_register_all_flag = BOOST_ONCE_INIT;\r
+ boost::call_once(av_register_all, av_register_all_flag); \r
+ \r
+ static boost::once_flag avcodec_init_flag = BOOST_ONCE_INIT;\r
+ boost::call_once(avcodec_init, avcodec_init_flag); \r
\r
input_.reset(new input());\r
input_->set_loop(std::find(params.begin(), params.end(), L"LOOP") != params.end());\r
frame_ptr render_frame()\r
{\r
while(ouput_channel_.empty() && !input_->is_eof())\r
- { \r
+ { \r
+ auto video_packet = input_->get_video_packet(); \r
+ auto audio_packet = input_->get_audio_packet(); \r
tbb::parallel_invoke(\r
[&]\r
{ // Video Decoding and Scaling\r
- auto video_packet = input_->get_video_packet();\r
if(!video_packet.empty())\r
{\r
auto decoded_frame = video_decoder_->execute(video_packet);\r
}, \r
[&] \r
{ // Audio Decoding\r
- auto audio_packet = input_->get_audio_packet();\r
if(!audio_packet.empty())\r
{\r
auto chunks = audio_decoder_->execute(audio_packet);\r
}\r
});\r
\r
+ if(video_packet.empty() && audio_packet.empty())\r
+ {\r
+ if(underrun_count_ == 0)\r
+ CASPAR_LOG(warning) << "File read underflow has STARTED.";\r
+ ++underrun_count_;\r
+ }\r
+ else if(underrun_count_ > 0)\r
+ {\r
+ CASPAR_LOG(trace) << "File Read Underrun has ENDED with " << underrun_count_ << " ticks.";\r
+ underrun_count_ = 0;\r
+ }\r
+\r
while(!video_frame_channel_.empty() && (!audio_chunk_channel_.empty() || !has_audio_))\r
{\r
- if(has_audio_)\r
+ if(has_audio_ && video_frame_channel_.front() != nullptr)\r
{\r
video_frame_channel_.front()->audio_data() = std::move(audio_chunk_channel_.front());\r
audio_chunk_channel_.pop_front();\r
\r
bool has_audio_;\r
\r
- // Filter 1 : Input\r
input_uptr input_; \r
\r
- // Filter 2 : Video Decoding and Scaling\r
video_decoder_uptr video_decoder_;\r
video_transformer_uptr video_transformer_;\r
- //std::deque<video_packet_ptr> videoDecodedPacketChannel_;\r
- std::deque<frame_ptr> video_frame_channel_;\r
+ std::deque<frame_ptr> video_frame_channel_;\r
\r
- // Filter 3 : Audio Decoding\r
audio_decoder_ptr 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<frame_ptr> ouput_channel_;\r
\r
std::wstring filename_;\r
+\r
+ long underrun_count_;\r
};\r
\r
frame_producer_ptr create_ffmpeg_producer(const std::vector<std::wstring>& params)\r
\r
#include "input.h"\r
\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "../../../common/utility/memory.h"\r
#include "../../../common/utility/scope_exit.h"\r
\r
\r
struct input::implementation : boost::noncopyable\r
{\r
- implementation() \r
- : video_frame_rate_(25.0), video_s_index_(-1), audio_s_index_(-1), video_codec_(nullptr), audio_codec_(nullptr)\r
+ implementation() : video_s_index_(-1), audio_s_index_(-1), video_codec_(nullptr), audio_codec_(nullptr)\r
{\r
loop_ = false;\r
//file_buffer_size_ = 0; \r
- video_packet_buffer_.set_capacity(25);\r
- audio_packet_buffer_.set_capacity(25);\r
+ video_packet_buffer_.set_capacity(50);\r
+ audio_packet_buffer_.set_capacity(50);\r
}\r
\r
~implementation()\r
CASPAR_LOG(warning) << "No audio stream found.";\r
\r
if(!video_codec_context_ && !audio_codex_context_)\r
- BOOST_THROW_EXCEPTION(file_read_error() << msg_info("No video or audio codec found."));\r
- \r
- video_frame_rate_ = static_cast<double>(video_codec_context_->time_base.den) / static_cast<double>(video_codec_context_->time_base.num); \r
+ BOOST_THROW_EXCEPTION(file_read_error() << msg_info("No video or audio codec found.")); \r
}\r
catch(...)\r
{\r
video_codec_context_.reset();\r
audio_codex_context_.reset();\r
format_context_.reset();\r
- video_frame_rate_ = 25.0;\r
video_s_index_ = -1;\r
audio_s_index_ = -1; \r
throw;\r
if(packet->stream_index == video_s_index_) \r
{\r
video_packet_buffer_.push(std::make_shared<aligned_buffer>(packet->data, packet->data + packet->size)); \r
+ packet_wait_cond_.notify_all();\r
//file_buffer_size_ += packet->size;\r
}\r
else if(packet->stream_index == audio_s_index_) \r
{\r
- audio_packet_buffer_.push(std::make_shared<aligned_buffer>(packet->data, packet->data + packet->size)); \r
+ audio_packet_buffer_.push(std::make_shared<aligned_buffer>(packet->data, packet->data + packet->size)); \r
+ packet_wait_cond_.notify_all(); \r
//file_buffer_size_ += packet->size;\r
}\r
}\r
{\r
return !is_running_ && video_packet_buffer_.empty() && audio_packet_buffer_.empty();\r
}\r
+\r
+ void wait_for_packet()\r
+ {\r
+ boost::unique_lock<boost::mutex> lock(packet_wait_mutex_);\r
+ while(is_running_ && video_packet_buffer_.empty() && audio_packet_buffer_.empty())\r
+ packet_wait_cond_.wait(lock); \r
+ }\r
\r
bool seek(unsigned long long seek_target)\r
{\r
return false;\r
}\r
\r
- //int file_buffer_max_size_;\r
+ //int file_buffer_max_size_;\r
//tbb::atomic<int> file_buffer_size_;\r
//boost::condition_variable file_buffer_size_cond_;\r
//boost::mutex file_buffer_size_mutex_;\r
- \r
+ \r
+ boost::condition_variable packet_wait_cond_;\r
+ boost::mutex packet_wait_mutex_;\r
+\r
+ std::shared_ptr<AVFormatContext> format_context_; // Destroy this last\r
+\r
tbb::queuing_mutex seek_mutex_;\r
\r
std::string filename_;\r
- std::shared_ptr<AVFormatContext> format_context_; // Destroy this last\r
\r
std::shared_ptr<AVCodecContext> video_codec_context_;\r
AVCodec* video_codec_;\r
tbb::concurrent_bounded_queue<std::shared_ptr<aligned_buffer>> audio_packet_buffer_;\r
boost::thread io_thread_;\r
tbb::atomic<bool> is_running_;\r
-\r
- double video_frame_rate_;\r
};\r
\r
input::input() : impl_(new implementation()){}\r
aligned_buffer input::get_audio_packet(){return impl_->get_audio_packet();}\r
bool input::seek(unsigned long long frame){return impl_->seek(frame);}\r
void input::start(){impl_->start();}\r
+void input::wait_for_packet(){impl_->wait_for_packet();}\r
}}}
\ No newline at end of file
\r
aligned_buffer get_video_packet();\r
aligned_buffer get_audio_packet();\r
+ void wait_for_packet();\r
\r
bool seek(unsigned long long frame);\r
void start();\r
\r
std::shared_ptr<AVFrame> execute(const aligned_buffer& video_packet)\r
{ \r
- std::shared_ptr<AVFrame> decoded_frame;\r
- decoded_frame.reset(avcodec_alloc_frame(), av_free);\r
+ std::shared_ptr<AVFrame> decoded_frame(avcodec_alloc_frame(), av_free);\r
\r
int frame_finished = 0;\r
if((-avcodec_decode_video(codec_context_, decoded_frame.get(), &frame_finished, video_packet.data(), video_packet.size())) > 0) \r
\r
#include "video_transformer.h"\r
\r
-#include "../../../video/video_format.h"\r
+#include "../../../format/video_format.h"\r
#include "../../../../common/utility/memory.h"\r
#include "../../../processor/frame.h"\r
#include "../../../processor/frame.h"\r
\r
frame_ptr execute(const std::shared_ptr<AVFrame>& decoded_frame)\r
{ \r
+ if(decoded_frame == nullptr)\r
+ return nullptr;\r
+\r
int width = codec_context_->width;\r
int height = codec_context_->height;\r
auto pix_fmt = codec_context_->pix_fmt;\r
#include "..\..\stdafx.h"\r
\r
#include "FlashAxContainer.h"\r
-#include "..\..\video\video_format.h"\r
+#include "..\..\format\video_format.h"\r
#include "flash_producer.h"\r
#include "TimerHelper.h"\r
\r
#pragma warning(push)\r
\r
#include "..\..\processor\frame.h"\r
-#include "..\..\video\video_format.h"\r
+#include "..\..\format\video_format.h"\r
\r
#include <ocmm.h>\r
#include <vector>\r
#include "flash_producer.h"\r
\r
#include "../../producer/frame_producer_device.h"\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "../../processor/frame.h"\r
#include "../../Server.h"\r
\r
#pragma once\r
\r
#include "../frame_producer.h"\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "../../channel.h"\r
\r
namespace caspar { namespace core { namespace flash{\r
#include "TimerHelper.h"\r
#include "bitmap.h"\r
\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "../../../common/utility/find_file.h"\r
#include "../../server.h"\r
#include "../../../common/concurrency/executor.h"\r
\r
#include "layer.h"\r
\r
-#include "../video/video_format.h"\r
+#include "../format/video_format.h"\r
#include "../processor/composite_frame.h"\r
\r
#include "../../common/utility/scope_exit.h"\r
\r
#include "../processor/frame_processor_device.h"\r
#include "../consumer/frame_consumer.h"\r
-#include "../video/video_format.h"\r
+#include "../format/video_format.h"\r
\r
#include "layer.h"\r
\r
#include "image_loader.h"\r
\r
#include "../../processor/frame_processor_device.h"\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "../../server.h"\r
#include "../../../common/utility/find_file.h"\r
#include "../../../common/utility/memory.h"\r
\r
#include "../../processor/frame.h"\r
#include "../../processor/composite_frame.h"\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "../../processor/frame_processor_device.h"\r
#include "../../server.h"\r
#include "../../../common/utility/find_file.h"\r
\r
#include "../producer/frame_producer.h"\r
\r
-#include "../video/video_format.h"\r
+#include "../format/video_format.h"\r
\r
namespace caspar { namespace core {\r
\r
\r
#include "transition_producer.h"\r
\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "../../processor/frame.h"\r
#include "../../processor/composite_frame.h"\r
#include "../../processor/frame_processor_device.h"\r
#include "AMCPCommandsImpl.h"\r
#include "AMCPProtocolStrategy.h"\r
#include "../../producer/frame_producer.h"\r
-#include "../../video/video_format.h"\r
+#include "../../format/video_format.h"\r
#include "../../producer/flash/flash_producer.h"\r
#include "../../producer/transition/transition_producer.h"\r
#include <boost/lexical_cast.hpp>\r
</channel>\r
</channels>\r
<controllers>\r
- <!--tcpcontroller>\r
+ <tcpcontroller>\r
<port>5250</port>\r
<protocol>AMCP</protocol>\r
- </tcpcontroller-->\r
+ </tcpcontroller>\r
</controllers>\r
</configuration>
\ No newline at end of file
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
<MultiProcessorCompilation>true</MultiProcessorCompilation>\r
<PreprocessorDefinitions>NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
- <WholeProgramOptimization>false</WholeProgramOptimization>\r
+ <WholeProgramOptimization>true</WholeProgramOptimization>\r
<TreatWarningAsError>true</TreatWarningAsError>\r
</ClCompile>\r
<PreLinkEvent>\r