]> git.sesse.net Git - casparcg/commitdiff
2.1.0: -Moved NTSC DV padding into ffmpeg/muxer.
authorronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 24 Mar 2012 14:24:51 +0000 (14:24 +0000)
committerronag <ronag@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Sat, 24 Mar 2012 14:24:51 +0000 (14:24 +0000)
git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.1.0@2729 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

13 files changed:
accelerator/cpu/image/image_mixer.cpp
accelerator/cpu/image/image_mixer.h
accelerator/ogl/image/image_mixer.cpp
accelerator/ogl/image/image_mixer.h
core/frame/frame.cpp
core/frame/frame.h
core/frame/frame_factory.h
core/mixer/image/image_mixer.h
core/mixer/mixer.cpp
core/mixer/mixer.h
modules/ffmpeg/producer/muxer/frame_muxer.cpp
modules/ffmpeg/producer/util/util.cpp
modules/flash/producer/flash_producer.cpp

index 1ee30443db8c1da51cee3d15ec1f4d91e3d4f367..d7c26fd8fa618a3e997b08b885a0c94c620c8b81 100644 (file)
@@ -359,7 +359,7 @@ public:
                return renderer_(std::move(items_), format_desc);\r
        }\r
        \r
-       virtual core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode)\r
+       virtual core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc)\r
        {\r
                std::vector<array<std::uint8_t>> buffers;\r
                BOOST_FOREACH(auto& plane, desc.planes)\r
@@ -367,7 +367,7 @@ public:
                        auto buf = spl::make_shared<buffer>(plane.size);\r
                        buffers.push_back(array<std::uint8_t>(buf->data(), plane.size, true, buf));\r
                }\r
-               return core::mutable_frame(std::move(buffers), core::audio_buffer(), tag, desc, frame_rate, field_mode);\r
+               return core::mutable_frame(std::move(buffers), core::audio_buffer(), tag, desc);\r
        }\r
 };\r
 \r
@@ -379,6 +379,6 @@ void image_mixer::pop(){impl_->pop();}
 boost::unique_future<array<const std::uint8_t>> image_mixer::operator()(const core::video_format_desc& format_desc){return impl_->render(format_desc);}\r
 void image_mixer::begin_layer(core::blend_mode blend_mode){impl_->begin_layer(blend_mode);}\r
 void image_mixer::end_layer(){impl_->end_layer();}\r
-core::mutable_frame image_mixer::create_frame(const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode) {return impl_->create_frame(tag, desc, frame_rate, field_mode);}\r
+core::mutable_frame image_mixer::create_frame(const void* tag, const core::pixel_format_desc& desc) {return impl_->create_frame(tag, desc);}\r
 \r
 }}}
\ No newline at end of file
index d5c8f7f542c49e342bf16db269e72bedda94d1d2..516b51ebbdbbac2e8be6470a27573bdcccaa4dd7 100644 (file)
@@ -44,7 +44,7 @@ public:
                \r
        boost::unique_future<array<const std::uint8_t>> operator()(const core::video_format_desc& format_desc) override;\r
                \r
-       core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode) override;\r
+       core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc) override;\r
 \r
        // Properties\r
 \r
index 7222153104abfa003d975f25e82f2ca4b932ae5a..6ac9b15adf794606f9f208f77f14a0cdbee0832c 100644 (file)
@@ -57,13 +57,11 @@ typedef boost::shared_future<spl::shared_ptr<texture>> future_texture;
 struct item\r
 {\r
        core::pixel_format_desc                                                         pix_desc;\r
-       core::field_mode                                                                        field_mode;\r
        std::vector<future_texture>                                                     textures;\r
        core::image_transform                                                           transform;\r
 \r
        item()\r
                : pix_desc(core::pixel_format::invalid)\r
-               , field_mode(core::field_mode::empty)\r
        {\r
        }\r
 };\r
