UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
sdl.cpp File Reference
#include "config.h"
#include "config_unix.h"
#include "config_win32.h"
#include "host.h"
#include "debug.h"
#include "keyboard_control.h"
#include "lib_common.h"
#include "messaging.h"
#include "module.h"
#include "video_display.h"
#include "tv.h"
#include "audio/types.h"
#include "audio/utils.h"
#include "utils/ring_buffer.h"
#include "video.h"
#include <math.h>
#include <SDL/SDL.h>
#include <SDL/SDL_syswm.h>
#include <condition_variable>
#include <mutex>
#include <queue>
Include dependency graph for sdl.cpp:

Go to the source code of this file.

Classes

struct  state_sdl
 

Macros

#define FOURCC_UYVY   0x59565955
 
#define FOURCC_YUYV   0x32595559
 
#define MAGIC_SDL   0x155734ae
 
#define MAX_BUFFER_SIZE   1
 
#define SDL_USER_NEWFRAME   SDL_USEREVENT
 

Functions

static void cleanup_screen (struct state_sdl *s)
 
static void compute_dst_rect (struct state_sdl *s, int vid_w, int vid_h, int window_w, int window_h, codec_t codec)
 
static void configure_audio (struct state_sdl *s)
 
static void display_frame (struct state_sdl *s, struct video_frame *frame)
 
static void display_sdl_done (void *state)
 
static bool display_sdl_get_property (void *state, int property, void *val, size_t *len)
 
static struct video_frame * display_sdl_getf (void *state)
 
static void * display_sdl_init (struct module *parent, const char *fmt, unsigned int flags)
 
static void display_sdl_probe (struct device_info **available_cards, int *count, void(**deleter)(void *))
 
static void display_sdl_put_audio_frame (void *state, const struct audio_frame *frame)
 
static bool display_sdl_putf (void *state, struct video_frame *frame, long long nonblock)
 
static bool display_sdl_reconfigure (void *state, struct video_desc desc)
 
static bool display_sdl_reconfigure_audio (void *state, int quant_samples, int channels, int sample_rate)
 
static bool display_sdl_reconfigure_real (void *state, struct video_desc desc)
 
static void display_sdl_run (void *arg)
 
static void loadSplashscreen (struct state_sdl *s)
 
 REGISTER_MODULE (sdl, &display_sdl_info, LIBRARY_CLASS_VIDEO_DISPLAY, VIDEO_DISPLAY_ABI_VERSION)
 
static void sdl_audio_callback (void *userdata, Uint8 *stream, int len)
 
static void show_help (void)
 
static bool update_size (struct state_sdl *s, int win_w, int win_h)
 

Variables

static const struct video_display_info display_sdl_info
 

Detailed Description

Macro Definition Documentation

◆ FOURCC_UYVY

#define FOURCC_UYVY   0x59565955

Definition at line 74 of file sdl.cpp.

Referenced by display_sdl_reconfigure_real().

◆ FOURCC_YUYV

#define FOURCC_YUYV   0x32595559

Definition at line 75 of file sdl.cpp.

Referenced by display_sdl_reconfigure_real().

◆ MAGIC_SDL

#define MAGIC_SDL   0x155734ae

Definition at line 73 of file sdl.cpp.

Referenced by display_sdl_done(), display_sdl_getf(), and display_sdl_putf().

◆ MAX_BUFFER_SIZE

#define MAX_BUFFER_SIZE   1

Definition at line 77 of file sdl.cpp.

Referenced by display_sdl_putf().

◆ SDL_USER_NEWFRAME

#define SDL_USER_NEWFRAME   SDL_USEREVENT

Definition at line 81 of file sdl.cpp.

Referenced by display_sdl_putf(), and display_sdl_run().

Function Documentation

◆ cleanup_screen()

static void cleanup_screen ( struct state_sdl * s)
static

Definition at line 381 of file sdl.cpp.

382{
384 if (s->yuv_image != NULL) {
385 SDL_FreeYUVOverlay(s->yuv_image);
386 s->yuv_image = NULL;
387 }
388 }
389 if (s->sdl_screen != NULL) {
390 SDL_FreeSurface(s->sdl_screen);
391 s->sdl_screen = NULL;
392 }
393}
SDL_Overlay * yuv_image
Definition sdl.cpp:89
struct video_desc current_display_desc
with those desc new data frames will be generated (getf)
Definition sdl.cpp:108
SDL_Surface * sdl_screen
Definition sdl.cpp:90
codec_t color_spec
Definition types.h:182
bool codec_is_a_rgb(codec_t codec)
Returns TRUE if specified pixelformat is some form of RGB (not YUV).

References codec_is_a_rgb(), video_desc::color_spec, state_sdl::current_display_desc, state_sdl::sdl_screen, and state_sdl::yuv_image.

Referenced by display_sdl_done().

Here is the call graph for this function:

◆ compute_dst_rect()

static void compute_dst_rect ( struct state_sdl * s,
int vid_w,
int vid_h,
int window_w,
int window_h,
codec_t codec )
static

Definition at line 158 of file sdl.cpp.

