static void dxt_glsl_compress_done(struct module *mod) { struct state_video_compress_rtdxt *s = (struct state_video_compress_rtdxt *) mod->priv_data; int i, x; if(s->out[0]) { for(int i = 0; i < (int) s->out[0]->tile_count; ++i) { if(s->encoder[i]) dxt_encoder_destroy(s->encoder[i]); } } for (i = 0; i < 2; ++i) { if(s->out[i]) { for (x = 0; x < (int) s->out[i]->tile_count; ++x) { free(s->out[i]->tiles[x].data); } } vf_free(s->out[i]); } free(s->decoded); destroy_gl_context(&s->gl_context); free(s); }
static void vidcap_testcard_done(void *state) { struct testcard_state *s = (struct testcard_state *) state; free(s->data); if (s->tiled) { int i; for (i = 0; i < s->tiles_cnt_horizontal; ++i) { free(s->tiles_data[i]); } vf_free(s->tiled); } vf_free(s->frame); if(s->audio_data) { free(s->audio_data); } delete s; }
/** * 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 void vidcap_v4l2_dispose_video_frame(struct video_frame *frame) { struct v4l2_dispose_deq_buffer_data *data = (struct v4l2_dispose_deq_buffer_data *) frame->dispose_udata; if (data) { if (ioctl(data->fd, VIDIOC_QBUF, &data->buf) != 0) { perror("Unable to enqueue buffer"); }; free(data); } else { free(frame->tiles[0].data); } vf_free(frame); }
static void display_sage_done(void *state) { struct state_sage *s = (struct state_sage *)state; assert(s->magic == MAGIC_SAGE); sem_destroy(&s->semaphore); pthread_cond_destroy(&s->buffer_writable_cond); pthread_mutex_destroy(&s->buffer_writable_lock); vf_free(s->frame); if (s->sage_state) s->sage_state->shutdown(); //delete s->sage_state; free(s); }
void vidcap_aggregate_done(void *state) { struct vidcap_aggregate_state *s = (struct vidcap_aggregate_state *) state; assert(s != NULL); if (s != NULL) { int i; for (i = 0; i < s->devices_cnt; ++i) { vidcap_done(s->devices[i]); } } vf_free(s->frame); }
static void cleanup_state(struct state_video_compress_jpeg *s) { int frame_idx; for (frame_idx = 0; frame_idx < 2; frame_idx++) { if(s->out[frame_idx]) { int x; for (x = 0; x < (int) s->out[frame_idx]->tile_count; ++x) { free(s->out[frame_idx]->tiles[x].data); } } vf_free(s->out[frame_idx]); } if(s->encoder) gpujpeg_encoder_destroy(s->encoder); }
static void display_deltacast_done(void *state) { struct state_deltacast *s = (struct state_deltacast *)state; if(s->initialized) { if(s->SlotHandle) VHD_UnlockSlotHandle(s->SlotHandle); VHD_StopStream(s->StreamHandle); VHD_CloseStreamHandle(s->StreamHandle); VHD_SetBoardProperty(s->BoardHandle,VHD_CORE_BP_BYPASS_RELAY_0,TRUE); VHD_CloseBoardHandle(s->BoardHandle); } vf_free(s->frame); free(s); }
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 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; }