]> git.sesse.net Git - casparcg/commitdiff
manually merged 4a2171b from master
authorniklaspandersson <niklas.p.andersson@svt.se>
Tue, 3 Sep 2013 08:08:17 +0000 (10:08 +0200)
committerniklaspandersson <niklas.p.andersson@svt.se>
Tue, 3 Sep 2013 08:08:17 +0000 (10:08 +0200)
manually merged 0c06544 from master
manually merged 8d99a50 from master

19 files changed:
core/consumer/frame_consumer.cpp
core/consumer/output.cpp
core/consumer/port.cpp
core/consumer/port.h
core/mixer/audio/audio_mixer.cpp
core/video_format.cpp
core/video_format.h
modules/bluefish/consumer/bluefish_consumer.cpp
modules/decklink/consumer/decklink_consumer.cpp
modules/decklink/producer/decklink_producer.cpp
modules/ffmpeg/producer/muxer/frame_muxer.cpp
modules/oal/consumer/oal_consumer.cpp
protocol/amcp/AMCPCommandsImpl.cpp
protocol/amcp/AMCPCommandsImpl.h
protocol/amcp/AMCPProtocolStrategy.cpp
shell/casparcg_auto_restart.bat [new file with mode: 0644]
shell/main.cpp
shell/shell.vcxproj
shell/shell.vcxproj.filters

index b7da6ce5e2eca5cc14ff069bf842e5968b89aa9a..de153d6a56090f73d7d95de6d2800bf10b3bd001 100644 (file)
@@ -175,6 +175,7 @@ class cadence_guard : public frame_consumer
 {
        spl::shared_ptr<frame_consumer>         consumer_;
        std::vector<int>                                        audio_cadence_;
+       video_format_desc                                       format_desc_;
        boost::circular_buffer<std::size_t>     sync_buffer_;
 public:
        cadence_guard(const spl::shared_ptr<frame_consumer>& consumer)
@@ -186,6 +187,7 @@ public:
        {
                audio_cadence_  = format_desc.audio_cadence;
                sync_buffer_    = boost::circular_buffer<std::size_t>(format_desc.audio_cadence.size());
+               format_desc_    = format_desc;
                consumer_->initialize(format_desc, channel_index);
        }
 
@@ -196,7 +198,7 @@ public:
 
                boost::unique_future<bool> result = wrap_as_future(true);
                
-               if(boost::range::equal(sync_buffer_, audio_cadence_) && audio_cadence_.front() == static_cast<int>(frame.audio_data().size())) 
+               if(boost::range::equal(sync_buffer_, audio_cadence_) && audio_cadence_.front() * format_desc_.audio_channels == static_cast<int>(frame.audio_data().size())) 
                {       
                        // Audio sent so far is in sync, now we can send the next chunk.
                        result = consumer_->send(frame);
@@ -205,7 +207,7 @@ public:
                else
                        CASPAR_LOG(trace) << print() << L" Syncing audio.";
 
-               sync_buffer_.push_back(static_cast<int>(frame.audio_data().size()));
+               sync_buffer_.push_back(static_cast<int>(frame.audio_data().size() / format_desc_.audio_channels));
                
                return std::move(result);
        }
index f6aaf6d96e1d2760488787fb4c42032e329543fd..01e4f7b7c51a68e793f09c4d4cff337353f7538b 100644 (file)
@@ -180,7 +180,7 @@ public:
                        std::map<int, boost::unique_future<bool>> send_results;
 
                        // Start invocations
-                       for (auto it = ports_.begin(); it != ports_.end(); ++it)
+                       for (auto it = ports_.begin(); it != ports_.end();)
                        {
                                auto& port      = it->second;
                                auto& frame     = frames_.at(port.buffer_depth()-minmax.first);
@@ -188,11 +188,22 @@ public:
                                try
                                {
                                        send_results.insert(std::make_pair(it->first, port.send(frame)));
+                                       ++it;
                                }
                                catch (...)
                                {
                                        CASPAR_LOG_CURRENT_EXCEPTION();
-                                       ports_.erase(it);
+                                       try
+                                       {
+                                               send_results.insert(std::make_pair(it->first, port.send(frame)));
+                                               ++it;
+                                       }
+                                       catch(...)
+                                       {
+                                               CASPAR_LOG_CURRENT_EXCEPTION();
+                                               CASPAR_LOG(error) << "Failed to recover consumer: " << port.print() << L". Removing it.";
+                                               it = ports_.erase(it);
+                                       }
                                }
                        }
 
index 652690cb45aa4d883b5b3c5ce8ba8d2d3dab4382..b85849c9e6979e002a730cc3dbeddaa79a5ee80e 100644 (file)
@@ -33,7 +33,11 @@ public:
                event_subject_ << monitor::event("type") % consumer_->name();
                return consumer_->send(std::move(frame));
        }