159{
160 s->dst_rect.x = 0;
161 s->dst_rect.y = 0;
162 s->dst_rect.w = vid_w;
163 s->dst_rect.h = vid_h;
164
165 if (codec_is_a_rgb(codec)) {
166 if (window_w > vid_w) {
167 s->dst_rect.x = ((int) window_w - vid_w) / 2;
168 } else if (window_w < vid_w) {
169 s->dst_rect.w = window_w;
170 }
171 if (window_h > vid_h) {
172 s->dst_rect.y = ((int) window_h - vid_h) / 2;
173 } else if (window_h < vid_h) {
174 s->dst_rect.h = window_h;
175 }
176 } else if (!codec_is_a_rgb(codec) && (vid_w != window_w || vid_h != window_h)) {
177 double frame_aspect = (double) vid_w / vid_h;
178 double screen_aspect = (double) window_w / window_h;
179 if(screen_aspect > frame_aspect) {
180 s->dst_rect.h = window_h;
181 s->dst_rect.w = window_h * frame_aspect;
182 s->dst_rect.x = ((int) window_w - s->dst_rect.w) / 2;
183 } else {
184 s->dst_rect.w = window_w;
185 s->dst_rect.h = window_w / frame_aspect;
186 s->dst_rect.y = ((int) window_h - s->dst_rect.h) / 2;
187 }
188 }
189
190 fprintf(stdout, "Setting SDL rect %dx%d - %d,%d.\n", s->dst_rect.w,
191 s->dst_rect.h, s->dst_rect.x, s->dst_rect.y);
192}
SDL_Rect dst_rect
Definition sdl.cpp:91

References codec_is_a_rgb(), and state_sdl::dst_rect.

Referenced by display_sdl_reconfigure_real(), and update_size().

Here is the call graph for this function:

◆ configure_audio()

static void configure_audio ( struct state_sdl * s)
static

Definition at line 664 of file sdl.cpp.

665{
666 s->audio_frame.data = NULL;
667
668 SDL_Init(SDL_INIT_AUDIO);
669
670 if(SDL_GetAudioStatus() != SDL_AUDIO_STOPPED) {
671 s->play_audio = FALSE;
672 fprintf(stderr, "[SDL] Audio init failed - driver is already used (testcard?)\n");
673 return;
674 }
675
676 s->audio_buffer = ring_buffer_init(1<<20);
677}
#define FALSE
struct ring_buffer * ring_buffer_init(int size)
char * data
Definition types.h:102
struct ring_buffer * audio_buffer
Definition sdl.cpp:101
struct audio_frame audio_frame
Definition sdl.cpp:102
bool play_audio
Definition sdl.cpp:103

References state_sdl::audio_buffer, state_sdl::audio_frame, audio_frame::data, FALSE, state_sdl::play_audio, and ring_buffer_init().

Referenced by display_sdl_init().

Here is the call graph for this function:

◆ display_frame()

static void display_frame ( struct state_sdl * s,
struct video_frame * frame )
static

Definition at line 219 of file sdl.cpp.

