UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
sdl.cpp
Go to the documentation of this file.
1
7/*
8 * Copyright (c) 2010-2023 CESNET, z. s. p. o.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, is permitted provided that the following conditions
13 * are met:
14 *
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 *
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * 3. Neither the name of CESNET nor the names of its contributors may be
23 * used to endorse or promote products derived from this software without
24 * specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
28 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
29 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
30 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
31 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
36 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
37 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */
39
40#include "config.h"
41#include "config_unix.h"
42#include "config_win32.h"
43#include "host.h"
44
45#include "debug.h"
46#include "keyboard_control.h"
47#include "lib_common.h"
48#include "messaging.h"
49#include "module.h"
50#include "video_display.h"
51#include "tv.h"
52#include "audio/types.h"
53#include "audio/utils.h"
54#include "utils/ring_buffer.h"
55#include "video.h"
56
57#ifdef __APPLE__
58#include "utils/autorelease_pool.h"
59extern "C" void NSApplicationLoad();
60#elif defined __linux__
61#include "x11_common.h"
62#endif /* __APPLE__ */
63
64#include <math.h>
65
66#include <SDL/SDL.h>
67#include <SDL/SDL_syswm.h>
68
69#include <condition_variable>
70#include <mutex>
71#include <queue>
72
73#define MAGIC_SDL 0x155734ae
74#define FOURCC_UYVY 0x59565955
75#define FOURCC_YUYV 0x32595559
76
77#define MAX_BUFFER_SIZE 1
78
79using namespace std;
80
81#define SDL_USER_NEWFRAME SDL_USEREVENT
82
83struct state_sdl {
84 uint32_t magic;
85
86 struct timeval tv;
87 int frames;
88
89 SDL_Overlay * yuv_image;
90 SDL_Surface * sdl_screen;
91 SDL_Rect dst_rect;
92
94 bool fs;
98
100
104
106 queue<struct video_frame *> free_frame_queue;
109 mutex lock;
110 condition_variable frame_consumed_cv;
111
112#ifdef __APPLE__
113 void *autorelease_pool;
114#endif
116
117 struct module mod;
118
119 state_sdl(struct module *parent) : magic(MAGIC_SDL), frames(0), yuv_image(nullptr), sdl_screen(nullptr), dst_rect(),
120 deinterlace(false), fs(false), nodecorate(false), fixed_size(false),
121 fixed_w(0), fixed_h(0),
124#ifdef __APPLE__
125 autorelease_pool(nullptr),
126#endif
128 {
129 gettimeofday(&tv, NULL);
133 }
134
137 }
138};
139
140static void loadSplashscreen(struct state_sdl *s);
141static void show_help(void);
142static bool display_sdl_putf(void *state, struct video_frame *frame, long long nonblock);
143static bool display_sdl_reconfigure(void *state, struct video_desc desc);
144static bool display_sdl_reconfigure_real(void *state, struct video_desc desc);
145
146static void cleanup_screen(struct state_sdl *s);
147static void configure_audio(struct state_sdl *s);
148static void sdl_audio_callback(void *userdata, Uint8 *stream, int len);
149static void compute_dst_rect(struct state_sdl *s, int vid_w, int vid_h, int window_w, int window_h, codec_t codec);
150static bool update_size(struct state_sdl *s, int win_w, int win_h);
151
157
158static void compute_dst_rect(struct state_sdl *s, int vid_w, int vid_h, int window_w, int window_h, codec_t codec)
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}
193
194static bool update_size(struct state_sdl *s, int win_w, int win_h)
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}
218
219static void display_frame(struct state_sdl *s, struct video_frame *frame)
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}
301
302static void display_sdl_run(void *arg)
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}
369
370static void show_help(void)
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}
380
381static void cleanup_screen(struct state_sdl *s)
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}
394
396{
397 struct state_sdl *s = (struct state_sdl *)state;
398
399 s->current_desc = desc;
400 return true;
401}
402
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}
449
450static void *display_sdl_init(struct module *parent, const char *fmt, unsigned int flags)
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}
558
559static void display_sdl_done(void *state)
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}
584
585static struct video_frame *display_sdl_getf(void *state)
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}
604
605static bool display_sdl_putf(void *state, struct video_frame *frame, long long nonblock)
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}
633
634static bool display_sdl_get_property(void *state, int property, void *val, size_t *len)
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}
654
655static void sdl_audio_callback(void *userdata, Uint8 *stream, int len) {
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}
663
664static void configure_audio(struct state_sdl *s)
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}
678
680 int sample_rate) {
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}
750
751static void display_sdl_put_audio_frame(void *state, const struct audio_frame *frame) {
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}
767
768static void display_sdl_probe(struct device_info **available_cards, int *count, void (**deleter)(void *)) {
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}
776
790
792
#define UNUSED(x)
void ** state
struct video_frame long long nonblock
int void * val
struct video_desc desc
int int int sample_rate
int int channels
struct video_frame * frame
const char * fmt
int void size_t * len
const char unsigned int flags
int void(** deleter)(void *))
int property
int quant_samples
void vf_free(struct video_frame *buf)
Frees video_frame structure.
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)
struct video_frame * vf_alloc_desc_data(struct video_desc desc)
This file contains definition of some common audio types.
#define TRUE
#define FALSE
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define PUTF_DISCARD
#define PUTF_BLOCKING
#define VIDEO_DISPLAY_ABI_VERSION
#define DISPLAY_FLAG_AUDIO_ANY
#define DISPLAY_NO_GENERIC_FPS_INDICATOR
#define DISPLAY_FLAG_AUDIO_EMBEDDED
struct video_frame * get_splashscreen()
@ DISPLAY_PROPERTY_CODECS
list of natively supported codecs - codec_t[]
void module_init_default(struct module *module_data)
Definition module.c:48
void module_register(struct module *module_data, struct module *parent)
Definition module.c:82
struct module * get_module(struct module *root, const char *const_path)
Definition module.c:264
void module_done(struct module *module_data)
Definition module.c:93
struct module * get_root_module(struct module *node)
Definition module.c:203
@ MODULE_CLASS_DATA
Definition module.h:86
int count
Definition hd-rum.c:44
void exit_uv(int status)
Definition host.cpp:625
const char * get_commandline_param(const char *key)
Definition host.cpp:894
#define INIT_NOERR
Definition host.h:73
#define LOG_LEVEL_DEBUG
Definition kernels.cu:48
bool keycontrol_register_key(struct module *receiver_mod, int64_t key, const char *message, const char *description)
Registers callback message for given key.
@ LIBRARY_CLASS_VIDEO_DISPLAY
Definition lib_common.h:79
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
Definition lib_common.h:144
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
decoder_t get_decoder_from_to(codec_t in, codec_t out)
decoder_func_t * decoder_t
Definition pixfmt_conv.h:96
struct ring_buffer * ring_buffer_init(int size)
int ring_buffer_read(struct ring_buffer *ring, char *out, int max_len)
void ring_buffer_write(struct ring_buffer *ring, const char *in, int len)
struct msghdr msg
static void display_sdl_done(void *state)
Definition sdl.cpp:559
#define FOURCC_UYVY
Definition sdl.cpp:74
static bool display_sdl_get_property(void *state, int property, void *val, size_t *len)
Definition sdl.cpp:634
static void display_frame(struct state_sdl *s, struct video_frame *frame)
Definition sdl.cpp:219
#define SDL_USER_NEWFRAME
Definition sdl.cpp:81
static bool display_sdl_reconfigure(void *state, struct video_desc desc)
Definition sdl.cpp:395
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
static void display_sdl_probe(struct device_info **available_cards, int *count, void(**deleter)(void *))
Definition sdl.cpp:768
static void configure_audio(struct state_sdl *s)
Definition sdl.cpp:664
static const struct video_display_info display_sdl_info
Definition sdl.cpp:777
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 void cleanup_screen(struct state_sdl *s)
Definition sdl.cpp:381
#define FOURCC_YUYV
Definition sdl.cpp:75
#define MAX_BUFFER_SIZE
Definition sdl.cpp:77
static bool display_sdl_reconfigure_audio(void *state, int quant_samples, int channels, int sample_rate)
Definition sdl.cpp:679
#define MAGIC_SDL
Definition sdl.cpp:73
static void loadSplashscreen(struct state_sdl *s)
Definition sdl.cpp:152
static bool display_sdl_putf(void *state, struct video_frame *frame, long long nonblock)
Definition sdl.cpp:605
static void sdl_audio_callback(void *userdata, Uint8 *stream, int len)
Definition sdl.cpp:655
static void show_help(void)
Definition sdl.cpp:370
static bool display_sdl_reconfigure_real(void *state, struct video_desc desc)
Definition sdl.cpp:403
static void * display_sdl_init(struct module *parent, const char *fmt, unsigned int flags)
Definition sdl.cpp:450
const char * parent
Definition settings.cpp:198
const char * name
Definition settings.cpp:193
struct used to comunicate with audio capture/playback device
Definition types.h:99
int sample_rate
Definition types.h:101
char * data
Definition types.h:102
int ch_count
Definition types.h:104
int bps
Definition types.h:100
int max_size
Definition types.h:105
char dev[1024]
Definition types.h:383
enum module_class cls
Definition module.h:115
mutex lock
Definition sdl.cpp:109
uint32_t sdl_flags_fs
Definition sdl.cpp:115
SDL_Rect dst_rect
Definition sdl.cpp:91
struct timeval tv
Definition sdl.cpp:86
bool fixed_size
Definition sdl.cpp:96
struct ring_buffer * audio_buffer
Definition sdl.cpp:101
struct module mod
Definition sdl.cpp:117
int fixed_w
Definition sdl.cpp:97
uint32_t magic
Definition sdl.cpp:84
~state_sdl()
Definition sdl.cpp:135
bool deinterlace
Definition sdl.cpp:93
bool fs
Definition sdl.cpp:94
struct video_desc current_desc
Definition sdl.cpp:107
int frames
Definition sdl.cpp:87
int screen_h
Definition sdl.cpp:99
uint32_t sdl_flags_win
Definition sdl.cpp:115
SDL_Overlay * yuv_image
Definition sdl.cpp:89
struct audio_frame audio_frame
Definition sdl.cpp:102
int buffered_frames_count
Definition sdl.cpp:105
int screen_w
Definition sdl.cpp:99
queue< struct video_frame * > free_frame_queue
Definition sdl.cpp:106
struct video_desc current_display_desc
with those desc new data frames will be generated (getf)
Definition sdl.cpp:108
state_sdl(struct module *parent)
Definition sdl.cpp:119
bool play_audio
Definition sdl.cpp:103
int fixed_h
Definition sdl.cpp:97
SDL_Surface * sdl_screen
Definition sdl.cpp:90
condition_variable frame_consumed_cv
Definition sdl.cpp:110
bool nodecorate
Definition sdl.cpp:95
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
unsigned int tile_count
Definition types.h:185
codec_t color_spec
Definition types.h:182
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
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
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
@ PROGRESSIVE
progressive frame
Definition types.h:164
codec_t
Definition types.h:65
@ YUYV
YCbCr 422 8-bit - Y0 Cb Y1 Cr.
Definition types.h:72
@ RGB
RGB 8-bit (packed into 24-bit word)
Definition types.h:80
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
Definition types.h:71
@ RGBA
RGBA 8-bit, big-endian.
Definition types.h:70
int usleep(unsigned int usec)
Definition usleep.c:47
void change_bps(char *out, int out_bps, const char *in, int in_bps, int in_len)
Definition utils.cpp:258
This is an umbrella header for video functions.
void vc_deinterlace(unsigned char *src, long src_linesize, int lines)
Deinterlaces framebuffer.
bool codec_is_a_rgb(codec_t codec)
Returns TRUE if specified pixelformat is some form of RGB (not YUV).
double get_bpp(codec_t codec)
static struct @76 codecs[]
bool video_desc_eq(struct video_desc a, struct video_desc b)
Compares two video descriptions.
void x11_set_display(void *disp)
Definition x11_common.c:92