-       
+       std::wstring print() const
+       {
+               return consumer_->print();
+       }
+
        int index() const
        {
                return index_;
@@ -64,6 +68,7 @@ void port::subscribe(const monitor::observable::observer_ptr& o){impl_->event_su
 void port::unsubscribe(const monitor::observable::observer_ptr& o){impl_->event_subject_.unsubscribe(o);}
 void port::video_format_desc(const struct video_format_desc& format_desc){impl_->video_format_desc(format_desc);}
 int port::buffer_depth() const{return impl_->buffer_depth();}
+std::wstring port::print() const{ return impl_->print();}
 bool port::has_synchronization_clock() const{return impl_->has_synchronization_clock();}
 boost::property_tree::wptree port::info() const{return impl_->info();}
 }}
\ No newline at end of file
index de21c520ce7d29a9d951f62001cbdd4373ceb71d..119deb0f71839af8ab19c4420fd87b5d40b6618f 100644 (file)
@@ -37,6 +37,7 @@ public:
        // Properties
 
        void video_format_desc(const struct video_format_desc& format_desc);
+       std::wstring print() const;
        int buffer_depth() const;
        bool has_synchronization_clock() const;
        boost::property_tree::wptree info() const;
index 8a4bc289f670f815af4af7e02244d34ede134e83..a970002992d4abd3504daaa9b6a5ff2d11f60e35 100644 (file)
@@ -181,9 +181,20 @@ public:
                audio_streams_ = std::move(next_audio_streams);
                
                if(audio_streams_.empty())              
-                       audio_streams_[nullptr].audio_data = audio_buffer_ps(audio_cadence_.front(), 0.0f);
+                       audio_streams_[nullptr].audio_data = audio_buffer_ps(audio_size(audio_cadence_.front()), 0.0f);
+
+               { // sanity check
+
+                       auto nb_invalid_streams = boost::count_if(audio_streams_ | boost::adaptors::map_values, [&](const audio_stream& x)
+                       {
+                               return x.audio_data.size() < audio_size(audio_cadence_.front());
+                       });
+
+                       if(nb_invalid_streams > 0)              
+                               CASPAR_LOG(trace) << "[audio_mixer] Incorrect frame audio cadence detected.";                   
+               }
                                
-               std::vector<float> result_ps(audio_cadence_.front(), 0.0f);
+               std::vector<float> result_ps(audio_size(audio_cadence_.front()), 0.0f);
                BOOST_FOREACH(auto& stream, audio_streams_ | boost::adaptors::map_values)
                {
                        if(stream.audio_data.size() < result_ps.size())
@@ -201,6 +212,11 @@ public:
                
                return result;
        }
+
+       size_t audio_size(size_t num_samples) const
+       {
+               return num_samples * format_desc_.audio_channels;
+       }
 };
 
 audio_mixer::audio_mixer() : impl_(new impl()){}
index b9f59e9283e33cc571a802a0663d7360ca19fc3e..9306e0185325cff22d25371d99fe8683afadc24a 100644 (file)
 namespace caspar { namespace core {
        
 const std::vector<video_format_desc> format_descs = boost::assign::list_of
-       (video_format_desc(video_format::pal,                    720,  576, 1024, 576,  field_mode::upper,                         25,     1, L"PAL",           boost::assign::list_of<int>(3840)                        ))
-       (video_format_desc(video_format::ntsc,                   720,  486,  720, 540,  field_mode::lower,                      30000,  1001, L"NTSC",          boost::assign::list_of<int>(3204)(3202)(3204)(3202)(3204)))
-       (video_format_desc(video_format::x576p2500,              720,  576,  720, 576,  field_mode::progressive,           25,     1, L"576p2500",      boost::assign::list_of<int>(3840)                        ))
-       (video_format_desc(video_format::x720p2398,             1280,  720, 1280, 720,  field_mode::progressive,        24000,  1001, L"720p2398",      boost::assign::list_of<int>(4004)                        )) 
-       (video_format_desc(video_format::x720p2400,             1280,  720, 1280, 720,  field_mode::progressive,           24,     1, L"720p2400",      boost::assign::list_of<int>(4000)                        )) 
-       (video_format_desc(video_format::x720p2500,             1280,  720, 1280, 720,  field_mode::progressive,           25,     1, L"720p2500",      boost::assign::list_of<int>(3840)                        )) 
-       (video_format_desc(video_format::x720p5000,             1280,  720, 1280, 720,  field_mode::progressive,           50,     1, L"720p5000",      boost::assign::list_of<int>(1920)                        )) 
-       (video_format_desc(video_format::x720p2997,             1280,  720, 1280, 720,  field_mode::progressive,        30000,  1001, L"720p2997",      boost::assign::list_of<int>(3204)(3202)(3204)(3202)(3204)))
-       (video_format_desc(video_format::x720p5994,             1280,  720, 1280, 720,  field_mode::progressive,        60000,  1001, L"720p5994",      boost::assign::list_of<int>(1602)(1601)(1602)(1601)(1602)))
-       (video_format_desc(video_format::x720p3000,             1280,  720, 1280, 720,  field_mode::progressive,           30,     1, L"720p3000",      boost::assign::list_of<int>(3200)                        ))
-       (video_format_desc(video_format::x720p6000,             1280,  720, 1280, 720,  field_mode::progressive,           60,     1, L"720p6000",      boost::assign::list_of<int>(1600)                        ))
-       (video_format_desc(video_format::x1080p2398,    1920, 1080, 1920, 1080, field_mode::progressive,        24000,  1001, L"1080p2398",     boost::assign::list_of<int>(4004)                        ))
-       (video_format_desc(video_format::x1080p2400,    1920, 1080, 1920, 1080, field_mode::progressive,           24,     1, L"1080p2400",     boost::assign::list_of<int>(4000)                        ))
-       (video_format_desc(video_format::x1080i5000,    1920, 1080, 1920, 1080, field_mode::upper,                         25,     1, L"1080i5000",     boost::assign::list_of<int>(3840)                        ))
-       (video_format_desc(video_format::x1080i5994,    1920, 1080, 1920, 1080, field_mode::upper,                      30000,  1001, L"1080i5994",     boost::assign::list_of<int>(3204)(3202)(3204)(3202)(3204)))
-       (video_format_desc(video_format::x1080i6000,    1920, 1080, 1920, 1080, field_mode::upper,                         30,     1, L"1080i6000",     boost::assign::list_of<int>(3200)                        ))
-       (video_format_desc(video_format::x1080p2500,    1920, 1080, 1920, 1080, field_mode::progressive,           25,     1, L"1080p2500",     boost::assign::list_of<int>(3840)                        ))
-       (video_format_desc(video_format::x1080p2997,    1920, 1080, 1920, 1080, field_mode::progressive,        30000,  1001, L"1080p2997",     boost::assign::list_of<int>(3204)(3202)(3204)(3202)(3204)))
-       (video_format_desc(video_format::x1080p3000,    1920, 1080, 1920, 1080, field_mode::progressive,           30,     1, L"1080p3000",     boost::assign::list_of<int>(3200)                        ))
-       (video_format_desc(video_format::x1080p5000,    1920, 1080, 1920, 1080, field_mode::progressive,           50,     1, L"1080p5000",     boost::assign::list_of<int>(1920)                        ))
-       (video_format_desc(video_format::x1080p5994,    1920, 1080, 1920, 1080, field_mode::progressive,        60000,  1001, L"1080p5994",     boost::assign::list_of<int>(1602)(1601)(1602)(1601)(1602)))
-       (video_format_desc(video_format::x1080p6000,    1920, 1080, 1920, 1080, field_mode::progressive,           60,     1, L"1080p6000",     boost::assign::list_of<int>(1600)                        ))
-       (video_format_desc(video_format::x2k2398,               2048, 1556, 2048, 1556, field_mode::progressive,    24000,  1001, L"2k2398",    boost::assign::list_of<int>(4004)                                                ))
-       (video_format_desc(video_format::x2k2400,               2048, 1556, 2048, 1556, field_mode::progressive,           24,     1, L"2k2400",        boost::assign::list_of<int>(4000)                                                ))
-       (video_format_desc(video_format::x2k2500,               2048, 1556, 2048, 1556, field_mode::progressive,       25,     1, L"2k2500",    boost::assign::list_of<int>(3840)                                                ))
-       (video_format_desc(video_format::x4k2398,               3840, 2160, 3840, 2160, field_mode::progressive,   24000,   1001, L"4k2398",    boost::assign::list_of<int>(4004)                                    ))
-       (video_format_desc(video_format::x4k2400,               3840, 2160, 3840, 2160, field_mode::progressive,      24,      1, L"4k2400",    boost::assign::list_of<int>(4000)                                                ))
-       (video_format_desc(video_format::x4k2500,               3840, 2160, 3840, 2160, field_mode::progressive,      25,      1, L"4k2500",    boost::assign::list_of<int>(3840)                                                ))
-       (video_format_desc(video_format::x4k2997,               3840, 2160, 3840, 2160, field_mode::progressive,   30000,   1001, L"4k2398",    boost::assign::list_of<int>(3204)(3202)(3204)(3202)(3204)))
-       (video_format_desc(video_format::x4k3000,               3840, 2160, 3840, 2160, field_mode::progressive,      30,      1, L"4k3000",    boost::assign::list_of<int>(3200)                                                ))
-       (video_format_desc(video_format::invalid,                  0,    0,    0,        0, field_mode::progressive,       1,      1, L"invalid",       boost::assign::list_of<int>(1)                           ));
+       (video_format_desc(video_format::pal,                    720,  576, 1024, 576,  field_mode::upper,                         25,     1, L"PAL",           boost::assign::list_of<int>(1920)                                                                                               ))
+       (video_format_desc(video_format::ntsc,                   720,  486,  720, 540,  field_mode::lower,                      30000,  1001, L"NTSC",          boost::assign::list_of<int>(1602)   (1601)    (1602)    (1601)    (1602)                ))
+       (video_format_desc(video_format::x576p2500,              720,  576,  720, 576,  field_mode::progressive,           25,     1, L"576p2500",      boost::assign::list_of<int>(1920)                                                                                               ))
+       (video_format_desc(video_format::x720p2398,             1280,  720, 1280, 720,  field_mode::progressive,        24000,  1001, L"720p2398",      boost::assign::list_of<int>(2002)                                                                                               )) 
+       (video_format_desc(video_format::x720p2400,             1280,  720, 1280, 720,  field_mode::progressive,           24,     1, L"720p2400",      boost::assign::list_of<int>(2000)                                                                                               )) 
+       (video_format_desc(video_format::x720p2500,             1280,  720, 1280, 720,  field_mode::progressive,           25,     1, L"720p2500",      boost::assign::list_of<int>(1920)                                                                                               )) 
+       (video_format_desc(video_format::x720p5000,             1280,  720, 1280, 720,  field_mode::progressive,           50,     1, L"720p5000",      boost::assign::list_of<int>(960)                                                                                                )) 
+       (video_format_desc(video_format::x720p2997,             1280,  720, 1280, 720,  field_mode::progressive,        30000,  1001, L"720p2997",      boost::assign::list_of<int>(1602)    (1601)    (1602)    (1601)    (1602)               ))
+       (video_format_desc(video_format::x720p5994,             1280,  720, 1280, 720,  field_mode::progressive,        60000,  1001, L"720p5994",      boost::assign::list_of<int>(801)(801)(800)(801)(801)(801)(800)(801)(801)(801)   ))
+       (video_format_desc(video_format::x720p3000,             1280,  720, 1280, 720,  field_mode::progressive,           30,     1, L"720p3000",      boost::assign::list_of<int>(1600)                                                                                               ))
+       (video_format_desc(video_format::x720p6000,             1280,  720, 1280, 720,  field_mode::progressive,           60,     1, L"720p6000",      boost::assign::list_of<int>(800)                                                                                                ))
+       (video_format_desc(video_format::x1080p2398,    1920, 1080, 1920, 1080, field_mode::progressive,        24000,  1001, L"1080p2398",     boost::assign::list_of<int>(2002)                                                                                               ))
+       (video_format_desc(video_format::x1080p2400,    1920, 1080, 1920, 1080, field_mode::progressive,           24,     1, L"1080p2400",     boost::assign::list_of<int>(2000)                                                                                               ))
+       (video_format_desc(video_format::x1080i5000,    1920, 1080, 1920, 1080, field_mode::upper,                         25,     1, L"1080i5000",     boost::assign::list_of<int>(1920)                                                                                               ))
+       (video_format_desc(video_format::x1080i5994,    1920, 1080, 1920, 1080, field_mode::upper,                      30000,  1001, L"1080i5994",     boost::assign::list_of<int>(1602)    (1601)    (1602)    (1601)    (1602)               ))
+       (video_format_desc(video_format::x1080i6000,    1920, 1080, 1920, 1080, field_mode::upper,                         30,     1, L"1080i6000",     boost::assign::list_of<int>(1600)                                                                                               ))
+       (video_format_desc(video_format::x1080p2500,    1920, 1080, 1920, 1080, field_mode::progressive,           25,     1, L"1080p2500",     boost::assign::list_of<int>(1920)                                                                                               ))
+       (video_format_desc(video_format::x1080p2997,    1920, 1080, 1920, 1080, field_mode::progressive,        30000,  1001, L"1080p2997",     boost::assign::list_of<int>(1602)    (1601)    (1602)    (1601)    (1602)               ))
+       (video_format_desc(video_format::x1080p3000,    1920, 1080, 1920, 1080, field_mode::progressive,           30,     1, L"1080p3000",     boost::assign::list_of<int>(1600)                                                                                               ))
+       (video_format_desc(video_format::x1080p5000,    1920, 1080, 1920, 1080, field_mode::progressive,           50,     1, L"1080p5000",     boost::assign::list_of<int>(960)                                                                                                ))
+       (video_format_desc(video_format::x1080p5994,    1920, 1080, 1920, 1080, field_mode::progressive,        60000,  1001, L"1080p5994",     boost::assign::list_of<int>(801)(801)(800)(801)(801)(801)(800)(801)(801)(801)   ))
+       (video_format_desc(video_format::x1080p6000,    1920, 1080, 1920, 1080, field_mode::progressive,           60,     1, L"1080p6000",     boost::assign::list_of<int>(800)                                                                                                ))
+       (video_format_desc(video_format::x2k2398,               2048, 1556, 2048, 1556, field_mode::progressive,    24000,  1001, L"2k2398",    boost::assign::list_of<int>(2002)                                                                                               ))
+       (video_format_desc(video_format::x2k2400,               2048, 1556, 2048, 1556, field_mode::progressive,           24,     1, L"2k2400",        boost::assign::list_of<int>(2000)                                                                                               ))
+       (video_format_desc(video_format::x2k2500,               2048, 1556, 2048, 1556, field_mode::progressive,       25,     1, L"2k2500",    boost::assign::list_of<int>(1920)                                                                                               ))
+       (video_format_desc(video_format::x4k2398,               3840, 2160, 3840, 2160, field_mode::progressive,   24000,   1001, L"4k2398",    boost::assign::list_of<int>(2002)                                                                                               ))
+       (video_format_desc(video_format::x4k2400,               3840, 2160, 3840, 2160, field_mode::progressive,      24,      1, L"4k2400",    boost::assign::list_of<int>(2000)                                                                                               ))
+       (video_format_desc(video_format::x4k2500,               3840, 2160, 3840, 2160, field_mode::progressive,      25,      1, L"4k2500",    boost::assign::list_of<int>(1920)                                                                                               ))
+       (video_format_desc(video_format::x4k2997,               3840, 2160, 3840, 2160, field_mode::progressive,   30000,   1001, L"4k2398",    boost::assign::list_of<int>(1602)    (1601)    (1602)    (1601)    (1602)               ))
+       (video_format_desc(video_format::x4k3000,               3840, 2160, 3840, 2160, field_mode::progressive,      30,      1, L"4k3000",    boost::assign::list_of<int>(1600)                                                                                               ))
+       (video_format_desc(video_format::invalid,                  0,    0,    0,        0, field_mode::progressive,       1,      1, L"invalid",       boost::assign::list_of<int>(1)                                                                                                  ));
+
 
 video_format_desc::video_format_desc(video_format format,
                                        int width,
index 0d9eee8718b85c155f9ab78b083d845561962ad3..56999b093c3fe52621acceb3de08408fcd8e78ca 100644 (file)
@@ -100,7 +100,7 @@ struct video_format_desc sealed
 
        int                                     audio_sample_rate;
        int                                     audio_channels;
-       std::vector<int>        audio_cadence;
+       std::vector<int>        audio_cadence;  // rotating optimal number of samples per frame
 
        video_format_desc(video_format format,
                                          int width,
index cbe48d10469d461559b95edcded08f08582b8ce8..23421ff0275a85bba14a45cbe8c1e003b1917ad4 100644 (file)
@@ -302,6 +302,10 @@ struct bluefish_consumer_proxy : public core::frame_consumer
        const int                                                       device_index_;
        const bool                                                      embedded_audio_;
        const bool                                                      key_only_;
+
+       std::vector<int>                                        audio_cadence_;
+       core::video_format_desc                         format_desc_;
+
 public:
 
        bluefish_consumer_proxy(int device_index, bool embedded_audio, bool key_only)
@@ -315,12 +319,17 @@ public:
        
        void initialize(const core::video_format_desc& format_desc, int channel_index) override
        {
+               format_desc_ = format_desc;
+               audio_cadence_ = format_desc.audio_cadence;
+
                consumer_.reset();
                consumer_.reset(new bluefish_consumer(format_desc, device_index_, embedded_audio_, key_only_, channel_index));
        }
        
        boost::unique_future<bool> send(core::const_frame frame) override
        {
+               CASPAR_VERIFY(audio_cadence_.front() * format_desc_.audio_channels == static_cast<size_t>(frame.audio_data().size()));
+               boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);
                return consumer_->send(frame);
        }
                
index 769ebc07b48a5f418075b2aa0dd16ef70c49a995..f5e0e69ef18b1830a32d47c1019ab0646d30d8f9 100644 (file)
@@ -129,12 +129,12 @@ public:
        // IDecklinkVideoFrame
 
        STDMETHOD_(long,                        GetWidth())                     {return static_cast<long>(format_desc_.width);}        
-    STDMETHOD_(long,                   GetHeight())            {return static_cast<long>(format_desc_.height);}        
-    STDMETHOD_(long,                   GetRowBytes())          {return static_cast<long>(format_desc_.width*4);}        
+       STDMETHOD_(long,                        GetHeight())            {return static_cast<long>(format_desc_.height);}        
+       STDMETHOD_(long,                        GetRowBytes())          {return static_cast<long>(format_desc_.width*4);}        
        STDMETHOD_(BMDPixelFormat,      GetPixelFormat())       {return bmdFormat8BitBGRA;}        
-    STDMETHOD_(BMDFrameFlags,  GetFlags())                     {return bmdFrameFlagDefault;}
-        
-    STDMETHOD(GetBytes(void** buffer))
+       STDMETHOD_(BMDFrameFlags,       GetFlags())                     {return bmdFrameFlagDefault;}
+               
+       STDMETHOD(GetBytes(void** buffer))
        {
                try
                {
@@ -163,9 +163,9 @@ public:
 
                return S_OK;
        }
-        
-    STDMETHOD(GetTimecode(BMDTimecodeFormat format, IDeckLinkTimecode** timecode)){return S_FALSE;}        
-    STDMETHOD(GetAncillaryData(IDeckLinkVideoFrameAncillary** ancillary))                {return S_FALSE;}
+               
+       STDMETHOD(GetTimecode(BMDTimecodeFormat format, IDeckLinkTimecode** timecode)){return S_FALSE;}        
+       STDMETHOD(GetAncillaryData(IDeckLinkVideoFrameAncillary** ancillary))             {return S_FALSE;}
 
        // decklink_frame       
 
@@ -229,7 +229,11 @@ public:
                is_running_ = true;
                                
                video_frame_buffer_.set_capacity(1);
-               audio_frame_buffer_.set_capacity(1);
+
+               // Blackmagic calls RenderAudioSamples() 50 times per second
+               // regardless of video mode so we sometimes need to give them
+               // samples from 2 frames in order to keep up
+               audio_frame_buffer_.set_capacity((format_desc.fps > 50.0) ? 2 : 1);
 
                graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f));   
                graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f));
