From 0324a1c7714f2f71063c274a4e03953a6145ff9e Mon Sep 17 00:00:00 2001 From: ronag Date: Sat, 3 Sep 2011 20:19:27 +0000 Subject: [PATCH] 2.0. Fixed rendering stalls caused by ogl frame allocation delays. git-svn-id: https://casparcg.svn.sourceforge.net/svnroot/casparcg/server/branches/2.0.0.2@1339 362d55ac-95cf-4e76-9f9a-cbaa9c17b72d --- core/mixer/gpu/ogl_device.cpp | 192 ++++++++++---------- core/mixer/gpu/ogl_device.h | 5 + core/mixer/image/image_kernel.cpp | 3 + modules/ffmpeg/producer/ffmpeg_producer.cpp | 25 ++- modules/ffmpeg/producer/util.cpp | 2 +- 5 files changed, 130 insertions(+), 97 deletions(-) diff --git a/core/mixer/gpu/ogl_device.cpp b/core/mixer/gpu/ogl_device.cpp index ba7db7ea0..9f83317d9 100644 --- a/core/mixer/gpu/ogl_device.cpp +++ b/core/mixer/gpu/ogl_device.cpp @@ -75,6 +75,32 @@ ogl_device::~ogl_device() glDeleteFramebuffersEXT(1, &fbo_); }); } + +safe_ptr ogl_device::allocate_device_buffer(size_t width, size_t height, size_t stride) +{ + std::shared_ptr buffer; + try + { + buffer.reset(new device_buffer(width, height, stride)); + } + catch(...) + { + try + { + yield(); + gc().wait(); + + // Try again + buffer.reset(new device_buffer(width, height, stride)); + } + catch(...) + { + CASPAR_LOG(error) << L"ogl: create_device_buffer failed!"; + throw; + } + } + return make_safe(buffer); +} safe_ptr ogl_device::create_device_buffer(size_t width, size_t height, size_t stride) { @@ -83,39 +109,51 @@ safe_ptr ogl_device::create_device_buffer(size_t width, size_t he auto& pool = device_pools_[stride-1][((width << 16) & 0xFFFF0000) | (height & 0x0000FFFF)]; std::shared_ptr buffer; if(!pool->items.try_pop(buffer)) - { - executor_.invoke([&] - { - try - { - buffer.reset(new device_buffer(width, height, stride)); - } - catch(...) - { - try - { - yield(); - gc().wait(); - - // Try again - buffer.reset(new device_buffer(width, height, stride)); - } - catch(...) - { - CASPAR_LOG(error) << L"ogl: create_device_buffer failed!"; - throw; - } - } - }, high_priority); - } + buffer = executor_.invoke([&]{return allocate_device_buffer(width, height, stride);}, high_priority); - ++pool->usage_count; + //++pool->usage_count; return safe_ptr(buffer.get(), [=](device_buffer*) mutable { pool->items.push(buffer); }); } + +safe_ptr ogl_device::allocate_host_buffer(size_t size, host_buffer::usage_t usage) +{ + std::shared_ptr buffer; + + try + { + buffer.reset(new host_buffer(size, usage)); + if(usage == host_buffer::write_only) + buffer->map(); + else + buffer->unmap(); + } + catch(...) + { + try + { + yield(); + gc().wait(); + + // Try again + buffer.reset(new host_buffer(size, usage)); + if(usage == host_buffer::write_only) + buffer->map(); + else + buffer->unmap(); + } + catch(...) + { + CASPAR_LOG(error) << L"ogl: create_host_buffer failed!"; + throw; + } + } + + return make_safe(buffer); +} safe_ptr ogl_device::create_host_buffer(size_t size, host_buffer::usage_t usage) { @@ -123,42 +161,10 @@ safe_ptr ogl_device::create_host_buffer(size_t size, host_buffer::u CASPAR_VERIFY(size > 0); auto& pool = host_pools_[usage][size]; std::shared_ptr buffer; - if(!pool->items.try_pop(buffer)) - { - executor_.invoke([&] - { - try - { - buffer.reset(new host_buffer(size, usage)); - if(usage == host_buffer::write_only) - buffer->map(); - else - buffer->unmap(); - } - catch(...) - { - try - { - yield(); - gc().wait(); - - // Try again - buffer.reset(new host_buffer(size, usage)); - if(usage == host_buffer::write_only) - buffer->map(); - else - buffer->unmap(); - } - catch(...) - { - CASPAR_LOG(error) << L"ogl: create_host_buffer failed!"; - throw; - } - } - }, high_priority); - } + if(!pool->items.try_pop(buffer)) + buffer = executor_.invoke([=]{return allocate_host_buffer(size, usage);}, high_priority); - ++pool->usage_count; + //++pool->usage_count; return safe_ptr(buffer.get(), [=](host_buffer*) mutable { @@ -174,43 +180,43 @@ safe_ptr ogl_device::create_host_buffer(size_t size, host_buffer::u }); } -template -void flush_pool(buffer_pool& pool) -{ - if(pool.flush_count.fetch_and_increment() < 16) - return; - - if(pool.usage_count.fetch_and_store(0) < pool.items.size()) - { - std::shared_ptr buffer; - pool.items.try_pop(buffer); - } - - pool.flush_count = 0; - pool.usage_count = 0; -} +//template +//void flush_pool(buffer_pool& pool) +//{ +// if(pool.flush_count.fetch_and_increment() < 16) +// return; +// +// if(pool.usage_count.fetch_and_store(0) < pool.items.size()) +// { +// std::shared_ptr buffer; +// pool.items.try_pop(buffer); +// } +// +// pool.flush_count = 0; +// pool.usage_count = 0; +//} void ogl_device::flush() { GL(glFlush()); - try - { - BOOST_FOREACH(auto& pools, device_pools_) - { - BOOST_FOREACH(auto& pool, pools) - flush_pool(*pool.second); - } - BOOST_FOREACH(auto& pools, host_pools_) - { - BOOST_FOREACH(auto& pool, pools) - flush_pool(*pool.second); - } - } - catch(...) - { - CASPAR_LOG_CURRENT_EXCEPTION(); - } + //try + //{ + // BOOST_FOREACH(auto& pools, device_pools_) + // { + // BOOST_FOREACH(auto& pool, pools) + // flush_pool(*pool.second); + // } + // BOOST_FOREACH(auto& pools, host_pools_) + // { + // BOOST_FOREACH(auto& pool, pools) + // flush_pool(*pool.second); + // } + //} + //catch(...) + //{ + // CASPAR_LOG_CURRENT_EXCEPTION(); + //} } void ogl_device::yield() diff --git a/core/mixer/gpu/ogl_device.h b/core/mixer/gpu/ogl_device.h index d1fb65b2d..872046c0b 100644 --- a/core/mixer/gpu/ogl_device.h +++ b/core/mixer/gpu/ogl_device.h @@ -115,10 +115,15 @@ public: safe_ptr create_device_buffer(size_t width, size_t height, size_t stride); safe_ptr create_host_buffer(size_t size, host_buffer::usage_t usage); + void yield(); boost::unique_future gc(); static std::wstring get_version(); + +private: + safe_ptr allocate_device_buffer(size_t width, size_t height, size_t stride); + safe_ptr allocate_host_buffer(size_t size, host_buffer::usage_t usage); }; }} \ No newline at end of file diff --git a/core/mixer/image/image_kernel.cpp b/core/mixer/image/image_kernel.cpp index 9e5e4de0c..1eeb50bd3 100644 --- a/core/mixer/image/image_kernel.cpp +++ b/core/mixer/image/image_kernel.cpp @@ -65,6 +65,8 @@ struct image_kernel::implementation : boost::noncopyable { static const double epsilon = 0.001; + ogl.yield(); + CASPAR_ASSERT(params.pix_desc.planes.size() == params.textures.size()); if(params.textures.empty() || !params.background) @@ -204,6 +206,7 @@ struct image_kernel::implementation : boost::noncopyable // Set render target + ogl.yield(); ogl.attach(*params.background); // Draw diff --git a/modules/ffmpeg/producer/ffmpeg_producer.cpp b/modules/ffmpeg/producer/ffmpeg_producer.cpp index 8d0c81d25..d1ca8c029 100644 --- a/modules/ffmpeg/producer/ffmpeg_producer.cpp +++ b/modules/ffmpeg/producer/ffmpeg_producer.cpp @@ -99,8 +99,22 @@ public: graph_->set_color("frame-time", diagnostics::color(0.1f, 1.0f, 0.1f)); graph_->set_color("underflow", diagnostics::color(0.6f, 0.3f, 0.9f)); - for(int n = 0; n < 32 && muxer_.empty(); ++n) - decode_frame(0); + // Do some pre-work in order to not block rendering thread for initialization and allocations. + + push_packets(); + auto video_frames = video_decoder_.poll(); + if(!video_frames.empty()) + { + auto& video_frame = video_frames.front(); + auto desc = get_pixel_format_desc(static_cast(video_frame->format), video_frame->width, video_frame->height); + if(desc.pix_fmt == core::pixel_format::invalid) + get_pixel_format_desc(PIX_FMT_BGRA, video_frame->width, video_frame->height); + + for(int n = 0; n < 3; ++n) + frame_factory->create_frame(this, desc); + } + BOOST_FOREACH(auto& video, video_frames) + muxer_.push(video, 0); } virtual safe_ptr receive(int hints) @@ -132,7 +146,7 @@ public: return disable_audio(last_frame_); } - void decode_frame(int hints) + void push_packets() { for(int n = 0; n < 16 && ((!muxer_.video_ready() && !video_decoder_.ready()) || (!muxer_.audio_ready() && !audio_decoder_.ready())); ++n) { @@ -143,6 +157,11 @@ public: audio_decoder_.push(pkt); } } + } + + void decode_frame(int hints) + { + push_packets(); tbb::parallel_invoke( [&] diff --git a/modules/ffmpeg/producer/util.cpp b/modules/ffmpeg/producer/util.cpp index 81148d614..2a2595680 100644 --- a/modules/ffmpeg/producer/util.cpp +++ b/modules/ffmpeg/producer/util.cpp @@ -140,7 +140,7 @@ safe_ptr make_write_frame(const void* tag, const safe_ptr(decoded_frame->format); - auto write = frame_factory->create_frame(tag, desc.pix_fmt != core::pixel_format::invalid ? desc : get_pixel_format_desc(PIX_FMT_BGRA, width, height)); + auto write = frame_factory->create_frame(tag, get_pixel_format_desc(PIX_FMT_BGRA, width, height)); write->set_type(get_mode(*decoded_frame)); std::shared_ptr sws_context; -- 2.39.2