1 #include "../stdafx.h"
\r
3 #include "cadence_guard.h"
\r
5 #include "frame_consumer.h"
\r
7 #include <common/env.h>
\r
8 #include <common/memory/safe_ptr.h>
\r
9 #include <common/except.h>
\r
11 #include <core/video_format.h>
\r
12 #include <core/frame/data_frame.h>
\r
14 namespace caspar { namespace core {
\r
16 // This class is used to guarantee that audio cadence is correct. This is important for NTSC audio.
\r
17 class cadence_guard : public frame_consumer
\r
19 safe_ptr<frame_consumer> consumer_;
\r
20 std::vector<int> audio_cadence_;
\r
21 boost::circular_buffer<int> sync_buffer_;
\r
23 cadence_guard(const safe_ptr<frame_consumer>& consumer)
\r
24 : consumer_(consumer)
\r
28 virtual void initialize(const video_format_desc& format_desc, int channel_index) override
\r
30 audio_cadence_ = format_desc.audio_cadence;
\r
31 sync_buffer_ = boost::circular_buffer<int>(format_desc.audio_cadence.size());
\r
32 consumer_->initialize(format_desc, channel_index);
\r
35 virtual bool send(const safe_ptr<const data_frame>& frame) override
\r
37 if(audio_cadence_.size() == 1)
\r
38 return consumer_->send(frame);
\r
42 if(boost::range::equal(sync_buffer_, audio_cadence_) && audio_cadence_.front() == static_cast<int>(frame->audio_data().size()))
\r
44 // Audio sent so far is in sync, now we can send the next chunk.
\r
45 result = consumer_->send(frame);
\r
46 boost::range::rotate(audio_cadence_, std::begin(audio_cadence_)+1);
\r
49 CASPAR_LOG(trace) << print() << L" Syncing audio.";
\r
51 sync_buffer_.push_back(static_cast<int>(frame->audio_data().size()));
\r
56 virtual std::wstring print() const override
\r
58 return consumer_->print();
\r
61 virtual boost::property_tree::wptree info() const override
\r
63 return consumer_->info();
\r
66 virtual bool has_synchronization_clock() const override
\r
68 return consumer_->has_synchronization_clock();
\r
71 virtual int buffer_depth() const override
\r
73 return consumer_->buffer_depth();
\r
76 virtual int index() const override
\r
78 return consumer_->index();
\r
82 safe_ptr<frame_consumer> create_consumer_cadence_guard(const safe_ptr<frame_consumer>& consumer)
\r
84 return make_safe<cadence_guard>(std::move(consumer));
\r