void probe_bktr(info_t * ipipe) { struct bktr_capture_area caparea; unsigned short status, fps; close(ipipe->fd_in); ipipe->fd_in = open(ipipe->name, O_RDONLY, 0); if (ipipe->fd_in < 0) { tc_log_error(__FILE__, "cannot open device: %s", strerror(errno)); goto error; } /* try a bktr ioctl */ if (ipipe->verbose & TC_DEBUG) tc_log_msg(__FILE__, "checking if bktr ioctls are supported..."); if (ioctl(ipipe->fd_in, METEORSTATUS, &status) < 0) { if (ipipe->verbose & TC_DEBUG) tc_log_msg(__FILE__, "... no"); goto error; } else { if (ipipe->verbose & TC_DEBUG) tc_log_msg(__FILE__, "... yes"); } if (ioctl(ipipe->fd_in, BT848_GCAPAREA, &caparea) < 0) { tc_log_perror(__FILE__, "BT848_GCAPAREA"); goto error; } ipipe->probe_info->width = caparea.x_size; ipipe->probe_info->height = caparea.y_size; if (ioctl(ipipe->fd_in, METEORGFPS, &fps) < 0) { tc_log_perror(__FILE__, "METEORGFPS"); goto error; } ipipe->probe_info->fps = fps; switch(fps) { case 30: ipipe->probe_info->frc = 4; break; case 25: ipipe->probe_info->frc = 3; break; default: break; } ipipe->probe_info->magic = TC_MAGIC_BKTR_VIDEO; return; error: ipipe->error = 1; ipipe->probe_info->codec = TC_CODEC_UNKNOWN; ipipe->probe_info->magic = TC_MAGIC_UNKNOWN; return; }
int tc_socket_init(const char *socket_path_) { struct sockaddr_un server_addr; client_sock = -1; server_sock = -1; tc_mutex_init(&tc_socket_msg_lock); if (tc_snprintf(socket_path, sizeof(socket_path), "%s", socket_path_) < 0){ tc_log_error(__FILE__, "Socket pathname too long (1)"); *socket_path = 0; return 0; } errno = 0; if (unlink(socket_path) != 0 && errno != ENOENT) { tc_log_error(__FILE__, "Unable to remove \"%s\": %s", socket_path, strerror(errno)); return 0; } server_addr.sun_family = AF_UNIX; if (tc_snprintf(server_addr.sun_path, sizeof(server_addr.sun_path), "%s", socket_path) < 0 ) { tc_log_error(__FILE__, "Socket pathname too long"); return 0; } server_sock = socket(AF_UNIX, SOCK_STREAM, 0); if (server_sock < 0) { tc_log_perror(__FILE__, "Unable to create server socket"); return 0; } if (bind(server_sock, (struct sockaddr *)&server_addr, sizeof(server_addr)) ) { tc_log_perror(__FILE__, "Unable to bind server socket"); close(server_sock); server_sock = -1; unlink(socket_path); // just in case return 0; } if (listen(server_sock, 5) < 0) { tc_log_perror(__FILE__, "Unable to activate server socket"); close(server_sock); unlink(socket_path); return 0; } return 1; }
int bktr_stop() { int c; /* shutdown signals first */ c = METEOR_SIG_MODE_MASK; ioctl(bktr_vfd, METEORSSIGNAL, &c); alarm(0); c = METEOR_CAP_STOP_CONT; ioctl(bktr_vfd, METEORCAPTUR, &c); c = AUDIO_MUTE; if (ioctl(bktr_tfd, BT848_SAUDIO, &c) < 0) { tc_log_perror(MOD_NAME, "BT848_SAUDIO AUDIO_MUTE"); return(1); } if (bktr_vfd > 0) { close(bktr_vfd); bktr_vfd = -1; } if (bktr_tfd > 0) { close(bktr_tfd); bktr_tfd = -1; } munmap(bktr_buffer, bktr_buffer_size); return(0); }
static int tc_v4l2_video_get_capture_buffer_count(V4L2Source *vs) { struct v4l2_requestbuffers reqbuf; int err = 0; reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuf.memory = V4L2_MEMORY_MMAP; reqbuf.count = TC_V4L2_BUFFERS_NUM; err = v4l2_ioctl(vs->video_fd, VIDIOC_REQBUFS, &reqbuf); if (err < 0) { tc_log_perror(MOD_NAME, "VIDIOC_REQBUFS"); return TC_ERROR; } vs->buffers_count = TC_MIN(reqbuf.count, TC_V4L2_BUFFERS_NUM); if (vs->buffers_count < 2) { tc_log_error(MOD_NAME, "not enough buffers for capture"); return TC_ERROR; } if (verbose_flag > TC_INFO) { tc_log_info(MOD_NAME, "%i buffers available (maximum supported: %i)", vs->buffers_count, TC_V4L2_BUFFERS_NUM); } return TC_OK; }
static int tc_v4l2_video_setup_capture_buffers(V4L2Source *vs) { struct v4l2_buffer buffer; int ix, err = 0; /* map the buffers */ for (ix = 0; ix < vs->buffers_count; ix++) { buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; buffer.index = ix; err = v4l2_ioctl(vs->video_fd, VIDIOC_QUERYBUF, &buffer); if (err < 0) { tc_log_perror(MOD_NAME, "VIDIOC_QUERYBUF"); return TC_ERROR; } vs->buffers[ix].length = buffer.length; vs->buffers[ix].start = v4l2_mmap(0, buffer.length, PROT_READ|PROT_WRITE, MAP_SHARED, vs->video_fd, buffer.m.offset); if (vs->buffers[ix].start == MAP_FAILED) { tc_log_perror(MOD_NAME, "mmap"); return TC_ERROR; } } /* then enqueue them all */ for (ix = 0; ix < vs->buffers_count; ix++) { buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; buffer.index = ix; err = v4l2_ioctl(vs->video_fd, VIDIOC_QBUF, &buffer); if (err < 0) { tc_log_perror(MOD_NAME, "VIDIOC_QBUF"); return TC_ERROR; } } return TC_OK; }
static int tc_v4l2_capture_stop(V4L2Source *vs) { int err = 0, arg = V4L2_BUF_TYPE_VIDEO_CAPTURE; err = v4l2_ioctl(vs->video_fd, VIDIOC_STREAMOFF, &arg); if (err < 0) { /* ugh, needs VIDEO_CAPTURE */ tc_log_perror(MOD_NAME, "VIDIOC_STREAMOFF"); return TC_ERROR; } return TC_OK; }
static int astat_stop(TCModuleInstance *self) { int ret = TC_OK; /* optimistism... */ AStatPrivateData *pd = NULL; TC_MODULE_SELF_CHECK(self, "stop"); pd = self->userdata; /* stats summary */ if (pd->min >= pd->silence_limit && pd->max <= pd->silence_limit) { tc_log_info(MOD_NAME, "audio track seems only silence"); } else if (pd->min == 0 || pd->max == 0) { tc_log_warn(MOD_NAME, "bad minimum/maximum value," " unable to find scale value"); ret = TC_ERROR; } else { double fmin = -((double) pd->min)/TCA_S16LE_MAX; double fmax = ((double) pd->max)/TCA_S16LE_MAX; /* FIXME: constantize in libtcaudio */ double vol = (fmin < fmax) ? 1./fmax : 1./fmin; if (pd->filepath == NULL) { tc_log_info(MOD_NAME, "(min=%.3f/max=%.3f), " "normalize volume with \"-s %.3f\"", -fmin, fmax, vol); } else { FILE *fh = fopen(pd->filepath, "w"); if (fh == NULL) { tc_log_perror(MOD_NAME, "unable to open scale value file"); ret = TC_ERROR; } else { fprintf(fh, "%.3f\n", vol); fclose(fh); // XXX if (verbose) { tc_log_info(MOD_NAME, "wrote audio scale value to '%s'", pd->filepath); } } tc_free(pd->filepath); pd->filepath = NULL; } } return TC_OK; }
int execute(char *command) { FILE *pptr; if(debug_flag) { tc_log_msg(MOD_NAME, "subtitler() execute(): arg command=%s\n", command); } pptr = popen(command, "r"); if(pptr <= 0) { tc_log_perror(MOD_NAME, "command"); return 0; } pclose(pptr); return 1; } /* end function execute */
static int tc_v4l2_video_count_buffers(V4L2Source *vs) { struct v4l2_buffer buffer; int ix, ret, buffers_filled = 0; for (ix = 0; ix < vs->buffers_count; ix++) { buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; buffer.index = ix; ret = v4l2_ioctl(vs->video_fd, VIDIOC_QUERYBUF, &buffer); if (ret < 0) { tc_log_perror(MOD_NAME, "error in querying buffers" " (ioctl(VIDIOC_QUERYBUF) failed)"); return -1; } if (buffer.flags & V4L2_BUF_FLAG_DONE) buffers_filled++; } return buffers_filled; }
void extract_rgb(info_t *ipipe) { uint8_t *video; avi_t *avifile = NULL; int key, error = 0; long frames, bytes, n; switch (ipipe->magic) { case TC_MAGIC_AVI: if (ipipe->nav_seek_file) { avifile = AVI_open_indexfd(ipipe->fd_in, 0, ipipe->nav_seek_file); } else { avifile = AVI_open_fd(ipipe->fd_in, 1); } if (NULL == avifile) { AVI_print_error("AVI open"); import_exit(1); } frames = AVI_video_frames(avifile); if (ipipe->frame_limit[1] < frames) { frames = ipipe->frame_limit[1]; } if (ipipe->verbose & TC_STATS) { tc_log_msg(__FILE__, "%ld video frames", frames); } video = tc_bufalloc(SIZE_RGB_FRAME); if (!video) { error = 1; break; } AVI_set_video_position(avifile, ipipe->frame_limit[0]); /* FIXME: should this be < rather than <= ? */ for (n = ipipe->frame_limit[0]; n <= frames; n++) { bytes = AVI_read_frame(avifile, video, &key); if (bytes < 0) { error = 1; break; } if (tc_pwrite(ipipe->fd_out, video, bytes) != bytes) { error = 1; break; } } tc_buffree(video); break; case TC_MAGIC_RAW: /* fallthrough */ default: if (ipipe->magic == TC_MAGIC_UNKNOWN) { tc_log_warn(__FILE__, "no file type specified, assuming %s", filetype(TC_MAGIC_RAW)); error = tc_preadwrite(ipipe->fd_in, ipipe->fd_out); break; } } if (error) { tc_log_perror(__FILE__, "error while writing data"); import_exit(error); } }
int bktr_init(int video_codec, const char *video_device, int width, int height, int fps, char *options) { struct meteor_geomet geo; struct meteor_pixfmt pxf; struct sigaction act; int h_max, w_max; int rgb_idx = -1; int yuv422_idx = -1; int yuv_idx = -1; int i; if (options != NULL) if (bktr_parse_options(options)) return(1); switch (bktr_format) { case METEOR_FMT_NTSC: h_max = 480; w_max = 640; break; case METEOR_FMT_PAL: h_max = 576; w_max = 768; break; default: h_max = 576; w_max = 768; break; } if (width > w_max) { tc_log_warn(MOD_NAME, "import width '%d' too large! " "PAL max width = 768, NTSC max width = 640", width); return(1); } if (height > h_max) { tc_log_warn(MOD_NAME, "import height %d too large! " "PAL max height = 576, NTSC max height = 480", height); return(1); } bktr_tcvhandle = tcv_init(); if (!bktr_tcvhandle) { tcv_log_warn(MOD_NAME, "tcv_init() failed"); return(1); } /* set the audio via the tuner. opening the device unmutes it. */ /* closing the device mutes it again. so we hold it open */ bktr_tfd = open(bktr_tuner, O_RDONLY); if (bktr_tfd < 0) { tc_log_perror(MOD_NAME, "open tuner"); return(1); } if (ioctl(bktr_tfd, BT848_SAUDIO, &bktr_asource) < 0) { tc_log_perror(MOD_NAME, "BT848_SAUDIO asource"); return(1); } if (bktr_mute) { i = AUDIO_MUTE; if (ioctl(bktr_tfd, BT848_SAUDIO, &i) < 0) { tc_log_perror(MOD_NAME, "BT848_SAUDIO AUDIO_MUTE"); return(1); } } else { i = AUDIO_UNMUTE; if (ioctl(bktr_tfd, BT848_SAUDIO, &i) < 0) { tc_log_perror(MOD_NAME, "BT848_SAUDIO AUDIO_UNMUTE"); return(1); } } /* open the video device */ bktr_vfd = open(video_device, O_RDONLY); if (bktr_vfd < 0) { tc_log_perror(MOD_NAME, video_device); return(1); } /* get the indices of supported formats that transcode can use */ for (i = 0; ; i++) { pxf.index = i; if (ioctl(bktr_vfd, METEORGSUPPIXFMT, &pxf) < 0) { if (errno == EINVAL) break; else return(1); } switch(pxf.type) { case METEOR_PIXTYPE_RGB: if ((pxf.Bpp == 4) && (pxf.swap_bytes == 0) && (pxf.swap_shorts == 0)) { rgb_idx = pxf.index; } break; case METEOR_PIXTYPE_YUV_PACKED: if ((pxf.swap_bytes == 0) && (pxf.swap_shorts == 1)) { yuv422_idx = pxf.index; } break; case METEOR_PIXTYPE_YUV_12: if ((pxf.swap_bytes == 1) && (pxf.swap_shorts == 1)) { yuv_idx = pxf.index; } break; case METEOR_PIXTYPE_YUV: default: break; } } /* set format, conversion function, and buffer size */ switch(video_codec) { case CODEC_RGB: i = rgb_idx; bktr_convert = BKTR2RGB; bktr_buffer_size = width * height * 4; break; case CODEC_YUV422: i = yuv422_idx; bktr_convert = BKTR2YUV422; bktr_buffer_size = width * height * 2; break; case CODEC_YUV: i = yuv_idx; bktr_convert = BKTR2YUV; bktr_buffer_size = width * height * 3 / 2; break; default: tc_log_warn(MOD_NAME, "video_codec (%d) must be %d or %d or %d\n", video_codec, CODEC_RGB, CODEC_YUV422, CODEC_YUV); return(1); } if (ioctl(bktr_vfd, METEORSACTPIXFMT, &i) < 0) { tc_log_perror(MOD_NAME, "METEORSACTPIXFMT"); return(1); } /* set the geometry */ geo.rows = height; geo.columns = width; geo.frames = 1; geo.oformat = 0; if (verbose_flag & TC_DEBUG) { tc_log_info(MOD_NAME, "geo.rows = %d, geo.columns = %d, " "geo.frames = %d, geo.oformat = %ld", geo.rows, geo.columns, geo.frames, (long)geo.oformat); } if (ioctl(bktr_vfd, METEORSETGEO, &geo) < 0) { tc_log_perror(MOD_NAME, "METEORSETGEO"); return(1); } /* extra options */ if (bktr_vsource) { if (ioctl(bktr_vfd, METEORSINPUT, &bktr_vsource) < 0) { tc_log_perror(MOD_NAME, "METEORSINPUT"); return(1); } } if (bktr_format) { if (ioctl(bktr_vfd, METEORSFMT, &bktr_format) < 0) { tc_log_perror(MOD_NAME, "METEORSFMT"); return(1); } } if (bktr_hwfps) { if (ioctl(bktr_vfd, METEORSFPS, &fps) < 0) { tc_log_perror(MOD_NAME, "METEORSFPS"); return(1); } } /* mmap the buffer */ bktr_buffer = mmap(0, bktr_buffer_size, PROT_READ, MAP_SHARED, bktr_vfd, 0); if (bktr_buffer == MAP_FAILED) { tc_log_perror(MOD_NAME, "mmap bktr_buffer"); return(1); } /* for sigsuspend() */ sigfillset(&sa_mask); sigdelset(&sa_mask, SIGUSR1); sigdelset(&sa_mask, SIGALRM); /* signal handler to know when data is ready to be read() */ memset(&act, 0, sizeof(act)); sigemptyset(&act.sa_mask); act.sa_handler = catchsignal; sigaction(SIGUSR1, &act, NULL); sigaction(SIGALRM, &act, NULL); i = SIGUSR1; if (ioctl(bktr_vfd, METEORSSIGNAL, &i) < 0) { tc_log_perror(MOD_NAME, "METEORSSIGNAL"); return(1); } /* let `er rip! */ i = METEOR_CAP_CONTINOUS; if (ioctl(bktr_vfd, METEORCAPTUR, &i) < 0) { tc_log_perror(MOD_NAME, "METEORCAPTUR"); return(1); } return(0); }
static int demux (uint8_t * buf, uint8_t * end, int flags) { static int mpeg1_skip_table[16] = { 0, 0, 4, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* * the demuxer keeps some state between calls: * if "state" = DEMUX_HEADER, then "head_buf" contains the first * "bytes" bytes from some header. * if "state" == DEMUX_DATA, then we need to copy "bytes" bytes * of ES data before the next header. * if "state" == DEMUX_SKIP, then we need to skip "bytes" bytes * of data before the next header. * * NEEDBYTES makes sure we have the requested number of bytes for a * header. If we dont, it copies what we have into head_buf and returns, * so that when we come back with more data we finish decoding this header. * * DONEBYTES updates "buf" to point after the header we just parsed. */ #define DEMUX_HEADER 0 #define DEMUX_DATA 1 #define DEMUX_SKIP 2 static int state = DEMUX_SKIP; static int state_bytes = 0; static uint8_t head_buf[264]; uint8_t * header; int bytes; int len; #define NEEDBYTES(x) \ do { \ int missing; \ \ missing = (x) - bytes; \ if (missing > 0) { \ if (header == head_buf) { \ if (missing <= end - buf) { \ ac_memcpy (header + bytes, buf, missing); \ buf += missing; \ bytes = (x); \ } else { \ ac_memcpy (header + bytes, buf, end - buf); \ state_bytes = bytes + end - buf; \ return 0; \ } \ } else { \ ac_memcpy (head_buf, header, bytes); \ state = DEMUX_HEADER; \ state_bytes = bytes; \ return 0; \ } \ } \ } while (0) #define DONEBYTES(x) \ do { \ if (header != head_buf) \ buf = header + (x); \ } while (0) if (flags & DEMUX_PAYLOAD_START) goto payload_start; switch (state) { case DEMUX_HEADER: if (state_bytes > 0) { header = head_buf; bytes = state_bytes; goto continue_header; } break; case DEMUX_DATA: if (demux_pid || (state_bytes > end - buf)) { if (fwrite (buf, end - buf, 1, stdout) != 1) { tc_log_perror(__FILE__, "Write error"); } state_bytes -= end - buf; return 0; } if (fwrite (buf, state_bytes, 1, stdout) != 1) { tc_log_perror(__FILE__, "Write error"); } buf += state_bytes; break; case DEMUX_SKIP: if (demux_pid || (state_bytes > end - buf)) { state_bytes -= end - buf; return 0; } buf += state_bytes; break; } while (1) { if (demux_pid) { state = DEMUX_SKIP; return 0; } payload_start: header = buf; bytes = end - buf; continue_header: NEEDBYTES (4); if (header[0] || header[1] || (header[2] != 1)) { if (demux_pid) { state = DEMUX_SKIP; return 0; } else if (header != head_buf) { buf++; goto payload_start; } else { header[0] = header[1]; header[1] = header[2]; header[2] = header[3]; bytes = 3; goto continue_header; } } if (demux_pid) { if ((header[3] >= 0xe0) && (header[3] <= 0xef)) goto pes; tc_log_error(__FILE__, "bad stream id %x", header[3]); exit (1); } switch (header[3]) { case 0xb9: /* program end code */ /* DONEBYTES (4); */ /* break; */ return 1; case 0xba: /* pack header */ NEEDBYTES (12); if ((header[4] & 0xc0) == 0x40) { /* mpeg2 */ NEEDBYTES (14); len = 14 + (header[13] & 7); NEEDBYTES (len); DONEBYTES (len); /* header points to the mpeg2 pack header */ } else if ((header[4] & 0xf0) == 0x20) { /* mpeg1 */ DONEBYTES (12); /* header points to the mpeg1 pack header */ } else { tc_log_error(__FILE__, "weird pack header"); exit (1); } break; default: if (header[3] == demux_track) { pes: NEEDBYTES (7); if ((header[6] & 0xc0) == 0x80) { /* mpeg2 */ NEEDBYTES (9); len = 9 + header[8]; NEEDBYTES (len); /* header points to the mpeg2 pes header */ } else { /* mpeg1 */ len = 7; while ((header-1)[len] == 0xff) { len++; NEEDBYTES (len); if (len > 23) { tc_log_warn(__FILE__, "too much stuffing"); break; } } if (((header-1)[len] & 0xc0) == 0x40) { len += 2; NEEDBYTES (len); } len += mpeg1_skip_table[(header - 1)[len] >> 4]; NEEDBYTES (len); /* header points to the mpeg1 pes header */ } DONEBYTES (len); bytes = 6 + (header[4] << 8) + header[5] - len; if (demux_pid || (bytes > end - buf)) { if (fwrite (buf, end - buf, 1, stdout) != 1) { tc_log_perror(__FILE__, "Write error"); } state = DEMUX_DATA; state_bytes = bytes - (end - buf); return 0; } else if (bytes <= 0) { continue; } if (fwrite (buf, bytes, 1, stdout) != 1) { tc_log_perror(__FILE__, "Write error"); } buf += bytes; } else if (header[3] < 0xb9) { tc_log_info(__FILE__, "looks like a video stream, not system stream"); DONEBYTES (4); } else { NEEDBYTES (6); DONEBYTES (6); bytes = (header[4] << 8) + header[5]; if (bytes > end - buf) { state = DEMUX_SKIP; state_bytes = bytes - (end - buf); return 0; } buf += bytes; } }
int chroma_key(int u, int v, double color,\ double color_window, double saturation) { double da, du, dv, ds; double dcolor, dvector; double dsine; if(debug_flag) { tc_log_msg(MOD_NAME, "subtitler(): chroma_key(): arg\n\ u=%d v=%d color=%.3f color_window=%.3f saturation=%.3f\n",\ u, v, color, color_window, saturation); } /* The U and V signals were intended for quadrature modulation on the 4.43 PAL carrier, lets do it: color vector, angle alpha sets color, amplitude sets saturation u / |/ alpha -v -- -- v | -u */ /* no color no action, prevent nan */ if( (u == 0) && (v == 0) ) return 0; /* calculate the vector amplitude (hypotenusa) */ du = (double)u; dv = (double)v; dvector = sqrt( (du * du) + ( dv * dv ) ); /* calculate if enough saturation (chroma level) */ /* saturation is specified as 0-100% */ /* range 0-1 */ ds = saturation / 100.0; /* multiply by maximum vector amplitude possible */ ds *= dmax_vector; // set in init /* if not this much color, return no match */ if(dvector < ds) return 0; /* calculate the sine */ dsine = (du / dvector); /* dsine must be in the range -1 to +1, else errno. */ /* get the vector angle */ errno = 0; dcolor = asin(dsine); if(errno == EDOM) { tc_log_perror(MOD_NAME, "subtitler(): rotate_color(): asin NOT A NUMBER :-)"); /* abort */ exit(1); } /* if V is negative, we move to the other 2 quadrants */ if(dv < 0) dcolor = M_PI - dcolor; dcolor *= 180.0 / M_PI; da = dcolor - color; /* if color in range, return match */ if( fabs(da) < color_window) return 1; return 0; } /* end function chroma_key */
void adjust_color(int *u, int *v, double degrees, double saturation) { double du, dv; double dcolor, dsaturation; double dsine; double dsat; int tmp_int; if(debug_flag) { tc_log_msg(MOD_NAME, "subtitler(): adjust_color(): arg\n\ *u=%d *v=%d degrees=%.3f saturation=%.3f\n",\ *u, *v, degrees, saturation); } /* The U and V signals were intended for quadrature modulation on the 4.43 PAL carrier, lets do it: color vector, angle alpha sets color, amplitude sets saturation u / |/ alpha -v -- -- v | -u */ /* no color no action, prevent nan */ if( (*u == 0) && (*v == 0) ) return; /* calculate the vector amplitude (hypotenusa) */ du = (double)*u; dv = (double)*v; dsaturation = sqrt( (du * du) + ( dv * dv ) ); /* calc multiplyer from percentage 0-100 */ dsat = saturation / 100.0; /* I wont apply a flipping vector each line, as in PAL, so as to keep our quadrature modulator simple, we have no phase errors here to correct. Phase errors in PAL cancel, but leave small saturation (vector amplitude) errors. */ /* calculate the sine */ dsine = (du / dsaturation); /* dsine must be in the range -1 to +1, else errno. */ /* get the vector angle */ errno = 0; dcolor = asin(dsine); if(errno == EDOM) { tc_log_perror(MOD_NAME, "subtitler(): rotate_color(): asin NOT A NUMBER :-)"); /* abort */ exit(1); } /* if V is negative, we move to the other 2 quadrants */ if(dv < 0) dcolor = M_PI - dcolor; /* add the hue to the vector angle, -PI/2 to PI/2 (inclusive) */ dcolor += (degrees * M_PI) / 180.0; /* change saturation by changing the vector amplitude */ dsaturation *= dsat; /* demodulate :) our quadrature demodulator */ tmp_int = sin(dcolor) * dsaturation; *u = tmp_int; tmp_int = cos(dcolor) * dsaturation; *v = tmp_int; /* and do this for each pixel...... */ return; } /* end function adjust_color */
int main(int argc, char *argv[]) { info_t ipipe; int user=0; long stream_stype = TC_STYPE_UNKNOWN, stream_magic = TC_MAGIC_UNKNOWN, stream_codec = TC_CODEC_UNKNOWN; int ch, done=0, track=0; char *magic=NULL, *codec=NULL, *name=NULL; //proper initialization memset(&ipipe, 0, sizeof(info_t)); ipipe.frame_limit[0]=0; ipipe.frame_limit[1]=LONG_MAX; libtc_init(&argc, &argv); while ((ch = getopt(argc, argv, "d:x:i:f:a:vt:C:?h")) != -1) { switch (ch) { case 'i': if(optarg[0]=='-') usage(EXIT_FAILURE); name = optarg; break; case 'd': if(optarg[0]=='-') usage(EXIT_FAILURE); verbose = atoi(optarg); break; case 'x': if(optarg[0]=='-') usage(EXIT_FAILURE); codec = optarg; break; case 'f': if(optarg[0]=='-') usage(EXIT_FAILURE); ipipe.nav_seek_file = optarg; break; case 't': if(optarg[0]=='-') usage(EXIT_FAILURE); magic = optarg; user=1; break; case 'a': if(optarg[0]=='-') usage(EXIT_FAILURE); track = strtol(optarg, NULL, 0); break; case 'C': if(optarg[0]=='-') usage(EXIT_FAILURE); if (2 != sscanf(optarg,"%ld-%ld", &ipipe.frame_limit[0], &ipipe.frame_limit[1])) usage(EXIT_FAILURE); if (ipipe.frame_limit[0] > ipipe.frame_limit[1]) { tc_log_error(EXE, "Invalid -C options"); usage(EXIT_FAILURE); } break; case 'v': version(); exit(0); break; case 'h': usage(EXIT_SUCCESS); default: usage(EXIT_FAILURE); } } ac_init(AC_ALL); /* ------------------------------------------------------------ * * fill out defaults for info structure * * ------------------------------------------------------------*/ // assume defaults if(name==NULL) stream_stype=TC_STYPE_STDIN; // no autodetection yet if(codec==NULL && magic==NULL) { tc_log_error(EXE, "invalid codec %s", codec); usage(EXIT_FAILURE); } if(codec==NULL) codec=""; // do not try to mess with the stream if(stream_stype!=TC_STYPE_STDIN) { if(tc_file_check(name)) exit(1); if((ipipe.fd_in = xio_open(name, O_RDONLY))<0) { tc_log_perror(EXE, "file open"); return(-1); } stream_magic = fileinfo(ipipe.fd_in, 0); if(verbose & TC_DEBUG) tc_log_msg(EXE, "(pid=%d) %s", getpid(), filetype(stream_magic)); } else ipipe.fd_in = STDIN_FILENO; if(verbose & TC_DEBUG) tc_log_msg(EXE, "(pid=%d) starting, doing %s", getpid(), codec); // fill out defaults for info structure ipipe.fd_out = STDOUT_FILENO; ipipe.magic = stream_magic; ipipe.stype = stream_stype; ipipe.codec = stream_codec; ipipe.track = track; ipipe.select = TC_VIDEO; ipipe.verbose = verbose; ipipe.name = name; /* ------------------------------------------------------------ * * codec specific section * * note: user provided magic values overwrite autodetection! * * ------------------------------------------------------------*/ if(magic==NULL) magic=""; // OGM if (ipipe.magic == TC_MAGIC_OGG) { // dummy for video if(strcmp(codec, "raw")==0) ipipe.codec = TC_CODEC_RGB24; if((strcmp(codec, "vorbis")==0) || (strcmp(codec, "ogg")==0)) { ipipe.codec = TC_CODEC_VORBIS; ipipe.select = TC_AUDIO; } if(strcmp(codec, "mp3")==0) { ipipe.codec = TC_CODEC_MP3; ipipe.select = TC_AUDIO; } if(strcmp(codec, "pcm")==0) { ipipe.codec = TC_CODEC_PCM; ipipe.select = TC_AUDIO; } extract_ogm(&ipipe); done = 1; } // MPEG2 if(strcmp(codec,"mpeg2")==0) { ipipe.codec = TC_CODEC_MPEG2; if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB; if(strcmp(magic, "m2v")==0) ipipe.magic = TC_MAGIC_M2V; if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW; extract_mpeg2(&ipipe); done = 1; } // PCM if(strcmp(codec,"pcm")==0) { ipipe.codec = TC_CODEC_PCM; ipipe.select = TC_AUDIO; if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB; if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI; if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW; if(strcmp(magic, "wav")==0) ipipe.magic = TC_MAGIC_WAV; extract_pcm(&ipipe); done = 1; } // SUBTITLE (private_stream_1) if(strcmp(codec,"ps1")==0) { ipipe.codec = TC_CODEC_PS1; ipipe.select = TC_AUDIO; if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB; if(strcmp(magic, "vdr")==0) ipipe.magic = TC_MAGIC_VDR; extract_ac3(&ipipe); done = 1; } // DV if(strcmp(codec,"dv")==0) { ipipe.codec = TC_CODEC_DV; if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI; if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW; extract_dv(&ipipe); done = 1; } // RGB if(strcmp(codec,"rgb")==0) { ipipe.codec = TC_CODEC_RGB24; if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI; if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW; if(strcmp(magic, "wav")==0) ipipe.magic = TC_MAGIC_WAV; extract_rgb(&ipipe); done = 1; } // DTS if(strcmp(codec,"dts")==0) { ipipe.codec = TC_CODEC_DTS; ipipe.select = TC_AUDIO; if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW; if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB; extract_ac3(&ipipe); done = 1; } // AC3 if(strcmp(codec,"ac3")==0) { ipipe.codec = TC_CODEC_AC3; ipipe.select = TC_AUDIO; if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW; if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB; extract_ac3(&ipipe); done = 1; } // MP3 if(strcmp(codec,"mp3")==0 || strcmp(codec,"mp2")==0) { ipipe.codec = TC_CODEC_MP3; ipipe.select = TC_AUDIO; if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI; if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW; if(strcmp(magic, "vob")==0) ipipe.magic = TC_MAGIC_VOB; extract_mp3(&ipipe); done = 1; } // YUV420P if(strcmp(codec,"yuv420p")==0) { ipipe.codec = TC_CODEC_YUV420P; if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI; if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW; if(strcmp(magic, "yuv4mpeg")==0) ipipe.magic = TC_MAGIC_YUV4MPEG; extract_yuv(&ipipe); done = 1; } // YUV422P if(strcmp(codec,"yuv422p")==0) { ipipe.codec = TC_CODEC_YUV422P; if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI; if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW; if(strcmp(magic, "yuv4mpeg")==0) ipipe.magic = TC_MAGIC_YUV4MPEG; extract_yuv(&ipipe); done = 1; } // UYVY if(strcmp(codec,"uyvy")==0) { ipipe.codec = TC_CODEC_UYVY; if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI; if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW; extract_yuv(&ipipe); done = 1; } // LZO if(strcmp(codec,"lzo")==0) { ipipe.codec = TC_CODEC_YUV420P; if(strcmp(magic, "avi")==0) ipipe.magic = TC_MAGIC_AVI; if(strcmp(magic, "raw")==0) ipipe.magic = TC_MAGIC_RAW; extract_lzo(&ipipe); done = 1; } // AVI extraction //need to check if there isn't a codec from the input option (if we have a file with TC_MAGIC_AVI and we specify -x pcm we have pcm and rgb output) if ((strcmp(magic, "avi")==0 || ipipe.magic==TC_MAGIC_AVI)&& (codec == NULL)) { ipipe.magic=TC_MAGIC_AVI; extract_avi(&ipipe); done = 1; } if (strcmp(codec, "raw")==0 || strcmp(codec, "video")==0) { ipipe.select=TC_VIDEO-1; ipipe.magic=TC_MAGIC_AVI; extract_avi(&ipipe); done = 1; } if(!done) { tc_log_error(EXE, "(pid=%d) unable to handle codec %s", getpid(), codec); exit(1); } if(ipipe.fd_in != STDIN_FILENO) xio_close(ipipe.fd_in); return(0); }
int main(int argc, char *argv[]) { info_t ipipe; int ch, n, user = 0, demux_mode = TC_DEMUX_SEQ_ADJUST; int npass = 0, *pass = NULL, *new_pass = NULL; int keep_initial_seq = 0, hard_fps_flag = 0, pack_sl = PACKAGE_ALL; int unit_seek = 0, resync_seq1 = 0, resync_seq2 = INT_MAX; int a_track = 0, v_track = 0, subid = 0x80; double fps = PAL_FPS; long stream_stype = TC_STYPE_UNKNOWN; long stream_codec = TC_CODEC_UNKNOWN; long stream_magic = TC_MAGIC_UNKNOWN; long x; char *magic = "", *codec = NULL, *name = NULL; char *logfile = SYNC_LOGFILE, *str = NULL, *end = NULL; //defaults: //proper initialization memset(&ipipe, 0, sizeof(info_t)); libtc_init(&argc, &argv); while ((ch = getopt(argc, argv, "A:a:d:x:i:vt:S:M:f:P:WHs:O?h")) != -1) { switch (ch) { case 'i': if (optarg[0] == '-') usage(EXIT_FAILURE); name = optarg; break; case 'O': keep_initial_seq = 1; break; case 'P': if (optarg[0] == '-') usage(EXIT_FAILURE); logfile = optarg; break; case 'S': if (optarg[0] == '-') usage(EXIT_FAILURE); n = sscanf(optarg,"%d,%d-%d", &unit_seek, &resync_seq1, &resync_seq2); if (n < 0) { tc_log_error(EXE, "invalid parameter for option -S"); usage(EXIT_FAILURE); } if (unit_seek < 0) { tc_log_error(EXE, "invalid unit parameter for option -S"); usage(EXIT_FAILURE); } if (resync_seq1 < 0 || resync_seq2 < 0 || resync_seq1 >= resync_seq2) { tc_log_error(EXE, "invalid sequence parameter for option -S"); usage(EXIT_FAILURE); } break; case 'd': if (optarg[0] == '-') usage(EXIT_FAILURE); verbose = atoi(optarg); break; case 'f': if (optarg[0] == '-') usage(EXIT_FAILURE); fps = atof(optarg); break; case 'W': demux_mode = TC_DEMUX_SEQ_LIST; logfile = NULL; break; case 'H': hard_fps_flag = 1; break; case 'x': if (optarg[0] == '-') usage(EXIT_FAILURE); codec = optarg; if (strcmp(codec,"ac3") == 0) { pack_sl = PACKAGE_AUDIO_AC3; stream_codec = TC_CODEC_AC3; } if (strcmp(codec,"mpeg2") == 0) { pack_sl = PACKAGE_VIDEO; stream_codec = TC_CODEC_MPEG2; } if (strcmp(codec,"mp3") == 0) { pack_sl = PACKAGE_AUDIO_MP3; stream_codec = TC_CODEC_MP3; } if (strcmp(codec,"pcm") == 0) { pack_sl = PACKAGE_AUDIO_PCM; stream_codec = TC_CODEC_PCM; } if (strcmp(codec,"ps1") == 0) { pack_sl = PACKAGE_SUBTITLE; stream_codec = TC_CODEC_SUB; } break; case 't': if (optarg[0] == '-') usage(EXIT_FAILURE); magic = optarg; user = 1; break; case 's': if (optarg[0] == '-') usage(EXIT_FAILURE); subid = strtol(optarg, NULL, 16); break; case 'A': if (optarg[0] == '-') usage(EXIT_FAILURE); while (1) { x = strtol(str, &end, 0); if ((end == str) || (x < 1) || (x > 0xff)) { tc_log_error(EXE, "invalid parameter for option -A"); exit(1); } if (*end == '\0') { break; } if (*end != ',') { tc_log_error(EXE, "invalid parameter for option -A"); exit(1); } str = end + 1; new_pass = realloc(pass, (npass + 1) * sizeof (int)); if (new_pass == NULL) { tc_log_error(EXE, "out of memory"); exit(1); } pass = new_pass; pass[npass++] = (int)x; } break; case 'M': if (optarg[0] == '-') usage(EXIT_FAILURE); demux_mode = atoi(optarg); if (demux_mode == TC_DEMUX_OFF) verbose = TC_QUIET; if (demux_mode < 0 || demux_mode > TC_DEMUX_MAX_OPTS) { tc_log_error(EXE, "invalid parameter for option -M"); exit(1); } break; case 'a': if (optarg[0] == '-') usage(EXIT_FAILURE); if ((n = sscanf(optarg,"%d,%d", &a_track, &v_track)) <= 0) { tc_log_error(EXE, "invalid parameter for option -a"); exit(1); } break; case 'v': version(); exit(0); break; case 'h': usage(EXIT_SUCCESS); default: usage(EXIT_FAILURE); } } ac_init(AC_ALL); /* ------------------------------------------------------------ * fill out defaults for info structure * ------------------------------------------------------------*/ // assume defaults if (name == NULL) stream_stype=TC_STYPE_STDIN; // no autodetection yet if (argc == 1) { usage(EXIT_FAILURE); } // do not try to mess with the stream if (stream_stype == TC_STYPE_STDIN) { ipipe.fd_in = STDIN_FILENO; } else { if (tc_file_check(name)) exit(1); ipipe.fd_in = xio_open(name, O_RDONLY); if (ipipe.fd_in < 0) { tc_log_perror(EXE, "open file"); exit(1); } // try to find out the filetype stream_magic = fileinfo(ipipe.fd_in, 0); if (verbose) tc_log_msg(EXE, "(pid=%d) %s", getpid(), filetype(stream_magic)); } // fill out defaults for info structure ipipe.fd_out = STDOUT_FILENO; ipipe.magic = stream_magic; ipipe.stype = stream_stype; ipipe.codec = stream_codec; ipipe.verbose = verbose; ipipe.ps_unit = unit_seek; ipipe.ps_seq1 = resync_seq1; ipipe.ps_seq2 = resync_seq2; ipipe.demux = demux_mode; ipipe.select = pack_sl; ipipe.keep_seq = keep_initial_seq; ipipe.subid = subid; ipipe.fps = fps; ipipe.hard_fps_flag = hard_fps_flag; ipipe.track = a_track; ipipe.name = logfile; //FIXME: video defaults to 0 /* ------------------------------------------------------------ * main processing mode * ------------------------------------------------------------*/ if (npass > 0) tcdemux_pass_through(&ipipe, pass, npass); else tcdemux_thread(&ipipe); return 0; }
/* FIXME: reorganize the layout */ static int tc_v4l2_video_grab_frame(V4L2Source *vs, uint8_t *dest, size_t length) { static struct v4l2_buffer buffer; /* FIXME */ int ix, err = 0, eio = 0, ret = TC_ERROR; // get buffer buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; err = v4l2_ioctl(vs->video_fd, VIDIOC_DQBUF, &buffer); if (err < 0) { tc_log_perror(MOD_NAME, "error in setup grab buffer (ioctl(VIDIOC_DQBUF) failed)"); if (errno != EIO) { return TC_OK; } else { eio = 1; for (ix = 0; ix < vs->buffers_count; ix++) { buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; buffer.index = ix; buffer.flags = 0; err = v4l2_ioctl(vs->video_fd, VIDIOC_DQBUF, &buffer); if (err < 0) tc_log_perror(MOD_NAME, "error in recovering grab buffer (ioctl(DQBUF) failed)"); } for (ix = 0; ix < vs->buffers_count; ix++) { buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; buffer.index = ix; buffer.flags = 0; err = v4l2_ioctl(vs->video_fd, VIDIOC_QBUF, &buffer); if (err < 0) tc_log_perror(MOD_NAME, "error in recovering grab buffer (ioctl(QBUF) failed)"); } } } ix = buffer.index; ret = vs->fetch_data(vs, vs->buffers[ix].start, buffer.bytesused, dest, length); // enqueue buffer again if (!eio) { buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buffer.memory = V4L2_MEMORY_MMAP; buffer.flags = 0; err = v4l2_ioctl(vs->video_fd, VIDIOC_QBUF, &buffer); if (err < 0) { tc_log_perror(MOD_NAME, "error in enqueuing buffer (ioctl(VIDIOC_QBUF) failed)"); return TC_OK; } } return ret; }
static void tc_socket_poll_internal(int blocking) { fd_set rfds, wfds; char msgbuf[TC_BUF_MAX]; int maxfd = -1, retval = -1; struct timeval tv = {0, 0}, *ptv = (blocking) ?NULL :&tv; FD_ZERO(&rfds); FD_ZERO(&wfds); FD_SET(server_sock, &rfds); maxfd = server_sock; if (client_sock >= 0) { FD_SET(client_sock, &rfds); //FD_SET(client_sock, &wfds); if (client_sock > maxfd) maxfd = client_sock; } retval = select(maxfd+1, &rfds, &wfds, NULL, ptv); if (retval == 0) { /* nothing interesting happened. It happens :) */ return; } if (retval < 0 && errno != EINTR) { /* EINTR is an expected "exceptional" condition */ tc_log_warn(__FILE__, "select(): %s", strerror(errno)); return; } if (FD_ISSET(server_sock, &rfds)) { int newsock = accept(server_sock, NULL, 0); if (newsock < 0) { tc_log_warn(__FILE__, "Unable to accept new connection: %s", strerror(errno)); return; } if (client_sock >= 0) { /* We already have a connection, so drop this one */ close(newsock); } else { client_sock = newsock; } } if (client_sock >= 0 && FD_ISSET(client_sock, &rfds)) { retval = recv(client_sock, msgbuf, sizeof(msgbuf)-1, 0); if (retval <= 0) { if (retval < 0) tc_log_perror(__FILE__, "Unable to read message from socket"); close(client_sock); client_sock = -1; } else { if (retval > sizeof(msgbuf)-1) // paranoia retval = sizeof(msgbuf)-1; msgbuf[retval] = 0; if (!handle(msgbuf)) { close(client_sock); client_sock = -1; } } } }
int tc_filter(frame_list_t *ptr_, char *options) { vframe_list_t *ptr = (vframe_list_t *)ptr_; int instance = ptr->filter_id; Image *pattern, *resized, *orig = 0; ImageInfo *image_info; PixelPacket *pixel_packet; pixelsMask *pixel_last; ExceptionInfo exception_info; if(ptr->tag & TC_FILTER_GET_CONFIG) { char buf[128]; optstr_filter_desc(options, MOD_NAME, MOD_CAP, MOD_VERSION, MOD_AUTHOR, "VRYMO", "1"); tc_snprintf(buf, 128, "/dev/null"); optstr_param(options, "pattern", "Pattern image file path", "%s", buf); tc_snprintf(buf, 128, "results.dat"); optstr_param(options, "results", "Results file path" , "%s", buf); tc_snprintf(buf, 128, "%f", compare[instance]->delta); optstr_param(options, "delta", "Delta error", "%f",buf,"0.0", "100.0"); return 0; } //---------------------------------- // // filter init // //---------------------------------- if(ptr->tag & TC_FILTER_INIT) { unsigned int t,r,index; pixelsMask *temp; compare[instance] = tc_malloc(sizeof(compareData)); if(compare[instance] == NULL) return (-1); compare[instance]->vob = tc_get_vob(); if(compare[instance]->vob ==NULL) return(-1); compare[instance]->delta=DELTA_COLOR; compare[instance]->step=1; compare[instance]->width=0; compare[instance]->height=0; compare[instance]->frames = 0; compare[instance]->pixel_mask = NULL; pixel_last = NULL; compare[instance]->width = compare[instance]->vob->ex_v_width; compare[instance]->height = compare[instance]->vob->ex_v_height; if (options != NULL) { char pattern_name[PATH_MAX]; char results_name[PATH_MAX]; memset(pattern_name,0,PATH_MAX); memset(results_name,0,PATH_MAX); if(verbose) tc_log_info(MOD_NAME, "options=%s", options); optstr_get(options, "pattern", "%[^:]", pattern_name); optstr_get(options, "results", "%[^:]", results_name); optstr_get(options, "delta", "%f", &compare[instance]->delta); if (verbose > 1) { tc_log_info(MOD_NAME, "Compare Image Settings:"); tc_log_info(MOD_NAME, " pattern = %s\n", pattern_name); tc_log_info(MOD_NAME, " results = %s\n", results_name); tc_log_info(MOD_NAME, " delta = %f\n", compare[instance]->delta); } if (strlen(results_name) == 0) { // Ponemos el nombre del fichero al original con extension dat strlcpy(results_name, "/tmp/compare.dat", sizeof(results_name)); } if (!(compare[instance]->results = fopen(results_name, "w"))) { tc_log_perror(MOD_NAME, "could not open file for writing"); } InitializeMagick(""); if (verbose > 1) tc_log_info(MOD_NAME, "Magick Initialized successfully"); GetExceptionInfo(&exception_info); image_info = CloneImageInfo ((ImageInfo *) NULL); strlcpy(image_info->filename, pattern_name, MaxTextExtent); if (verbose > 1) tc_log_info(MOD_NAME, "Trying to open image"); orig = ReadImage(image_info, &exception_info); if (orig == (Image *) NULL) { MagickWarning(exception_info.severity, exception_info.reason, exception_info.description); strlcpy(pattern_name, "/dev/null", sizeof(pattern_name)); }else{ if (verbose > 1) tc_log_info(MOD_NAME, "Image loaded successfully"); } } else{ tc_log_perror(MOD_NAME, "Not image provided"); } if (options != NULL) if (optstr_lookup (options, "help")) { help_optstr(); } fprintf(compare[instance]->results,"#fps:%f\n",compare[instance]->vob->fps); if (orig != NULL){ // Flip and resize if (compare[instance]->vob->im_v_codec == CODEC_YUV) TransformRGBImage(orig,YCbCrColorspace); if (verbose > 1) tc_log_info(MOD_NAME, "Resizing the Image"); resized = ResizeImage(orig, compare[instance]->width, compare[instance]->height, GaussianFilter, 1, &exception_info); if (verbose > 1) tc_log_info(MOD_NAME, "Flipping the Image"); pattern = FlipImage(resized, &exception_info); if (pattern == (Image *) NULL) { MagickError (exception_info.severity, exception_info.reason, exception_info.description); } // Filling the matrix with the pixels values not // alpha if (verbose > 1) tc_log_info(MOD_NAME, "GetImagePixels"); pixel_packet = GetImagePixels(pattern,0,0, pattern->columns, pattern->rows); if (verbose > 1) tc_log_info(MOD_NAME, "Filling the Image matrix"); for (t = 0; t < pattern->rows; t++) for (r = 0; r < pattern->columns; r++){ index = t*pattern->columns + r; if (pixel_packet[index].opacity == 0){ temp=tc_malloc(sizeof(struct pixelsMask)); temp->row=t; temp->col=r; temp->r = (uint8_t)ScaleQuantumToChar(pixel_packet[index].red); temp->g = (uint8_t)ScaleQuantumToChar(pixel_packet[index].green); temp->b = (uint8_t)ScaleQuantumToChar(pixel_packet[index].blue); temp->next=NULL; if (pixel_last == NULL){ pixel_last = temp; compare[instance]->pixel_mask = temp; }else{ pixel_last->next = temp; pixel_last = temp; } } } if (verbose) tc_log_info(MOD_NAME, "%s %s", MOD_VERSION, MOD_CAP); } return(0); } //---------------------------------- // // filter close // //---------------------------------- if(ptr->tag & TC_FILTER_CLOSE) { if (compare[instance] != NULL) { fclose(compare[instance]->results); free(compare[instance]); } DestroyMagick(); compare[instance]=NULL; return(0); } /* filter close */ //---------------------------------- // // filter frame routine // //---------------------------------- // tag variable indicates, if we are called before // transcodes internal video/audio frame processing routines // or after and determines video/audio context if((ptr->tag & TC_POST_M_PROCESS) && (ptr->tag & TC_VIDEO)) { // For now I only support RGB color space pixelsMask *item = NULL; double sr,sg,sb; double avg_dr,avg_dg,avg_db; if (compare[instance]->vob->im_v_codec == CODEC_RGB){ int r,g,b,c; double width_long; if (compare[instance]->pixel_mask != NULL) { item = compare[instance]->pixel_mask; c = 0; sr = 0.0; sg = 0.0; sb = 0.0; width_long = compare[instance]->width*3; while(item){ r = item->row*width_long + item->col*3; g = item->row*width_long + item->col*3 + 1; b = item->row*width_long + item->col*3 + 2; // diff between points // Interchange RGB values if necesary sr = sr + (double)abs((unsigned char)ptr->video_buf[r] - item->r); sg = sg + (double)abs((unsigned char)ptr->video_buf[g] - item->g); sb = sb + (double)abs((unsigned char)ptr->video_buf[b] - item->b); item = item->next; c++; } avg_dr = sr/(double)c; avg_dg = sg/(double)c; avg_db = sb/(double)c; if ((avg_dr < compare[instance]->delta) && (avg_dg < compare[instance]->delta) && (avg_db < compare[instance]->delta)) fprintf(compare[instance]->results,"1"); else fprintf(compare[instance]->results,"n"); fflush(compare[instance]->results); } compare[instance]->frames++; return(0); }else{ // The colospace is YUV // FIXME: Doesn't works, I need to code all this part // again int Y,Cr,Cb,c; if (compare[instance]->pixel_mask != NULL) { item = compare[instance]->pixel_mask; c = 0; sr = 0.0; sg = 0.0; sb = 0.0; while(item){ Y = item->row*compare[instance]->width + item->col; Cb = compare[instance]->height*compare[instance]->width + (int)((item->row*compare[instance]->width + item->col)/4); Cr = compare[instance]->height*compare[instance]->width + (int)((compare[instance]->height*compare[instance]->width)/4) + (int)((item->row*compare[instance]->width + item->col)/4); // diff between points // Interchange RGB values if necesary sr = sr + (double)abs((unsigned char)ptr->video_buf[Y] - item->r); sg = sg + (double)abs((unsigned char)ptr->video_buf[Cb] - item->g); sb = sb + (double)abs((unsigned char)ptr->video_buf[Cr] - item->b); item = item->next; c++; } avg_dr = sr/(double)c; avg_dg = sg/(double)c; avg_db = sb/(double)c; if ((avg_dr < compare[instance]->delta) && (avg_dg < compare[instance]->delta) && (avg_db < compare[instance]->delta)) fprintf(compare[instance]->results,"1"); else fprintf(compare[instance]->results,"n"); } compare[instance]->frames++; return(0); } } return(0); }
int probe_source_xml(vob_t *vob, int which) { int retval = 1; #ifdef HAVE_LIBXML2 int tochild[2], fromchild[2]; /* pipes */ pid_t pid; int resize; if (pipe(tochild) == -1) { tc_log_perror(PACKAGE, "probe_source_xml(): pipe(tochild) failed"); return 0; } if (pipe(fromchild) == -1) { tc_log_perror(PACKAGE, "probe_source_xml(): pipe(fromchild) failed"); close(tochild[0]); close(tochild[1]); return 0; } pid = fork(); if (pid == -1) { tc_log_perror(PACKAGE, "probe_source_xml(): fork failed"); return 0; } else if (pid > 0) { /* Child process */ const char *new_argv[6]; close(tochild[1]); close(fromchild[0]); if (tochild[0] != 0) { if (dup2(tochild[0], 0) == -1) { tc_log_perror(PACKAGE, "probe_source_xml(): dup2(0) failed"); exit(-1); } close(tochild[0]); } if (fromchild[1] != 1) { // theoretically always true, but JIC if (dup2(fromchild[1], 1) == -1) { tc_log_perror(PACKAGE, "probe_source_xml(): dup2(1) failed"); exit(-1); } close(fromchild[1]); } new_argv[0] = "tcxmlcheck"; new_argv[1] = "-i"; new_argv[2] = vob->video_in_file; new_argv[3] = "-B"; new_argv[4] = (which==PROBE_XML_VIDEO ? "-V" : "-A"); new_argv[5] = NULL; execvp("tcxmlcheck", (char **)new_argv); tc_log_perror(PACKAGE, "probe_source_xml(): exec(tcxmlcheck) failed"); exit(-1); } /* Parent process */ retval = 0; close(tochild[0]); close(fromchild[1]); if (write(tochild[1], vob, sizeof(vob_t)) != sizeof(vob_t)) { tc_log_error(PACKAGE, "Error writing data to tcxmlcheck: %s", strerror(errno)); close(tochild[1]); close(fromchild[0]); /* Can't just return--need to reap the child */ goto reapchild; } close(tochild[1]); if (read(fromchild[0], vob, sizeof(vob_t)) != sizeof(vob_t)) { tc_log_error(PACKAGE, "Error reading data from tcxmlcheck"); close(fromchild[0]); goto reapchild; } if (read(fromchild[0], &resize, sizeof(int)) != sizeof(int)) { tc_log_error(PACKAGE, "Error reading data from tcxmlcheck 2"); close(fromchild[0]); goto reapchild; } close(fromchild[0]); if (which == PROBE_XML_VIDEO && resize == 2) { // XML forced resize, clear command line parameters resize1 = TC_FALSE; resize2 = TC_FALSE; zoom = TC_FALSE; vob->resize1_mult = 32; vob->vert_resize1 = 0; vob->hori_resize1 = 0; vob->resize2_mult = 32; vob->vert_resize2 = 0; vob->hori_resize2 = 0; vob->zoom_width = 0; vob->zoom_height = 0; vob->zoom_filter = TCV_ZOOM_LANCZOS3; } retval = 1; reapchild: // clean up after the child process waitpid(pid, NULL, 0); #endif // HAVE_LIBXML2 return retval; }
void probe_oss(info_t * ipipe) { int encodings; int encoding; int precision; int channels; int sample_rate; close(ipipe->fd_in); ipipe->fd_in = open(ipipe->name, O_RDONLY, 0); if (ipipe->fd_in < 0) { tc_log_error(__FILE__, "cannot (re)open device: %s", strerror(errno)); goto error; } /* try tc's defaults */ encoding = AFMT_S16_LE; precision = 16; channels = 2; sample_rate = 48000; if (ioctl(ipipe->fd_in, SNDCTL_DSP_GETFMTS, &encodings) < 0) { tc_log_perror(__FILE__, "SNDCTL_DSP_SETFMT"); goto error; } if (encodings & AFMT_S16_LE) { if (ioctl(ipipe->fd_in, SNDCTL_DSP_SETFMT, &encoding) < 0) { if (encodings & AFMT_U8) { encoding = AFMT_U8; precision = 8; if (ioctl(ipipe->fd_in, SNDCTL_DSP_SETFMT, &encoding) < 0) { tc_log_perror(__FILE__, "SNDCTL_DSP_SETFMT"); goto error; } } } } if (ioctl(ipipe->fd_in, SNDCTL_DSP_CHANNELS, &channels) < 0) { tc_log_perror(__FILE__, "SNDCTL_DSP_CHANNELS"); goto error; } if (ipipe->verbose & TC_DEBUG) tc_log_msg(__FILE__, "checking for valid samplerate..."); if (ioctl(ipipe->fd_in, SNDCTL_DSP_SPEED, &sample_rate) < 0) { sample_rate = 44100; if (ioctl(ipipe->fd_in, SNDCTL_DSP_SPEED, &sample_rate) < 0) { sample_rate = 32000; if (ioctl(ipipe->fd_in, SNDCTL_DSP_SPEED, &sample_rate) < 0) { sample_rate = 22050; if (ioctl(ipipe->fd_in, SNDCTL_DSP_SPEED, &sample_rate) < 0) { sample_rate = 24000; if (ioctl(ipipe->fd_in, SNDCTL_DSP_SPEED, &sample_rate) < 0) { sample_rate = 16000; if (ioctl(ipipe->fd_in, SNDCTL_DSP_SPEED, &sample_rate) < 0) { sample_rate = 11025; if (ioctl(ipipe->fd_in, SNDCTL_DSP_SPEED, &sample_rate) < 0) { if (ipipe->verbose & TC_DEBUG) tc_log_msg(__FILE__, "... not found"); goto error; } } } } } } } if (ipipe->verbose & TC_DEBUG) tc_log_msg(__FILE__, "... found %d", sample_rate); ipipe->probe_info->track[0].bits = precision; ipipe->probe_info->track[0].chan = channels; ipipe->probe_info->track[0].samplerate = sample_rate; ipipe->probe_info->track[0].format = 0x1; if (ipipe->probe_info->track[0].chan > 0) ipipe->probe_info->num_tracks = 1; ipipe->probe_info->magic = TC_MAGIC_OSS_AUDIO; ipipe->probe_info->codec = TC_CODEC_PCM; return; error: ipipe->error = 1; ipipe->probe_info->codec = TC_CODEC_UNKNOWN; ipipe->probe_info->magic = TC_MAGIC_UNKNOWN; return; }