⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tvi_v4l2.c

📁 君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图片解码,浏览,电子书,录音,想学ucos,识货的人就下吧 russblock fmradio explore set
💻 C
📖 第 1 页 / 共 5 页
字号:
{    if (priv->audio_inited) return;    if (!priv->tv_param->noaudio) {#if defined(HAVE_ALSA9) || defined(HAVE_ALSA1X)        if (priv->tv_param->alsa)            audio_in_init(&priv->audio_in, AUDIO_IN_ALSA);        else            audio_in_init(&priv->audio_in, AUDIO_IN_OSS);#else        audio_in_init(&priv->audio_in, AUDIO_IN_OSS);#endif        if (priv->audio_dev) {            audio_in_set_device(&priv->audio_in, priv->audio_dev);        }        audio_in_set_samplerate(&priv->audio_in, 44100);        if (priv->capability.capabilities & V4L2_CAP_TUNER) {            if (priv->tuner.audmode == V4L2_TUNER_MODE_STEREO) {                audio_in_set_channels(&priv->audio_in, 2);            } else {                audio_in_set_channels(&priv->audio_in, 1);            }        } else {            if (priv->tv_param->forcechan >= 0) {                audio_in_set_channels(&priv->audio_in, priv->tv_param->forcechan);            } else {                audio_in_set_channels(&priv->audio_in, 2);            }        }        if (audio_in_setup(&priv->audio_in) < 0) return;        priv->audio_inited = 1;    }}#if 0/*** the number of milliseconds elapsed between time0 and time1*/static size_t difftv(struct timeval time1, struct timeval time0){    return        (time1.tv_sec  - time0.tv_sec)  * 1000 +        (time1.tv_usec - time0.tv_usec) / 1000;}#endif/*** Get current video capture format.*/static int getfmt(priv_t *priv){    int i;    priv->format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    if ((i = ioctl(priv->video_fd, VIDIOC_G_FMT, &priv->format)) < 0) {        mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get format failed: %s\n",               info.short_name, strerror(errno));    }    return i;}/*** Get current video capture standard.*/static int getstd(priv_t *priv){    v4l2_std_id id;    int i=0;    if (ioctl(priv->video_fd, VIDIOC_G_STD, &id) < 0) {        mp_msg(MSGT_TV, MSGL_ERR, "%s: ioctl get standard failed: %s\n",               info.short_name, strerror(errno));        return -1;    }    do {        priv->standard.index = i++;        if (ioctl(priv->video_fd, VIDIOC_ENUMSTD, &priv->standard) < 0) {            return -1;        }    } while (priv->standard.id != id);    return 0;}/***********************************************************************\ *                                                                     * *                                                                     * *        Interface to mplayer                                         * *                                                                     * *                                                                     *\***********************************************************************/static int set_mute(priv_t *priv, int value) {    struct v4l2_control control;    control.id = V4L2_CID_AUDIO_MUTE;    control.value = value;    if (ioctl(priv->video_fd, VIDIOC_S_CTRL, &control) < 0) {        mp_msg(MSGT_TV,MSGL_ERR,"%s: ioctl set mute failed: %s\n",               info.short_name, strerror(errno));        return 0;    }    return 1;}/*** MPlayer uses values from -100 up to 100 for controls.** Here they are scaled to what the tv card needs and applied.*/static int set_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 (val_signed) {        if (control->value < 0) {            control->value = qctrl.default_value + control->value *                (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;}#ifdef HAVE_TV_TELETEXTstatic int vbi_init(priv_t* priv,char* device){    int vbi_fd=0;    struct v4l2_capability cap;    struct v4l2_format fmt;    int res;    if(!device)        return TVI_CONTROL_FALSE;    priv->vbi_dev=strdup(device);    vbi_fd=open(priv->vbi_dev,O_RDWR);    if(vbi_fd<0){        mp_msg(MSGT_TV,MSGL_ERR,"vbi: could not open device %s\n",priv->vbi_dev);        return  TVI_CONTROL_FALSE;    }        if(ioctl(vbi_fd,VIDIOC_QUERYCAP,&cap)<0){        mp_msg(MSGT_TV,MSGL_ERR,"vbi: Query capatibilities failed for %s\n",priv->vbi_dev);        close(vbi_fd);        return  TVI_CONTROL_FALSE;    }    if(!cap.capabilities & V4L2_CAP_VBI_CAPTURE){        mp_msg(MSGT_TV,MSGL_ERR,"vbi: %s does not support VBI capture\n",priv->vbi_dev);        close(vbi_fd);        return  TVI_CONTROL_FALSE;    }    memset(&fmt,0,sizeof(struct v4l2_format));    fmt.type=V4L2_BUF_TYPE_VBI_CAPTURE;    if((res=ioctl(vbi_fd,VIDIOC_G_FMT,&fmt))<0){        mp_msg(MSGT_TV,MSGL_ERR,"vbi: Query format failed: %x\n",res);        close(vbi_fd);        return  TVI_CONTROL_FALSE;    }    if(fmt.fmt.vbi.sample_format!=V4L2_PIX_FMT_GREY){        mp_msg(MSGT_TV,MSGL_ERR,"vbi: format 0x%x is not supported\n",fmt.fmt.vbi.sample_format);        close(vbi_fd);        return TVI_CONTROL_FALSE;    }    priv->vbi_fd=vbi_fd;    mp_msg(MSGT_TV,MSGL_DBG3,"vbi: init ok\n");    return TVI_CONTROL_TRUE;}static int vbi_get_props(priv_t* priv,tt_stream_props* ptsp){    struct v4l2_format fmt;    int res;    if(!priv || !ptsp)        return TVI_CONTROL_FALSE;    memset(&fmt,0,sizeof(struct v4l2_format));    fmt.type=V4L2_BUF_TYPE_VBI_CAPTURE;    if((res=ioctl(priv->vbi_fd,VIDIOC_G_FMT,&fmt))<0){        mp_msg(MSGT_TV,MSGL_ERR,"vbi_get_props: Query format failed: %x\n",res);        return  TVI_CONTROL_FALSE;    }    ptsp->interlaced=(fmt.fmt.vbi.flags& V4L2_VBI_INTERLACED?1:0);    ptsp->offset=fmt.fmt.vbi.offset;    ptsp->sampling_rate=fmt.fmt.vbi.sampling_rate;    ptsp->samples_per_line=fmt.fmt.vbi.samples_per_line,    ptsp->count[0]=fmt.fmt.vbi.count[0];    ptsp->count[1]=fmt.fmt.vbi.count[1];    ptsp->bufsize = ptsp->samples_per_line * (ptsp->count[0] + ptsp->count[1]);    mp_msg(MSGT_TV,MSGL_V,"vbi_get_props: sampling_rate=%d,offset:%d,samples_per_line: %d\n interlaced:%s, count=[%d,%d]\n",            ptsp->sampling_rate,        ptsp->offset,        ptsp->samples_per_line,        ptsp->interlaced?"Yes":"No",        ptsp->count[0],        ptsp->count[1]);    return TVI_CONTROL_TRUE;}static void *vbi_grabber(void *data){    priv_t *priv = (priv_t *) data;    int bytes,seq,prev_seq;    unsigned char* buf;    tt_stream_props tsp;    if(!priv->priv_vbi){        mp_msg(MSGT_TV,MSGL_WARN,"vbi: vbi not initialized. stopping thread.\n");        return NULL;    }    if(vbi_get_props(priv,&tsp)!=TVI_CONTROL_TRUE)        return NULL;    buf=malloc(tsp.bufsize);    seq=0;    prev_seq=0;    mp_msg(MSGT_TV,MSGL_V,"vbi: vbi capture thread started.\n");    while (!priv->vbi_shutdown){        bytes=read(priv->vbi_fd,buf,tsp.bufsize);		if (bytes!=tsp.bufsize){	    mp_msg(MSGT_TV,MSGL_WARN,"vbi: expecting bytes: %d, got: %d\n",tsp.bufsize,bytes);	    break;	}        seq=*(int*)(buf+bytes-4);	if(seq<=1) continue;	if (prev_seq && seq!=prev_seq+1){	    prev_seq=0;	    seq=0;	}	prev_seq=seq;        teletext_control(priv->priv_vbi,TV_VBI_CONTROL_DECODE_PAGE,&buf);	mp_msg(MSGT_TV,MSGL_DBG3,"grabber: seq:%d\n",seq);    }    free(buf);    return NULL;}#endif //HAVE_TV_TELETEXTstatic int control(priv_t *priv, int cmd, void *arg){    struct v4l2_control control;    struct v4l2_frequency frequency;    switch(cmd) {    case TVI_CONTROL_IS_VIDEO:        return priv->capability.capabilities & V4L2_CAP_VIDEO_CAPTURE?            TVI_CONTROL_TRUE: TVI_CONTROL_FALSE;    case TVI_CONTROL_IS_AUDIO:        if (priv->tv_param->force_audio) return TVI_CONTROL_TRUE;    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 = (float)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;        *(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;        }        /* according to the v4l2 specs VIDIOC_S_FMT should not fail, inflexible drivers          might even always return the default parameters -> update the format here*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -