]> git.sesse.net Git - casparcg/blobdiff - core/frame/frame.h
[general] Abstracted the concept of a key only frame so that readers of const_frame...
[casparcg] / core / frame / frame.h
index 998792a08a494c3d6ae15655021d1e10ca0e1530..fff5382c845a715e34cecb93380e2dd107852be5 100644 (file)
-/*\r
-* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\r
-*\r
-*  This file is part of CasparCG.\r
-*\r
-*    CasparCG is free software: you can redistribute it and/or modify\r
-*    it under the terms of the GNU General Public License as published by\r
-*    the Free Software Foundation, either version 3 of the License, or\r
-*    (at your option) any later version.\r
-*\r
-*    CasparCG is distributed in the hope that it will be useful,\r
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-*    GNU General Public License for more details.\r
-\r
-*    You should have received a copy of the GNU General Public License\r
-*    along with CasparCG.  If not, see <http://www.gnu.org/licenses/>.\r
-*\r
-*/\r
-#pragma once\r
-\r
-#include <memory>\r
-#include <vector>\r
-\r
-#include "audio_chunk.h"\r
-#include "frame_format.h"\r
-\r
-#include "../../common/image/image.h"\r
-\r
-#include <tbb/parallel_invoke.h>\r
-\r
-#include <boost/range/algorithm.hpp>\r
-\r
-namespace caspar {\r
-\r
-// NOTE: audio data is ALWAYS shallow copy\r
-class frame : boost::noncopyable\r
-{\r
-public:\r
-       virtual ~frame(){}\r
-       \r
-       virtual const unsigned char* data() const { return const_cast<frame&>(*this).data(); }\r
-       virtual unsigned char* data() = 0;\r
-       virtual size_t size() const = 0;\r
-       virtual void* tag() const { return nullptr; }\r
-       virtual const std::vector<audio_chunk_ptr>& audio_data() const { return audioData_; }   \r
-       virtual std::vector<audio_chunk_ptr>& audio_data() { return audioData_; }                       \r
-\r
-       static std::shared_ptr<frame> null()\r
-       {\r
-               class null_frame : public frame\r
-               {\r
-                       unsigned char* data() { return nullptr; };\r
-                       size_t size() const { return 0; };\r
-               };\r
-               static auto my_null_frame = std::make_shared<null_frame>();\r
-               return my_null_frame;\r
-       }\r
-private:       \r
-       std::vector<audio_chunk_ptr> audioData_;\r
-};\r
-typedef std::shared_ptr<frame> frame_ptr;\r
-typedef std::shared_ptr<const frame> frame_const_ptr;\r
-typedef std::unique_ptr<frame> frame_uptr;\r
-typedef std::unique_ptr<const frame> frame_const_uptr;\r
-\r
-inline bool operator==(const frame& lhs, const frame& rhs)\r
-{\r
-       return lhs.data() == rhs.data() && (lhs.data() == nullptr || lhs.size() == rhs.size());\r
-}\r
-\r
-template<typename frame_ptr_type>\r
-frame_ptr_type& set_frame_volume(frame_ptr_type& result_frame, float volume)\r
-{\r
-       assert(result_frame != nullptr);\r
-       assert(boost::range::find(result_frame->audio_data(), nullptr) == result_frame->audio_data().end());\r
-       boost::range::for_each(result_frame->audio_data(), std::bind(&audio_chunk::set_volume, std::placeholders::_1, volume));\r
-       return result_frame;\r
-}\r
-\r
-template<typename frame_ptr_type>\r
-frame_ptr_type& clear_frame(frame_ptr_type& result_frame)\r
-{\r
-       assert(result_frame != nullptr);\r
-       common::image::clear(result_frame->data(), result_frame->size());\r
-       result_frame->audio_data().clear();\r
-       return result_frame;\r
-}\r
-\r
-template<typename frame_ptr_type>\r
-frame_ptr_type& pre_over_frame(frame_ptr_type& result_frame, const frame_const_ptr& frame1, const frame_const_ptr& frame2)\r
-{\r
-       assert(result_frame != nullptr && frame1 != nullptr && frame2 != nullptr);\r
-       assert(result_frame->size() == frame1->size());\r
-       assert(result_frame->size() == frame2->size());\r
-       assert(boost::range::find(frame1->audio_data(), nullptr) == frame1->audio_data().end());\r
-       assert(boost::range::find(frame2->audio_data(), nullptr) == frame2->audio_data().end());\r
-       tbb::parallel_invoke(\r
-       [&]{common::image::pre_over(result_frame->data(), frame1->data(), frame2->data(), result_frame->size());},\r
-       [&]\r
-       {\r
-               if(result_frame != frame1)\r
-                       boost::range::copy(frame1->audio_data(), std::back_inserter(result_frame->audio_data()));\r
-               if(result_frame != frame2)\r
-                       boost::range::copy(frame2->audio_data(), std::back_inserter(result_frame->audio_data()));\r
-       });\r
-       return result_frame;\r
-}\r
-\r
-template<typename frame_ptr_type>\r
-frame_ptr_type& copy_frame(frame_ptr_type& result_frame, const frame_const_ptr& frame)\r
-{      \r
-       assert(result_frame != nullptr && frame != nullptr);\r
-       assert(result_frame->size() == frame->size());\r
-       if(result_frame == frame)\r
-               return result_frame;\r
-       tbb::parallel_invoke(\r
-       [&]{common::image::copy(result_frame->data(), frame->data(), result_frame->size());},\r
-       [&]{boost::range::copy(frame->audio_data(), std::back_inserter(result_frame->audio_data()));});\r
-       return result_frame;\r
-} \r
-\r
-template<typename frame_ptr_type>\r
-frame_ptr_type& copy_frame(frame_ptr_type& result_frame, const frame_const_ptr& frame, const frame_format_desc& format_desc)\r
-{      \r
-       assert(result_frame != nullptr && frame != nullptr);\r
-       assert(result_frame->size() == format_desc.size);\r
-       assert(frame->size() == format_desc.size);\r
-       if(result_frame == frame)\r
-               return result_frame;\r
-       tbb::parallel_invoke(\r
-       [&]\r
-       {\r
-               if(format_desc.mode == video_mode::progressive)\r
-                       common::image::copy(result_frame->data(), frame->data(), result_frame->size());\r
-               else\r
-                       common::image::copy_field(result_frame->data(), frame->data(), format_desc.mode == video_mode::upper ? 1 : 0, format_desc.width, format_desc.height);\r
-       },\r
-       [&]{boost::range::copy(frame->audio_data(), std::back_inserter(result_frame->audio_data()));});\r
-       return result_frame;\r
-} \r
-\r
-template<typename frame_ptr_type, typename frame_container>\r
-frame_ptr_type& compose_frames(frame_ptr_type& result_frame, const frame_container& frames)\r
-{\r
-       assert(boost::range::find(frames, nullptr) == frames.end());\r
-       assert(boost::range::find_if(frames, [&](const frame_ptr& frame) { return frame->size() != result_frame->size();}) == frames.end());\r
-       if(frames.empty())      \r
-               clear_frame(result_frame);      \r
-       else if(frames.size() == 1)     \r
-               copy_frame(result_frame, frames[0]);    \r
-       else if(frames.size() == 2)     \r
-               pre_over_frame(result_frame, frames[0], frames[1]);     \r
-       else\r
-       {\r
-               for(size_t n = 0; n < frames.size() - 2; ++n)\r
-                       pre_over_frame(frames[0], frames[n], frames[n+1]);\r
-               pre_over_frame(result_frame, frames[0], frames[frames.size()-1]);\r
-       }\r
-       return result_frame;\r
-}\r
-\r
-}
\ No newline at end of file
+#pragma once
+
+#undef BOOST_PARAMETER_MAX_ARITY
+#define BOOST_PARAMETER_MAX_ARITY 7
+
+#include "../fwd.h"
+
+#include <common/memory.h>
+#include <common/forward.h>
+#include <common/array.h>
+#include <common/future_fwd.h>
+#include <common/cache_aligned_vector.h>
+#include <common/timer.h>
+
+#include <cstddef>
+#include <cstdint>
+
+FORWARD1(boost, template<typename> class shared_future);
+
+namespace caspar { namespace core {
+
+typedef caspar::array<const int32_t> audio_buffer;
+typedef cache_aligned_vector<int32_t> mutable_audio_buffer;
+class frame_geometry;
+
+class mutable_frame final
+{
+       mutable_frame(const mutable_frame&);
+       mutable_frame& operator=(const mutable_frame&);
+public:
+
+       // Static Members
+
+       // Constructors
+
+       explicit mutable_frame(std::vector<array<std::uint8_t>> image_buffers,
+                                               mutable_audio_buffer audio_data,
+                                               const void* tag,
+                                               const pixel_format_desc& desc,
+                                               const audio_channel_layout& channel_layout);
+       ~mutable_frame();
+
+       // Methods
+
+       mutable_frame(mutable_frame&& other);
+       mutable_frame& operator=(mutable_frame&& other);
+
+       void swap(mutable_frame& other);
+
+       // Properties
+
+       const core::pixel_format_desc& pixel_format_desc() const;
+       const core::audio_channel_layout& audio_channel_layout() const;
+
+       const array<std::uint8_t>& image_data(std::size_t index = 0) const;
+       const core::mutable_audio_buffer& audio_data() const;
+
+       array<std::uint8_t>& image_data(std::size_t index = 0);
+       core::mutable_audio_buffer& audio_data();
+
+       std::size_t width() const;
+       std::size_t height() const;
+
+       const void* stream_tag() const;
+
+       const core::frame_geometry& geometry() const;
+       void set_geometry(const frame_geometry& g);
+
+       caspar::timer since_created() const;
+
+private:
+       struct impl;
+       spl::unique_ptr<impl> impl_;
+};
+
+class const_frame final
+{
+public:
+
+       // Static Members
+
+       static const const_frame& empty();
+
+       // Constructors
+
+       explicit const_frame(const void* tag = nullptr);
+       explicit const_frame(std::shared_future<array<const std::uint8_t>> image,
+                                               audio_buffer audio_data,
+                                               const void* tag,
+                                               const pixel_format_desc& desc,
+                                               const audio_channel_layout& channel_layout);
+       const_frame(mutable_frame&& other);
+       ~const_frame();
+
+       // Methods
+
+       const_frame(const_frame&& other);
+       const_frame& operator=(const_frame&& other);
+       const_frame(const const_frame&);
+       const_frame& operator=(const const_frame& other);
+
+       const_frame key_only() const;
+
+       // Properties
+
+       const core::pixel_format_desc& pixel_format_desc() const;
+       const core::audio_channel_layout& audio_channel_layout() const;
+
+       array<const std::uint8_t> image_data(int index = 0) const;
+       const core::audio_buffer& audio_data() const;
+
+       std::size_t width() const;
+       std::size_t height() const;
+       std::size_t size() const;
+
+       const void* stream_tag() const;
+
+       const core::frame_geometry& geometry() const;
+       void set_geometry(const frame_geometry& g);
+       int64_t get_age_millis() const;
+
+       bool operator==(const const_frame& other);
+       bool operator!=(const const_frame& other);
+       bool operator<(const const_frame& other);
+       bool operator>(const const_frame& other);
+
+private:
+       struct impl;
+       spl::shared_ptr<impl> impl_;
+};
+
+}}