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:
parent
1230149fdd
commit
48a537d45c
2 changed files with 54 additions and 56 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,16 +30,14 @@ 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;
|
sc_cond wait_cond;
|
||||||
sc_cond wait_cond;
|
|
||||||
|
|
||||||
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 {
|
||||||
|
|
Loading…
Reference in a new issue