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

📄 tvi_v4l2.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
📖 第 1 页 / 共 4 页
字号:
/***  Video 4 Linux 2 input****  This file is part of MPlayer, see http://mplayerhq.hu/ for info.  ****  (c) 2003 Martin Olschewski <olschewski@zpr.uni-koeln.de>**  (c) 2003 Jindrich Makovicka <makovick@kmlinux.fjfi.cvut.cz>**  **  File licensed under the GPL, see http://www.fsf.org/ for more info.****  Some ideas are based on works from**    Alex Beregszaszi <alex@naxine.org>**    Gerd Knorr <kraxel@bytesex.org>****  CODE IS UNDER DEVELOPMENT, NO FEATURE REQUESTS PLEASE!*//*known issues:- norm setting isn't consistent with tvi_v4l- the same for volume/bass/treble/balance*/#include "config.h"#if defined(USE_TV) && defined(HAVE_TV_V4L2)#include <errno.h>#include <fcntl.h>#include <pthread.h>#include <stdio.h>#include <string.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>#ifdef HAVE_SYS_SYSINFO_H#include <sys/sysinfo.h>#endif#include "videodev2.h"#include "../mp_msg.h"#include "../libvo/img_format.h"#include "../libaf/af_format.h"#include "tv.h"#include "audio_in.h"/* information about this file */static tvi_info_t info = {    "Video 4 Linux 2 input",    "v4l2",    "Martin Olschewski <olschewski@zpr.uni-koeln.de>",    "first try, more to come ;-)"};struct map {    struct v4l2_buffer buf;    void   *addr;    size_t len;};#define BUFFER_COUNT 6/* private data */typedef struct {    /* video */    char			*video_dev;    int				video_fd;    int                         mp_format;    struct v4l2_capability	capability;    struct v4l2_input           input;    struct v4l2_format		format;    struct v4l2_standard	standard;    struct v4l2_tuner		tuner;    struct map			*map;    int				mapcount;    int				frames;    volatile long long          first_frame;    long long                   curr_frame;    /* audio video interleaving ;-) */    volatile int		streamon;    pthread_t			audio_grabber_thread;    pthread_mutex_t		skew_mutex;    /* 2nd level video buffers */    int                         first;    int                         immediate_mode;    int                         video_buffer_size_max;    volatile int                video_buffer_size_current;    unsigned char		**video_ringbuffer;    long long                   *video_timebuffer;    volatile int		video_head;    volatile int		video_tail;    volatile int		video_cnt;    pthread_t			video_grabber_thread;    pthread_mutex_t             video_buffer_mutex;    /* audio */    char			*audio_dev;    audio_in_t                  audio_in;    long long                   audio_start_time;    int                         audio_buffer_size;    int                         aud_skew_cnt;    unsigned char		*audio_ringbuffer;    long long			*audio_skew_buffer;    long long			*audio_skew_delta_buffer;    volatile int		audio_head;    volatile int		audio_tail;    volatile int		audio_cnt;    volatile long long          audio_skew;    volatile double             audio_skew_factor;    volatile long long          audio_skew_measure_time;    volatile int                audio_drop;    volatile int                shutdown;    double                      audio_secs_per_block;    long long                   audio_skew_total;    long long                   audio_skew_delta_total;    long			audio_recv_blocks_total;    long			audio_sent_blocks_total;} priv_t;#include "tvi_def.h"static void *audio_grabber(void *data);static void *video_grabber(void *data);/**********************************************************************\    Only few of the fourccs are the same in v4l2 and mplayer:    IMGFMT_YVU9 == V4L2_PIX_FMT_YVU410    IMGFMT_YV12 == V4L2_PIX_FMT_YVU420    IMGFMT_NV12 == V4L2_PIX_FMT_NV12    IMGFMT_422P == V4L2_PIX_FMT_YUV422P    IMGFMT_411P == V4L2_PIX_FMT_YUV411P    IMGFMT_UYVY == V4L2_PIX_FMT_UYVY    IMGFMT_Y41P == V4L2_PIX_FMT_Y41P    This may be an useful translation table for some others:    IMGFMT_RGB8  == V4L2_PIX_FMT_RGB332    IMGFMT_RGB15 == V4L2_PIX_FMT_RGB555    IMGFMT_RGB16 == V4L2_PIX_FMT_RGB565    IMGFMT_RGB24 == V4L2_PIX_FMT_RGB24    IMGFMT_RGB32 == V4L2_PIX_FMT_RGB32    IMGFMT_BGR24 == V4L2_PIX_FMT_BGR24    IMGFMT_BGR32 == V4L2_PIX_FMT_BGR32    IMGFMT_Y800  == V4L2_PIX_FMT_GREY    IMGFMT_IF09  == V4L2_PIX_FMT_YUV410    IMGFMT_I420  == V4L2_PIX_FMT_YUV420    IMGFMT_YUY2  == V4L2_PIX_FMT_YUYV\**********************************************************************//*** Translate a mplayer fourcc to a video4linux2 pixel format.*/static int fcc_mp2vl(int fcc){    switch (fcc) {    case IMGFMT_RGB8:	return V4L2_PIX_FMT_RGB332;    case IMGFMT_RGB15:	return V4L2_PIX_FMT_RGB555;    case IMGFMT_RGB16:	return V4L2_PIX_FMT_RGB565;    case IMGFMT_RGB24:	return V4L2_PIX_FMT_RGB24;    case IMGFMT_RGB32:	return V4L2_PIX_FMT_RGB32;    case IMGFMT_BGR24:	return V4L2_PIX_FMT_BGR24;    case IMGFMT_BGR32:	return V4L2_PIX_FMT_BGR32;    case IMGFMT_Y800:	return V4L2_PIX_FMT_GREY;    case IMGFMT_IF09:	return V4L2_PIX_FMT_YUV410;    case IMGFMT_I420:	return V4L2_PIX_FMT_YUV420;    case IMGFMT_YUY2:	return V4L2_PIX_FMT_YUYV;    case IMGFMT_YV12:	return V4L2_PIX_FMT_YUV420;    case IMGFMT_UYVY:   return V4L2_PIX_FMT_UYVY;    }    return fcc;}/*** Translate a video4linux2 fourcc aka pixel format to mplayer.*/static int fcc_vl2mp(int fcc){    switch (fcc) {    case V4L2_PIX_FMT_RGB332:	return IMGFMT_RGB8;    case V4L2_PIX_FMT_RGB555:	return IMGFMT_RGB15;    case V4L2_PIX_FMT_RGB565:	return IMGFMT_RGB16;    case V4L2_PIX_FMT_RGB24:	return IMGFMT_RGB24;    case V4L2_PIX_FMT_RGB32:	return IMGFMT_RGB32;    case V4L2_PIX_FMT_BGR24:	return IMGFMT_BGR24;    case V4L2_PIX_FMT_BGR32:	return IMGFMT_BGR32;    case V4L2_PIX_FMT_GREY:		return IMGFMT_Y800;    case V4L2_PIX_FMT_YUV410:	return IMGFMT_IF09;    case V4L2_PIX_FMT_YUV420:	return IMGFMT_I420;    case V4L2_PIX_FMT_YUYV:		return IMGFMT_YUY2;    case V4L2_PIX_FMT_UYVY:     return IMGFMT_UYVY;    }    return fcc;}/*** Translate a video4linux2 fourcc aka pixel format** to a human readable string.*/static char *pixfmt2name(int pixfmt){    static char unknown[24];    switch (pixfmt) {    case V4L2_PIX_FMT_RGB332:	return "RGB332";    case V4L2_PIX_FMT_RGB555:	return "RGB555";    case V4L2_PIX_FMT_RGB565:	return "RGB565";    case V4L2_PIX_FMT_RGB555X:	return "RGB555X";    case V4L2_PIX_FMT_RGB565X:	return "RGB565X";    case V4L2_PIX_FMT_BGR24:	return "BGR24";    case V4L2_PIX_FMT_RGB24:	return "RGB24";    case V4L2_PIX_FMT_BGR32:	return "BGR32";    case V4L2_PIX_FMT_RGB32:	return "RGB32";    case V4L2_PIX_FMT_GREY:		return "GREY";    case V4L2_PIX_FMT_YVU410:	return "YVU410";    case V4L2_PIX_FMT_YVU420:	return "YVU420";    case V4L2_PIX_FMT_YUYV:		return "YUYV";    case V4L2_PIX_FMT_UYVY:		return "UYVY";/*	case V4L2_PIX_FMT_YVU422P:	return "YVU422P"; *//*	case V4L2_PIX_FMT_YVU411P:	return "YVU411P"; */    case V4L2_PIX_FMT_YUV422P:	return "YUV422P";    case V4L2_PIX_FMT_YUV411P:	return "YUV411P";    case V4L2_PIX_FMT_Y41P:		return "Y41P";    case V4L2_PIX_FMT_NV12:		return "NV12";    case V4L2_PIX_FMT_NV21:		return "NV21";    case V4L2_PIX_FMT_YUV410:	return "YUV410";    case V4L2_PIX_FMT_YUV420:	return "YUV420";    case V4L2_PIX_FMT_YYUV:		return "YYUV";    case V4L2_PIX_FMT_HI240:	return "HI240";    case V4L2_PIX_FMT_WNVA:		return "WNVA";    }    sprintf(unknown, "unknown (0x%x)", pixfmt);    return unknown;}/*** Gives the depth of a video4linux2 fourcc aka pixel format in bits.*/static int pixfmt2depth(int pixfmt){    switch (pixfmt) {    case V4L2_PIX_FMT_RGB332:	return 8;    case V4L2_PIX_FMT_RGB555:    case V4L2_PIX_FMT_RGB565:    case V4L2_PIX_FMT_RGB555X:    case V4L2_PIX_FMT_RGB565X:	return 16;    case V4L2_PIX_FMT_BGR24:    case V4L2_PIX_FMT_RGB24:	return 24;    case V4L2_PIX_FMT_BGR32:    case V4L2_PIX_FMT_RGB32:	return 32;    case V4L2_PIX_FMT_GREY:	return 8;    case V4L2_PIX_FMT_YVU410:	return 9;    case V4L2_PIX_FMT_YVU420:	return 12;    case V4L2_PIX_FMT_YUYV:    case V4L2_PIX_FMT_UYVY:    case V4L2_PIX_FMT_YUV422P:    case V4L2_PIX_FMT_YUV411P:	return 16;    case V4L2_PIX_FMT_Y41P:    case V4L2_PIX_FMT_NV12:    case V4L2_PIX_FMT_NV21:	return 12;    case V4L2_PIX_FMT_YUV410:	return 9;    case V4L2_PIX_FMT_YUV420:	return 12;    case V4L2_PIX_FMT_YYUV:	return 16;    case V4L2_PIX_FMT_HI240:	return 8;    }    return 0;}static int amode2v4l(int amode) {    switch (amode) {    case 0:	return V4L2_TUNER_MODE_MONO;    case 1:	return V4L2_TUNER_MODE_STEREO;    case 2:	return V4L2_TUNER_MODE_LANG1;    case 3:	return V4L2_TUNER_MODE_LANG2;    default:	return -1;    }}// sets and sanitizes audio buffer/block sizesstatic void setup_audio_buffer_sizes(priv_t *priv){    int bytes_per_sample = priv->audio_in.bytes_per_sample;    double fps = priv->standard.frameperiod.denominator /	priv->standard.frameperiod.numerator;    int seconds = priv->video_buffer_size_max/fps;    if (seconds < 5) seconds = 5;    if (seconds > 500) seconds = 500;    // make the audio buffer at least as the video buffer capacity (or 5 seconds) long    priv->audio_buffer_size = 1 + seconds*priv->audio_in.samplerate	*priv->audio_in.channels	*bytes_per_sample/priv->audio_in.blocksize;    if (priv->audio_buffer_size < 256) priv->audio_buffer_size = 256;    // make the skew buffer at least 1 second long    priv->aud_skew_cnt = 1 + 1*priv->audio_in.samplerate	*priv->audio_in.channels	*bytes_per_sample/priv->audio_in.blocksize;    if (priv->aud_skew_cnt < 16) priv->aud_skew_cnt = 16;    mp_msg(MSGT_TV, MSGL_V, "Audio capture - buffer %d blocks of %d bytes, skew average from %d meas.\n",	   priv->audio_buffer_size, priv->audio_in.blocksize, priv->aud_skew_cnt);}#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 *

⌨️ 快捷键说明

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