]> git.sesse.net Git - casparcg/commitdiff
2.0.0.2:
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 13 Nov 2010 18:46:46 +0000 (18:46 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 13 Nov 2010 18:46:46 +0000 (18:46 +0000)
 ffmpeg_producer:
    - re-renders last frame in case of file read underflow instead of blocking.
 frame_processor_device:
    - Improved frame pooling with proper key generation from pixel_format_desc.
 ffmeg_input:
    - aligned memcpy sometimes crashes, replaced with normal memcpy.

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

25 files changed:
common/gl/pixel_buffer_object.cpp
common/log/log.h
core/channel.cpp
core/consumer/oal/oal_consumer.cpp
core/core.vcxproj
core/format/pixel_format.h
core/processor/frame_processor_device.cpp
core/processor/frame_processor_device.h
core/processor/frame_renderer.cpp
core/producer/color/color_producer.cpp
core/producer/ffmpeg/ffmpeg_producer.cpp
core/producer/ffmpeg/input.cpp
core/producer/ffmpeg/input.h
core/producer/ffmpeg/video/video_decoder.cpp
core/producer/ffmpeg/video/video_transformer.cpp
core/producer/flash/flash_producer.cpp
core/producer/frame_producer.h
core/producer/frame_producer_device.cpp
core/producer/image/image_producer.cpp
core/producer/image/image_scroll_producer.cpp
core/producer/layer.cpp
core/producer/transition/transition_producer.cpp
shell/caspar.config
shell/shell.vcxproj
shell/shell.vcxproj.filters

index f0cdc85e6f3aae6b7201de9b3d63e5a210110cd5..e4b46cba1f504f54106ecc3b3c4d154ee6817949 100644 (file)
@@ -11,7 +11,7 @@ namespace caspar { namespace common { namespace gl {
 struct pixel_buffer_object::implementation : boost::noncopyable\r
 {\r
        implementation(size_t width, size_t height, GLenum format) \r
-               : width_(width), height_(height), pbo_(0), format_(format),\r
+               : width_(width), height_(height), pbo_(0), format_(format), data_(nullptr),\r
                        texture_(0), writing_(false), reading_(false), mapped_(false)\r
        {\r
                switch(format)\r
@@ -45,6 +45,8 @@ struct pixel_buffer_object::implementation : boost::noncopyable
        {\r
                if(pbo_ != 0)\r
                        glDeleteBuffers(1, &pbo_);\r
+               if(texture_ != 0)\r
+                       glDeleteTextures(1, &texture_);\r
        }       \r
 \r
        void bind_pbo(GLenum mode)\r
@@ -92,17 +94,22 @@ struct pixel_buffer_object::implementation : boost::noncopyable
        void* end_write()\r
        {\r
                if(mapped_)\r
-                       BOOST_THROW_EXCEPTION(invalid_operation());\r
+               {\r
+                       if(!writing_)\r
+                               return data_;\r
+                       else\r
+                               BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Buffer is already mapped."));\r
+               }\r
 \r
                bind_pbo(GL_PIXEL_UNPACK_BUFFER);\r
                GL(glBufferData(GL_PIXEL_UNPACK_BUFFER, size_, NULL, GL_STREAM_DRAW));\r
-               auto data = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);\r
+               data_= glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);\r
                unbind_pbo(GL_PIXEL_UNPACK_BUFFER);             \r
-               if(!data)\r
+               if(!data_)\r
                        BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("glMapBuffer failed"));\r
                writing_ = false;\r
                mapped_ = true;\r
-               return data;\r
+               return data_;\r
        }\r
        \r
        void begin_read()\r
@@ -120,16 +127,21 @@ struct pixel_buffer_object::implementation : boost::noncopyable
        void* end_read()\r
        {\r
                if(mapped_)\r
-                       BOOST_THROW_EXCEPTION(invalid_operation());\r
+               {\r
+                       if(!reading_)\r
+                               return data_;\r
+                       else\r
+                               BOOST_THROW_EXCEPTION(invalid_operation() << msg_info("Buffer is already mapped."));\r
+               }\r
 \r
                bind_pbo(GL_PIXEL_PACK_BUFFER);\r
-               auto data = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);   \r
+               data_ = glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);   \r
                unbind_pbo(GL_PIXEL_PACK_BUFFER);\r
-               if(!data)\r
+               if(!data_)\r
                        BOOST_THROW_EXCEPTION(std::bad_alloc());\r
                reading_ = false;\r
                mapped_ = true;\r
-               return data;\r
+               return data_;\r
        }\r
 \r
        void is_smooth(bool smooth)\r
@@ -158,6 +170,7 @@ struct pixel_buffer_object::implementation : boost::noncopyable
 \r
        GLint internal_;\r
        GLenum format_;\r
+       void* data_;\r
 };\r
 \r
 pixel_buffer_object::pixel_buffer_object(){}\r
index 9d0b869fe394a236a42413eca197182c2e215a06..157f12c53bfe35715ad946f182b3a2ca3b4fe84c 100644 (file)
@@ -27,17 +27,17 @@ void add_file_sink(const std::wstring& folder);
 \r
 enum severity_level\r
 {\r
-    trace,\r
-    debug,\r
-    info,\r
-    warning,\r
-    error,\r
-    fatal\r
+       trace,\r
+       debug,\r
+       info,\r
+       warning,\r
+       error,\r
+       fatal\r
 };\r
 \r
 template< typename CharT, typename TraitsT >\r
 inline std::basic_ostream< CharT, TraitsT >& operator<< (\r
-    std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)\r
+       std::basic_ostream< CharT, TraitsT >& strm, severity_level lvl)\r
 {\r
        if(lvl == trace)\r
                strm << "trace";\r
@@ -61,13 +61,13 @@ typedef boost::log::sources::wseverity_logger_mt<severity_level> caspar_logger;
 \r
 BOOST_LOG_DECLARE_GLOBAL_LOGGER_INIT(logger, caspar_logger)\r
 {\r
-    internal::init();\r
-    return caspar_logger(boost::log::keywords::severity = trace);\r
+       internal::init();\r
+       return caspar_logger(boost::log::keywords::severity = trace);\r
 }\r
 \r
 #define CASPAR_LOG(lvl)\\r
-    BOOST_LOG_STREAM_WITH_PARAMS(::caspar::log::get_logger(),\\r
-        (::boost::log::keywords::severity = ::caspar::log::lvl))\r
+       BOOST_LOG_STREAM_WITH_PARAMS(::caspar::log::get_logger(),\\r
+               (::boost::log::keywords::severity = ::caspar::log::lvl))\r
 \r
 #define CASPAR_LOG_CURRENT_EXCEPTION() \\r
        try\\r
index bdbe4217fdf2d5ec767ce7e6853684fe7710727e..3e2473f669596f9816b952c2d6593041753a955e 100644 (file)
@@ -15,6 +15,11 @@ public:
                : producer_device_(producer_device), processor_device_(processor_device), consumer_device_(consumer_device)\r
        {\r
        }\r
+\r
+       ~implementation()\r
+       {\r
+               producer_device_->clear();\r
+       }\r
        \r
        void load(int render_layer, const frame_producer_ptr& producer, load_option::type option = load_option::none)\r
        {\r
index fa14210bb84b9e42f128871dcdc3b1a165eb85c1..b39c172199f8c0e8a431f7255e74f004fb0dcfe4 100644 (file)
@@ -33,7 +33,7 @@ namespace caspar { namespace core { namespace oal {
 \r
 struct consumer::implementation : public sf::SoundStream, boost::noncopyable\r
 {\r
-       implementation() : container_(5)\r
+       implementation() : container_(5), underrun_count_(0)\r
        {\r
                input_.set_capacity(2);\r
                sf::SoundStream::Initialize(2, 48000);\r
@@ -66,12 +66,20 @@ struct consumer::implementation : public sf::SoundStream, boost::noncopyable
                static std::vector<short> silence(1920*2, 0);\r
                \r
                std::shared_ptr<std::vector<short>> audio_data;\r
+               \r
                if(!input_.try_pop(audio_data))\r
                {\r
-                       CASPAR_LOG(trace) << "Sound Buffer Underrun";\r
+                       if(underrun_count_ == 0)\r
+                               CASPAR_LOG(warning) << "### Sound Input underflow has STARTED.";\r
+                       ++underrun_count_;\r
                        input_.pop(audio_data);\r
                }\r
-\r
+               else if(underrun_count_ > 0)\r
+               {\r
+                       CASPAR_LOG(trace) << "### Sound Input Underrun has ENDED with " << underrun_count_ << " ticks.";\r
+                       underrun_count_ = 0;\r
+               }\r
+                       \r
                if(audio_data->empty())\r
                {       \r
                        data.Samples = silence.data();\r
@@ -86,6 +94,7 @@ struct consumer::implementation : public sf::SoundStream, boost::noncopyable
                return true;\r
        }\r
 \r
+       long underrun_count_;\r
        boost::circular_buffer<std::vector<short>> container_;\r
        tbb::concurrent_bounded_queue<std::shared_ptr<std::vector<short>>> input_;\r
 };\r
index 713a2651e81df7938623cf91c07ebef5be5deb2b..6900ae489449687b5fc5b30ac3da0f325f53ec23 100644 (file)
       <PreprocessorDefinitions>NDEBUG;_VC80_UPGRADE=0x0710;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <WholeProgramOptimization>true</WholeProgramOptimization>\r
       <TreatWarningAsError>true</TreatWarningAsError>\r
+      <OmitFramePointers>true</OmitFramePointers>\r
     </ClCompile>\r
     <PreLinkEvent>\r
       <Command>\r
index 2bf7372a6b268020992a6a61d0f8c58b1e0c13d9..4de9ea624e1b11736e141739ee8dafceb43a2a15 100644 (file)
@@ -41,8 +41,48 @@ struct pixel_format_desc
        }\r
 \r
        pixel_format::type pix_fmt;\r
-\r
        std::array<plane, 4> planes;\r
+\r
+       static size_t hash(const pixel_format_desc& desc)\r
+       {\r
+               size_t hash = 0;\r
+               switch(desc.pix_fmt)\r
+               {\r
+               case pixel_format::ycbcr:\r
+               case pixel_format::ycbcra:\r
+                       //  0-10 (11) width\r
+                       // 11-21 (11) height\r
+                       // 22-24 (3)  x-ratio\r
+                       // 25-27 (3)  y-ratio\r
+                   // 28-29 (2)  unused\r
+                   // 30        (1)  alpha\r
+                   // 31    (1)  yuv = true => 1\r
+                       hash |= (desc.planes[0].width & 0x7FF) << 0;\r
+                       hash |= (desc.planes[0].height & 0x7FF) << 11;\r
+                       hash |= ((desc.planes[0].height/desc.planes[1].height) & 0x7) << 22;\r
+                       hash |= ((desc.planes[0].width/desc.planes[1].width) & 0x7) << 25;\r
+                       hash |= desc.pix_fmt == pixel_format::ycbcra ? (1 << 30) : 0;\r
+                       hash |= 1 << 31;\r
+                       return hash;\r
+               case pixel_format::bgra:\r
+               case pixel_format::rgba:\r
+               case pixel_format::argb:\r
+               case pixel_format::abgr:\r
+               \r
+                       //0-10  (11) height\r
+                       //11-21 (11) width\r
+                   //22-29 (8)  unused\r
+                       //30    (1)  alpha\r
+                       //31    (1)  yuv = false => 0\r
+                       hash |= (desc.planes[0].height & 0xFFFF) << 0;\r
+                       hash |= (desc.planes[0].width  & 0xFFFF) << 15;\r
+                       hash |= 1 << 30;\r
+                       return hash;\r
+\r
+               default:\r
+                       return hash;\r
+               };\r
+       }\r
 };\r
        \r
 }}
\ No newline at end of file
index bf746e920ada5cd050022e728dbef8d343ac7995..078945683d64638d79dd525a9896ce0cfdd12e79 100644 (file)
@@ -29,12 +29,8 @@ namespace caspar { namespace core {
 struct frame_processor_device::implementation : boost::noncopyable\r
 {      \r
        implementation(frame_processor_device* self, const video_format_desc& format_desc) \r
-               : fmt_(format_desc), underrun_count_(0)\r
+               : fmt_(format_desc), output_underrun_count_(0), input_underrun_count_(0)\r
        {               \r
-               boost::promise<frame_ptr> promise;\r
-               active_frame_ = promise.get_future();\r
-               promise.set_value(nullptr);\r
-\r
                input_.set_capacity(2);\r
                output_.set_capacity(2);\r
                executor_.start();\r
@@ -57,22 +53,26 @@ struct frame_processor_device::implementation : boost::noncopyable
 \r
        ~implementation()\r
        {\r
+               stop();\r
+       }\r
+\r
+       void stop()\r
+       {\r
+               output_.clear();\r
+               input_.clear();\r
+               input_.push(nullptr);\r
+               output_.push(nullptr);\r
                executor_.stop();\r
        }\r
-                                       \r
-       frame_ptr create_frame(const pixel_format_desc& desc, void* tag)\r
+\r
+       frame_ptr create_frame(const pixel_format_desc& desc)\r
        {\r
-               size_t key = reinterpret_cast<size_t>(tag);\r
+               size_t key = pixel_format_desc::hash(desc);\r
                auto& pool = writing_pools_[key];\r
                \r
                frame_ptr my_frame;\r
-               if(!pool.try_pop(my_frame))\r
-               {\r
-                       my_frame = executor_.invoke([&]\r
-                       {\r
-                               return std::shared_ptr<frame>(new frame(desc));\r
-                       });\r
-               }\r
+               if(!pool.try_pop(my_frame))             \r
+                       my_frame = executor_.invoke([&]{return std::shared_ptr<frame>(new frame(desc));});              \r
                \r
                auto destructor = [=]\r
                {\r
@@ -80,28 +80,22 @@ struct frame_processor_device::implementation : boost::noncopyable
                        writing_pools_[key].push(my_frame);\r
                };\r
 \r
-               return frame_ptr(my_frame.get(), [=](frame*)                                                    \r
-               {\r
-                       executor_.begin_invoke(destructor);\r
-               });\r
-       }\r
-\r
-       void release_tag(void* tag)\r
-       {\r
-               writing_pools_[reinterpret_cast<size_t>(tag)].clear();\r
+               return frame_ptr(my_frame.get(), [=](frame*){executor_.begin_invoke(destructor);});\r
        }\r
-       \r
+               \r
        void send(const frame_ptr& input_frame)\r
        {                       \r
+               if(input_frame == nullptr)\r
+                       return;\r
+\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
-                               if(output_frame != nullptr)\r
-                                       output_.push(renderer_->render(output_frame));\r
+                               output_.push(renderer_->render(input_frame));\r
+                               frame_ptr dummy;\r
+                               input_.try_pop(dummy);\r
                        }\r
                        catch(...)\r
                        {\r
@@ -114,16 +108,32 @@ struct frame_processor_device::implementation : boost::noncopyable
        {\r
                if(!output_.try_pop(output_frame))\r
                {\r
-                       if(underrun_count_ == 0)                        \r
-                               CASPAR_LOG(trace) << "Frame Processor Underrun has STARTED.";\r
+                       if(input_.empty())\r
+                       {\r
+                               if(input_underrun_count_ == 0)                  \r
+                                       CASPAR_LOG(trace) << "### Frame Processor Input Underrun has STARTED. ###";\r
+                       \r
+                               ++input_underrun_count_;\r
+                       }\r
+                       else \r
+                       {\r
+                               if(output_underrun_count_ == 0)                 \r
+                                       CASPAR_LOG(trace) << "### Frame Processor Output Underrun has STARTED. ###";\r
                        \r
-                       ++underrun_count_;\r
+                               ++output_underrun_count_;\r
+                       }\r
+\r
                        output_.pop(output_frame);\r
-               }               \r
-               else if(underrun_count_ > 0)\r
+               }       \r
+               else if(input_underrun_count_ > 0)\r
+               {\r
+                       CASPAR_LOG(trace) << "### Frame Processor Input Underrun has ENDED with " << output_underrun_count_ << " ticks. ###";\r
+                       input_underrun_count_ = 0;\r
+               }       \r
+               else if(output_underrun_count_ > 0)\r
                {\r
-                       CASPAR_LOG(trace) << "Frame Processor Underrun has ENDED with " << underrun_count_ << " ticks.";\r
-                       underrun_count_ = 0;\r
+                       CASPAR_LOG(trace) << "### Frame Processor Output Underrun has ENDED with " << output_underrun_count_ << " ticks. ###";\r
+                       output_underrun_count_ = 0;\r
                }\r
        }\r
 \r
@@ -134,8 +144,6 @@ struct frame_processor_device::implementation : boost::noncopyable
        frame_queue reading_pool_;      \r
                                \r
        std::unique_ptr<sf::Context> ogl_context_;\r
-\r
-       boost::unique_future<frame_ptr> active_frame_;\r
        \r
        common::executor executor_;\r
        \r
@@ -144,7 +152,8 @@ struct frame_processor_device::implementation : boost::noncopyable
 \r
        frame_renderer_ptr renderer_;\r
 \r
-       long underrun_count_;\r
+       long output_underrun_count_;\r
+       long input_underrun_count_;\r
 };\r
        \r
 #if defined(_MSC_VER)\r
@@ -153,24 +162,26 @@ struct frame_processor_device::implementation : boost::noncopyable
 \r
 frame_processor_device::frame_processor_device(const video_format_desc& format_desc) \r
        : impl_(new implementation(this, format_desc)){}\r
-frame_ptr frame_processor_device::create_frame(const  pixel_format_desc& desc, void* tag){return impl_->create_frame(desc, tag);}\r
-void frame_processor_device::release_tag(void* tag){impl_->release_tag(tag);}\r
+frame_ptr frame_processor_device::create_frame(const  pixel_format_desc& desc){return impl_->create_frame(desc);}\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
 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
+frame_ptr frame_processor_device::create_frame(size_t width, size_t height)\r
 {\r
+       // Create bgra frame\r
        pixel_format_desc desc;\r
        desc.pix_fmt = pixel_format::bgra;\r
        desc.planes[0] = pixel_format_desc::plane(width, height, 4);\r
-       return create_frame(desc, tag);\r
+       return create_frame(desc);\r
 }\r
                        \r
-frame_ptr frame_processor_device::create_frame(void* tag)\r
+frame_ptr frame_processor_device::create_frame()\r
 {\r
+       // Create bgra frame with output resolution\r
        pixel_format_desc desc;\r
        desc.pix_fmt = pixel_format::bgra;\r
        desc.planes[0] = pixel_format_desc::plane(get_video_format_desc().width, get_video_format_desc().height, 4);\r
-       return create_frame(desc, tag);\r
+       return create_frame(desc);\r
 }\r
+void frame_processor_device::stop(){impl_->stop();}\r
 }}
\ No newline at end of file
index 1fb115ec25e183601a6a514cb4122f6298f90f52..3c47bcb3b1052232bbc1d4b7533c9e24e07017ba 100644 (file)
@@ -33,15 +33,14 @@ class frame_processor_device : boost::noncopyable
 public:\r
        frame_processor_device(const video_format_desc& format_desc);\r
                \r
+       void stop();\r
        void send(const frame_ptr& frame);\r
        void 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
-       frame_ptr create_frame(void* tag);\r
-\r
-       void release_tag(void* tag);\r
-\r
+       frame_ptr create_frame(const pixel_format_desc& desc);          \r
+       frame_ptr create_frame(size_t width, size_t heightg);                   \r
+       frame_ptr create_frame();\r
+       \r
        const video_format_desc get_video_format_desc() const;\r
 private:\r
        struct implementation;\r
index 772beb3d0b7821ced98f4c53db1885f34eb68cb1..a009602860ff3db68d401370156db19c7ef41b52 100644 (file)
@@ -57,7 +57,7 @@ struct frame_renderer::implementation : boost::noncopyable
                        writing_[next_index]->draw(shader_);\r
                                \r
                        // Create an output frame\r
-                       auto temp_frame = frame_processor_.create_frame(this);\r
+                       auto temp_frame = frame_processor_.create_frame();\r
                        \r
                        // Read from framebuffer into page-locked memory.\r
                        temp_frame->begin_read();\r
index 7a244ce6ea30ab40031ab14aa5af27d25a532865..168c7086666a9ba008a74efa67b5b16d1edd68e4 100644 (file)
 #pragma intrinsic(__movsd, __stosd)\r
 \r
 namespace caspar { namespace core {\r
-\r
-class color_producer : public frame_producer\r
-{\r
-public:\r
-       explicit color_producer(unsigned int color_value) \r
-               : color_value_(color_value){}\r
-\r
-       ~color_producer()\r
-       {\r
-               if(frame_processor_)\r
-                       frame_processor_->release_tag(this);\r
-       }\r
-\r
-       frame_ptr render_frame()\r
-       { \r
-               return frame_;\r
-       }\r
-\r
-       void initialize(const frame_processor_device_ptr& frame_processor)\r
-       {\r
-               frame_processor_ = frame_processor;\r
-               frame_ = frame_processor->create_frame(this);\r
-               __stosd(reinterpret_cast<unsigned long*>(frame_->data()), color_value_, frame_->size() / sizeof(unsigned long));\r
-       }\r
-\r
-       frame_processor_device_ptr frame_processor_;\r
-       frame_ptr frame_;\r
-       unsigned int color_value_;\r
-};\r
-\r
-union Color \r
+       \r
+unsigned int get_pixel_color_value(const std::wstring& parameter)\r
 {\r
-       struct Components \r
+       union Color \r
        {\r
-               unsigned char a;\r
-               unsigned char r;\r
-               unsigned char g;\r
-               unsigned char b;\r
-       } comp;\r
+               struct Components \r
+               {\r
+                       unsigned char a;\r
+                       unsigned char r;\r
+                       unsigned char g;\r
+                       unsigned char b;\r
+               } comp;\r
 \r
-       unsigned int value;\r
-};\r
+               unsigned int value;\r
+       };\r
 \r
-unsigned int get_pixel_color_value(const std::wstring& parameter)\r
-{\r
        std::wstring color_code;\r
        if(parameter.length() != 9 || parameter[0] != '#')\r
                BOOST_THROW_EXCEPTION(invalid_argument() << arg_name_info("parameter") << arg_value_info(common::narrow(parameter)) << msg_info("Invalid color code"));\r
@@ -91,11 +62,41 @@ unsigned int get_pixel_color_value(const std::wstring& parameter)
        return color.value;\r
 }\r
 \r
+class color_producer : public frame_producer\r
+{\r
+public:\r
+       explicit color_producer(const std::wstring& color) : color_str_(color), color_value_(get_pixel_color_value(color)){}\r
+       \r
+       frame_ptr render_frame()\r
+       { \r
+               return frame_;\r
+       }\r
+\r
+       void initialize(const frame_processor_device_ptr& frame_processor)\r
+       {\r
+               frame_processor_ = frame_processor;\r
+               frame_ = frame_processor->create_frame();\r
+               __stosd(reinterpret_cast<unsigned long*>(frame_->data()), color_value_, frame_->size() / sizeof(unsigned long));\r
+       }\r
+       \r
+       std::wstring print()\r
+       {\r
+               std::wstringstream str;\r
+               str << L"color_producer " << color_str_ << L".";\r
+               return str.str();\r
+       }\r
+\r
+       frame_processor_device_ptr frame_processor_;\r
+       frame_ptr frame_;\r
+       unsigned int color_value_;\r
+       std::wstring color_str_;\r
+};\r
+\r
 frame_producer_ptr create_color_producer(const std::vector<std::wstring>& params)\r
 {\r
        if(params.empty() || params[0].at(0) != '#')\r
                return nullptr;\r
-       return std::make_shared<color_producer>(get_pixel_color_value(params[0]));\r
+       return std::make_shared<color_producer>(params[0]);\r
 }\r
 \r
 }}
\ No newline at end of file
index 12b98638842a47a6f7d6e940318fe250d46ed1f8..e91bd40af091b39a0af4f27433c252a3d995a220 100644 (file)
@@ -75,8 +75,6 @@ public:
                        if(!input_->seek(boost::lexical_cast<unsigned long long>(*seek)))\r
                                CASPAR_LOG(warning) << "Failed to seek file: " << filename_  << "to frame" << *seek;\r
                }\r
-\r
-               input_->start();\r
        }\r
                \r
        void initialize(const frame_processor_device_ptr& frame_processor)\r
