📄 tvi_v4l2.c
字号:
priv->mp_format = fcc_vl2mp(priv->format.fmt.pix.pixelformat); return TVI_CONTROL_TRUE; case TVI_CONTROL_VID_GET_WIDTH: if (getfmt(priv) < 0) return TVI_CONTROL_FALSE; *(int *)arg = priv->format.fmt.pix.width; mp_msg(MSGT_TV, MSGL_V, "%s: get width: %d\n", info.short_name, *(int *)arg); return TVI_CONTROL_TRUE; case TVI_CONTROL_VID_CHK_WIDTH: return TVI_CONTROL_TRUE; case TVI_CONTROL_VID_SET_WIDTH: if (getfmt(priv) < 0) return TVI_CONTROL_FALSE; priv->format.fmt.pix.width = *(int *)arg; mp_msg(MSGT_TV, MSGL_V, "%s: set width: %d\n", info.short_name, *(int *)arg); if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set width failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } return TVI_CONTROL_TRUE; case TVI_CONTROL_VID_GET_HEIGHT: if (getfmt(priv) < 0) return TVI_CONTROL_FALSE; *(int *)arg = priv->format.fmt.pix.height; mp_msg(MSGT_TV, MSGL_V, "%s: get height: %d\n", info.short_name, *(int *)arg); return TVI_CONTROL_TRUE; case TVI_CONTROL_VID_CHK_HEIGHT: return TVI_CONTROL_TRUE; case TVI_CONTROL_VID_SET_HEIGHT: if (getfmt(priv) < 0) return TVI_CONTROL_FALSE; priv->format.fmt.pix.height = *(int *)arg; priv->format.fmt.pix.field = V4L2_FIELD_ANY; mp_msg(MSGT_TV, MSGL_V, "%s: set height: %d\n", info.short_name, *(int *)arg); if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set height failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } return TVI_CONTROL_TRUE; case TVI_CONTROL_VID_GET_BRIGHTNESS: control.id = V4L2_CID_BRIGHTNESS; if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) { *(int *)arg = control.value; return TVI_CONTROL_TRUE; } return TVI_CONTROL_FALSE; case TVI_CONTROL_VID_SET_BRIGHTNESS: control.id = V4L2_CID_BRIGHTNESS; control.value = *(int *)arg; return set_control(priv, &control, 1); case TVI_CONTROL_VID_GET_HUE: control.id = V4L2_CID_HUE; if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) { *(int *)arg = control.value; return TVI_CONTROL_TRUE; } return TVI_CONTROL_FALSE; case TVI_CONTROL_VID_SET_HUE: control.id = V4L2_CID_HUE; control.value = *(int *)arg; return set_control(priv, &control, 1); case TVI_CONTROL_VID_GET_SATURATION: control.id = V4L2_CID_SATURATION; if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) { *(int *)arg = control.value; return TVI_CONTROL_TRUE; } return TVI_CONTROL_FALSE; case TVI_CONTROL_VID_SET_SATURATION: control.id = V4L2_CID_SATURATION; control.value = *(int *)arg; return set_control(priv, &control, 1); case TVI_CONTROL_VID_GET_GAIN: { control.id = V4L2_CID_AUTOGAIN; if(get_control(priv,&control,0)!=TVI_CONTROL_TRUE) return TVI_CONTROL_FALSE; if(control.value){ //Auto Gain control is enabled *(int*)arg=0; return TVI_CONTROL_TRUE; } //Manual Gain control control.id = V4L2_CID_GAIN; if(get_control(priv,&control,0)!=TVI_CONTROL_TRUE) return TVI_CONTROL_FALSE; *(int*)arg=control.value?control.value:1; return TVI_CONTROL_TRUE; } case TVI_CONTROL_VID_SET_GAIN: { //value==0 means automatic gain control int value=*(int*)arg; if (value < 0 || value>100) return TVI_CONTROL_FALSE; control.id=value?V4L2_CID_GAIN:V4L2_CID_AUTOGAIN; control.value=value?value:1; return set_control(priv,&control,0); } case TVI_CONTROL_VID_GET_CONTRAST: control.id = V4L2_CID_CONTRAST; if (get_control(priv, &control, 1) == TVI_CONTROL_TRUE) { *(int *)arg = control.value; return TVI_CONTROL_TRUE; } return TVI_CONTROL_FALSE; case TVI_CONTROL_VID_SET_CONTRAST: control.id = V4L2_CID_CONTRAST; control.value = *(int *)arg; return set_control(priv, &control, 1); case TVI_CONTROL_TUN_GET_FREQ: frequency.tuner = 0; frequency.type = V4L2_TUNER_ANALOG_TV; if (ioctl(priv->video_fd, VIDIOC_G_FREQUENCY, &frequency) < 0) { mp_msg(MSGT_TV,MSGL_ERR,"%s: ioctl get frequency failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } *(int *)arg = frequency.frequency; return TVI_CONTROL_TRUE; case TVI_CONTROL_TUN_SET_FREQ:#if 0 set_mute(priv, 1); usleep(100000); // wait to suppress noise during switching#endif frequency.tuner = 0; frequency.type = V4L2_TUNER_ANALOG_TV; frequency.frequency = *(int *)arg; if (ioctl(priv->video_fd, VIDIOC_S_FREQUENCY, &frequency) < 0) { mp_msg(MSGT_TV,MSGL_ERR,"%s: ioctl set frequency failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; }#if 0 usleep(100000); // wait to suppress noise during switching set_mute(priv, 0);#endif return TVI_CONTROL_TRUE; case TVI_CONTROL_TUN_GET_TUNER: mp_msg(MSGT_TV, MSGL_V, "%s: get tuner\n",info.short_name); if (ioctl(priv->video_fd, VIDIOC_G_TUNER, &priv->tuner) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get tuner failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } return TVI_CONTROL_TRUE; case TVI_CONTROL_TUN_SET_TUNER: mp_msg(MSGT_TV, MSGL_V, "%s: set tuner\n",info.short_name); if (ioctl(priv->video_fd, VIDIOC_S_TUNER, &priv->tuner) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set tuner failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } return TVI_CONTROL_TRUE; case TVI_CONTROL_TUN_GET_NORM: *(int *)arg = priv->standard.index; return TVI_CONTROL_TRUE; case TVI_CONTROL_TUN_GET_SIGNAL: if (ioctl(priv->video_fd, VIDIOC_G_TUNER, &priv->tuner) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get tuner failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } *(int*)arg=100*(priv->tuner.signal>>8)/255; return TVI_CONTROL_TRUE; case TVI_CONTROL_TUN_SET_NORM: priv->standard.index = *(int *)arg; if (ioctl(priv->video_fd, VIDIOC_ENUMSTD, &priv->standard) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl enum norm failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } mp_msg(MSGT_TV, MSGL_V, "%s: set norm: %s\n", info.short_name, priv->standard.name); if (ioctl(priv->video_fd, VIDIOC_S_STD, &priv->standard.id) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set norm failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } return TVI_CONTROL_TRUE; case TVI_CONTROL_SPC_GET_NORMID: { int i; for (i = 0;; i++) { struct v4l2_standard standard; memset(&standard, 0, sizeof(standard)); standard.index = i; if (-1 == ioctl(priv->video_fd, VIDIOC_ENUMSTD, &standard)) return TVI_CONTROL_FALSE; if (!strcasecmp(standard.name, (char *)arg)) { *(int *)arg = i; return TVI_CONTROL_TRUE; } } return TVI_CONTROL_FALSE; } case TVI_CONTROL_SPC_GET_INPUT: if (ioctl(priv->video_fd, VIDIOC_G_INPUT, (int *)arg) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get input failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } return TVI_CONTROL_TRUE; case TVI_CONTROL_SPC_SET_INPUT: mp_msg(MSGT_TV, MSGL_V, "%s: set input: %d\n", info.short_name, *(int *)arg); priv->input.index = *(int *)arg; if (ioctl(priv->video_fd, VIDIOC_ENUMINPUT, &priv->input) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl enum input failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } if (ioctl(priv->video_fd, VIDIOC_S_INPUT, (int *)arg) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set input failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } return TVI_CONTROL_TRUE; case TVI_CONTROL_AUD_GET_FORMAT: init_audio(priv); if (!priv->audio_inited) return TVI_CONTROL_FALSE; *(int *)arg = AF_FORMAT_S16_LE; mp_msg(MSGT_TV, MSGL_V, "%s: get audio format: %d\n", info.short_name, *(int *)arg); return TVI_CONTROL_TRUE; case TVI_CONTROL_AUD_GET_SAMPLERATE: init_audio(priv); if (!priv->audio_inited) return TVI_CONTROL_FALSE; *(int *)arg = priv->audio_in.samplerate; mp_msg(MSGT_TV, MSGL_V, "%s: get audio samplerate: %d\n", info.short_name, *(int *)arg); return TVI_CONTROL_TRUE; case TVI_CONTROL_AUD_GET_SAMPLESIZE: init_audio(priv); if (!priv->audio_inited) return TVI_CONTROL_FALSE; *(int *)arg = priv->audio_in.bytes_per_sample; mp_msg(MSGT_TV, MSGL_V, "%s: get audio samplesize: %d\n", info.short_name, *(int *)arg); return TVI_CONTROL_TRUE; case TVI_CONTROL_AUD_GET_CHANNELS: init_audio(priv); if (!priv->audio_inited) return TVI_CONTROL_FALSE; *(int *)arg = priv->audio_in.channels; mp_msg(MSGT_TV, MSGL_V, "%s: get audio channels: %d\n", info.short_name, *(int *)arg); return TVI_CONTROL_TRUE; case TVI_CONTROL_AUD_SET_SAMPLERATE: init_audio(priv); mp_msg(MSGT_TV, MSGL_V, "%s: set audio samplerate: %d\n", info.short_name, *(int *)arg); if (audio_in_set_samplerate(&priv->audio_in, *(int*)arg) < 0) return TVI_CONTROL_FALSE;// setup_audio_buffer_sizes(priv); return TVI_CONTROL_TRUE;#ifdef HAVE_TV_TELETEXT case TVI_CONTROL_VBI_INIT: { void* ptr; tt_stream_props tsp; if (vbi_init(priv,*(char**)arg)!=TVI_CONTROL_TRUE) return TVI_CONTROL_FALSE; if(vbi_get_props(priv,&tsp)==TVI_CONTROL_TRUE) { ptr=&tsp; if(teletext_control(NULL,TV_VBI_CONTROL_START,&ptr)==TVI_CONTROL_TRUE) priv->priv_vbi=ptr; else priv->priv_vbi=NULL; } return TVI_CONTROL_TRUE; } default: return teletext_control(priv->priv_vbi,cmd,arg);#endif } mp_msg(MSGT_TV, MSGL_V, "%s: unknown control: %d\n", info.short_name, cmd); return(TVI_CONTROL_UNKNOWN);}#define PRIV ((priv_t *) (tvi_handle->priv))/* handler creator - entry point ! */static tvi_handle_t *tvi_init_v4l2(tv_param_t* tv_param){ tvi_handle_t *tvi_handle; /* new_handle initializes priv with memset 0 */ tvi_handle = new_handle(); if (!tvi_handle) { return NULL; } PRIV->video_fd = -1; PRIV->video_dev = strdup(tv_param->device? tv_param->device: "/dev/video0"); if (!PRIV->video_dev) { free_handle(tvi_handle); return NULL; } if (tv_param->adevice) { PRIV->audio_dev = strdup(tv_param->adevice); if (!PRIV->audio_dev) { free(PRIV->video_dev); free_handle(tvi_handle); return NULL; } } PRIV->tv_param=tv_param; return tvi_handle;}#undef PRIVstatic int uninit(priv_t *priv){ int i, frames, dropped = 0;#ifdef HAVE_TV_TELETEXT priv->vbi_shutdown=1; if(priv->vbi_grabber_thread) pthread_join(priv->vbi_grabber_thread, NULL); teletext_control(priv->priv_vbi,TV_VBI_CONTROL_STOP,(void*)1); priv->priv_vbi=NULL; if(priv->vbi_fd){ close(priv->vbi_fd); priv->vbi_fd=0; } if(priv->vbi_dev){ free(priv->vbi_dev); priv->vbi_dev=0; } #endif priv->shutdown = 1; if(priv->video_grabber_thread) pthread_join(priv->video_grabber_thread, NULL); pthread_mutex_destroy(&priv->video_buffer_mutex); if (priv->streamon) { struct v4l2_buffer buf; /* get performance */ frames = 1 + (priv->curr_frame - priv->first_frame + priv->standard.frameperiod.numerator * 500000 / priv->standard.frameperiod.denominator) * priv->standard.frameperiod.denominator / priv->standard.frameperiod.numerator / 1000000; dropped = frames - priv->frames; /* turn off streaming */ if (ioctl(priv->video_fd, VIDIOC_STREAMOFF, &(priv->map[0].buf.type)) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl streamoff failed: %s\n", info.short_name, strerror(errno));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -