vdr  2.4.1
dvbsdffdevice.c
Go to the documentation of this file.
1 /*
2  * dvbsdffdevice.h: The DVB SD Full Featured device interface
3  *
4  * See the README file for copyright information and how to reach the author.
5  *
6  * $Id: dvbsdffdevice.c 4.0 2014/03/15 12:35:21 kls Exp $
7  */
8 
9 #include "dvbsdffdevice.h"
10 #include <errno.h>
11 #include <limits.h>
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>
17 #include <sys/mman.h>
18 #include <vdr/eitscan.h>
19 #include <vdr/transfer.h>
20 #include "dvbsdffosd.h"
21 
22 // --- cDvbSdFfDevice --------------------------------------------------------
23 
25 
26 cDvbSdFfDevice::cDvbSdFfDevice(int Adapter, int Frontend, bool OutputOnly)
27 :cDvbDevice(Adapter, Frontend)
28 {
29  spuDecoder = NULL;
30  digitalAudio = false;
31  playMode = pmNone;
32  outputOnly = OutputOnly;
33 
34  // Devices that are only present on cards with decoders:
35 
37  fd_video = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDWR | O_NONBLOCK);
38  fd_audio = DvbOpen(DEV_DVB_AUDIO, adapter, frontend, O_RDWR | O_NONBLOCK);
40 
41  // The offset of the /dev/video devices:
42 
43  if (devVideoOffset < 0) { // the first one checks this
44  FILE *f = NULL;
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")) { // found the _first_ DVB card
51  devVideoOffset = ofs;
52  dsyslog("video device offset is %d", devVideoOffset);
53  break;
54  }
55  }
56  else
57  break;
58  fclose(f);
59  }
60  else
61  break;
62  }
63  if (devVideoOffset < 0)
64  devVideoOffset = 0;
65  if (f)
66  fclose(f);
67  }
69 }
70 
72 {
73  delete spuDecoder;
74  // We're not explicitly closing any device files here, since this sometimes
75  // caused segfaults. Besides, the program is about to terminate anyway...
76 }
77 
79 {
80  if (On)
83 }
84 
86 {
87  return true;
88 }
89 
91 {
92  return true;
93 }
94 
96 {
97  if (!spuDecoder && IsPrimaryDevice())
98  spuDecoder = new cDvbSpuDecoder();
99  return spuDecoder;
100 }
101 
102 uchar *cDvbSdFfDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY)
103 {
104  if (devVideoIndex < 0)
105  return NULL;
106  char buffer[PATH_MAX];
107  snprintf(buffer, sizeof(buffer), "%s%d", DEV_VIDEO, devVideoIndex);
108  int videoDev = open(buffer, O_RDWR);
109  if (videoDev >= 0) {
110  uchar *result = NULL;
111  // set up the size and RGB
112  v4l2_format fmt;
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));
122  reqBuf.count = 2;
123  reqBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
124  reqBuf.memory = V4L2_MEMORY_MMAP;
125  if (ioctl(videoDev, VIDIOC_REQBUFS, &reqBuf) >= 0) {
126  v4l2_buffer mbuf;
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) {
134  v4l2_buffer buf;
135  memset(&buf, 0, sizeof(buf));
136  buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
137  buf.memory = V4L2_MEMORY_MMAP;
138  buf.index = 0;
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;
145  buf.index = 0;
146  if (ioctl(videoDev, VIDIOC_DQBUF, &buf) == 0) {
147  if (ioctl(videoDev, VIDIOC_STREAMOFF, &type) == 0) {
148  // make RGB out of BGR:
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];
153  mem1[2] = mem1[0];
154  mem1[0] = tmp;
155  mem1 += 3;
156  }
157 
158  if (Quality < 0)
159  Quality = 100;
160 
161  dsyslog("grabbing to %s %d %d %d", Jpeg ? "JPEG" : "PNM", Quality, fmt.fmt.pix.width, fmt.fmt.pix.height);
162  if (Jpeg) {
163  // convert to JPEG:
164  result = RgbToJpeg(mem, fmt.fmt.pix.width, fmt.fmt.pix.height, Size, Quality);
165  if (!result)
166  esyslog("ERROR: failed to convert image to JPEG");
167  }
168  else {
169  // convert to PNM:
170  char buf[32];
171  snprintf(buf, sizeof(buf), "P6\n%d\n%d\n255\n", fmt.fmt.pix.width, fmt.fmt.pix.height);
172  int l = strlen(buf);
173  int bytes = memsize * 3;
174  Size = l + bytes;
175  result = MALLOC(uchar, Size);
176  if (result) {
177  memcpy(result, buf, l);
178  memcpy(result + l, mem, bytes);
179  }
180  else
181  esyslog("ERROR: failed to convert image to PNM");
182  }
183  }
184  else
185  esyslog("ERROR: video device VIDIOC_STREAMOFF failed");
186  }
187  else
188  esyslog("ERROR: video device VIDIOC_DQBUF failed");
189  }
190  else
191  esyslog("ERROR: video device VIDIOC_STREAMON failed");
192  }
193  else
194  esyslog("ERROR: video device VIDIOC_QBUF failed");
195  munmap(mem, msize);
196  }
197  else
198  esyslog("ERROR: failed to memmap video device");
199  }
200  else
201  esyslog("ERROR: video device VIDIOC_QUERYBUF failed");
202  }
203  else
204  esyslog("ERROR: video device VIDIOC_REQBUFS failed");
205  }
206  else
207  esyslog("ERROR: video device VIDIOC_S_FMT failed");
208  close(videoDev);
209  return result;
210  }
211  else
212  LOG_ERROR_STR(buffer);
213  return NULL;
214 }
215 
217 {
218  cDevice::SetVideoDisplayFormat(VideoDisplayFormat);
219  if (Setup.VideoFormat) {
220  CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_LETTER_BOX));
221  }
222  else {
223  switch (VideoDisplayFormat) {
224  case vdfPanAndScan:
225  CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_PAN_SCAN));
226  break;
227  case vdfLetterBox:
228  CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_LETTER_BOX));
229  break;
230  case vdfCenterCutOut:
231  CHECK(ioctl(fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_CENTER_CUT_OUT));
232  break;
233  default: esyslog("ERROR: unknown video display format %d", VideoDisplayFormat);
234  }
235  }
236 }
237 
238 void cDvbSdFfDevice::SetVideoFormat(bool VideoFormat16_9)
239 {
240  CHECK(ioctl(fd_video, VIDEO_SET_FORMAT, VideoFormat16_9 ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3));
242 }
243 
244 void cDvbSdFfDevice::GetVideoSize(int &Width, int &Height, double &VideoAspect)
245 {
246  if (fd_video >= 0) {
247  video_size_t vs;
248  if (ioctl(fd_video, VIDEO_GET_SIZE, &vs) == 0) {
249  Width = vs.w;
250  Height = vs.h;
251  switch (vs.aspect_ratio) {
252  default:
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;
256  }
257  return;
258  }
259  else
260  LOG_ERROR;
261  }
262  cDevice::GetVideoSize(Width, Height, VideoAspect);
263 }
264 
265 void cDvbSdFfDevice::GetOsdSize(int &Width, int &Height, double &PixelAspect)
266 {
267  if (fd_video >= 0) {
268  video_size_t vs;
269  if (ioctl(fd_video, VIDEO_GET_SIZE, &vs) == 0) {
270  Width = 720;
271  if (vs.h != 480 && vs.h != 240)
272  Height = 576; // PAL
273  else
274  Height = 480; // NTSC
275  switch (Setup.VideoFormat ? vs.aspect_ratio : VIDEO_FORMAT_4_3) {
276  default:
277  case VIDEO_FORMAT_4_3: PixelAspect = 4.0 / 3.0; break;
278  case VIDEO_FORMAT_221_1: // FF DVB cards only distinguish between 4:3 and 16:9
279  case VIDEO_FORMAT_16_9: PixelAspect = 16.0 / 9.0; break;
280  }
281  PixelAspect /= double(Width) / Height;
282  return;
283  }
284  else
285  LOG_ERROR;
286  }
287  cDevice::GetOsdSize(Width, Height, PixelAspect);
288 }
289 
291 {
293  return false;
294  return ioctl(fd_audio, AUDIO_SET_BYPASS_MODE, On) == 0;
295 }
296 
297 // ptAudio ptVideo ptPcr ptTeletext ptDolby ptOther
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 };
299 
300 bool cDvbSdFfDevice::SetPid(cPidHandle *Handle, int Type, bool On)
301 {
302  if (Handle->pid) {
303  dmx_pes_filter_params pesFilterParams;
304  memset(&pesFilterParams, 0, sizeof(pesFilterParams));
305  if (On) {
306  if (Handle->handle < 0) {
307  Handle->handle = DvbOpen(DEV_DVB_DEMUX, adapter, frontend, O_RDWR | O_NONBLOCK, true);
308  if (Handle->handle < 0) {
309  LOG_ERROR;
310  return false;
311  }
312  }
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;
316  pesFilterParams.pes_type= PesTypes[Type < ptOther ? Type : ptOther];
317  pesFilterParams.flags = DMX_IMMEDIATE_START;
318  if (ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
319  LOG_ERROR;
320  return false;
321  }
322  }
323  else if (!Handle->used) {
324  CHECK(ioctl(Handle->handle, DMX_STOP));
325  if (Type <= ptTeletext) {
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) // let's only do this once
333  SetPlayMode(pmNone); // necessary to switch a PID from DMX_PES_VIDEO/AUDIO to DMX_PES_OTHER
334  }
335  close(Handle->handle);
336  Handle->handle = -1;
337  }
338  }
339  return true;
340 }
341 
342 bool cDvbSdFfDevice::ProvidesSource(int Source) const
343 {
344  if (outputOnly)
345  return false;
346  else
347  return cDvbDevice::ProvidesSource(Source);
348 }
349 
351 {
352  if (outputOnly)
353  return 0;
355 }
356 
358 {
359  if (LiveView) {
360  // Avoid noise while switching:
361  CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, true));
362  CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
363  CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER));
364  CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER));
365  }
366 
367  // Turn off live PIDs:
368 
371  DetachAll(pidHandles[ptPcr].pid);
373  DelPid(pidHandles[ptAudio].pid);
374  DelPid(pidHandles[ptVideo].pid);
375  DelPid(pidHandles[ptPcr].pid, ptPcr);
377  DelPid(pidHandles[ptDolby].pid);
378 }
379 
380 bool cDvbSdFfDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
381 {
382  int apid = Channel->Apid(0);
383  int vpid = Channel->Vpid();
384  int dpid = Channel->Dpid(0);
385 
386  bool DoTune = !IsTunedToTransponder(Channel);
387 
388  bool pidHandlesVideo = vpid && pidHandles[ptVideo].pid == vpid;
389  bool pidHandlesAudio = apid && pidHandles[ptAudio].pid == apid;
390 
391  bool TurnOffLivePIDs = DoTune
392  || !IsPrimaryDevice()
393  || LiveView // for a new live view the old PIDs need to be turned off
394  || pidHandlesVideo // for recording the PIDs must be shifted from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
395  ;
396 
397  bool StartTransferMode = IsPrimaryDevice() && !DoTune
398  && (LiveView && HasPid(vpid ? vpid : apid) && (!pidHandlesVideo || (!pidHandlesAudio && (dpid ? pidHandles[ptAudio].pid != dpid : true)))// the PID is already set as DMX_PES_OTHER
399  || !LiveView && (pidHandlesVideo || pidHandlesAudio) // a recording is going to shift the PIDs from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER
400  );
401  if (CamSlot() && !ChannelCamRelations.CamDecrypt(Channel->GetChannelID(), CamSlot()->SlotNumber()))
402  StartTransferMode |= LiveView && IsPrimaryDevice() && Channel->Ca() >= CA_ENCRYPTED_MIN;
403 
404  bool TurnOnLivePIDs = !StartTransferMode && LiveView;
405 
406  // Turn off live PIDs if necessary:
407 
408  if (TurnOffLivePIDs)
409  TurnOffLiveMode(LiveView);
410 
411  // Set the tuner:
412 
413  if (!cDvbDevice::SetChannelDevice(Channel, LiveView))
414  return false;
415 
416  // PID settings:
417 
418  if (TurnOnLivePIDs) {
419  SetAudioBypass(false);
420  if (!(AddPid(Channel->Ppid(), ptPcr) && AddPid(vpid, ptVideo) && AddPid(apid, ptAudio))) {
421  esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->Number(), CardIndex() + 1);
422  return false;
423  }
424  if (IsPrimaryDevice())
425  AddPid(Channel->Tpid(), ptTeletext);
426  CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, true)); // actually one would expect 'false' here, but according to Marco Schluessler <marco@lordzodiac.de> this works
427  // to avoid missing audio after replaying a DVD; with 'false' there is an audio disturbance when switching
428  // between two channels on the same transponder on DVB-S
429  CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
430  }
431  else if (StartTransferMode)
432  cControl::Launch(new cTransferControl(this, Channel));
433 
434  return true;
435 }
436 
438 {
439  audio_status_t as;
440  CHECK(ioctl(fd_audio, AUDIO_GET_STATUS, &as));
441  return as.channel_select;
442 }
443 
445 {
446  CHECK(ioctl(fd_audio, AUDIO_CHANNEL_SELECT, AudioChannel));
447 }
448 
450 {
451  if (digitalAudio)
452  Volume = 0;
453  audio_mixer_t am;
454  // conversion for linear volume response:
455  am.volume_left = am.volume_right = 2 * Volume - Volume * Volume / 255;
456  CHECK(ioctl(fd_audio, AUDIO_SET_MIXER, &am));
457 }
458 
460 {
461  if (digitalAudio != On) {
462  if (digitalAudio)
463  cCondWait::SleepMs(1000); // Wait until any leftover digital data has been flushed
464  digitalAudio = On;
465  SetVolumeDevice(On || IsMute() ? 0 : CurrentVolume());
466  }
467 }
468 
470 {
471  const tTrackId *TrackId = GetTrack(Type);
472  if (TrackId && TrackId->id) {
473  SetAudioBypass(false);
474  if (IS_AUDIO_TRACK(Type) || (IS_DOLBY_TRACK(Type) && SetAudioBypass(true))) {
475  if (pidHandles[ptAudio].pid && pidHandles[ptAudio].pid != TrackId->id) {
477  if (CamSlot())
478  CamSlot()->SetPid(pidHandles[ptAudio].pid, false);
479  pidHandles[ptAudio].pid = TrackId->id;
480  SetPid(&pidHandles[ptAudio], ptAudio, true);
481  if (CamSlot()) {
482  CamSlot()->SetPid(pidHandles[ptAudio].pid, true);
483  CamSlot()->StartDecrypting();
484  }
485  }
486  }
487  else if (IS_DOLBY_TRACK(Type)) {
489  return;
490  // Currently this works only in Transfer Mode
492  }
493  }
494 }
495 
497 {
498  return cDevice::CanReplay();
499 }
500 
502 {
503  if (PlayMode != pmExtern_THIS_SHOULD_BE_AVOIDED && fd_video < 0 && fd_audio < 0) {
504  // reopen the devices
505  fd_video = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDWR | O_NONBLOCK);
506  fd_audio = DvbOpen(DEV_DVB_AUDIO, adapter, frontend, O_RDWR | O_NONBLOCK);
508  }
509 
510  switch (PlayMode) {
511  case pmNone:
512  // special handling to return from PCM replay:
513  CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
514  CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
515  CHECK(ioctl(fd_video, VIDEO_PLAY));
516 
517  CHECK(ioctl(fd_video, VIDEO_STOP, true));
518  CHECK(ioctl(fd_audio, AUDIO_STOP, true));
519  CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER));
520  CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER));
521  CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX));
522  CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX));
523  CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
524  CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false));
525  break;
526  case pmAudioVideo:
527  case pmAudioOnlyBlack:
528  if (playMode == pmNone)
529  TurnOffLiveMode(true);
530  CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
531  CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
532  CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, PlayMode == pmAudioVideo));
533  CHECK(ioctl(fd_audio, AUDIO_PLAY));
534  CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
535  CHECK(ioctl(fd_video, VIDEO_PLAY));
536  break;
537  case pmAudioOnly:
538  CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
539  CHECK(ioctl(fd_audio, AUDIO_STOP, true));
540  CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER));
541  CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
542  CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false));
543  CHECK(ioctl(fd_audio, AUDIO_PLAY));
544  CHECK(ioctl(fd_video, VIDEO_SET_BLANK, false));
545  break;
546  case pmVideoOnly:
547  CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true));
548  CHECK(ioctl(fd_video, VIDEO_STOP, true));
549  CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX));
550  CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false));
551  CHECK(ioctl(fd_audio, AUDIO_PLAY));
552  CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER));
553  CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
554  CHECK(ioctl(fd_video, VIDEO_PLAY));
555  break;
557  close(fd_video);
558  close(fd_audio);
559  fd_video = fd_audio = -1;
560  break;
561  default: esyslog("ERROR: unknown playmode %d", PlayMode);
562  }
563  playMode = PlayMode;
564  return true;
565 }
566 
568 {
569  if (fd_stc >= 0) {
570  struct dmx_stc stc;
571  stc.num = 0;
572  if (ioctl(fd_stc, DMX_GET_STC, &stc) == -1) {
573  esyslog("ERROR: stc %d: %m", CardIndex() + 1);
574  return -1;
575  }
576  return stc.stc / stc.base;
577  }
578  return -1;
579 }
580 
581 void cDvbSdFfDevice::TrickSpeed(int Speed, bool Forward)
582 {
583  if (fd_video >= 0)
584  CHECK(ioctl(fd_video, VIDEO_SLOWMOTION, Speed));
585 }
586 
588 {
589  if (fd_video >= 0)
590  CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER));
591  if (fd_audio >= 0)
592  CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER));
593  cDevice::Clear();
594 }
595 
597 {
599  if (fd_audio >= 0)
600  CHECK(ioctl(fd_audio, AUDIO_CONTINUE));
601  }
602  else {
603  if (fd_audio >= 0) {
604  CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true));
605  CHECK(ioctl(fd_audio, AUDIO_CONTINUE));
606  }
607  if (fd_video >= 0)
608  CHECK(ioctl(fd_video, VIDEO_CONTINUE));
609  }
610  cDevice::Play();
611 }
612 
614 {
616  if (fd_audio >= 0)
617  CHECK(ioctl(fd_audio, AUDIO_PAUSE));
618  }
619  else {
620  if (fd_audio >= 0) {
621  CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false));
622  CHECK(ioctl(fd_audio, AUDIO_PAUSE));
623  }
624  if (fd_video >= 0)
625  CHECK(ioctl(fd_video, VIDEO_FREEZE));
626  }
627  cDevice::Freeze();
628 }
629 
631 {
632  if (fd_audio >= 0) {
633  CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false));
634  CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, true));
635  }
636  cDevice::Mute();
637 }
638 
639 void cDvbSdFfDevice::StillPicture(const uchar *Data, int Length)
640 {
641  if (!Data || Length < TS_SIZE)
642  return;
643  if (Data[0] == 0x47) {
644  // TS data
645  cDevice::StillPicture(Data, Length);
646  }
647  else if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) {
648  // PES data
649  char *buf = MALLOC(char, Length);
650  if (!buf)
651  return;
652  int i = 0;
653  int blen = 0;
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) { // video packet
658  // skip PES header
659  int offs = i + 6;
660  // skip header extension
661  if ((Data[i + 6] & 0xC0) == 0x80) {
662  // MPEG-2 PES header
663  if (Data[i + 8] >= Length)
664  break;
665  offs += 3;
666  offs += Data[i + 8];
667  len -= 3;
668  len -= Data[i + 8];
669  if (len < 0 || offs + len > Length)
670  break;
671  }
672  else {
673  // MPEG-1 PES header
674  while (offs < Length && len > 0 && Data[offs] == 0xFF) {
675  offs++;
676  len--;
677  }
678  if (offs <= Length - 2 && len >= 2 && (Data[offs] & 0xC0) == 0x40) {
679  offs += 2;
680  len -= 2;
681  }
682  if (offs <= Length - 5 && len >= 5 && (Data[offs] & 0xF0) == 0x20) {
683  offs += 5;
684  len -= 5;
685  }
686  else if (offs <= Length - 10 && len >= 10 && (Data[offs] & 0xF0) == 0x30) {
687  offs += 10;
688  len -= 10;
689  }
690  else if (offs < Length && len > 0) {
691  offs++;
692  len--;
693  }
694  }
695  if (blen + len > Length) // invalid PES length field
696  break;
697  memcpy(&buf[blen], &Data[offs], len);
698  i = offs + len;
699  blen += len;
700  }
701  else if (Data[i + 3] >= 0xBD && Data[i + 3] <= 0xDF) // other PES packets
702  i += len + 6;
703  else
704  i++;
705  }
706  else
707  i++;
708  }
709  video_still_picture sp = { buf, blen };
710  CHECK(ioctl(fd_video, VIDEO_STILLPICTURE, &sp));
711  free(buf);
712  }
713  else {
714  // non-PES data
715  video_still_picture sp = { (char *)Data, Length };
716  CHECK(ioctl(fd_video, VIDEO_STILLPICTURE, &sp));
717  }
718 }
719 
720 bool cDvbSdFfDevice::Poll(cPoller &Poller, int TimeoutMs)
721 {
722  Poller.Add((playMode == pmAudioOnly || playMode == pmAudioOnlyBlack) ? fd_audio : fd_video, true);
723  return Poller.Poll(TimeoutMs);
724 }
725 
726 bool cDvbSdFfDevice::Flush(int TimeoutMs)
727 {
728  //TODO actually this function should wait until all buffered data has been processed by the card, but how?
729  return true;
730 }
731 
732 int cDvbSdFfDevice::PlayVideo(const uchar *Data, int Length)
733 {
734  return WriteAllOrNothing(fd_video, Data, Length, 1000, 10);
735 }
736 
737 int cDvbSdFfDevice::PlayAudio(const uchar *Data, int Length, uchar Id)
738 {
739  return WriteAllOrNothing(fd_audio, Data, Length, 1000, 10);
740 }
741 
742 int cDvbSdFfDevice::PlayTsVideo(const uchar *Data, int Length)
743 {
744  return WriteAllOrNothing(fd_video, Data, Length, 1000, 10);
745 }
746 
747 int cDvbSdFfDevice::PlayTsAudio(const uchar *Data, int Length)
748 {
749  return WriteAllOrNothing(fd_audio, Data, Length, 1000, 10);
750 }
751 
752 // --- cDvbSdFfDeviceProbe ---------------------------------------------------
753 
755 {
756  outputOnly = false;
757 }
758 
759 bool cDvbSdFfDeviceProbe::Probe(int Adapter, int Frontend)
760 {
761  static uint32_t SubsystemIds[] = {
762  0x110A0000, // Fujitsu Siemens DVB-C
763  0x13C20000, // Technotrend/Hauppauge WinTV DVB-S rev1.X or Fujitsu Siemens DVB-C
764  0x13C20001, // Technotrend/Hauppauge WinTV DVB-T rev1.X
765  0x13C20002, // Technotrend/Hauppauge WinTV DVB-C rev2.X
766  0x13C20003, // Technotrend/Hauppauge WinTV Nexus-S rev2.X
767  0x13C20004, // Galaxis DVB-S rev1.3
768  0x13C20006, // Fujitsu Siemens DVB-S rev1.6
769  0x13C20008, // Technotrend/Hauppauge DVB-T
770  0x13C2000A, // Technotrend/Hauppauge WinTV Nexus-CA rev1.X
771  0x13C2000E, // Technotrend/Hauppauge WinTV Nexus-S rev2.3
772  0x13C21002, // Technotrend/Hauppauge WinTV DVB-S rev1.3 SE
773  0x00000000
774  };
775  uint32_t SubsystemId = GetSubsystemId(Adapter, Frontend);
776  for (uint32_t *sid = SubsystemIds; *sid; sid++) {
777  if (*sid == SubsystemId) {
778  dsyslog("creating cDvbSdFfDevice");
779  new cDvbSdFfDevice(Adapter, Frontend, outputOnly);
780  return true;
781  }
782  }
783  return false;
784 }
cDvbSdFfDeviceProbe::cDvbSdFfDeviceProbe
cDvbSdFfDeviceProbe(void)
Definition: dvbsdffdevice.c:754
TS_SIZE
#define TS_SIZE
Definition: remux.h:34
cPoller::Poll
bool Poll(int TimeoutMs=0)
Definition: tools.c:1517
cTransferControl
Definition: transfer.h:30
cPoller
Definition: tools.h:393
cDvbDeviceProbe::GetSubsystemId
static uint32_t GetSubsystemId(int Adapter, int Frontend)
Definition: dvbdevice.c:2368
cDvbSdFfDevice::PlayTsAudio
virtual int PlayTsAudio(const uchar *Data, int Length)
Plays the given data block as audio.
Definition: dvbsdffdevice.c:747
cChannel::Ppid
int Ppid(void) const
Definition: channels.h:155
DEV_DVB_OSD
#define DEV_DVB_OSD
Definition: dvbdevice.h:73
cChannelCamRelations::CamDecrypt
bool CamDecrypt(tChannelID ChannelID, int CamSlotNumber)
Definition: ci.c:2974
cDvbSdFfDevice::spuDecoder
cDvbSpuDecoder * spuDecoder
Definition: dvbsdffdevice.h:32
cDvbSdFfDevice::~cDvbSdFfDevice
virtual ~cDvbSdFfDevice()
Definition: dvbsdffdevice.c:71
cDvbOsdProvider
Definition: dvbsdffosd.h:14
cDvbSdFfDevice::HasDecoder
virtual bool HasDecoder(void) const
Tells whether this device has an MPEG decoder.
Definition: dvbsdffdevice.c:85
cSetup::VideoFormat
int VideoFormat
Definition: config.h:317
pmAudioOnly
@ pmAudioOnly
Definition: device.h:41
pmExtern_THIS_SHOULD_BE_AVOIDED
@ pmExtern_THIS_SHOULD_BE_AVOIDED
Definition: device.h:44
cDvbSdFfDevice::PlayTsVideo
virtual int PlayTsVideo(const uchar *Data, int Length)
Plays the given data block as video.
Definition: dvbsdffdevice.c:742
cChannel::Number
int Number(void) const
Definition: channels.h:179
dvbsdffosd.h
cChannel::Dpid
int Dpid(int i) const
Definition: channels.h:161
cDvbSdFfDevice::SetAudioTrackDevice
virtual void SetAudioTrackDevice(eTrackType Type)
Sets the current audio track to the given value.
Definition: dvbsdffdevice.c:469
DEV_DVB_AUDIO
#define DEV_DVB_AUDIO
Definition: dvbdevice.h:78
cDvbSdFfDevice::Poll
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.
Definition: dvbsdffdevice.c:720
cDvbSdFfDevice::SetVideoFormat
virtual void SetVideoFormat(bool VideoFormat16_9)
Sets the output video format to either 16:9 or 4:3 (only useful if this device has an MPEG decoder).
Definition: dvbsdffdevice.c:238
cDevice::AddPid
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:541
cDvbSdFfDevice::ProvidesSource
virtual bool ProvidesSource(int Source) const
Returns true if this device can provide the given source.
Definition: dvbsdffdevice.c:342
DvbOpen
int DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, bool ReportError)
Definition: dvbdevice.c:1868
cDvbSdFfDevice::PlayAudio
virtual int PlayAudio(const uchar *Data, int Length, uchar Id)
Plays the given data block as audio.
Definition: dvbsdffdevice.c:737
cDvbSdFfDevice::Mute
virtual void Mute(void)
Turns off audio while replaying.
Definition: dvbsdffdevice.c:630
tTrackId
Definition: device.h:80
cDvbDevice::frontend
int frontend
Definition: dvbdevice.h:184
tTrackId::id
uint16_t id
Definition: device.h:81
cDevice::CurrentVolume
static int CurrentVolume(void)
Definition: device.h:622
cDevice::HasPid
bool HasPid(int Pid) const
Returns true if this device is currently receiving the given PID.
Definition: device.c:531
Setup
cSetup Setup
Definition: config.c:372
cDvbSdFfDevice::StillPicture
virtual void StillPicture(const uchar *Data, int Length)
Displays the given I-frame as a still picture.
Definition: dvbsdffdevice.c:639
cSetup::VideoDisplayFormat
int VideoDisplayFormat
Definition: config.h:316
cDvbSdFfDevice::Play
virtual void Play(void)
Sets the device into play mode (after a previous trick mode).
Definition: dvbsdffdevice.c:596
cDevice::SetVideoDisplayFormat
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:487
cDvbSdFfDevice::devVideoIndex
int devVideoIndex
Definition: dvbsdffdevice.h:57
cDvbSdFfDevice::fd_video
int fd_video
Definition: dvbsdffdevice.h:19
cDvbSdFfDevice::SetChannelDevice
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView)
Sets the device to the given channel (actual physical setup).
Definition: dvbsdffdevice.c:380
cDvbSdFfDevice::SetAudioChannelDevice
virtual void SetAudioChannelDevice(int AudioChannel)
Sets the audio channel to stereo (0), mono left (1) or mono right (2).
Definition: dvbsdffdevice.c:444
cDvbSdFfDevice::GetSpuDecoder
virtual cSpuDecoder * GetSpuDecoder(void)
Returns a pointer to the device's SPU decoder (or NULL, if this device doesn't have an SPU decoder).
Definition: dvbsdffdevice.c:95
cDevice::DetachAll
void DetachAll(int Pid)
Detaches all receivers from this device for this pid.
Definition: device.c:1831
CA_ENCRYPTED_MIN
#define CA_ENCRYPTED_MIN
Definition: channels.h:44
cDevice::MakePrimaryDevice
virtual void MakePrimaryDevice(bool On)
Informs a device that it will be the primary device.
Definition: device.c:179
cDvbSdFfDevice::SetDigitalAudioDevice
virtual void SetDigitalAudioDevice(bool On)
Tells the output device that the current audio track is Dolby Digital.
Definition: dvbsdffdevice.c:459
cDvbSdFfDevice::GetSTC
virtual int64_t GetSTC(void)
Gets the current System Time Counter, which can be used to synchronize audio, video and subtitles.
Definition: dvbsdffdevice.c:567
cDevice::ptVideo
@ ptVideo
Definition: device.h:390
cDevice::cPidHandle::pid
int pid
Definition: device.h:393
cDevice::CanReplay
virtual bool CanReplay(void) const
Returns true if this device can currently start a replay session.
Definition: device.c:1205
cDevice::IsPrimaryDevice
bool IsPrimaryDevice(void) const
Definition: device.h:213
DEV_VIDEO
#define DEV_VIDEO
Definition: dvbdevice.h:70
cDvbSdFfDevice::SetAudioBypass
bool SetAudioBypass(bool On)
Definition: dvbsdffdevice.c:290
cControl::Launch
static void Launch(cControl *Control)
Definition: player.c:79
pmVideoOnly
@ pmVideoOnly
Definition: device.h:43
DEV_DVB_DEMUX
#define DEV_DVB_DEMUX
Definition: dvbdevice.h:76
cDevice::GetVideoSize
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:514
uchar
unsigned char uchar
Definition: tools.h:31
cDvbSdFfDevice::AvoidRecording
virtual bool AvoidRecording(void) const
Definition: dvbsdffdevice.c:90
cDevice::StillPicture
virtual void StillPicture(const uchar *Data, int Length)
Displays the given I-frame as a still picture.
Definition: device.c:1250
cDevice::cPidHandle
Definition: device.h:391
cDvbDevice::SetChannelDevice
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView)
Sets the device to the given channel (actual physical setup).
Definition: dvbdevice.c:2284
vdfCenterCutOut
@ vdfCenterCutOut
Definition: device.h:60
cChannel::Tpid
int Tpid(void) const
Definition: channels.h:171
cDvbDevice::setTransferModeForDolbyDigital
static int setTransferModeForDolbyDigital
Definition: dvbdevice.h:273
cDevice::DelPid
void DelPid(int Pid, ePidType PidType=ptOther)
Deletes a PID from the set of PIDs this device shall receive.
Definition: device.c:606
cDvbDevice::adapter
int adapter
Definition: dvbdevice.h:184
cDvbSdFfDevice::CanReplay
virtual bool CanReplay(void) const
Returns true if this device can currently start a replay session.
Definition: dvbsdffdevice.c:496
cDvbSdFfDevice::MakePrimaryDevice
virtual void MakePrimaryDevice(bool On)
Informs a device that it will be the primary device.
Definition: dvbsdffdevice.c:78
cDvbSdFfDevice::GetOsdSize
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 ...
Definition: dvbsdffdevice.c:265
ePlayMode
ePlayMode
Definition: device.h:39
eTrackType
eTrackType
Definition: device.h:63
cDevice::Freeze
virtual void Freeze(void)
Puts the device into "freeze frame" mode.
Definition: device.c:1238
cDvbSdFfDeviceProbe::Probe
virtual bool Probe(int Adapter, int Frontend)
Probes for a DVB device at the given Adapter and creates the appropriate object derived from cDvbDevi...
Definition: dvbsdffdevice.c:759
IS_AUDIO_TRACK
#define IS_AUDIO_TRACK(t)
Definition: device.h:76
cDevice::pidHandles
cPidHandle pidHandles[MAXPIDHANDLES]
Definition: device.h:399
cDvbSdFfDevice::Flush
virtual bool Flush(int TimeoutMs=0)
Returns true if the device's output buffers are empty, i.
Definition: dvbsdffdevice.c:726
cDevice::ptDolby
@ ptDolby
Definition: device.h:390
cDvbSdFfDevice::cDvbSdFfDevice
cDvbSdFfDevice(int Adapter, int Frontend, bool OutputOnly)
Definition: dvbsdffdevice.c:26
ChannelCamRelations
cChannelCamRelations ChannelCamRelations
Definition: ci.c:2917
cChannel::Vpid
int Vpid(void) const
Definition: channels.h:154
cDevice::ptTeletext
@ ptTeletext
Definition: device.h:390
cDvbDevice
The cDvbDevice implements a DVB device which can be accessed through the Linux DVB driver API.
Definition: dvbdevice.h:171
dsyslog
#define dsyslog(a...)
Definition: tools.h:37
cDvbSpuDecoder
Definition: dvbspu.h:95
pmAudioOnlyBlack
@ pmAudioOnlyBlack
Definition: device.h:42
cDevice::GetOsdSize
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 ...
Definition: device.c:521
cChannel
Definition: channels.h:89
cDevice::ptPcr
@ ptPcr
Definition: device.h:390
cChannel::Apid
int Apid(int i) const
Definition: channels.h:160
cDevice::GetTrack
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:1079
MALLOC
#define MALLOC(type, size)
Definition: tools.h:47
cDvbSdFfDevice::SetPid
virtual bool SetPid(cPidHandle *Handle, int Type, bool On)
Does the actual PID setting on this device.
Definition: dvbsdffdevice.c:300
cSpuDecoder
Definition: spu.h:19
cDvbSdFfDevice::outputOnly
bool outputOnly
Definition: dvbsdffdevice.h:20
LOG_ERROR
#define LOG_ERROR
Definition: tools.h:39
cDvbSdFfDevice::TurnOffLiveMode
void TurnOffLiveMode(bool LiveView)
Definition: dvbsdffdevice.c:357
cDevice::Mute
virtual void Mute(void)
Turns off audio while replaying.
Definition: device.c:1245
RgbToJpeg
uchar * RgbToJpeg(uchar *Mem, int Width, int Height, int &Size, int Quality)
Converts the given Memory to a JPEG image and returns a pointer to the resulting image.
Definition: tools.c:1298
cDvbDevice::IsTunedToTransponder
virtual bool IsTunedToTransponder(const cChannel *Channel) const
Returns true if this device is currently tuned to the given Channel's transponder.
Definition: dvbdevice.c:2274
PesTypes
static dmx_pes_type_t PesTypes[]
Definition: dvbsdffdevice.c:298
cDvbDevice::ProvidesSource
virtual bool ProvidesSource(int Source) const
Returns true if this device can provide the given source.
Definition: dvbdevice.c:2166
WriteAllOrNothing
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
CHECK
#define CHECK(s)
Definition: tools.h:51
vdfLetterBox
@ vdfLetterBox
Definition: device.h:59
pmNone
@ pmNone
Definition: device.h:39
cDvbSdFfDevice::playMode
ePlayMode playMode
Definition: dvbsdffdevice.h:87
cDevice::cPidHandle::used
int used
Definition: device.h:396
cCondWait::SleepMs
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
Definition: thread.c:72
cDvbSdFfDevice::fd_osd
int fd_osd
Definition: dvbsdffdevice.h:19
cDvbSdFfDevice::GrabImage
virtual uchar * GrabImage(int &Size, bool Jpeg=true, int Quality=-1, int SizeX=-1, int SizeY=-1)
Grabs the currently visible screen image.
Definition: dvbsdffdevice.c:102
cChannel::Ca
int Ca(int Index=0) const
Definition: channels.h:173
cDevice::ForceTransferMode
void ForceTransferMode(void)
Forces the device into transfermode for the current channel.
Definition: device.c:921
cDvbSdFfDevice::SetVideoDisplayFormat
virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
Sets the video display format to the given one (only useful if this device has an MPEG decoder).
Definition: dvbsdffdevice.c:216
cChannel::GetChannelID
tChannelID GetChannelID(void) const
Definition: channels.h:190
cDvbDevice::NumProvidedSystems
virtual int NumProvidedSystems(void) const
Returns the number of individual "delivery systems" this device provides.
Definition: dvbdevice.c:2244
cDvbSdFfDevice::PlayVideo
virtual int PlayVideo(const uchar *Data, int Length)
Plays the given data block as video.
Definition: dvbsdffdevice.c:732
cDevice::Clear
virtual void Clear(void)
Clears all video and audio data from the device.
Definition: device.c:1224
cDevice::Play
virtual void Play(void)
Sets the device into play mode (after a previous trick mode).
Definition: device.c:1231
DEV_DVB_VIDEO
#define DEV_DVB_VIDEO
Definition: dvbdevice.h:77
cDvbSdFfDevice::devVideoOffset
static int devVideoOffset
Definition: dvbsdffdevice.h:56
vdfPanAndScan
@ vdfPanAndScan
Definition: device.h:58
dvbsdffdevice.h
cDevice::ptAudio
@ ptAudio
Definition: device.h:390
cDvbSdFfDevice::NumProvidedSystems
virtual int NumProvidedSystems(void) const
Returns the number of individual "delivery systems" this device provides.
Definition: dvbsdffdevice.c:350
cDvbSdFfDevice::digitalAudio
bool digitalAudio
Definition: dvbsdffdevice.h:77
cPoller::Add
bool Add(int FileHandle, bool Out)
Definition: tools.c:1485
cDevice::cPidHandle::handle
int handle
Definition: device.h:395
eVideoDisplayFormat
eVideoDisplayFormat
Definition: device.h:58
cDvbSdFfDevice::fd_audio
int fd_audio
Definition: dvbsdffdevice.h:19
cDvbSdFfDevice::Clear
virtual void Clear(void)
Clears all video and audio data from the device.
Definition: dvbsdffdevice.c:587
cDvbSdFfDevice::GetVideoSize
virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect)
Returns the Width, Height and VideoAspect ratio of the currently displayed video material.
Definition: dvbsdffdevice.c:244
cDvbSdFfDevice::SetVolumeDevice
virtual void SetVolumeDevice(int Volume)
Sets the audio volume on this device (Volume = 0...255).
Definition: dvbsdffdevice.c:449
esyslog
#define esyslog(a...)
Definition: tools.h:35
cDvbSdFfDevice
The cDvbSdFfDevice implements a DVB device which can be accessed through the Linux DVB driver API.
Definition: dvbsdffdevice.h:17
cDvbSdFfDevice::fd_stc
int fd_stc
Definition: dvbsdffdevice.h:19
cDvbSdFfDevice::GetAudioChannelDevice
virtual int GetAudioChannelDevice(void)
Gets the current audio channel, which is stereo (0), mono left (1) or mono right (2).
Definition: dvbsdffdevice.c:437
cDvbSdFfDevice::Freeze
virtual void Freeze(void)
Puts the device into "freeze frame" mode.
Definition: dvbsdffdevice.c:613
LOG_ERROR_STR
#define LOG_ERROR_STR(s)
Definition: tools.h:40
cDvbSdFfDeviceProbe::outputOnly
bool outputOnly
Definition: dvbsdffdevice.h:108
cDvbSdFfDevice::TrickSpeed
virtual void TrickSpeed(int Speed, bool Forward)
Sets the device into a mode where replay is done slower.
Definition: dvbsdffdevice.c:581
cDevice::IsMute
bool IsMute(void) const
Definition: device.h:610
cDevice::ptOther
@ ptOther
Definition: device.h:390
pmAudioVideo
@ pmAudioVideo
Definition: device.h:40
cDvbSdFfDevice::SetPlayMode
virtual bool SetPlayMode(ePlayMode PlayMode)
Sets the device into the given play mode.
Definition: dvbsdffdevice.c:501
IS_DOLBY_TRACK
#define IS_DOLBY_TRACK(t)
Definition: device.h:77