@@ -87,7 +85,7 @@ public:
        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
@@ -112,12 +110,13 @@ public:
                        if(video_packet.empty() && audio_packet.empty())\r
                        {\r
                                if(underrun_count_ == 0)\r
-                                       CASPAR_LOG(warning) << "File read underflow has STARTED.";\r
+                                       CASPAR_LOG(warning) << "### File read underflow has STARTED.";\r
                                ++underrun_count_;\r
+                               return last_frame_;\r
                        }\r
                        else if(underrun_count_ > 0)\r
                        {\r
-                               CASPAR_LOG(trace) << "File Read Underrun has ENDED with " << underrun_count_ << " ticks.";\r
+                               CASPAR_LOG(trace) << "### File Read Underrun has ENDED with " << underrun_count_ << " ticks.";\r
                                underrun_count_ = 0;\r
                        }\r
 \r
@@ -135,13 +134,19 @@ public:
                        }                               \r
                }\r
 \r
-               frame_ptr frame;\r
                if(!ouput_channel_.empty())\r
                {\r
-                       frame = ouput_channel_.front();\r
+                       last_frame_ = ouput_channel_.front();\r
                        ouput_channel_.pop();\r
                }\r
-               return frame;\r
+               return last_frame_;\r
+       }\r
+\r
+       std::wstring print()\r
+       {\r
+               std::wstringstream str;\r
+               str << L"ffmpeg_producer " << filename_ << L".";\r
+               return str.str();\r
        }\r
                        \r
        bool has_audio_;\r
