X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=core%2Fframe%2Fframe.cpp;h=2feb67ec4dcb2eeaef4091219bf18cdcdb10286f;hb=1678432d8cabef093a58e27791f68499c031dba9;hp=9587953320660fd964372629689d9de01a5ad039;hpb=8c61df76c4b35ab58316f35b6a09a3f977efd596;p=casparcg diff --git a/core/frame/frame.cpp b/core/frame/frame.cpp index 958795332..2feb67ec4 100644 --- a/core/frame/frame.cpp +++ b/core/frame/frame.cpp @@ -19,42 +19,64 @@ * Author: Robert Nagy, ronag89@gmail.com */ -#include "../stdafx.h" +#include "../StdAfx.h" #include "frame.h" #include #include +#include +#include +#include #include #include +#include +#include + +#include +#include #include #include namespace caspar { namespace core { - + struct mutable_frame::impl : boost::noncopyable -{ +{ std::vector> buffers_; - core::audio_buffer audio_data_; + core::mutable_audio_buffer audio_data_; const core::pixel_format_desc desc_; + const core::audio_channel_layout channel_layout_; const void* tag_; - - impl(std::vector> buffers, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc) + core::frame_geometry geometry_ = frame_geometry::get_default(); + caspar::timer since_created_timer_; + + impl( + std::vector> buffers, + mutable_audio_buffer audio_data, + const void* tag, + const core::pixel_format_desc& desc, + const core::audio_channel_layout& channel_layout) : buffers_(std::move(buffers)) - , audio_data_(std::move(audio_buffer)) + , audio_data_(std::move(audio_data)) , desc_(desc) + , channel_layout_(channel_layout) , tag_(tag) { - BOOST_FOREACH(auto& buffer, buffers_) + for (auto& buffer : buffers_) if(!buffer.data()) CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info("mutable_frame: null argument")); } }; - -mutable_frame::mutable_frame(std::vector> image_buffers, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc) - : impl_(new impl(std::move(image_buffers), std::move(audio_buffer), tag, desc)){} + +mutable_frame::mutable_frame( + std::vector> image_buffers, + mutable_audio_buffer audio_data, + const void* tag, + const core::pixel_format_desc& desc, + const core::audio_channel_layout& channel_layout) + : impl_(new impl(std::move(image_buffers), std::move(audio_data), tag, desc, channel_layout)){} mutable_frame::~mutable_frame(){} mutable_frame::mutable_frame(mutable_frame&& other) : impl_(std::move(other.impl_)){} mutable_frame& mutable_frame::operator=(mutable_frame&& other) @@ -64,14 +86,17 @@ mutable_frame& mutable_frame::operator=(mutable_frame&& other) } void mutable_frame::swap(mutable_frame& other){impl_.swap(other.impl_);} const core::pixel_format_desc& mutable_frame::pixel_format_desc() const{return impl_->desc_;} +const core::audio_channel_layout& mutable_frame::audio_channel_layout() const { return impl_->channel_layout_; } const array& mutable_frame::image_data(std::size_t index) const{return impl_->buffers_.at(index);} -const core::audio_buffer& mutable_frame::audio_data() const{return impl_->audio_data_;} +const core::mutable_audio_buffer& mutable_frame::audio_data() const{return impl_->audio_data_;} array& mutable_frame::image_data(std::size_t index){return impl_->buffers_.at(index);} -core::audio_buffer& mutable_frame::audio_data(){return impl_->audio_data_;} +core::mutable_audio_buffer& mutable_frame::audio_data(){return impl_->audio_data_;} std::size_t mutable_frame::width() const{return impl_->desc_.planes.at(0).width;} -std::size_t mutable_frame::height() const{return impl_->desc_.planes.at(0).height;} -const void* mutable_frame::stream_tag()const{return impl_->tag_;} -const void* mutable_frame::data_tag()const{return impl_.get();} +std::size_t mutable_frame::height() const{return impl_->desc_.planes.at(0).height;} +const void* mutable_frame::stream_tag()const{return impl_->tag_;} +const frame_geometry& mutable_frame::geometry() const { return impl_->geometry_; } +void mutable_frame::set_geometry(const frame_geometry& g) { impl_->geometry_ = g; } +caspar::timer mutable_frame::since_created() const { return impl_->since_created_timer_; } const const_frame& const_frame::empty() { @@ -81,44 +106,93 @@ const const_frame& const_frame::empty() } struct const_frame::impl : boost::noncopyable -{ - mutable std::vector>> future_buffers_; - int id_; - core::audio_buffer audio_data_; - const core::pixel_format_desc desc_; - const void* tag_; +{ + mutable std::vector>> future_buffers_; + mutable core::audio_buffer audio_data_; + const core::pixel_format_desc desc_; + const core::audio_channel_layout channel_layout_; + const void* tag_; + core::frame_geometry geometry_; + caspar::timer since_created_timer_; + bool should_record_age_; + mutable tbb::atomic recorded_age_; + std::shared_future> key_only_on_demand_; impl(const void* tag) - : desc_(core::pixel_format::invalid) - , tag_(tag) - , id_(0) + : audio_data_(0, 0, true, 0) + , desc_(core::pixel_format::invalid) + , channel_layout_(audio_channel_layout::invalid()) + , tag_(tag) + , geometry_(frame_geometry::get_default()) + , should_record_age_(true) { + recorded_age_ = 0; } - - impl(boost::shared_future> image, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc) - : audio_data_(std::move(audio_buffer)) + + impl(const impl& other) + : future_buffers_(other.future_buffers_) + , audio_data_(other.audio_data_) + , desc_(other.desc_) + , channel_layout_(other.channel_layout_) + , tag_(other.tag_) + , geometry_(other.geometry_) + , since_created_timer_(other.since_created_timer_) + , should_record_age_(other.should_record_age_) + , key_only_on_demand_(other.key_only_on_demand_) + { + recorded_age_ = other.recorded_age_; + } + + impl( + std::shared_future> image, + audio_buffer audio_data, + const void* tag, + const core::pixel_format_desc& desc, + const core::audio_channel_layout& channel_layout, + caspar::timer since_created_timer = caspar::timer()) + : audio_data_(std::move(audio_data)) , desc_(desc) + , channel_layout_(channel_layout) , tag_(tag) - , id_(reinterpret_cast(this)) + , geometry_(frame_geometry::get_default()) + , since_created_timer_(std::move(since_created_timer)) + , should_record_age_(false) { - if(desc.format != core::pixel_format::bgra) + if (desc.format != core::pixel_format::bgra) CASPAR_THROW_EXCEPTION(not_implemented()); - - future_buffers_.push_back(std::move(image)); + + future_buffers_.push_back(image); + + key_only_on_demand_ = std::async(std::launch::deferred, [image] + { + auto fill = image.get(); + auto key = cache_aligned_vector(fill.size()); + + aligned_memshfl(key.data(), fill.data(), fill.size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303); + + return array(key.data(), key.size(), false, std::move(key)); + }).share(); } impl(mutable_frame&& other) - : audio_data_(other.audio_data()) + : audio_data_(0, 0, true, 0) // Complex init done in body instead. , desc_(other.pixel_format_desc()) + , channel_layout_(other.audio_channel_layout()) , tag_(other.stream_tag()) - , id_(reinterpret_cast(this)) + , geometry_(other.geometry()) + , since_created_timer_(other.since_created()) + , should_record_age_(true) { - for(std::size_t n = 0; n < desc_.planes.size(); ++n) + spl::shared_ptr shared_audio_data(new mutable_audio_buffer(std::move(other.audio_data()))); + // pointer returned by vector::data() should be the same after move, but just to be safe. + audio_data_ = audio_buffer(shared_audio_data->data(), shared_audio_data->size(), true, std::move(shared_audio_data)); + + for (std::size_t n = 0; n < desc_.planes.size(); ++n) { - boost::promise> p; - p.set_value(std::move(other.image_data(n))); - future_buffers_.push_back(p.get_future()); + future_buffers_.push_back(make_ready_future>(std::move(other.image_data(n))).share()); } + + recorded_age_ = -1; } array image_data(int index) const @@ -126,6 +200,11 @@ struct const_frame::impl : boost::noncopyable return tag_ != empty().stream_tag() ? future_buffers_.at(index).get() : array(nullptr, 0, true, 0); } + spl::shared_ptr key_only() const + { + return spl::make_shared(key_only_on_demand_, audio_data_, tag_, desc_, channel_layout_, since_created_timer_); + } + std::size_t width() const { return tag_ != empty().stream_tag() ? desc_.planes.at(0).width : 0; @@ -140,11 +219,29 @@ struct const_frame::impl : boost::noncopyable { return tag_ != empty().stream_tag() ? desc_.planes.at(0).size : 0; } + + int64_t get_age_millis() const + { + if (should_record_age_) + { + if (recorded_age_ == -1) + recorded_age_ = static_cast(since_created_timer_.elapsed() * 1000.0); + + return recorded_age_; + } + else + return static_cast(since_created_timer_.elapsed() * 1000.0); + } }; - + const_frame::const_frame(const void* tag) : impl_(new impl(tag)){} -const_frame::const_frame(boost::shared_future> image, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc) - : impl_(new impl(std::move(image), std::move(audio_buffer), tag, desc)){} +const_frame::const_frame( + std::shared_future> image, + audio_buffer audio_data, + const void* tag, + const core::pixel_format_desc& desc, + const core::audio_channel_layout& channel_layout) + : impl_(new impl(std::move(image), std::move(audio_data), tag, desc, channel_layout)){} const_frame::const_frame(mutable_frame&& other) : impl_(new impl(std::move(other))){} const_frame::~const_frame(){} const_frame::const_frame(const_frame&& other) : impl_(std::move(other.impl_)){} @@ -154,6 +251,7 @@ const_frame& const_frame::operator=(const_frame&& other) return *this; } const_frame::const_frame(const const_frame& other) : impl_(other.impl_){} +const_frame::const_frame(const const_frame::impl& other) : impl_(new impl(other)) {} const_frame& const_frame::operator=(const const_frame& other) { impl_ = other.impl_; @@ -161,15 +259,32 @@ const_frame& const_frame::operator=(const const_frame& other) } bool const_frame::operator==(const const_frame& other){return impl_ == other.impl_;} bool const_frame::operator!=(const const_frame& other){return !(*this == other);} -bool const_frame::operator<(const const_frame& other){return impl_< other.impl_;} -bool const_frame::operator>(const const_frame& other){return impl_> other.impl_;} +bool const_frame::operator<(const const_frame& other){return impl_ < other.impl_;} +bool const_frame::operator>(const const_frame& other){return impl_ > other.impl_;} const core::pixel_format_desc& const_frame::pixel_format_desc()const{return impl_->desc_;} +const core::audio_channel_layout& const_frame::audio_channel_layout()const { return impl_->channel_layout_; } array const_frame::image_data(int index)const{return impl_->image_data(index);} const core::audio_buffer& const_frame::audio_data()const{return impl_->audio_data_;} std::size_t const_frame::width()const{return impl_->width();} -std::size_t const_frame::height()const{return impl_->height();} -std::size_t const_frame::size()const{return impl_->size();} -const void* const_frame::stream_tag()const{return impl_->tag_;} -const void* const_frame::data_tag()const{return impl_.get();} +std::size_t const_frame::height()const{return impl_->height();} +std::size_t const_frame::size()const{return impl_->size();} +const void* const_frame::stream_tag()const{return impl_->tag_;} +const frame_geometry& const_frame::geometry() const { return impl_->geometry_; } +const_frame const_frame::with_geometry(const frame_geometry& g) const +{ + const_frame copy(*impl_); + + copy.impl_->geometry_ = g; + + return copy; +} +int64_t const_frame::get_age_millis() const { return impl_->get_age_millis(); } +const_frame const_frame::key_only() const +{ + auto result = const_frame(); + result.impl_ = impl_->key_only(); + + return result; +} -}} \ No newline at end of file +}}