]> git.sesse.net Git - casparcg/commitdiff
Improved the screen consumer
authorhellgore <hellgore@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 8 Aug 2012 11:56:59 +0000 (11:56 +0000)
committerhellgore <hellgore@362d55ac-95cf-4e76-9f9a-cbaa9c17b72d>
Wed, 8 Aug 2012 11:56:59 +0000 (11:56 +0000)
============================

* No longer spin waits for vsync (the video card driver seems to do this at
  least with nvidia), but sleeps almost up until the time when the vertical
  blank occurs, thus the time for swap buffers (a smaller spin wait than
  before).
* Now deinterlaces to two separate frames so for example 50i will no longer
  be converted to 25p but instead to 50p for smooth playback of interlaced
  content.

git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/trunk@3205 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d

modules/ogl/consumer/ogl_consumer.cpp

index 56629197da28d30580a43a17afd928ea33a91cf9..8acc4d6bca4b85230f4abdd0e9ef31857cd008a9 100644 (file)
@@ -134,6 +134,9 @@ struct ogl_consumer : boost::noncopyable
        safe_ptr<diagnostics::graph>    graph_;\r
        boost::timer                                    perf_timer_;\r
        boost::timer                                    tick_timer_;\r
+       boost::timer                                    vblank_timer_;\r
+\r
+       caspar::high_prec_timer wait_timer_;\r
 \r
        tbb::concurrent_bounded_queue<safe_ptr<core::read_frame>>       frame_buffer_;\r
 \r
@@ -152,7 +155,7 @@ public:
                , screen_height_(format_desc.height)\r
                , square_width_(format_desc.square_width)\r
                , square_height_(format_desc.square_height)\r
-               , filter_(format_desc.field_mode == core::field_mode::progressive || !config.auto_deinterlace ? L"" : L"YADIF=0:-1", boost::assign::list_of(PIX_FMT_BGRA))\r
+               , filter_(format_desc.field_mode == core::field_mode::progressive || !config.auto_deinterlace ? L"" : L"YADIF=1:-1", boost::assign::list_of(PIX_FMT_BGRA))\r
        {               \r
                if(format_desc_.format == core::video_format::ntsc && config_.aspect == configuration::aspect_4_3)\r
                {\r
@@ -285,13 +288,10 @@ public:
                                        }\r
                        \r
                                        safe_ptr<core::read_frame> frame;\r
+\r
                                        frame_buffer_.pop(frame);\r
-                                       \r
-                                       perf_timer_.restart();\r
-                                       render(frame);\r
-                                       graph_->set_value("frame-time", perf_timer_.elapsed()*format_desc_.fps*0.5);    \r
 \r
-                                       window_.Display();\r
+                                       render_and_draw_frame(frame);\r
                                        \r
                                        graph_->set_value("tick-time", tick_timer_.elapsed()*format_desc_.fps*0.5);     \r
                                        tick_timer_.restart();\r
@@ -310,6 +310,20 @@ public:
                        CASPAR_LOG_CURRENT_EXCEPTION();\r
                }\r
        }\r
+\r
+       void try_sleep_almost_until_vblank()\r
+       {\r
+               static const double THRESHOLD = 0.005;\r
+               double threshold = config_.vsync ? THRESHOLD : 0.0;\r
+\r
+               auto elapsed = vblank_timer_.elapsed();\r
+               auto frame_time = 1.0 / (format_desc_.fps * format_desc_.field_count);\r
+\r
+               if (elapsed + threshold < frame_time)\r
+               {\r
+                       wait_timer_.tick(frame_time - elapsed - threshold);\r
+               }\r
+       }\r
        \r
        safe_ptr<AVFrame> get_av_frame()\r
        {               \r
@@ -326,22 +340,52 @@ public:
                return av_frame;\r
        }\r
 \r
-       void render(const safe_ptr<core::read_frame>& frame)\r
-       {                       \r
+       void render_and_draw_frame(const safe_ptr<core::read_frame>& frame)\r
+       {\r
                if(static_cast<size_t>(frame->image_data().size()) != format_desc_.size)\r
                        return;\r
                                        \r
+               perf_timer_.restart();\r
                auto av_frame = get_av_frame();\r
                av_frame->data[0] = const_cast<uint8_t*>(frame->image_data().begin());\r
 \r
                filter_.push(av_frame);\r
                auto frames = filter_.poll_all();\r
 \r
-               if(frames.empty())\r
+               if (frames.empty())\r
                        return;\r
 \r
-               av_frame = frames[0];\r
+               if (frames.size() == 1)\r
+               {\r
+                       render(frames[0], frame->image_data().size());\r
+                       graph_->set_value("frame-time", perf_timer_.elapsed() * format_desc_.fps * 0.5);\r
+\r
+                       try_sleep_almost_until_vblank();\r
+                       window_.Display();\r
+                       vblank_timer_.restart();\r
+               }\r
+               else if (frames.size() == 2)\r
+               {\r
+                       render(frames[0], frame->image_data().size());\r
+                       double perf_elapsed = perf_timer_.elapsed();\r
+\r
+                       try_sleep_almost_until_vblank();\r
+                       window_.Display();\r
+                       vblank_timer_.restart();\r
+\r
+                       perf_timer_.restart();\r
+                       render(frames[1], frame->image_data().size());\r
+                       perf_elapsed += perf_timer_.elapsed();\r
+                       graph_->set_value("frame-time", perf_elapsed * format_desc_.fps * 0.5);\r
 \r
+                       try_sleep_almost_until_vblank();\r
+                       window_.Display();\r
+                       vblank_timer_.restart();\r
+               }\r
+       }\r
+\r
+       void render(safe_ptr<AVFrame> av_frame, int image_data_size)\r
+       {\r
                if(av_frame->linesize[0] != static_cast<int>(format_desc_.width*4))\r
                {\r
                        const uint8_t *src_data[4] = {0};\r
@@ -371,9 +415,9 @@ public:
                if(ptr)\r
                {\r
                        if(config_.key_only)\r
-                               fast_memshfl(reinterpret_cast<char*>(ptr), av_frame->data[0], frame->image_data().size(), 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
+                               fast_memshfl(reinterpret_cast<char*>(ptr), av_frame->data[0], image_data_size, 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\r
                        else\r
-                               fast_memcpy(reinterpret_cast<char*>(ptr), av_frame->data[0], frame->image_data().size());\r
+                               fast_memcpy(reinterpret_cast<char*>(ptr), av_frame->data[0], image_data_size);\r
 \r
                        glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); // release the mapped buffer\r
                }\r
@@ -395,8 +439,9 @@ public:
 \r
        bool send(const safe_ptr<core::read_frame>& frame)\r
        {\r
-               if(!frame_buffer_.try_push(frame))\r
-                       graph_->set_tag("dropped-frame");\r
+               if (!frame_buffer_.try_push(frame))\r
+                       graph_->set_tag("dropped-frame"); \r
+\r
                return is_running_;\r
        }\r
                \r