X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=decklink_output.cpp;h=a3d220b37c98bb96834415af5a277c47424b83cb;hb=fa54f2630c56a1df0046923d6a77b1bd58abf240;hp=d68467703103966942ce730076ab25875008ad5b;hpb=fdf765b229349a1d1a30414341957a4d10a0b6c9;p=nageru diff --git a/decklink_output.cpp b/decklink_output.cpp index d684677..a3d220b 100644 --- a/decklink_output.cpp +++ b/decklink_output.cpp @@ -12,6 +12,7 @@ #include "decklink_output.h" #include "decklink_util.h" #include "flags.h" +#include "metrics.h" #include "print_latency.h" #include "timebase.h" #include "v210_converter.h" @@ -45,6 +46,8 @@ atomic metric_decklink_output_completed_frames_unknown{0}; atomic metric_decklink_output_scheduled_samples{0}; +Summary metric_decklink_output_margin_seconds; + } // namespace DeckLinkOutput::DeckLinkOutput(ResourcePool *resource_pool, QSurface *surface, unsigned width, unsigned height, unsigned card_index) @@ -73,20 +76,23 @@ DeckLinkOutput::DeckLinkOutput(ResourcePool *resource_pool, QSurface *surface, u global_metrics.add("decklink_output_completed_frames", {{ "status", "unknown" }}, &metric_decklink_output_completed_frames_unknown); global_metrics.add("decklink_output_scheduled_samples", &metric_decklink_output_scheduled_samples); + vector quantiles{0.01, 0.1, 0.25, 0.5, 0.75, 0.9, 0.99}; + metric_decklink_output_margin_seconds.init(quantiles, 60.0); + global_metrics.add("decklink_output_margin_seconds", &metric_decklink_output_margin_seconds); }); } -void DeckLinkOutput::set_device(IDeckLink *decklink) +bool DeckLinkOutput::set_device(IDeckLink *decklink) { if (decklink->QueryInterface(IID_IDeckLinkOutput, (void**)&output) != S_OK) { - fprintf(stderr, "Card %u has no outputs\n", card_index); - exit(1); + fprintf(stderr, "Warning: Card %u has no outputs\n", card_index); + return false; } IDeckLinkDisplayModeIterator *mode_it; if (output->GetDisplayModeIterator(&mode_it) != S_OK) { - fprintf(stderr, "Failed to enumerate output display modes for card %u\n", card_index); - exit(1); + fprintf(stderr, "Warning: Failed to enumerate output display modes for card %u\n", card_index); + return false; } video_modes.clear(); @@ -112,6 +118,7 @@ void DeckLinkOutput::set_device(IDeckLink *decklink) // if they exist. We're not very likely to need analog outputs, so we don't need a way // to change beyond that. video_connection = pick_default_video_connection(decklink, BMDDeckLinkVideoOutputConnections, card_index); + return true; } void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts) @@ -373,6 +380,9 @@ void DeckLinkOutput::wait_for_frame(int64_t pts, int *dropped_frames, int64_t *f *frame_timestamp = steady_clock::now() + nanoseconds((target_time - stream_frame_time) * 1000000000 / TIMEBASE); + metric_decklink_output_margin_seconds.count_event( + (target_time - stream_frame_time) / double(TIMEBASE)); + // If we're ahead of time, wait for the frame to (approximately) start. if (stream_frame_time < target_time) { should_quit.sleep_until(*frame_timestamp); @@ -515,7 +525,7 @@ unique_ptr DeckLinkOutput::get_frame() check_error(); glBindBuffer(GL_PIXEL_PACK_BUFFER, frame->pbo); check_error(); - glBufferStorage(GL_PIXEL_PACK_BUFFER, stride * height, NULL, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT); + glBufferStorage(GL_PIXEL_PACK_BUFFER, stride * height, nullptr, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT); check_error(); frame->uyvy_ptr = (uint8_t *)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, stride * height, GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT); check_error();