2 * Copyright 2013 NewTek
4 * This file is part of CasparCG (www.casparcg.com).
6 * CasparCG is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * CasparCG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
19 * Author: Robert Nagy, ronag@live.com
22 #include "../StdAfx.h"
24 #include "newtek_ivga_consumer.h"
26 #include <core/consumer/frame_consumer.h>
27 #include <core/parameters/parameters.h>
28 #include <core/video_format.h>
29 #include <core/mixer/read_frame.h>
31 #include <common/utility/assert.h>
32 #include <common/concurrency/executor.h>
34 #include <boost/algorithm/string.hpp>
36 #include <tbb/atomic.h>
38 #include "../util/air_send.h"
40 namespace caspar { namespace newtek {
42 struct newtek_ivga_consumer : public core::frame_consumer
44 std::shared_ptr<void> air_send_;
45 core::video_format_desc format_desc_;
46 core::channel_layout channel_layout_;
48 tbb::atomic<bool> connected_;
52 newtek_ivga_consumer(core::channel_layout channel_layout)
54 , channel_layout_(channel_layout)
56 if (!airsend::is_available())
57 BOOST_THROW_EXCEPTION(caspar_exception() << msg_info(narrow(airsend::dll_name()) + " not available"));
62 ~newtek_ivga_consumer()
68 virtual void initialize(const core::video_format_desc& format_desc, int channel_index) override
74 format_desc.time_scale,
76 format_desc.field_mode == core::field_mode::progressive,
77 static_cast<float>(format_desc.square_width) / static_cast<float>(format_desc.square_height),
79 channel_layout_.num_channels,
80 format_desc.audio_sample_rate),
83 CASPAR_VERIFY(air_send_);
85 format_desc_ = format_desc;
87 CASPAR_LOG(info) << print() << L" Successfully Initialized.";
90 virtual boost::unique_future<bool> send(const safe_ptr<core::read_frame>& frame) override
92 CASPAR_VERIFY(format_desc_.height * format_desc_.width * 4 == static_cast<unsigned>(frame->image_data().size()));
94 return executor_.begin_invoke([=]() -> bool
98 std::vector<int16_t, tbb::cache_aligned_allocator<int16_t>> audio_buffer;
100 if (core::needs_rearranging(
101 frame->multichannel_view(),
103 channel_layout_.num_channels))
105 core::audio_buffer downmixed;
108 frame->multichannel_view().num_samples()
109 * channel_layout_.num_channels,
112 auto dest_view = core::make_multichannel_view<int32_t>(
113 downmixed.begin(), downmixed.end(), channel_layout_);
115 core::rearrange_or_rearrange_and_mix(
116 frame->multichannel_view(),
118 core::default_mix_config_repository());
120 audio_buffer = core::audio_32_to_16(downmixed);
124 audio_buffer = core::audio_32_to_16(frame->audio_data());
127 airsend::add_audio(air_send_.get(), audio_buffer.data(), audio_buffer.size() / channel_layout_.num_channels);
131 connected_ = airsend::add_frame_bgra(air_send_.get(), frame->image_data().begin());
137 virtual std::wstring print() const override
139 return L"newtek-ivga";
142 virtual boost::property_tree::wptree info() const override
144 boost::property_tree::wptree info;
145 info.add(L"type", L"newtek-ivga-consumer");
149 virtual size_t buffer_depth() const override
154 virtual int index() const override
159 virtual int64_t presentation_frame_age_millis() const override
164 virtual bool has_synchronization_clock() const override
170 safe_ptr<core::frame_consumer> create_ivga_consumer(const core::parameters& params)
172 if(params.size() < 1 || params[0] != L"NEWTEK_IVGA")
173 return core::frame_consumer::empty();
175 const auto channel_layout = core::default_channel_layout_repository()
177 params.get(L"CHANNEL_LAYOUT", L"STEREO"));
179 return make_safe<newtek_ivga_consumer>(channel_layout);
182 safe_ptr<core::frame_consumer> create_ivga_consumer(const boost::property_tree::wptree& ptree)
184 const auto channel_layout =
185 core::default_channel_layout_repository()
187 boost::to_upper_copy(ptree.get(L"channel-layout", L"STEREO")));
189 return make_safe<newtek_ivga_consumer>(channel_layout);