Optionally do not delay the first frame

A delay buffer delayed all the frames except the first one, to open the
scrcpy window immediately and get a picture.

Make this feature optional, so that the delay buffer might also be used
for audio (especially for simulating a high delay for debugging).

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
This commit is contained in:
Romain Vimont 2023-03-02 22:33:31 +01:00
parent 9b3ca208bf
commit e1333f6f3b
3 changed files with 12 additions and 7 deletions

View file

@ -194,10 +194,8 @@ sc_delay_buffer_frame_sink_push(struct sc_frame_sink *sink,
sc_clock_update(&db->clock, sc_tick_now(), pts); sc_clock_update(&db->clock, sc_tick_now(), pts);
sc_cond_signal(&db->wait_cond); sc_cond_signal(&db->wait_cond);
if (db->clock.count == 1) { if (db->first_frame_asap && db->clock.count == 1) {
sc_mutex_unlock(&db->mutex); sc_mutex_unlock(&db->mutex);
// First frame, push it immediately, not to delay the opening of the
// scrcpy window
return sc_frame_source_sinks_push(&db->frame_source, frame); return sc_frame_source_sinks_push(&db->frame_source, frame);
} }
@ -227,10 +225,12 @@ sc_delay_buffer_frame_sink_push(struct sc_frame_sink *sink,
} }
void void
sc_delay_buffer_init(struct sc_delay_buffer *db, sc_tick delay) { sc_delay_buffer_init(struct sc_delay_buffer *db, sc_tick delay,
bool first_frame_asap) {
assert(delay > 0); assert(delay > 0);
db->delay = delay; db->delay = delay;
db->first_frame_asap = first_frame_asap;
sc_frame_source_init(&db->frame_source); sc_frame_source_init(&db->frame_source);

View file

@ -29,6 +29,7 @@ struct sc_delay_buffer {
struct sc_frame_sink frame_sink; // frame sink trait struct sc_frame_sink frame_sink; // frame sink trait
sc_tick delay; sc_tick delay;
bool first_frame_asap;
sc_thread thread; sc_thread thread;
sc_mutex mutex; sc_mutex mutex;
@ -49,8 +50,11 @@ struct sc_delay_buffer_callbacks {
* Initialize a delay buffer. * Initialize a delay buffer.
* *
* \param delay a (strictly) positive delay * \param delay a (strictly) positive delay
* \param first_frame_asap if true, do not delay the first frame (useful for
a video stream).
*/ */
void void
sc_delay_buffer_init(struct sc_delay_buffer *db, sc_tick delay); sc_delay_buffer_init(struct sc_delay_buffer *db, sc_tick delay,
bool first_frame_asap);
#endif #endif

View file

@ -669,7 +669,8 @@ aoa_hid_end:
struct sc_frame_source *src = &s->video_decoder.frame_source; struct sc_frame_source *src = &s->video_decoder.frame_source;
if (options->display_buffer) { if (options->display_buffer) {
sc_delay_buffer_init(&s->display_buffer, options->display_buffer); sc_delay_buffer_init(&s->display_buffer, options->display_buffer,
true);
sc_frame_source_add_sink(src, &s->display_buffer.frame_sink); sc_frame_source_add_sink(src, &s->display_buffer.frame_sink);
src = &s->display_buffer.frame_source; src = &s->display_buffer.frame_source;
} }
@ -686,7 +687,7 @@ aoa_hid_end:
struct sc_frame_source *src = &s->video_decoder.frame_source; struct sc_frame_source *src = &s->video_decoder.frame_source;
if (options->v4l2_buffer) { if (options->v4l2_buffer) {
sc_delay_buffer_init(&s->v4l2_buffer, options->v4l2_buffer); sc_delay_buffer_init(&s->v4l2_buffer, options->v4l2_buffer, true);
sc_frame_source_add_sink(src, &s->v4l2_buffer.frame_sink); sc_frame_source_add_sink(src, &s->v4l2_buffer.frame_sink);
src = &s->v4l2_buffer.frame_source; src = &s->v4l2_buffer.frame_source;
} }