220{
221 struct timeval tv;
222
223 if (s->deinterlace) {
224 vc_deinterlace((unsigned char *) frame->tiles[0].data,
227 }
228
231 goto free_frame;
232 }
233 }
234
235 if (codec_is_a_rgb(frame->color_spec) && (s->sdl_screen->format->BitsPerPixel == 32 || s->sdl_screen->format->BitsPerPixel == 24)) {
236 codec_t dst_codec = s->sdl_screen->format->BitsPerPixel == 32 ? RGBA : RGB;
237 decoder_t decoder = get_decoder_from_to(frame->color_spec, dst_codec);
238 assert(decoder != nullptr);
239 SDL_LockSurface(s->sdl_screen);
240 size_t linesize = vc_get_linesize(frame->tiles[0].width, frame->color_spec);
241 size_t dst_linesize = vc_get_linesize(frame->tiles[0].width, dst_codec);
242 for (size_t i = 0; i < min<size_t>(frame->tiles[0].height, s->sdl_screen->h); ++i) {
243 decoder((unsigned char *) s->sdl_screen->pixels +
244 s->sdl_screen->pitch * (s->dst_rect.y + i) +
245 s->dst_rect.x *
246 s->sdl_screen->format->BytesPerPixel,
247 (unsigned char *) frame->tiles[0].data + i * linesize,
248 min<long>(dst_linesize,s->sdl_screen->pitch),
249 s->sdl_screen->format->Rshift,
250 s->sdl_screen->format->Gshift,
251 s->sdl_screen->format->Bshift);
252 }
253
254 SDL_UnlockSurface(s->sdl_screen);
255 SDL_Flip(s->sdl_screen);
256 } else if (codec_is_a_rgb(frame->color_spec)) {
257 int bpp = get_bpp(frame->color_spec);
258 size_t src_linesize = vc_get_linesize(frame->tiles[0].width, frame->color_spec);
259 SDL_LockSurface(s->sdl_screen);
260 for (size_t i = 0; i < min<size_t>(frame->tiles[0].height, s->sdl_screen->h); ++i) {
261 unsigned char *src = (unsigned char *) frame->tiles[0].data + i * src_linesize;
262 for (size_t j = 0; j < frame->tiles[0].width; j++) {
263 uint32_t rgba =
264 (src[0] >> s->sdl_screen->format->Rloss) << s->sdl_screen->format->Rshift |
265 (src[1] >> s->sdl_screen->format->Gloss) << s->sdl_screen->format->Gshift |
266 (src[2] >> s->sdl_screen->format->Bloss) << s->sdl_screen->format->Bshift;
267 memcpy((unsigned char *) s->sdl_screen->pixels +
268 s->sdl_screen->pitch * (s->dst_rect.y + i) +
269 (s->dst_rect.x + j) *
270 s->sdl_screen->format->BytesPerPixel,
271 &rgba,
272 s->sdl_screen->format->BytesPerPixel);
273 src += bpp;
274 }
275 }
276 SDL_UnlockSurface(s->sdl_screen);
277 SDL_Flip(s->sdl_screen);
278 } else {
279 SDL_LockYUVOverlay(s->yuv_image);
280 memcpy(*s->yuv_image->pixels, frame->tiles[0].data, frame->tiles[0].data_len);
281 SDL_UnlockYUVOverlay(s->yuv_image);
282 SDL_DisplayYUVOverlay(s->yuv_image, &s->dst_rect);
283 }
284
285free_frame:
286 s->lock.lock();
287 s->free_frame_queue.push(frame);
288 s->lock.unlock();
289
290 s->frames++;
291 gettimeofday(&tv, NULL);
292 double seconds = tv_diff(tv, s->tv);
293 if (seconds > 5) {
294 double fps = s->frames / seconds;
295 log_msg(LOG_LEVEL_INFO, "[SDL] %d frames in %g seconds = %g FPS\n",
296 s->frames, seconds, fps);
297 s->tv = tv;
298 s->frames = 0;
299 }
300}
struct video_frame * frame
struct video_desc video_desc_from_frame(const struct video_frame *frame)
Returns struct video_desc from video frame.
int vc_get_linesize(unsigned int width, codec_t codec)
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
decoder_t get_decoder_from_to(codec_t in, codec_t out)
decoder_func_t * decoder_t
Definition pixfmt_conv.h:96
static bool display_sdl_reconfigure_real(void *state, struct video_desc desc)
Definition sdl.cpp:403
mutex lock
Definition sdl.cpp:109
struct timeval tv
Definition sdl.cpp:86
bool deinterlace
Definition sdl.cpp:93
int frames
Definition sdl.cpp:87
queue< struct video_frame * > free_frame_queue
Definition sdl.cpp:106
unsigned int width
Definition types.h:280
char * data
Raw tile data. Pointer must be at least 4B aligned.
Definition types.h:287
unsigned int data_len
length of the data
Definition types.h:288
unsigned int height
Definition types.h:281
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
Definition types.h:345
codec_t color_spec
Definition types.h:306
double tv_diff(struct timeval curr_time, struct timeval prev_time)
Definition tv.c:97
codec_t
Definition types.h:65
@ RGB
RGB 8-bit (packed into 24-bit word)
Definition types.h:80
@ RGBA
RGBA 8-bit, big-endian.
Definition types.h:70
void vc_deinterlace(unsigned char *src, long src_linesize, int lines)
Deinterlaces framebuffer.
double get_bpp(codec_t codec)
bool video_desc_eq(struct video_desc a, struct video_desc b)
Compares two video descriptions.

References codec_is_a_rgb(), video_frame::color_spec, state_sdl::current_display_desc, tile::data, tile::data_len, state_sdl::deinterlace, display_sdl_reconfigure_real(), state_sdl::dst_rect, frame, state_sdl::frames, state_sdl::free_frame_queue, get_bpp(), get_decoder_from_to(), tile::height, state_sdl::lock, LOG_LEVEL_INFO, log_msg(), RGB, RGBA, state_sdl::sdl_screen, video_frame::tiles, state_sdl::tv, tv_diff(), vc_deinterlace(), vc_get_linesize(), video_desc_eq(), video_desc_from_frame(), tile::width, and state_sdl::yuv_image.

Referenced by display_put_frame(), and display_sdl_run().

Here is the call graph for this function:

◆ display_sdl_done()

static void display_sdl_done ( void * state)
static

Definition at line 559 of file sdl.cpp.

560{
561 struct state_sdl *s = (struct state_sdl *)state;
562
563 assert(s->magic == MAGIC_SDL);
564
566
567 /*FIXME: free all the stuff */
568 SDL_ShowCursor(SDL_ENABLE);
569
570 SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);
571 SDL_Quit();
572#ifdef __APPLE__
573 autorelease_pool_destroy(s->autorelease_pool);
574#endif
575
576 while (s->free_frame_queue.size() > 0) {
577 struct video_frame *buffer = s->free_frame_queue.front();
578 s->free_frame_queue.pop();
579 vf_free(buffer);
580 }
581
582 delete s;
583}
void ** state
void vf_free(struct video_frame *buf)
Frees video_frame structure.
static void cleanup_screen(struct state_sdl *s)
Definition sdl.cpp:381
#define MAGIC_SDL
Definition sdl.cpp:73
uint32_t magic
Definition sdl.cpp:84
Struct video_frame represents a video frame and contains video description.
Definition types.h:305

References cleanup_screen(), state_sdl::free_frame_queue, state_sdl::magic, MAGIC_SDL, state, and vf_free().