@@ -159,7 +164,9 @@ public:
        \r
        std::wstring                                            filename_;\r
 \r
-       long underrun_count_;\r
+       long                                                            underrun_count_;\r
+\r
+       frame_ptr                                                       last_frame_;\r
 };\r
 \r
 frame_producer_ptr create_ffmpeg_producer(const  std::vector<std::wstring>& params)\r
index 2b2dbbc9d389afa29a0038afa25efa7d1128abbc..bc78f7883d3d35cc0c82ada7cc2e61a078180c18 100644 (file)
@@ -10,6 +10,7 @@
 #include <tbb/queuing_mutex.h>\r
 \r
 #include <boost/thread.hpp>\r
+#include <boost/exception/error_info.hpp>\r
 \r
 #include <errno.h>\r
 #include <system_error>\r
@@ -34,27 +35,19 @@ struct input::implementation : boost::noncopyable
 {\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
+               loop_ = false;  \r
                video_packet_buffer_.set_capacity(50);\r
                audio_packet_buffer_.set_capacity(50);\r
        }\r
 \r
        ~implementation()\r
        {               \r
-               stop();\r
-       }\r
-       \r
-       void stop()\r
-       {\r
                is_running_ = false;\r
                audio_packet_buffer_.clear();\r
                video_packet_buffer_.clear();\r
-               //file_buffer_size_ = 0;\r
-               //file_buffer_size_cond_.notify_all();\r
                io_thread_.join();\r
        }\r
