?? grab-ng.c
字號:
/* * next generation[tm] xawtv capture interfaces * * (c) 2001 Gerd Knorr <kraxel@bytesex.org> * */#define NG_PRIVATE#include "config.h"#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <pthread.h>#include <dirent.h>#include <fnmatch.h>#include <errno.h>#include <ctype.h>#include <inttypes.h>#include <fcntl.h>#include <sys/time.h>#include <sys/types.h>#include <sys/stat.h>#include <dlfcn.h>#ifndef RTLD_NOW# define RTLD_NOW RTLD_LAZY#endif#include "grab-ng.h"int ng_debug = 0;int ng_log_bad_stream = 0;int ng_log_resync = 0;int ng_chromakey = 0x00ff00ff;int ng_ratio_x = 4;int ng_ratio_y = 3;int ng_jpeg_quality = 75;char ng_v4l_conf[256] = "v4l-conf";/* --------------------------------------------------------------------- */const unsigned int ng_vfmt_to_depth[VIDEO_FMT_COUNT] = { 0, /* unused */ 8, /* RGB8 */ 8, /* GRAY8 */ 16, /* RGB15 LE */ 16, /* RGB16 LE */ 16, /* RGB15 BE */ 16, /* RGB16 BE */ 24, /* BGR24 */ 32, /* BGR32 */ 24, /* RGB24 */ 32, /* RGB32 */ 16, /* LUT2 */ 32, /* LUT4 */ 16, /* YUYV */ 16, /* YUV422P */ 12, /* YUV420P */ 0, /* MJPEG */ 0, /* JPEG */ 16, /* UYVY */ 0, /* MPEG */};const char* ng_vfmt_to_desc[VIDEO_FMT_COUNT] = { "none", "8 bit PseudoColor (dithering)", "8 bit StaticGray", "15 bit TrueColor (LE)", "16 bit TrueColor (LE)", "15 bit TrueColor (BE)", "16 bit TrueColor (BE)", "24 bit TrueColor (LE: bgr)", "32 bit TrueColor (LE: bgr-)", "24 bit TrueColor (BE: rgb)", "32 bit TrueColor (BE: -rgb)", "16 bit TrueColor (lut)", "32 bit TrueColor (lut)", "16 bit YUV 4:2:2 (packed, YUYV)", "16 bit YUV 4:2:2 (planar)", "12 bit YUV 4:2:0 (planar)", "MJPEG (AVI)", "JPEG (JFIF)", "16 bit YUV 4:2:2 (packed, UYVY)", "MPEG video",};/* --------------------------------------------------------------------- */const unsigned int ng_afmt_to_channels[AUDIO_FMT_COUNT] = { 0, 1, 2, 1, 2, 1, 2, 0};const unsigned int ng_afmt_to_bits[AUDIO_FMT_COUNT] = { 0, 8, 8, 16, 16, 16, 16, 0};const char* ng_afmt_to_desc[AUDIO_FMT_COUNT] = { "none", "8bit mono", "8bit stereo", "16bit mono (LE)", "16bit stereo (LE)", "16bit mono (BE)", "16bit stereo (BE)", "MPEG audio",};/* --------------------------------------------------------------------- */const char* ng_attr_to_desc[] = { "none", "norm", "input", "volume", "mute", "audio mode", "color", "bright", "hue", "contrast",};/* --------------------------------------------------------------------- */void ng_init_video_buf(struct ng_video_buf *buf){ memset(buf,0,sizeof(*buf)); pthread_mutex_init(&buf->lock,NULL); pthread_cond_init(&buf->cond,NULL);}void ng_release_video_buf(struct ng_video_buf *buf){ int release; pthread_mutex_lock(&buf->lock); buf->refcount--; release = (buf->refcount == 0); pthread_mutex_unlock(&buf->lock); if (release && NULL != buf->release) buf->release(buf);}void ng_print_video_buf(char *tag, struct ng_video_buf *buf){ fprintf(stderr,"buf %5s: %dx%d [%s]\n", tag, buf->fmt.width, buf->fmt.height, ng_vfmt_to_desc[buf->fmt.fmtid]);}void ng_copy_video_buf(struct ng_video_buf *dst, struct ng_video_buf *src){ memcpy(dst->data, src->data, src->size); dst->size = src->size; dst->info = src->info;}void ng_wakeup_video_buf(struct ng_video_buf *buf){ pthread_cond_signal(&buf->cond);}void ng_waiton_video_buf(struct ng_video_buf *buf){ pthread_mutex_lock(&buf->lock); while (buf->refcount) pthread_cond_wait(&buf->cond, &buf->lock); pthread_mutex_unlock(&buf->lock);}static int malloc_video_bufs;static int malloc_audio_bufs;static void ng_free_video_buf(struct ng_video_buf *buf){ free(buf->data); free(buf); malloc_video_bufs--;}struct ng_video_buf*ng_malloc_video_buf(void *handle, struct ng_video_fmt *fmt){ struct ng_video_buf *buf; buf = malloc(sizeof(*buf)); if (NULL == buf) return NULL; ng_init_video_buf(buf); buf->fmt = *fmt; buf->size = fmt->height * fmt->bytesperline; if (0 == buf->size) buf->size = fmt->width * fmt->height * 3; buf->data = malloc(buf->size); if (NULL == buf->data) { free(buf); return NULL; } buf->refcount = 1; buf->release = ng_free_video_buf; malloc_video_bufs++; return buf;}struct ng_audio_buf*ng_malloc_audio_buf(struct ng_audio_fmt *fmt, int size){ struct ng_audio_buf *buf; buf = malloc(sizeof(*buf)+size); memset(buf,0,sizeof(*buf)); buf->fmt = *fmt; buf->size = size; buf->data = (char*)buf + sizeof(*buf); malloc_audio_bufs++; return buf;}void ng_free_audio_buf(struct ng_audio_buf *buf){ malloc_audio_bufs--; free(buf);}static void __fini malloc_bufs_check(void){ OOPS_ON(malloc_video_bufs > 0, "malloc_video_bufs is %d (expected 0)", malloc_video_bufs); OOPS_ON(malloc_audio_bufs > 0, "malloc_audio_bufs is %d (expected 0)", malloc_audio_bufs);}/* --------------------------------------------------------------------- */struct ng_attribute*ng_attr_byid(struct ng_devstate *dev, int id){ struct list_head *item; struct ng_attribute *attr; list_for_each(item, &dev->attrs) { attr = list_entry(item, struct ng_attribute, device_list); if (attr->id == id) return attr; } return NULL;}struct ng_attribute*ng_attr_byname(struct ng_devstate *dev, char *name){ struct list_head *item; struct ng_attribute *attr; list_for_each(item, &dev->attrs) { attr = list_entry(item, struct ng_attribute, device_list); if (0 == strcasecmp(attr->name,name)) return attr; } return NULL;}const char*ng_attr_getstr(struct ng_attribute *attr, int value){ int i; if (NULL == attr) return NULL; if (attr->type != ATTR_TYPE_CHOICE) return NULL; for (i = 0; attr->choices[i].str != NULL; i++) if (attr->choices[i].nr == value) return attr->choices[i].str; return NULL;}intng_attr_getint(struct ng_attribute *attr, char *value){ int i,val; if (NULL == attr) return -1; if (attr->type != ATTR_TYPE_CHOICE) return -1; for (i = 0; attr->choices[i].str != NULL; i++) { if (0 == strcasecmp(attr->choices[i].str,value)) return attr->choices[i].nr; } if (isdigit(value[0])) { /* Hmm. String not found, but starts with a digit. Check if this is a valid number ... */ val = atoi(value); for (i = 0; attr->choices[i].str != NULL; i++) if (val == attr->choices[i].nr) return attr->choices[i].nr; } return -1;}voidng_attr_listchoices(struct ng_attribute *attr){ int i; fprintf(stderr,"valid choices for \"%s\": ",attr->name); for (i = 0; attr->choices[i].str != NULL; i++) fprintf(stderr,"%s\"%s\"", i ? ", " : "", attr->choices[i].str); fprintf(stderr,"\n");}intng_attr_int2percent(struct ng_attribute *attr, int value){ int range,percent; range = attr->max - attr->min; percent = (value - attr->min) * 100 / range; if (percent < 0) percent = 0; if (percent > 100) percent = 100; return percent;}intng_attr_percent2int(struct ng_attribute *attr, int percent){ int range,value; range = attr->max - attr->min; value = percent * range / 100 + attr->min; if (value < attr->min) value = attr->min; if (value > attr->max) value = attr->max; return value;}intng_attr_parse_int(struct ng_attribute *attr, char *str){ int value,n; if (0 == sscanf(str,"%d%n",&value,&n)) /* parse error */ return attr->defval; if (str[n] == '%') value = ng_attr_percent2int(attr,value); if (value < attr->min) value = attr->min; if (value > attr->max) value = attr->max; return value;}/* --------------------------------------------------------------------- */voidng_ratio_fixup(int *width, int *height, int *xoff, int *yoff){ int h = *height; int w = *width; if (0 == ng_ratio_x || 0 == ng_ratio_y) return; if (w * ng_ratio_y < h * ng_ratio_x) { *height = *width * ng_ratio_y / ng_ratio_x; if (yoff) *yoff += (h-*height)/2; } else if (w * ng_ratio_y > h * ng_ratio_x) { *width = *height * ng_ratio_x / ng_ratio_y; if (yoff) *xoff += (w-*width)/2; }}voidng_ratio_fixup2(int *width, int *height, int *xoff, int *yoff, int ratio_x, int ratio_y, int up){ int h = *height; int w = *width; if (0 == ratio_x || 0 == ratio_y) return; if ((!up && w * ratio_y < h * ratio_x) || (up && w * ratio_y > h * ratio_x)) { *height = *width * ratio_y / ratio_x; if (yoff) *yoff += (h-*height)/2; } else if ((!up && w * ratio_y > h * ratio_x) || (up && w * ratio_y < h * ratio_x)) { *width = *height * ratio_x / ratio_y; if (yoff) *xoff += (w-*width)/2; }}/* --------------------------------------------------------------------- */LIST_HEAD(ng_conv);LIST_HEAD(ng_aconv);LIST_HEAD(ng_filters);LIST_HEAD(ng_writers);LIST_HEAD(ng_readers);LIST_HEAD(ng_vid_drivers);LIST_HEAD(ng_dsp_drivers);LIST_HEAD(ng_mix_drivers);static int ng_check_magic(int magic, char *plugname, char *type){ char *h; h=strrchr(plugname,'/'); if (h) h++; else h=plugname; if (magic != NG_PLUGIN_MAGIC) { fprintf(stderr, "ERROR: plugin magic mismatch [me=%x,%s=%x]\n", NG_PLUGIN_MAGIC,h,magic); return -1; }#if 0 if (ng_debug) fprintf(stderr,"plugins: %s registered by %s\n",type,plugname);#endif return 0;}intng_conv_register(int magic, char *plugname, struct ng_video_conv *list, int count){ int n; if (0 != ng_check_magic(magic,plugname,"video converters")) return -1; for (n = 0; n < count; n++) list_add_tail(&(list[n].list),&ng_conv); return 0;}intng_aconv_register(int magic, char *plugname, struct ng_audio_conv *list, int count){ int n; if (0 != ng_check_magic(magic,plugname,"audio converters")) return -1; for (n = 0; n < count; n++) list_add_tail(&(list[n].list),&ng_aconv); return 0;}intng_filter_register(int magic, char *plugname, struct ng_video_filter *filter){ if (0 != ng_check_magic(magic,plugname,"filter")) return -1; list_add_tail(&filter->list,&ng_filters); return 0;}intng_writer_register(int magic, char *plugname, struct ng_writer *writer){ if (0 != ng_check_magic(magic,plugname,"writer")) return -1; list_add_tail(&writer->list,&ng_writers); return 0;}intng_reader_register(int magic, char *plugname, struct ng_reader *reader){ if (0 != ng_check_magic(magic,plugname,"reader")) return -1; list_add_tail(&reader->list,&ng_readers); return 0;}intng_vid_driver_register(int magic, char *plugname, struct ng_vid_driver *driver){ struct list_head *item; struct ng_vid_driver *drv; if (0 != ng_check_magic(magic,plugname,"video drv")) return -1; list_for_each(item,&ng_vid_drivers) { drv = list_entry(item, struct ng_vid_driver, list); if (drv->priority > driver->priority) { list_add_tail(&driver->list,&drv->list); return 0; } } list_add_tail(&driver->list,&ng_vid_drivers); return 0;}intng_dsp_driver_register(int magic, char *plugname, struct ng_dsp_driver *driver){ struct list_head *item; struct ng_dsp_driver *drv; if (0 != ng_check_magic(magic,plugname,"dsp drv")) return -1; list_for_each(item,&ng_dsp_drivers) { drv = list_entry(item, struct ng_dsp_driver, list); if (drv->priority > driver->priority) { list_add_tail(&driver->list,&drv->list); return 0; } } list_add_tail(&driver->list,&ng_dsp_drivers); return 0;}intng_mix_driver_register(int magic, char *plugname, struct ng_mix_driver *driver){ struct list_head *item; struct ng_mix_driver *drv; if (0 != ng_check_magic(magic,plugname,"mixer drv")) return -1; list_for_each(item,&ng_mix_drivers) { drv = list_entry(item, struct ng_mix_driver, list); if (drv->priority > driver->priority) { list_add_tail(&driver->list,&drv->list); return 0; } } list_add_tail(&driver->list,&ng_mix_drivers); return 0;}struct ng_video_conv*ng_conv_find_to(unsigned int out, int *i){ struct list_head *item; struct ng_video_conv *ret; int j = 0; list_for_each(item,&ng_conv) { if (j < *i) { j++; continue; } ret = list_entry(item, struct ng_video_conv, list);#if 0 fprintf(stderr,"\tconv to: %-28s => %s\n", ng_vfmt_to_desc[ret->fmtid_in], ng_vfmt_to_desc[ret->fmtid_out]);#endif if (ret->fmtid_out == out) { (*i)++; return ret; } (*i)++; j++; } return NULL;}struct ng_video_conv*ng_conv_find_from(unsigned int in, int *i){ struct list_head *item; struct ng_video_conv *ret; int j = 0; list_for_each(item,&ng_conv) { if (j < *i) { j++; continue; } ret = list_entry(item, struct ng_video_conv, list);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -