13 #include <linux/videodev2.h>
14 #include <linux/dvb/audio.h>
15 #include <linux/dvb/dmx.h>
16 #include <linux/dvb/video.h>
17 #include <sys/ioctl.h>
19 #include <vdr/eitscan.h>
20 #include <vdr/transfer.h>
66 ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX);
79 memset(&hdmiConfig, 0,
sizeof(hdmiConfig));
124 #define BUFFER_SIZE (sizeof(struct v4l2_pix_format) + 1920 * 1080 * 2)
127 uint8_t * result = NULL;
131 esyslog(
"GrabImage: failed open DVB video device");
141 if (readBytes < (
int)
sizeof(
struct v4l2_pix_format))
142 esyslog(
"GrabImage: failed reading from DVB video device");
144 struct v4l2_pix_format * pixfmt;
147 pixfmt = (
struct v4l2_pix_format *) buffer;
148 dsyslog(
"GrabImage: Read image of size %d x %d",
149 pixfmt->width, pixfmt->height);
150 dataSize = readBytes -
sizeof(
struct v4l2_pix_format);
151 if (dataSize < (
int) pixfmt->sizeimage)
152 esyslog(
"GrabImage: image is not complete");
156 temp = (uint8_t *) malloc(pixfmt->width * 3 * pixfmt->height);
158 int numPixels = pixfmt->width * pixfmt->height;
159 uint8_t * destData = temp;
160 uint8_t * srcData = buffer +
sizeof(
struct v4l2_pix_format);
161 while (numPixels > 0)
163 destData[0] = srcData[1];
164 destData[1] = srcData[0];
165 destData[2] = srcData[2];
166 destData[3] = srcData[3];
167 destData[4] = srcData[0];
168 destData[5] = srcData[2];
175 result =
YuvToJpeg(temp, pixfmt->width, pixfmt->height, Size, Quality);
182 snprintf(buf,
sizeof(buf),
"P6\n%d\n%d\n255\n",
183 pixfmt->width, pixfmt->height);
185 Size = l + pixfmt->width * 3 * pixfmt->height;
186 result = (uint8_t *) malloc(Size);
189 memcpy(result, buf, l);
190 uint8_t * destData = result + l;
191 uint8_t * srcData = buffer +
sizeof(
struct v4l2_pix_format);
192 int numPixels = pixfmt->width * pixfmt->height;
193 while (numPixels > 0)
195 int cb = srcData[0] - 128;
197 int cr = srcData[2] - 128;
203 r = y1 + (int) (1.402f * cr);
204 g = y1 - (int) (0.344f * cb + 0.714f * cr);
205 b = y1 + (int) (1.772f * cb);
206 destData[0] = r > 255 ? 255 : r < 0 ? 0 : r;
207 destData[1] = g > 255 ? 255 : g < 0 ? 0 : g;
208 destData[2] = b > 255 ? 255 : b < 0 ? 0 : b;
209 r = y2 + (int) (1.402f * cr);
210 g = y2 - (int) (0.344f * cb + 0.714f * cr);
211 b = y2 + (int) (1.772f * cb);
212 destData[3] = r > 255 ? 255 : r < 0 ? 0 : r;
213 destData[4] = g > 255 ? 255 : g < 0 ? 0 : g;
214 destData[5] = b > 255 ? 255 : b < 0 ? 0 : b;
253 if (ioctl(
fd_video, VIDEO_GET_SIZE, &vs) == 0) {
254 if (vs.h == 480 || vs.h == 240)
267 if (ioctl(
fd_video, VIDEO_GET_SIZE, &vs) == 0) {
270 switch (vs.aspect_ratio) {
272 case VIDEO_FORMAT_4_3: VideoAspect = 4.0 / 3.0;
break;
273 case VIDEO_FORMAT_16_9: VideoAspect = 16.0 / 9.0;
break;
274 case VIDEO_FORMAT_221_1: VideoAspect = 2.21;
break;
293 dmx_pes_filter_params pesFilterParams;
294 memset(&pesFilterParams, 0,
sizeof(pesFilterParams));
327 if (!(Type <= ptDolby && Handle->used <= 1)) {
328 pesFilterParams.pid = Handle->
pid;
329 pesFilterParams.input = DMX_IN_FRONTEND;
330 pesFilterParams.output = DMX_OUT_TS_TAP;
331 pesFilterParams.pes_type= DMX_PES_OTHER;
332 pesFilterParams.flags = DMX_IMMEDIATE_START;
333 if (ioctl(Handle->
handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
339 else if (!Handle->
used) {
374 int apid = Channel->
Apid(0);
375 int vpid = Channel->
Vpid();
376 int dpid = Channel->
Dpid(0);
383 bool TurnOffLivePIDs = DoTune
390 && (LiveView &&
HasPid(vpid ? vpid : apid) && (!pidHandlesVideo || (!pidHandlesAudio && (dpid ?
pidHandles[
ptAudio].
pid != dpid :
true)))
391 || !LiveView && (pidHandlesVideo || pidHandlesAudio)
398 bool TurnOnLivePIDs = !StartTransferMode && LiveView;
412 if (TurnOnLivePIDs) {
418 else if (StartTransferMode)
449 if (TrackId && TrackId->
id) {
495 ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX);
528 ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY);
541 if (ioctl(
fd_video, VIDEO_GET_PTS, &pts) == -1) {
553 if (ioctl(
fd_audio, AUDIO_GET_PTS, &pts) == -1) {
581 double osdPixelAspect;
583 GetOsdSize(osdWidth, osdHeight, osdPixelAspect);
588 int x = (Rect.
X() * 1000 + osdWidth / 2) / osdWidth;
589 int y = (Rect.
Y() * 1000 + osdHeight / 2) / osdHeight;
590 int w = (Rect.
Width() * 1000 + osdWidth / 2) / osdWidth;
591 int h = (Rect.
Height() * 1000 + osdHeight / 2) / osdHeight;
670 if (Data[0] == 0x47) {
674 else if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) {
676 char *buf =
MALLOC(
char, Length);
681 while (i < Length - 6) {
682 if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) {
683 int len = Data[i + 4] * 256 + Data[i + 5];
684 if ((Data[i + 3] & 0xF0) == 0xE0) {
688 if ((Data[i + 6] & 0xC0) == 0x80) {
690 if (Data[i + 8] >= Length)
696 if (len < 0 || offs + len > Length)
701 while (offs < Length && len > 0 && Data[offs] == 0xFF) {
705 if (offs <= Length - 2 && len >= 2 && (Data[offs] & 0xC0) == 0x40) {
709 if (offs <= Length - 5 && len >= 5 && (Data[offs] & 0xF0) == 0x20) {
713 else if (offs <= Length - 10 && len >= 10 && (Data[offs] & 0xF0) == 0x30) {
717 else if (offs < Length && len > 0) {
722 if (blen + len > Length)
724 memcpy(&buf[blen], &Data[offs], len);
728 else if (Data[i + 3] >= 0xBD && Data[i + 3] <= 0xDF)
748 return Poller.
Poll(TimeoutMs);
760 TsBuffer[1] = PusiSet ? 0x40 : 0x00;
761 TsBuffer[1] |= Pid >> 8;
762 TsBuffer[2] = Pid & 0xFF;
765 TsBuffer[3] = 0x10 | Counter;
766 memcpy(TsBuffer + 4, Data, 184);
770 uint8_t adaptationLength;
772 TsBuffer[3] = 0x30 | Counter;
773 adaptationLength = 183 - Length;
774 TsBuffer[4] = adaptationLength;
775 if (adaptationLength > 0)
778 memset(TsBuffer + 6, 0xFF, adaptationLength - 1);
780 memcpy(TsBuffer + 5 + adaptationLength, Data, Length);
793 BuildTsPacket(TsBuffer + tsOffset, i == 0, Pid, Counter, Data + i * 184, Length);
798 Counter = (Counter + 1) & 15;
842 if (streamId >= 0xC0 && streamId <= 0xDF)
846 else if (streamId == 0xBD)
848 const uint8_t * payload = Data + 9 + Data[8];
849 if ((payload[0] & 0xF8) == 0xA0)
854 else if ((payload[0] & 0xF8) == 0x88)
859 else if ((payload[0] & 0xF8) == 0x80)
869 pid = 200 + (int) streamType;
891 int pid =
TsPid(Data);
919 int pid =
TsPid(Data);
922 int AudioStreamType = -1;
929 if (AudioStreamType < 0) {
957 static uint32_t SubsystemIds[] = {
965 uint32_t SubsystemId = 0;
966 FileName =
cString::sprintf(
"/sys/class/dvb/dvb%d.frontend%d/device/subsystem_vendor", Adapter, Frontend);
967 if ((f = fopen(FileName,
"r")) != NULL) {
968 if (
char *s = ReadLine.
Read(f))
969 SubsystemId = strtoul(s, NULL, 0) << 16;
972 FileName =
cString::sprintf(
"/sys/class/dvb/dvb%d.frontend%d/device/subsystem_device", Adapter, Frontend);
973 if ((f = fopen(FileName,
"r")) != NULL) {
974 if (
char *s = ReadLine.
Read(f))
975 SubsystemId |= strtoul(s, NULL, 0);
978 for (uint32_t *sid = SubsystemIds; *sid; sid++) {
979 if (*sid == SubsystemId) {
981 int fd = open(FileName, O_RDWR);
984 dsyslog(
"creating cDvbHdFfDevice");
998 #define JPEGCOMPRESSMEM 4000000
1018 int Used = jcd->
size;
1020 if (
uchar *NewBuffer = (
uchar *)realloc(jcd->
mem, NewSize)) {
1021 jcd->
size = NewSize;
1022 jcd->
mem = NewBuffer;
1025 esyslog(
"ERROR: out of memory");
1029 cinfo->dest->next_output_byte = jcd->
mem + Used;
1030 cinfo->dest->free_in_buffer = jcd->
size - Used;
1041 int Used = cinfo->dest->next_output_byte - jcd->
mem;
1042 if (Used < jcd->size) {
1045 jcd->
mem = NewBuffer;
1048 esyslog(
"ERROR: out of memory");
1057 else if (Quality > 100)
1060 jpeg_destination_mgr jdm;
1066 struct jpeg_compress_struct cinfo;
1067 struct jpeg_error_mgr jerr;
1068 cinfo.err = jpeg_std_error(&jerr);
1069 jpeg_create_compress(&cinfo);
1072 cinfo.client_data = &jcd;
1073 cinfo.image_width = Width;
1074 cinfo.image_height = Height;
1075 cinfo.input_components = 3;
1076 cinfo.in_color_space = JCS_YCbCr;
1078 jpeg_set_defaults(&cinfo);
1079 jpeg_set_quality(&cinfo, Quality,
true);
1080 jpeg_start_compress(&cinfo,
true);
1083 JSAMPROW rp[Height];
1084 for (
int k = 0; k < Height; k++)
1085 rp[k] = &Mem[rs * k];
1086 jpeg_write_scanlines(&cinfo, rp, Height);
1087 jpeg_finish_compress(&cinfo);
1088 jpeg_destroy_compress(&cinfo);