61#include <SDL2/SDL_ttf.h>
63#include <SDL/SDL_ttf.h>
85#define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_RATE * AUDIO_BPS * \
86 s->audio.ch_count * BUFFER_SEC)
88#define AUDIO_SAMPLE_RATE 48000
89#define BANNER_HEIGHT 150L
90#define BANNER_MARGIN_BOTTOM 75L
92#define DEFAULT_FORMAT "1920:1080:24:UYVY"
93#define EPS_PLUS_1 1.0001
94#define FONT_HEIGHT 108
95#define MOD_NAME "[testcard2] "
99#define DEFAULT_FONT_DIR "C:\\windows\\fonts"
100static const char *
const font_candidates[] = {
"cour.ttf", };
101#elif defined __APPLE__
102#define DEFAULT_FONT_DIR "/System/Library/Fonts"
103static const char *
const font_candidates[] = {
110#define DEFAULT_FONT_DIR "/usr/share/fonts"
111static const char *
const font_candidates[] = {
112 "DejaVuSansMono.ttf",
113 "truetype/freefont/FreeMonoBold.ttf",
"truetype/dejavu/DejaVuSansMono.ttf",
114 "TTF/DejaVuSansMono.ttf",
"liberation/LiberationMono-Regular.ttf",
115 "liberation-mono/LiberationMono-Regular.ttf",
156 short int * data = (
short int *)(
void *) s->
audio_tone;
159 data[i] = data[i+1] = (float) sin( ((
double)i/(
double)200) * M_PI * 2. ) * SHRT_MAX;
162 printf(
"[testcard2] playing audio\n");
169 char *tmp = strtok_r(
fmt,
":", &save_ptr);
178 "Width must be a positive multiple of 2.\n");
181 tmp = strtok_r(NULL,
":", &save_ptr);
191 tmp = strtok_r(NULL,
":", &save_ptr);
201 tmp = strtok_r(NULL,
":", &save_ptr);
213 color_printf(
"testcard2 is an alternative implementation of testing signal source.\n");
214 color_printf(
"It is less maintained than mainline testcard and has less features but has some extra ones, i. a. a timer (if SDL(2)_ttf is found.\n");
219 color_printf(
TBOLD(
TRED(
"\t-t testcard2")
"[:size=<width>x<height>][:fps=<fps>][:codec=<codec>][:mode=<mode>]")
"\n");
234 if (strlen(ptr) > 0 && isdigit(ptr[0])) {
247 char *save_ptr = NULL;
248 char *tmp = strtok_r(ptr,
":", &save_ptr);
262 tmp = strchr(tmp,
'=') + 1;
263 if (isdigit(tmp[0]) && strchr(tmp,
'x') != NULL) {
278 fprintf(stderr,
"[testcard2] Unknown option: %s\n", tmp);
282 tmp = strtok_r(NULL,
":", &save_ptr);
305 for (
unsigned i = 0; i < s->
desc.
width; i += rect_size) {
314 col_num = (col_num + 1) %
COL_NUM;
325 fprintf(stderr,
"[testcard2] Disabling audio output. "
344 fprintf(stderr,
"[testcard] Disabling audio output. "
345 "SDL-mixer missing, running on Mac or other problem.");
358 pthread_mutex_init(&s->
lock, NULL);
371 pthread_mutex_lock(&s->
lock);
375 pthread_mutex_unlock(&s->
lock);
380 pthread_mutex_destroy(&s->
lock);
400 struct timeval next_frame_time = { 0 };
402 int prev_x1 = rand() % ((s->
desc.
width - 300) / 6) * 6;
403 int prev_y1 = rand() % ((s->
desc.
height - 300) / 6) * 6;
404 int down1 = rand() % 2, right1 = rand() % 2;
405 int prev_x2 = rand() % ((s->
desc.
width - 96) / 6) * 6;
406 int prev_y2 = rand() % ((s->
desc.
height - 96) / 6) * 6;
407 int down2 = rand() % 2, right2 = rand() % 2;
409 int stat_count_prev = 0;
413#ifdef HAVE_LIBSDL_TTF
414#define EXIT_THREAD { free(banner); exit_uv(1); s->should_exit = true; platform_sem_post(&s->semaphore); return NULL; }
415 TTF_Font *
font = NULL;
424 const char *font_dir =
IF_NOT_NULL_ELSE(getenv(
"UG_FONT_DIR"), DEFAULT_FONT_DIR);
426 for (
unsigned i = 0;
font == NULL && i <
sizeof font_candidates /
sizeof font_candidates[0]; ++i) {
427 strncpy(font_path, font_dir,
sizeof font_path - 1);
428 strncat(font_path,
"/",
sizeof font_path - strlen(font_path) - 1);
429 strncat(font_path, font_candidates[i],
sizeof font_path - strlen(font_path) - 1);
432 MSG(VERBOSE,
"Tried font %s: %s\n", font_path,
438 "Unable to load any usable font! Last font tried %s: %s\n",
439 font_path, TTF_GetError());
442 MSG(INFO,
"Using font: %s\n", font_path);
446 unsigned char square_cols[2][48];
449 for (
int i = 0; i < 6; ++i) src[i] = 0xffff00aa;
457 unsigned char *tmp = malloc(data_len);
458 memcpy(tmp, s->
bg, data_len);
463 r.
x = prev_x1 + (right1 ? 1 : -1) * 6;
464 r.
y = prev_y1 + (down1 ? 1 : -1) * 6;
465 if(r.
x < 0) { right1 = 1; r.
x = 0; }
466 if(r.
y < 0) { down1 = 1; r.
y = 0; }
473 for (
int y = 0;
y < r.
h; ++
y) {
474 for (
int x = 0;
x < r.
w / 6;
x += 1) {
475 memcpy(ptr + block_size *
x, square_cols[0], block_size);
482 r.
x = prev_x2 + (right2 ? 1 : -1) * 12;
483 r.
y = prev_y2 + (down2 ? 1 : -1) * 9;
484 if(r.
x < 0) { right2 = 1; r.
x = 0; }
485 if(r.
y < 0) { down2 = 1; r.
y = 0; }
492 for (
int y = 0;
y < r.
h; ++
y) {
493 for (
int x = 0;
x < r.
w / 6;
x += 1) {
494 memcpy(ptr + block_size *
x, square_cols[1], block_size);
499#ifdef HAVE_LIBSDL_TTF
502 SDL_Color
col = { 0, 0, 0, 0 };
506 snprintf(frames,
sizeof frames,
"%02d:%02d:%02d %3d", (
int) since_start / 3600,
507 (
int) since_start / 60 % 60,
508 (
int) since_start % 60,
510 SDL_Surface *text = TTF_RenderText_Solid(
font,
512 long xoff = ((long) s->
desc.
width - text->w) / 2;
514 for (
int i = 0 ; i < text->h; i++) {
515 uint32_t *d = banner + xoff + (i + yoff) * s->
desc.
width;
516 for (
int j = 0 ; j <
MIN(text->w, (
int) s->
desc.
width - xoff); j++) {
517 if (((
char *)text->pixels) [i * text->pitch + j]) {
524 SDL_FreeSurface(text);
529 long long since_start_usec = (s->
count * 1000000LLU) / s->
desc.
fps;
531 struct timeval curr_time;
532 gettimeofday(&curr_time, NULL);
533 if(
tv_gt(next_frame_time, curr_time)) {
534 int sleep_time =
tv_diff_usec(next_frame_time, curr_time);
547 pthread_mutex_lock(&s->
lock);
548 while (s->
data != NULL) {
551 s->
data = (
char *) tmp;
552 pthread_mutex_unlock(&s->
lock);
555 double seconds =
tv_diff(curr_time, s->
t0);
557 float fps = (s->
count - stat_count_prev) / seconds;
559 (s->
count - stat_count_prev), seconds, fps);
561 stat_count_prev = s->
count;
565#ifdef HAVE_LIBSDL_TTF
574 struct timeval curr_time;
575 gettimeofday(&curr_time, NULL);
611 assert(s->
data != NULL);
617 pthread_mutex_lock(&s->
lock);
620 pthread_mutex_unlock(&s->
lock);
638 *available_devices = NULL;
struct video_frame * frame
struct audio_frame ** audio
int void(** deleter)(void *))
void vf_free(struct video_frame *buf)
Frees video_frame structure.
void vf_data_deleter(struct video_frame *buf)
int vc_get_linesize(unsigned int width, codec_t codec)
struct video_frame * vf_alloc_desc(struct video_desc desc)
Allocates video frame accordig given desc.
codec_t get_codec_from_name(const char *name)
This file contains definition of some common audio types.
static const unsigned char font[]
int color_printf(const char *format,...)
void log_msg(int level, const char *format,...)
#define LOG_LEVEL_INFO
normal reporting
#define LOG_LEVEL_ERROR
general errors
#define LOG_LEVEL_VERBOSE
#define VIDCAP_INIT_NOERR
state not initialized, other action performed (typically help)
#define VIDCAP_INIT_OK
initialization successful
#define VIDCAP_NO_GENERIC_FPS_INDICATOR
#define VIDEO_CAPTURE_ABI_VERSION
#define VIDCAP_INIT_FAIL
error ocured
unsigned int audio_capture_channels
#define DEFAULT_AUDIO_CAPTURE_CHANNELS
@ LIBRARY_CLASS_VIDEO_CAPTURE
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
#define IS_KEY_PREFIX(tok, key)
expands to true value if <k> from tok in format <k>=<v> is prefix of key
#define IF_NOT_NULL_ELSE(val, default_val)
struct used to comunicate with audio capture/playback device
struct timeval start_time
pthread_cond_t data_consumed_cv
double seconds_tone_played
volatile bool should_exit
unsigned char * bg
bars coverted to dest color_spec
struct timeval last_audio_time
char * data
Raw tile data. Pointer must be at least 4B aligned.
enum interlacing_t interlacing
unsigned int width
width of every tile (!)
unsigned int height
height of every tile (!)
void(* data_deleter)(struct video_frame *)
void(* dispose)(struct video_frame *)
Struct video_frame represents a video frame and contains video description.
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
struct video_frame_callbacks callbacks
#define AUDIO_BUFFER_SIZE
#define AUDIO_SAMPLE_RATE
static int configure_audio(struct testcard_state2 *s)
static void vidcap_testcard2_probe(struct device_info **available_devices, int *count, void(**deleter)(void *))
static bool parse_fmt(struct testcard_state2 *s, char *fmt)
static void grab_audio(struct testcard_state2 *s)
static int vidcap_testcard2_init(struct vidcap_params *params, void **state)
static struct video_frame * vidcap_testcard2_grab(void *arg, struct audio_frame **audio)
static const struct video_capture_info vidcap_testcard2_info
static void vidcap_testcard2_done(void *state)
#define BANNER_MARGIN_BOTTOM
void * vidcap_testcard2_thread(void *args)
const uint32_t rect_colors[]
void testcard_show_codec_help(const char *name, bool src_8b_only)
void testcard_fillRect(struct testcard_pixmap *s, struct testcard_rect *r, uint32_t color)
void testcard_convert_buffer(codec_t in_c, codec_t out_c, unsigned char *out, unsigned const char *in, int width, int height)
void set_thread_name(const char *name)
uint32_t tv_diff_usec(struct timeval curr_time, struct timeval prev_time)
void tv_add_usec(struct timeval *ts, long long offset) __attribute__((always_inline))
int tv_gt(struct timeval a, struct timeval b)
double tv_diff(struct timeval curr_time, struct timeval prev_time)
This file contains some common data types.
@ PROGRESSIVE
progressive frame
@ VIDEO_CODEC_NONE
dummy color spec
@ RGBA
RGBA 8-bit, big-endian.
int usleep(unsigned int usec)
static double parse_fps(const char *string, bool interlaced)
struct video_desc get_video_desc_from_string(const char *string)
This is an umbrella header for video functions.
const char * vidcap_params_get_fmt(const struct vidcap_params *params)
unsigned int vidcap_params_get_flags(const struct vidcap_params *params)
#define VIDCAP_FLAG_AUDIO_EMBEDDED
HD-SDI embedded audio.
double get_bpp(codec_t codec)
size_t vc_get_datalen(unsigned int width, unsigned int height, codec_t codec)