Here is the call graph for this function:

◆ display_sdl_get_property()

static bool display_sdl_get_property ( void * state,
int property,
void * val,
size_t * len )
static

Definition at line 634 of file sdl.cpp.

635{
636 UNUSED(state);
637 codec_t codecs[] = {UYVY, YUYV, RGBA, RGB};
638
639 switch (property) {
641 if(sizeof(codecs) <= *len) {
642 memcpy(val, codecs, sizeof(codecs));
643 } else {
644 return false;
645 }
646
647 *len = sizeof(codecs);
648 break;
649 default:
650 return false;
651 }
652 return true;
653}
#define UNUSED(x)
int void * val
int void size_t * len
int property
@ DISPLAY_PROPERTY_CODECS
list of natively supported codecs - codec_t[]
@ YUYV
YCbCr 422 8-bit - Y0 Cb Y1 Cr.
Definition types.h:72
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
Definition types.h:71
static struct @76 codecs[]

References codecs, DISPLAY_PROPERTY_CODECS, len, property, RGB, RGBA, state, UNUSED, UYVY, val, and YUYV.

◆ display_sdl_getf()

static struct video_frame * display_sdl_getf ( void * state)
static

Definition at line 585 of file sdl.cpp.

586{
587 struct state_sdl *s = (struct state_sdl *)state;
588 assert(s->magic == MAGIC_SDL);
589
590 lock_guard<mutex> lock(s->lock);
591
592 while (s->free_frame_queue.size() > 0) {
593 struct video_frame *buffer = s->free_frame_queue.front();
594 s->free_frame_queue.pop();
596 return buffer;
597 } else {
598 vf_free(buffer);
599 }
600 }
601
603}
struct video_frame * vf_alloc_desc_data(struct video_desc desc)
struct video_desc current_desc
Definition sdl.cpp:107

References state_sdl::current_desc, state_sdl::free_frame_queue, state_sdl::lock, state_sdl::magic, MAGIC_SDL, state, vf_alloc_desc_data(), vf_free(), video_desc_eq(), and video_desc_from_frame().

Here is the call graph for this function:

◆ display_sdl_init()

static void * display_sdl_init ( struct module * parent,
const char * fmt,
unsigned int flags )
static

Definition at line 450 of file sdl.cpp.

451{
452 struct state_sdl *s = new state_sdl(parent);
453 int ret;
454 const SDL_VideoInfo *video_info;
455
456 if (fmt != NULL) {
457 if (strcmp(fmt, "help") == 0) {
458 show_help();
459 delete s;
460 return INIT_NOERR;
461 }
462
463 char *tmp = strdup(fmt);
464 char *ptr = tmp;
465 char *tok;
466 char *save_ptr = NULL;
467
468 while((tok = strtok_r(ptr, ":", &save_ptr)))
469 {
470 if (strcmp(tok, "fs") == 0) {
471 s->fs = 1;
472 } else if (strcmp(tok, "d") == 0) {
473 s->deinterlace = 1;
474 } else if (strcmp(tok, "nodecorate") == 0) {
475 s->nodecorate = true;
476 } else if (strncmp(tok, "fixed_size", strlen("fixed_size")) == 0) {
477 s->fixed_size = true;
478 if (strncmp(tok, "fixed_size=", strlen("fixed_size=")) == 0) {
479 char *size = tok + strlen("fixed_size=");
480 if (strchr(size, 'x')) {
481 s->fixed_w = atoi(size);
482 s->fixed_h = atoi(strchr(size, 'x') + 1);
483 }
484 }
485 }
486 ptr = NULL;
487 }
488
489 free (tmp);
490 }
491
492#ifdef __APPLE__
493 /* Startup function to call when running Cocoa code from a Carbon application.
494 * Whatever the fuck that means.
495 * Avoids uncaught exception (1002) when creating CGSWindow */
496 NSApplicationLoad();
497 s->autorelease_pool = autorelease_pool_allocate();
498#endif
499
500 ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);
501
502 if (ret < 0) {
503 printf("Unable to initialize SDL.\n");
504 delete s;
505 return NULL;
506 }
507
508 video_info = SDL_GetVideoInfo();
509 s->screen_w = video_info->current_w;
510 s->screen_h = video_info->current_h;
511
512 SDL_SysWMinfo info;
513 memset(&info, 0, sizeof(SDL_SysWMinfo));
514 ret = SDL_GetWMInfo(&info);
515#ifdef __linux__
516 if (ret == 1) {
517 x11_set_display(info.info.x11.display);
518 } else if (ret == 0) {
519 fprintf(stderr, "[SDL] Warning: SDL_GetWMInfo unimplemented\n");
520 } else if (ret == -1) {
521 fprintf(stderr, "[SDL] Warning: SDL_GetWMInfo failure: %s\n", SDL_GetError());
522 } else abort();
523#endif
524
525 if (s->fixed_size && s->fixed_w && s->fixed_h) {
526 struct video_desc desc;
527 desc.width = s->fixed_w;
528 desc.height = s->fixed_h;
531 desc.fps = 1;
532 desc.tile_count = 1;
533
535 }
537
538 if (flags) {
540 s->play_audio = TRUE;
542 } else {
544 log_msg(LOG_LEVEL_ERROR, "[SDL] Only accepted audio output for SDL is \"embedded\".\n");
545 } else {
546 log_msg(LOG_LEVEL_ERROR, "[SDL] Unsupported/unknown flag passed.\n");
547 }
548 return NULL;
549 }
550 } else {
551 s->play_audio = FALSE;
552 }
553
554 keycontrol_register_key(get_module(get_root_module(parent), "control"), 'q', "execute exit", "quit");
555
556 return (void *)s;
557}
struct video_desc desc
const char * fmt
const char unsigned int flags
#define TRUE
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define DISPLAY_FLAG_AUDIO_ANY
#define DISPLAY_FLAG_AUDIO_EMBEDDED
struct module * get_module(struct module *root, const char *const_path)
Definition module.c:264
struct module * get_root_module(struct module *node)
Definition module.c:203
#define INIT_NOERR
Definition host.h:73
bool keycontrol_register_key(struct module *receiver_mod, int64_t key, const char *message, const char *description)
Registers callback message for given key.
static void configure_audio(struct state_sdl *s)
Definition sdl.cpp:664
static void loadSplashscreen(struct state_sdl *s)
Definition sdl.cpp:152
static void show_help(void)
Definition sdl.cpp:370
const char * parent
Definition settings.cpp:198
bool fixed_size
Definition sdl.cpp:96
int fixed_w
Definition sdl.cpp:97
bool fs
Definition sdl.cpp:94
int screen_h
Definition sdl.cpp:99
int screen_w
Definition sdl.cpp:99
state_sdl(struct module *parent)
Definition sdl.cpp:119
int fixed_h
Definition sdl.cpp:97
bool nodecorate
Definition sdl.cpp:95
unsigned int tile_count
Definition types.h:185
enum interlacing_t interlacing
Definition types.h:184
double fps
Definition types.h:183
unsigned int width
width of every tile (!)
Definition types.h:179
unsigned int height
height of every tile (!)
Definition types.h:180
@ PROGRESSIVE
progressive frame
Definition types.h:164
void x11_set_display(void *disp)
Definition x11_common.c:92

