std::vector<float> result_ps(audio_cadence_.front(), 0.0f);\r
BOOST_FOREACH(auto& stream, audio_streams_ | boost::adaptors::map_values)\r
{\r
+ //CASPAR_LOG(debug) << stream.audio_data.size() << L" : " << result_ps.size();\r
+\r
+ if(stream.audio_data.size() < result_ps.size())\r
+ {\r
+ stream.audio_data.resize(result_ps.size(), 0.0f);\r
+ CASPAR_LOG(trace) << L"[audio_mixer] Appended zero samples";\r
+ }\r
+\r
auto out = boost::range::transform(result_ps, stream.audio_data, std::begin(result_ps), std::plus<float>());\r
stream.audio_data.erase(std::begin(stream.audio_data), std::begin(stream.audio_data) + std::distance(std::begin(result_ps), out));\r
} \r
\r
ffmpeg::frame_muxer muxer_;\r
\r
+ boost::circular_buffer<size_t> sync_buffer_;\r
+\r
public:\r
decklink_producer(const core::video_format_desc& format_desc, size_t device_index, const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filter)\r
: decklink_(get_device(device_index))\r
, frame_factory_(frame_factory)\r
, audio_cadence_(frame_factory->get_video_format_desc().audio_cadence)\r
, muxer_(format_desc.fps, frame_factory, filter, ffmpeg::display_mode::deinterlace)\r
- {\r
+ , sync_buffer_(format_desc.audio_cadence.size())\r
+ { \r
hints_ = 0;\r
frame_buffer_.set_capacity(2);\r
\r
\r
frame_timer_.restart();\r
\r
+ // PUSH\r
+\r
void* bytes = nullptr;\r
if(FAILED(video->GetBytes(&bytes)) || !bytes)\r
return S_OK;\r
av_frame->height = video->GetHeight();\r
av_frame->interlaced_frame = format_desc_.field_mode != core::field_mode::progressive;\r
av_frame->top_field_first = format_desc_.field_mode == core::field_mode::upper ? 1 : 0;\r
- \r
- muxer_.push(av_frame, hints_); \r
- \r
+ \r
+ std::shared_ptr<core::audio_buffer> audio_buffer;\r
+\r
// It is assumed that audio is always equal or ahead of video.\r
- if(audio && SUCCEEDED(audio->GetBytes(&bytes)))\r
+ if(audio && SUCCEEDED(audio->GetBytes(&bytes)) && bytes)\r
{\r
auto sample_frame_count = audio->GetSampleFrameCount();\r
auto audio_data = reinterpret_cast<int32_t*>(bytes);\r
- muxer_.push(std::make_shared<core::audio_buffer>(audio_data, audio_data + sample_frame_count*format_desc_.audio_channels));\r
+ audio_buffer = std::make_shared<core::audio_buffer>(audio_data, audio_data + sample_frame_count*format_desc_.audio_channels);\r
}\r
- else\r
+ else \r
+ audio_buffer = std::make_shared<core::audio_buffer>(audio_cadence_.front(), 0);\r
+ \r
+ sync_buffer_.push_back(audio_buffer->size());\r
+ \r
+ if(!boost::range::equal(sync_buffer_, audio_cadence_))\r
{\r
- muxer_.push(std::make_shared<core::audio_buffer>(audio_cadence_.front(), 0));\r
- std::rotate(std::begin(audio_cadence_), std::begin(audio_cadence_)+1, std::end(audio_cadence_));\r
+ CASPAR_LOG(trace) << print() << L" Syncing audio.";\r
+ return S_OK;\r
}\r
\r
+ muxer_.push(audio_buffer);\r
+ muxer_.push(av_frame, hints_); \r
+ \r
+ // Note: We don't fully sync with cadence, we send last and first (1602, 1602) to have as many samples as possible when inserting into mixer\r
+ if(!boost::range::equal(sync_buffer_, audio_cadence_)) \r
+ {\r
+ CASPAR_LOG(trace) << L"[cadence_guard] Audio cadence unsynced. Skipping frame.";\r
+ return S_OK;\r
+ }\r
+ \r
+ boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);\r
+ \r
+ // POLL\r
+ \r
for(auto frame = muxer_.poll(); frame; frame = muxer_.poll())\r
{\r
if(!frame_buffer_.try_push(make_safe_ptr(frame)))\r