SDL2: rewritten to C

This commit is contained in:
Martin Pulec
2023-03-13 10:19:26 +01:00
parent 5b0eb5b43d
commit 2bf5afe521

View File

@@ -1,5 +1,5 @@
/**
* @file video_display/sdl2.cpp
* @file video_display/sdl2.c
* @author Lukas Hejtmanek <xhejtman@ics.muni.cz>
* @author Milos Liska <xliska@fi.muni.cz>
* @author Martin Pulec <pulec@cesnet.cz>
@@ -57,6 +57,7 @@
#include "messaging.h"
#include "module.h"
#include "utils/color_out.h"
#include "utils/list.h"
#include "video_display.h"
#include "video.h"
@@ -71,32 +72,23 @@
#include <SDL.h>
#endif
#include <algorithm>
#include <array>
#include <cassert>
#include <condition_variable>
#include <cstdint>
#include <mutex>
#include <queue>
#include <string>
#include <unordered_map>
#include <utility> // pair
#define SDL2_DEINTERLACE_IMPOSSIBLE_MSG_ID 0x327058e5
#define MAGIC_SDL2 0x3cc234a1
#define BUFFER_COUNT 2
#define MOD_NAME "[SDL] "
using namespace std;
struct state_sdl2;
static void show_help(void);
static void display_frame(struct state_sdl2 *s, struct video_frame *frame);
static struct video_frame *display_sdl2_getf(void *state);
static void display_sdl2_new_message(struct module *);
static void display_sdl2_new_message(struct module *mod);
static int display_sdl2_reconfigure(void *state, struct video_desc desc);
static int display_sdl2_reconfigure_real(void *state, struct video_desc desc);
static void loadSplashscreen(struct state_sdl2 *s);
enum deint { DEINT_OFF, DEINT_ON, DEINT_FORCE };
struct state_sdl2 {
struct module mod;
@@ -106,61 +98,50 @@ struct state_sdl2 {
Uint32 sdl_user_new_message_event;
Uint32 sdl_user_reconfigure_event;
int display_idx{0};
int x{SDL_WINDOWPOS_UNDEFINED},
y{SDL_WINDOWPOS_UNDEFINED};
int renderer_idx{-1};
SDL_Window *window{nullptr};
SDL_Renderer *renderer{nullptr};
int display_idx;
unsigned x;
unsigned y;
int renderer_idx;
SDL_Window *window;
SDL_Renderer *renderer;
bool fs{false};
enum class deint { off, on, force } deinterlace = deint::off;
bool keep_aspect{false};
bool vsync{true};
bool fixed_size{false};
int fixed_w{0}, fixed_h{0};
uint32_t window_flags{0}; ///< user requested flags
bool fs;
enum deint deinterlace;
bool keep_aspect;
bool vsync;
bool fixed_size;
unsigned fixed_w, fixed_h;
uint32_t window_flags; ///< user requested flags
mutex lock;
condition_variable frame_consumed_cv;
pthread_mutex_t lock;
pthread_cond_t frame_consumed_cv;
condition_variable reconfigured_cv;
pthread_cond_t reconfigured_cv;
int reconfiguration_status;
struct video_desc current_display_desc{};
struct video_frame *last_frame{nullptr};
struct video_desc current_display_desc;
struct video_frame *last_frame;
queue<struct video_frame *> free_frame_queue;
struct simple_linked_list *free_frame_queue;
state_sdl2(struct module *parent) {
module_init_default(&mod);
mod.priv_magic = MAGIC_SDL2;
mod.new_message = display_sdl2_new_message;
mod.cls = MODULE_CLASS_DATA;
module_register(&mod, parent);
sdl_user_new_frame_event = SDL_RegisterEvents(3);
assert(sdl_user_new_frame_event != (Uint32) -1);
sdl_user_new_message_event = sdl_user_new_frame_event + 1;
sdl_user_reconfigure_event = sdl_user_new_frame_event + 2;
}
~state_sdl2() {
module_done(&mod);
}
static const char *deint_to_string(deint val) {
switch (val) {
case deint::off: return "OFF";
case deint::on: return "ON";
case deint::force: return "FORCE";
}
return NULL;
}
};
static constexpr array display_sdl2_keybindings{
pair{'d', "toggle deinterlace"},
pair{'f', "toggle fullscreen"},
pair{'q', "quit"}
static const char *deint_to_string(enum deint val) {
switch (val) {
case DEINT_OFF: return "OFF";
case DEINT_ON: return "ON";
case DEINT_FORCE: return "FORCE";
}
return NULL;
}
static const struct {
char key;
const char *description;
} keybindings[] = {
{'d', "toggle deinterlace"},
{'f', "toggle fullscreen"},
{'q', "quit"},
};
#define SDL_CHECK(cmd) do { int ret = cmd; if (ret != 0) { log_msg(LOG_LEVEL_ERROR, MOD_NAME "Error (%s): %s\n", #cmd, SDL_GetError());} } while(0)
@@ -172,7 +153,7 @@ static void display_frame(struct state_sdl2 *s, struct video_frame *frame)
}
SDL_Texture *texture = (SDL_Texture *) frame->callbacks.dispose_udata;
if (s->deinterlace == state_sdl2::deint::force || (s->deinterlace == state_sdl2::deint::on && frame->interlacing == INTERLACED_MERGED)) {
if (s->deinterlace == DEINT_FORCE || (s->deinterlace == DEINT_ON && frame->interlacing == INTERLACED_MERGED)) {
size_t pitch = vc_get_linesize(frame->tiles[0].width, frame->color_spec);
if (!vc_deinterlace_ex(frame->color_spec, (unsigned char *) frame->tiles[0].data, pitch, (unsigned char *) frame->tiles[0].data, pitch, frame->tiles[0].height)) {
log_msg_once(LOG_LEVEL_ERROR, SDL2_DEINTERLACE_IMPOSSIBLE_MSG_ID, MOD_NAME "Cannot deinterlace, unsupported pixel format '%s'!\n", get_codec_name(frame->color_spec));
@@ -192,10 +173,10 @@ static void display_frame(struct state_sdl2 *s, struct video_frame *frame)
return; // we are only redrawing on window resize
}
std::unique_lock<std::mutex> lk(s->lock);
s->free_frame_queue.push(frame);
lk.unlock();
s->frame_consumed_cv.notify_one();
pthread_mutex_lock(&s->lock);
simple_linked_list_append(s->free_frame_queue, frame);
pthread_mutex_unlock(&s->lock);
pthread_cond_signal(&s->frame_consumed_cv);
s->last_frame = frame;
}
@@ -244,9 +225,8 @@ static bool display_sdl2_process_key(struct state_sdl2 *s, int64_t key)
{
switch (key) {
case 'd':
s->deinterlace = s->deinterlace == state_sdl2::deint::off ? state_sdl2::deint::on : state_sdl2::deint::off;
log_msg(LOG_LEVEL_INFO, "Deinterlacing: %s\n",
state_sdl2::deint_to_string(s->deinterlace));
s->deinterlace = s->deinterlace == DEINT_OFF ? DEINT_ON : DEINT_OFF;
log_msg(LOG_LEVEL_INFO, "Deinterlacing: %s\n", deint_to_string(s->deinterlace));
return true;
case 'f':
s->fs = !s->fs;
@@ -273,11 +253,11 @@ static void display_sdl2_run(void *arg)
continue;
}
if (sdl_event.type == s->sdl_user_reconfigure_event) {
unique_lock<mutex> lk(s->lock);
pthread_mutex_lock(&s->lock);
struct video_desc desc = *(struct video_desc *) sdl_event.user.data1;
s->reconfiguration_status = display_sdl2_reconfigure_real(s, desc);
lk.unlock();
s->reconfigured_cv.notify_one();
pthread_mutex_unlock(&s->lock);
pthread_cond_signal(&s->reconfigured_cv);
} else if (sdl_event.type == s->sdl_user_new_frame_event) {
if (sdl_event.user.data1 != NULL) {
@@ -342,48 +322,48 @@ static void display_sdl2_run(void *arg)
static void sdl2_print_displays() {
for (int i = 0; i < SDL_GetNumVideoDisplays(); ++i) {
if (i > 0) {
cout << ", ";
printf(", ");
}
const char *dname = SDL_GetDisplayName(i);
if (dname == nullptr) {
if (dname == NULL) {
dname = SDL_GetError();
}
col() << SBOLD(i) << " - " << dname;
color_printf(TBOLD("%d") " - %s", i, dname);
}
cout << "\n";
printf("\n");
}
static void show_help(void)
{
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
printf("SDL options:\n");
col() << SBOLD(SRED("\t-d sdl") << "[[:fs|:d|:display=<didx>|:driver=<drv>|:novsync|:renderer=<ridx>|:nodecorate|:fixed_size[=WxH]|:window_flags=<f>|:pos=<x>,<y>|:keep-aspect]*|:help]") << "\n";
color_printf(TBOLD(TRED("\t-d sdl") "[[:fs|:d|:display=<didx>|:driver=<drv>|:novsync|:renderer=<ridx>|:nodecorate|:fixed_size[=WxH]|:window_flags=<f>|:pos=<x>,<y>|:keep-aspect]*|:help]") "\n");
printf("\twhere:\n");
col() << SBOLD("\t\td[force]") << " - deinterlace (force even for progresive video)\n";
col() << SBOLD("\t\t fs") << " - fullscreen\n";
col() << SBOLD("\t\t <didx>") << " - display index, available indices: ";
color_printf(TBOLD("\t\td[force]") " - deinterlace (force even for progresive video)\n");
color_printf(TBOLD("\t\t fs") " - fullscreen\n");
color_printf(TBOLD("\t\t <didx>") " - display index, available indices: ");
sdl2_print_displays();
col() << SBOLD("\t\t <drv>") << " - one of following: ";
color_printf(TBOLD("\t\t <drv>") " - one of following: ");
for (int i = 0; i < SDL_GetNumVideoDrivers(); ++i) {
col() << (i == 0 ? "" : ", ") << SBOLD(SDL_GetVideoDriver(i));
color_printf("%s" TBOLD("%s"), (i == 0 ? "" : ", "), SDL_GetVideoDriver(i));
}
col() << "\n";
col() << SBOLD("\t keep-aspect") << " - keep window aspect ratio respecive to the video\n";
col() << SBOLD("\t novsync") << " - disable sync on VBlank\n";
col() << SBOLD("\t nodecorate") << " - disable window border\n";
col() << SBOLD("\tfixed_size[=WxH]") << " - use fixed sized window\n";
col() << SBOLD("\t window_flags") << " - flags to be passed to SDL_CreateWindow (use prefix 0x for hex)\n";
col() << SBOLD("\t\t <ridx>") << " - renderer index: ";
color_printf("\n");
color_printf(TBOLD("\t keep-aspect") " - keep window aspect ratio respecive to the video\n");
color_printf(TBOLD("\t novsync") " - disable sync on VBlank\n");
color_printf(TBOLD("\t nodecorate") " - disable window border\n");
color_printf(TBOLD("\tfixed_size[=WxH]") " - use fixed sized window\n");
color_printf(TBOLD("\t window_flags") " - flags to be passed to SDL_CreateWindow (use prefix 0x for hex)\n");
color_printf(TBOLD("\t\t <ridx>") " - renderer index: ");
for (int i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
SDL_RendererInfo renderer_info;
if (SDL_GetRenderDriverInfo(i, &renderer_info) == 0) {
col() << (i == 0 ? "" : ", ") << SBOLD(i) << " - " << SBOLD(renderer_info.name);
color_printf("%s" TBOLD("%d") " - " TBOLD("%s"), (i == 0 ? "" : ", "), i, renderer_info.name);
}
}
printf("\n");
cout << "\n\tKeyboard shortcuts:\n";
for (auto const &i : display_sdl2_keybindings) {
col() << SBOLD("\t\t'" << i.first) << "'\t - " << i.second << "\n";
printf("\n\tKeyboard shortcuts:\n");
for (unsigned int i = 0; i < sizeof keybindings / sizeof keybindings[0]; ++i) {
color_printf("\t\t" TBOLD("'%c'") "\t - %s\n", keybindings[i].key, keybindings[i].description);
}
SDL_Quit();
}
@@ -392,11 +372,11 @@ static int display_sdl2_reconfigure(void *state, struct video_desc desc)
{
struct state_sdl2 *s = (struct state_sdl2 *) state;
if (desc.interlacing == INTERLACED_MERGED && s->deinterlace == state_sdl2::deint::off) {
LOG(LOG_LEVEL_WARNING) << MOD_NAME "Receiving interlaced video but deinterlacing is off - suggesting toggling it on (press 'd' or pass cmdline option)\n";
if (desc.interlacing == INTERLACED_MERGED && s->deinterlace == DEINT_OFF) {
log_msg(LOG_LEVEL_WARNING, MOD_NAME "Receiving interlaced video but deinterlacing is off - suggesting toggling it on (press 'd' or pass cmdline option)\n");
}
unique_lock<mutex> lk(s->lock);
pthread_mutex_lock(&s->lock);
SDL_Event event;
event.type = s->sdl_user_reconfigure_event;
@@ -404,13 +384,18 @@ static int display_sdl2_reconfigure(void *state, struct video_desc desc)
SDL_PushEvent(&event);
s->reconfiguration_status = -1;
s->reconfigured_cv.wait(lk, [s]{return s->reconfiguration_status >= 0;});
while (s->reconfiguration_status == -1) {
pthread_cond_wait(&s->reconfigured_cv, &s->lock);
}
pthread_mutex_unlock(&s->lock);
return s->reconfiguration_status;
}
struct ug_to_sdl_pf { codec_t first; uint32_t second; };
static const ug_to_sdl_pf pf_mapping[] = {
static const struct {
codec_t first;
uint32_t second;
} pf_mapping[] = {
{ I420, SDL_PIXELFORMAT_IYUV },
{ UYVY, SDL_PIXELFORMAT_UYVY },
{ YUYV, SDL_PIXELFORMAT_YUY2 },
@@ -428,36 +413,35 @@ static uint32_t get_ug_to_sdl_format(codec_t ug_codec) {
return SDL_PIXELFORMAT_ARGB2101010;
}
const auto *it = find_if(begin(pf_mapping), end(pf_mapping), [ug_codec](const ug_to_sdl_pf &u) { return u.first == ug_codec; });
if (it == end(pf_mapping)) {
LOG(LOG_LEVEL_ERROR) << MOD_NAME << "Wrong codec: " << get_codec_name(ug_codec) << "\n";
return SDL_PIXELFORMAT_UNKNOWN;
for (unsigned int i = 0; i < sizeof pf_mapping / sizeof pf_mapping[0]; ++i) {
if (pf_mapping[i].first == ug_codec) {
return pf_mapping[i].second;
}
}
return it->second;
log_msg(LOG_LEVEL_ERROR, MOD_NAME "Wrong codec: %s\n", get_codec_name(ug_codec));
return SDL_PIXELFORMAT_UNKNOWN;
}
ADD_TO_PARAM("sdl2-r10k",
"* sdl2-r10k\n"
" Enable 10-bit RGB support for SDL2 (EXPERIMENTAL)\n");
static auto get_supported_pfs() {
vector<codec_t> codecs;
codecs.reserve(sizeof pf_mapping / sizeof pf_mapping[0]);
static int get_supported_pfs(codec_t *codecs) {
int count = 0;
for (auto const &item : pf_mapping) {
codecs.push_back(item.first);
for (unsigned int i = 0; i < sizeof pf_mapping / sizeof pf_mapping[0]; ++i) {
codecs[count++] = pf_mapping[i].first;
}
if (get_commandline_param("sdl2-r10k") != nullptr) {
codecs.push_back(R10k);
if (get_commandline_param("sdl2-r10k") != NULL) {
codecs[count++] = R10k;
}
return codecs;
return count;
}
static void cleanup_frames(struct state_sdl2 *s) {
s->last_frame = nullptr;
while (s->free_frame_queue.size() > 0) {
struct video_frame *buffer = s->free_frame_queue.front();
s->free_frame_queue.pop();
s->last_frame = NULL;
struct video_frame *buffer = NULL;
while ((buffer = simple_linked_list_pop(s->free_frame_queue)) != NULL) {
SDL_Texture *texture = (SDL_Texture *) buffer->callbacks.dispose_udata;
SDL_DestroyTexture(texture);
vf_free(buffer);
@@ -476,7 +460,7 @@ static bool recreate_textures(struct state_sdl2 *s, struct video_desc desc) {
struct video_frame *f = vf_alloc_desc(desc);
f->callbacks.dispose_udata = (void *) texture;
SDL_LockTexture(texture, NULL, (void **) &f->tiles[0].data, &s->texture_pitch);
s->free_frame_queue.push(f);
simple_linked_list_append(s->free_frame_queue, f);
}
return true;
@@ -556,7 +540,11 @@ static void *display_sdl2_init(struct module *parent, const char *fmt, unsigned
return NULL;
}
const char *driver = NULL;
struct state_sdl2 *s = new state_sdl2{parent};
struct state_sdl2 *s = calloc(1, sizeof *s);
s->x = s->y = SDL_WINDOWPOS_UNDEFINED;
s->renderer_idx = -1;
s->vsync = true;
if (fmt == NULL) {
fmt = "";
@@ -567,7 +555,7 @@ static void *display_sdl2_init(struct module *parent, const char *fmt, unsigned
while((tok = strtok_r(tmp, ":", &save_ptr)))
{
if (strcmp(tok, "d") == 0 || strcmp(tok, "dforce") == 0) {
s->deinterlace = strcmp(tok, "d") == 0 ? state_sdl2::deint::on : state_sdl2::deint::off;
s->deinterlace = strcmp(tok, "d") == 0 ? DEINT_ON : DEINT_OFF;
} else if (strncmp(tok, "display=", strlen("display=")) == 0) {
s->display_idx = atoi(tok + strlen("display="));
} else if (strncmp(tok, "driver=", strlen("driver=")) == 0) {
@@ -576,7 +564,7 @@ static void *display_sdl2_init(struct module *parent, const char *fmt, unsigned
s->fs = true;
} else if (strcmp(tok, "help") == 0) {
show_help();
delete s;
free(s);
return INIT_NOERR;
} else if (strcmp(tok, "novsync") == 0) {
s->vsync = false;
@@ -597,15 +585,15 @@ static void *display_sdl2_init(struct module *parent, const char *fmt, unsigned
int f;
if (sscanf(tok + strlen("window_flags="), "%i", &f) != 1) {
log_msg(LOG_LEVEL_ERROR, "Wrong window_flags: %s\n", tok);
delete s;
free(s);
return NULL;
}
s->window_flags |= f;
} else if (strstr(tok, "pos=") == tok) {
tok += strlen("pos=");
if (strchr(tok, ',') == nullptr) {
if (strchr(tok, ',') == NULL) {
log_msg(LOG_LEVEL_ERROR, "[SDL] position: %s\n", tok);
delete s;
free(s);
return NULL;
}
s->x = atoi(tok);
@@ -614,7 +602,7 @@ static void *display_sdl2_init(struct module *parent, const char *fmt, unsigned
s->renderer_idx = atoi(tok + strlen("renderer="));
} else {
log_msg(LOG_LEVEL_ERROR, "[SDL] Wrong option: %s\n", tok);
delete s;
free(s);
return NULL;
}
tmp = NULL;
@@ -623,13 +611,13 @@ static void *display_sdl2_init(struct module *parent, const char *fmt, unsigned
int ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
if (ret < 0) {
log_msg(LOG_LEVEL_ERROR, "Unable to initialize SDL2: %s\n", SDL_GetError());
delete s;
free(s);
return NULL;
}
ret = SDL_VideoInit(driver);
if (ret < 0) {
log_msg(LOG_LEVEL_ERROR, "Unable to initialize SDL2 video: %s\n", SDL_GetError());
delete s;
free(s);
return NULL;
}
log_msg(LOG_LEVEL_NOTICE, "[SDL] Using driver: %s\n", SDL_GetCurrentVideoDriver());
@@ -637,11 +625,30 @@ static void *display_sdl2_init(struct module *parent, const char *fmt, unsigned
SDL_ShowCursor(SDL_DISABLE);
SDL_DisableScreenSaver();
for (auto const &i : display_sdl2_keybindings) {
if (i.first == 'q') { // don't report 'q' to avoid accidental close - user can use Ctrl-c there
module_init_default(&s->mod);
s->mod.priv_magic = MAGIC_SDL2;
s->mod.new_message = display_sdl2_new_message;
s->mod.cls = MODULE_CLASS_DATA;
module_register(&s->mod, parent);
pthread_mutex_init(&s->lock, NULL);
pthread_cond_init(&s->frame_consumed_cv, NULL);
pthread_cond_init(&s->reconfigured_cv , NULL);
s->sdl_user_new_frame_event = SDL_RegisterEvents(3);
assert(s->sdl_user_new_frame_event != (Uint32) -1);
s->sdl_user_new_message_event = s->sdl_user_new_frame_event + 1;
s->sdl_user_reconfigure_event = s->sdl_user_new_frame_event + 2;
s->free_frame_queue = simple_linked_list_init();
for (unsigned int i = 0; i < sizeof keybindings / sizeof keybindings[0]; ++i) {
if (keybindings[i].key == 'q') { // don't report 'q' to avoid accidental close - user can use Ctrl-c there
continue;
}
keycontrol_register_key(&s->mod, i.first, to_string(static_cast<int>(i.first)).c_str(), i.second);
char key_str[128];
snprintf(key_str, sizeof key_str, "%d", keybindings[i].key);
keycontrol_register_key(&s->mod, keybindings[i].key, key_str, keybindings[i].description);
}
log_msg(LOG_LEVEL_NOTICE, "SDL2 initialized successfully.\n");
@@ -671,7 +678,15 @@ static void display_sdl2_done(void *state)
SDL_QuitSubSystem(SDL_INIT_EVENTS);
SDL_Quit();
delete s;
simple_linked_list_destroy(s->free_frame_queue);
pthread_mutex_destroy(&s->lock);
pthread_cond_destroy(&s->frame_consumed_cv);
pthread_cond_destroy(&s->reconfigured_cv);
module_done(&s->mod);
free(s);
}
static struct video_frame *display_sdl2_getf(void *state)
@@ -679,10 +694,12 @@ static struct video_frame *display_sdl2_getf(void *state)
struct state_sdl2 *s = (struct state_sdl2 *)state;
assert(s->mod.priv_magic == MAGIC_SDL2);
unique_lock<mutex> lk(s->lock);
s->frame_consumed_cv.wait(lk, [s]{return s->free_frame_queue.size() > 0;});
struct video_frame *buffer = s->free_frame_queue.front();
s->free_frame_queue.pop();
pthread_mutex_lock(&s->lock);
while (simple_linked_list_size(s->free_frame_queue) == 0) {
pthread_cond_wait(&s->frame_consumed_cv, &s->lock);
}
struct video_frame *buffer = simple_linked_list_pop(s->free_frame_queue);
pthread_mutex_unlock(&s->lock);
return buffer;
}
@@ -693,26 +710,33 @@ static int display_sdl2_putf(void *state, struct video_frame *frame, long long t
assert(s->mod.priv_magic == MAGIC_SDL2);
std::unique_lock<std::mutex> lk(s->lock);
pthread_mutex_lock(&s->lock);
if (timeout_ns == PUTF_DISCARD) {
assert(frame != nullptr);
s->free_frame_queue.push(frame);
assert(frame != NULL);
simple_linked_list_append(s->free_frame_queue, frame);
pthread_mutex_unlock(&s->lock);
return 0;
}
if (frame != NULL && timeout_ns > 0) {
if (timeout_ns == PUTF_BLOCKING) {
s->frame_consumed_cv.wait(lk, [s]{return s->free_frame_queue.size() > 0;});
} else {
s->frame_consumed_cv.wait_for(lk, timeout_ns * 1ns, [s]{return s->free_frame_queue.size() > 0;});
int rc = 0;
while (rc == 0 && simple_linked_list_size(s->free_frame_queue) != 0) {
if (timeout_ns == PUTF_BLOCKING) {
rc = pthread_cond_wait(&s->frame_consumed_cv, &s->lock);
} else {
time_ns_t tout = get_time_in_ns() + timeout_ns;
struct timespec abstime = { .tv_sec = tout / NS_IN_SEC, .tv_nsec = tout % NS_IN_SEC };
rc = pthread_cond_timedwait(&s->frame_consumed_cv, &s->lock, &abstime);
}
}
}
if (frame != NULL && s->free_frame_queue.size() == 0) {
s->free_frame_queue.push(frame);
LOG(LOG_LEVEL_INFO) << MOD_NAME << "1 frame(s) dropped!\n";
if (frame != NULL && simple_linked_list_size(s->free_frame_queue) == 0) {
simple_linked_list_append(s->free_frame_queue, frame);
log_msg(LOG_LEVEL_INFO, MOD_NAME "1 frame(s) dropped!\n");
pthread_mutex_unlock(&s->lock);
return 1;
}
lk.unlock();
pthread_mutex_unlock(&s->lock);
SDL_Event event;
event.type = s->sdl_user_new_frame_event;
event.user.data1 = frame;
@@ -724,13 +748,13 @@ static int display_sdl2_putf(void *state, struct video_frame *frame, long long t
static int display_sdl2_get_property(void *state, int property, void *val, size_t *len)
{
struct state_sdl2 *s = (struct state_sdl2 *) state;
auto codecs = get_supported_pfs();
size_t codecs_len = codecs.size() * sizeof(codec_t);
codec_t codecs[VIDEO_CODEC_COUNT];
size_t codecs_len = get_supported_pfs(codecs) * sizeof(codec_t);
switch (property) {
case DISPLAY_PROPERTY_CODECS:
if (codecs_len <= *len) {
memcpy(val, codecs.data(), codecs_len);
memcpy(val, codecs, codecs_len);
*len = codecs_len;
} else {
return FALSE;
@@ -755,16 +779,6 @@ static void display_sdl2_new_message(struct module *mod)
SDL_PushEvent(&event);
}
static void display_sdl2_put_audio_frame([[maybe_unused]] void *state, [[maybe_unused]] const struct audio_frame *frame)
{
}
static int display_sdl2_reconfigure_audio([[maybe_unused]] void *state, [[maybe_unused]] int quant_samples,
[[maybe_unused]] int channels, [[maybe_unused]] int sample_rate)
{
return FALSE;
}
static void display_sdl2_probe(struct device_info **available_cards, int *count, void (**deleter)(void *)) {
UNUSED(deleter);
*count = 1;
@@ -783,8 +797,8 @@ static const struct video_display_info display_sdl2_info = {
display_sdl2_putf,
display_sdl2_reconfigure,
display_sdl2_get_property,
display_sdl2_put_audio_frame,
display_sdl2_reconfigure_audio,
NULL,
NULL,
DISPLAY_NEEDS_MAINLOOP,
MOD_NAME,
};