X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fdecklink%2Fconsumer%2Fdecklink_consumer.cpp;h=9895fac1017938bf67154049f9399b55d997cc73;hb=51e34f2513d2a26f7da4681b53748a8b24ad8dc1;hp=a68513157bafad1383988aabfd2cc6e08b664be8;hpb=07ea8ea982ca19ebbfcf21bb575e107fc0495588;p=casparcg diff --git a/modules/decklink/consumer/decklink_consumer.cpp b/modules/decklink/consumer/decklink_consumer.cpp index a68513157..9895fac10 100644 --- a/modules/decklink/consumer/decklink_consumer.cpp +++ b/modules/decklink/consumer/decklink_consumer.cpp @@ -28,7 +28,6 @@ #include -#include #include #include #include @@ -43,7 +42,10 @@ #include #include -namespace caspar { +#include +#include + +namespace caspar { namespace decklink { struct configuration { @@ -52,15 +54,21 @@ struct configuration bool internal_key; bool low_latency; bool key_only; - size_t buffer_depth; configuration() : device_index(1) , embedded_audio(false) , internal_key(false) , low_latency(false) - , key_only(false) - , buffer_depth(core::consumer_buffer_depth()){} + , key_only(false){} + + size_t preroll_count() const + { + size_t count = 0; + count += low_latency ? 2 : 3; + count += embedded_audio ? 1 : 0; + return count; + } }; class decklink_frame : public IDeckLinkVideoFrame @@ -101,7 +109,7 @@ public: STDMETHOD(GetBytes(void** buffer)) { - static std::vector zeros(1920*1080*4, 0); + static std::vector> zeros(1920*1080*4, 0); if(static_cast(frame_->image_data().size()) != format_desc_.size) { *buffer = zeros.data(); @@ -137,8 +145,7 @@ struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLink CComQIPtr configuration_; CComQIPtr keyer_; - tbb::spin_mutex exception_mutex_; - std::exception_ptr exception_; + Concurrency::overwrite_buffer exception_; tbb::atomic is_running_; @@ -151,12 +158,12 @@ struct decklink_consumer : public IDeckLinkVideoOutputCallback, public IDeckLink size_t preroll_count_; - boost::circular_buffer> audio_container_; + boost::circular_buffer> audio_container_; tbb::concurrent_bounded_queue> video_frame_buffer_; tbb::concurrent_bounded_queue> audio_frame_buffer_; - std::shared_ptr graph_; + safe_ptr graph_; boost::timer tick_timer_; public: @@ -168,7 +175,7 @@ public: , keyer_(decklink_) , model_name_(get_model_name(decklink_)) , format_desc_(format_desc) - , buffer_size_(config.embedded_audio ? config.buffer_depth + 1 : config.buffer_depth) // Minimum buffer-size 3. + , buffer_size_(config.preroll_count()) , frames_scheduled_(0) , audio_scheduled_(0) , preroll_count_(0) @@ -179,12 +186,13 @@ public: video_frame_buffer_.set_capacity(1); audio_frame_buffer_.set_capacity(1); - graph_ = diagnostics::create_graph(narrow(print())); graph_->add_guide("tick-time", 0.5); 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)); graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f)); graph_->set_color("flushed-frame", diagnostics::color(0.4f, 0.3f, 0.8f)); + graph_->set_text(print()); + diagnostics::register_graph(graph_); enable_video(get_display_mode(output_, format_desc_.format, bmdFormat8BitBGRA, bmdVideoOutputFlagDefault)); @@ -262,7 +270,7 @@ public: void enable_audio() { - if(FAILED(output_->EnableAudioOutput(bmdAudioSampleRate48kHz, bmdAudioSampleType16bitInteger, 2, bmdAudioOutputStreamTimestamped))) + if(FAILED(output_->EnableAudioOutput(bmdAudioSampleRate48kHz, bmdAudioSampleType32bitInteger, 2, bmdAudioOutputStreamTimestamped))) BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not enable audio output.")); if(FAILED(output_->SetAudioCallback(this))) @@ -319,12 +327,11 @@ public: std::shared_ptr frame; video_frame_buffer_.pop(frame); - schedule_next_video(make_safe(frame)); + schedule_next_video(make_safe_ptr(frame)); } catch(...) { - tbb::spin_mutex::scoped_lock lock(exception_mutex_); - exception_ = std::current_exception(); + Concurrency::send(exception_, std::current_exception()); return E_FAIL; } @@ -352,13 +359,12 @@ public: { std::shared_ptr frame; audio_frame_buffer_.pop(frame); - schedule_next_audio(make_safe(frame)); + schedule_next_audio(make_safe_ptr(frame)); } } catch(...) { - tbb::spin_mutex::scoped_lock lock(exception_mutex_); - exception_ = std::current_exception(); + Concurrency::send(exception_, std::current_exception()); return E_FAIL; } @@ -369,7 +375,7 @@ public: { const int sample_frame_count = frame->audio_data().size()/format_desc_.audio_channels; - audio_container_.push_back(std::vector(frame->audio_data().begin(), frame->audio_data().end())); + audio_container_.push_back(std::vector(frame->audio_data().begin(), frame->audio_data().end())); if(FAILED(output_->ScheduleAudioSamples(audio_container_.back().data(), sample_frame_count, (audio_scheduled_++) * sample_frame_count, format_desc_.audio_sample_rate, nullptr))) CASPAR_LOG(error) << print() << L" Failed to schedule audio."; @@ -387,15 +393,13 @@ public: void send(const safe_ptr& frame) { - { - tbb::spin_mutex::scoped_lock lock(exception_mutex_); - if(exception_ != nullptr) - std::rethrow_exception(exception_); - } + if(exception_.has_value()) + std::rethrow_exception(exception_.value()); if(!is_running_) BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Is not running.")); + Concurrency::scoped_oversubcription_token oversubscribe; if(config_.embedded_audio) audio_frame_buffer_.push(frame); video_frame_buffer_.push(frame); @@ -409,14 +413,13 @@ public: struct decklink_consumer_proxy : public core::frame_consumer { - const configuration config_; - com_context context_; - core::video_format_desc format_desc_; + const configuration config_; + std::unique_ptr context_; + core::video_format_desc format_desc_; public: decklink_consumer_proxy(const configuration& config) : config_(config) - , context_(L"decklink_consumer[" + boost::lexical_cast(config.device_index) + L"]") { } @@ -429,8 +432,15 @@ public: virtual void initialize(const core::video_format_desc& format_desc) { + Concurrency::scoped_oversubcription_token oversubscribe; format_desc_ = format_desc; - context_.reset([&]{return new decklink_consumer(config_, format_desc_);}); + struct co_init + { + co_init(){CoInitialize(nullptr);} + ~co_init(){CoUninitialize();} + } init; + context_ = nullptr; + context_.reset(new decklink_consumer(config_, format_desc_)); CASPAR_LOG(info) << print() << L" Successfully Initialized."; } @@ -452,7 +462,7 @@ public: } }; -safe_ptr create_decklink_consumer(const std::vector& params) +safe_ptr create_consumer(const std::vector& params) { if(params.size() < 1 || params[0] != L"DECKLINK") return core::frame_consumer::empty(); @@ -470,7 +480,7 @@ safe_ptr create_decklink_consumer(const std::vector(config); } -safe_ptr create_decklink_consumer(const boost::property_tree::ptree& ptree) +safe_ptr create_consumer(const boost::property_tree::ptree& ptree) { configuration config; @@ -483,7 +493,7 @@ safe_ptr create_decklink_consumer(const boost::property_tr return make_safe(config); } -} +}} /* ##############################################################################