@@ -411,19 +415,24 @@ public:
                                        start_playback();                               
                                }
                                else
-                                       schedule_next_audio(core::audio_buffer(format_desc_.audio_cadence[preroll % format_desc_.audio_cadence.size()], 0));    
+                               {
+                                       schedule_next_audio(core::audio_buffer(format_desc_.audio_cadence[preroll % format_desc_.audio_cadence.size()] * format_desc_.audio_channels, 0));
+                               }
                        }
                        else
                        {
                                auto frame = core::const_frame::empty();
-                               audio_frame_buffer_.pop(frame);
-                               send_completion_.try_completion();
-                               schedule_next_audio(frame.audio_data());
+
+                               while(audio_frame_buffer_.try_pop(frame))
+                               {
+                                       send_completion_.try_completion();
+                                       schedule_next_audio(frame.audio_data());
+                               }
                        }
 
                        unsigned long buffered;
                        output_->GetBufferedAudioSampleFrameCount(&buffered);
-                       graph_->set_value("buffered-audio", static_cast<double>(buffered)/(format_desc_.audio_cadence[0]*2));
+                       graph_->set_value("buffered-audio", static_cast<double>(buffered)/(format_desc_.audio_cadence[0]*format_desc_.audio_channels*2));
                }
                catch(...)
                {
index 1a9eac90c64928e5e7cfe8c3feb073448452609c..331aa3f818332731d07a4fa351fed23b2d3373da 100644 (file)
@@ -241,7 +241,7 @@ public:
                        // Note: Uses 1 step rotated cadence for 1001 modes (1602, 1602, 1601, 1602, 1601)
                        // This cadence fills the audio mixer most optimally.
 
-                       sync_buffer_.push_back(audio->GetSampleFrameCount()*out_format_desc_.audio_channels);           
+                       sync_buffer_.push_back(audio->GetSampleFrameCount());           
                        if(!boost::range::equal(sync_buffer_, audio_cadence_))
                        {
                                CASPAR_LOG(trace) << print() << L" Syncing audio.";
index 36b747a0e788450f8b1f653e8586d5b96d89a767..99bfb0ddc11554a996fea96c9f805b4ddbc3b940 100644 (file)
@@ -127,7 +127,7 @@ struct frame_muxer::impl : boost::noncopyable
 
                if(!audio->data[0])             
                {
-                       boost::range::push_back(audio_stream_, core::audio_buffer(audio_cadence_.front(), 0));  
+                       boost::range::push_back(audio_stream_, core::audio_buffer(audio_cadence_.front() * format_desc_.audio_channels, 0));    
                }
                else
                {
@@ -156,9 +156,9 @@ struct frame_muxer::impl : boost::noncopyable
                switch(display_mode_)
                {
                case display_mode::duplicate:                                   
-                       return audio_stream_.size() >= static_cast<size_t>(audio_cadence_[0] + audio_cadence_[1 % audio_cadence_.size()]);
+                       return audio_stream_.size() >= static_cast<size_t>(audio_cadence_[0] + audio_cadence_[1 % audio_cadence_.size()])*format_desc_.audio_channels;
                default:                                                                                
-                       return audio_stream_.size() >= static_cast<size_t>(audio_cadence_.front());
+                       return audio_stream_.size() >= static_cast<size_t>(audio_cadence_.front()) * format_desc_.audio_channels;
                }
        }
 
@@ -235,11 +235,11 @@ struct frame_muxer::impl : boost::noncopyable
 
        core::audio_buffer pop_audio()
        {
-               if(audio_stream_.size() < audio_cadence_.front())
+               if(audio_stream_.size() < audio_cadence_.front() * format_desc_.audio_channels)
                        CASPAR_THROW_EXCEPTION(out_of_range());
 
                auto begin = audio_stream_.begin();
-               auto end   = begin + audio_cadence_.front();
+               auto end   = begin + audio_cadence_.front() * format_desc_.audio_channels;
 
                core::audio_buffer samples(begin, end);
                audio_stream_.erase(begin, end);
index 43455fbada1527bd8996e9e79ed24dc32d922e33..a8d33915f36fe76eb576bfa3294d1019b5406e33 100644 (file)
@@ -164,7 +164,7 @@ public:
 
                        for(std::size_t n = 0; n < buffers_.size(); ++n)
                        {
-                               std::vector<int16_t> audio(format_desc_.audio_cadence[n % format_desc_.audio_cadence.size()], 0);
+                               std::vector<int16_t> audio(format_desc_.audio_cadence[n % format_desc_.audio_cadence.size()]*format_desc_.audio_channels, 0);
                                alBufferData(buffers_[n], AL_FORMAT_STEREO16, audio.data(), static_cast<ALsizei>(audio.size()*sizeof(int16_t)), format_desc_.audio_sample_rate);
                                alSourceQueueBuffers(source_, 1, &buffers_[n]);
                        }
@@ -191,7 +191,7 @@ public:
                                        alSourceUnqueueBuffers(source_, 1, &buffer);
                                        if(buffer)
                                        {
-                                               std::vector<int16_t> audio(format_desc_.audio_cadence[n % format_desc_.audio_cadence.size()], 0);
+                                               std::vector<int16_t> audio(format_desc_.audio_cadence[n % format_desc_.audio_cadence.size()] * format_desc_.audio_channels, 0);
                                                alBufferData(buffer, AL_FORMAT_STEREO16, audio.data(), static_cast<ALsizei>(audio.size()*sizeof(int16_t)), format_desc_.audio_sample_rate);
                                                alSourceQueueBuffers(source_, 1, &buffer);
                                        }
index a0a3e5faccedbdc7bbbb30aae8c0f21e66566794..cc877bada57287842370fc127bd19edd3622094c 100644 (file)
@@ -1957,10 +1957,17 @@ bool ThumbnailCommand::DoExecuteGenerateAll()
 
 bool KillCommand::DoExecute()
 {
-       shutdown_server_now_->set_value(false); //false for not waiting for keypress
+       shutdown_server_now_->set_value(false); //false for not attempting to restart
        SetReplyString(TEXT("202 KILL OK\r\n"));
        return true;
 }
 
+bool RestartCommand::DoExecute()
+{
+       shutdown_server_now_->set_value(true);  //true for attempting to restart
+       SetReplyString(TEXT("202 RESTART OK\r\n"));
+       return true;
+}
+
 }      //namespace amcp
 }}     //namespace caspar
