Pvrinput-plugin
Inhaltsverzeichnis |
Beschreibung
Autor: Andreas Regel
Dieses Plugin ermöglicht es, analoges TV mit dem VDR in Verbindung mit einer Hauppauge PVR-Karte zu benutzen. Die Funktion ist prinzipiell die gleiche wie beim analogtv-plugin, die Bedienung und Einrichtung jedoch deutlich einfacher. Mit ivtv >= 0.8.0 wurde die Treiber Struktur geändert, so dass z.Z. einige Funktionen von pvrinput damit nicht funktionieren. Für die Erstellung der channels.conf siehe das README zum Plugin. Alternativ kann die channels.conf auch mit w pvrscan erstellt werden, w_pvrscan führt einen automatischen Kanalsuchlauf durch.
Hardwareanforderungen
Softwareanforderungen
- ivtv Treiber (jeweils aktuelle Version verwenden)
Sonstiges
Probleme
- Mit neueren Versionen der IVTV-Treiber kann es beim Setzen des VBI-Modes zu Fehlern kommen. Im Zusammenhang mit dem osdteletext-Plugins kann daher für analoges TV kein Teletext angezeigt werden.
Die Fehlermeldungen lauten: IVTV_IOC_G_CODEC failed, 22: Das Argument ist ungültig Error setting vbi embedded mode, 22: Das Argument ist ungültig.
Die Lösung ist die Datei device.c zu patchen:
--- device.c.old 2006-04-30 17:35:56.000000000 +0200 +++ device.c 2007-04-04 22:51:32.000000000 +0200 @@ -22,7 +22,7 @@ const short kVideoPid = 301; const short kAudioPid = 300; -const short kTeletextPid = 305; +const uint8_t kTeletextPid = (uint8_t)305; typedef enum { @@ -408,18 +408,36 @@ if (vbi_fd > 0) { - int vbi_insert = 1; - if (ioctl(vbi_fd, IVTV_IOC_S_VBI_EMBED, &vbi_insert) < 0) - { - log(0, "Error setting vbi embedded mode, %d:%s", errno, strerror(errno)); - } - struct v4l2_format vbi_fmt; - vbi_fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; - vbi_fmt.fmt.sliced.service_set = V4L2_SLICED_TELETEXT_B; - if (ioctl(vbi_fd, VIDIOC_S_FMT, &vbi_fmt) < 0) - { - log(0, "Error setting vbi mode, %d:%s", errno, strerror(errno)); - } + struct v4l2_ext_control vbi_ctrl; + vbi_ctrl.id = V4L2_CID_MPEG_STREAM_VBI_FMT; + vbi_ctrl.value = V4L2_MPEG_STREAM_VBI_FMT_IVTV; + + struct v4l2_ext_controls ctrls; + bzero(&ctrls, sizeof(struct v4l2_ext_controls)); + ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + ctrls.count = 1; + ctrls.controls = &vbi_ctrl; + + if (ioctl(vbi_fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0) + { + log(0, "Can't enable VBI recording %d:%s", errno, strerror(errno)); + } + + struct v4l2_format vbifmt; + bzero(&vbifmt, sizeof(struct v4l2_format)); + vbifmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE; + vbifmt.fmt.sliced.service_set = V4L2_SLICED_VBI_625; + + if (ioctl(vbi_fd, VIDIOC_S_FMT, &vbifmt) < 0) + { + log(0, "Can't enable VBI recording %d:%s", errno, strerror(errno)); + + } + + if (ioctl(vbi_fd, VIDIOC_G_FMT, &vbifmt) >= 0) + { + log(0, "VBI service: %d, io size: %d" ,vbifmt.fmt.sliced.service_set, vbifmt.fmt.sliced.io_size); + } } while (active) @@ -734,38 +752,65 @@ bool cPvrDevice::SetCodec(void) { - struct ivtv_ioctl_codec codec; + static const uint numCtrls = 7; + struct v4l2_ext_controls ctrls; + struct v4l2_ext_control ext_ctrl[numCtrls]; - if (IOCTL(video_fd, IVTV_IOC_G_CODEC, &codec) != 0) - { - log(0, "IVTV_IOC_G_CODEC failed, %d:%s", errno, strerror(errno)); - return false; - } - codec.stream_type = IVTV_STREAM_PS; // IVTV_STREAM_DVD_S2 - codec.aspect = PvrSetup.AspectRatio + 1; - codec.pulldown = PvrSetup.Pulldown; - codec.bitrate = PvrSetup.VideoBitrate * 1000; - codec.bitrate_peak = 15000000; - codec.bitrate_mode = bitrateCBR; + /* Set controls */ + bzero(&ctrls, sizeof(struct v4l2_ext_controls)); + bzero(&ext_ctrl, sizeof(struct v4l2_ext_control) * numCtrls); - codec.framespergop = PvrSetup.FramesPerGop; // 15 for NTSC - codec.bframes = PvrSetup.BFrames + 1; - codec.gop_closure = PvrSetup.GopClosure; + ext_ctrl[0].id = V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ; + ext_ctrl[0].value = V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000; - codec.dnr_mode = PvrSetup.DnrMode; - codec.dnr_type = PvrSetup.DnrType; - codec.dnr_spatial = PvrSetup.DnrSpatial; - codec.dnr_temporal = PvrSetup.DnrTemporal; + ext_ctrl[2].id = V4L2_CID_MPEG_AUDIO_ENCODING; + ext_ctrl[2].value = V4L2_MPEG_AUDIO_ENCODING_LAYER_2; - codec.audio_bitmask = 0x0009 | ((PvrSetup.AudioBitrate + 1) << 4); - codec.framerate = 1; + ext_ctrl[3].id = V4L2_CID_MPEG_AUDIO_L2_BITRATE; + ext_ctrl[3].value = PvrSetup.AudioBitrate; - if (IOCTL(video_fd, IVTV_IOC_S_CODEC, &codec) != 0) - { - log(0, "IVTV_IOC_S_CODEC failed, %d:%s", errno, strerror(errno)); - return false; - } - return true; + + ext_ctrl[1].id = V4L2_CID_MPEG_VIDEO_ASPECT; + ext_ctrl[1].value = PvrSetup.AspectRatio; + + + ext_ctrl[4].id = V4L2_CID_MPEG_VIDEO_BITRATE; + ext_ctrl[4].value = PvrSetup.VideoBitrate * 1000; + + ext_ctrl[5].id = V4L2_CID_MPEG_VIDEO_BITRATE_PEAK; + ext_ctrl[5].value = 15000000; + + ext_ctrl[6].id = V4L2_CID_MPEG_STREAM_TYPE; + ext_ctrl[6].value = V4L2_MPEG_STREAM_TYPE_MPEG2_PS; + + for (uint i = 0; i < numCtrls; i++) + { + int value = ext_ctrl[i].value; + + ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + ctrls.count = 1; + ctrls.controls = ext_ctrl + i; + + if (IOCTL(video_fd, VIDIOC_S_EXT_CTRLS, &ctrls) < 0) + { + log(0, "VIDIOC_S_EXT_CTRLS set to %d failed %d:%s", value, errno, strerror(errno)); + } + } + + /* Get controls */ + ext_ctrl[0].id = V4L2_CID_MPEG_VIDEO_GOP_SIZE; + ext_ctrl[0].value = 0; + + ctrls.ctrl_class = V4L2_CTRL_CLASS_MPEG; + ctrls.count = 1; + ctrls.controls = ext_ctrl; + + if (IOCTL(video_fd, VIDIOC_G_EXT_CTRLS, &ctrls) < 0) + { + log(0, "Get V4L2_CID_MPEG_VIDEO_GOP_SIZE failed, defaulting to 12 %d:%s", errno, strerror(errno)); + ext_ctrl[0].value = 12; + } + return true; } bool cPvrDevice::SetPicture(int brightness, int contrast, int saturation, int hue)