#include <common/diagnostics/graph.h>\r
#include <common/log/log.h>\r
#include <common/utility/timer.h>\r
+#include <common/utility/string.h>\r
\r
+#include <core/consumer/frame_consumer.h>\r
#include <core/video_format.h>\r
\r
-#include <core/consumer/frame/read_frame.h>\r
+#include <core/mixer/read_frame.h>\r
\r
#include <SFML/Audio.hpp>\r
\r
#include <boost/circular_buffer.hpp>\r
+#include <boost/timer.hpp>\r
\r
#include <tbb/concurrent_queue.h>\r
\r
namespace caspar {\r
\r
-struct oal_consumer::implementation : public sf::SoundStream, boost::noncopyable\r
+struct oal_consumer : public core::frame_consumer, public sf::SoundStream\r
{\r
- safe_ptr<diagnostics::graph> graph_;\r
- timer perf_timer_;\r
+ safe_ptr<diagnostics::graph> graph_;\r
+ boost::timer perf_timer_;\r
\r
- tbb::concurrent_bounded_queue<std::vector<short>> input_;\r
- boost::circular_buffer<std::vector<short>> container_;\r
- tbb::atomic<bool> is_running_;\r
+ tbb::concurrent_bounded_queue<std::vector<short>> input_;\r
+ boost::circular_buffer<std::vector<short>> container_;\r
+ tbb::atomic<bool> is_running_;\r
\r
- core::video_format_desc format_desc_;\r
+ core::video_format_desc format_desc_;\r
+ int preroll_count_;\r
public:\r
- implementation(const core::video_format_desc& format_desc) \r
+ oal_consumer() \r
: graph_(diagnostics::create_graph(narrow(print())))\r
- , container_(5)\r
- , format_desc_(format_desc)\r
+ , container_(16)\r
+ , preroll_count_(0)\r
{\r
graph_->add_guide("tick-time", 0.5);\r
graph_->set_color("tick-time", diagnostics::color(0.1f, 0.7f, 0.8f));\r
is_running_ = true;\r
- input_.set_capacity(4);\r
-\r
- // Fill input buffer with silence.\r
- for(size_t n = 0; n < buffer_depth(); ++n)\r
- input_.push(std::vector<short>(static_cast<size_t>(48000.0f/format_desc_.fps)*2, 0)); \r
-\r
- sf::SoundStream::Initialize(2, 48000);\r
- Play(); \r
- CASPAR_LOG(info) << print() << " Sucessfully initialized.";\r
+ input_.set_capacity(core::consumer_buffer_depth()-2);\r
}\r
\r
- ~implementation()\r
+ ~oal_consumer()\r
{\r
is_running_ = false;\r
input_.try_push(std::vector<short>());\r
Stop();\r
CASPAR_LOG(info) << print() << L" Shutting down."; \r
}\r
- \r
- void send(const safe_ptr<const core::read_frame>& frame)\r
- { \r
- if(!frame->audio_data().empty())\r
- input_.push(std::vector<short>(frame->audio_data().begin(), frame->audio_data().end())); \r
- else\r
- input_.push(std::vector<short>(static_cast<size_t>(48000.0f/format_desc_.fps)*2, 0)); \r
+\r
+ virtual void initialize(const core::video_format_desc& format_desc)\r
+ {\r
+ format_desc_ = format_desc; \r
+ sf::SoundStream::Initialize(2, 48000);\r
+ Play(); \r
+ CASPAR_LOG(info) << print() << " Sucessfully initialized.";\r
}\r
+ \r
+ virtual bool send(const safe_ptr<core::read_frame>& frame)\r
+ { \r
+ if(preroll_count_ < input_.capacity())\r
+ {\r
+ while(input_.try_push(std::vector<int16_t>(format_desc_.audio_samples_per_frame, 0)))\r
+ ++preroll_count_;\r
+ }\r
\r
- size_t buffer_depth() const{return 3;}\r
+ input_.push(std::vector<int16_t>(frame->audio_data().begin(), frame->audio_data().end())); \r
\r
+ return true;\r
+ }\r
+ \r
virtual bool OnGetData(sf::SoundStream::Chunk& data)\r
{ \r
std::vector<short> audio_data; \r
data.Samples = container_.back().data();\r
data.NbSamples = container_.back().size(); \r
\r
- graph_->update_value("tick-time", static_cast<float>(perf_timer_.elapsed()/format_desc_.interval*0.5)); \r
- perf_timer_.reset();\r
+ graph_->update_value("tick-time", perf_timer_.elapsed()*format_desc_.fps*0.5); \r
+ perf_timer_.restart();\r
\r
return is_running_;\r
}\r
\r
- std::wstring print() const\r
+ virtual std::wstring print() const\r
{\r
- return L"oal[default]";\r
+ return L"oal[" + format_desc_.name + L"]";\r
}\r
-};\r
\r
-oal_consumer::oal_consumer(){}\r
-oal_consumer::oal_consumer(oal_consumer&& other) : impl_(std::move(other.impl_)){}\r
-void oal_consumer::send(const safe_ptr<const core::read_frame>& frame){impl_->send(frame);}\r
-size_t oal_consumer::buffer_depth() const{return impl_->buffer_depth();}\r
-void oal_consumer::initialize(const core::video_format_desc& format_desc){impl_.reset(new implementation(format_desc));}\r
-std::wstring oal_consumer::print() const { return impl_->print(); }\r
+ virtual const core::video_format_desc& get_video_format_desc() const\r
+ {\r
+ return format_desc_;\r
+ }\r
+};\r
\r
safe_ptr<core::frame_consumer> create_oal_consumer(const std::vector<std::wstring>& params)\r
{\r
\r
return make_safe<oal_consumer>();\r
}\r
+\r
+safe_ptr<core::frame_consumer> create_oal_consumer()\r
+{\r
+ return make_safe<oal_consumer>();\r
+}\r
+\r
}\r