\ No newline at end of file
index 8fca23c89ca73be26b5ec388ba627ae11f725f75..4729960f1adc2ce0f06596270e52fcc7d8083cfc 100644 (file)
@@ -322,23 +322,16 @@ private:
        boost::promise<bool>* shutdown_server_now_;
 };
 
-//class KillCommand : public AMCPCommand
-//{
-//public:
-//     KillCommand() {}
-//     virtual bool DoExecute();
-//     virtual AMCPCommandCondition CheckConditions();
-//
-//     virtual bool NeedChannel() {
-//             return false;
-//     }
-//     virtual AMCPCommandScheduling GetDefaultScheduling() {
-//             return AddToQueue;
-//     }
-//     virtual int GetMinimumParameters() {
-//             return 0;
-//     }
-//};
+class RestartCommand : public AMCPCommandBase<0> 
+{
+public:
+       RestartCommand(IO::ClientInfoPtr client, boost::promise<bool>& shutdown_server_now) : AMCPCommandBase(client), shutdown_server_now_(&shutdown_server_now) {}
+       std::wstring print() const { return L"RestartCommand";}
+       bool DoExecute();
+
+private:
+       boost::promise<bool>* shutdown_server_now_;
+};
 
 }      //namespace amcp
 }}     //namespace caspar
