From 7ff2360e67fd316e165dfd4e33322939de25c061 Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Tue, 26 Nov 2019 20:30:46 +0100 Subject: [PATCH] Video capture: print FPS generically Centralized FPS statistics output instead of in individual vidcap modules in order to avoid multiplicities in code. + removed the FPS statistics code from testcard --- src/main.cpp | 26 ++++++++++++++++++++++--- src/video_capture.cpp | 9 +++++++++ src/video_capture.h | 4 +++- src/video_capture/DirectShowGrabber.cpp | 1 + src/video_capture/aggregate.c | 1 + src/video_capture/aja.cpp | 1 + src/video_capture/avfoundation.mm | 1 + src/video_capture/banner.cpp | 1 + src/video_capture/bitflow.cpp | 1 + src/video_capture/bluefish444.cpp | 1 + src/video_capture/decklink.cpp | 1 + src/video_capture/deltacast.cpp | 1 + src/video_capture/deltacast_dvi.cpp | 1 + src/video_capture/dvs.c | 1 + src/video_capture/file.c | 1 + src/video_capture/import.cpp | 1 + src/video_capture/ndi.cpp | 1 + src/video_capture/null.c | 1 + src/video_capture/quicktime.c | 1 + src/video_capture/rtsp.cpp | 1 + src/video_capture/screen_osx.c | 1 + src/video_capture/screen_x11.c | 1 + src/video_capture/spout.cpp | 1 + src/video_capture/switcher.c | 1 + src/video_capture/swmix.cpp | 1 + src/video_capture/syphon.mm | 1 + src/video_capture/testcard.cpp | 14 +------------ src/video_capture/testcard2.c | 1 + src/video_capture/ug_input.cpp | 1 + src/video_capture/v4l2.c | 1 + src/video_capture/ximea.c | 1 + 31 files changed, 63 insertions(+), 17 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 675ec4cb4..8dd41d48f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -62,6 +62,7 @@ #include "config_win32.h" #endif // HAVE_CONFIG_H +#include #include #include #include @@ -87,6 +88,7 @@ #include "rtp/rtp.h" #include "rtsp/rtsp_utils.h" #include "ug_runtime_error.h" +#include "utils/color_out.h" #include "utils/misc.h" #include "utils/net.h" #include "utils/thread.h" @@ -142,6 +144,7 @@ static constexpr const char *DEFAULT_AUDIO_CODEC = "PCM"; using rang::fg; using rang::style; using namespace std; +using namespace std::chrono; struct state_uv { state_uv() : capture_device{}, display_device{}, audio{}, state_video_rxtx{} { @@ -409,6 +412,21 @@ static void usage(const char *exec_path, bool full = false) printf("\n"); } +static void print_fps(bool should_print, steady_clock::time_point &t0, int &frames) { + if (!should_print) { + return; + } + frames += 1; + steady_clock::time_point t1 = steady_clock::now(); + double seconds = duration_cast>(t1 - t0).count(); + if (seconds >= 5.0) { + float fps = frames / seconds; + LOG(LOG_LEVEL_INFO) << "[capture] " << frames << " frames in " << seconds << " seconds = " << BOLD(fps << " FPS\n"); + t0 = t1; + frames = 0; + } +} + /** * This function captures video and possibly compresses it. * It then delegates sending to another thread. @@ -421,9 +439,10 @@ static void *capture_thread(void *arg) struct module *uv_mod = (struct module *)arg; struct state_uv *uv = (struct state_uv *) uv_mod->priv_data; - struct wait_obj *wait_obj; - - wait_obj = wait_obj_init(); + struct wait_obj *wait_obj = wait_obj_init(); + steady_clock::time_point t0 = steady_clock::now(); + int frames = 0; + bool should_print_fps = vidcap_generic_fps(uv->capture_device); while (!should_exit) { /* Capture and transmit video... */ @@ -436,6 +455,7 @@ static void *capture_thread(void *arg) } if (tx_frame != NULL) { + print_fps(should_print_fps, t0, frames); //tx_frame = vf_get_copy(tx_frame); bool wait_for_cur_uncompressed_frame; shared_ptr frame; diff --git a/src/video_capture.cpp b/src/video_capture.cpp index 9ab1827c5..4a7c11972 100644 --- a/src/video_capture.cpp +++ b/src/video_capture.cpp @@ -270,3 +270,12 @@ struct video_frame *vidcap_grab(struct vidcap *state, struct audio_frame **audio return frame; } +/** + * @brief Module doesn't have own FPS indicator -> use a generic one + */ +bool vidcap_generic_fps(struct vidcap *state) +{ + assert(state->magic == VIDCAP_MAGIC); + return state->funcs->use_generic_fps_indicator; +} + diff --git a/src/video_capture.h b/src/video_capture.h index 48d94f4c5..c8156551b 100644 --- a/src/video_capture.h +++ b/src/video_capture.h @@ -98,7 +98,7 @@ #include "types.h" -#define VIDEO_CAPTURE_ABI_VERSION 7 +#define VIDEO_CAPTURE_ABI_VERSION 8 #ifdef __cplusplus extern "C" { @@ -141,6 +141,7 @@ struct video_capture_info { int (*init) (struct vidcap_params *param, void **state); void (*done) (void *state); struct video_frame *(*grab) (void *state, struct audio_frame **audio); + bool use_generic_fps_indicator; ///@todo use everywhere, then remove }; struct module; @@ -153,6 +154,7 @@ int initialize_video_capture(struct module *parent, struct vidcap **state); void vidcap_done(struct vidcap *state); struct video_frame *vidcap_grab(struct vidcap *state, struct audio_frame **audio); +bool vidcap_generic_fps(struct vidcap *state); #ifdef __cplusplus } diff --git a/src/video_capture/DirectShowGrabber.cpp b/src/video_capture/DirectShowGrabber.cpp index 2f641bb40..57532aafc 100644 --- a/src/video_capture/DirectShowGrabber.cpp +++ b/src/video_capture/DirectShowGrabber.cpp @@ -1485,6 +1485,7 @@ static const struct video_capture_info vidcap_dshow_info = { vidcap_dshow_init, vidcap_dshow_done, vidcap_dshow_grab, + false }; REGISTER_MODULE(dshow, &vidcap_dshow_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/aggregate.c b/src/video_capture/aggregate.c index 378dd66a6..10dff7b37 100644 --- a/src/video_capture/aggregate.c +++ b/src/video_capture/aggregate.c @@ -247,6 +247,7 @@ static const struct video_capture_info vidcap_aggregate_info = { vidcap_aggregate_init, vidcap_aggregate_done, vidcap_aggregate_grab, + false }; REGISTER_MODULE(aggregate, &vidcap_aggregate_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/aja.cpp b/src/video_capture/aja.cpp index 94b6ee797..e6f1fddf6 100644 --- a/src/video_capture/aja.cpp +++ b/src/video_capture/aja.cpp @@ -1143,6 +1143,7 @@ static const struct video_capture_info vidcap_aja_info = { vidcap_aja_init, vidcap_aja_done, vidcap_aja_grab, + false }; REGISTER_MODULE(aja, &vidcap_aja_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/avfoundation.mm b/src/video_capture/avfoundation.mm index 51416ce3d..603b3cd41 100644 --- a/src/video_capture/avfoundation.mm +++ b/src/video_capture/avfoundation.mm @@ -597,6 +597,7 @@ static const struct video_capture_info vidcap_avfoundation_info = { vidcap_avfoundation_init, vidcap_avfoundation_done, vidcap_avfoundation_grab, + false }; REGISTER_MODULE(avfoundation, &vidcap_avfoundation_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/banner.cpp b/src/video_capture/banner.cpp index 155d571b5..fecee8e1f 100644 --- a/src/video_capture/banner.cpp +++ b/src/video_capture/banner.cpp @@ -269,6 +269,7 @@ static const struct video_capture_info vidcap_banner_info = { vidcap_banner_init, vidcap_banner_done, vidcap_banner_grab, + false }; REGISTER_MODULE(banner, &vidcap_banner_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/bitflow.cpp b/src/video_capture/bitflow.cpp index be1527b1c..01ed8c5d2 100644 --- a/src/video_capture/bitflow.cpp +++ b/src/video_capture/bitflow.cpp @@ -361,6 +361,7 @@ static const struct video_capture_info vidcap_bitflow_info = { vidcap_bitflow_init, vidcap_bitflow_done, vidcap_bitflow_grab, + false }; REGISTER_MODULE(bitflow, &vidcap_bitflow_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/bluefish444.cpp b/src/video_capture/bluefish444.cpp index 7413f5ef4..b8c882a7b 100644 --- a/src/video_capture/bluefish444.cpp +++ b/src/video_capture/bluefish444.cpp @@ -1081,6 +1081,7 @@ static const struct video_capture_info vidcap_bluefish444_info = { vidcap_bluefish444_init, vidcap_bluefish444_done, vidcap_bluefish444_grab, + false }; REGISTER_MODULE(bluefish444, &vidcap_bluefish444_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/decklink.cpp b/src/video_capture/decklink.cpp index 3626a38f3..e3cba7c56 100644 --- a/src/video_capture/decklink.cpp +++ b/src/video_capture/decklink.cpp @@ -1755,6 +1755,7 @@ static const struct video_capture_info vidcap_decklink_info = { vidcap_decklink_init, vidcap_decklink_done, vidcap_decklink_grab, + false }; REGISTER_MODULE(decklink, &vidcap_decklink_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/deltacast.cpp b/src/video_capture/deltacast.cpp index 1713a2b45..d4c47d25e 100644 --- a/src/video_capture/deltacast.cpp +++ b/src/video_capture/deltacast.cpp @@ -583,6 +583,7 @@ static const struct video_capture_info vidcap_deltacast_info = { vidcap_deltacast_init, vidcap_deltacast_done, vidcap_deltacast_grab, + false }; REGISTER_MODULE(deltacast, &vidcap_deltacast_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/deltacast_dvi.cpp b/src/video_capture/deltacast_dvi.cpp index 8ad366a88..8a3811354 100644 --- a/src/video_capture/deltacast_dvi.cpp +++ b/src/video_capture/deltacast_dvi.cpp @@ -834,6 +834,7 @@ static const struct video_capture_info vidcap_deltacast_dvi_info = { vidcap_deltacast_dvi_init, vidcap_deltacast_dvi_done, vidcap_deltacast_dvi_grab, + false }; REGISTER_MODULE(deltacast-dv, &vidcap_deltacast_dvi_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/dvs.c b/src/video_capture/dvs.c index 0d79b1bb9..3699009d1 100644 --- a/src/video_capture/dvs.c +++ b/src/video_capture/dvs.c @@ -686,6 +686,7 @@ static const struct video_capture_info vidcap_dvs_info = { vidcap_dvs_init, vidcap_dvs_done, vidcap_dvs_grab, + false }; REGISTER_MODULE(dvs, &vidcap_dvs_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/file.c b/src/video_capture/file.c index 7d40ec522..909dfd68b 100644 --- a/src/video_capture/file.c +++ b/src/video_capture/file.c @@ -590,6 +590,7 @@ static const struct video_capture_info vidcap_file_info = { vidcap_file_init, vidcap_file_done, vidcap_file_grab, + false }; REGISTER_MODULE(file, &vidcap_file_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/import.cpp b/src/video_capture/import.cpp index 0852faf4a..94921bce9 100644 --- a/src/video_capture/import.cpp +++ b/src/video_capture/import.cpp @@ -1136,6 +1136,7 @@ static const struct video_capture_info vidcap_import_info = { vidcap_import_init, vidcap_import_done, vidcap_import_grab, + false }; REGISTER_MODULE(import, &vidcap_import_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/ndi.cpp b/src/video_capture/ndi.cpp index dfebcd9c9..9b2da9535 100644 --- a/src/video_capture/ndi.cpp +++ b/src/video_capture/ndi.cpp @@ -441,6 +441,7 @@ static const struct video_capture_info vidcap_ndi_info = { vidcap_ndi_init, vidcap_ndi_done, vidcap_ndi_grab, + false }; REGISTER_MODULE(ndi, &vidcap_ndi_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/null.c b/src/video_capture/null.c index a00962eab..beb3ade45 100644 --- a/src/video_capture/null.c +++ b/src/video_capture/null.c @@ -99,6 +99,7 @@ static const struct video_capture_info vidcap_null_info = { vidcap_null_init, vidcap_null_done, vidcap_null_grab, + false }; REGISTER_MODULE(none, &vidcap_null_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/quicktime.c b/src/video_capture/quicktime.c index 932e4e97a..a57a55697 100644 --- a/src/video_capture/quicktime.c +++ b/src/video_capture/quicktime.c @@ -1217,6 +1217,7 @@ static const struct video_capture_info vidcap_quicktime_info = { vidcap_quicktime_init, vidcap_quicktime_done, vidcap_quicktime_grab, + false }; REGISTER_MODULE(quicktime, &vidcap_quicktime_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/rtsp.cpp b/src/video_capture/rtsp.cpp index 874a4e551..fd5afcbe4 100644 --- a/src/video_capture/rtsp.cpp +++ b/src/video_capture/rtsp.cpp @@ -1187,6 +1187,7 @@ static const struct video_capture_info vidcap_rtsp_info = { vidcap_rtsp_init, vidcap_rtsp_done, vidcap_rtsp_grab, + false }; REGISTER_MODULE(rtsp, &vidcap_rtsp_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/screen_osx.c b/src/video_capture/screen_osx.c index 67bc6d8ce..477c060a3 100644 --- a/src/video_capture/screen_osx.c +++ b/src/video_capture/screen_osx.c @@ -267,6 +267,7 @@ static const struct video_capture_info vidcap_screen_osx_info = { vidcap_screen_osx_init, vidcap_screen_osx_done, vidcap_screen_osx_grab, + false }; REGISTER_MODULE(screen, &vidcap_screen_osx_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/screen_x11.c b/src/video_capture/screen_x11.c index 4cfc8b1ec..6c3d5786e 100644 --- a/src/video_capture/screen_x11.c +++ b/src/video_capture/screen_x11.c @@ -450,6 +450,7 @@ static const struct video_capture_info vidcap_screen_x11_info = { vidcap_screen_x11_init, vidcap_screen_x11_done, vidcap_screen_x11_grab, + false }; REGISTER_MODULE(screen, &vidcap_screen_x11_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/spout.cpp b/src/video_capture/spout.cpp index f80a75601..6ca96086e 100644 --- a/src/video_capture/spout.cpp +++ b/src/video_capture/spout.cpp @@ -228,6 +228,7 @@ static const struct video_capture_info vidcap_spout_info = { vidcap_spout_init, vidcap_spout_done, vidcap_spout_grab, + false }; REGISTER_MODULE(spout, &vidcap_spout_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/switcher.c b/src/video_capture/switcher.c index 906cc3022..f22e43d63 100644 --- a/src/video_capture/switcher.c +++ b/src/video_capture/switcher.c @@ -262,6 +262,7 @@ static const struct video_capture_info vidcap_switcher_info = { vidcap_switcher_init, vidcap_switcher_done, vidcap_switcher_grab, + false }; REGISTER_MODULE(switcher, &vidcap_switcher_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/swmix.cpp b/src/video_capture/swmix.cpp index dff950e24..d28b33c91 100644 --- a/src/video_capture/swmix.cpp +++ b/src/video_capture/swmix.cpp @@ -1357,6 +1357,7 @@ static const struct video_capture_info vidcap_swmix_info = { vidcap_swmix_init, vidcap_swmix_done, vidcap_swmix_grab, + false }; REGISTER_MODULE(swmix, &vidcap_swmix_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/syphon.mm b/src/video_capture/syphon.mm index c0f1ffa9e..25e2e279d 100644 --- a/src/video_capture/syphon.mm +++ b/src/video_capture/syphon.mm @@ -465,6 +465,7 @@ static const struct video_capture_info vidcap_syphon_info = { vidcap_syphon_init, vidcap_syphon_done, vidcap_syphon_grab, + false }; REGISTER_MODULE(syphon, &vidcap_syphon_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/testcard.cpp b/src/video_capture/testcard.cpp index e34df90e7..dacb5a375 100644 --- a/src/video_capture/testcard.cpp +++ b/src/video_capture/testcard.cpp @@ -100,7 +100,6 @@ enum class image_pattern : int { struct testcard_state { std::chrono::steady_clock::time_point last_frame_time; - int count; int size; int pan; struct testcard_pixmap pixmap; @@ -598,7 +597,6 @@ static int vidcap_testcard_init(struct vidcap_params *params, void **state) s->data = vf_get_tile(s->frame, 0)->data; } - s->count = 0; s->last_frame_time = std::chrono::steady_clock::now(); printf("Testcard capture set to %dx%d, bpp %f\n", vf_get_tile(s->frame, 0)->width, @@ -670,17 +668,6 @@ static struct video_frame *vidcap_testcard_grab(void *arg, struct audio_frame ** } state->last_frame_time = curr_time; - state->count++; - - double seconds = - std::chrono::duration_cast>(curr_time - state->t0).count(); - if (seconds >= 5.0) { - float fps = state->count / seconds; - log_msg(LOG_LEVEL_INFO, "[testcard] %d frames in %g seconds = %g FPS\n", - state->count, seconds, fps); - state->t0 = curr_time; - state->count = 0; - } if (state->grab_audio) { #ifdef HAVE_LIBSDL_MIXER @@ -827,6 +814,7 @@ static const struct video_capture_info vidcap_testcard_info = { vidcap_testcard_init, vidcap_testcard_done, vidcap_testcard_grab, + true }; REGISTER_MODULE(testcard, &vidcap_testcard_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/testcard2.c b/src/video_capture/testcard2.c index 9e9d4641e..575775fb5 100644 --- a/src/video_capture/testcard2.c +++ b/src/video_capture/testcard2.c @@ -551,6 +551,7 @@ static const struct video_capture_info vidcap_testcard2_info = { vidcap_testcard2_init, vidcap_testcard2_done, vidcap_testcard2_grab, + false }; REGISTER_MODULE(testcard2, &vidcap_testcard2_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/ug_input.cpp b/src/video_capture/ug_input.cpp index 6014a1119..5925d348b 100644 --- a/src/video_capture/ug_input.cpp +++ b/src/video_capture/ug_input.cpp @@ -213,6 +213,7 @@ static const struct video_capture_info vidcap_ug_input_info = { vidcap_ug_input_init, vidcap_ug_input_done, vidcap_ug_input_grab, + false }; REGISTER_MODULE(ug_input, &vidcap_ug_input_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/v4l2.c b/src/video_capture/v4l2.c index 586d6acf2..8a9e44f68 100644 --- a/src/video_capture/v4l2.c +++ b/src/video_capture/v4l2.c @@ -874,6 +874,7 @@ static const struct video_capture_info vidcap_v4l2_info = { vidcap_v4l2_init, vidcap_v4l2_done, vidcap_v4l2_grab, + false }; REGISTER_MODULE(v4l2, &vidcap_v4l2_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION); diff --git a/src/video_capture/ximea.c b/src/video_capture/ximea.c index 93e47f5f1..570bce7bf 100644 --- a/src/video_capture/ximea.c +++ b/src/video_capture/ximea.c @@ -236,6 +236,7 @@ static const struct video_capture_info vidcap_ximea_info = { vidcap_ximea_init, vidcap_ximea_done, vidcap_ximea_grab, + true }; REGISTER_MODULE(ximea, &vidcap_ximea_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION);