public: \r
\r
template<typename Func>\r
- static auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept\r
+ static void begin_invoke(Func&& func) // noexcept\r
{ \r
- return get_instance().executor_.begin_invoke(std::forward<Func>(func)); \r
+ if(get_instance().executor_.size() < 1024)\r
+ get_instance().executor_.begin_invoke(std::forward<Func>(func)); \r
}\r
\r
static void register_drawable(const std::shared_ptr<drawable>& drawable)\r
\r
if(!tick_data_.empty())\r
{\r
- float sum = std::accumulate(tick_data_.begin(), tick_data_.end(), 0.0) + std::numeric_limits<float>::min();\r
+ float sum = *std::max_element(tick_data_.begin(), tick_data_.end()) + std::numeric_limits<float>::min();\r
line_data_.push_back(std::make_pair(static_cast<float>(sum)/static_cast<float>(tick_data_.size()), tick_tag_));\r
tick_data_.clear();\r
}\r
\r
#include <core/mixer/write_frame.h>\r
#include <core/producer/frame/frame_transform.h>\r
+#include <common/diagnostics/graph.h>\r
\r
#include <tbb/cache_aligned_allocator.h>\r
\r
\r
struct audio_mixer::implementation\r
{\r
+ safe_ptr<diagnostics::graph> graph_;\r
std::stack<core::frame_transform> transform_stack_;\r
std::map<const void*, audio_stream> audio_streams_;\r
std::vector<audio_item> items_;\r
video_format_desc format_desc_;\r
\r
public:\r
- implementation()\r
- : format_desc_(video_format_desc::get(video_format::invalid))\r
+ implementation(const safe_ptr<diagnostics::graph>& graph)\r
+ : graph_(graph)\r
+ , format_desc_(video_format_desc::get(video_format::invalid))\r
{\r
+ graph_->set_color("volume", diagnostics::color(1.0f, 0.8f, 0.1f));\r
transform_stack_.push(core::frame_transform());\r
}\r
\r
\r
audio_buffer result;\r
result.reserve(result_ps.size());\r
- boost::range::transform(result_ps, std::back_inserter(result), [](float sample){return static_cast<int32_t>(sample);}); \r
+ boost::range::transform(result_ps, std::back_inserter(result), [](float sample){return static_cast<int32_t>(sample);}); \r
+\r
+ auto max = boost::range::max_element(result);\r
+\r
+ graph_->update_value("volume", static_cast<double>(std::abs(*max))/std::numeric_limits<int32_t>::max());\r
+\r
return result;\r
}\r
};\r
\r
-audio_mixer::audio_mixer() : impl_(new implementation()){}\r
+audio_mixer::audio_mixer(const safe_ptr<diagnostics::graph>& graph) : impl_(new implementation(graph)){}\r
void audio_mixer::begin(core::basic_frame& frame){impl_->begin(frame);}\r
void audio_mixer::visit(core::write_frame& frame){impl_->visit(frame);}\r
void audio_mixer::end(){impl_->end();}\r
\r
#include <vector>\r
\r
-namespace caspar { namespace core {\r
+namespace caspar {\r
+ \r
+namespace diagnostics {\r
+ \r
+class graph;\r
+\r
+}\r
+\r
+namespace core {\r
\r
struct video_format_desc;\r
\r
class audio_mixer : public core::frame_visitor, boost::noncopyable\r
{\r
public:\r
- audio_mixer();\r
+ audio_mixer(const safe_ptr<diagnostics::graph>& graph);\r
\r
virtual void begin(core::basic_frame& frame);\r
virtual void visit(core::write_frame& frame);\r
, format_desc_(format_desc)\r
, ogl_(ogl)\r
, image_mixer_(ogl)\r
+ , audio_mixer_(graph_)\r
, executor_(L"mixer")\r
{ \r
graph_->set_color("mix-time", diagnostics::color(1.0f, 0.0f, 0.9f));\r
\r
boost::iterator_range<uint8_t*> write_frame::image_data(size_t index){return impl_->image_data(index);}\r
audio_buffer& write_frame::audio_data() { return impl_->audio_data_; }\r
-const boost::iterator_range<const int32_t*> write_frame::audio_data() const\r
-{\r
- return boost::iterator_range<const int32_t*>(impl_->audio_data_.data(), impl_->audio_data_.data() + impl_->audio_data_.size());\r
-}\r
const void* write_frame::tag() const {return impl_->tag_;}\r
const core::pixel_format_desc& write_frame::get_pixel_format_desc() const{return impl_->desc_;}\r
const std::vector<safe_ptr<device_buffer>>& write_frame::get_textures() const{return impl_->textures_;}\r
\r
// basic_frame\r
\r
- virtual void accept(core::frame_visitor& visitor) override;\r
+ virtual void accept(frame_visitor& visitor) override;\r
\r
// write _frame\r
\r
void swap(write_frame& other);\r
\r
boost::iterator_range<uint8_t*> image_data(size_t plane_index = 0); \r
-\r
audio_buffer& audio_data();\r
- const boost::iterator_range<const int32_t*> audio_data() const;\r
\r
void commit(uint32_t plane_index);\r
void commit();\r
\r
- void set_type(const core::field_mode::type& mode);\r
- core::field_mode::type get_type() const;\r
+ void set_type(const field_mode::type& mode);\r
+ field_mode::type get_type() const;\r
\r
const void* tag() const;\r
\r
virtual boost::unique_future<std::wstring> call(const std::wstring& str) override {return (*producer_)->call(str);}\r
virtual safe_ptr<frame_producer> get_following_producer() const override {return (*producer_)->get_following_producer();}\r
virtual void set_leading_producer(const safe_ptr<frame_producer>& producer) override {(*producer_)->set_leading_producer(producer);}\r
- virtual int64_t nb_frames() const override {return (*producer_)->nb_frames();}\r
+ virtual uint32_t nb_frames() const override {return (*producer_)->nb_frames();}\r
};\r
\r
safe_ptr<core::frame_producer> create_producer_destroy_proxy(safe_ptr<core::frame_producer>&& producer)\r
{\r
const std::wstring print_;\r
const safe_ptr<basic_frame> frame_;\r
- const int64_t nb_frames_;\r
+ const uint32_t nb_frames_;\r
public:\r
last_frame_producer(const safe_ptr<frame_producer>& producer) \r
: print_(producer->print())\r
virtual safe_ptr<basic_frame> receive(int){return frame_;}\r
virtual safe_ptr<core::basic_frame> last_frame() const{return frame_;}\r
virtual std::wstring print() const{return L"dummy[" + print_ + L"]";}\r
- virtual int64_t nb_frames() const {return nb_frames_;} \r
+ virtual uint32_t nb_frames() const {return nb_frames_;} \r
virtual boost::property_tree::wptree info() const override\r
{\r
boost::property_tree::wptree info;\r
virtual safe_ptr<basic_frame> receive(int){return basic_frame::empty();}\r
virtual safe_ptr<basic_frame> last_frame() const{return basic_frame::empty();}\r
virtual void set_frame_factory(const safe_ptr<frame_factory>&){}\r
- virtual int64_t nb_frames() const {return 0;}\r
+ virtual uint32_t nb_frames() const {return 0;}\r
virtual std::wstring print() const { return L"empty";}\r
\r
virtual boost::property_tree::wptree info() const override\r
virtual safe_ptr<frame_producer> get_following_producer() const {return frame_producer::empty();} // nothrow\r
virtual void set_leading_producer(const safe_ptr<frame_producer>&) {} // nothrow\r
\r
- virtual int64_t nb_frames() const {return std::numeric_limits<int>::max();}\r
+ virtual uint32_t nb_frames() const {return std::numeric_limits<uint32_t>::max();}\r
\r
virtual safe_ptr<basic_frame> receive(int hints) = 0;\r
virtual safe_ptr<core::basic_frame> last_frame() const = 0;\r
safe_ptr<frame_producer> foreground_;\r
safe_ptr<frame_producer> background_;\r
int64_t frame_number_;\r
- int auto_play_delta_;\r
+ int32_t auto_play_delta_;\r
bool is_paused_;\r
\r
public:\r
background_ = producer;\r
auto_play_delta_ = auto_play_delta;\r
\r
+ if(auto_play_delta_ > -1 && foreground_ == frame_producer::empty())\r
+ play();\r
+\r
if(preview) // Play the first frame and pause.\r
{ \r
play();\r
if(frame == core::basic_frame::late())\r
return foreground_->last_frame();\r
\r
- auto frames_left = foreground_->nb_frames() - (++frame_number_) - auto_play_delta_;\r
+ auto frames_left = static_cast<int64_t>(foreground_->nb_frames()) - static_cast<int64_t>(++frame_number_) - static_cast<int64_t>(auto_play_delta_);\r
if(auto_play_delta_ > -1 && frames_left < 1)\r
{\r
play();\r
return info;\r
}\r
\r
- virtual int64_t nb_frames() const override\r
+ virtual uint32_t nb_frames() const override\r
{\r
- return std::numeric_limits<int>::max();\r
+ return std::numeric_limits<uint32_t>::max();\r
}\r
\r
virtual boost::unique_future<std::wstring> call(const std::wstring& param) override\r
return disable_audio(last_frame_);\r
}\r
\r
- virtual int64_t nb_frames() const override\r
+ virtual uint32_t nb_frames() const override\r
{\r
return std::min(fill_producer_->nb_frames(), key_producer_->nb_frames());\r
}\r
return disable_audio(last_frame_);\r
}\r
\r
- virtual int64_t nb_frames() const override\r
+ virtual uint32_t nb_frames() const override\r
{\r
return get_following_producer()->nb_frames();\r
}\r
{ \r
safe_ptr<core::basic_frame> last_frame_;\r
com_context<decklink_producer> context_;\r
- const int64_t length_;\r
+ const uint32_t length_;\r
public:\r
\r
- explicit decklink_producer_proxy(const safe_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, size_t device_index, const std::wstring& filter_str, int64_t length)\r
+ explicit decklink_producer_proxy(const safe_ptr<core::frame_factory>& frame_factory, const core::video_format_desc& format_desc, size_t device_index, const std::wstring& filter_str, uint32_t length)\r
: context_(L"decklink_producer[" + boost::lexical_cast<std::wstring>(device_index) + L"]")\r
, last_frame_(core::basic_frame::empty())\r
, length_(length)\r
return disable_audio(last_frame_);\r
}\r
\r
- virtual int64_t nb_frames() const override\r
+ virtual uint32_t nb_frames() const override\r
{\r
return length_;\r
}\r
\r
auto device_index = get_param(L"DEVICE", params, 1);\r
auto filter_str = get_param(L"FILTER", params); \r
- auto length = get_param(L"LENGTH", params, std::numeric_limits<int64_t>::max()); \r
+ auto length = get_param(L"LENGTH", params, std::numeric_limits<uint32_t>::max()); \r
auto format_desc = core::video_format_desc::get(get_param(L"FORMAT", params, L"INVALID"));\r
\r
boost::replace_all(filter_str, L"DEINTERLACE", L"YADIF=0:-1");\r
{\r
avfilter_register_all();\r
//fix_yadif_filter_format_query();\r
- av_register_all();\r
+ av_register_all();
+ avformat_network_init();\r
avcodec_init();\r
avcodec_register_all();\r
av_lockmgr_register(ffmpeg_lock_callback);\r
\r
void uninit()\r
{\r
- avfilter_uninit();\r
+ avfilter_uninit();
+ avformat_network_deinit();\r
av_lockmgr_register(nullptr);\r
}\r
\r
return packets_.size() > 10;\r
}\r
\r
- int64_t nb_frames() const\r
+ uint32_t nb_frames() const\r
{\r
return 0;//std::max<int64_t>(nb_frames_, file_frame_number_);\r
}\r
void audio_decoder::push(const std::shared_ptr<AVPacket>& packet){impl_->push(packet);}\r
bool audio_decoder::ready() const{return impl_->ready();}\r
std::shared_ptr<core::audio_buffer> audio_decoder::poll(){return impl_->poll();}\r
-int64_t audio_decoder::nb_frames() const{return impl_->nb_frames();}\r
-size_t audio_decoder::file_frame_number() const{return impl_->file_frame_number_;}\r
+uint32_t audio_decoder::nb_frames() const{return impl_->nb_frames();}\r
+uint32_t audio_decoder::file_frame_number() const{return impl_->file_frame_number_;}\r
\r
}}
\ No newline at end of file
void push(const std::shared_ptr<AVPacket>& packet);\r
std::shared_ptr<core::audio_buffer> poll();\r
\r
- int64_t nb_frames() const;\r
+ uint32_t nb_frames() const;\r
\r
- size_t file_frame_number() const;\r
+ uint32_t file_frame_number() const;\r
private:\r
struct implementation;\r
safe_ptr<implementation> impl_;\r
std::unique_ptr<frame_muxer> muxer_;\r
\r
const double fps_;\r
- const int64_t start_;\r
- const int64_t length_;\r
- const bool loop_;\r
+ const uint32_t start_;\r
+ const uint32_t length_;\r
\r
safe_ptr<core::basic_frame> last_frame_;\r
\r
std::queue<std::pair<safe_ptr<core::basic_frame>, size_t>> frame_buffer_;\r
\r
int64_t frame_number_;\r
- int64_t file_frame_number_;;\r
+ uint32_t file_frame_number_;\r
\r
public:\r
- explicit ffmpeg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, const std::wstring& filter, bool loop, int64_t start, int64_t length) \r
+ explicit ffmpeg_producer(const safe_ptr<core::frame_factory>& frame_factory, const std::wstring& filename, const std::wstring& filter, bool loop, uint32_t start, uint32_t length) \r
: filename_(filename)\r
, frame_factory_(frame_factory) \r
, format_desc_(frame_factory->get_video_format_desc())\r
, fps_(read_fps(*input_.context(), format_desc_.fps))\r
, start_(start)\r
, length_(length)\r
- , loop_(loop)\r
, last_frame_(core::basic_frame::empty())\r
, frame_number_(0)\r
{\r
return disable_audio(last_frame_);\r
}\r
\r
- virtual int64_t nb_frames() const override\r
+ virtual uint32_t nb_frames() const override\r
{\r
- if(loop_)\r
- return std::numeric_limits<int64_t>::max();\r
+ if(input_.loop())\r
+ return std::numeric_limits<uint32_t>::max();\r
\r
- auto nb_frames = file_nb_frames();\r
+ uint32_t nb_frames = file_nb_frames();\r
\r
- nb_frames = std::min(static_cast<int64_t>(length_), nb_frames);\r
+ nb_frames = std::min(length_, nb_frames);\r
nb_frames = muxer_->calc_nb_frames(nb_frames);\r
\r
- return nb_frames - start_;\r
+ return nb_frames > start_ ? nb_frames - start_ : 0;\r
}\r
\r
- virtual int64_t file_nb_frames() const\r
+ uint32_t file_nb_frames() const\r
{\r
- int64_t file_nb_frames = 0;\r
+ uint32_t file_nb_frames = 0;\r
file_nb_frames = std::max(file_nb_frames, video_decoder_ ? video_decoder_->nb_frames() : 0);\r
file_nb_frames = std::max(file_nb_frames, audio_decoder_ ? audio_decoder_->nb_frames() : 0);\r
return file_nb_frames;\r
}\r
-\r
- virtual int64_t frame_number() const\r
- {\r
- return frame_number_;\r
- }\r
-\r
- virtual int64_t file_frame_number() const\r
- {\r
- return file_frame_number_;\r
- }\r
-\r
+ \r
virtual boost::unique_future<std::wstring> call(const std::wstring& param) override\r
{\r
boost::promise<std::wstring> promise;\r
{\r
return L"ffmpeg[" + boost::filesystem::wpath(filename_).filename() + L"|" \r
+ print_mode() + L"|" \r
- + boost::lexical_cast<std::wstring>(file_frame_number()) + L"/" + boost::lexical_cast<std::wstring>(file_nb_frames()) + L"]";\r
+ + boost::lexical_cast<std::wstring>(file_frame_number_) + L"/" + boost::lexical_cast<std::wstring>(file_nb_frames()) + L"]";\r
}\r
\r
boost::property_tree::wptree info() const override\r
}\r
if(boost::regex_match(param, what, seek_exp))\r
{\r
- input_.seek(boost::lexical_cast<int64_t>(what["VALUE"].str()));\r
+ input_.seek(boost::lexical_cast<uint32_t>(what["VALUE"].str()));\r
return L"";\r
}\r
\r
return core::frame_producer::empty();\r
\r
auto loop = boost::range::find(params, L"LOOP") != params.end();\r
- auto start = get_param(L"SEEK", params, static_cast<uint64_t>(0));\r
- auto length = get_param(L"LENGTH", params, std::numeric_limits<uint64_t>::max());\r
+ auto start = get_param(L"SEEK", params, static_cast<uint32_t>(0));\r
+ auto length = get_param(L"LENGTH", params, std::numeric_limits<uint32_t>::max());\r
auto filter_str = get_param(L"FILTER", params, L""); \r
\r
boost::replace_all(filter_str, L"DEINTERLACE", L"YADIF=0:-1");\r
\r
const std::wstring filename_;\r
tbb::atomic<bool> loop_;\r
- const uint64_t start_; \r
- const uint64_t length_;\r
- size_t frame_number_;\r
+ const uint32_t start_; \r
+ const uint32_t length_;\r
+ uint32_t frame_number_;\r
\r
tbb::concurrent_bounded_queue<std::shared_ptr<AVPacket>> buffer_;\r
tbb::atomic<size_t> buffer_size_;\r
\r
tbb::recursive_mutex mutex_;\r
\r
- explicit implementation(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, int64_t start, int64_t length) \r
+ explicit implementation(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, uint32_t start, uint32_t length) \r
: graph_(graph)\r
, format_context_(open_input(filename)) \r
, default_stream_index_(av_find_default_stream_index(format_context_.get()))\r
return is_running_ && (is_eof_ || (buffer_size_ > MAX_BUFFER_SIZE || buffer_.size() > MAX_BUFFER_COUNT) && buffer_.size() > MIN_BUFFER_COUNT);\r
}\r
\r
- void do_seek(const int64_t target)\r
+ void do_seek(const uint32_t target)\r
{ \r
CASPAR_LOG(debug) << print() << " Seeking: " << target;\r
\r
buffer_.push(flush_packet);\r
} \r
\r
- void seek(int64_t target)\r
+ void seek(uint32_t target)\r
{\r
tbb::recursive_mutex::scoped_lock lock(mutex_);\r
\r
}\r
};\r
\r
-input::input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, int64_t start, int64_t length) \r
+input::input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, uint32_t start, uint32_t length) \r
: impl_(new implementation(graph, filename, loop, start, length)){}\r
bool input::eof() const {return impl_->is_eof_;}\r
bool input::try_pop(std::shared_ptr<AVPacket>& packet){return impl_->try_pop(packet);}\r
safe_ptr<AVFormatContext> input::context(){return impl_->format_context_;}\r
void input::loop(bool value){impl_->loop_ = value;}\r
bool input::loop() const{return impl_->loop_;}\r
-void input::seek(int64_t target){impl_->seek(target);}\r
+void input::seek(uint32_t target){impl_->seek(target);}\r
}}\r
class input : boost::noncopyable\r
{\r
public:\r
- explicit input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, int64_t start, int64_t length);\r
+ explicit input(const safe_ptr<diagnostics::graph>& graph, const std::wstring& filename, bool loop, uint32_t start, uint32_t length);\r
\r
bool try_pop(std::shared_ptr<AVPacket>& packet);\r
bool eof() const;\r
void loop(bool value);\r
bool loop() const;\r
\r
- void seek(int64_t target);\r
+ void seek(uint32_t target);\r
\r
safe_ptr<AVFormatContext> context();\r
private:\r
display_mode_ = display_mode::invalid;\r
}\r
\r
- int64_t calc_nb_frames(int64_t nb_frames) const\r
+ uint32_t calc_nb_frames(uint32_t nb_frames) const\r
{\r
+ uint64_t nb_frames2 = nb_frames;\r
+\r
switch(display_mode_) // Take into account transformation in run.\r
{\r
case display_mode::deinterlace_bob_reinterlace:\r
case display_mode::interlace: \r
case display_mode::half:\r
- nb_frames /= 2;\r
+ nb_frames2 /= 2;\r
break;\r
case display_mode::duplicate:\r
- nb_frames *= 2;\r
+ nb_frames2 *= 2;\r
break;\r
}\r
\r
if(filter_.is_double_rate()) // Take into account transformations in filter.\r
- nb_frames *= 2;\r
+ nb_frames2 *= 2;\r
\r
- return nb_frames;\r
+ return static_cast<uint32_t>(nb_frames2);\r
}\r
};\r
\r
void frame_muxer::push(const std::shared_ptr<AVFrame>& video_frame, int hints){impl_->push(video_frame, hints);}\r
void frame_muxer::push(const std::shared_ptr<core::audio_buffer>& audio_samples){return impl_->push(audio_samples);}\r
std::shared_ptr<basic_frame> frame_muxer::poll(){return impl_->poll();}\r
-int64_t frame_muxer::calc_nb_frames(int64_t nb_frames) const {return impl_->calc_nb_frames(nb_frames);}\r
+uint32_t frame_muxer::calc_nb_frames(uint32_t nb_frames) const {return impl_->calc_nb_frames(nb_frames);}\r
bool frame_muxer::video_ready() const{return impl_->video_ready();}\r
bool frame_muxer::audio_ready() const{return impl_->audio_ready();}\r
void frame_muxer::force_deinterlacing(bool value){impl_->force_deinterlacing(value);}\r
\r
std::shared_ptr<core::basic_frame> poll();\r
\r
- int64_t calc_nb_frames(int64_t nb_frames) const;\r
+ uint32_t calc_nb_frames(uint32_t nb_frames) const;\r
\r
void force_deinterlacing(bool value);\r
\r
\r
std::queue<safe_ptr<AVPacket>> packets_;\r
\r
- const int64_t nb_frames_;\r
+ const uint32_t nb_frames_;\r
\r
const size_t width_;\r
const size_t height_;\r
public:\r
explicit implementation(const safe_ptr<AVFormatContext>& context) \r
: codec_context_(open_codec(*context, AVMEDIA_TYPE_VIDEO, index_))\r
- , nb_frames_(context->streams[index_]->nb_frames)\r
+ , nb_frames_(static_cast<uint32_t>(context->streams[index_]->nb_frames))\r
, width_(codec_context_->width)\r
, height_(codec_context_->height)\r
{\r
return packets_.size() > 10;\r
}\r
\r
- int64_t nb_frames() const\r
+ uint32_t nb_frames() const\r
{\r
- return std::max<int64_t>(nb_frames_, file_frame_number_);\r
+ return std::max<uint32_t>(nb_frames_, file_frame_number_);\r
}\r
};\r
\r
void video_decoder::push(const std::shared_ptr<AVPacket>& packet){impl_->push(packet);}\r
std::shared_ptr<AVFrame> video_decoder::poll(){return impl_->poll();}\r
bool video_decoder::ready() const{return impl_->ready();}\r
-int64_t video_decoder::nb_frames() const{return impl_->nb_frames();}\r
size_t video_decoder::width() const{return impl_->width_;}\r
size_t video_decoder::height() const{return impl_->height_;}\r
+uint32_t video_decoder::nb_frames() const{return impl_->nb_frames();}\r
+uint32_t video_decoder::file_frame_number() const{return impl_->file_frame_number_;}\r
bool video_decoder::is_progressive() const{return impl_->is_progressive_;}\r
-size_t video_decoder::file_frame_number() const{return impl_->file_frame_number_;}\r
\r
}}
\ No newline at end of file
void push(const std::shared_ptr<AVPacket>& packet);\r
std::shared_ptr<AVFrame> poll();\r
\r
- size_t width() const;\r
- size_t height() const;\r
- int64_t nb_frames() const;\r
- bool is_progressive() const;\r
+ size_t width() const;\r
+ size_t height() const;\r
+\r
+ uint32_t nb_frames() const;\r
+ uint32_t file_frame_number() const;\r
+\r
+ bool is_progressive() const;\r
\r
- size_t file_frame_number() const;\r
private:\r
struct implementation;\r
safe_ptr<implementation> impl_;\r
return info;\r
}\r
\r
- virtual int64_t nb_frames() const override\r
+ virtual uint32_t nb_frames() const override\r
{\r
if(height_ > format_desc_.height)\r
{\r
<channel>\r
<video-mode>PAL</video-mode>\r
<consumers>\r
- <decklink>\r
- <embedded-audio>true</embedded-audio>\r
- </decklink>\r
<screen>\r
- \r
+ <device>2</device>\r
</screen>\r
+ <system-audio></system-audio>\r
</consumers>\r
</channel>\r
</channels>\r