Use a callback to notify a new frame
Make the decoder independant of the SDL even mechanism, by registering a callback on the video_buffer.
This commit is contained in:
parent
72df2c23f9
commit
b1c7c71160
@ -19,13 +19,7 @@ push_frame(struct decoder *decoder) {
|
|||||||
&previous_frame_skipped);
|
&previous_frame_skipped);
|
||||||
if (previous_frame_skipped) {
|
if (previous_frame_skipped) {
|
||||||
fps_counter_add_skipped_frame(decoder->fps_counter);
|
fps_counter_add_skipped_frame(decoder->fps_counter);
|
||||||
// the previous EVENT_NEW_FRAME will consume this frame
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
static SDL_Event new_frame_event = {
|
|
||||||
.type = EVENT_NEW_FRAME,
|
|
||||||
};
|
|
||||||
SDL_PushEvent(&new_frame_event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -267,6 +267,19 @@ av_log_callback(void *avcl, int level, const char *fmt, va_list vl) {
|
|||||||
free(local_fmt);
|
free(local_fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
video_buffer_on_frame_available(struct video_buffer *vb, void *userdata) {
|
||||||
|
(void) vb;
|
||||||
|
(void) userdata;
|
||||||
|
|
||||||
|
static SDL_Event new_frame_event = {
|
||||||
|
.type = EVENT_NEW_FRAME,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Post the event on the UI thread
|
||||||
|
SDL_PushEvent(&new_frame_event);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
scrcpy(const struct scrcpy_options *options) {
|
scrcpy(const struct scrcpy_options *options) {
|
||||||
if (!server_init(&server)) {
|
if (!server_init(&server)) {
|
||||||
@ -333,7 +346,12 @@ scrcpy(const struct scrcpy_options *options) {
|
|||||||
}
|
}
|
||||||
fps_counter_initialized = true;
|
fps_counter_initialized = true;
|
||||||
|
|
||||||
if (!video_buffer_init(&video_buffer, options->render_expired_frames)) {
|
static const struct video_buffer_callbacks video_buffer_cbs = {
|
||||||
|
.on_frame_available = video_buffer_on_frame_available,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!video_buffer_init(&video_buffer, options->render_expired_frames,
|
||||||
|
&video_buffer_cbs, NULL)) {
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
video_buffer_initialized = true;
|
video_buffer_initialized = true;
|
||||||
|
@ -7,7 +7,9 @@
|
|||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
|
||||||
bool
|
bool
|
||||||
video_buffer_init(struct video_buffer *vb, bool wait_consumer) {
|
video_buffer_init(struct video_buffer *vb, bool wait_consumer,
|
||||||
|
const struct video_buffer_callbacks *cbs,
|
||||||
|
void *cbs_userdata) {
|
||||||
vb->producer_frame = av_frame_alloc();
|
vb->producer_frame = av_frame_alloc();
|
||||||
if (!vb->producer_frame) {
|
if (!vb->producer_frame) {
|
||||||
goto error_0;
|
goto error_0;
|
||||||
@ -43,6 +45,11 @@ video_buffer_init(struct video_buffer *vb, bool wait_consumer) {
|
|||||||
// there is initially no frame, so consider it has already been consumed
|
// there is initially no frame, so consider it has already been consumed
|
||||||
vb->pending_frame_consumed = true;
|
vb->pending_frame_consumed = true;
|
||||||
|
|
||||||
|
assert(cbs);
|
||||||
|
assert(cbs->on_frame_available);
|
||||||
|
vb->cbs = cbs;
|
||||||
|
vb->cbs_userdata = cbs_userdata;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
error_3:
|
error_3:
|
||||||
@ -95,10 +102,17 @@ video_buffer_producer_offer_frame(struct video_buffer *vb,
|
|||||||
|
|
||||||
video_buffer_swap_producer_frame(vb);
|
video_buffer_swap_producer_frame(vb);
|
||||||
|
|
||||||
*previous_frame_skipped = !vb->pending_frame_consumed;
|
bool skipped = !vb->pending_frame_consumed;
|
||||||
|
*previous_frame_skipped = skipped;
|
||||||
vb->pending_frame_consumed = false;
|
vb->pending_frame_consumed = false;
|
||||||
|
|
||||||
sc_mutex_unlock(&vb->mutex);
|
sc_mutex_unlock(&vb->mutex);
|
||||||
|
|
||||||
|
if (!skipped) {
|
||||||
|
// If skipped, then the previous call will consume this frame, the
|
||||||
|
// callback must not be called
|
||||||
|
vb->cbs->on_frame_available(vb, vb->cbs_userdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const AVFrame *
|
const AVFrame *
|
||||||
|
@ -39,10 +39,20 @@ struct video_buffer {
|
|||||||
|
|
||||||
sc_cond pending_frame_consumed_cond;
|
sc_cond pending_frame_consumed_cond;
|
||||||
bool pending_frame_consumed;
|
bool pending_frame_consumed;
|
||||||
|
|
||||||
|
const struct video_buffer_callbacks *cbs;
|
||||||
|
void *cbs_userdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct video_buffer_callbacks {
|
||||||
|
// Called when a new frame can be consumed by
|
||||||
|
// video_buffer_consumer_take_frame(vb)
|
||||||
|
void (*on_frame_available)(struct video_buffer *vb, void *userdata);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
video_buffer_init(struct video_buffer *vb, bool wait_consumer);
|
video_buffer_init(struct video_buffer *vb, bool wait_consumer,
|
||||||
|
const struct video_buffer_callbacks *cbs, void *cbs_userdata);
|
||||||
|
|
||||||
void
|
void
|
||||||
video_buffer_destroy(struct video_buffer *vb);
|
video_buffer_destroy(struct video_buffer *vb);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user