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

📄 tvi_v4l.c

📁 君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图片解码,浏览,电子书,录音,想学ucos,识货的人就下吧 russblock fmradio explore set
💻 C
📖 第 1 页 / 共 5 页
字号:
            {                mp_msg(MSGT_TV, MSGL_ERR, "ioctl get channel failed: %s\n", strerror(errno));                return(TVI_CONTROL_FALSE);            }            return(TVI_CONTROL_TRUE);        }        case TVI_CONTROL_SPC_SET_INPUT:        {            struct video_channel chan;            int req_chan = *(int *)arg;            int i;            if (req_chan >= priv->capability.channels)            {                mp_msg(MSGT_TV, MSGL_ERR, "Invalid input requested: %d, valid: 0-%d\n",                       req_chan, priv->capability.channels - 1);                return(TVI_CONTROL_FALSE);            }            for (i = 0; i < priv->capability.channels; i++)            {                if (priv->channels[i].channel == req_chan)                    chan = priv->channels[i];            }            if (ioctl(priv->video_fd, VIDIOCSCHAN, &chan) == -1)            {                mp_msg(MSGT_TV, MSGL_ERR, "ioctl set chan failed: %s\n", strerror(errno));                return(TVI_CONTROL_FALSE);            }            mp_msg(MSGT_TV, MSGL_INFO, "Using input '%s'\n", chan.name);            priv->act_channel = i;            /* update tuner state *///          if (priv->capability.type & VID_TYPE_TUNER)            if (priv->channels[priv->act_channel].flags & VIDEO_VC_TUNER)                control(priv, TVI_CONTROL_TUN_GET_TUNER, 0);            /* update local channel list */            control(priv, TVI_CONTROL_SPC_GET_INPUT, &req_chan);            return(TVI_CONTROL_TRUE);        case TVI_CONTROL_IMMEDIATE:            priv->immediate_mode = 1;            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    }    return(TVI_CONTROL_UNKNOWN);}static int set_mute(priv_t* priv,int value){    if (!priv->capability.audios) {        return 0;	    if(value)        priv->audio[priv->audio_id].flags |=VIDEO_AUDIO_MUTE;    else        priv->audio[priv->audio_id].flags &= ~VIDEO_AUDIO_MUTE;    }    if(ioctl(priv->video_fd, VIDIOCSAUDIO, &priv->audio[priv->audio_id])<0)        return 0;    return 1;}// copies a video frame// for YV12 swaps the 2nd and 3rd planestatic inline void copy_frame(priv_t *priv, unsigned char *dest, unsigned char *source){    if(priv->tv_param->automute>0){        if (ioctl(priv->video_fd, VIDIOCGTUNER, &priv->tuner) >= 0) {            if(priv->tv_param->automute<<8>priv->tuner.signal){                fill_blank_frame(dest,priv->bytesperline * priv->height,priv->format);                set_mute(priv,1);                return;            }        }        set_mute(priv,0);    }    // YV12 uses VIDEO_PALETTE_YUV420P, but the planes are swapped    if (priv->format == IMGFMT_YV12) {        fast_memcpy(dest, source, priv->width * priv->height);        fast_memcpy(dest+priv->width * priv->height*5/4, source+priv->width * priv->height, priv->width * priv->height/4);        fast_memcpy(dest+priv->width * priv->height, source+priv->width * priv->height*5/4, priv->width * priv->height/4);        return;    }    fast_memcpy(dest, source, priv->bytesperline * priv->height);}// maximum skew change, in frames#define MAX_SKEW_DELTA 0.6static void *video_grabber(void *data){#define MAXTOL (priv->nbuf)    priv_t *priv = (priv_t*)data;    struct timeval curtime;    long long skew, prev_skew, xskew, interval, prev_interval;    int frame;    int i;    int framecount;    int tolerance;    unsigned long num;    /* start the capture process */    if ( priv->tv_param->mjpeg )    {        mp_msg(MSGT_TV, MSGL_INFO, "  MJP: gonna capture ! \n");        for (i=0; i < priv->nbuf; i++) {            num = i;            if (ioctl(priv->video_fd, MJPIOC_QBUF_CAPT, &num) < 0)                mp_msg(MSGT_TV, MSGL_ERR,                       "\n  MJP: ioctl MJPIOC_QBUF_CAPT b failed: %s\n", strerror(errno));        }    }    else    {        for (i=0; i < priv->nbuf; i++) {            if (ioctl(priv->video_fd, VIDIOCMCAPTURE, &priv->buf[i]) == -1)                mp_msg(MSGT_TV, MSGL_ERR, "\nioctl mcapture failed: %s\n", strerror(errno));        }    }    gettimeofday(&curtime, NULL);    priv->starttime = (long long)1e6*curtime.tv_sec + curtime.tv_usec;    priv->audio_skew_measure_time = 0;    pthread_mutex_unlock(&priv->audio_starter);    xskew = 0;    skew = 0;    interval = 0;    prev_interval = 0;    prev_skew = 0;    tolerance = MAXTOL;    for (framecount = 0; !priv->shutdown;)    {        for (i = 0; i < priv->nbuf && !priv->shutdown; i++, framecount++) {            if (priv->immediate_mode) {                while (priv->video_cnt == priv->video_buffer_size_max) {                    usleep(10000);                    if (priv->shutdown) {                        return NULL;                    }                }            }            frame = i;            if ( priv->tv_param->mjpeg )            {                while (ioctl(priv->video_fd, MJPIOC_SYNC, &priv->buf[frame].frame) < 0 &&                       (errno == EAGAIN || errno == EINTR));            }            else            {                while (ioctl(priv->video_fd, VIDIOCSYNC, &priv->buf[frame].frame) < 0 &&                       (errno == EAGAIN || errno == EINTR));            }            mp_dbg(MSGT_TV, MSGL_DBG3, "\npicture sync failed\n");            gettimeofday(&curtime, NULL);            if (!priv->immediate_mode) {                interval = (long long)1e6*curtime.tv_sec + curtime.tv_usec - priv->starttime;            } else {                interval = (long long)1e6*framecount/priv->fps;            }            if (!priv->immediate_mode) {                long long period, orig_interval;                if (tolerance == 0) {                    if (interval - prev_interval == 0) {                        mp_msg(MSGT_TV, MSGL_V, "\nvideo capture thread: frame delta = 0\n");                    } else if ((interval - prev_interval < (long long)0.85e6/priv->fps)                               || (interval - prev_interval > (long long)1.15e6/priv->fps) ) {                        mp_msg(MSGT_TV, MSGL_V, "\nvideo capture thread: frame delta ~ %.1lf fps\n",                               (double)1e6/(interval - prev_interval));                    }                }                // correct the rate fluctuations on a small scale                orig_interval = interval;                period = priv->video_interval_sum/VIDEO_AVG_BUFFER_SIZE;                if (interval - prev_interval > 105*period/100) {                    if (tolerance > 0) {                        mp_msg(MSGT_TV, MSGL_DBG3, "correcting timestamp\n");                        interval = prev_interval + priv->video_interval_sum/VIDEO_AVG_BUFFER_SIZE;                        tolerance--;                    } else {                        mp_msg(MSGT_TV, MSGL_DBG3, "bad - frames were dropped\n");                        tolerance = MAXTOL;                    }                } else {                    if (tolerance < MAXTOL) {                        mp_msg(MSGT_TV, MSGL_DBG3, "fluctuation overcome\n");                    }                    tolerance = MAXTOL;                }                priv->video_interval_sum -= priv->video_avg_buffer[priv->video_avg_ptr];                priv->video_avg_buffer[priv->video_avg_ptr++] = orig_interval-prev_interval;                priv->video_interval_sum += orig_interval-prev_interval;                if (priv->video_avg_ptr >= VIDEO_AVG_BUFFER_SIZE) priv->video_avg_ptr = 0;//              fprintf(stderr, "fps: %lf\n", (double)1e6*VIDEO_AVG_BUFFER_SIZE/priv->video_interval_sum);                // interpolate the skew in time                pthread_mutex_lock(&priv->skew_mutex);                xskew = priv->audio_skew + (interval - priv->audio_skew_measure_time)*priv->audio_skew_factor;                pthread_mutex_unlock(&priv->skew_mutex);                // correct extreme skew changes to avoid (especially) moving backwards in time                if (xskew - prev_skew > (interval - prev_interval)*MAX_SKEW_DELTA) {                    skew = prev_skew + (interval - prev_interval)*MAX_SKEW_DELTA;                } else if (xskew - prev_skew < -(interval - prev_interval)*MAX_SKEW_DELTA) {                    skew = prev_skew - (interval - prev_interval)*MAX_SKEW_DELTA;                } else {                    skew = xskew;                }            }            mp_msg(MSGT_TV, MSGL_DBG3, "\nfps = %lf, interval = %lf, a_skew = %f, corr_skew = %f\n",                   (interval != prev_interval) ? (double)1e6/(interval - prev_interval) : -1,                   (double)1e-6*interval, (double)1e-6*xskew, (double)1e-6*skew);            mp_msg(MSGT_TV, MSGL_DBG3, "vcnt = %d, acnt = %d\n", priv->video_cnt, priv->audio_cnt);            prev_skew = skew;            prev_interval = interval;            /* allocate a new buffer, if needed */            pthread_mutex_lock(&priv->video_buffer_mutex);            if (priv->video_buffer_size_current < priv->video_buffer_size_max) {                if (priv->video_cnt == priv->video_buffer_size_current) {                    unsigned char *newbuf = calloc(priv->bytesperline, priv->height);                    if (newbuf) {                        memmove(priv->video_ringbuffer+priv->video_tail+1, priv->video_ringbuffer+priv->video_tail,                               (priv->video_buffer_size_current-priv->video_tail)*sizeof(unsigned char *));                        memmove(priv->video_timebuffer+priv->video_tail+1, priv->video_timebuffer+priv->video_tail,                               (priv->video_buffer_size_current-priv->video_tail)*sizeof(long long));                        priv->video_ringbuffer[priv->video_tail] = newbuf;                        if ((priv->video_head >= priv->video_tail) && (priv->video_cnt > 0)) priv->video_head++;                        priv->video_buffer_size_current++;                    }                }            }            pthread_mutex_unlock(&priv->video_buffer_mutex);            if (priv->video_cnt == priv->video_buffer_size_current) {                if (!priv->immediate_mode) {                    mp_msg(MSGT_TV, MSGL_ERR, "\nvideo buffer full - dropping frame\n");                }            } else {                if (priv->immediate_mode) {                    priv->video_timebuffer[priv->video_tail] = interval;                } else {                    // compensate for audio skew                    // negative skew => there are more audio samples, increase interval                    // positive skew => less samples, shorten the interval                    priv->video_timebuffer[priv->video_tail] = interval - skew;                }                if ( priv->tv_param->mjpeg )                    copy_frame(priv, priv->video_ringbuffer[priv->video_tail],                               priv->mmap+(priv->mjpeg_bufsize)*i);                else                    copy_frame(priv, priv->video_ringbuffer[priv->video_tail],                               priv->mmap+priv->mbuf.offsets[frame]);                priv->video_tail = (priv->video_tail+1)%priv->video_buffer_size_current;                priv->video_cnt++;            }            if ( priv->tv_param->mjpeg )            {                num = frame;                if (ioctl(priv->video_fd, MJPIOC_QBUF_CAPT, &num) < 0)                {                    mp_msg(MSGT_TV, MSGL_ERR, "\n  MJP: ioctl MJPIOC_QBUF_CAPT end failed: %s\n",                           strerror(errno));                    continue;                }            }            else            {                if (ioctl(priv->video_fd, VIDIOCMCAPTURE, &priv->buf[frame]) == -1)                {                    mp_msg(MSGT_TV, MSGL_ERR, "\nioctl mcapture failed: %s\n", strerror(errno));                    continue;                }            }        }    }    mp_msg(MSGT_TV, MSGL_INFO, "  MJP: returning! \n");    return NULL;}static double grab_video_frame(priv_t *priv, char *buffer, int len){    double interval;    if (priv->first) {        pthread_create(&priv->video_grabber_thread, NULL, video_grabber, priv);        priv->first = 0;    }    while (priv->video_cnt == 0) {        usleep(10000);    }    pthread_mutex_lock(&priv->video_buffer_mutex);    interval = (double)priv->video_timebuffer[priv->video_head]*1e-6;    fast_memcpy(buffer, priv->video_ringbuffer[priv->video_head], len);    priv->video_cnt--;    priv->video_head = (priv->video_head+1)%priv->video_buffer_size_current;    pthread_mutex_unlock(&priv->video_buffer_mutex);    return interval;}static int get_video_framesize(priv_t *priv){    return(priv->bytesperline * priv->height);}static void *audio_grabber(void *data){    priv_t *priv = (priv_t*)data;    struct timeval tv;    int i, audio_skew_ptr = 0;    long long current_time, prev_skew = 0;    pthread_mutex_lock(&priv->audio_starter);    audio_in_start_capture(&priv->audio_in);    for (i = 0; i < priv->aud_skew_cnt; i++)        priv->audio_skew_buffer[i] = 0;    for (; !priv->shutdown;)    {        if (audio_in_read_chunk(&priv->audio_in, priv->audio_ringbuffer+priv->audio_tail*priv->audio_in.blocksize) < 0)            continue;        gettimeofday(&tv, NULL);        priv->audio_recv_blocks_total++;        current_time = (long long)1e6*tv.tv_sec +

⌨️ 快捷键说明

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