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

📄 stream_pvr.c

📁 君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图片解码,浏览,电子书,录音,想学ucos,识货的人就下吧 russblock fmradio explore set
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  Copyright (C) 2006 Benjamin Zores *  Copyright (C) 2007 Sven Gothel (Channel Navigation) *   Stream layer for hardware MPEG 1/2/4 encoders a.k.a PVR *    (such as WinTV PVR-150/250/350/500 (a.k.a IVTV), pvrusb2 and cx88). *   See http://ivtvdriver.org/index.php/Main_Page for more details on the *    cards supported by the ivtv driver. * *   This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software Foundation, *  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include "config.h"#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <mplaylib.h>#include <ctype.h>#include <sys/time.h>#include <errno.h>#include <sys/ioctl.h>#include <sys/fcntl.h>#include <inttypes.h>#include <sys/poll.h>#include <linux/types.h>#include <linux/videodev2.h>#include "mp_msg.h"#include "help_mp.h"#include "stream.h"#include "pvr.h"#include "frequencies.h"#include "libavutil/common.h"#include "libavutil/avstring.h"#define PVR_DEFAULT_DEVICE "/dev/video0"#define PVR_MAX_CONTROLS 10/* logging mechanisms */#define LOG_LEVEL_PVR  "[pvr]"#define LOG_LEVEL_V4L2 "[v4l2]"#define LOG_LEVEL_ENCODER "[encoder]"/* audio codec mode */#define PVR_AUDIO_MODE_ARG_STEREO                              "stereo"#define PVR_AUDIO_MODE_ARG_JOINT_STEREO                        "joint_stereo"#define PVR_AUDIO_MODE_ARG_DUAL                                "dual"#define PVR_AUDIO_MODE_ARG_MONO                                "mono"/* video codec bitrate mode */#define PVR_VIDEO_BITRATE_MODE_ARG_VBR                         "vbr"#define PVR_VIDEO_BITRATE_MODE_ARG_CBR                         "cbr"/* video codec stream type */#define PVR_VIDEO_STREAM_TYPE_PS                               "ps"#define PVR_VIDEO_STREAM_TYPE_TS                               "ts"#define PVR_VIDEO_STREAM_TYPE_MPEG1                            "mpeg1"#define PVR_VIDEO_STREAM_TYPE_DVD                              "dvd"#define PVR_VIDEO_STREAM_TYPE_VCD                              "vcd"#define PVR_VIDEO_STREAM_TYPE_SVCD                             "svcd"#define PVR_STATION_NAME_SIZE 256/* command line arguments */int pvr_param_aspect_ratio = 0;int pvr_param_sample_rate = 0;int pvr_param_audio_layer = 0;int pvr_param_audio_bitrate = 0;char *pvr_param_audio_mode = NULL;int pvr_param_bitrate = 0;char *pvr_param_bitrate_mode = NULL;int pvr_param_bitrate_peak = 0;char *pvr_param_stream_type = NULL;typedef struct station_elem_s {  char name[8];  int freq;  char station[PVR_STATION_NAME_SIZE];  int enabled;} station_elem_t;typedef struct stationlist_s {  char name[PVR_STATION_NAME_SIZE];  station_elem_t *list;  int total; /* total number */  int used; /* used number */  int enabled; /* enabled number */} stationlist_t;struct pvr_t {  int dev_fd;  char *video_dev;  /* v4l2 params */  int mute;  int input;  int normid;  int brightness;  int contrast;  int hue;  int saturation;  int width;  int height;  int freq;  int chan_idx;  int chan_idx_last;  stationlist_t stationlist;  /* dups the tv_param_channel, or the url's channel param */  char *param_channel;  /* encoder params */  int aspect;  int samplerate;  int layer;  int audio_rate;  int audio_mode;  int bitrate;  int bitrate_mode;  int bitrate_peak;  int stream_type;};static struct pvr_t *pvr_init (void){  struct pvr_t *pvr = NULL;  pvr = calloc (1, sizeof (struct pvr_t));   pvr->dev_fd = -1;  pvr->video_dev = strdup (PVR_DEFAULT_DEVICE);  /* v4l2 params */  pvr->mute = 0;  pvr->input = 0;  pvr->normid = -1;  pvr->brightness = 0;  pvr->contrast = 0;  pvr->hue = 0;  pvr->saturation = 0;  pvr->width = -1;  pvr->height = -1;  pvr->freq = -1;  pvr->chan_idx = -1;  pvr->chan_idx_last = -1;  /* set default encoding settings   * may be overlapped by user parameters   * Use VBR MPEG_PS encoding at 6 Mbps (peak at 9.6 Mbps)   * with 48 KHz L2 384 kbps audio.   */  pvr->aspect = V4L2_MPEG_VIDEO_ASPECT_4x3;  pvr->samplerate = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000;  pvr->layer = V4L2_MPEG_AUDIO_ENCODING_LAYER_2;  pvr->audio_rate = V4L2_MPEG_AUDIO_L2_BITRATE_384K;  pvr->audio_mode = V4L2_MPEG_AUDIO_MODE_STEREO;  pvr->bitrate = 6000000;  pvr->bitrate_mode = V4L2_MPEG_VIDEO_BITRATE_MODE_VBR;  pvr->bitrate_peak = 9600000;  pvr->stream_type = V4L2_MPEG_STREAM_TYPE_MPEG2_PS;    return pvr;}static voidpvr_uninit (struct pvr_t *pvr){  if (!pvr)    return;  /* close device */  if (pvr->dev_fd)    close (pvr->dev_fd);    if (pvr->video_dev)    free (pvr->video_dev);  if (pvr->stationlist.list)    free (pvr->stationlist.list);  if (pvr->param_channel)    free (pvr->param_channel);    free (pvr);}/** * @brief Copy Constructor for stationlist * * @see parse_setup_stationlist */static intcopycreate_stationlist (stationlist_t *stationlist, int num){  int i;  if (chantab < 0 || !stationlist)    return -1;  num = FFMAX (num, chanlists[chantab].count);  if (stationlist->list)  {    free (stationlist->list);    stationlist->list = NULL;  }    stationlist->total = 0;  stationlist->enabled = 0;  stationlist->used = 0;  stationlist->list = calloc (num, sizeof (station_elem_t));  if (!stationlist->list)  {    mp_msg (MSGT_OPEN, MSGL_ERR,            "%s No memory allocated for station list, giving up\n",            LOG_LEVEL_V4L2);    return -1;  }    /* transport the channel list data to our extented struct */  stationlist->total = num;  av_strlcpy (stationlist->name, chanlists[chantab].name, PVR_STATION_NAME_SIZE);  for (i = 0; i < chanlists[chantab].count; i++)  {    stationlist->list[i].station[0]= '\0'; /* no station name yet */    av_strlcpy (stationlist->list[i].name,             chanlists[chantab].list[i].name, PVR_STATION_NAME_SIZE);    stationlist->list[i].freq = chanlists[chantab].list[i].freq;    stationlist->list[i].enabled = 1; /* default enabled */    stationlist->enabled++;    stationlist->used++;  }  return 0;}static intprint_all_stations (struct pvr_t *pvr){  int i;  if (!pvr || !pvr->stationlist.list)     return -1;  for (i = 0; i < pvr->stationlist.total; i++)  {    mp_msg (MSGT_OPEN, MSGL_V,            "%s %3d: [%c] channel: %8s - freq: %8d - station: %s\n",            LOG_LEVEL_V4L2, i, (pvr->stationlist.list[i].enabled) ? 'X' : ' ',            pvr->stationlist.list[i].name, pvr->stationlist.list[i].freq,            pvr->stationlist.list[i].station);  }  return 0;}/** * Disables all stations * * @see parse_setup_stationlist */static voiddisable_all_stations (struct pvr_t *pvr){  int i;  for (i = 0; i < pvr->stationlist.total; i++)    pvr->stationlist.list[i].enabled = 0;  pvr->stationlist.enabled = 0;}/** * Update or add a station * * @see parse_setup_stationlist */static intset_station (struct pvr_t *pvr, const char *station,             const char *channel, int freq){  int i;  if (!pvr || !pvr->stationlist.list)     return -1;  if (0 >= pvr->stationlist.total || (!channel && !freq))    return -1;  /* select channel */  for (i = 0; i < pvr->stationlist.used; i++)  {    if (channel && !strcasecmp (pvr->stationlist.list[i].name, channel))      break; /* found existing channel entry */    if (freq > 0 && pvr->stationlist.list[i].freq == freq)      break; /* found existing frequency entry */  }  if (i < pvr->stationlist.used)  {    /**     * found an existing entry,     * which is about to change with the user data.     * it is also enabled ..     */    if (!pvr->stationlist.list[i].enabled)    {      pvr->stationlist.list[i].enabled = 1;      pvr->stationlist.enabled++;    }        if (station)      av_strlcpy (pvr->stationlist.list[i].station,               station, PVR_STATION_NAME_SIZE);    else if (channel)      av_strlcpy (pvr->stationlist.list[i].station,               channel, PVR_STATION_NAME_SIZE);    else      snprintf (pvr->stationlist.list[i].station,                PVR_STATION_NAME_SIZE, "F %d", freq);    mp_msg (MSGT_OPEN, MSGL_DBG2,            "%s Set user station channel: %8s - freq: %8d - station: %s\n",            LOG_LEVEL_V4L2, pvr->stationlist.list[i].name,            pvr->stationlist.list[i].freq,            pvr->stationlist.list[i].station);    return 0;  }  /* from here on, we have to create a new entry, frequency is mandatory */  if (freq < 0)  {    mp_msg (MSGT_OPEN, MSGL_ERR,            "%s Cannot add new station/channel without frequency\n",            LOG_LEVEL_V4L2);    return -1;  }  if (pvr->stationlist.total < i)  {    /**     * we have to extend the stationlist about      * an arbitrary size, even though this path is not performance critical     */    pvr->stationlist.total += 10;    pvr->stationlist.list =      realloc (pvr->stationlist.list,               pvr->stationlist.total * sizeof (station_elem_t));    if (!pvr->stationlist.list)    {      mp_msg (MSGT_OPEN, MSGL_ERR,              "%s No memory allocated for station list, giving up\n",              LOG_LEVEL_V4L2);      return -1;    }    /* clear the new space ..*/    memset (&(pvr->stationlist.list[pvr->stationlist.used]), 0,            (pvr->stationlist.total - pvr->stationlist.used)            * sizeof (station_elem_t));  }  /* here we go, our actual new entry */  pvr->stationlist.used++;  pvr->stationlist.list[i].enabled = 1;  pvr->stationlist.enabled++;  if (station)    av_strlcpy (pvr->stationlist.list[i].station,             station, PVR_STATION_NAME_SIZE);  if (channel)    av_strlcpy (pvr->stationlist.list[i].name, channel, PVR_STATION_NAME_SIZE);  else    snprintf (pvr->stationlist.list[i].name,              PVR_STATION_NAME_SIZE, "F %d", freq);  pvr->stationlist.list[i].freq = freq;  mp_msg (MSGT_OPEN, MSGL_DBG2,          "%s Add user station channel: %8s - freq: %8d - station: %s\n",          LOG_LEVEL_V4L2, pvr->stationlist.list[i].name,          pvr->stationlist.list[i].freq,          pvr->stationlist.list[i].station);  return 0;}/** * Here we set our stationlist, as follow *  - choose the frequency channel table, e.g. ntsc-cable *  - create our stationlist, same element size as the channellist *  - copy the channellist content to our stationlist *  - IF the user provides his channel-mapping, THEN: *    - disable all stations *    - update and/or create entries in the stationlist and enable them */static intparse_setup_stationlist (struct pvr_t *pvr){  int i;  if (!pvr)     return -1;  /* Create our station/channel list */  if (stream_tv_defaults.chanlist)  {    /* select channel list */    for (i = 0; chanlists[i].name != NULL; i++)    {      if (!strcasecmp (chanlists[i].name, stream_tv_defaults.chanlist))      {        chantab = i;        break;      }    }    if (!chanlists[i].name)    {      mp_msg (MSGT_OPEN, MSGL_ERR,              "%s unable to find channel list %s, using default %s\n",              LOG_LEVEL_V4L2, stream_tv_defaults.chanlist, chanlists[chantab].name);    }    else    {      mp_msg (MSGT_OPEN, MSGL_INFO,              "%s select channel list %s, entries %d\n", LOG_LEVEL_V4L2,               chanlists[chantab].name, chanlists[chantab].count);    }  }    if (0 > chantab)  {    mp_msg (MSGT_OPEN, MSGL_FATAL,            "%s No channel list selected, giving up\n", LOG_LEVEL_V4L2);    return -1;  }  if (copycreate_stationlist (&(pvr->stationlist), -1) < 0)  {    mp_msg (MSGT_OPEN, MSGL_FATAL,            "%s No memory allocated for station list, giving up\n",            LOG_LEVEL_V4L2);    return -1;  }  /* Handle user channel mappings */  if (stream_tv_defaults.channels)   {    char channel[PVR_STATION_NAME_SIZE];    char station[PVR_STATION_NAME_SIZE];    char **channels = stream_tv_defaults.channels;    disable_all_stations (pvr);    while (*channels)     {      char *tmp = *(channels++);      char *sep = strchr (tmp, '-');      int freq=-1;      if (!sep)        continue; /* Wrong syntax, but mplayer should not crash */      av_strlcpy (station, sep + 1, PVR_STATION_NAME_SIZE);      sep[0] = '\0';      av_strlcpy (channel, tmp, PVR_STATION_NAME_SIZE);      while ((sep = strchr (station, '_')))        sep[0] = ' ';      /* if channel number is a number and larger than 1000 treat it as       * frequency tmp still contain pointer to null-terminated string with       * channel number here       */      if ((freq = atoi (channel)) <= 1000)        freq = -1;       if (set_station (pvr, station, (freq <= 0) ? channel : NULL, freq) < 0)      {        mp_msg (MSGT_OPEN, MSGL_ERR,                "%s Unable to set user station channel: %8s - freq: %8d - station: %s\n", LOG_LEVEL_V4L2,                 channel, freq, station);      }    }  }    return print_all_stations (pvr);}static intget_v4l2_freq (struct pvr_t *pvr){  int freq;  struct v4l2_frequency vf;  struct v4l2_tuner vt;  if (!pvr)    return -1;    if (pvr->dev_fd < 0)    return -1;  memset (&vt, 0, sizeof (vt));  memset (&vf, 0, sizeof (vf));  if (ioctl (pvr->dev_fd, VIDIOC_G_TUNER, &vt) < 0)  {    mp_msg (MSGT_OPEN, MSGL_ERR, "%s can't set tuner (%s).\n",            LOG_LEVEL_V4L2, strerror (errno));    return -1;  }  if (ioctl (pvr->dev_fd, VIDIOC_G_FREQUENCY, &vf) < 0)  {    mp_msg (MSGT_OPEN, MSGL_ERR, "%s can't get frequency %d.\n",            LOG_LEVEL_V4L2, errno);    return -1;  }  freq = vf.frequency;  if (!(vt.capability & V4L2_TUNER_CAP_LOW))    freq *= 1000;  freq /= 16;  return freq;}static intset_v4l2_freq (struct pvr_t *pvr){  struct v4l2_frequency vf;  struct v4l2_tuner vt;    if (!pvr)    return -1;    if (0 >= pvr->freq)  {    mp_msg (MSGT_OPEN, MSGL_ERR,            "%s Frequency invalid %d !!!\n", LOG_LEVEL_V4L2, pvr->freq);    return -1;  }  /* don't set the frequency, if it's already set.   * setting it here would interrupt the stream.   */  if (get_v4l2_freq (pvr) == pvr->freq)  {    mp_msg (MSGT_OPEN, MSGL_STATUS,            "%s Frequency %d already set.\n", LOG_LEVEL_V4L2, pvr->freq);    return 0;  }  if (pvr->dev_fd < 0)    return -1;  memset (&vf, 0, sizeof (vf));  memset (&vt, 0, sizeof (vt));  if (ioctl (pvr->dev_fd, VIDIOC_G_TUNER, &vt) < 0)  {    mp_msg (MSGT_OPEN, MSGL_ERR, "%s can't get tuner (%s).\n",            LOG_LEVEL_V4L2, strerror (errno));    return -1;  }  vf.type = vt.type;  vf.frequency = pvr->freq * 16;  if (!(vt.capability & V4L2_TUNER_CAP_LOW))    vf.frequency /= 1000;  if (ioctl (pvr->dev_fd, VIDIOC_S_FREQUENCY, &vf) < 0)  {    mp_msg (MSGT_OPEN, MSGL_ERR, "%s can't set frequency (%s).\n",            LOG_LEVEL_V4L2, strerror (errno));    return -1;

⌨️ 快捷键说明

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