index c461fe17bc32d7fc139a3116e10c35932f8b3020..cc15b5f5cd0361b54027b2fe4e50fa814d6f7bab 100644 (file)
@@ -359,6 +359,7 @@ private:
                else if(s == TEXT("LOG"))                       return std::make_shared<LogCommand>(client);
                else if(s == TEXT("THUMBNAIL"))         return std::make_shared<ThumbnailCommand>(client, thumb_gen_);
                else if(s == TEXT("KILL"))                      return std::make_shared<KillCommand>(client, shutdown_server_now_);
+               else if(s == TEXT("RESTART"))           return std::make_shared<RestartCommand>(client, shutdown_server_now_);
 
                return nullptr;
        }
diff --git a/shell/casparcg_auto_restart.bat b/shell/casparcg_auto_restart.bat
new file mode 100644 (file)
index 0000000..9aef2b3
--- /dev/null
@@ -0,0 +1,7 @@
+@Echo off
+:Start
+SET ERRORLEVEL 0
+
+casparcg.exe
+
+if ERRORLEVEL 5 goto :Start
index c10c2a6f719a48442dcddee7c8ffa01da914daa8..fc86da8c0ec2c2ee2d820750d99cdf97bd322aae 100644 (file)
@@ -316,6 +316,7 @@ void on_abort(int)
 
 int main(int argc, wchar_t* argv[])
 {      
+       int return_code = 0;
        SetUnhandledExceptionFilter(UserUnhandledExceptionFilter);
        signal(SIGABRT, on_abort);
 
@@ -391,12 +392,10 @@ int main(int argc, wchar_t* argv[])
                boost::property_tree::write_xml(str, env::properties(), w);
                CASPAR_LOG(info) << L"casparcg.config:\n-----------------------------------------\n" << str.str().c_str() << L"-----------------------------------------";
                
-               auto wait = run();
+               return_code = run() ? 5 : 0;
                
                Sleep(500);
                CASPAR_LOG(info) << "Successfully shutdown CasparCG Server.";
-
-               if(wait) system("pause");       
        }
        catch(boost::property_tree::file_parser_error&)
        {
@@ -413,5 +412,5 @@ int main(int argc, wchar_t* argv[])
                Sleep(4000);
        }               
        