-\r
+       \r
        void load(const std::string& filename)\r
        {       \r
                try\r
@@ -62,11 +55,21 @@ struct input::implementation : boost::noncopyable
                        int errn;\r
                        AVFormatContext* weak_format_context_;\r
                        if((errn = -av_open_input_file(&weak_format_context_, filename.c_str(), nullptr, 0, nullptr)) > 0)\r
-                               BOOST_THROW_EXCEPTION(file_read_error() << msg_info("No video or audio codec found."));\r
+                               BOOST_THROW_EXCEPTION(\r
+                                       file_read_error() << \r
+                                       msg_info("No format context found.") << \r
+                                       boost::errinfo_api_function("av_open_input_file") <<\r
+                                       boost::errinfo_errno(errn) <<\r
+                                       boost::errinfo_file_name(filename));\r
+\r
                        format_context_.reset(weak_format_context_, av_close_input_file);\r
                        \r
                        if((errn = -av_find_stream_info(format_context_.get())) > 0)\r
-                               throw std::runtime_error("File read error");\r
+                               BOOST_THROW_EXCEPTION(\r
+                                       file_read_error() << \r
+                                       boost::errinfo_api_function("av_find_stream_info") <<\r
+                                       msg_info("No stream found.") << \r
+                                       boost::errinfo_errno(errn));\r
 \r
                        video_codec_context_ = open_video_stream();\r
                        if(!video_codec_context_)\r
@@ -77,7 +80,7 @@ struct input::implementation : boost::noncopyable
                                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
+                               BOOST_THROW_EXCEPTION(file_read_error() << msg_info("No video or audio codec context found."));         \r
                }\r
                catch(...)\r
                {\r
@@ -89,13 +92,9 @@ struct input::implementation : boost::noncopyable
                        throw;\r
                }\r
                filename_ = filename;\r
