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>
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));
249 if (ioctl(
fd_video, VIDEO_GET_SIZE, &vs) == 0) {
250 if (vs.h == 480 || vs.h == 240)
263 if (ioctl(
fd_video, VIDEO_GET_SIZE, &vs) == 0) {
266 switch (vs.aspect_ratio) {
268 case VIDEO_FORMAT_4_3: VideoAspect = 4.0 / 3.0;
break;
269 case VIDEO_FORMAT_16_9: VideoAspect = 16.0 / 9.0;
break;
270 case VIDEO_FORMAT_221_1: VideoAspect = 2.21;
break;
284 if (ioctl(
fd_video, VIDEO_GET_SIZE, &vs) == 0) {
286 if (vs.h != 480 && vs.h != 240)
292 case VIDEO_FORMAT_4_3: PixelAspect = 4.0 / 3.0;
break;
293 case VIDEO_FORMAT_221_1:
294 case VIDEO_FORMAT_16_9: PixelAspect = 16.0 / 9.0;
break;
296 PixelAspect /= double(Width) / Height;
309 return ioctl(
fd_audio, AUDIO_SET_BYPASS_MODE, On) == 0;
313 static dmx_pes_type_t
PesTypes[] = { DMX_PES_AUDIO, DMX_PES_VIDEO, DMX_PES_PCR, DMX_PES_TELETEXT, DMX_PES_OTHER, DMX_PES_OTHER };
318 dmx_pes_filter_params pesFilterParams;
319 memset(&pesFilterParams, 0,
sizeof(pesFilterParams));
328 pesFilterParams.pid = Handle->
pid;
329 pesFilterParams.input = DMX_IN_FRONTEND;
330 pesFilterParams.output = (Type <=
ptTeletext && Handle->
used <= 1) ? DMX_OUT_DECODER : DMX_OUT_TS_TAP;
332 pesFilterParams.flags = DMX_IMMEDIATE_START;
333 if (ioctl(Handle->
handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
338 else if (!Handle->
used) {
341 pesFilterParams.pid = 0x1FFF;
342 pesFilterParams.input = DMX_IN_FRONTEND;
343 pesFilterParams.output = DMX_OUT_DECODER;
344 pesFilterParams.pes_type=
PesTypes[Type];
345 pesFilterParams.flags = DMX_IMMEDIATE_START;
346 CHECK(ioctl(Handle->
handle, DMX_SET_PES_FILTER, &pesFilterParams));
347 if (
PesTypes[Type] == DMX_PES_VIDEO)
390 int apid = Channel->
Apid(0);
391 int vpid = Channel->
Vpid();
392 int dpid = Channel->
Dpid(0);
399 bool TurnOffLivePIDs = DoTune
406 && (LiveView &&
HasPid(vpid ? vpid : apid) && (!pidHandlesVideo || (!pidHandlesAudio && (dpid ?
pidHandles[
ptAudio].
pid != dpid :
true)))
407 || !LiveView && (pidHandlesVideo || pidHandlesAudio)
412 bool TurnOnLivePIDs = !StartTransferMode && LiveView;
426 if (TurnOnLivePIDs) {
439 else if (StartTransferMode)
449 return as.channel_select;
463 am.volume_left = am.volume_right = 2 * Volume - Volume * Volume / 255;
480 if (TrackId && TrackId->
id) {
522 CHECK(ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
529 CHECK(ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX));
530 CHECK(ioctl(
fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX));
539 CHECK(ioctl(
fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
542 CHECK(ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
549 CHECK(ioctl(
fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
557 CHECK(ioctl(
fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX));
561 CHECK(ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
569 default:
esyslog(
"ERROR: unknown playmode %d", PlayMode);
580 if (ioctl(
fd_stc, DMX_GET_STC, &stc) == -1) {
584 return stc.stc / stc.base;
651 if (Data[0] == 0x47) {
655 else if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) {
657 char *buf =
MALLOC(
char, Length);
662 while (i < Length - 6) {
663 if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) {
664 int len = Data[i + 4] * 256 + Data[i + 5];
665 if ((Data[i + 3] & 0xF0) == 0xE0) {
669 if ((Data[i + 6] & 0xC0) == 0x80) {
671 if (Data[i + 8] >= Length)
677 if (len < 0 || offs + len > Length)
682 while (offs < Length && len > 0 && Data[offs] == 0xFF) {
686 if (offs <= Length - 2 && len >= 2 && (Data[offs] & 0xC0) == 0x40) {
690 if (offs <= Length - 5 && len >= 5 && (Data[offs] & 0xF0) == 0x20) {
694 else if (offs <= Length - 10 && len >= 10 && (Data[offs] & 0xF0) == 0x30) {
698 else if (offs < Length && len > 0) {
703 if (blen + len > Length)
705 memcpy(&buf[blen], &Data[offs], len);
709 else if (Data[i + 3] >= 0xBD && Data[i + 3] <= 0xDF)
717 video_still_picture sp = { buf, blen };
723 video_still_picture sp = { (
char *)Data, Length };
731 return Poller.
Poll(TimeoutMs);
769 static uint32_t SubsystemIds[] = {
783 uint32_t SubsystemId = GetSubsystemId(Adapter, Frontend);
784 for (uint32_t *sid = SubsystemIds; *sid; sid++) {
785 if (*sid == SubsystemId) {
786 dsyslog(
"creating cDvbSdFfDevice");