std::string dumpStyle(const TextStyle& s, bool onlydiff) { TextStyle def; std::stringstream stream; if (!onlydiff || def.hAlign != s.hAlign) stream << "hAlign=" << get_halign(s.hAlign); if (!onlydiff || def.vAlign != s.vAlign) stream << " vAlign=" << get_valign(s.vAlign); if (!onlydiff || def.multiline != s.multiline) stream << " " << (s.multiline ? "multiline" : "singleline"); if (!onlydiff || def.breakLongWords != s.breakLongWords) stream << " " << (s.breakLongWords ? "breakLongWords=1" : "breakLongWords=0"); if (!onlydiff || def.kerning != s.kerning) stream << " kerning=" << s.kerning; if (!onlydiff || def.linesOffset != s.linesOffset) stream << " linesOffset=" << s.linesOffset; if (!onlydiff || def.fontSize != s.fontSize) stream << " fontSize=" << s.fontSize; if (!onlydiff || def.outline != s.outline) stream << " outline=" << s.outline; if (s.font) { stream << " font='" << s.font->getName() << "'"; } return stream.str(); }
static int vidcap_testcard_init(const struct vidcap_params *params, void **state) { struct testcard_state *s; char *filename; const char *strip_fmt = NULL; FILE *in = NULL; unsigned int i, j; unsigned int rect_size = COL_NUM; codec_t codec = RGBA; int aligned_x; char *save_ptr = NULL; if (vidcap_params_get_fmt(params) == NULL || strcmp(vidcap_params_get_fmt(params), "help") == 0) { printf("testcard options:\n"); printf("\t-t testcard:<width>:<height>:<fps>:<codec>[:filename=<filename>][:p][:s=<X>x<Y>][:i|:sf][:still][:pattern=bars|blank|noise]\n"); printf("\t<filename> - use file named filename instead of default bars\n"); printf("\tp - pan with frame\n"); printf("\ts - split the frames into XxY separate tiles\n"); printf("\ti|sf - send as interlaced or segmented frame (if none of those is set, progressive is assumed)\n"); printf("\tstill - send still image\n"); printf("\tpattern - pattern to use\n"); show_codec_help("testcard", codecs_8b, codecs_10b); return VIDCAP_INIT_NOERR; } s = new testcard_state(); if (!s) return VIDCAP_INIT_FAIL; s->frame = vf_alloc(1); char *fmt = strdup(vidcap_params_get_fmt(params)); char *tmp; int h_align = 0; double bpp = 0; if (strlen(fmt) == 0) { free(fmt); fmt = strdup(DEFAULT_FORMAT); } tmp = strtok_r(fmt, ":", &save_ptr); if (!tmp) { fprintf(stderr, "Wrong format for testcard '%s'\n", fmt); goto error; } vf_get_tile(s->frame, 0)->width = atoi(tmp); tmp = strtok_r(NULL, ":", &save_ptr); if (!tmp) { fprintf(stderr, "Wrong format for testcard '%s'\n", fmt); goto error; } vf_get_tile(s->frame, 0)->height = atoi(tmp); tmp = strtok_r(NULL, ":", &save_ptr); if (!tmp) { fprintf(stderr, "Wrong format for testcard '%s'\n", fmt); goto error; } s->frame->fps = atof(tmp); tmp = strtok_r(NULL, ":", &save_ptr); if (!tmp) { fprintf(stderr, "Wrong format for testcard '%s'\n", fmt); goto error; } codec = get_codec_from_name(tmp); if (codec == VIDEO_CODEC_NONE) { fprintf(stderr, "Unknown codec '%s'\n", tmp); goto error; } { const codec_t *sets[] = {codecs_8b, codecs_10b}; bool supported = false; for (int i = 0; i < 2; ++i) { const codec_t *it = sets[i]; while (*it != VIDEO_CODEC_NONE) { if (codec == *it++) { supported = true; } } } if (!supported) { log_msg(LOG_LEVEL_ERROR, "Unsupported codec '%s'\n", tmp); goto error; } } h_align = get_halign(codec); bpp = get_bpp(codec); s->frame->color_spec = codec; s->still_image = FALSE; if(bpp == 0) { fprintf(stderr, "Unsupported codec '%s'\n", tmp); goto error; } aligned_x = vf_get_tile(s->frame, 0)->width; if (h_align) { aligned_x = (aligned_x + h_align - 1) / h_align * h_align; } rect_size = (vf_get_tile(s->frame, 0)->width + rect_size - 1) / rect_size; s->frame_linesize = aligned_x * bpp; s->frame->interlacing = PROGRESSIVE; s->size = aligned_x * vf_get_tile(s->frame, 0)->height * bpp; filename = NULL; tmp = strtok_r(NULL, ":", &save_ptr); while (tmp) { if (strcmp(tmp, "p") == 0) { s->pan = 48; } else if (strncmp(tmp, "filename=", strlen("filename=")) == 0) { filename = tmp + strlen("filename="); in = fopen(filename, "r"); if (!in) { perror("fopen"); goto error; } fseek(in, 0L, SEEK_END); long filesize = ftell(in); assert(filesize >= 0); fseek(in, 0L, SEEK_SET); s->data = (char *) malloc(s->size * bpp * 2); if (s->size != filesize) { fprintf(stderr, "Error wrong file size for selected " "resolution and codec. File size %ld, " "computed size %d\n", filesize, s->size); goto error; } if (!in || fread(s->data, filesize, 1, in) == 0) { fprintf(stderr, "Cannot read file %s\n", filename); goto error; } fclose(in); in = NULL; memcpy(s->data + s->size, s->data, s->size); vf_get_tile(s->frame, 0)->data = s->data; } else if (strncmp(tmp, "s=", 2) == 0) { strip_fmt = tmp; } else if (strcmp(tmp, "i") == 0) { s->frame->interlacing = INTERLACED_MERGED; } else if (strcmp(tmp, "sf") == 0) { s->frame->interlacing = SEGMENTED_FRAME; } else if (strcmp(tmp, "still") == 0) { s->still_image = TRUE; } else if (strncmp(tmp, "pattern=", strlen("pattern=")) == 0) { const char *pattern = tmp + strlen("pattern="); if (strcmp(pattern, "bars") == 0) { s->pattern = image_pattern::BARS; } else if (strcmp(pattern, "blank") == 0) { s->pattern = image_pattern::BLANK; } else if (strcmp(pattern, "noise") == 0) { s->pattern = image_pattern::NOISE; } else { fprintf(stderr, "[testcard] Unknown pattern!\n");; goto error; } } else { fprintf(stderr, "[testcard] Unknown option: %s\n", tmp); goto error; } tmp = strtok_r(NULL, ":", &save_ptr); } if (!filename) { struct testcard_rect r; int col_num = 0; s->pixmap.w = aligned_x; s->pixmap.h = vf_get_tile(s->frame, 0)->height * 2; int pixmap_len = s->pixmap.w * s->pixmap.h * 4; // maximal size (RGBA/r10k - has 4 bpp) s->pixmap.data = malloc(pixmap_len); if (s->pattern == image_pattern::BLANK) { memset(s->pixmap.data, 0, pixmap_len); } else if (s->pattern == image_pattern::NOISE) { uint8_t *sample = (uint8_t *) s->pixmap.data; for (int i = 0; i < pixmap_len; ++i) { *sample++ = rand() % 0xff; } } else { assert (s->pattern == image_pattern::BARS); for (j = 0; j < vf_get_tile(s->frame, 0)->height; j += rect_size) { int grey = 0xff010101; if (j == rect_size * 2) { r.w = vf_get_tile(s->frame, 0)->width; r.h = rect_size / 4; r.x = 0; r.y = j; testcard_fillRect(&s->pixmap, &r, 0xffffffff); r.h = rect_size - (rect_size * 3 / 4); r.y = j + rect_size * 3 / 4; testcard_fillRect(&s->pixmap, &r, 0xff000000); } for (i = 0; i < vf_get_tile(s->frame, 0)->width; i += rect_size) { r.w = rect_size; r.h = rect_size; r.x = i; r.y = j; printf("Fill rect at %d,%d\n", r.x, r.y); if (j != rect_size * 2) { testcard_fillRect(&s->pixmap, &r, rect_colors[col_num]); col_num = (col_num + 1) % COL_NUM; } else { r.h = rect_size / 2; r.y += rect_size / 4; testcard_fillRect(&s->pixmap, &r, grey); grey += 0x00010101 * (255 / COL_NUM); } } } } s->data = (char *) s->pixmap.data; if (codec == UYVY || codec == v210) { rgb2yuv422((unsigned char *) s->data, aligned_x, vf_get_tile(s->frame, 0)->height); } if (codec == v210) { s->data = (char *)tov210((unsigned char *) s->data, aligned_x, aligned_x, vf_get_tile(s->frame, 0)->height, bpp); free(s->pixmap.data); } if (codec == R10k) { toR10k((unsigned char *) s->data, vf_get_tile(s->frame, 0)->width, vf_get_tile(s->frame, 0)->height); } if(codec == RGB) { s->data = (char *)toRGB((unsigned char *) s->data, vf_get_tile(s->frame, 0)->width, vf_get_tile(s->frame, 0)->height); free(s->pixmap.data); } tmp = filename; vf_get_tile(s->frame, 0)->data = (char *) malloc(2 * s->size); memcpy(vf_get_tile(s->frame, 0)->data, s->data, s->size); memcpy(vf_get_tile(s->frame, 0)->data + s->size, vf_get_tile(s->frame, 0)->data, s->size); free(s->data); s->data = vf_get_tile(s->frame, 0)->data; } s->count = 0; s->last_frame_time = std::chrono::steady_clock::now(); printf("Testcard capture set to %dx%d, bpp %f\n", vf_get_tile(s->frame, 0)->width, vf_get_tile(s->frame, 0)->height, bpp); vf_get_tile(s->frame, 0)->data_len = s->size; if(strip_fmt != NULL) { if(configure_tiling(s, strip_fmt) != 0) { goto error; } } if(vidcap_params_get_flags(params) & VIDCAP_FLAG_AUDIO_EMBEDDED) { s->grab_audio = TRUE; if(configure_audio(s) != 0) { s->grab_audio = FALSE; fprintf(stderr, "[testcard] Disabling audio output. " "SDL-mixer missing, running on Mac or other problem.\n"); } } else { s->grab_audio = FALSE; } free(fmt); *state = s; return VIDCAP_INIT_OK; error: free(fmt); free(s->data); vf_free(s->frame); if (in) fclose(in); delete s; return VIDCAP_INIT_FAIL; }