94#define MOD_NAME "[testcard] "
95#define AUDIO_BUFFER_SAMPLES (AUDIO_SAMPLE_RATE * BUFFER_SEC)
96#define DEFAULT_FORMAT ((struct video_desc) { 1920, 1080, UYVY, 25.0, INTERLACED_MERGED, 1 })
97#define DEFAULT_PATTERN "bars"
137 const double scale = 0.1;
158 MOD_NAME "Requested %d Hz audio but only %d HZ is "
159 "currently supported by "
196 char *tmp, *token, *saveptr = NULL;
202 if(
fmt[1] !=
'=')
return 1;
204 tmp = strdup(&
fmt[2]);
205 token = strtok_r(tmp,
"x", &saveptr);
206 grid_w = atoi(token);
207 token = strtok_r(NULL,
"x", &saveptr);
208 grid_h = atoi(token);
220 assert(tile_cnt >= 1);
230 for(x = 0; x < grid_w; ++x) {
247 for(y = 1; y < grid_h; ++y) {
270 char *tmp = strtok_r(*
fmt,
":", save_ptr);
277 if ((tmp = strtok_r(NULL,
":", save_ptr)) == NULL) {
284 fprintf(stderr,
"Wrong dimensions for testcard.\n");
288 if ((tmp = strtok_r(NULL,
":", save_ptr)) == NULL) {
296 if ((tmp = strtok_r(NULL,
":", save_ptr)) == NULL) {
316 unsigned char *data = NULL;
317 if (
pam_read(filename, &info, &data, malloc) == 0) {
320 switch (info.depth) {
334 *in_file_contents = (
char *) malloc(data_len);
336 uint16_t *in = (uint16_t *)(
void *) data;
337 uint16_t *out = (uint16_t *)(
void *) *in_file_contents;
338 for (
size_t i = 0; i < (size_t) info.width * info.height * 3; ++i) {
339 *out++ = ntohs(*in++) * ((1<<16U) / (info.maxval + 1));
342 memcpy(*in_file_contents, data, data_len);
350 unsigned char *data = NULL;
351 if (
y4m_read(filename, &info, &data, malloc) == 0) {
354 if (info.bitdepth <
DEPTH8 ||
357 MSG(ERROR,
"Only 3-channel 8+ bit Y4M is supported.\n");
365 unsigned char *converted = malloc(data_len);
367 switch (info.subsampling) {
369 if (info.bitdepth ==
DEPTH8) {
374 data, converted, info.bitdepth);
378 if (info.bitdepth ==
DEPTH8) {
383 data, converted, info.bitdepth);
387 if (info.bitdepth ==
DEPTH8) {
392 data, converted, info.bitdepth);
396 MSG(ERROR,
"Wrong Y4M subsampling: %d", info.subsampling);
400 *in_file_contents = (
char *) converted;
408 }
else if (
ends_with(filename,
".y4m")) {
416 *in_file_contents = (
char *) malloc(data_len);
417 FILE *in = fopen(filename,
"r");
422 fseek(in, 0L, SEEK_END);
423 long filesize = ftell(in);
424 if (filesize == -1) {
428 fseek(in, 0L, SEEK_SET);
431 if (data_len != filesize) {
434 "and codec. File size %ld, computed size %ld\n", filesize, data_len);
441 if (fread(*in_file_contents, filesize, 1, in) != 1) {
449 free(*in_file_contents);
450 *in_file_contents = NULL;
456 printf(
"testcard options:\n");
457 color_printf(
TBOLD(
TRED(
"\t-t testcard")
"[:size=<width>x<height>][:fps=<fps>][:codec=<codec>]")
"[:file=<filename>][:p][:s=<X>x<Y>][:i|:sf][:still][:pattern=<pattern>] " TBOLD(
"| -t testcard:[full]help\n"));
461 color_printf(
TBOLD(
"\t file ")
" - use file for input data instead of predefined pattern\n"
462 "\t (raw or PAM/PNM/Y4M)\n");
463 color_printf(
TBOLD(
"\t fps ")
" - frames per second (with optional 'i' suffix for interlaced)\n");
465 color_printf(
TBOLD(
"\t mode ")
" - use specified mode (use 'mode=help' for list)\n");
468 color_printf(
TBOLD(
"\t s ")
" - split the frames into XxY separate tiles (currently defunct)\n");
473 "frames to capture\n");
484 color_printf(
TBOLD(
"Note:")
" only certain codec and generator combinations produce full-depth samples (not up-sampled 8-bit), use " TBOLD(
"pattern=help")
" for details.\n");
498 "Audio frequency must be positive, given: %d\n",
508 char *filename = NULL;
509 const char *strip_fmt = NULL;
510 char *save_ptr = NULL;
513 char *in_file_contents = NULL;
514 size_t in_file_contents_size = 0;
521 if ((s = calloc(1,
sizeof *s)) == NULL) {
533 if (strlen(ptr) > 0 && isdigit(ptr[0])) {
537 tmp = strtok_r(ptr,
":", &save_ptr);
539 if (strcmp(tmp,
"p") == 0) {
541 }
else if (strcmp(tmp,
"i") == 0) {
544 }
else if (strcmp(tmp,
"sf") == 0) {
546 log_msg(
LOG_LEVEL_WARNING,
"[testcard] Deprecated 'sf' option. Use format testcard:1920:1080:25sf:UYVY instead!\n");
547 }
else if (strcmp(tmp,
"still") == 0) {
550 const char *
pattern = strchr(tmp,
'=') + 1;
563 if (!strncmp(tmp,
"s=", 2)) {
564 MSG(WARNING,
"parameter s= denotes now size "
567 tmp = strchr(tmp,
'=') + 1;
568 if (isdigit(tmp[0]) && strchr(tmp,
'x') != NULL) {
578 strip_fmt = strchr(tmp,
'=') + 1;
584 filename = strchr(tmp,
'=') + 1;
585 }
else if (strstr(tmp,
"afrequency=") == tmp) {
589 strtoll(strchr(tmp,
'=') + 1, NULL, 0);
591 fprintf(stderr,
"[testcard] Unknown option: %s\n", tmp);
594 tmp = strtok_r(NULL,
":", &save_ptr);
623 if (in_file_contents_size > 0) {
632 if (strip_fmt != NULL) {
633 log_msg(
LOG_LEVEL_ERROR,
"Multi-tile testcard (stripping) is currently broken, you can use eg. \"-t aggregate -t testcard[args] -t testcard[args]\" instead!\n");
636 if(configure_tiling(s, strip_fmt) != 0) {
653 free(in_file_contents);
661 free(in_file_contents);
710 if (
state->video_frames + 1 ==
state->capture_frames) {
716 }
while ((
double) (curr_time -
state->last_frame_time) /
NS_IN_SEC <
717 1.0 /
state->frame->fps);
719 state->frame->timestamp =
732 for (i = 0; i <
count; ++i) {
735 state->tiled->tiles[i].width,
state->tiled->color_spec);
739 if(
state->tiled->tiles[i].data >=
state->tiles_data[i] +
740 state->tiled->tiles[i].data_len *
state->tiles_cnt_vertical) {
741 state->tiled->tiles[i].data =
state->tiles_data[i];
748 state->video_frames += 1;
759 snprintf(card->
name,
sizeof card->
name,
"Testing signal");
769 int framerates[] = {24, 30, 60};
770 const char *
const pix_fmts[] = {
"UYVY",
"RGB"};
782 for (
const char *
const *pix_fmt = pix_fmts; pix_fmt != pix_fmts +
sizeof pix_fmts /
sizeof pix_fmts[0]; pix_fmt++) {
783 for (
const struct size *size = sizes; size != sizes +
sizeof sizes /
sizeof sizes[0]; size++) {
784 for (
const int *fps = framerates; fps != framerates +
sizeof framerates /
sizeof framerates[0]; fps++) {
788 size->width, size->height,
792 "{\"width\":\"%d\", "
793 "\"height\":\"%d\", "
794 "\"format\":\"%s\", "
796 size->width, size->height,
802 dev_add_option(card,
"Still",
"Send still image",
"still",
":still",
true);
803 dev_add_option(card,
"Pattern",
"Pattern to use",
"pattern",
":pattern=",
false);
struct audio_frame ** audio
int void(** deleter)(void *))
struct video_frame * vf_alloc(int count)
Allocates blank video frame.
void vf_free(struct video_frame *buf)
Frees video_frame structure.
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.
const char * get_codec_name(codec_t codec)
codec_t get_codec_from_name(const char *name)
#define DEFAULT_AUDIO_BPS
This file contains definition of some common audio types.
#define STORE_I32_SAMPLE(ptr, val, out_bps)
stores given int32_t sample at required out_bps
int color_printf(const char *format,...)
static __device__ vec3 round(const vec3 &v)
void log_msg(int level, const char *format,...)
#define LOG_LEVEL_INFO
normal reporting
#define LOG_LEVEL_ERROR
general errors
#define LOG_LEVEL_WARNING
less severe errors
#define VIDCAP_INIT_NOERR
state not initialized, other action performed (typically help)
#define VIDCAP_INIT_OK
initialization successful
#define VIDEO_CAPTURE_ABI_VERSION
#define VIDCAP_INIT_FAIL
error ocured
unsigned int audio_capture_bps
unsigned int audio_capture_sample_rate
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)
int get_framerate_d(double fps)
int get_framerate_n(double fps)
const char * ug_strerror(int errnum)
bool pam_read(const char *filename, struct pam_metadata *info, unsigned char **data, void *(*allocator)(size_t))
bool ends_with(const char *haystick, const char *needle)
struct used to comunicate with audio capture/playback device
char name[1024]
human readable name of the mode
char id[1024]
< optional zero-terminated array of available modes
char name[1024]
human readable name of the device
struct device_info::mode modes[512]
struct video_frame * tiled
video_pattern_generator_t generator
time_ns_t last_frame_time
struct audio_len_pattern apattern
struct video_frame * frame
Struct tile is an area of video_frame.
char * data
Raw tile data. Pointer must be at least 4B aligned.
unsigned int data_len
length of the data
enum interlacing_t interlacing
unsigned int width
width of every tile (!)
unsigned int height
height of every tile (!)
Struct video_frame represents a video frame and contains video description.
enum interlacing_t interlacing
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
void testcard_show_codec_help(const char *name, bool src_8b_only)
bool testcard_has_conversion(codec_t c)
static time_ns_t get_time_in_ns()
This file contains some common data types.
@ TIMESTAMP_VALID
timestamp set by source (in 90 kHz clock)
void dev_add_option(struct device_info *dev, const char *name, const char *desc, const char *key, const char *opt_str, bool is_boolean)
@ SEGMENTED_FRAME
Segmented frame. Contains the same data as progressive frame.
@ INTERLACED_MERGED
Columngs of both fields are interlaced together.
@ RGB
RGB 8-bit (packed into 24-bit word)
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
@ VIDEO_CODEC_NONE
dummy color spec
@ RG48
16-bit RGB little-endian (RlRhGl...)
@ Y416
interleaved little-endian YCbCr 4444 16-bit - UYVA
@ RGBA
RGBA 8-bit, big-endian.
void vf_split(struct video_frame *out, struct video_frame *src, unsigned int x_count, unsigned int y_count, int preallocate)
const char * video_desc_to_string(struct video_desc d)
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.
static const struct video_capture_info vidcap_testcard_info
static void generate_audio_sine(struct testcard_state *s)
static const int alen_pattern_5994[]
static struct video_desc parse_format(char **fmt, char **save_ptr)
static bool configure_audio(struct testcard_state *s)
static int vidcap_testcard_init(struct vidcap_params *params, void **state)
#define AUDIO_BUFFER_SAMPLES
static size_t testcard_load_from_file_y4m(const char *filename, struct video_desc *desc, char **in_file_contents)
static const int alen_pattern_2997[]
static size_t testcard_load_from_file(const char *filename, struct video_desc *desc, char **in_file_contents, bool deduce_pixfmt)
static size_t testcard_load_from_file_pam(const char *filename, struct video_desc *desc, char **in_file_contents)
@ DEFAULT_AUIDIO_FREQUENCY
static void vidcap_testcard_probe(struct device_info **available_devices, int *count, void(**deleter)(void *))
static bool validate_settings(struct testcard_state *s, struct video_desc desc)
static const int alen_pattern_11988[]
static audio_frame * vidcap_testcard_get_audio(struct testcard_state *s)
static struct video_frame * vidcap_testcard_grab(void *arg, struct audio_frame **audio)
static void vidcap_testcard_done(void *state)
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_ANY
void i420_8_to_uyvy(int width, int height, const unsigned char *in, unsigned char *out)
void i444_8_to_uyvy(int width, int height, const unsigned char *in, unsigned char *out)
void i422_16_to_y416(int width, int height, const unsigned char *in, unsigned char *out, int in_depth)
void i420_16_to_y416(int width, int height, const unsigned char *in, unsigned char *out, int in_depth)
void i422_8_to_uyvy(int width, int height, const unsigned char *in, unsigned char *out)
bool codec_is_planar(codec_t codec)
size_t vc_get_datalen(unsigned int width, unsigned int height, codec_t codec)
int get_bits_per_component(codec_t codec)
codec_t get_codec_from_file_extension(const char *ext)
void i444_16_to_y416(int width, int height, const unsigned char *in, unsigned char *out, int in_depth)
struct tile * vf_get_tile(struct video_frame *buf, int pos)
Returns pointer to n-th tile from video frame Equivalent to &video_frame::tiles[pos].
void video_pattern_generator_fill_data(video_pattern_generator_t s, const char *data)
char * video_pattern_generator_next_frame(video_pattern_generator_t s)
video_pattern_generator_t video_pattern_generator_create(const char *config, int width, int height, codec_t color_spec, int offset)
void video_pattern_generator_destroy(video_pattern_generator_t s)
size_t y4m_read(const char *filename, struct y4m_metadata *info, unsigned char **data, void *(*allocator)(size_t))