-       return 0;
+       return return_code;
 }
\ No newline at end of file
index 44be3361b724d455ad6066eddce38b0ab401b28a..78088c4d184e50d9fdee2a5719683efc359d2e14 100644 (file)
@@ -70,6 +70,7 @@
       <SubType>Designer</SubType>\r
     </None>\r
     <None Include="CasparCG.ico" />\r
+    <None Include="casparcg_auto_restart.bat" />\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="server.h" />\r
@@ -176,7 +177,9 @@ copy "$(SolutionDir)dependencies64\tbb\bin\*.dll" "$(OutDir)"
 copy "$(SolutionDir)dependencies64\glew\bin\*.dll" "$(OutDir)"\r
 copy "$(SolutionDir)dependencies64\freeimage\bin\*.dll" "$(OutDir)"\r
 copy "$(SolutionDir)dependencies64\openal\bin\*.dll" "$(OutDir)"\r
-copy "$(ProjectDir)casparcg.config" "$(OutDir)"</Command>\r
+copy "$(ProjectDir)casparcg.config" "$(OutDir)"\r
+copy "$(ProjectDir)casparcg_auto_restart.bat" "$(OutDir)"\r
+</Command>\r
     </PostBuildEvent>\r
   </ItemDefinitionGroup>\r
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">\r
@@ -223,7 +226,8 @@ copy "$(SolutionDir)dependencies64\tbb\bin\*.dll" "$(OutDir)"
 copy "$(SolutionDir)dependencies64\glew\bin\*.dll" "$(OutDir)"\r
 copy "$(SolutionDir)dependencies64\freeimage\bin\*.dll" "$(OutDir)"\r
 copy "$(SolutionDir)dependencies64\openal\bin\*.dll" "$(OutDir)"\r
-copy "$(ProjectDir)casparcg.config" "$(OutDir)"</Command>\r
+copy "$(ProjectDir)casparcg.config" "$(OutDir)"\r
+copy "$(ProjectDir)casparcg_auto_restart.bat" "$(OutDir)"</Command>\r
     </PostBuildEvent>\r
   </ItemDefinitionGroup>\r
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
index 30fdc61e0b7b0d86779725121a9cbe3671492363..06b5d5743d17f48215a361c17d9810913701718e 100644 (file)
@@ -14,6 +14,7 @@
   <ItemGroup>\r
     <None Include="casparcg.config" />\r
     <None Include="CasparCG.ico" />\r
+    <None Include="casparcg_auto_restart.bat" />\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="server.h">\r