]> git.sesse.net Git - casparcg/blob - core/consumer/oal/oal_consumer.cpp
2.0.0.2:
[casparcg] / core / consumer / oal / oal_consumer.cpp
1 /*\r
2 * copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
3 *\r
4 *  This file is part of CasparCG.\r
5 *\r
6 *    CasparCG is free software: you can redistribute it and/or modify\r
7 *    it under the terms of the GNU General Public License as published by\r
8 *    the Free Software Foundation, either version 3 of the License, or\r
9 *    (at your option) any later version.\r
10 *\r
11 *    CasparCG is distributed in the hope that it will be useful,\r
12 *    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14 *    GNU General Public License for more details.\r
15 \r
16 *    You should have received a copy of the GNU General Public License\r
17 *    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
18 *\r
19 */\r
20  \r
21 #include "../../StdAfx.h"\r
22 \r
23 #include "oal_consumer.h"\r
24 \r
25 #include "../../processor/frame.h"\r
26 #include "../../format/video_format.h"\r
27 \r
28 #include <SFML/Audio.hpp>\r
29 \r
30 #include <boost/circular_buffer.hpp>\r
31 \r
32 namespace caspar { namespace core { namespace oal {     \r
33 \r
34 struct consumer::implementation : public sf::SoundStream, boost::noncopyable\r
35 {\r
36         implementation() : container_(5), underrun_count_(0)\r
37         {\r
38                 input_.set_capacity(3);\r
39                 sf::SoundStream::Initialize(2, 48000);\r
40         }\r
41 \r
42         ~implementation()\r
43         {\r
44                 input_.clear();\r
45                 Stop();\r
46         }\r
47         \r
48         void push(const frame_ptr& frame)\r
49         {\r
50                 // NOTE: tbb::concurrent_queue does not have rvalue support. \r
51                 // Use shared_ptr to emulate move semantics\r
52                 input_.push(std::make_shared<std::vector<short>>(std::move(frame->get_audio_data()))); \r
53                 \r
54                 if(GetStatus() != Playing && input_.size() > 2)\r
55                         Play();\r
56         }\r
57         \r
58         bool OnStart() \r
59         {\r
60                 input_.clear();\r
61                 return true;\r
62         }\r
63 \r
64         bool OnGetData(sf::SoundStream::Chunk& data)\r
65         {\r
66                 static std::vector<short> silence(1920*2, 0);\r
67                 \r
68                 std::shared_ptr<std::vector<short>> audio_data;\r
69                 \r
70                 if(!input_.try_pop(audio_data))\r
71                 {\r
72                         if(underrun_count_ == 0)\r
73                                 CASPAR_LOG(trace) << "### Sound Input underflow has STARTED.";\r
74                         ++underrun_count_;\r
75                         input_.pop(audio_data);\r
76                 }\r
77                 else if(underrun_count_ > 0)\r
78                 {\r
79                         CASPAR_LOG(trace) << "### Sound Input Underrun has ENDED with " << underrun_count_ << " ticks.";\r
80                         underrun_count_ = 0;\r
81                 }\r
82                         \r
83                 if(audio_data->empty())\r
84                 {       \r
85                         data.Samples = silence.data();\r
86                         data.NbSamples = silence.size();\r
87                 }\r
88                 else\r
89                 {\r
90                         container_.push_back(std::move(*audio_data));\r
91                         data.Samples = container_.back().data();\r
92                         data.NbSamples = container_.back().size();\r
93                 }\r
94                 return true;\r
95         }\r
96 \r
97         long underrun_count_;\r
98         boost::circular_buffer<std::vector<short>> container_;\r
99         tbb::concurrent_bounded_queue<std::shared_ptr<std::vector<short>>> input_;\r
100 };\r
101 \r
102 consumer::consumer(const video_format_desc&) : impl_(new implementation()){}\r
103 void consumer::prepare(const frame_ptr& frame){impl_->push(frame);}\r
104 }}}\r