References state_sdl::state_sdl(), video_desc::color_spec, configure_audio(), state_sdl::deinterlace, desc, DISPLAY_FLAG_AUDIO_ANY, DISPLAY_FLAG_AUDIO_EMBEDDED, display_sdl_reconfigure_real(), FALSE, state_sdl::fixed_h, state_sdl::fixed_size, state_sdl::fixed_w, flags, fmt, video_desc::fps, state_sdl::fs, get_module(), get_root_module(), video_desc::height, INIT_NOERR, video_desc::interlacing, keycontrol_register_key(), loadSplashscreen(), LOG_LEVEL_ERROR, log_msg(), state_sdl::nodecorate, parent, state_sdl::play_audio, PROGRESSIVE, RGBA, state_sdl::screen_h, state_sdl::screen_w, show_help(), video_desc::tile_count, TRUE, video_desc::width, and x11_set_display().

Here is the call graph for this function:

◆ display_sdl_probe()

static void display_sdl_probe ( struct device_info ** available_cards,
int * count,
void(** deleter )(void *) )
static

Definition at line 768 of file sdl.cpp.

768 {
770 *count = 1;
771 *available_cards = (struct device_info *) calloc(1, sizeof(struct device_info));
772 strcpy((*available_cards)[0].dev, "");
773 strcpy((*available_cards)[0].name, "SDL SW display");
774 (*available_cards)[0].repeatable = true;
775}
int void(** deleter)(void *))
int count
Definition hd-rum.c:44
const char * name
Definition settings.cpp:193
char dev[1024]
Definition types.h:383

References count, deleter, device_info::dev, name, and UNUSED.

◆ display_sdl_put_audio_frame()

static void display_sdl_put_audio_frame ( void * state,
const struct audio_frame * frame )
static

Definition at line 751 of file sdl.cpp.

751 {
752 struct state_sdl *s = (struct state_sdl *)state;
753 char *tmp;
754
755 if(!s->play_audio)
756 return;
757
758 if(frame->bps == 4 || frame->bps == 3) {
759 tmp = (char *) malloc(frame->data_len / frame->bps * 2);
760 change_bps(tmp, 2, frame->data, frame->bps, frame->data_len);
761 ring_buffer_write(s->audio_buffer, tmp, frame->bps * 2);
762 free(tmp);
763 } else {
764 ring_buffer_write(s->audio_buffer, frame->data, frame->data_len);
765 }
766}
void ring_buffer_write(struct ring_buffer *ring, const char *in, int len)
void change_bps(char *out, int out_bps, const char *in, int in_bps, int in_len)
Definition utils.cpp:258

References state_sdl::audio_buffer, change_bps(), frame, state_sdl::play_audio, ring_buffer_write(), and state.

Here is the call graph for this function:

◆ display_sdl_putf()

static bool display_sdl_putf ( void * state,
struct video_frame * frame,
long long nonblock )
static

Definition at line 605 of file sdl.cpp.

