12 #include <linux/videodev2.h>
13 #include <linux/dvb/audio.h>
14 #include <linux/dvb/dmx.h>
15 #include <linux/dvb/video.h>
16 #include <sys/ioctl.h>
18 #include <vdr/eitscan.h>
19 #include <vdr/transfer.h>
45 char buffer[PATH_MAX];
46 for (
int ofs = 0; ofs < 100; ofs++) {
47 snprintf(buffer,
sizeof(buffer),
"/proc/video/dev/video%d", ofs);
48 if ((f = fopen(buffer,
"r")) != NULL) {
49 if (fgets(buffer,
sizeof(buffer), f)) {
50 if (strstr(buffer,
"DVB Board")) {
106 char buffer[PATH_MAX];
108 int videoDev = open(buffer, O_RDWR);
110 uchar *result = NULL;
113 memset(&fmt, 0,
sizeof(fmt));
114 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
115 fmt.fmt.pix.width = SizeX;
116 fmt.fmt.pix.height = SizeY;
117 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
118 fmt.fmt.pix.field = V4L2_FIELD_ANY;
119 if (ioctl(videoDev, VIDIOC_S_FMT, &fmt) == 0) {
120 v4l2_requestbuffers reqBuf;
121 memset(&reqBuf, 0,
sizeof(reqBuf));
123 reqBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
124 reqBuf.memory = V4L2_MEMORY_MMAP;
125 if (ioctl(videoDev, VIDIOC_REQBUFS, &reqBuf) >= 0) {
127 memset(&mbuf, 0,
sizeof(mbuf));
128 mbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
129 mbuf.memory = V4L2_MEMORY_MMAP;
130 if (ioctl(videoDev, VIDIOC_QUERYBUF, &mbuf) == 0) {
131 int msize = mbuf.length;
132 unsigned char *mem = (
unsigned char *)mmap(0, msize, PROT_READ | PROT_WRITE, MAP_SHARED, videoDev, 0);
133 if (mem && mem != (
unsigned char *)-1) {
135 memset(&buf, 0,
sizeof(buf));
136 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
137 buf.memory = V4L2_MEMORY_MMAP;
139 if (ioctl(videoDev, VIDIOC_QBUF, &buf) == 0) {
140 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
141 if (ioctl (videoDev, VIDIOC_STREAMON, &type) == 0) {
142 memset(&buf, 0,
sizeof(buf));
143 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
144 buf.memory = V4L2_MEMORY_MMAP;
146 if (ioctl(videoDev, VIDIOC_DQBUF, &buf) == 0) {
147 if (ioctl(videoDev, VIDIOC_STREAMOFF, &type) == 0) {
149 int memsize = fmt.fmt.pix.width * fmt.fmt.pix.height;
150 unsigned char *mem1 = mem;
151 for (
int i = 0; i < memsize; i++) {
152 unsigned char tmp = mem1[2];
161 dsyslog(
"grabbing to %s %d %d %d", Jpeg ?
"JPEG" :
"PNM", Quality, fmt.fmt.pix.width, fmt.fmt.pix.height);
164 result =
RgbToJpeg(mem, fmt.fmt.pix.width, fmt.fmt.pix.height, Size, Quality);
166 esyslog(
"ERROR: failed to convert image to JPEG");
171 snprintf(buf,
sizeof(buf),
"P6\n%d\n%d\n255\n", fmt.fmt.pix.width, fmt.fmt.pix.height);
173 int bytes = memsize * 3;
177 memcpy(result, buf, l);
178 memcpy(result + l, mem, bytes);
181 esyslog(
"ERROR: failed to convert image to PNM");
185 esyslog(
"ERROR: video device VIDIOC_STREAMOFF failed");
188 esyslog(
"ERROR: video device VIDIOC_DQBUF failed");
191 esyslog(
"ERROR: video device VIDIOC_STREAMON failed");
194 esyslog(
"ERROR: video device VIDIOC_QBUF failed");
198 esyslog(
"ERROR: failed to memmap video device");
201 esyslog(
"ERROR: video device VIDIOC_QUERYBUF failed");
204 esyslog(
"ERROR: video device VIDIOC_REQBUFS failed");
207 esyslog(
"ERROR: video device VIDIOC_S_FMT failed");
220 CHECK(ioctl(
fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_LETTER_BOX));
223 switch (VideoDisplayFormat) {
225 CHECK(ioctl(
fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_PAN_SCAN));
228 CHECK(ioctl(
fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_LETTER_BOX));
231 CHECK(ioctl(
fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_CENTER_CUT_OUT));
233 default:
esyslog(
"ERROR: unknown video display format %d", VideoDisplayFormat);
240 CHECK(ioctl(
fd_video, VIDEO_SET_FORMAT, VideoFormat16_9 ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3));
248 if (ioctl(
fd_video, VIDEO_GET_SIZE, &vs) == 0) {
251 switch (vs.aspect_ratio) {
253 case VIDEO_FORMAT_4_3: VideoAspect = 4.0 / 3.0;
break;
254 case VIDEO_FORMAT_16_9: VideoAspect = 16.0 / 9.0;
break;
255 case VIDEO_FORMAT_221_1: VideoAspect = 2.21;
break;
269 if (ioctl(
fd_video, VIDEO_GET_SIZE, &vs) == 0) {
271 if (vs.h != 480 && vs.h != 240)
277 case VIDEO_FORMAT_4_3: PixelAspect = 4.0 / 3.0;
break;
278 case VIDEO_FORMAT_221_1:
279 case VIDEO_FORMAT_16_9: PixelAspect = 16.0 / 9.0;
break;
281 PixelAspect /= double(Width) / Height;
294 return ioctl(
fd_audio, AUDIO_SET_BYPASS_MODE, On) == 0;
298 static dmx_pes_type_t
PesTypes[] = { DMX_PES_AUDIO, DMX_PES_VIDEO, DMX_PES_PCR, DMX_PES_TELETEXT, DMX_PES_OTHER, DMX_PES_OTHER };
303 dmx_pes_filter_params pesFilterParams;
304 memset(&pesFilterParams, 0,
sizeof(pesFilterParams));
313 pesFilterParams.pid = Handle->
pid;
314 pesFilterParams.input = DMX_IN_FRONTEND;
315 pesFilterParams.output = (Type <=
ptTeletext && Handle->
used <= 1) ? DMX_OUT_DECODER : DMX_OUT_TS_TAP;
317 pesFilterParams.flags = DMX_IMMEDIATE_START;
318 if (ioctl(Handle->
handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
323 else if (!Handle->
used) {
326 pesFilterParams.pid = 0x1FFF;
327 pesFilterParams.input = DMX_IN_FRONTEND;
328 pesFilterParams.output = DMX_OUT_DECODER;
329 pesFilterParams.pes_type=
PesTypes[Type];
330 pesFilterParams.flags = DMX_IMMEDIATE_START;
331 CHECK(ioctl(Handle->
handle, DMX_SET_PES_FILTER, &pesFilterParams));
332 if (
PesTypes[Type] == DMX_PES_VIDEO)
382 int apid = Channel->
Apid(0);
383 int vpid = Channel->
Vpid();
384 int dpid = Channel->
Dpid(0);
391 bool TurnOffLivePIDs = DoTune
398 && (LiveView &&
HasPid(vpid ? vpid : apid) && (!pidHandlesVideo || (!pidHandlesAudio && (dpid ?
pidHandles[
ptAudio].
pid != dpid :
true)))
399 || !LiveView && (pidHandlesVideo || pidHandlesAudio)
404 bool TurnOnLivePIDs = !StartTransferMode && LiveView;
418 if (TurnOnLivePIDs) {
421 esyslog(
"ERROR: failed to set PIDs for channel %d on device %d", Channel->
Number(), CardIndex() + 1);
431 else if (StartTransferMode)
441 return as.channel_select;
455 am.volume_left = am.volume_right = 2 * Volume - Volume * Volume / 255;
472 if (TrackId && TrackId->
id) {
483 CamSlot()->StartDecrypting();
514 CHECK(ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
521 CHECK(ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX));
522 CHECK(ioctl(
fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX));
531 CHECK(ioctl(
fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
534 CHECK(ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
541 CHECK(ioctl(
fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
549 CHECK(ioctl(
fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX));
553 CHECK(ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
561 default:
esyslog(
"ERROR: unknown playmode %d", PlayMode);
572 if (ioctl(
fd_stc, DMX_GET_STC, &stc) == -1) {
573 esyslog(
"ERROR: stc %d: %m", CardIndex() + 1);
576 return stc.stc / stc.base;
643 if (Data[0] == 0x47) {
647 else if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) {
649 char *buf =
MALLOC(
char, Length);
654 while (i < Length - 6) {
655 if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) {
656 int len = Data[i + 4] * 256 + Data[i + 5];
657 if ((Data[i + 3] & 0xF0) == 0xE0) {
661 if ((Data[i + 6] & 0xC0) == 0x80) {
663 if (Data[i + 8] >= Length)
669 if (len < 0 || offs + len > Length)
674 while (offs < Length && len > 0 && Data[offs] == 0xFF) {
678 if (offs <= Length - 2 && len >= 2 && (Data[offs] & 0xC0) == 0x40) {
682 if (offs <= Length - 5 && len >= 5 && (Data[offs] & 0xF0) == 0x20) {
686 else if (offs <= Length - 10 && len >= 10 && (Data[offs] & 0xF0) == 0x30) {
690 else if (offs < Length && len > 0) {
695 if (blen + len > Length)
697 memcpy(&buf[blen], &Data[offs], len);
701 else if (Data[i + 3] >= 0xBD && Data[i + 3] <= 0xDF)
709 video_still_picture sp = { buf, blen };
715 video_still_picture sp = { (
char *)Data, Length };
723 return Poller.
Poll(TimeoutMs);
761 static uint32_t SubsystemIds[] = {
776 for (uint32_t *sid = SubsystemIds; *sid; sid++) {
777 if (*sid == SubsystemId) {
778 dsyslog(
"creating cDvbSdFfDevice");