-       }\r
-\r
-       void start()\r
-       {\r
                io_thread_ = boost::thread([=]{read_file();});\r
        }\r
-                       \r
+                               \r
        std::shared_ptr<AVCodecContext> open_video_stream()\r
        {               \r
                AVStream** streams_end = format_context_->streams+format_context_->nb_streams;\r
@@ -150,28 +149,14 @@ struct input::implementation : boost::noncopyable
 \r
                        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
-                               {\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
+                               auto buffer = std::make_shared<aligned_buffer>(packet->data, packet->data + packet->size);\r
+                               if(packet->stream_index == video_s_index_)                                              \r
+                                       video_packet_buffer_.push(buffer);                                              \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
-                                       packet_wait_cond_.notify_all(); \r
-                                       //file_buffer_size_ += packet->size;\r
-                               }\r
+                                       audio_packet_buffer_.push(buffer);              \r
                        }\r
                        else if(!loop_ || av_seek_frame(format_context_.get(), -1, 0, AVSEEK_FLAG_BACKWARD) < 0) // TODO: av_seek_frame does not work for all formats\r
                                is_running_ = false;\r
-                       \r
-                       //if(is_running_)\r
-                       //{\r
-                       //      boost::unique_lock<boost::mutex> lock(file_buffer_size_mutex_);\r
-                       //      while(file_buffer_size_ > 32*1000000)\r
-                       //              file_buffer_size_cond_.wait(lock);      \r
-                       //}\r
                }\r
                \r
                is_running_ = false;\r
@@ -182,12 +167,8 @@ struct input::implementation : boost::noncopyable
        aligned_buffer get_video_packet()\r
        {\r
                std::shared_ptr<aligned_buffer> video_packet;\r
-               if(video_packet_buffer_.try_pop(video_packet))\r
-               {\r
-                       return std::move(*video_packet);\r
-                       //file_buffer_size_ -= video_packet->size;\r
-                       //file_buffer_size_cond_.notify_all();\r
-               }\r
+               if(video_packet_buffer_.try_pop(video_packet))          \r
+                       return std::move(*video_packet);                \r
                return aligned_buffer();\r
        }\r
 \r
@@ -195,11 +176,7 @@ struct input::implementation : boost::noncopyable
        {\r
                std::shared_ptr<aligned_buffer> audio_packet;\r
                if(audio_packet_buffer_.try_pop(audio_packet))\r
-               {\r
                        return std::move(*audio_packet);\r
-                       //file_buffer_size_ -= audio_packet->size;\r
-                       //file_buffer_size_cond_.notify_all();\r
-               }\r
                return aligned_buffer();\r
        }\r
 \r
@@ -207,40 +184,23 @@ struct input::implementation : boost::noncopyable
        {\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
+               \r
        bool seek(unsigned long long seek_target)\r
        {\r
                tbb::queuing_mutex::scoped_lock lock(seek_mutex_);\r
-               if(av_seek_frame(format_context_.get(), -1, seek_target*AV_TIME_BASE, 0) >= 0)\r
-               {\r
-                       video_packet_buffer_.clear();\r
-                       audio_packet_buffer_.clear();\r
-                       // TODO: Not sure its enough to jsut flush in input class\r
-                       if(video_codec_context_)\r
-                               avcodec_flush_buffers(video_codec_context_.get());\r
-                       if(audio_codex_context_)\r
-                               avcodec_flush_buffers(audio_codex_context_.get());\r
-                       return true;\r
-               }\r
+               if(av_seek_frame(format_context_.get(), -1, seek_target*AV_TIME_BASE, 0) < 0)\r
+                       return false;\r
                \r
-               return false;\r
+               video_packet_buffer_.clear();\r
+               audio_packet_buffer_.clear();\r
+               // TODO: Not sure its enough to jsut flush in input class\r
+               if(video_codec_context_)\r
+                       avcodec_flush_buffers(video_codec_context_.get());\r
+               if(audio_codex_context_)\r
+                       avcodec_flush_buffers(audio_codex_context_.get());\r
+               return true;\r
        }\r
-       \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
-       boost::condition_variable                       packet_wait_cond_;\r
-       boost::mutex                                            packet_wait_mutex_;\r
-\r
+                               \r
        std::shared_ptr<AVFormatContext>        format_context_;        // Destroy this last\r
 \r
        tbb::queuing_mutex                                      seek_mutex_;\r
@@ -272,6 +232,4 @@ bool input::is_eof() const{return impl_->is_eof();}
 aligned_buffer input::get_video_packet(){return impl_->get_video_packet();}\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
index 73ddac186d3fbaafe3ab6a6f35f834491bb57cf3..bf9a61c9f0cf29b3a0bd9f7ef925f26f06e9838d 100644 (file)
@@ -20,10 +20,8 @@ public:
 \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
        bool is_eof() const;\r
        void set_loop(bool value);\r
index 1f1fdc4f86d06e1ee4a03cfa0d2174e6f12986a5..a0743c6c3c2ba511876294843f3c84cf7e85342f 100644 (file)
@@ -27,8 +27,9 @@ struct video_decoder::implementation : boost::noncopyable
                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
-                       decoded_frame.reset();                  \r
+               const int result = avcodec_decode_video(codec_context_, decoded_frame.get(), &frame_finished, video_packet.data(), video_packet.size());\r
+               if(result < 0)                                          \r
+                       return nullptr;                 \r
                \r
                return decoded_frame;           \r
        }\r