606{
607 struct state_sdl *s = (struct state_sdl *)state;
608
609 assert(s->magic == MAGIC_SDL);
610
611 if (nonblock == PUTF_DISCARD) {
612 vf_free(frame);
613 return true;
614 }
615
616 std::unique_lock<std::mutex> lk(s->lock);
618 && frame != NULL) {
619 vf_free(frame);
620 printf("1 frame(s) dropped!\n");
621 return false;
622 }
623 s->frame_consumed_cv.wait(lk, [s]{return s->buffered_frames_count < MAX_BUFFER_SIZE;});
624 s->buffered_frames_count += 1;
625 lk.unlock();
626 SDL_Event event;
627 event.type = SDL_USER_NEWFRAME;
628 event.user.data1 = frame;
629 SDL_PushEvent(&event);
630
631 return true;
632}
struct video_frame long long nonblock
#define PUTF_DISCARD
#define PUTF_BLOCKING
#define SDL_USER_NEWFRAME
Definition sdl.cpp:81
#define MAX_BUFFER_SIZE
Definition sdl.cpp:77
int buffered_frames_count
Definition sdl.cpp:105
condition_variable frame_consumed_cv
Definition sdl.cpp:110

References state_sdl::buffered_frames_count, frame, state_sdl::frame_consumed_cv, state_sdl::lock, state_sdl::magic, MAGIC_SDL, MAX_BUFFER_SIZE, nonblock, PUTF_BLOCKING, PUTF_DISCARD, SDL_USER_NEWFRAME, state, and vf_free().

Referenced by loadSplashscreen().

Here is the call graph for this function:

◆ display_sdl_reconfigure()

static bool display_sdl_reconfigure ( void * state,
struct video_desc desc )
static

Definition at line 395 of file sdl.cpp.

396{
397 struct state_sdl *s = (struct state_sdl *)state;
398
399 s->current_desc = desc;
400 return true;
401}

References state_sdl::current_desc, desc, and state.

Referenced by loadSplashscreen().

◆ display_sdl_reconfigure_audio()

static bool display_sdl_reconfigure_audio ( void * state,
int quant_samples,
int channels,
int sample_rate )
static

Definition at line 679 of file sdl.cpp.

