Pvrinput-plugin
Inhaltsverzeichnis |
Beschreibung
Autor: Andreas Regel (bis 2006). Weiterentwicklung seitdem durch Winfried Koehler und Martin Dauskardt
Dieses Plugin ermöglicht es, analoges TV (und UKW-Radio) mit dem VDR in Verbindung mit einer vom Plugin unterstützen 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 die letzte reguläre Version 0.1.1 von pvrinput damit nicht mehr funktioniert. Für die Erstellung der channels.conf siehe das README zum Plugin. Alternativ kann die channels.conf auch mit w pvrscan oder dem Wirbelscan-plugin erstellt werden, die einen automatischen Kanalsuchlauf durchführen.
Hardwareanforderungen
Softwareanforderungen
- ivtv Treiber (jeweils aktuelle Version verwenden)
Sonstiges
Probleme
Teletext-Problem
- 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 @@ -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)