index c20d1634231dccc071c3a8c4ce5400b6a57a3083..948bf709a1ce94a8b139e2c8a71f38e29b59a3e3 100644 (file)
@@ -54,13 +54,7 @@ pixel_format::type get_pixel_format(PixelFormat pix_fmt)
 struct video_transformer::implementation : boost::noncopyable\r
 {\r
        implementation(AVCodecContext* codec_context) : codec_context_(codec_context), sw_warning_(false){}\r
-\r
-       ~implementation()\r
-       {\r
-               if(frame_processor_)\r
-                       frame_processor_->release_tag(this);\r
-       }\r
-\r
+       \r
        frame_ptr execute(const std::shared_ptr<AVFrame>& decoded_frame)\r
        {                               \r
                if(decoded_frame == nullptr)\r
@@ -110,7 +104,7 @@ struct video_transformer::implementation : boost::noncopyable
 \r
                if(desc.pix_fmt != pixel_format::invalid)\r
                {\r
-                       result_frame = frame_processor_->create_frame(desc, this);\r
+                       result_frame = frame_processor_->create_frame(desc);\r
 \r
                        tbb::parallel_for(0, static_cast<int>(desc.planes.size()), 1, [&](int n)\r
                        {\r
@@ -135,7 +129,7 @@ struct video_transformer::implementation : boost::noncopyable
                                CASPAR_LOG(warning) << "Hardware accelerated color transform not supported.";\r
                                sw_warning_ = true;\r
                        }\r
-                       result_frame = frame_processor_->create_frame(width, height, this);\r
+                       result_frame = frame_processor_->create_frame(width, height);\r
 \r
                        AVFrame av_frame;       \r
                        avcodec_get_frame_defaults(&av_frame);\r
@@ -145,6 +139,12 @@ struct video_transformer::implementation : boost::noncopyable
                        {\r
                                double param;\r
                                sws_context_.reset(sws_getContext(width, height, pix_fmt, width, height, PIX_FMT_BGRA, SWS_BILINEAR, nullptr, nullptr, &param), sws_freeContext);\r
+                               if(!sws_context_)\r
+                                       BOOST_THROW_EXCEPTION(\r
+                                               operation_failed() <<\r
+                                               msg_info("Could not create software scaling context.") << \r
+                                               boost::errinfo_api_function("sws_getContext"));\r
+\r
                        }               \r
                 \r
                        sws_scale(sws_context_.get(), decoded_frame->data, decoded_frame->linesize, 0, height, av_frame.data, av_frame.linesize);               \r
index 50b1adf10634e78aae3fccd3a3154418475e21be..a1dc32bf095244367572cf98f3c40124638a0a98 100644 (file)
@@ -71,8 +71,6 @@ struct flash_producer::implementation
        ~implementation() \r
        {\r
                stop();\r
-               if(frame_processor_)\r
-                       frame_processor_->release_tag(this);\r
        }\r
 \r
        void start(bool force = true)\r
@@ -271,7 +269,7 @@ struct flash_producer::implementation
                        });\r
                }       \r
 \r
-               auto frame = frame_processor_->create_frame(format_desc.width, format_desc.height, this);\r
+               auto frame = frame_processor_->create_frame(format_desc.width, format_desc.height);\r
                common::aligned_parallel_memcpy(frame->data(), current_frame_->data(), current_frame_->size()); \r
 \r
                return frame;\r
index 6d3f29c6197882aa7cf955f4fd3f7323e2e49b3e..0222a183772010a93b4cc37d97ddddeb7cde51b3 100644 (file)
@@ -70,6 +70,8 @@ public:
        /// \param      frame_processor The frame frame_processor. \r
        ////////////////////////////////////////////////////////////////////////////////////////////////////\r
        virtual void initialize(const frame_processor_device_ptr& frame_processor) = 0;\r
+\r
+       virtual std::wstring print() { return L"Unknown frame_producer.";}\r
 };\r
 typedef std::shared_ptr<frame_producer> frame_producer_ptr;\r
 \r
index 11861aef33c364864c85d9e978043954bd211826..67abf9866447399c47837ba39fae5a53ee10e349 100644 (file)
@@ -47,6 +47,7 @@ struct frame_producer_device::implementation : boost::noncopyable
                        \r
        ~implementation()\r
        {\r
+               frame_processor_->stop();\r
                is_running_ = false;\r
                render_thread_.join();\r
        }\r
index c527f1bb96e8ed6edeece96576990d9c27650e80..4a1d723b69c6cfb3e01e0e9dffcf0f13d6ca10dc 100644 (file)
@@ -18,13 +18,7 @@ namespace caspar { namespace core { namespace image{
 struct image_producer : public frame_producer\r
 {\r
        image_producer(const std::wstring& filename) : filename_(filename)      {}\r
-\r
-       ~image_producer()\r
-       {\r
-               if(frame_processor_)\r
-                       frame_processor_->release_tag(this);\r
-       }\r
-\r
+       \r
        frame_ptr render_frame(){return frame_;}\r
 \r
        void initialize(const frame_processor_device_ptr& frame_processor)\r
@@ -32,7 +26,7 @@ struct image_producer : public frame_producer
                frame_processor_ = frame_processor;\r
                auto bitmap = load_image(filename_);\r
                FreeImage_FlipVertical(bitmap.get());\r
-               frame_ = frame_processor->create_frame(FreeImage_GetWidth(bitmap.get()), FreeImage_GetHeight(bitmap.get()), this);\r
+               frame_ = frame_processor->create_frame(FreeImage_GetWidth(bitmap.get()), FreeImage_GetHeight(bitmap.get()));\r
                common::aligned_parallel_memcpy(frame_->data(), FreeImage_GetBits(bitmap.get()), frame_->size());\r
        }\r
        \r
index 4c33b0355d3fb4ea611d42340318dd5d6acfe8b5..375c13faf17326826305356baa905fc2bf84e5f1 100644 (file)
@@ -51,12 +51,6 @@ struct image_scroll_producer : public frame_producer
 \r
                loop_ = std::find(params.begin(), params.end(), L"LOOP") != params.end();\r
        }\r
-       \r
-       ~image_scroll_producer()\r
-       {\r
-               if(frame_processor_)\r
-                       frame_processor_->release_tag(this);\r
-       }\r
 \r
        void load_and_pad_image(const std::wstring& filename)\r
        {\r
@@ -79,7 +73,7 @@ struct image_scroll_producer : public frame_producer
 \r
        frame_ptr do_render_frame()\r
        {\r
-               frame_ptr frame = frame_processor_->create_frame(format_desc_.width, format_desc_.height, this);\r
+               frame_ptr frame = frame_processor_->create_frame(format_desc_.width, format_desc_.height);\r
                common::clear(frame->data(), format_desc_.size);\r
 \r
                const int delta_x = direction_ == direction::Left ? speed_ : -speed_;\r
index 4ae74bbb95a18be644ee9bb77084d91b13e5aebb..61876047fc456c280e9eda3687b7e296e5a7fce7 100644 (file)
@@ -80,8 +80,9 @@ struct layer::implementation
                catch(...)\r
                {\r
                        CASPAR_LOG_CURRENT_EXCEPTION();\r
+                       CASPAR_LOG(warning) << L"Removed " << (active_ ? active_->print() : L"frame_producer") << L" from layer.";\r
                        active_ = nullptr;\r
-                       CASPAR_LOG(warning) << "Removed producer from layer.";\r
+                       last_frame_ = nullptr;\r
                }\r
 \r
                return last_frame_;\r
index b1e335d067114167abc1100fb54fa87739188929..c8222094a07bc20f81b063a90b24d679c897d9ef 100644 (file)
@@ -67,7 +67,7 @@ struct transition_producer::implementation : boost::noncopyable
 \r
                        tbb::parallel_invoke\r
                        (\r
-                               [&]{dest = render_frame(dest_producer_);},\r
+                               [&]{dest   = render_frame(dest_producer_);},\r
                                [&]{source = render_frame(source_producer_);}\r
                        );\r
 \r
@@ -94,16 +94,27 @@ struct transition_producer::implementation : boost::noncopyable
                {\r
                        CASPAR_LOG_CURRENT_EXCEPTION();\r
                        producer = nullptr;\r
-                       CASPAR_LOG(warning) << "Removed renderer from transition.";\r
+                       CASPAR_LOG(warning) << "Removed producer from transition.";\r
                }\r
 \r
-               if(frame == nullptr && producer != nullptr && \r
-                       producer->get_following_producer() != nullptr)\r
+               if(frame == nullptr)\r
                {\r
-                       auto following = producer->get_following_producer();\r
-                       following->initialize(frame_processor_);\r
-                       following->set_leading_producer(producer);\r
-                       producer = following;\r
+                       if(producer == nullptr || producer->get_following_producer() == nullptr)\r
+                               return nullptr;\r
+\r
+                       try\r
+                       {\r
+                               auto following = producer->get_following_producer();\r
+                               following->initialize(frame_processor_);\r
+                               following->set_leading_producer(producer);\r
+                               producer = following;\r
+                       }\r
+                       catch(...)\r
+                       {\r
+                               CASPAR_LOG(warning) << "Failed to initialize following producer. Removing it.";\r
+                               producer = nullptr;\r
+                       }\r
+\r
                        return render_frame(producer);\r
                }\r
                return frame;\r
index 9c3d9cb9b5293f9adeae80b53995ad594e32c432..8f2c94310790eced28a59bb9d934f71485e577bc 100644 (file)
@@ -8,18 +8,18 @@
   </paths>\r
   <channels>\r
     <channel>\r
-      <videomode>PAL</videomode>\r
+      <videomode>720p2500</videomode>\r
       <consumers>\r
-        <!--ogl>\r
+        <ogl>\r
           <device>1</device>\r
           <stretch>uniform</stretch>\r
           <windowed>true</windowed>\r
         </ogl>\r
-        <audio/-->\r
-        <bluefish>\r
+        <audio/>\r
+        <!--bluefish>\r
           <device>1</device> \r
           <embedded-audio>true</embedded-audio>\r
-        </bluefish>\r
+        </bluefish-->\r
       </consumers>\r
     </channel>\r
   </channels>\r
index 1c984a7c8d45c8ef4b84cd13f5fa318971788999..19181ac45d4c38edc87215908cecf74849c7cedf 100644 (file)
     <None Include="caspar.config">\r
       <SubType>Designer</SubType>\r
     </None>\r
+    <None Include="My Amplifier Results\r006hs\r006hs.ampl" />\r
+    <None Include="My Amplifier Results\r007cc\r007cc.ampl" />\r
+    <None Include="My Amplifier Results\r008lw\r008lw.ampl" />\r
+    <None Include="My Inspector Results\r000ti3\r000ti3.insp" />\r
   </ItemGroup>\r
   <PropertyGroup Label="Globals">\r
     <ProjectGuid>{8C26C94F-8092-4769-8D84-DEA479721C5B}</ProjectGuid>\r
index 25a28368228d5c830f74c578353864b36da9f996..1f6386dbb80005758ee0d2a8cdb7c53dd14ec084 100644 (file)
@@ -5,10 +5,25 @@
   </ItemGroup>\r
   <ItemGroup>\r
     <None Include="caspar.config" />\r
+    <None Include="My Amplifier Results\r006hs\r006hs.ampl">\r
+      <Filter>My Amplifier Results</Filter>\r
+    </None>\r
+    <None Include="My Amplifier Results\r007cc\r007cc.ampl">\r
+      <Filter>My Amplifier Results</Filter>\r
+    </None>\r
+    <None Include="My Amplifier Results\r008lw\r008lw.ampl">\r
+      <Filter>My Amplifier Results</Filter>\r
+    </None>\r
+    <None Include="My Inspector Results\r000ti3\r000ti3.insp">\r
+      <Filter>My Inspector Results</Filter>\r
+    </None>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <Filter Include="My Amplifier Results">\r
       <UniqueIdentifier>{4df636fc-0183-410c-8d76-2d0e06c29ca3}</UniqueIdentifier>\r
     </Filter>\r
+    <Filter Include="My Inspector Results">\r
+      <UniqueIdentifier>{54aa3e52-b5b4-4451-84e3-3b5d5ddcee0e}</UniqueIdentifier>\r
+    </Filter>\r
   </ItemGroup>\r
 </Project>
\ No newline at end of file