📄 tvi_v4l2.c
字号:
(qctrl.default_value - qctrl.minimum) / 100; } else { control->value = qctrl.default_value + control->value * (qctrl.maximum - qctrl.default_value) / 100; } } else { if (control->value < 50) { control->value = qctrl.default_value + (control->value-50) * (qctrl.default_value - qctrl.minimum) / 50; } else { control->value = qctrl.default_value + (control->value-50) * (qctrl.maximum - qctrl.default_value) / 50; } } if (ioctl(priv->video_fd, VIDIOC_S_CTRL, control) < 0) { mp_msg(MSGT_TV, MSGL_ERR,"%s: ioctl set %s %d failed: %s\n", info.short_name, qctrl.name, control->value, strerror(errno)); return TVI_CONTROL_FALSE; } mp_msg(MSGT_TV, MSGL_V, "%s: set %s: %d [%d, %d]\n", info.short_name, qctrl.name, control->value, qctrl.minimum, qctrl.maximum); return TVI_CONTROL_TRUE;}/*** Scale the control values back to what mplayer needs.*/static int get_control(priv_t *priv, struct v4l2_control *control, int val_signed) { struct v4l2_queryctrl qctrl; qctrl.id = control->id; if (ioctl(priv->video_fd, VIDIOC_QUERYCTRL, &qctrl) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl query control failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } if (ioctl(priv->video_fd, VIDIOC_G_CTRL, control) < 0) { mp_msg(MSGT_TV, MSGL_ERR,"%s: ioctl get %s failed: %s\n", info.short_name, qctrl.name, strerror(errno)); return TVI_CONTROL_FALSE; } mp_msg(MSGT_TV, MSGL_V, "%s: get %s: %d [%d, %d]\n", info.short_name, qctrl.name, control->value, qctrl.minimum, qctrl.maximum); if (val_signed) { if (control->value < qctrl.default_value) { control->value = (control->value - qctrl.default_value) * 100 / (qctrl.default_value - qctrl.minimum); } else { control->value = (control->value - qctrl.default_value) * 100 / (qctrl.maximum - qctrl.default_value); } } else { if (control->value < qctrl.default_value) { control->value = (control->value - qctrl.default_value) * 50 / (qctrl.default_value - qctrl.minimum) + 50; } else { control->value = (control->value - qctrl.default_value) * 50 / (qctrl.maximum - qctrl.default_value) + 50; } } return TVI_CONTROL_TRUE;}static int control(priv_t *priv, int cmd, void *arg){ struct v4l2_control control; struct v4l2_frequency frequency; switch(cmd) { case TVI_CONTROL_IS_AUDIO: if (tv_param_force_audio) return TVI_CONTROL_TRUE; return priv->input.audioset ? TVI_CONTROL_TRUE: TVI_CONTROL_FALSE; case TVI_CONTROL_IS_VIDEO: return priv->capability.capabilities & V4L2_CAP_VIDEO_CAPTURE? TVI_CONTROL_TRUE: TVI_CONTROL_FALSE; case TVI_CONTROL_IS_TUNER: return priv->capability.capabilities & V4L2_CAP_TUNER? TVI_CONTROL_TRUE: TVI_CONTROL_FALSE; case TVI_CONTROL_IMMEDIATE: priv->immediate_mode = 1; return TVI_CONTROL_TRUE; case TVI_CONTROL_VID_GET_FPS: *(float *)arg = priv->standard.frameperiod.denominator / priv->standard.frameperiod.numerator; mp_msg(MSGT_TV, MSGL_V, "%s: get fps: %f\n", info.short_name, *(float *)arg); return TVI_CONTROL_TRUE; case TVI_CONTROL_VID_GET_BITS: if (getfmt(priv) < 0) return TVI_CONTROL_FALSE; *(int *)arg = pixfmt2depth(priv->format.fmt.pix.pixelformat); mp_msg(MSGT_TV, MSGL_V, "%s: get depth: %d\n", info.short_name, *(int *)arg); return TVI_CONTROL_TRUE; case TVI_CONTROL_VID_GET_FORMAT: if (getfmt(priv) < 0) return TVI_CONTROL_FALSE; if (priv->mp_format == IMGFMT_YV12 && priv->format.fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) { *(int *)arg = IMGFMT_YV12; } else { *(int *)arg = fcc_vl2mp(priv->format.fmt.pix.pixelformat); } mp_msg(MSGT_TV, MSGL_V, "%s: get format: %s\n", info.short_name, pixfmt2name(priv->format.fmt.pix.pixelformat)); return TVI_CONTROL_TRUE; case TVI_CONTROL_VID_SET_FORMAT: if (getfmt(priv) < 0) return TVI_CONTROL_FALSE; priv->format.fmt.pix.pixelformat = fcc_mp2vl(*(int *)arg); priv->format.fmt.pix.field = V4L2_FIELD_ANY; priv->mp_format = *(int *)arg; mp_msg(MSGT_TV, MSGL_V, "%s: set format: %s\n", info.short_name, pixfmt2name(priv->format.fmt.pix.pixelformat)); if (ioctl(priv->video_fd, VIDIOC_S_FMT, &priv->format) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl set format failed: %s\n", info.short_name, strerror(errno)); return TVI_CONTROL_FALSE; } 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_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 if (priv->input.audioset) { set_mute(priv, 1); usleep(100000); // wait to supress 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 if (priv->input.audioset) { usleep(100000); // wait to supress 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_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: *(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: *(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: *(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: *(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: 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; } 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 ! */tvi_handle_t *tvi_init_v4l2(char *video_dev, char *audio_dev){ 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(video_dev? video_dev: "/dev/video"); if (!PRIV->video_dev) { free_handle(tvi_handle); return NULL; } if (audio_dev) { PRIV->audio_dev = strdup(audio_dev); if (!PRIV->audio_dev) { free(PRIV->video_dev); free_handle(tvi_handle); return NULL; } } return tvi_handle;}#undef PRIVstatic int uninit(priv_t *priv){ int i, frames, dropped = 0; priv->shutdown = 1; 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)); } priv->streamon = 0; /* unqueue all remaining buffers */ memset(&buf,0,sizeof(buf)); buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; while (!ioctl(priv->video_fd, VIDIOC_DQBUF, &buf)); } /* unmap all buffers */ for (i = 0; i < priv->mapcount; i++) { if (munmap(priv->map[i].addr, priv->map[i].len) < 0) { mp_msg(MSGT_TV, MSGL_ERR, "%s: munmap capture buffer failed: %s\n", info.short_name, strerror(errno)); } } /* stop audio thread */ if (!tv_param_noaudio && !tv_param_immediate) { pthread_join(priv->audio_grabber_thread, NULL); pthread_mutex_destroy(&priv->skew_mutex); } if (priv->input.audioset) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -