/** * Compresses video frame with tiles API * * @param[in] s compress state * @param[in] frame uncompressed frame * @param buffer_index 0 or 1 - driver should have 2 output buffers, filling the selected one. * Returned video frame should stay valid until requesting compress with the * same index. * @param parent parent module (for the case when there is a need to reconfigure) * @return compressed video frame, may be NULL if compression failed */ static struct video_frame *compress_frame_tiles(struct compress_state_real *s, struct video_frame *frame, int buffer_index, struct module *parent) { if(frame->tile_count != s->state_count) { s->state = realloc(s->state, frame->tile_count * sizeof(struct module *)); for(unsigned int i = s->state_count; i < frame->tile_count; ++i) { char compress_options[1024]; strncpy(compress_options, s->compress_options, sizeof(compress_options)); compress_options[sizeof(compress_options) - 1] = '\0'; s->state[i] = s->handle->init_func(parent, compress_options); if(!s->state[i]) { fprintf(stderr, "Compression initialization failed\n"); return NULL; } } for(int i = 0; i < 2; ++i) { vf_free(s->out_frame[i]); s->out_frame[i] = vf_alloc(frame->tile_count); } s->state_count = frame->tile_count; } task_result_handle_t task_handle[frame->tile_count]; struct compress_worker_data data_tile[frame->tile_count]; for(unsigned int i = 0; i < frame->tile_count; ++i) { struct compress_worker_data *data = &data_tile[i]; data->state = s->state[i]; data->tile = &frame->tiles[i]; data->desc = video_desc_from_frame(frame); data->desc.tile_count = 1; data->buffer_index = buffer_index;; data->callback = s->handle->compress_tile_func; task_handle[i] = task_run_async(compress_tile_callback, data); } for(unsigned int i = 0; i < frame->tile_count; ++i) { struct compress_worker_data *data = wait_task(task_handle[i]); if(i == 0) { // update metadata from first tile data->desc.tile_count = frame->tile_count; vf_write_desc(s->out_frame[buffer_index], data->desc); } if(data->ret) { memcpy(&s->out_frame[buffer_index]->tiles[i], data->ret, sizeof(struct tile)); } else { return NULL; } } return s->out_frame[buffer_index]; }
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; }
static int configure_tiling(struct testcard_state *s, const char *fmt) { char *tmp, *token, *saveptr = NULL; int tile_cnt; int x; int grid_w, grid_h; if(fmt[1] != '=') return 1; tmp = strdup(&fmt[2]); token = strtok_r(tmp, "x", &saveptr); grid_w = atoi(token); token = strtok_r(NULL, "x", &saveptr); grid_h = atoi(token); free(tmp); s->tiled = vf_alloc(grid_w * grid_h); s->tiles_cnt_horizontal = grid_w; s->tiles_cnt_vertical = grid_h; s->tiled->color_spec = s->frame->color_spec; s->tiled->fps = s->frame->fps; s->tiled->interlacing = s->frame->interlacing; tile_cnt = grid_w * grid_h; assert(tile_cnt >= 1); s->tiles_data = (char **) malloc(tile_cnt * sizeof(char *)); /* split only horizontally!!!!!! */ vf_split(s->tiled, s->frame, grid_w, 1, 1 /*prealloc*/); /* for each row, make the tile data correct. * .data pointers of same row point to same block, * but different row */ for(x = 0; x < grid_w; ++x) { int y; s->tiles_data[x] = s->tiled->tiles[x].data; s->tiled->tiles[x].width = s->frame->tiles[0].width/ grid_w; s->tiled->tiles[x].height = s->frame->tiles[0].height / grid_h; s->tiled->tiles[x].data_len = s->frame->tiles[0].data_len / (grid_w * grid_h); s->tiled->tiles[x].data = s->tiles_data[x] = (char *) realloc(s->tiled->tiles[x].data, s->tiled->tiles[x].data_len * grid_h * 2); memcpy(s->tiled->tiles[x].data + s->tiled->tiles[x].data_len * grid_h, s->tiled->tiles[x].data, s->tiled->tiles[x].data_len * grid_h); /* recopy tiles vertically */ for(y = 1; y < grid_h; ++y) { memcpy(&s->tiled->tiles[y * grid_w + x], &s->tiled->tiles[x], sizeof(struct tile)); /* make the pointers correct */ s->tiles_data[y * grid_w + x] = s->tiles_data[x] + y * s->tiled->tiles[x].height * vc_get_linesize(s->tiled->tiles[x].width, s->tiled->color_spec); s->tiled->tiles[y * grid_w + x].data = s->tiles_data[x] + y * s->tiled->tiles[x].height * vc_get_linesize(s->tiled->tiles[x].width, s->tiled->color_spec); } } return 0; }
static int configure_with(struct state_video_compress_rtdxt *s, struct video_frame *frame) { unsigned int x; enum dxt_format format; int i; for (i = 0; i < 2; ++i) { s->out[i] = vf_alloc(frame->tile_count); } for (x = 0; x < frame->tile_count; ++x) { if (vf_get_tile(frame, x)->width != vf_get_tile(frame, 0)->width || vf_get_tile(frame, x)->width != vf_get_tile(frame, 0)->width) { fprintf(stderr,"[RTDXT] Requested to compress tiles of different size!"); //exit_uv(128); return FALSE; } } for (i = 0; i < 2; ++i) { s->out[i]->fps = frame->fps; s->out[i]->color_spec = s->color_spec; for (x = 0; x < frame->tile_count; ++x) { vf_get_tile(s->out[i], x)->width = vf_get_tile(frame, 0)->width; vf_get_tile(s->out[i], x)->height = vf_get_tile(frame, 0)->height; } } switch (frame->color_spec) { case RGB: s->decoder = (decoder_t) memcpy; format = DXT_FORMAT_RGB; break; case RGBA: s->decoder = (decoder_t) memcpy; format = DXT_FORMAT_RGBA; break; case R10k: s->decoder = (decoder_t) vc_copyliner10k; format = DXT_FORMAT_RGBA; break; case YUYV: s->decoder = (decoder_t) vc_copylineYUYV; format = DXT_FORMAT_YUV422; break; case UYVY: case Vuy2: case DVS8: s->decoder = (decoder_t) memcpy; format = DXT_FORMAT_YUV422; break; case v210: s->decoder = (decoder_t) vc_copylinev210; format = DXT_FORMAT_YUV422; break; case DVS10: s->decoder = (decoder_t) vc_copylineDVS10; format = DXT_FORMAT_YUV422; break; case DPX10: s->decoder = (decoder_t) vc_copylineDPX10toRGBA; format = DXT_FORMAT_RGBA; break; default: fprintf(stderr, "[RTDXT] Unknown codec: %d\n", frame->color_spec); //exit_uv(128); return FALSE; } /* We will deinterlace the output frame */ if(frame->interlacing == INTERLACED_MERGED) { for (i = 0; i < 2; ++i) { s->out[i]->interlacing = PROGRESSIVE; } s->interlaced_input = TRUE; fprintf(stderr, "[DXT compress] Enabling automatic deinterlacing.\n"); } else { for (i = 0; i < 2; ++i) { s->out[i]->interlacing = frame->interlacing; } s->interlaced_input = FALSE; } int data_len = 0; s->encoder = malloc(frame->tile_count * sizeof(struct dxt_encoder *)); if(s->out[0]->color_spec == DXT1) { for(int i = 0; i < (int) frame->tile_count; ++i) { s->encoder[i] = dxt_encoder_create(DXT_TYPE_DXT1, s->out[0]->tiles[0].width, s->out[0]->tiles[0].height, format, s->gl_context.legacy); } data_len = dxt_get_size(s->out[0]->tiles[0].width, s->out[0]->tiles[0].height, DXT_TYPE_DXT1); } else if(s->out[0]->color_spec == DXT5){ for(int i = 0; i < (int) frame->tile_count; ++i) { s->encoder[i] = dxt_encoder_create(DXT_TYPE_DXT5_YCOCG, s->out[0]->tiles[0].width, s->out[0]->tiles[0].height, format, s->gl_context.legacy); } data_len = dxt_get_size(s->out[0]->tiles[0].width, s->out[0]->tiles[0].height, DXT_TYPE_DXT5_YCOCG); } for(int i = 0; i < (int) frame->tile_count; ++i) { if(s->encoder[i] == NULL) { fprintf(stderr, "[RTDXT] Unable to create decoder.\n"); //exit_uv(128); return FALSE; } } s->encoder_input_linesize = s->out[0]->tiles[0].width; switch(format) { case DXT_FORMAT_RGBA: s->encoder_input_linesize *= 4; break; case DXT_FORMAT_RGB: s->encoder_input_linesize *= 3; break; case DXT_FORMAT_YUV422: s->encoder_input_linesize *= 2; break; case DXT_FORMAT_YUV: /* not used - just not compilator to complain */ abort(); break; } assert(data_len > 0); assert(s->encoder_input_linesize > 0); for (i = 0; i < 2; ++i) { for (x = 0; x < frame->tile_count; ++x) { vf_get_tile(s->out[i], x)->data_len = data_len; vf_get_tile(s->out[i], x)->data = (char *) malloc(data_len); } } s->decoded = malloc(4 * s->out[0]->tiles[0].width * s->out[0]->tiles[0].height); s->configured = TRUE; return TRUE; }
void * vidcap_aggregate_init(char *init_fmt, unsigned int flags) { struct vidcap_aggregate_state *s; char *save_ptr = NULL; char *item; char *parse_string; char *tmp; int i; printf("vidcap_aggregate_init\n"); s = (struct vidcap_aggregate_state *) calloc(1, sizeof(struct vidcap_aggregate_state)); if(s == NULL) { printf("Unable to allocate aggregate capture state\n"); return NULL; } s->frames = 0; gettimeofday(&s->t0, NULL); if(!init_fmt || strcmp(init_fmt, "help") == 0) { show_help(); return NULL; } s->devices_cnt = 0; tmp = parse_string = strdup(init_fmt); while(strtok_r(tmp, "#", &save_ptr)) { s->devices_cnt++; tmp = NULL; } free(parse_string); s->devices = calloc(1, s->devices_cnt * sizeof(struct vidcap *)); i = 0; tmp = parse_string = strdup(init_fmt); while((item = strtok_r(tmp, "#", &save_ptr))) { char *device; char *config = strdup(item); char *save_ptr_dev = NULL; char *device_cfg; unsigned int dev_flags = 0u; device = strtok_r(config, ":", &save_ptr_dev); device_cfg = save_ptr_dev; if(i == 0) { dev_flags = flags; } else { // do not grab from second and other devices dev_flags = flags & ~(VIDCAP_FLAG_AUDIO_EMBEDDED | VIDCAP_FLAG_AUDIO_AESEBU | VIDCAP_FLAG_AUDIO_ANALOG); } s->devices[i] = initialize_video_capture(device, device_cfg, dev_flags); free(config); if(!s->devices[i]) { fprintf(stderr, "[aggregate] Unable to initialize device %d (%s:%s).\n", i, device, device_cfg); goto error; } ++i; tmp = NULL; } free(parse_string); s->frame = vf_alloc(s->devices_cnt); return s; error: if(s->devices) { int i; for (i = 0u; i < s->devices_cnt; ++i) { if(s->devices[i]) { vidcap_done(s->devices[i]); } } } free(s); return NULL; }
static void *display_sage_init(struct module *parent, const char *fmt, unsigned int flags) { UNUSED(fmt); UNUSED(flags); UNUSED(parent); struct state_sage *s; s = (struct state_sage *) calloc(1, sizeof(struct state_sage)); assert(s != NULL); s->confName = NULL; if(fmt) { if(strcmp(fmt, "help") == 0) { printf("SAGE usage:\n"); printf("\tuv -t sage[:config=<config_file>|:fs=<fsIP>][:codec=<fcc>][:d]\n"); printf("\t <config_file> - SAGE app config file, default \"ultragrid.conf\"\n"); printf("\t <fsIP> - FS manager IP address\n"); printf("\t <fcc> - FourCC of codec that will be used to transmit to SAGE\n"); printf("\t Supported options are UYVY, RGBA, RGB or DXT1\n"); printf("\t d - deinterlace output\n"); return &display_init_noerr; } else { char *tmp, *parse_str; tmp = parse_str = strdup(fmt); char *save_ptr = NULL; char *item; while((item = strtok_r(parse_str, ":", &save_ptr))) { parse_str = NULL; if(strncmp(item, "config=", strlen("config=")) == 0) { s->confName = item + strlen("config="); } else if(strncmp(item, "codec=", strlen("codec=")) == 0) { uint32_t fourcc; if(strlen(item + strlen("codec=")) != sizeof(fourcc)) { fprintf(stderr, "Malformed FourCC code (wrong length).\n"); free(s); return NULL; } memcpy((void *) &fourcc, item + strlen("codec="), sizeof(fourcc)); s->requestedDisplayCodec = get_codec_from_fcc(fourcc); if(s->requestedDisplayCodec == VIDEO_CODEC_NONE) { fprintf(stderr, "Codec not found according to FourCC.\n"); free(s); return NULL; } if(s->requestedDisplayCodec != UYVY && s->requestedDisplayCodec != RGBA && s->requestedDisplayCodec != RGB && s->requestedDisplayCodec != DXT1 #ifdef SAGE_NATIVE_DXT5YCOCG && s->requestedDisplayCodec != DXT5 #endif // SAGE_NATIVE_DXT5YCOCG ) { fprintf(stderr, "Entered codec is not nativelly supported by SAGE.\n"); free(s); return NULL; } } else if(strcmp(item, "tx") == 0) { s->is_tx = true; } else if(strncmp(item, "fs=", strlen("fs=")) == 0) { s->fsIP = item + strlen("fs="); } else if(strcmp(item, "d") == 0) { s->deinterlace = true; } else { fprintf(stderr, "[SAGE] unrecognized configuration: %s\n", item); free(s); return NULL; } } free(tmp); } } if (!s->is_tx) { // read config file only if we are in dispaly mode (not sender mode) struct stat sb; if(s->confName) { if(stat(s->confName, &sb)) { perror("Unable to use SAGE config file"); free(s); return NULL; } } else if(stat("ultragrid.conf", &sb) == 0) { s->confName = "ultragrid.conf"; } if(s->confName) { printf("[SAGE] Using config file %s.\n", s->confName); } } if(s->confName == NULL && s->fsIP == NULL) { fprintf(stderr, "[SAGE] Unable to locate FS manager address. " "Set either in config file or from command line.\n"); free(s); return NULL; } s->magic = MAGIC_SAGE; gettimeofday(&s->t0, NULL); s->frames = 0; s->frame = vf_alloc(1); s->tile = vf_get_tile(s->frame, 0); /* sage init */ //FIXME sem se musi propasovat ty spravne parametry argc argv s->appID = 0; s->nodeID = 1; s->sage_state = NULL; /* thread init */ sem_init(&s->semaphore, 0, 0); s->buffer_writable = 1; s->grab_waiting = 1; pthread_mutex_init(&s->buffer_writable_lock, 0); pthread_cond_init(&s->buffer_writable_cond, NULL); /*if (pthread_create (&(s->thread_id), NULL, display_thread_sage, (void *)s) != 0) { perror("Unable to create display thread\n"); return NULL; }*/ debug_msg("Window initialized %p\n", s); return (void *)s; }
static int vidcap_aggregate_init(const struct vidcap_params *params, void **state) { struct vidcap_aggregate_state *s; printf("vidcap_aggregate_init\n"); s = (struct vidcap_aggregate_state *) calloc(1, sizeof(struct vidcap_aggregate_state)); if(s == NULL) { printf("Unable to allocate aggregate capture state\n"); return VIDCAP_INIT_FAIL; } s->audio_source_index = -1; s->frames = 0; gettimeofday(&s->t0, NULL); if(vidcap_params_get_fmt(params) && strcmp(vidcap_params_get_fmt(params), "") != 0) { show_help(); free(s); return VIDCAP_INIT_NOERR; } s->devices_cnt = 0; const struct vidcap_params *tmp = params; while((tmp = vidcap_params_get_next(tmp))) { if (vidcap_params_get_driver(tmp) != NULL) s->devices_cnt++; else break; } s->devices = calloc(s->devices_cnt, sizeof(struct vidcap *)); tmp = params; for (int i = 0; i < s->devices_cnt; ++i) { tmp = vidcap_params_get_next(tmp); int ret = initialize_video_capture(NULL, (struct vidcap_params *) tmp, &s->devices[i]); if(ret != 0) { fprintf(stderr, "[aggregate] Unable to initialize device %d (%s:%s).\n", i, vidcap_params_get_driver(tmp), vidcap_params_get_fmt(tmp)); goto error; } } s->captured_frames = calloc(s->devices_cnt, sizeof(struct video_frame *)); s->frame = vf_alloc(s->devices_cnt); *state = s; return VIDCAP_INIT_OK; error: if(s->devices) { int i; for (i = 0u; i < s->devices_cnt; ++i) { if(s->devices[i]) { vidcap_done(s->devices[i]); } } } free(s); return VIDCAP_INIT_FAIL; }
/** * @brief This is compression initialization function that really does the stuff. * @param[in] parent parent module * @param[in] config_string configuration (in format <driver>:<options>) * @param[out] state created state * @retval 0 if state created sucessfully * @retval <0 if error occured * @retval >0 finished successfully, no state created (eg. displayed help) */ static int compress_init_real(struct module *parent, char *config_string, struct compress_state_real **state) { struct compress_state_real *s; char *compress_options = NULL; if(!config_string) return -1; if(strcmp(config_string, "help") == 0) { show_compress_help(); return 1; } pthread_once(&compression_list_initialized, init_compressions); s = (struct compress_state_real *) calloc(1, sizeof(struct compress_state_real)); s->state_count = 1; int i; for(i = 0; i < compress_modules_count; ++i) { if(strncasecmp(config_string, available_compress_modules[i]->name, strlen(available_compress_modules[i]->name)) == 0) { s->handle = available_compress_modules[i]; if(config_string[strlen(available_compress_modules[i]->name)] == ':') compress_options = config_string + strlen(available_compress_modules[i]->name) + 1; else compress_options = ""; } } if(!s->handle) { fprintf(stderr, "Unknown compression: %s\n", config_string); free(s); return -1; } strncpy(s->compress_options, compress_options, sizeof(s->compress_options) - 1); s->compress_options[sizeof(s->compress_options) - 1] = '\0'; if(s->handle->init_func) { s->state = calloc(1, sizeof(struct module *)); char compress_options[1024]; strncpy(compress_options, s->compress_options, sizeof(compress_options) - 1); compress_options[sizeof(compress_options) - 1] = '\0'; s->state[0] = s->handle->init_func(parent, compress_options); if(!s->state[0]) { fprintf(stderr, "Compression initialization failed: %s\n", config_string); free(s->state); free(s); return -1; } if(s->state[0] == &compress_init_noerr) { free(s->state); free(s); return 1; } for(int i = 0; i < 2; ++i) { s->out_frame[i] = vf_alloc(1); } } else { return -1; } *state = s; return 0; }
static int configure_with(struct state_video_compress_jpeg *s, struct video_frame *frame) { unsigned int x; int frame_idx; s->saved_desc.width = frame->tiles[0].width; s->saved_desc.height = frame->tiles[0].height; s->saved_desc.color_spec = frame->color_spec; s->saved_desc.fps = frame->fps; s->saved_desc.interlacing = frame->interlacing; s->saved_desc.tile_count = frame->tile_count; for (frame_idx = 0; frame_idx < 2; frame_idx++) { s->out[frame_idx] = vf_alloc(frame->tile_count); } for (x = 0; x < frame->tile_count; ++x) { if (vf_get_tile(frame, x)->width != vf_get_tile(frame, 0)->width || vf_get_tile(frame, x)->width != vf_get_tile(frame, 0)->width) { fprintf(stderr,"[JPEG] Requested to compress tiles of different size!"); //exit_uv(129); return FALSE; } } for (frame_idx = 0; frame_idx < 2; frame_idx++) { for (x = 0; x < frame->tile_count; ++x) { vf_get_tile(s->out[frame_idx], x)->width = vf_get_tile(frame, 0)->width; vf_get_tile(s->out[frame_idx], x)->height = vf_get_tile(frame, 0)->height; } s->out[frame_idx]->interlacing = frame->interlacing; s->out[frame_idx]->fps = frame->fps; s->out[frame_idx]->color_spec = s->color_spec; s->out[frame_idx]->color_spec = JPEG; } switch (frame->color_spec) { case RGB: s->decoder = (decoder_t) memcpy; s->rgb = TRUE; break; case RGBA: s->decoder = (decoder_t) vc_copylineRGBAtoRGB; s->rgb = TRUE; break; case BGR: s->decoder = (decoder_t) vc_copylineBGRtoRGB; s->rgb = TRUE; break; /* TODO: enable (we need R10k -> RGB) * case R10k: s->decoder = (decoder_t) vc_copyliner10k; s->rgb = TRUE; break;*/ case YUYV: s->decoder = (decoder_t) vc_copylineYUYV; s->rgb = FALSE; break; case UYVY: case Vuy2: case DVS8: s->decoder = (decoder_t) memcpy; s->rgb = FALSE; break; case v210: s->decoder = (decoder_t) vc_copylinev210; s->rgb = FALSE; break; case DVS10: s->decoder = (decoder_t) vc_copylineDVS10; s->rgb = FALSE; break; case DPX10: s->decoder = (decoder_t) vc_copylineDPX10toRGB; s->rgb = TRUE; break; default: fprintf(stderr, "[JPEG] Unknown codec: %d\n", frame->color_spec); //exit_uv(128); return FALSE; } s->encoder_param.verbose = 0; s->encoder_param.segment_info = 1; if(s->rgb) { s->encoder_param.interleaved = 0; s->encoder_param.restart_interval = s->restart_interval == -1 ? 8 : s->restart_interval; /* LUMA */ s->encoder_param.sampling_factor[0].horizontal = 1; s->encoder_param.sampling_factor[0].vertical = 1; /* Cb and Cr */ s->encoder_param.sampling_factor[1].horizontal = 1; s->encoder_param.sampling_factor[1].vertical = 1; s->encoder_param.sampling_factor[2].horizontal = 1; s->encoder_param.sampling_factor[2].vertical = 1; } else { s->encoder_param.interleaved = 1; s->encoder_param.restart_interval = s->restart_interval == -1 ? 2 : s->restart_interval; /* LUMA */ s->encoder_param.sampling_factor[0].horizontal = 2; s->encoder_param.sampling_factor[0].vertical = 1; /* Cb and Cr */ s->encoder_param.sampling_factor[1].horizontal = 1; s->encoder_param.sampling_factor[1].vertical = 1; s->encoder_param.sampling_factor[2].horizontal = 1; s->encoder_param.sampling_factor[2].vertical = 1; } struct gpujpeg_image_parameters param_image; gpujpeg_image_set_default_parameters(¶m_image); param_image.width = s->out[0]->tiles[0].width; param_image.height = s->out[0]->tiles[0].height; param_image.comp_count = 3; if(s->rgb) { param_image.color_space = GPUJPEG_RGB; param_image.sampling_factor = GPUJPEG_4_4_4; } else { param_image.color_space = GPUJPEG_YCBCR_BT709; param_image.sampling_factor = GPUJPEG_4_2_2; } s->encoder = gpujpeg_encoder_create(&s->encoder_param, ¶m_image); for (frame_idx = 0; frame_idx < 2; frame_idx++) { for (x = 0; x < frame->tile_count; ++x) { vf_get_tile(s->out[frame_idx], x)->data = (char *) malloc(s->out[frame_idx]->tiles[0].width * s->out[frame_idx]->tiles[0].height * 3); } } s->encoder_input_linesize = s->out[frame_idx]->tiles[0].width * (param_image.color_space == GPUJPEG_RGB ? 3 : 2); if(!s->encoder) { fprintf(stderr, "[DXT GLSL] Failed to create encoder.\n"); //exit_uv(128); return FALSE; } s->decoded = malloc(4 * s->out[0]->tiles[0].width * s->out[0]->tiles[0].height); return TRUE; }
void *fastdxt_init(char *num_threads_str) { /* This function does the following: * 1. Allocate memory for buffers * 2. Spawn compressor threads */ int x; int i; struct video_compress *compress; if(num_threads_str && strcmp(num_threads_str, "help") == 0) { printf("FastDXT usage:\n"); printf("\t-FastDXT[:<num_threads>]\n"); printf("\t\t<num_threads> - count of compress threads (default %d)\n", NUM_THREADS_DEFAULT); return NULL; } compress = calloc(1, sizeof(struct video_compress)); /* initial values */ compress->num_threads = 0; if(num_threads_str == NULL) compress->num_threads = NUM_THREADS_DEFAULT; else compress->num_threads = atoi(num_threads_str); assert (compress->num_threads >= 1 && compress->num_threads <= MAX_THREADS); for(i = 0; i < 2; ++i) { compress->out[i] = vf_alloc(1); compress->tile[i] = vf_get_tile(compress->out[i], 0); } for(i = 0; i < 2; ++i) { compress->tile[i]->width = 0; compress->tile[i]->height = 0; } compress->thread_count = 0; if (pthread_mutex_init(&(compress->lock), NULL)) { perror("Error initializing mutex!"); return NULL; } for (x = 0; x < compress->num_threads; x++) { platform_sem_init(&compress->thread_compress[x], 0, 0); platform_sem_init(&compress->thread_done[x], 0, 0); } pthread_mutex_lock(&(compress->lock)); for (x = 0; x < compress->num_threads; x++) { if (pthread_create (&(compress->thread_ids[x]), NULL, (void *)compress_thread, (void *)compress)) { perror("Unable to create compressor thread!"); exit_uv(x); return NULL; } } pthread_mutex_unlock(&(compress->lock)); while(compress->num_threads != compress->thread_count) /* wait for all threads online */ ; fprintf(stderr, "All compression threads are online.\n"); return compress; }
static void *display_deltacast_init(struct module *parent, const char *fmt, unsigned int flags) { UNUSED(parent); struct state_deltacast *s; ULONG Result,DllVersion,NbBoards,ChnType; ULONG BrdId = 0; s = (struct state_deltacast *)calloc(1, sizeof(struct state_deltacast)); s->magic = DELTACAST_MAGIC; s->frame = vf_alloc(1); s->tile = vf_get_tile(s->frame, 0); s->frames = 0; gettimeofday(&s->tv, NULL); s->initialized = FALSE; if(flags & DISPLAY_FLAG_AUDIO_EMBEDDED) { s->play_audio = TRUE; } else { s->play_audio = FALSE; } s->BoardHandle = s->StreamHandle = s->SlotHandle = NULL; s->audio_configured = FALSE; if(fmt && strcmp(fmt, "help") == 0) { show_help(); vf_free(s->frame); free(s); return &display_init_noerr; } if(fmt) { char *tmp = strdup(fmt); char *save_ptr = NULL; char *tok; tok = strtok_r(tmp, ":", &save_ptr); if(!tok) { free(tmp); show_help(); goto error; } if (strncasecmp(tok, "board=", strlen("board=")) == 0) { BrdId = atoi(tok + strlen("board=")); } else { fprintf(stderr, "Unknown option: %s\n\n", tok); free(tmp); show_help(); goto error; } free(tmp); } /* Query VideoMasterHD information */ Result = VHD_GetApiInfo(&DllVersion,&NbBoards); if (Result != VHDERR_NOERROR) { fprintf(stderr, "[DELTACAST] ERROR : Cannot query VideoMasterHD" " information. Result = 0x%08X\n", Result); goto error; } if (NbBoards == 0) { fprintf(stderr, "[DELTACAST] No DELTA board detected, exiting...\n"); goto error; } if(BrdId >= NbBoards) { fprintf(stderr, "[DELTACAST] Wrong index %d. Found %d cards.\n", BrdId, NbBoards); goto error; } /* Open a handle on first DELTA-hd/sdi/codec board */ Result = VHD_OpenBoardHandle(BrdId,&s->BoardHandle,NULL,0); if (Result != VHDERR_NOERROR) { fprintf(stderr, "[DELTACAST] ERROR : Cannot open DELTA board %u handle. Result = 0x%08X\n",BrdId,Result); goto error; } VHD_GetBoardProperty(s->BoardHandle, VHD_CORE_BP_TX0_TYPE, &ChnType); if((ChnType!=VHD_CHNTYPE_SDSDI)&&(ChnType!=VHD_CHNTYPE_HDSDI)&&(ChnType!=VHD_CHNTYPE_3GSDI)) { fprintf(stderr, "[DELTACAST] ERROR : The selected channel is not an SDI one\n"); goto bad_channel; } /* Disable RX0-TX0 by-pass relay loopthrough */ VHD_SetBoardProperty(s->BoardHandle,VHD_CORE_BP_BYPASS_RELAY_0,FALSE); /* Select a 1/1 clock system */ VHD_SetBoardProperty(s->BoardHandle,VHD_SDI_BP_CLOCK_SYSTEM,VHD_CLOCKDIV_1); pthread_mutex_init(&s->lock, NULL); return s; bad_channel: VHD_CloseBoardHandle(s->BoardHandle); error: vf_free(s->frame); free(s); return NULL; }