680 {
681 struct state_sdl *s = (struct state_sdl *)state;
682 if (!s->play_audio) {
683 return false;
684 }
685 SDL_AudioSpec desired, obtained;
686 int sample_type;
687
691
692 if(s->audio_frame.data != NULL) {
693 free(s->audio_frame.data);
694 SDL_CloseAudio();
695 }
696
697 if(quant_samples % 8 != 0) {
698 fprintf(stderr, "[SDL] audio format isn't supported: "
699 "channels: %d, samples: %d, sample rate: %d\n",
701 goto error;
702 }
703 switch(quant_samples) {
704 case 8:
705 sample_type = AUDIO_S8;
706 break;
707 case 16:
708 sample_type = AUDIO_S16LSB;
709 break;
710 /* TO enable in sdl 1.3
711 * case 32:
712 sample_type = AUDIO_S32;
713 break; */
714 default:
715 return false;
716 }
717
718 desired.freq=sample_rate;
719 desired.format=sample_type;
720 desired.channels=channels;
721
722 /* Large audio buffer reduces risk of dropouts but increases response time */
723 desired.samples=1024;
724
725 /* Our callback function */
726 desired.callback=sdl_audio_callback;
727 desired.userdata=s;
728
729
730 /* Open the audio device */
731 if ( SDL_OpenAudio(&desired, &obtained) < 0 ){
732 fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
733 goto error;
734 }
735
736 s->audio_frame.max_size = 5 * (quant_samples / 8) * channels *
738 s->audio_frame.data = (char *) malloc (s->audio_frame.max_size);
739
740 /* Start playing */
741 SDL_PauseAudio(0);
742
743 return true;
744error:
745 s->play_audio = FALSE;
746 s->audio_frame.max_size = 0;
747 s->audio_frame.data = NULL;
748 return false;
749}
int int int sample_rate
int int channels
int quant_samples
static void sdl_audio_callback(void *userdata, Uint8 *stream, int len)
Definition sdl.cpp:655
int sample_rate
Definition types.h:101
int ch_count
Definition types.h:104
int bps
Definition types.h:100
int max_size
Definition types.h:105

References state_sdl::audio_frame, audio_frame::bps, audio_frame::ch_count, channels, audio_frame::data, FALSE, audio_frame::max_size, state_sdl::play_audio, quant_samples, audio_frame::sample_rate, sample_rate, sdl_audio_callback(), and state.

Here is the call graph for this function:

◆ display_sdl_reconfigure_real()

static bool display_sdl_reconfigure_real ( void * state,
struct video_desc desc )
static

Definition at line 403 of file sdl.cpp.

404{
405 struct state_sdl *s = (struct state_sdl *)state;
406
407 fprintf(stdout, "Reconfigure to size %dx%d\n", desc.width,
408 desc.height);
409
410 uint32_t flags_common = SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_RESIZABLE;
411 s->sdl_flags_fs = flags_common | SDL_FULLSCREEN;
412 s->sdl_flags_win = flags_common | (s->nodecorate ? SDL_NOFRAME : 0);
414
415 if (!s->fixed_size ||
416 !s->sdl_screen /* first run */) {
417 if (!update_size(s, desc.width, desc.height)) {
418 memset(&s->current_display_desc, 0, sizeof s->current_display_desc);
419 return false;
420 }
421 } else {
422 SDL_FillRect(s->sdl_screen, NULL, 0x000000);
423 SDL_Flip(s->sdl_screen);
425 }
426
427 const char *window_title = get_commandline_param("window-title");
428 if (window_title) {
429 SDL_WM_SetCaption(window_title, window_title);
430 } else {
431 SDL_WM_SetCaption("Ultragrid - SDL Display", "Ultragrid");
432 }
433
434 SDL_ShowCursor(SDL_DISABLE);
435
437 s->yuv_image =
438 SDL_CreateYUVOverlay(desc.width, desc.height, desc.color_spec == UYVY ?
440 if (s->yuv_image == NULL) {
441 printf("SDL_overlay initialization failed.\n");
442 memset(&s->current_display_desc, 0, sizeof s->current_display_desc);
443 return false;
444 }
445 }
446
447 return true;
448}
const char * get_commandline_param(const char *key)
Definition host.cpp:894
#define FOURCC_UYVY
Definition sdl.cpp:74
static void compute_dst_rect(struct state_sdl *s, int vid_w, int vid_h, int window_w, int window_h, codec_t codec)
Definition sdl.cpp:158
static bool update_size(struct state_sdl *s, int win_w, int win_h)
Definition sdl.cpp:194
#define FOURCC_YUYV
Definition sdl.cpp:75
uint32_t sdl_flags_fs
Definition sdl.cpp:115
uint32_t sdl_flags_win
Definition sdl.cpp:115

References codec_is_a_rgb(), video_desc::color_spec, compute_dst_rect(), state_sdl::current_display_desc, desc, state_sdl::fixed_size, FOURCC_UYVY, FOURCC_YUYV, get_commandline_param(), video_desc::height, state_sdl::nodecorate, state_sdl::sdl_flags_fs, state_sdl::sdl_flags_win, state_sdl::sdl_screen, state, update_size(), UYVY, video_desc::width, and state_sdl::yuv_image.

Referenced by display_frame(), and display_sdl_init().

Here is the call graph for this function:

◆ display_sdl_run()

static void display_sdl_run ( void * arg)
static

Definition at line 302 of file sdl.cpp.

303{
304 struct state_sdl *s = (struct state_sdl *)arg;
305 bool should_exit_sdl = false;
306
307 while (!should_exit_sdl) {
308 struct message *msg;
309 while ((msg = check_message(&s->mod))) {
310 auto msg_univ = reinterpret_cast<struct msg_universal *>(msg);
311 struct response *r;
312 if (strncasecmp(msg_univ->text, "win-title ", strlen("win_title ")) == 0) {
313 const char *title = msg_univ->text + strlen("win_title");
314 SDL_WM_SetCaption(title, title);
315 r = new_response(RESPONSE_OK, NULL);
316 } else {
317 log_msg(LOG_LEVEL_ERROR, "[SDL] Unknown command received: %s\n", msg_univ->text);
319 }
320 free_message(msg, r);
321 }
322
323 SDL_Event sdl_event;
324 if (SDL_WaitEvent(&sdl_event)) {
325 switch (sdl_event.type) {
327 {
328 std::unique_lock<std::mutex> lk(s->lock);
329 s->buffered_frames_count -= 1;
330 lk.unlock();
331 s->frame_consumed_cv.notify_one();
332 if (sdl_event.user.data1 != NULL) {
333 display_frame(s, (struct video_frame *) sdl_event.user.data1);
334 } else { // poison pill received
335 should_exit_sdl = true;
336 }
337 break;
338 }
339 case SDL_VIDEORESIZE:
340 update_size(s, sdl_event.resize.w, sdl_event.resize.h);
341 break;
342 case SDL_KEYDOWN:
343 switch (sdl_event.key.keysym.sym) {
344 case SDLK_d:
345 s->deinterlace = s->deinterlace ? FALSE : TRUE;
346 log_msg(LOG_LEVEL_INFO, "Deinterlacing: %s\n",
347 s->deinterlace ? "ON" : "OFF");
348 break;
349 case SDLK_f:
350 s->fs = !s->fs;
352 break;
353 case SDLK_q:
354 exit_uv(0);
355 break;
356 default:
357 log_msg(LOG_LEVEL_DEBUG, "[SDL] Unhandled key: %s\n",
358 SDL_GetKeyName(sdl_event.key.keysym.sym));
359 break;
360 }
361 break;
362 case SDL_QUIT:
363 exit_uv(0);
364 break;
365 }
366 }
367 }
368}
void exit_uv(int status)
Definition host.cpp:625
#define LOG_LEVEL_DEBUG
Definition kernels.cu:48
void free_message(struct message *msg, struct response *r)
struct response * new_response(int status, const char *text)
struct message * check_message(struct module *mod)
#define RESPONSE_OK
Definition messaging.h:57
#define RESPONSE_BAD_REQUEST
Definition messaging.h:60
struct msghdr msg
static void display_frame(struct state_sdl *s, struct video_frame *frame)
Definition sdl.cpp:219
struct module mod
Definition sdl.cpp:117

References state_sdl::buffered_frames_count, check_message(), state_sdl::current_display_desc, state_sdl::deinterlace, display_frame(), exit_uv(), FALSE, state_sdl::frame_consumed_cv, free_message(), state_sdl::fs, video_desc::height, state_sdl::lock, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, log_msg(), state_sdl::mod, msg, new_response(), RESPONSE_BAD_REQUEST, RESPONSE_OK, SDL_USER_NEWFRAME, TRUE, update_size(), and video_desc::width.

Here is the call graph for this function:

◆ loadSplashscreen()

static void loadSplashscreen ( struct state_sdl * s)
static

Definition at line 152 of file sdl.cpp.

152 {
156}
struct video_frame * get_splashscreen()
static bool display_sdl_reconfigure(void *state, struct video_desc desc)
Definition sdl.cpp:395
static bool display_sdl_putf(void *state, struct video_frame *frame, long long nonblock)
Definition sdl.cpp:605

References display_sdl_putf(), display_sdl_reconfigure(), frame, get_splashscreen(), PUTF_BLOCKING, and video_desc_from_frame().

Referenced by display_sdl_init().

Here is the call graph for this function:

◆ REGISTER_MODULE()

REGISTER_MODULE ( sdl ,
& display_sdl_info,
LIBRARY_CLASS_VIDEO_DISPLAY ,
VIDEO_DISPLAY_ABI_VERSION  )

◆ sdl_audio_callback()

static void sdl_audio_callback ( void * userdata,
Uint8 * stream,
int len )
static

Definition at line 655 of file sdl.cpp.

655 {
656 struct state_sdl *s = (struct state_sdl *)userdata;
657 if (ring_buffer_read(s->audio_buffer, (char *) stream, len) != len)
658 {
659 fprintf(stderr, "[SDL] audio buffer underflow!!!\n");
660 usleep(500);
661 }
662}
int ring_buffer_read(struct ring_buffer *ring, char *out, int max_len)
int usleep(unsigned int usec)
Definition usleep.c:47

References state_sdl::audio_buffer, len, ring_buffer_read(), and usleep().

Referenced by display_sdl_reconfigure_audio().

Here is the call graph for this function:

◆ show_help()

static void show_help ( void )
static

Definition at line 370 of file sdl.cpp.

371{
372 printf("SDL options:\n");
373 printf("\t-d sdl[:fs|:d|:nodecorate|:fixed_size[=WxH]]* | help\n");
374 printf("\tfs - fullscreen\n");
375 printf("\td - deinterlace\n");
376 printf("\tnodecorate - disable WM decoration\n");
377 printf("\tfixed_size[=WxH] - use fixed sized window\n");
378 //printf("\t<f> - read frame content from the filename\n");
379}

Referenced by display_sdl_init().

◆ update_size()

static bool update_size ( struct state_sdl * s,
int win_w,
int win_h )
static

Definition at line 194 of file sdl.cpp.

195{
196 unsigned int x_res_x, x_res_y;
197
198 if (s->fs) {
199 x_res_x = s->screen_w;
200 x_res_y = s->screen_h;
201 } else {
202 x_res_x = win_w;
203 x_res_y = win_h;
204 }
205 SDL_Surface *sdl_screen_old = s->sdl_screen;
206 s->sdl_screen = SDL_SetVideoMode(x_res_x, x_res_y, 0, s->fs ? s->sdl_flags_fs : s->sdl_flags_win);
207 fprintf(stdout, "Setting video mode %dx%d.\n", x_res_x, x_res_y);
209 if (s->sdl_screen == NULL) {
210 fprintf(stderr, "Error setting video mode %dx%d!\n", x_res_x,
211 x_res_y);
212 s->sdl_screen = sdl_screen_old;
213 return false;
214 } else {
215 return true;
216 }
217}

References video_desc::color_spec, compute_dst_rect(), state_sdl::current_display_desc, state_sdl::fs, video_desc::height, state_sdl::screen_h, state_sdl::screen_w, state_sdl::sdl_flags_fs, state_sdl::sdl_flags_win, state_sdl::sdl_screen, and video_desc::width.

Referenced by display_sdl_reconfigure_real(), and display_sdl_run().

Here is the call graph for this function:

Variable Documentation

◆ display_sdl_info

const struct video_display_info display_sdl_info
static
Initial value:
= {
}
#define DISPLAY_NO_GENERIC_FPS_INDICATOR
static void display_sdl_done(void *state)
Definition sdl.cpp:559
static bool display_sdl_get_property(void *state, int property, void *val, size_t *len)
Definition sdl.cpp:634
static void display_sdl_probe(struct device_info **available_cards, int *count, void(**deleter)(void *))
Definition sdl.cpp:768
static struct video_frame * display_sdl_getf(void *state)
Definition sdl.cpp:585
static void display_sdl_run(void *arg)
Definition sdl.cpp:302
static void display_sdl_put_audio_frame(void *state, const struct audio_frame *frame)
Definition sdl.cpp:751
static bool display_sdl_reconfigure_audio(void *state, int quant_samples, int channels, int sample_rate)
Definition sdl.cpp:679
static void * display_sdl_init(struct module *parent, const char *fmt, unsigned int flags)
Definition sdl.cpp:450

Definition at line 777 of file sdl.cpp.