diff --git a/app/meson.build b/app/meson.build index 553ea63a..4503a0cb 100644 --- a/app/meson.build +++ b/app/meson.build @@ -6,6 +6,7 @@ src = [ 'src/convert.c', 'src/decoder.c', 'src/device.c', + 'src/fpscounter.c', 'src/frames.c', 'src/lockutil.c', 'src/netutil.c', diff --git a/app/src/fpscounter.c b/app/src/fpscounter.c new file mode 100644 index 00000000..4cb512f3 --- /dev/null +++ b/app/src/fpscounter.c @@ -0,0 +1,62 @@ +#include "fpscounter.h" + +#include + +#include "log.h" + +void fps_counter_init(struct fps_counter *counter) { + counter->started = SDL_FALSE; + // no need to initialize the other fields, they are meaningful only when + // started is true +} + +void fps_counter_start(struct fps_counter *counter) { + counter->started = SDL_TRUE; + counter->slice_start = SDL_GetTicks(); + counter->nr_rendered = 0; +#ifdef SKIP_FRAMES + counter->nr_skipped = 0; +#endif +} + +void fps_counter_stop(struct fps_counter *counter) { + counter->started = SDL_FALSE; +} + +static void display_fps(struct fps_counter *counter) { +#ifdef SKIP_FRAMES + if (counter->nr_skipped) { + LOGI("%d fps (+%d frames skipped)", counter->nr_rendered, counter->nr_skipped); + } else { +#endif + LOGI("%d fps", counter->nr_rendered); +#ifdef SKIP_FRAMES + } +#endif +} + +static void check_expired(struct fps_counter *counter) { + Uint32 now = SDL_GetTicks(); + if (now - counter->slice_start >= 1000) { + display_fps(counter); + // add a multiple of one second + Uint32 elapsed_slices = (now - counter->slice_start) / 1000; + counter->slice_start += 1000 * elapsed_slices; + counter->nr_rendered = 0; +#ifdef SKIP_FRAMES + counter->nr_skipped = 0; +#endif + } +} + +void fps_counter_add_rendered_frame(struct fps_counter *counter) { + check_expired(counter); + ++counter->nr_rendered; +} + +#ifdef SKIP_FRAMES +void fps_counter_add_skipped_frame(struct fps_counter *counter) { + check_expired(counter); + ++counter->nr_skipped; +} +#endif diff --git a/app/src/fpscounter.h b/app/src/fpscounter.h new file mode 100644 index 00000000..27b16f28 --- /dev/null +++ b/app/src/fpscounter.h @@ -0,0 +1,26 @@ +#ifndef FPSCOUNTER_H +#define FPSCOUNTER_H + +#include + +#include "config.h" + +struct fps_counter { + SDL_bool started; + Uint32 slice_start; // initialized by SDL_GetTicks() + int nr_rendered; +#ifdef SKIP_FRAMES + int nr_skipped; +#endif +}; + +void fps_counter_init(struct fps_counter *counter); +void fps_counter_start(struct fps_counter *counter); +void fps_counter_stop(struct fps_counter *counter); + +void fps_counter_add_rendered_frame(struct fps_counter *counter); +#ifdef SKIP_FRAMES +void fps_counter_add_skipped_frame(struct fps_counter *counter); +#endif + +#endif diff --git a/app/src/frames.c b/app/src/frames.c index 1730e565..27fcc1fb 100644 --- a/app/src/frames.c +++ b/app/src/frames.c @@ -33,6 +33,7 @@ SDL_bool frames_init(struct frames *frames) { // there is initially no rendering frame, so consider it has already been // consumed frames->rendering_frame_consumed = SDL_TRUE; + fps_counter_init(&frames->fps_counter); return SDL_TRUE; @@ -68,8 +69,8 @@ SDL_bool frames_offer_decoded_frame(struct frames *frames) { cond_wait(frames->rendering_frame_consumed_cond, frames->mutex); } #else - if (!frames->rendering_frame_consumed) { - LOGD("Skip frame"); + if (frames->fps_counter.started && !frames->rendering_frame_consumed) { + fps_counter_add_skipped_frame(&frames->fps_counter); } #endif @@ -85,6 +86,9 @@ SDL_bool frames_offer_decoded_frame(struct frames *frames) { const AVFrame *frames_consume_rendered_frame(struct frames *frames) { SDL_assert(!frames->rendering_frame_consumed); frames->rendering_frame_consumed = SDL_TRUE; + if (frames->fps_counter.started) { + fps_counter_add_rendered_frame(&frames->fps_counter); + } #ifndef SKIP_FRAMES // if SKIP_FRAMES is disabled, then notify the decoder the current frame is // consumed, so that it may push a new one diff --git a/app/src/frames.h b/app/src/frames.h index 86142525..7a52d2c8 100644 --- a/app/src/frames.h +++ b/app/src/frames.h @@ -5,6 +5,7 @@ #include #include "config.h" +#include "fpscounter.h" // forward declarations typedef struct AVFrame AVFrame; @@ -18,6 +19,7 @@ struct frames { SDL_cond *rendering_frame_consumed_cond; #endif SDL_bool rendering_frame_consumed; + struct fps_counter fps_counter; }; SDL_bool frames_init(struct frames *frames); diff --git a/app/src/scrcpy.c b/app/src/scrcpy.c index b6158737..d55ae897 100644 --- a/app/src/scrcpy.c +++ b/app/src/scrcpy.c @@ -15,6 +15,7 @@ #include "device.h" #include "events.h" #include "frames.h" +#include "fpscounter.h" #include "log.h" #include "lockutil.h" #include "netutil.h" @@ -29,24 +30,6 @@ static struct frames frames; static struct decoder decoder; static struct controller controller; -static long timestamp_ms(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - -static void count_frame(void) { - static long ts = 0; - static int nbframes = 0; - long now = timestamp_ms(); - ++nbframes; - if (now - ts > 1000) { - LOGD("%d fps", nbframes); - ts = now; - nbframes = 0; - } -} - static void event_loop(void) { SDL_Event event; while (SDL_WaitEvent(&event)) { @@ -62,11 +45,11 @@ static void event_loop(void) { screen.has_frame = SDL_TRUE; // this is the very first frame, show the window screen_show_window(&screen); + fps_counter_start(&frames.fps_counter); } if (!screen_update_frame(&screen, &frames)) { return; } - count_frame(); // display fps for debug break; case SDL_WINDOWEVENT: switch (event.window.event) {