vdr 2.7.7
dvbhdffdevice.c
Go to the documentation of this file.
1/*
2 * dvbhdffdevice.c: The DVB HD Full Featured device interface
3 *
4 * See the README file for copyright information and how to reach the author.
5 */
6
7#include <stdint.h>
8
9#include "dvbhdffdevice.h"
10#include <errno.h>
11#include <limits.h>
12#include <libsi/si.h>
13#include <linux/videodev2.h>
14#include <linux/dvb/dmx.h>
15#include <linux/dvb/video.h>
16#include <sys/ioctl.h>
17#include <sys/mman.h>
18#include <vdr/eitscan.h>
19#include <vdr/transfer.h>
20#include "hdffosd.h"
21#include "setup.h"
22
23
24static uchar *YuvToJpeg(uchar *Mem, int Width, int Height, int &Size, int Quality);
25
26
27// --- cDvbHdFfDevice --------------------------------------------------------
28
30
33{
34 spuDecoder = NULL;
35 audioChannel = 0;
37 mHdffCmdIf = NULL;
38 outputOnly = OutputOnly;
39
40 if (outputOnly) {
42 // cannot close fd_tuner, fd_ca and delete ciAdapter, dvbTuner here - are cDvbDevice private
43 }
44
45 // Devices that are only present on cards with decoders:
46
48 fd_video = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDWR | O_NONBLOCK);
49 fd_audio = DvbOpen(DEV_DVB_AUDIO, adapter, frontend, O_RDWR | O_NONBLOCK);
50
51 //TODO missing /dev/video offset calculation
52
53 isHdffPrimary = false;
54 if (devHdffOffset < 0) {
56 isHdffPrimary = true;
58
59 uint32_t firmwareVersion = mHdffCmdIf->CmdGetFirmwareVersion(NULL, 0);
60 if (firmwareVersion < 0x401)
62 else
64
65 /* reset some stuff in case the VDR was killed before and had no chance
66 to clean up. */
67 mHdffCmdIf->CmdOsdReset();
68
69 mHdffCmdIf->CmdAvSetVideoSpeed(0, 100);
70 mHdffCmdIf->CmdAvSetAudioSpeed(0, 100);
71
72 mHdffCmdIf->CmdAvEnableVideoAfterStop(0, false);
73 mHdffCmdIf->CmdAvSetPcrPid(0, 0);
74 mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF_VIDEO_STREAM_MPEG1);
75 mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_MPEG1);
76
77 ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX);
78 mHdffCmdIf->CmdAvSetDecoderInput(0, 0);
79 mHdffCmdIf->CmdAvEnableSync(0, true);
80 mHdffCmdIf->CmdAvSetPlayMode(0, true);
81 /* reset done */
82
83 mHdffCmdIf->CmdAvSetAudioDelay(gHdffSetup.AudioDelay);
84 mHdffCmdIf->CmdAvSetAudioDownmix((HdffAudioDownmixMode_t) gHdffSetup.AudioDownmix);
85 mHdffCmdIf->CmdAvSetSyncShift(gHdffSetup.AvSyncShift);
86 mHdffCmdIf->CmdMuxSetVideoOut((HdffVideoOut_t) gHdffSetup.AnalogueVideo);
87 mHdffCmdIf->CmdHdmiSetVideoMode(gHdffSetup.GetVideoMode());
88
89 HdffHdmiConfig_t hdmiConfig;
90 memset(&hdmiConfig, 0, sizeof(hdmiConfig));
91 hdmiConfig.TransmitAudio = true;
92 hdmiConfig.ForceDviMode = false;
93 hdmiConfig.CecEnabled = gHdffSetup.CecEnabled;
94 strcpy(hdmiConfig.CecDeviceName, "VDR");
95 hdmiConfig.VideoModeAdaption = (HdffVideoModeAdaption_t) gHdffSetup.VideoModeAdaption;
96 mHdffCmdIf->CmdHdmiConfigure(&hdmiConfig);
97
98 mHdffCmdIf->CmdRemoteSetProtocol((HdffRemoteProtocol_t) gHdffSetup.RemoteProtocol);
99 mHdffCmdIf->CmdRemoteSetAddressFilter(gHdffSetup.RemoteAddress >= 0, gHdffSetup.RemoteAddress);
100 }
101}
102
104{
105 delete spuDecoder;
106 if (isHdffPrimary)
107 {
108 delete mHdffCmdIf;
109 }
110 // We're not explicitly closing any device files here, since this sometimes
111 // caused segfaults. Besides, the program is about to terminate anyway...
112}
113
115{
116 if (On) {
118
119 gHdffSetup.SetVideoFormat(mHdffCmdIf);
120 }
122}
123
125{
126 return isHdffPrimary;
127}
128
135
136uchar *cDvbHdFfDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
137{
138 #define BUFFER_SIZE (sizeof(struct v4l2_pix_format) + 1920 * 1080 * 2)
139 int fd;
140 uint8_t * buffer;
141 uint8_t * result = NULL;
142
143 fd = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDONLY);
144 if (fd < 0) {
145 esyslog("GrabImage: failed open DVB video device");
146 return NULL;
147 }
148
149 buffer = (uint8_t *) malloc(BUFFER_SIZE);
150 if (buffer)
151 {
152 int readBytes;
153
154 readBytes = read(fd, buffer, BUFFER_SIZE);
155 if (readBytes < (int) sizeof(struct v4l2_pix_format))
156 esyslog("GrabImage: failed reading from DVB video device");
157 else {
158 struct v4l2_pix_format * pixfmt;
159 int dataSize;
160
161 pixfmt = (struct v4l2_pix_format *) buffer;
162 dsyslog("GrabImage: Read image of size %d x %d",
163 pixfmt->width, pixfmt->height);
164 dataSize = readBytes - sizeof(struct v4l2_pix_format);
165 if (dataSize < (int) pixfmt->sizeimage)
166 esyslog("GrabImage: image is not complete");
167 else {
168 if (Jpeg) {
169 uint8_t * temp;
170 temp = (uint8_t *) malloc(pixfmt->width * 3 * pixfmt->height);
171 if (temp) {
172 int numPixels = pixfmt->width * pixfmt->height;
173 uint8_t * destData = temp;
174 uint8_t * srcData = buffer + sizeof(struct v4l2_pix_format);
175 while (numPixels > 0)
176 {
177 destData[0] = srcData[1];
178 destData[1] = srcData[0];
179 destData[2] = srcData[2];
180 destData[3] = srcData[3];
181 destData[4] = srcData[0];
182 destData[5] = srcData[2];
183 srcData += 4;
184 destData += 6;
185 numPixels -= 2;
186 }
187 if (Quality < 0)
188 Quality = 100;
189 result = YuvToJpeg(temp, pixfmt->width, pixfmt->height, Size, Quality);
190 free(temp);
191 }
192 }
193 else {
194 // convert to PNM:
195 char buf[32];
196 snprintf(buf, sizeof(buf), "P6\n%d\n%d\n255\n",
197 pixfmt->width, pixfmt->height);
198 int l = strlen(buf);
199 Size = l + pixfmt->width * 3 * pixfmt->height;
200 result = (uint8_t *) malloc(Size);
201 if (result)
202 {
203 memcpy(result, buf, l);
204 uint8_t * destData = result + l;
205 uint8_t * srcData = buffer + sizeof(struct v4l2_pix_format);
206 int numPixels = pixfmt->width * pixfmt->height;
207 while (numPixels > 0)
208 {
209 int cb = srcData[0] - 128;
210 int y1 = srcData[1];
211 int cr = srcData[2] - 128;
212 int y2 = srcData[3];
213 int r;
214 int g;
215 int b;
216
217 r = y1 + (int) (1.402f * cr);
218 g = y1 - (int) (0.344f * cb + 0.714f * cr);
219 b = y1 + (int) (1.772f * cb);
220 destData[0] = r > 255 ? 255 : r < 0 ? 0 : r;
221 destData[1] = g > 255 ? 255 : g < 0 ? 0 : g;
222 destData[2] = b > 255 ? 255 : b < 0 ? 0 : b;
223 r = y2 + (int) (1.402f * cr);
224 g = y2 - (int) (0.344f * cb + 0.714f * cr);
225 b = y2 + (int) (1.772f * cb);
226 destData[3] = r > 255 ? 255 : r < 0 ? 0 : r;
227 destData[4] = g > 255 ? 255 : g < 0 ? 0 : g;
228 destData[5] = b > 255 ? 255 : b < 0 ? 0 : b;
229
230 srcData += 4;
231 destData += 6;
232 numPixels -= 2;
233 }
234 }
235 }
236 }
237 }
238 free(buffer);
239 }
240
241 close(fd);
242
243 return result;
244}
245
247{
248 if (gHdffSetup.TvFormat == HDFF_TV_FORMAT_4_BY_3)
249 {
250 switch (VideoDisplayFormat)
251 {
252 case vdfPanAndScan:
253 case vdfCenterCutOut:
255 break;
256
257 case vdfLetterBox:
259 break;
260 }
261 gHdffSetup.SetVideoFormat(mHdffCmdIf);
262 }
263 cDevice::SetVideoDisplayFormat(VideoDisplayFormat);
264}
265
266void cDvbHdFfDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect)
267{
268 if (fd_video >= 0) {
269 video_size_t vs;
270 if (ioctl(fd_video, VIDEO_GET_SIZE, &vs) == 0) {
271 Width = vs.w;
272 Height = vs.h;
273 switch (vs.aspect_ratio) {
274 default:
275 case VIDEO_FORMAT_4_3: VideoAspect = 4.0 / 3.0; break;
276 case VIDEO_FORMAT_16_9: VideoAspect = 16.0 / 9.0; break;
277 case VIDEO_FORMAT_221_1: VideoAspect = 2.21; break;
278 }
279 return;
280 }
281 else
282 LOG_ERROR;
283 }
284 cDevice::GetVideoSize(Width, Height, VideoAspect);
285}
286
287void cDvbHdFfDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect)
288{
289 gHdffSetup.GetOsdSize(Width, Height, PixelAspect);
290}
291
292bool cDvbHdFfDevice::SetPid(cPidHandle *Handle, int Type, bool On)
293{
294 //printf("SetPid Type %d, On %d, PID %5d, streamtype %d, handle %d, used %d\n", Type, On, Handle->pid, Handle->streamType, Handle->handle, Handle->used);
295 if (Handle->pid) {
296 dmx_pes_filter_params pesFilterParams;
297 memset(&pesFilterParams, 0, sizeof(pesFilterParams));
298 if (On) {
299 if (Handle->handle < 0) {
300 Handle->handle = DvbOpen(DEV_DVB_DEMUX, adapter, frontend, O_RDWR | O_NONBLOCK, true);
301 if (Handle->handle < 0) {
302 LOG_ERROR;
303 return false;
304 }
305 }
306 if (Type == ptPcr)
307 mHdffCmdIf->CmdAvSetPcrPid(0, Handle->pid);
308 else if (Type == ptVideo) {
309 if (Handle->streamType == 0x1B)
310 mHdffCmdIf->CmdAvSetVideoPid(0, Handle->pid, HDFF_VIDEO_STREAM_H264);
311 else
312 mHdffCmdIf->CmdAvSetVideoPid(0, Handle->pid, HDFF_VIDEO_STREAM_MPEG2);
313 }
314 else if (Type == ptAudio) {
315 if (Handle->streamType == 0x03)
316 mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_MPEG1);
317 else if (Handle->streamType == 0x04)
318 mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_MPEG2);
319 else if (Handle->streamType == SI::AC3DescriptorTag)
320 mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_AC3);
321 else if (Handle->streamType == SI::EnhancedAC3DescriptorTag)
322 mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_EAC3);
323 else if (Handle->streamType == 0x0F)
324 mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_AAC);
325 else if (Handle->streamType == 0x11)
326 mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_HE_AAC);
327 else
328 mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_MPEG1);
329 }
330 if (!(Type <= ptDolby && Handle->used <= 1)) {
331 pesFilterParams.pid = Handle->pid;
332 pesFilterParams.input = DMX_IN_FRONTEND;
333 pesFilterParams.output = DMX_OUT_TS_TAP;
334 pesFilterParams.pes_type= DMX_PES_OTHER;
335 pesFilterParams.flags = DMX_IMMEDIATE_START;
336 if (ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
337 LOG_ERROR;
338 return false;
339 }
340 }
341 }
342 else if (!Handle->used) {
343 CHECK(ioctl(Handle->handle, DMX_STOP));
344 if (Type == ptPcr)
345 mHdffCmdIf->CmdAvSetPcrPid(0, 0);
346 else if (Type == ptVideo)
347 mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF_VIDEO_STREAM_MPEG1);
348 else if (Type == ptAudio)
349 mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_MPEG1);
350 else if (Type == ptDolby)
351 mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_AC3);
352 //TODO missing setting to 0x1FFF??? see cDvbDevice::SetPid()
353 close(Handle->handle);
354 Handle->handle = -1;
355 }
356 }
357 return true;
358}
359
360bool cDvbHdFfDevice::ProvidesSource(int Source) const
361{
362 if (outputOnly)
363 return false;
364 return cDvbDevice::ProvidesSource(Source);
365}
366
368{
369 if (outputOnly)
370 return 0;
372}
373
375{
376 // Turn off live PIDs:
377
387}
388
389bool cDvbHdFfDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
390{
391 int apid = Channel->Apid(0);
392 int vpid = Channel->Vpid();
393 int dpid = Channel->Dpid(0);
394
395 bool DoTune = !IsTunedToTransponder(Channel);
396
397 bool pidHandlesVideo = vpid && pidHandles[ptVideo].pid == vpid;
398 bool pidHandlesAudio = apid && pidHandles[ptAudio].pid == apid;
399
400 bool TurnOffLivePIDs = DoTune
401 || !IsPrimaryDevice()
402 || LiveView // for a new live view the old PIDs need to be turned off
403 || pidHandlesVideo // for recording the PIDs must be shifted from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
404 ;
405
406 bool StartTransferMode = IsPrimaryDevice() && !DoTune
407 && (LiveView && HasPid(vpid ? vpid : apid) && (!pidHandlesVideo || (!pidHandlesAudio && (dpid ? pidHandles[ptAudio].pid != dpid : true)))// the PID is already set as DMX_PES_OTHER
408 || !LiveView && (pidHandlesVideo || pidHandlesAudio) // a recording is going to shift the PIDs from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
409 );
410 if (CamSlot() && !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), CamSlot()->SlotNumber()))
411 StartTransferMode |= LiveView && IsPrimaryDevice() && Channel->Ca() >= CA_ENCRYPTED_MIN;
412
413 //printf("SetChannelDevice Transfer %d, Live %d\n", StartTransferMode, LiveView);
414
415 bool TurnOnLivePIDs = !StartTransferMode && LiveView;
416
417 // Turn off live PIDs if necessary:
418
419 if (TurnOffLivePIDs)
420 TurnOffLiveMode(LiveView);
421
422 // Set the tuner:
423
424 if (!cDvbDevice::SetChannelDevice(Channel, LiveView))
425 return false;
426
427 // PID settings:
428
429 if (TurnOnLivePIDs) {
430 if (!(AddPid(Channel->Ppid(), ptPcr) && AddPid(vpid, ptVideo, Channel->Vtype()) && AddPid(apid ? apid : dpid, ptAudio, apid ? 0 : Channel->Dtype(0)))) {
431 esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->Number(), CardIndex() + 1);
432 return false;
433 }
434 }
435 else if (StartTransferMode)
436 cControl::Launch(new cTransferControl(this, Channel));
437
438 return true;
439}
440
445
447{
448 mHdffCmdIf->CmdAvSetAudioChannel(AudioChannel);
449 audioChannel = AudioChannel;
450}
451
453{
454 mHdffCmdIf->CmdMuxSetVolume(Volume * 100 / 255);
455}
456
458{
459 //printf("SetAudioTrackDevice %d\n", Type);
460 const tTrackId *TrackId = GetTrack(Type);
461 if (TrackId && TrackId->id) {
462 int streamType = 0;
463#if (APIVERSNUM >= 20301)
465 const cChannel * channel = Channels->GetByNumber(CurrentChannel());
466#else
467 cChannel * channel = Channels.GetByNumber(CurrentChannel());
468#endif
469 if (channel) {
470 if (IS_AUDIO_TRACK(Type))
471 streamType = channel->Atype(Type - ttAudioFirst);
472 else if (IS_DOLBY_TRACK(Type))
473 streamType = channel->Dtype(Type - ttDolbyFirst);
474 }
475 //printf("SetAudioTrackDevice new %d %d, current %d\n", TrackId->id, streamType, pidHandles[ptAudio].pid);
476 if (pidHandles[ptAudio].pid && pidHandles[ptAudio].pid != TrackId->id) {
478 if (CamSlot())
479 CamSlot()->SetPid(pidHandles[ptAudio].pid, false);
480 pidHandles[ptAudio].pid = TrackId->id;
481 pidHandles[ptAudio].streamType = streamType;
483 if (CamSlot()) {
484 CamSlot()->SetPid(pidHandles[ptAudio].pid, true);
486 }
487 }
488 }
489}
490
492{
493 return cDevice::CanReplay();
494}
495
497{
498 if (PlayMode == pmNone) {
499 if (fd_video == -1)
500 fd_video = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDWR | O_NONBLOCK);
501 if (fd_audio == -1)
502 fd_audio = DvbOpen(DEV_DVB_AUDIO, adapter, frontend, O_RDWR | O_NONBLOCK);
503
504 mHdffCmdIf->CmdAvSetVideoSpeed(0, 100);
505 mHdffCmdIf->CmdAvSetAudioSpeed(0, 100);
506
507 mHdffCmdIf->CmdAvEnableVideoAfterStop(0, false);
508 mHdffCmdIf->CmdAvSetPcrPid(0, 0);
509 mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF_VIDEO_STREAM_MPEG1);
510 mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_MPEG1);
511
512 ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX);
513 mHdffCmdIf->CmdAvSetDecoderInput(0, 0);
514 mHdffCmdIf->CmdAvEnableSync(0, true);
515 mHdffCmdIf->CmdAvSetPlayMode(0, true);
516 mHdffCmdIf->CmdAvMuteAudio(0, false);
517 }
518 else {
519 if (playMode == pmNone)
520 TurnOffLiveMode(true);
521
522 if (PlayMode == pmExtern_THIS_SHOULD_BE_AVOIDED)
523 {
524 close(fd_video);
525 fd_video = -1;
526 close(fd_audio);
527 fd_audio = -1;
528 }
529 else
530 {
532 mHdffCmdIf->CmdAvSetPlayMode(1, isTransferMode);
533 mHdffCmdIf->CmdAvSetStc(0, 100000);
534 mHdffCmdIf->CmdAvEnableSync(0, false);
535 mHdffCmdIf->CmdAvEnableVideoAfterStop(0, true);
536
537 playVideoPid = -1;
538 playAudioPid = -1;
539 playPcrPid = -1;
540 audioCounter = 0;
541 videoCounter = 0;
542 freezed = false;
543 trickMode = false;
544 isPlayingVideo = false;
545
546 mHdffCmdIf->CmdAvSetDecoderInput(0, 2);
547 ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY);
548 }
549 }
550 playMode = PlayMode;
551 return true;
552}
553
555{
556 if (isPlayingVideo)
557 {
558 if (fd_video >= 0) {
559 uint64_t pts;
560 if (ioctl(fd_video, VIDEO_GET_PTS, &pts) == -1) {
561 esyslog("ERROR: pts %d: %m", CardIndex() + 1);
562 return -1;
563 }
564 //printf("video PTS %lld\n", pts);
565 return pts;
566 }
567 }
568 else
569 {
570 if (fd_audio >= 0) {
571 uint64_t pts;
572 if (ioctl(fd_audio, AUDIO_GET_PTS, &pts) == -1) {
573 esyslog("ERROR: pts %d: %m", CardIndex() + 1);
574 return -1;
575 }
576 //printf("audio PTS %lld\n", pts);
577 return pts;
578 }
579 }
580 return -1;
581}
582
583cRect cDvbHdFfDevice::CanScaleVideo(const cRect &Rect, int Alignment)
584{
585 return Rect;
586}
587
589{
590 if (Rect == cRect::Null)
591 {
592 mHdffCmdIf->CmdAvSetVideoWindow(0, false, 0, 0, 0, 0);
593 }
594 else
595 {
596 //printf("ScaleVideo: Rect = %d %d %d %d\n", Rect.X(), Rect.Y(), Rect.Width(), Rect.Height());
597
598 int osdWidth;
599 int osdHeight;
600 double osdPixelAspect;
601
602 GetOsdSize(osdWidth, osdHeight, osdPixelAspect);
603 //printf("ScaleVideo: OsdSize = %d %d %g\n", osdWidth, osdHeight, osdPixelAspect);
604
605 // Convert the video window coordinates in 1/10 percent of the display
606 // resolution.
607 int x = (Rect.X() * 1000 + osdWidth / 2) / osdWidth;
608 int y = (Rect.Y() * 1000 + osdHeight / 2) / osdHeight;
609 int w = (Rect.Width() * 1000 + osdWidth / 2) / osdWidth;
610 int h = (Rect.Height() * 1000 + osdHeight / 2) / osdHeight;
611 //printf("ScaleVideo: Win1 = %d %d %d %d\n", x, y, w, h);
612
613 // fix aspect ratio, reposition video
614 if (w > h) {
615 x += (w - h) / 2;
616 w = h;
617 }
618 else if (w < h) {
619 y += (h - w) / 2;
620 h = w;
621 }
622
623 //printf("ScaleVideo: Win2 = %d %d %d %d\n", x, y, w, h);
624 mHdffCmdIf->CmdAvSetVideoWindow(0, true, x, y, w, h);
625 }
626}
627
628#if (APIVERSNUM >= 20103)
629void cDvbHdFfDevice::TrickSpeed(int Speed, bool Forward)
630#else
632#endif
633{
634 freezed = false;
635 mHdffCmdIf->CmdAvEnableSync(0, false);
636 mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_MPEG1);
637 playAudioPid = -1;
638 if (Speed > 0)
639 mHdffCmdIf->CmdAvSetVideoSpeed(0, 100 / Speed);
640 trickMode = true;
641}
642
644{
645 CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER));
646 mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF_VIDEO_STREAM_MPEG1);
647 mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_MPEG1);
648 playVideoPid = -1;
649 playAudioPid = -1;
651}
652
654{
655 freezed = false;
656 trickMode = false;
657 if (isPlayingVideo)
658 mHdffCmdIf->CmdAvEnableSync(0, true);
659 mHdffCmdIf->CmdAvSetVideoSpeed(0, 100);
660 mHdffCmdIf->CmdAvSetAudioSpeed(0, 100);
661 mHdffCmdIf->CmdAvMuteAudio(0, false);
663}
664
666{
667 freezed = true;
668 mHdffCmdIf->CmdAvSetVideoSpeed(0, 0);
669 mHdffCmdIf->CmdAvSetAudioSpeed(0, 0);
671}
672
674{
675 mHdffCmdIf->CmdAvMuteAudio(0, true);
677}
678
680{
681 switch (Vtype) {
682 case 0x01: return HDFF_VIDEO_STREAM_MPEG1;
683 case 0x02: return HDFF_VIDEO_STREAM_MPEG2;
684 case 0x1B: return HDFF_VIDEO_STREAM_H264;
685 default: return HDFF_VIDEO_STREAM_MPEG2; // fallback to MPEG2
686 }
687}
688
689void cDvbHdFfDevice::StillPicture(const uchar *Data, int Length)
690{
691 if (!Data || Length < TS_SIZE)
692 return;
693 if (Data[0] == 0x47) {
694 // TS data
695 cDevice::StillPicture(Data, Length);
696 }
697 else if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) {
698 // PES data
699 char *buf = MALLOC(char, Length);
700 if (!buf)
701 return;
702 int i = 0;
703 int blen = 0;
704 while (i < Length - 6) {
705 if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) {
706 int len = Data[i + 4] * 256 + Data[i + 5];
707 if ((Data[i + 3] & 0xF0) == 0xE0) { // video packet
708 // skip PES header
709 int offs = i + 6;
710 // skip header extension
711 if ((Data[i + 6] & 0xC0) == 0x80) {
712 // MPEG-2 PES header
713 if (Data[i + 8] >= Length)
714 break;
715 offs += 3;
716 offs += Data[i + 8];
717 len -= 3;
718 len -= Data[i + 8];
719 if (len < 0 || offs + len > Length)
720 break;
721 }
722 else {
723 // MPEG-1 PES header
724 while (offs < Length && len > 0 && Data[offs] == 0xFF) {
725 offs++;
726 len--;
727 }
728 if (offs <= Length - 2 && len >= 2 && (Data[offs] & 0xC0) == 0x40) {
729 offs += 2;
730 len -= 2;
731 }
732 if (offs <= Length - 5 && len >= 5 && (Data[offs] & 0xF0) == 0x20) {
733 offs += 5;
734 len -= 5;
735 }
736 else if (offs <= Length - 10 && len >= 10 && (Data[offs] & 0xF0) == 0x30) {
737 offs += 10;
738 len -= 10;
739 }
740 else if (offs < Length && len > 0) {
741 offs++;
742 len--;
743 }
744 }
745 if (blen + len > Length) // invalid PES length field
746 break;
747 memcpy(&buf[blen], &Data[offs], len);
748 i = offs + len;
749 blen += len;
750 }
751 else if (Data[i + 3] >= 0xBD && Data[i + 3] <= 0xDF) // other PES packets
752 i += len + 6;
753 else
754 i++;
755 }
756 else
757 i++;
758 }
759 mHdffCmdIf->CmdAvShowStillImage(0, (uint8_t *)buf, blen, MapVideoStreamTypes(PatPmtParser()->Vtype()));
760 free(buf);
761 }
762 else {
763 // non-PES data
764 mHdffCmdIf->CmdAvShowStillImage(0, Data, Length, MapVideoStreamTypes(PatPmtParser()->Vtype()));
765 }
766}
767
768bool cDvbHdFfDevice::Poll(cPoller &Poller, int TimeoutMs)
769{
770 Poller.Add(fd_video, true);
771 return Poller.Poll(TimeoutMs);
772}
773
774bool cDvbHdFfDevice::Flush(int TimeoutMs)
775{
776 //TODO actually this function should wait until all buffered data has been processed by the card, but how?
777 return true;
778}
779
780void cDvbHdFfDevice::BuildTsPacket(uint8_t * TsBuffer, bool PusiSet, uint16_t Pid, uint8_t Counter, const uint8_t * Data, uint32_t Length)
781{
782 TsBuffer[0] = 0x47;
783 TsBuffer[1] = PusiSet ? 0x40 : 0x00;
784 TsBuffer[1] |= Pid >> 8;
785 TsBuffer[2] = Pid & 0xFF;
786 if (Length >= 184)
787 {
788 TsBuffer[3] = 0x10 | Counter;
789 memcpy(TsBuffer + 4, Data, 184);
790 }
791 else
792 {
793 uint8_t adaptationLength;
794
795 TsBuffer[3] = 0x30 | Counter;
796 adaptationLength = 183 - Length;
797 TsBuffer[4] = adaptationLength;
798 if (adaptationLength > 0)
799 {
800 TsBuffer[5] = 0x00;
801 memset(TsBuffer + 6, 0xFF, adaptationLength - 1);
802 }
803 memcpy(TsBuffer + 5 + adaptationLength, Data, Length);
804 }
805}
806
807uint32_t cDvbHdFfDevice::PesToTs(uint8_t * TsBuffer, uint16_t Pid, uint8_t & Counter, const uint8_t * Data, uint32_t Length)
808{
809 uint32_t tsOffset;
810 uint32_t i;
811
812 tsOffset = 0;
813 i = 0;
814 while (Length > 0)
815 {
816 BuildTsPacket(TsBuffer + tsOffset, i == 0, Pid, Counter, Data + i * 184, Length);
817 if (Length >= 184)
818 Length -= 184;
819 else
820 Length = 0;
821 Counter = (Counter + 1) & 15;
822 tsOffset += 188;
823 i++;
824 }
825 return tsOffset;
826}
827
828int cDvbHdFfDevice::PlayVideo(const uchar *Data, int Length)
829{
830 if (freezed)
831 return -1;
832 if (!isPlayingVideo)
833 {
834 mHdffCmdIf->CmdAvEnableSync(0, true);
835 isPlayingVideo = true;
836 }
837
838 // ignore padding PES packets
839 if (Data[3] == 0xBE)
840 return Length;
841
842 //TODO: support greater Length
843 uint8_t tsBuffer[188 * 16];
844 uint32_t tsLength;
845 int pid = 100;
846
847 tsLength = PesToTs(tsBuffer, pid, videoCounter, Data, Length);
848
849 if (pid != playVideoPid) {
850 playVideoPid = pid;
851 mHdffCmdIf->CmdAvSetVideoPid(0, playVideoPid, HDFF_VIDEO_STREAM_MPEG2, true);
852 }
853 if (WriteAllOrNothing(fd_video, tsBuffer, tsLength, 1000, 10) <= 0)
854 Length = 0;
855 return Length;
856}
857
858int cDvbHdFfDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
859{
860 if (freezed)
861 return -1;
862 uint8_t streamId;
863 uint8_t tsBuffer[188 * 16];
864 uint32_t tsLength;
867 int pid;
868
869 streamId = Data[3];
870 if (streamId >= 0xC0 && streamId <= 0xDF)
871 {
872 streamType = HDFF_AUDIO_STREAM_MPEG1;
873 }
874 else if (streamId == 0xBD)
875 {
876 const uint8_t * payload = Data + 9 + Data[8];
877 if ((payload[0] & 0xF8) == 0xA0)
878 {
879 containerType = HDFF_AV_CONTAINER_PES_DVD;
880 streamType = HDFF_AUDIO_STREAM_PCM;
881 }
882 else if ((payload[0] & 0xF8) == 0x88)
883 {
884 containerType = HDFF_AV_CONTAINER_PES_DVD;
885 streamType = HDFF_AUDIO_STREAM_DTS;
886 }
887 else if ((payload[0] & 0xF8) == 0x80)
888 {
889 containerType = HDFF_AV_CONTAINER_PES_DVD;
890 streamType = HDFF_AUDIO_STREAM_AC3;
891 }
892 else
893 {
894 streamType = HDFF_AUDIO_STREAM_AC3;
895 }
896 }
897 pid = 200 + (int) streamType;
898 tsLength = PesToTs(tsBuffer, pid, audioCounter, Data, Length);
899
900 if (pid != playAudioPid) {
901 playAudioPid = pid;
902 mHdffCmdIf->CmdAvSetAudioPid(0, playAudioPid, streamType, containerType);
903 }
904 if (WriteAllOrNothing(fd_video, tsBuffer, tsLength, 1000, 10) <= 0)
905 Length = 0;
906 return Length;
907}
908
909int cDvbHdFfDevice::PlayTsVideo(const uchar *Data, int Length)
910{
911 if (freezed)
912 return -1;
913 if (!isPlayingVideo)
914 {
915 mHdffCmdIf->CmdAvEnableSync(0, true);
916 isPlayingVideo = true;
917 }
918
919 int pid = TsPid(Data);
920 if (pid != playVideoPid) {
921 PatPmtParser();
922 if (pid == PatPmtParser()->Vpid()) {
923 playVideoPid = pid;
924 mHdffCmdIf->CmdAvSetVideoPid(0, playVideoPid, MapVideoStreamTypes(PatPmtParser()->Vtype()), true);
925 }
926 }
928 if (pid != playPcrPid) {
929 if (pid == PatPmtParser()->Ppid()) {
930 playPcrPid = pid;
931 mHdffCmdIf->CmdAvSetPcrPid(0, playPcrPid);
932 }
933 }
934 }
935 return WriteAllOrNothing(fd_video, Data, Length, 1000, 10);
936}
937
939{
940 switch (Atype) {
941 case 0x03: return HDFF_AUDIO_STREAM_MPEG1;
942 case 0x04: return HDFF_AUDIO_STREAM_MPEG2;
945 case 0x0F: return HDFF_AUDIO_STREAM_AAC;
946 case 0x11: return HDFF_AUDIO_STREAM_HE_AAC;
947 default: return HDFF_AUDIO_STREAM_MPEG1;
948 }
949}
950
951int cDvbHdFfDevice::PlayTsAudio(const uchar *Data, int Length)
952{
953 if (freezed)
954 return -1;
955 int pid = TsPid(Data);
956 if (pid != playAudioPid) {
957 playAudioPid = pid;
958 int AudioStreamType = -1;
959 for (int i = 0; PatPmtParser()->Apid(i); i++) {
960 if (playAudioPid == PatPmtParser()->Apid(i)) {
961 AudioStreamType = PatPmtParser()->Atype(i);
962 break;
963 }
964 }
965 if (AudioStreamType < 0) {
966 for (int i = 0; PatPmtParser()->Dpid(i); i++) {
967 if (playAudioPid == PatPmtParser()->Dpid(i)) {
968 AudioStreamType = PatPmtParser()->Dtype(i);
969 break;
970 }
971 }
972 }
973 mHdffCmdIf->CmdAvSetAudioPid(0, playAudioPid, MapAudioStreamTypes(AudioStreamType));
974 }
975 return WriteAllOrNothing(fd_video, Data, Length, 1000, 10);
976}
977
979{
980 //TODO why not just keep a pointer?
981 if (devHdffOffset >= 0) {
983 if (device)
984 return device->mHdffCmdIf;
985 }
986 return NULL;
987}
988
989// --- cDvbHdFfDeviceProbe ---------------------------------------------------
990
995
996bool cDvbHdFfDeviceProbe::Probe(int Adapter, int Frontend)
997{
998 static uint32_t SubsystemIds[] = {
999 0x13C23009, // Technotrend S2-6400 HDFF development samples
1000 0x13C2300A, // Technotrend S2-6400 HDFF production version
1001 0x00000000
1002 };
1003 cString FileName;
1004 cReadLine ReadLine;
1005 FILE *f = NULL;
1006 uint32_t SubsystemId = 0;
1007 FileName = cString::sprintf("/sys/class/dvb/dvb%d.frontend%d/device/subsystem_vendor", Adapter, Frontend);
1008 if ((f = fopen(FileName, "r")) != NULL) {
1009 if (char *s = ReadLine.Read(f))
1010 SubsystemId = strtoul(s, NULL, 0) << 16;
1011 fclose(f);
1012 }
1013 FileName = cString::sprintf("/sys/class/dvb/dvb%d.frontend%d/device/subsystem_device", Adapter, Frontend);
1014 if ((f = fopen(FileName, "r")) != NULL) {
1015 if (char *s = ReadLine.Read(f))
1016 SubsystemId |= strtoul(s, NULL, 0);
1017 fclose(f);
1018 }
1019 for (uint32_t *sid = SubsystemIds; *sid; sid++) {
1020 if (*sid == SubsystemId) {
1021 FileName = cString::sprintf("/dev/dvb/adapter%d/osd0", Adapter);
1022 int fd = open(FileName, O_RDWR);
1023 if (fd != -1) { //TODO treat the second path of the S2-6400 as a budget device
1024 close(fd);
1025 dsyslog("creating cDvbHdFfDevice%s", outputOnly ? " (output only)" : "");
1026 new cDvbHdFfDevice(Adapter, Frontend, outputOnly);
1027 return true;
1028 }
1029 else if (outputOnly) {
1030 dsyslog("cDvbHdFfDevice 2nd tuner disabled (outputonly)");
1031 return true;
1032 }
1033 }
1034 }
1035 return false;
1036}
1037
1038
1039// --- YuvToJpeg -------------------------------------------------------------
1040
1041#include <jpeglib.h>
1042
1043#define JPEGCOMPRESSMEM 4000000
1044
1049
1050static void JpegCompressInitDestination(j_compress_ptr cinfo)
1051{
1052 tJpegCompressData *jcd = (tJpegCompressData *)cinfo->client_data;
1053 if (jcd) {
1054 cinfo->dest->free_in_buffer = jcd->size = JPEGCOMPRESSMEM;
1055 cinfo->dest->next_output_byte = jcd->mem = MALLOC(uchar, jcd->size);
1056 }
1057}
1058
1059static boolean JpegCompressEmptyOutputBuffer(j_compress_ptr cinfo)
1060{
1061 tJpegCompressData *jcd = (tJpegCompressData *)cinfo->client_data;
1062 if (jcd) {
1063 int Used = jcd->size;
1064 int NewSize = jcd->size + JPEGCOMPRESSMEM;
1065 if (uchar *NewBuffer = (uchar *)realloc(jcd->mem, NewSize)) {
1066 jcd->size = NewSize;
1067 jcd->mem = NewBuffer;
1068 }
1069 else {
1070 esyslog("ERROR: out of memory");
1071 return false;
1072 }
1073 if (jcd->mem) {
1074 cinfo->dest->next_output_byte = jcd->mem + Used;
1075 cinfo->dest->free_in_buffer = jcd->size - Used;
1076 return true;
1077 }
1078 }
1079 return false;
1080}
1081
1082static void JpegCompressTermDestination(j_compress_ptr cinfo)
1083{
1084 tJpegCompressData *jcd = (tJpegCompressData *)cinfo->client_data;
1085 if (jcd) {
1086 int Used = cinfo->dest->next_output_byte - jcd->mem;
1087 if (Used < jcd->size) {
1088 if (uchar *NewBuffer = (uchar *)realloc(jcd->mem, Used)) {
1089 jcd->size = Used;
1090 jcd->mem = NewBuffer;
1091 }
1092 else
1093 esyslog("ERROR: out of memory");
1094 }
1095 }
1096}
1097
1098static uchar *YuvToJpeg(uchar *Mem, int Width, int Height, int &Size, int Quality)
1099{
1100 if (Quality < 0)
1101 Quality = 0;
1102 else if (Quality > 100)
1103 Quality = 100;
1104
1105 jpeg_destination_mgr jdm;
1106
1107 jdm.init_destination = JpegCompressInitDestination;
1108 jdm.empty_output_buffer = JpegCompressEmptyOutputBuffer;
1109 jdm.term_destination = JpegCompressTermDestination;
1110
1111 struct jpeg_compress_struct cinfo;
1112 struct jpeg_error_mgr jerr;
1113 cinfo.err = jpeg_std_error(&jerr);
1114 jpeg_create_compress(&cinfo);
1115 cinfo.dest = &jdm;
1117 cinfo.client_data = &jcd;
1118 cinfo.image_width = Width;
1119 cinfo.image_height = Height;
1120 cinfo.input_components = 3;
1121 cinfo.in_color_space = JCS_YCbCr;
1122
1123 jpeg_set_defaults(&cinfo);
1124 jpeg_set_quality(&cinfo, Quality, true);
1125 jpeg_start_compress(&cinfo, true);
1126
1127 int rs = Width * 3;
1128 JSAMPROW rp[Height];
1129 for (int k = 0; k < Height; k++)
1130 rp[k] = &Mem[rs * k];
1131 jpeg_write_scanlines(&cinfo, rp, Height);
1132 jpeg_finish_compress(&cinfo);
1133 jpeg_destroy_compress(&cinfo);
1134
1135 Size = jcd.size;
1136 return jcd.mem;
1137}
#define CA_ENCRYPTED_MIN
Definition channels.h:44
#define LOCK_CHANNELS_READ
Definition channels.h:270
cChannelCamRelations ChannelCamRelations
Definition ci.c:2947
virtual void SetPid(int Pid, bool Active)
Sets the given Pid (which has previously been added through a call to AddPid()) to Active.
Definition ci.c:2697
virtual void StartDecrypting(void)
Sends all CA_PMT entries to the CAM that have been modified since the last call to this function.
Definition ci.c:2776
int Vpid(void) const
Definition channels.h:154
int Atype(int i) const
Definition channels.h:166
int Number(void) const
Definition channels.h:179
int Dtype(int i) const
Definition channels.h:167
int Dpid(int i) const
Definition channels.h:161
int Vtype(void) const
Definition channels.h:156
int Apid(int i) const
Definition channels.h:160
tChannelID GetChannelID(void) const
Definition channels.h:191
int Ppid(void) const
Definition channels.h:155
int Ca(int Index=0) const
Definition channels.h:173
static void Launch(cControl *Control)
Definition player.c:79
void StopSectionHandler(void)
A device that has called StartSectionHandler() must call this function (typically in its destructor) ...
Definition device.c:681
virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect)
Returns the Width, Height and VideoAspect ratio of the currently displayed video material.
Definition device.c:533
@ ptTeletext
Definition device.h:410
@ ptPcr
Definition device.h:410
@ ptDolby
Definition device.h:410
@ ptAudio
Definition device.h:410
@ ptVideo
Definition device.h:410
bool HasPid(int Pid) const
Returns true if this device is currently receiving the given PID.
Definition device.c:550
static cDevice * GetDevice(int Index)
Gets the device with the given Index.
Definition device.c:230
void DelPid(int Pid, ePidType PidType=ptOther)
Deletes a PID from the set of PIDs this device shall receive.
Definition device.c:625
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
Definition device.h:371
bool IsPrimaryDevice(bool CheckDecoder=true) const
Definition device.h:223
bool Transferring(void) const
Returns true if we are currently in Transfer Mode.
Definition device.c:1391
virtual void MakePrimaryDevice(bool On)
Informs a device that it will be the primary device.
Definition device.c:186
void DetachAll(int Pid)
Detaches all receivers from this device for this pid.
Definition device.c:1918
virtual void Play(void)
Sets the device into play mode (after a previous trick mode).
Definition device.c:1308
const cPatPmtParser * PatPmtParser(void) const
Returns a pointer to the patPmtParser, so that a derived device can use the stream information from i...
Definition device.h:660
cPidHandle pidHandles[MAXPIDHANDLES]
Definition device.h:419
const tTrackId * GetTrack(eTrackType Type)
Returns a pointer to the given track id, or NULL if Type is not less than ttMaxTrackTypes.
Definition device.c:1143
virtual void Mute(void)
Turns off audio while replaying.
Definition device.c:1322
virtual void Freeze(void)
Puts the device into "freeze frame" mode.
Definition device.c:1315
virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
Sets the video display format to the given one (only useful if this device has an MPEG decoder).
Definition device.c:506
virtual bool CanReplay(void) const
Returns true if this device can currently start a replay session.
Definition device.c:1282
virtual void Clear(void)
Clears all video and audio data from the device.
Definition device.c:1301
int CardIndex(void) const
Returns the card index of this device (0 ... MAXDEVICES - 1).
Definition device.h:224
cCamSlot * CamSlot(void) const
Returns the CAM slot that is currently used with this device, or NULL if no CAM slot is in use.
Definition device.h:493
bool AddPid(int Pid, ePidType PidType=ptOther, int StreamType=0)
Adds a PID to the set of PIDs this device shall receive.
Definition device.c:560
static cDevice * device[MAXDEVICES]
Definition device.h:75
virtual void StillPicture(const uchar *Data, int Length)
Displays the given I-frame as a still picture.
Definition device.c:1327
cDvbDevice(int Adapter, int Frontend)
Definition dvbdevice.c:1878
virtual int NumProvidedSystems(void) const override
Returns the number of individual "delivery systems" this device provides.
Definition dvbdevice.c:2303
cTSBuffer * tsBuffer
< Controls how the DVB device handles Transfer Mode when replaying Dolby Digital audio.
Definition dvbdevice.h:284
virtual bool ProvidesSource(int Source) const override
Returns true if this device can provide the given source.
Definition dvbdevice.c:2225
int Frontend(void) const
Definition dvbdevice.c:1930
virtual bool IsTunedToTransponder(const cChannel *Channel) const override
Returns true if this device is currently tuned to the given Channel's transponder.
Definition dvbdevice.c:2333
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView) override
Sets the device to the given channel (actual physical setup).
Definition dvbdevice.c:2348
int Adapter(void) const
Definition dvbdevice.h:192
virtual bool Probe(int Adapter, int Frontend)
Probes for a DVB device at the given Adapter and creates the appropriate object derived from cDvbDevi...
The cDvbHdFfDevice implements a DVB device which can be accessed through the Linux DVB driver API.
virtual void SetAudioTrackDevice(eTrackType Type)
Sets the current audio track to the given value.
virtual cRect CanScaleVideo(const cRect &Rect, int Alignment=taCenter)
Asks the output device whether it can scale the currently shown video in such a way that it fits into...
bool supportsPcrInTransferMode
virtual cSpuDecoder * GetSpuDecoder(void)
Returns a pointer to the device's SPU decoder (or NULL, if this device doesn't have an SPU decoder).
virtual int NumProvidedSystems(void) const
Returns the number of individual "delivery systems" this device provides.
virtual int GetAudioChannelDevice(void)
Gets the current audio channel, which is stereo (0), mono left (1) or mono right (2).
virtual void GetOsdSize(int &Width, int &Height, double &PixelAspect)
Returns the Width, Height and PixelAspect ratio the OSD should use to best fit the resolution of the ...
ePlayMode playMode
virtual void ScaleVideo(const cRect &Rect=cRect::Null)
Scales the currently shown video in such a way that it fits into the given Rect.
virtual void StillPicture(const uchar *Data, int Length)
Displays the given I-frame as a still picture.
virtual bool Flush(int TimeoutMs=0)
Returns true if the device's output buffers are empty, i.
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView)
Sets the device to the given channel (actual physical setup).
uint8_t audioCounter
virtual void SetAudioChannelDevice(int AudioChannel)
Sets the audio channel to stereo (0), mono left (1) or mono right (2).
void BuildTsPacket(uint8_t *TsBuffer, bool PusiSet, uint16_t Pid, uint8_t Counter, const uint8_t *Data, uint32_t Length)
virtual bool Poll(cPoller &Poller, int TimeoutMs=0)
Returns true if the device itself or any of the file handles in Poller is ready for further action.
uint32_t PesToTs(uint8_t *TsBuffer, uint16_t Pid, uint8_t &Counter, const uint8_t *Data, uint32_t Length)
virtual int PlayTsAudio(const uchar *Data, int Length)
Plays the given data block as audio.
virtual bool SetPlayMode(ePlayMode PlayMode)
Sets the device into the given play mode.
virtual int PlayAudio(const uchar *Data, int Length, uchar Id)
Plays the given data block as audio.
static HDFF::cHdffCmdIf * GetHdffCmdHandler(void)
virtual void Clear(void)
Clears all video and audio data from the device.
cDvbHdFfDevice(int Adapter, int Frontend, bool OutputOnly)
virtual void Mute(void)
Turns off audio while replaying.
virtual bool SetPid(cPidHandle *Handle, int Type, bool On)
Does the actual PID setting on this device.
virtual bool CanReplay(void) const
Returns true if this device can currently start a replay session.
HDFF::cHdffCmdIf * mHdffCmdIf
virtual ~cDvbHdFfDevice()
virtual int PlayTsVideo(const uchar *Data, int Length)
Plays the given data block as video.
virtual void Play(void)
Sets the device into play mode (after a previous trick mode).
cDvbSpuDecoder * spuDecoder
static int devHdffOffset
virtual uchar * GrabImage(int &Size, bool Jpeg=true, int Quality=-1, int SizeX=-1, int SizeY=-1)
Grabs the currently visible screen image.
void TurnOffLiveMode(bool LiveView)
virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
Sets the video display format to the given one (only useful if this device has an MPEG decoder).
virtual int64_t GetSTC(void)
Gets the current System Time Counter, which can be used to synchronize audio, video and subtitles.
virtual void SetVolumeDevice(int Volume)
Sets the audio volume on this device (Volume = 0...255).
virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect)
Returns the Width, Height and VideoAspect ratio of the currently displayed video material.
virtual bool HasDecoder(void) const
Tells whether this device has an MPEG decoder.
virtual int PlayVideo(const uchar *Data, int Length)
Plays the given data block as video.
virtual void MakePrimaryDevice(bool On)
Informs a device that it will be the primary device.
virtual void TrickSpeed(int Speed)
uint8_t videoCounter
virtual bool ProvidesSource(int Source) const
Returns true if this device can provide the given source.
virtual void Freeze(void)
Puts the device into "freeze frame" mode.
int Dtype(int i) const
Definition remux.h:421
int Dpid(int i) const
Definition remux.h:418
int Apid(int i) const
Definition remux.h:417
int Atype(int i) const
Definition remux.h:420
bool Add(int FileHandle, bool Out)
Definition tools.c:1553
bool Poll(int TimeoutMs=0)
Definition tools.c:1585
char * Read(FILE *f)
Definition tools.c:1527
Definition osd.h:352
static const cRect Null
Definition osd.h:357
int Height(void) const
Definition osd.h:368
int Y(void) const
Definition osd.h:366
int X(void) const
Definition osd.h:365
int Width(void) const
Definition osd.h:367
static cString sprintf(const char *fmt,...) __attribute__((format(printf
Definition tools.c:1195
static cDevice * ReceiverDevice(void)
Definition transfer.h:38
eVideoDisplayFormat
Definition device.h:58
@ vdfLetterBox
Definition device.h:59
@ vdfCenterCutOut
Definition device.h:60
@ vdfPanAndScan
Definition device.h:58
ePlayMode
Definition device.h:39
@ pmNone
Definition device.h:39
@ pmExtern_THIS_SHOULD_BE_AVOIDED
Definition device.h:44
#define IS_AUDIO_TRACK(t)
Definition device.h:76
eTrackType
Definition device.h:63
@ ttAudioFirst
Definition device.h:65
@ ttDolbyFirst
Definition device.h:68
#define IS_DOLBY_TRACK(t)
Definition device.h:77
int DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, bool ReportError)
Definition dvbdevice.c:1921
#define DEV_DVB_DEMUX
Definition dvbdevice.h:76
#define DEV_DVB_AUDIO
Definition dvbdevice.h:78
#define DEV_DVB_VIDEO
Definition dvbdevice.h:77
#define DEV_DVB_OSD
Definition dvbdevice.h:73
static boolean JpegCompressEmptyOutputBuffer(j_compress_ptr cinfo)
static void JpegCompressInitDestination(j_compress_ptr cinfo)
static uchar * YuvToJpeg(uchar *Mem, int Width, int Height, int &Size, int Quality)
#define BUFFER_SIZE
static HdffAudioStreamType_t MapAudioStreamTypes(int Atype)
#define JPEGCOMPRESSMEM
static void JpegCompressTermDestination(j_compress_ptr cinfo)
static HdffVideoStreamType_t MapVideoStreamTypes(int Vtype)
#define AUDIO_GET_PTS
HdffVideoStreamType_t
Definition hdffcmd_av.h:47
@ HDFF_VIDEO_STREAM_H264
Definition hdffcmd_av.h:51
@ HDFF_VIDEO_STREAM_MPEG1
Definition hdffcmd_av.h:49
@ HDFF_VIDEO_STREAM_MPEG2
Definition hdffcmd_av.h:50
@ HDFF_TV_FORMAT_4_BY_3
Definition hdffcmd_av.h:58
HdffAudioDownmixMode_t
Definition hdffcmd_av.h:88
HdffAudioStreamType_t
Definition hdffcmd_av.h:34
@ HDFF_AUDIO_STREAM_AAC
Definition hdffcmd_av.h:39
@ HDFF_AUDIO_STREAM_DTS
Definition hdffcmd_av.h:43
@ HDFF_AUDIO_STREAM_MPEG2
Definition hdffcmd_av.h:37
@ HDFF_AUDIO_STREAM_HE_AAC
Definition hdffcmd_av.h:40
@ HDFF_AUDIO_STREAM_EAC3
Definition hdffcmd_av.h:42
@ HDFF_AUDIO_STREAM_PCM
Definition hdffcmd_av.h:41
@ HDFF_AUDIO_STREAM_AC3
Definition hdffcmd_av.h:38
@ HDFF_AUDIO_STREAM_MPEG1
Definition hdffcmd_av.h:36
@ HDFF_VIDEO_CONVERSION_CENTRE_CUT_OUT
Definition hdffcmd_av.h:68
@ HDFF_VIDEO_CONVERSION_LETTERBOX_16_BY_9
Definition hdffcmd_av.h:65
HdffAvContainerType_t
Definition hdffcmd_av.h:28
@ HDFF_AV_CONTAINER_PES_DVD
Definition hdffcmd_av.h:30
@ HDFF_AV_CONTAINER_PES
Definition hdffcmd_av.h:29
HdffVideoModeAdaption_t
HdffVideoOut_t
Definition hdffcmd_mux.h:29
HdffRemoteProtocol_t
@ EnhancedAC3DescriptorTag
Definition si.h:136
@ AC3DescriptorTag
Definition si.h:119
int TsPid(const uchar *p)
Definition remux.h:82
#define TS_SIZE
Definition remux.h:34
cHdffSetup gHdffSetup
Definition setup.c:16
char CecDeviceName[14]
HdffVideoModeAdaption_t VideoModeAdaption
uint16_t id
Definition device.h:81
int WriteAllOrNothing(int fd, const uchar *Data, int Length, int TimeoutMs, int RetryMs)
Writes either all Data to the given file descriptor, or nothing at all.
Definition tools.c:90
unsigned char uchar
Definition tools.h:31
#define CHECK(s)
Definition tools.h:51
#define dsyslog(a...)
Definition tools.h:37
#define MALLOC(type, size)
Definition tools.h:47
#define esyslog(a...)
Definition tools.h:35
#define LOG_ERROR
Definition tools.h:39