* Made screen consumer poll the second field from the yadif filter after the first field has been displayed to better utilize the cpu time.
* Buffer more audio in oal_consumer when higher frame rates are used to reduce the possibility of audio pops.
#include <boost/thread.hpp>
#include <boost/chrono/system_clocks.hpp>
+#include <time.h>
+
+#include <cmath>
+
using namespace boost::chrono;
namespace caspar {
void prec_timer::tick_millis(int64_t ticks_to_wait)
{
- auto t = duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();
+ ticks_to_wait *= 1000000;
+ auto t = duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();
if (time_ != 0)
{
if (!done)
{
- // if > 0.002s left, do Sleep(1), which will actually sleep some
- // steady amount, probably 1-2 ms,
- // and do so in a nice way (cpu meter drops; laptop battery spared).
- // otherwise, do a few Sleep(0)'s, which just give up the timeslice,
- // but don't really save cpu or battery, but do pass a tiny
- // amount of time.
- if (ticks_left > 2)
- boost::this_thread::sleep_for(milliseconds(1));
- /*else
- for (int i = 0; i < 10; ++i)
- Sleep(0); // causes thread to give up its timeslice*/
+ timespec spec;
+
+ if (ticks_left > 2000000)
+ {
+ spec.tv_sec = ticks_left / 1000000000;
+ spec.tv_nsec = 1000000;
+ }
+ else
+ {
+ spec.tv_sec = 0;
+ spec.tv_nsec = ticks_left / 100;
+ }
+
+ nanosleep(&spec, nullptr);
}
- t = duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();
+ t = duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();
} while (!done);
}
#include <AL/alc.h>
#include <AL/al.h>
-#include <array>
-
namespace caspar { namespace oal {
typedef cache_aligned_vector<int16_t> audio_buffer_16;
core::video_format_desc format_desc_;
ALuint source_ = 0;
- std::array<ALuint, 3> buffers_;
+ std::vector<ALuint> buffers_;
executor executor_ { L"oal_consumer" };
public:
oal_consumer()
{
- buffers_.fill(0);
presentation_age_ = 0;
init_device();
~oal_consumer()
{
- executor_.begin_invoke([=]
+ executor_.invoke([=]
{
if(source_)
{
format_desc_ = format_desc;
channel_index_ = channel_index;
graph_->set_text(print());
-
+
executor_.begin_invoke([=]
{
+ buffers_.resize(format_desc_.fps > 30 ? 8 : 4);
alGenBuffers(static_cast<ALsizei>(buffers_.size()), buffers_.data());
alGenSources(1, &source_);
for(std::size_t n = 0; n < buffers_.size(); ++n)
{
- std::vector<int16_t> audio(format_desc_.audio_cadence[n % format_desc_.audio_cadence.size()]*format_desc_.audio_channels, 0);
+ audio_buffer_16 audio(format_desc_.audio_cadence[n % format_desc_.audio_cadence.size()]*format_desc_.audio_channels, 0);
alBufferData(buffers_[n], AL_FORMAT_STEREO16, audio.data(), static_cast<ALsizei>(audio.size()*sizeof(int16_t)), format_desc_.audio_sample_rate);
alSourceQueueBuffers(source_, 1, &buffers_[n]);
}
int delay_millis() const
{
- return 160;
+ return 213;
}
int buffer_depth() const override
return av_frame;
}
- void render_and_draw_frame(core::const_frame frame)
+ void render_and_draw_frame(core::const_frame input_frame)
{
- if(static_cast<size_t>(frame.image_data().size()) != format_desc_.size)
+ if(static_cast<size_t>(input_frame.image_data().size()) != format_desc_.size)
return;
if(screen_width_ == 0 && screen_height_ == 0)
perf_timer_.restart();
auto av_frame = get_av_frame();
- av_frame->data[0] = const_cast<uint8_t*>(frame.image_data().begin());
+ av_frame->data[0] = const_cast<uint8_t*>(input_frame.image_data().begin());
filter_.push(av_frame);
- auto frames = filter_.poll_all();
+ auto frame = filter_.poll();
- if (frames.empty())
+ if (!frame)
return;
- if (frames.size() == 1)
+ if (!filter_.is_double_rate())
{
- render(frames[0]);
+ render(spl::make_shared_ptr(frame));
graph_->set_value("frame-time", perf_timer_.elapsed() * format_desc_.fps * 0.5);
wait_for_vblank_and_display(); // progressive frame
}
- else if (frames.size() == 2)
+ else
{
- render(frames[0]);
+ render(spl::make_shared_ptr(frame));
double perf_elapsed = perf_timer_.elapsed();
wait_for_vblank_and_display(); // field1
perf_timer_.restart();
- render(frames[1]);
+ frame = filter_.poll();
+ render(spl::make_shared_ptr(frame));
perf_elapsed += perf_timer_.elapsed();
graph_->set_value("frame-time", perf_elapsed * format_desc_.fps * 0.5);