]> git.sesse.net Git - casparcg/blob - core/consumer/cadence_guard.cpp
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches...
[casparcg] / core / consumer / cadence_guard.cpp
1 #include "../stdafx.h"\r
2 \r
3 #include "cadence_guard.h"\r
4 \r
5 #include "frame_consumer.h"\r
6 \r
7 #include <common/env.h>\r
8 #include <common/memory/safe_ptr.h>\r
9 #include <common/except.h>\r
10 \r
11 #include <core/video_format.h>\r
12 #include <core/frame/data_frame.h>\r
13 \r
14 namespace caspar { namespace core {\r
15 \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
18 {\r
19         safe_ptr<frame_consumer>                consumer_;\r
20         std::vector<int>                                audio_cadence_;\r
21         boost::circular_buffer<int>     sync_buffer_;\r
22 public:\r
23         cadence_guard(const safe_ptr<frame_consumer>& consumer)\r
24                 : consumer_(consumer)\r
25         {\r
26         }\r
27         \r
28         virtual void initialize(const video_format_desc& format_desc, int channel_index) override\r
29         {\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
33         }\r
34 \r
35         virtual bool send(const safe_ptr<const data_frame>& frame) override\r
36         {               \r
37                 if(audio_cadence_.size() == 1)\r
38                         return consumer_->send(frame);\r
39 \r
40                 bool result = true;\r
41                 \r
42                 if(boost::range::equal(sync_buffer_, audio_cadence_) && audio_cadence_.front() == static_cast<int>(frame->audio_data().size())) \r
43                 {       \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
47                 }\r
48                 else\r
49                         CASPAR_LOG(trace) << print() << L" Syncing audio.";\r
50 \r
51                 sync_buffer_.push_back(static_cast<int>(frame->audio_data().size()));\r
52                 \r
53                 return result;\r
54         }\r
55 \r
56         virtual std::wstring print() const override\r
57         {\r
58                 return consumer_->print();\r
59         }\r
60 \r
61         virtual boost::property_tree::wptree info() const override\r
62         {\r
63                 return consumer_->info();\r
64         }\r
65 \r
66         virtual bool has_synchronization_clock() const override\r
67         {\r
68                 return consumer_->has_synchronization_clock();\r
69         }\r
70 \r
71         virtual int buffer_depth() const override\r
72         {\r
73                 return consumer_->buffer_depth();\r
74         }\r
75 \r
76         virtual int index() const override\r
77         {\r
78                 return consumer_->index();\r
79         }\r
80 };\r
81 \r
82 safe_ptr<frame_consumer> create_consumer_cadence_guard(const safe_ptr<frame_consumer>& consumer)\r
83 {\r
84         return make_safe<cadence_guard>(std::move(consumer));\r
85 }\r
86 \r
87 }}