- static std::vector<unsigned char> zeros(1920*1080*4, 0);\r
- *buffer = const_cast<unsigned char*>(frame_->image_data().begin());\r
+ static std::vector<uint8_t> zeros(1920*1080*4, 0);\r
+ *buffer = const_cast<uint8_t*>(frame_->image_data().begin());\r
if(static_cast<size_t>(frame_->image_data().size()) != format_desc_.size)\r
*buffer = zeros.data();\r
return S_OK;\r
if(static_cast<size_t>(frame_->image_data().size()) != format_desc_.size)\r
*buffer = zeros.data();\r
return S_OK;\r
- const std::wstring model_name_;\r
- const core::video_format_desc format_desc_;\r
- const size_t buffer_size_;\r
+ const std::wstring model_name_;\r
+ const core::video_format_desc format_desc_;\r
+ const size_t buffer_size_;\r
- tbb::concurrent_bounded_queue<std::shared_ptr<const core::read_frame>> video_frame_buffer_;\r
- tbb::concurrent_bounded_queue<std::shared_ptr<const core::read_frame>> audio_frame_buffer_;\r
+ tbb::concurrent_bounded_queue<std::shared_ptr<core::read_frame>> video_frame_buffer_;\r
+ tbb::concurrent_bounded_queue<std::shared_ptr<core::read_frame>> audio_frame_buffer_;\r
\r
graph_ = diagnostics::create_graph(narrow(print()));\r
graph_->add_guide("tick-time", 0.5);\r
\r
graph_ = diagnostics::create_graph(narrow(print()));\r
graph_->add_guide("tick-time", 0.5);\r
- graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
+ graph_->set_color("tick-time", diagnostics::color(0.0f, 0.6f, 0.9f)); \r
graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f));\r
graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
graph_->set_color("late-frame", diagnostics::color(0.6f, 0.3f, 0.3f));\r
graph_->set_color("dropped-frame", diagnostics::color(0.3f, 0.6f, 0.3f));\r
- graph_->set_color("flushed-frame", diagnostics::color(0.3f, 0.3f, 0.6f));\r
+ graph_->set_color("flushed-frame", diagnostics::color(0.4f, 0.3f, 0.8f));\r
\r
enable_video(get_display_mode(output_, format_desc_.format, bmdFormat8BitBGRA, bmdVideoOutputFlagDefault));\r
\r
\r
enable_video(get_display_mode(output_, format_desc_.format, bmdFormat8BitBGRA, bmdVideoOutputFlagDefault));\r
\r
\r
if(config.embedded_audio) \r
output_->BeginAudioPreroll(); \r
\r
for(size_t n = 0; n < buffer_size_; ++n)\r
\r
if(config.embedded_audio) \r
output_->BeginAudioPreroll(); \r
\r
for(size_t n = 0; n < buffer_size_; ++n)\r
- video_frame_buffer_.try_push(core::read_frame::empty());\r
- audio_frame_buffer_.try_push(core::read_frame::empty());\r
+ video_frame_buffer_.try_push(std::make_shared<core::read_frame>());\r
+ audio_frame_buffer_.try_push(std::make_shared<core::read_frame>());\r
{\r
if(FAILED(keyer_->Enable(FALSE))) \r
CASPAR_LOG(error) << print() << L" Failed to enable internal keyer."; \r
{\r
if(FAILED(keyer_->Enable(FALSE))) \r
CASPAR_LOG(error) << print() << L" Failed to enable internal keyer."; \r
BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not enable video output."));\r
\r
if(FAILED(output_->SetScheduledFrameCompletionCallback(this)))\r
BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Could not enable video output."));\r
\r
if(FAILED(output_->SetScheduledFrameCompletionCallback(this)))\r
- BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(print()) + " Failed to set playback completion callback."));\r
+ BOOST_THROW_EXCEPTION(caspar_exception() \r
+ << msg_info(narrow(print()) + " Failed to set playback completion callback.")\r
+ << boost::errinfo_api_function("SetScheduledFrameCompletionCallback"));\r
else if(result == bmdOutputFrameDropped)\r
graph_->add_tag("dropped-frame");\r
else if(result == bmdOutputFrameFlushed)\r
graph_->add_tag("flushed-frame");\r
\r
else if(result == bmdOutputFrameDropped)\r
graph_->add_tag("dropped-frame");\r
else if(result == bmdOutputFrameFlushed)\r
graph_->add_tag("flushed-frame");\r
\r
- frame_container_.erase(std::find_if(frame_container_.begin(), frame_container_.end(), [&](const std::shared_ptr<IDeckLinkVideoFrame> frame)\r
+ frame_container_.erase(std::find_if(frame_container_.begin(), frame_container_.end(), [&](const std::shared_ptr<IDeckLinkVideoFrame>& frame)\r
- std::shared_ptr<const core::read_frame> frame; \r
- video_frame_buffer_.pop(frame); \r
- schedule_next_video(safe_ptr<const core::read_frame>(frame)); \r
+ std::shared_ptr<core::read_frame> frame; \r
+ video_frame_buffer_.pop(frame); \r
+ schedule_next_video(make_safe(frame)); \r
- static std::vector<short> silence(48000, 0);\r
- \r
- const int sample_count = format_desc_.audio_samples_per_frame;\r
- const int sample_frame_count = sample_count/2;\r
+ const int sample_frame_count = frame->audio_data().size()/format_desc_.audio_channels;\r
- const short* frame_audio_data = frame->audio_data().size() == sample_count ? frame->audio_data().begin() : silence.data();\r
- audio_container_.push_back(std::vector<short>(frame_audio_data, frame_audio_data+sample_count));\r
+ audio_container_.push_back(std::vector<int16_t>(frame->audio_data().begin(), frame->audio_data().end()));\r
\r
if(FAILED(output_->ScheduleAudioSamples(audio_container_.back().data(), sample_frame_count, (audio_scheduled_++) * sample_frame_count, format_desc_.audio_sample_rate, nullptr)))\r
CASPAR_LOG(error) << print() << L" Failed to schedule audio.";\r
}\r
\r
\r
if(FAILED(output_->ScheduleAudioSamples(audio_container_.back().data(), sample_frame_count, (audio_scheduled_++) * sample_frame_count, format_desc_.audio_sample_rate, nullptr)))\r
CASPAR_LOG(error) << print() << L" Failed to schedule audio.";\r
}\r
\r
if(FAILED(output_->ScheduleVideoFrame(frame_container_.back().get(), (frames_scheduled_++) * format_desc_.duration, format_desc_.duration, format_desc_.time_scale)))\r
CASPAR_LOG(error) << print() << L" Failed to schedule video.";\r
\r
if(FAILED(output_->ScheduleVideoFrame(frame_container_.back().get(), (frames_scheduled_++) * format_desc_.duration, format_desc_.duration, format_desc_.time_scale)))\r
CASPAR_LOG(error) << print() << L" Failed to schedule video.";\r
\r
- if(exception_ != nullptr)\r
- std::rethrow_exception(exception_);\r
+ {\r
+ tbb::spin_mutex::scoped_lock lock(exception_mutex_);\r
+ if(exception_ != nullptr)\r
+ std::rethrow_exception(exception_);\r
+ }\r
- const configuration config_;\r
-\r
- com_context<decklink_consumer> context_;\r
+ const configuration config_;\r
+ com_context<decklink_consumer> context_;\r
+ core::video_format_desc format_desc_;\r
+ size_t fail_count_;\r
- context_->send(frame);\r
+ if(!context_)\r
+ context_.reset([&]{return new decklink_consumer(config_, format_desc_);});\r
+\r
+ try\r
+ {\r
+ context_->send(frame);\r
+ fail_count_ = 0;\r
+ }\r
+ catch(...)\r
+ {\r
+ context_.reset();\r
+\r
+ if(fail_count_++ > 3)\r
+ return false; // Outside didn't handle exception properly, just give up.\r
+ \r
+ throw;\r
+ }\r
+\r
+ return true;\r
config.low_latency = std::find(params.begin(), params.end(), L"LOW_LATENCY") != params.end();\r
config.embedded_audio = std::find(params.begin(), params.end(), L"EMBEDDED_AUDIO") != params.end();\r
config.key_only = std::find(params.begin(), params.end(), L"KEY_ONLY") != params.end();\r
config.low_latency = std::find(params.begin(), params.end(), L"LOW_LATENCY") != params.end();\r
config.embedded_audio = std::find(params.begin(), params.end(), L"EMBEDDED_AUDIO") != params.end();\r
config.key_only = std::find(params.begin(), params.end(), L"KEY_ONLY") != params.end();\r
config.low_latency = ptree.get("low-latency", config.low_latency);\r
config.key_only = ptree.get("key-only", config.key_only);\r
config.device_index = ptree.get("device", config.device_index);\r
config.embedded_audio = ptree.get("embedded-audio", config.embedded_audio);\r
config.low_latency = ptree.get("low-latency", config.low_latency);\r
config.key_only = ptree.get("key-only", config.key_only);\r
config.device_index = ptree.get("device", config.device_index);\r
config.embedded_audio = ptree.get("embedded-audio", config.embedded_audio);\r