Remove anonymous struct in delay buffer

For clarity, the fields used only when a delay was set were wrapped in
an anonymous structure.

Now that the delay buffer has been extracted to a separate component,
the delay is necessarily set (it may not be 0), so the fields are always
used.

PR #3757 <https://github.com/Genymobile/scrcpy/pull/3757>
This commit is contained in:
Romain Vimont 2023-03-02 21:30:24 +01:00
parent 1230149fdd
commit 48a537d45c
2 changed files with 54 additions and 56 deletions

View file

@ -43,37 +43,37 @@ run_buffering(void *data) {
assert(db->delay > 0); assert(db->delay > 0);
for (;;) { for (;;) {
sc_mutex_lock(&db->b.mutex); sc_mutex_lock(&db->mutex);
while (!db->b.stopped && sc_vecdeque_is_empty(&db->b.queue)) { while (!db->stopped && sc_vecdeque_is_empty(&db->queue)) {
sc_cond_wait(&db->b.queue_cond, &db->b.mutex); sc_cond_wait(&db->queue_cond, &db->mutex);
} }
if (db->b.stopped) { if (db->stopped) {
sc_mutex_unlock(&db->b.mutex); sc_mutex_unlock(&db->mutex);
goto stopped; goto stopped;
} }
struct sc_delayed_frame dframe = sc_vecdeque_pop(&db->b.queue); struct sc_delayed_frame dframe = sc_vecdeque_pop(&db->queue);
sc_tick max_deadline = sc_tick_now() + db->delay; sc_tick max_deadline = sc_tick_now() + db->delay;
// PTS (written by the server) are expressed in microseconds // PTS (written by the server) are expressed in microseconds
sc_tick pts = SC_TICK_FROM_US(dframe.frame->pts); sc_tick pts = SC_TICK_FROM_US(dframe.frame->pts);
bool timed_out = false; bool timed_out = false;
while (!db->b.stopped && !timed_out) { while (!db->stopped && !timed_out) {
sc_tick deadline = sc_clock_to_system_time(&db->b.clock, pts) sc_tick deadline = sc_clock_to_system_time(&db->clock, pts)
+ db->delay; + db->delay;
if (deadline > max_deadline) { if (deadline > max_deadline) {
deadline = max_deadline; deadline = max_deadline;
} }
timed_out = timed_out =
!sc_cond_timedwait(&db->b.wait_cond, &db->b.mutex, deadline); !sc_cond_timedwait(&db->wait_cond, &db->mutex, deadline);
} }
bool stopped = db->b.stopped; bool stopped = db->stopped;
sc_mutex_unlock(&db->b.mutex); sc_mutex_unlock(&db->mutex);
if (stopped) { if (stopped) {
sc_delayed_frame_destroy(&dframe); sc_delayed_frame_destroy(&dframe);
@ -89,20 +89,20 @@ run_buffering(void *data) {
sc_delayed_frame_destroy(&dframe); sc_delayed_frame_destroy(&dframe);
if (!ok) { if (!ok) {
LOGE("Delayed frame could not be pushed, stopping"); LOGE("Delayed frame could not be pushed, stopping");
sc_mutex_lock(&db->b.mutex); sc_mutex_lock(&db->mutex);
// Prevent to push any new frame // Prevent to push any new frame
db->b.stopped = true; db->stopped = true;
sc_mutex_unlock(&db->b.mutex); sc_mutex_unlock(&db->mutex);
goto stopped; goto stopped;
} }
} }
stopped: stopped:
assert(db->b.stopped); assert(db->stopped);
// Flush queue // Flush queue
while (!sc_vecdeque_is_empty(&db->b.queue)) { while (!sc_vecdeque_is_empty(&db->queue)) {
struct sc_delayed_frame *dframe = sc_vecdeque_popref(&db->b.queue); struct sc_delayed_frame *dframe = sc_vecdeque_popref(&db->queue);
sc_delayed_frame_destroy(dframe); sc_delayed_frame_destroy(dframe);
} }
@ -117,29 +117,29 @@ sc_delay_buffer_frame_sink_open(struct sc_frame_sink *sink,
struct sc_delay_buffer *db = DOWNCAST(sink); struct sc_delay_buffer *db = DOWNCAST(sink);
(void) ctx; (void) ctx;
bool ok = sc_mutex_init(&db->b.mutex); bool ok = sc_mutex_init(&db->mutex);
if (!ok) { if (!ok) {
return false; return false;
} }
ok = sc_cond_init(&db->b.queue_cond); ok = sc_cond_init(&db->queue_cond);
if (!ok) { if (!ok) {
goto error_destroy_mutex; goto error_destroy_mutex;
} }
ok = sc_cond_init(&db->b.wait_cond); ok = sc_cond_init(&db->wait_cond);
if (!ok) { if (!ok) {
goto error_destroy_queue_cond; goto error_destroy_queue_cond;
} }
sc_clock_init(&db->b.clock); sc_clock_init(&db->clock);
sc_vecdeque_init(&db->b.queue); sc_vecdeque_init(&db->queue);
if (!sc_frame_source_sinks_open(&db->frame_source, ctx)) { if (!sc_frame_source_sinks_open(&db->frame_source, ctx)) {
goto error_destroy_wait_cond; goto error_destroy_wait_cond;
} }
ok = sc_thread_create(&db->b.thread, run_buffering, "scrcpy-dbuf", db); ok = sc_thread_create(&db->thread, run_buffering, "scrcpy-dbuf", db);
if (!ok) { if (!ok) {
LOGE("Could not start buffering thread"); LOGE("Could not start buffering thread");
goto error_close_sinks; goto error_close_sinks;
@ -150,11 +150,11 @@ sc_delay_buffer_frame_sink_open(struct sc_frame_sink *sink,
error_close_sinks: error_close_sinks:
sc_frame_source_sinks_close(&db->frame_source); sc_frame_source_sinks_close(&db->frame_source);
error_destroy_wait_cond: error_destroy_wait_cond:
sc_cond_destroy(&db->b.wait_cond); sc_cond_destroy(&db->wait_cond);
error_destroy_queue_cond: error_destroy_queue_cond:
sc_cond_destroy(&db->b.queue_cond); sc_cond_destroy(&db->queue_cond);
error_destroy_mutex: error_destroy_mutex:
sc_mutex_destroy(&db->b.mutex); sc_mutex_destroy(&db->mutex);
return false; return false;
} }
@ -163,19 +163,19 @@ static void
sc_delay_buffer_frame_sink_close(struct sc_frame_sink *sink) { sc_delay_buffer_frame_sink_close(struct sc_frame_sink *sink) {
struct sc_delay_buffer *db = DOWNCAST(sink); struct sc_delay_buffer *db = DOWNCAST(sink);
sc_mutex_lock(&db->b.mutex); sc_mutex_lock(&db->mutex);
db->b.stopped = true; db->stopped = true;
sc_cond_signal(&db->b.queue_cond); sc_cond_signal(&db->queue_cond);
sc_cond_signal(&db->b.wait_cond); sc_cond_signal(&db->wait_cond);
sc_mutex_unlock(&db->b.mutex); sc_mutex_unlock(&db->mutex);
sc_thread_join(&db->b.thread, NULL); sc_thread_join(&db->thread, NULL);
sc_frame_source_sinks_close(&db->frame_source); sc_frame_source_sinks_close(&db->frame_source);
sc_cond_destroy(&db->b.wait_cond); sc_cond_destroy(&db->wait_cond);
sc_cond_destroy(&db->b.queue_cond); sc_cond_destroy(&db->queue_cond);
sc_mutex_destroy(&db->b.mutex); sc_mutex_destroy(&db->mutex);
} }
static bool static bool
@ -183,19 +183,19 @@ sc_delay_buffer_frame_sink_push(struct sc_frame_sink *sink,
const AVFrame *frame) { const AVFrame *frame) {
struct sc_delay_buffer *db = DOWNCAST(sink); struct sc_delay_buffer *db = DOWNCAST(sink);
sc_mutex_lock(&db->b.mutex); sc_mutex_lock(&db->mutex);
if (db->b.stopped) { if (db->stopped) {
sc_mutex_unlock(&db->b.mutex); sc_mutex_unlock(&db->mutex);
return false; return false;
} }
sc_tick pts = SC_TICK_FROM_US(frame->pts); sc_tick pts = SC_TICK_FROM_US(frame->pts);
sc_clock_update(&db->b.clock, sc_tick_now(), pts); sc_clock_update(&db->clock, sc_tick_now(), pts);
sc_cond_signal(&db->b.wait_cond); sc_cond_signal(&db->wait_cond);
if (db->b.clock.count == 1) { if (db->clock.count == 1) {
sc_mutex_unlock(&db->b.mutex); sc_mutex_unlock(&db->mutex);
// First frame, push it immediately, for two reasons: // First frame, push it immediately, for two reasons:
// - not to delay the opening of the scrcpy window // - not to delay the opening of the scrcpy window
// - the buffering estimation needs at least two clock points, so it // - the buffering estimation needs at least two clock points, so it
@ -206,7 +206,7 @@ sc_delay_buffer_frame_sink_push(struct sc_frame_sink *sink,
struct sc_delayed_frame dframe; struct sc_delayed_frame dframe;
bool ok = sc_delayed_frame_init(&dframe, frame); bool ok = sc_delayed_frame_init(&dframe, frame);
if (!ok) { if (!ok) {
sc_mutex_unlock(&db->b.mutex); sc_mutex_unlock(&db->mutex);
return false; return false;
} }
@ -214,16 +214,16 @@ sc_delay_buffer_frame_sink_push(struct sc_frame_sink *sink,
dframe.push_date = sc_tick_now(); dframe.push_date = sc_tick_now();
#endif #endif
ok = sc_vecdeque_push(&db->b.queue, dframe); ok = sc_vecdeque_push(&db->queue, dframe);
if (!ok) { if (!ok) {
sc_mutex_unlock(&db->b.mutex); sc_mutex_unlock(&db->mutex);
LOG_OOM(); LOG_OOM();
return false; return false;
} }
sc_cond_signal(&db->b.queue_cond); sc_cond_signal(&db->queue_cond);
sc_mutex_unlock(&db->b.mutex); sc_mutex_unlock(&db->mutex);
return true; return true;
} }

View file

@ -30,7 +30,6 @@ struct sc_delay_buffer {
sc_tick delay; sc_tick delay;
struct {
sc_thread thread; sc_thread thread;
sc_mutex mutex; sc_mutex mutex;
sc_cond queue_cond; sc_cond queue_cond;
@ -39,7 +38,6 @@ struct sc_delay_buffer {
struct sc_clock clock; struct sc_clock clock;
struct sc_delayed_frame_queue queue; struct sc_delayed_frame_queue queue;
bool stopped; bool stopped;
} b; // buffering
}; };
struct sc_delay_buffer_callbacks { struct sc_delay_buffer_callbacks {