@@ -157,26 +155,27 @@ private:
                          std::shared_ptr<texture>&                     layer_key_texture,\r
                          const core::video_format_desc&        format_desc,\r
                          core::field_mode                                      field_mode)\r
-       {               \r
-               // Fix frames           \r
-               BOOST_FOREACH(auto& item, layer.items)          \r
-               {\r
+       {                       \r
+               // REMOVED: This is done in frame_muxer. \r
+               // Fix frames\r
+               //BOOST_FOREACH(auto& item, layer.items)                \r
+               //{\r
                        //if(std::abs(item.transform.fill_scale[1]-1.0) > 1.0/target_texture->height() ||\r
                        //   std::abs(item.transform.fill_translation[1]) > 1.0/target_texture->height())               \r
                        //      CASPAR_LOG(warning) << L"[image_mixer] Frame should be deinterlaced. Send FILTER DEINTERLACE_BOB when creating producer.";      \r
 \r
-                       if(item.pix_desc.planes.at(0).height == 480) // NTSC DV\r
-                       {\r
-                               item.transform.fill_translation[1] += 2.0/static_cast<double>(format_desc.height);\r
-                               item.transform.fill_scale[1] *= 1.0 - 6.0*1.0/static_cast<double>(format_desc.height);\r
-                       }\r
+                       //if(item.pix_desc.planes.at(0).height == 480) // NTSC DV\r
+                       //{\r
+                       //      item.transform.fill_translation[1] += 2.0/static_cast<double>(format_desc.height);\r
+                       //      item.transform.fill_scale[1] *= 1.0 - 6.0*1.0/static_cast<double>(format_desc.height);\r
+                       //}\r
        \r
-                       // Fix field-order if needed\r
-                       if(item.field_mode == core::field_mode::lower && format_desc.field_mode == core::field_mode::upper)\r
-                               item.transform.fill_translation[1] += 1.0/static_cast<double>(format_desc.height);\r
-                       else if(item.field_mode == core::field_mode::upper && format_desc.field_mode == core::field_mode::lower)\r
-                               item.transform.fill_translation[1] -= 1.0/static_cast<double>(format_desc.height);\r
-               }\r
+                       //// Fix field-order if needed\r
+                       //if(item.field_mode == core::field_mode::lower && format_desc.field_mode == core::field_mode::upper)\r
+                       //      item.transform.fill_translation[1] += 1.0/static_cast<double>(format_desc.height);\r
+                       //else if(item.field_mode == core::field_mode::upper && format_desc.field_mode == core::field_mode::lower)\r
+                       //      item.transform.fill_translation[1] -= 1.0/static_cast<double>(format_desc.height);\r
+               //}\r
 \r
                // Mask out fields\r
                BOOST_FOREACH(auto& item, layer.items)                          \r
@@ -319,7 +318,6 @@ public:
 \r
                item item;\r
                item.pix_desc   = frame.pixel_format_desc();\r
-               item.field_mode = frame.field_mode();\r
                item.transform  = transform_stack_.back();\r
                \r
                // NOTE: Once we have copied the arrays they are no longer valid for reading!!! Check for alternative solution e.g. transfer with AMD_pinned_memory.\r
@@ -343,13 +341,13 @@ public:
                return renderer_(std::move(layers_), format_desc);\r
        }\r
        \r
-       core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode) override\r
+       core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc) override\r
        {\r
                std::vector<array<std::uint8_t>> buffers;\r
                BOOST_FOREACH(auto& plane, desc.planes)         \r
                        buffers.push_back(ogl_->create_array(plane.size));              \r
 \r
-               return core::mutable_frame(std::move(buffers), core::audio_buffer(), tag, desc, frame_rate, field_mode);\r
+               return core::mutable_frame(std::move(buffers), core::audio_buffer(), tag, desc);\r
        }\r
 };\r
 \r
@@ -361,6 +359,6 @@ void image_mixer::pop(){impl_->pop();}
 boost::unique_future<array<const std::uint8_t>> image_mixer::operator()(const core::video_format_desc& format_desc){return impl_->render(format_desc);}\r
 void image_mixer::begin_layer(core::blend_mode blend_mode){impl_->begin_layer(blend_mode);}\r
 void image_mixer::end_layer(){impl_->end_layer();}\r
-core::mutable_frame image_mixer::create_frame(const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode) {return impl_->create_frame(tag, desc, frame_rate, field_mode);}\r
+core::mutable_frame image_mixer::create_frame(const void* tag, const core::pixel_format_desc& desc) {return impl_->create_frame(tag, desc);}\r
 \r
 }}}
\ No newline at end of file
index 4ced1155f1a6208b1dee6f2d8a1efc1858a339bd..6411672a96a1bc6c59418610b7d9fc37ed7f5fd8 100644 (file)
@@ -55,7 +55,7 @@ public:
        // Methods\r
                        \r
        boost::unique_future<array<const std::uint8_t>> operator()(const core::video_format_desc& format_desc) override;                \r
-       core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode) override;\r
+       core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc) override;\r
 \r
        // core::image_mixer\r
        \r
index fc4d9409f796f79737c251e56fe268ee80e7dbf1..95b1a0372d1d2225531373e83f2637dcd9ab27a2 100644 (file)
@@ -36,20 +36,16 @@ namespace caspar { namespace core {
                \r
 struct mutable_frame::impl : boost::noncopyable\r
 {                      \r
-       std::vector<array<std::uint8_t>>                                        buffers_;\r
+       std::vector<array<std::uint8_t>>                        buffers_;\r
        core::audio_buffer                                                      audio_data_;\r
        const core::pixel_format_desc                           desc_;\r
        const void*                                                                     tag_;\r
-       double                                                                          frame_rate_;\r
-       core::field_mode                                                        field_mode_;\r
        \r
-       impl(std::vector<array<std::uint8_t>> buffers, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode\r
+       impl(std::vector<array<std::uint8_t>> buffers, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc) \r
                : buffers_(std::move(buffers))\r
                , audio_data_(std::move(audio_buffer))\r
                , desc_(desc)\r
                , tag_(tag)\r
-               , frame_rate_(frame_rate)\r
-               , field_mode_(field_mode)\r
        {\r
                BOOST_FOREACH(auto& buffer, buffers_)\r
                        if(!buffer.data())\r
@@ -57,8 +53,8 @@ struct mutable_frame::impl : boost::noncopyable
        }\r
 };\r
        \r
-mutable_frame::mutable_frame(std::vector<array<std::uint8_t>> image_buffers, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode\r
-       : impl_(new impl(std::move(image_buffers), std::move(audio_buffer), tag, desc, frame_rate, field_mode)){}\r
+mutable_frame::mutable_frame(std::vector<array<std::uint8_t>> image_buffers, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc) \r
+       : impl_(new impl(std::move(image_buffers), std::move(audio_buffer), tag, desc)){}\r
 mutable_frame::~mutable_frame(){}\r
 mutable_frame::mutable_frame(mutable_frame&& other) : impl_(std::move(other.impl_)){}\r
 mutable_frame& mutable_frame::operator=(mutable_frame&& other)\r
@@ -72,8 +68,6 @@ const array<std::uint8_t>& mutable_frame::image_data(std::size_t index) const{re
 const core::audio_buffer& mutable_frame::audio_data() const{return impl_->audio_data_;}\r
 array<std::uint8_t>& mutable_frame::image_data(std::size_t index){return impl_->buffers_.at(index);}\r
 core::audio_buffer& mutable_frame::audio_data(){return impl_->audio_data_;}\r
-double mutable_frame::frame_rate() const{return impl_->frame_rate_;}\r
-core::field_mode mutable_frame::field_mode() const{return impl_->field_mode_;}\r
 std::size_t mutable_frame::width() const{return impl_->desc_.planes.at(0).width;}\r
 std::size_t mutable_frame::height() const{return impl_->desc_.planes.at(0).height;}                                            \r
 const void* mutable_frame::stream_tag()const{return impl_->tag_;}                              \r
@@ -93,24 +87,19 @@ struct const_frame::impl : boost::noncopyable
        core::audio_buffer                                                      audio_data_;\r
        const core::pixel_format_desc                           desc_;\r
        const void*                                                                     tag_;\r
-       double                                                                          frame_rate_;\r
-       core::field_mode                                                        field_mode_;\r
 \r
        impl(const void* tag)\r
                : desc_(core::pixel_format::invalid)\r
                , tag_(tag)     \r
                , id_(0)\r
-               , field_mode_(core::field_mode::empty)\r
        {\r
        }\r
        \r
-       impl(boost::shared_future<array<const std::uint8_t>> image, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode\r
+       impl(boost::shared_future<array<const std::uint8_t>> image, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc) \r
                : audio_data_(std::move(audio_buffer))\r
                , desc_(desc)\r
                , tag_(tag)\r
                , id_(reinterpret_cast<int>(this))\r
-               , frame_rate_(frame_rate)\r
-               , field_mode_(field_mode)\r
        {\r
                if(desc.format != core::pixel_format::bgra)\r
                        BOOST_THROW_EXCEPTION(not_implemented());\r
@@ -123,8 +112,6 @@ struct const_frame::impl : boost::noncopyable
                , desc_(other.pixel_format_desc())\r
                , tag_(other.stream_tag())\r
                , id_(reinterpret_cast<int>(this))\r
-               , frame_rate_(other.frame_rate())\r
-               , field_mode_(other.field_mode())\r
        {\r
                for(std::size_t n = 0; n < desc_.planes.size(); ++n)\r
                {\r
@@ -156,8 +143,8 @@ struct const_frame::impl : boost::noncopyable
 };\r
        \r
 const_frame::const_frame(const void* tag) : impl_(new impl(tag)){}\r
-const_frame::const_frame(boost::shared_future<array<const std::uint8_t>> image, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode\r
-       : impl_(new impl(std::move(image), std::move(audio_buffer), tag, desc, frame_rate, field_mode)){}\r
+const_frame::const_frame(boost::shared_future<array<const std::uint8_t>> image, audio_buffer audio_buffer, const void* tag, const core::pixel_format_desc& desc) \r
+       : impl_(new impl(std::move(image), std::move(audio_buffer), tag, desc)){}\r
 const_frame::const_frame(mutable_frame&& other) : impl_(new impl(std::move(other))){}\r
 const_frame::~const_frame(){}\r
 const_frame::const_frame(const_frame&& other) : impl_(std::move(other.impl_)){}\r
@@ -179,8 +166,6 @@ 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_;}\r
 array<const std::uint8_t> const_frame::image_data(int index)const{return impl_->image_data(index);}\r
 const core::audio_buffer& const_frame::audio_data()const{return impl_->audio_data_;}\r
-double const_frame::frame_rate()const{return impl_->frame_rate_;}\r
-core::field_mode const_frame::field_mode()const{return impl_->field_mode_;}\r
 std::size_t const_frame::width()const{return impl_->width();}\r
 std::size_t const_frame::height()const{return impl_->height();}        \r
 std::size_t const_frame::size()const{return impl_->size();}                                            \r
index 820dd831534d43c1ff1457a14576ceda95288b7f..419d71f8891aad549201370a3d99597f4e265be0 100644 (file)
@@ -36,9 +36,7 @@ public:
        explicit mutable_frame(std::vector<array<std::uint8_t>> image_buffers, \r
                                                audio_buffer audio_buffer, \r
                                                const void* tag, \r
-                                               const struct pixel_format_desc& desc, \r
-                                               double frame_rate, \r
-                                               core::field_mode field_mode);\r
+                                               const struct pixel_format_desc& desc);\r
        ~mutable_frame();\r
 \r
        // Methods\r
@@ -58,9 +56,6 @@ public:
        array<std::uint8_t>& image_data(std::size_t index = 0);\r
        core::audio_buffer& audio_data();\r
        \r
-       double frame_rate() const;\r
-       core::field_mode field_mode() const;\r
-\r
        std::size_t width() const;\r
        std::size_t height() const;\r
                                                                \r
@@ -86,9 +81,7 @@ public:
        explicit const_frame(boost::shared_future<array<const std::uint8_t>> image, \r
                                                audio_buffer audio_buffer, \r
                                                const void* tag, \r
-                                               const struct pixel_format_desc& desc, \r
-                                               double frame_rate, \r
-                                               core::field_mode field_mode);\r
+                                               const struct pixel_format_desc& desc);\r
        const_frame(mutable_frame&& other);\r
        ~const_frame();\r
 \r
@@ -106,9 +99,6 @@ public:
        array<const std::uint8_t> image_data(int index = 0) const;\r
        const core::audio_buffer& audio_data() const;\r
                \r
-       double frame_rate() const;\r
-       core::field_mode field_mode() const;\r
-\r
        std::size_t width() const;\r
        std::size_t height() const;\r
        std::size_t size() const;\r
index 791f5addff732148e6e9d30fc55087abee5a8c95..75d46e6719c01e76818d2d49ff9bfbfe74a2eb45 100644 (file)
@@ -25,8 +25,6 @@
 \r
 #include <common/memory.h>\r
 \r
-#include <core/video_format.h>\r
-\r
 namespace caspar { namespace core {\r
                        \r
 class frame_factory : boost::noncopyable\r
@@ -43,12 +41,7 @@ public:
 \r
        // Methods\r
 \r
-       virtual class mutable_frame     create_frame(const void* video_stream_tag, const struct pixel_format_desc& desc, double frame_rate, core::field_mode field_mode) = 0;   \r
-       class mutable_frame                     create_frame(const void* video_stream_tag, const struct pixel_format_desc& desc)\r
-       {\r
-               auto format_desc = video_format_desc();\r
-               return create_frame(video_stream_tag, desc, format_desc.fps, format_desc.field_mode);\r
-       }\r
+       virtual class mutable_frame     create_frame(const void* video_stream_tag, const struct pixel_format_desc& desc) = 0;   \r
 \r
        // Properties\r
 };\r
index 7e54b236f020431e80cd68e4b48b2b8d4f499e73..aed2c8c46f711beed8ae8c686347d944a6c690a2 100644 (file)
@@ -66,7 +66,7 @@ public:
                \r
        virtual boost::unique_future<array<const std::uint8_t>> operator()(const struct video_format_desc& format_desc) = 0;\r
 \r
-       virtual class mutable_frame create_frame(const void* tag, const struct pixel_format_desc& desc, double frame_rate, core::field_mode field_mode) = 0;\r
+       virtual class mutable_frame create_frame(const void* tag, const struct pixel_format_desc& desc) = 0;\r
 \r
        // Properties\r
 };\r
index 1651143390644f5a5f360a8e9c7b8dc92a6e7b9e..2a0adbd62af9ede0f3cde51eacbe3ba7eaff31c5 100644 (file)
@@ -99,7 +99,7 @@ public:
 \r
                                auto desc = core::pixel_format_desc(core::pixel_format::bgra);\r
                                desc.planes.push_back(core::pixel_format_desc::plane(format_desc.width, format_desc.height, 4));\r
-                               return const_frame(std::move(image), std::move(audio), this, desc, format_desc.fps, format_desc.field_mode);    \r
+                               return const_frame(std::move(image), std::move(audio), this, desc);     \r
                        }\r
                        catch(...)\r
                        {\r
@@ -134,5 +134,5 @@ mixer::mixer(spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mi
 void mixer::set_blend_mode(int index, blend_mode value){impl_->set_blend_mode(index, value);}\r
 boost::unique_future<boost::property_tree::wptree> mixer::info() const{return impl_->info();}\r
 const_frame mixer::operator()(std::map<int, draw_frame> frames, const struct video_format_desc& format_desc){return (*impl_)(std::move(frames), format_desc);}\r
-mutable_frame mixer::create_frame(const void* tag, const core::pixel_format_desc& desc, double frame_rate, core::field_mode field_mode) {return impl_->image_mixer_->create_frame(tag, desc, frame_rate, field_mode);}\r
+mutable_frame mixer::create_frame(const void* tag, const core::pixel_format_desc& desc) {return impl_->image_mixer_->create_frame(tag, desc);}\r
 }}
\ No newline at end of file
index 9bf2df1e2f6fbf6d73f2369dd3ec87f957fecff6..328b852387743b7300f86138ec9787cba859fac0 100644 (file)
@@ -56,7 +56,7 @@ public:
        \r
        void set_blend_mode(int index, blend_mode value);\r
 \r
-       class mutable_frame create_frame(const void* tag, const struct pixel_format_desc& desc, double frame_rate, core::field_mode field_mode);\r
+       class mutable_frame create_frame(const void* tag, const struct pixel_format_desc& desc);\r
 \r
        // Properties\r
 \r
index 6e7166d2369a3a3f47fd28140f0cdcefc25f42bf..0212f105f81ca26673a74d19fc9966d3d6819d22 100644 (file)
@@ -278,6 +278,12 @@ struct frame_muxer::impl : boost::noncopyable
                        display_mode_ = display_mode::simple;\r
                }\r
 \r
+               if(frame->height == 480)\r
+               {\r
+                       auto pad_str = L"PAD=" + boost::lexical_cast<std::wstring>(frame->width) + L":486:0:2:black";\r
+                       filter_str = append_filter(filter_str, pad_str);\r
+               }\r
+\r
                filter_ = filter(filter_str);\r
                CASPAR_LOG(info) << L"[frame_muxer] " << display_mode_ << L" " << print_mode(frame->width, frame->height, in_fps_, frame->interlaced_frame > 0);\r
        }\r
index ff5610c0d5d6312e4d536ff67ed66736b639ba5e..cf45ece8ada5e429754446d9494e79372edbf3b4 100644 (file)
@@ -211,7 +211,7 @@ core::mutable_frame make_frame(const void* tag, const spl::shared_ptr<AVFrame>&
                \r
                auto target_desc = pixel_format_desc(target_pix_fmt, width, height);\r
 \r
-               auto write = frame_factory.create_frame(tag, target_desc, fps, get_mode(*decoded_frame));\r
+               auto write = frame_factory.create_frame(tag, target_desc);\r
 \r
                std::shared_ptr<SwsContext> sws_context;\r
 \r
@@ -261,7 +261,7 @@ core::mutable_frame make_frame(const void* tag, const spl::shared_ptr<AVFrame>&
        }\r
        else\r
        {\r
-               auto write = frame_factory.create_frame(tag, desc, fps, get_mode(*decoded_frame));\r
+               auto write = frame_factory.create_frame(tag, desc);\r
                \r
                for(int n = 0; n < static_cast<int>(desc.planes.size()); ++n)\r
                {\r
index 398c9b3ec6ef020fb7bd5ba710bae7df5fe74892..376273a3fb0306e52ce0ade193f3620609c0cbfa 100644 (file)
@@ -290,7 +290,7 @@ public:
                \r
                        core::pixel_format_desc desc = core::pixel_format::bgra;\r
                        desc.planes.push_back(core::pixel_format_desc::plane(width_, height_, 4));\r
-                       auto frame = frame_factory_->create_frame(this, desc, fps(), core::field_mode::progressive);\r
+                       auto frame = frame_factory_->create_frame(this, desc);\r
 \r
                        A_memcpy(frame.image_data(0).begin(), bmp_.data(), width_*height_*4);\r
                        head_ = core::draw_frame(std::move(frame));     \r