12 #include <linux/videodev2.h>
13 #include <linux/dvb/audio.h>
14 #include <linux/dvb/dmx.h>
15 #include <linux/dvb/video.h>
16 #include <sys/ioctl.h>
18 #include <vdr/eitscan.h>
19 #include <vdr/transfer.h>
45 char buffer[PATH_MAX];
46 for (
int ofs = 0; ofs < 100; ofs++) {
47 snprintf(buffer,
sizeof(buffer),
"/proc/video/dev/video%d", ofs);
48 if ((f = fopen(buffer,
"r")) != NULL) {
49 if (fgets(buffer,
sizeof(buffer), f)) {
50 if (strstr(buffer,
"DVB Board")) {
106 char buffer[PATH_MAX];
108 int videoDev = open(buffer, O_RDWR);
110 uchar *result = NULL;
113 memset(&fmt, 0,
sizeof(fmt));
114 fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
115 fmt.fmt.pix.width = SizeX;
116 fmt.fmt.pix.height = SizeY;
117 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_BGR24;
118 fmt.fmt.pix.field = V4L2_FIELD_ANY;
119 if (ioctl(videoDev, VIDIOC_S_FMT, &fmt) == 0) {
120 v4l2_requestbuffers reqBuf;
121 memset(&reqBuf, 0,
sizeof(reqBuf));
123 reqBuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
124 reqBuf.memory = V4L2_MEMORY_MMAP;
125 if (ioctl(videoDev, VIDIOC_REQBUFS, &reqBuf) >= 0) {
127 memset(&mbuf, 0,
sizeof(mbuf));
128 mbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
129 mbuf.memory = V4L2_MEMORY_MMAP;
130 if (ioctl(videoDev, VIDIOC_QUERYBUF, &mbuf) == 0) {
131 int msize = mbuf.length;
132 unsigned char *mem = (
unsigned char *)mmap(0, msize, PROT_READ | PROT_WRITE, MAP_SHARED, videoDev, 0);
133 if (mem && mem != (
unsigned char *)-1) {
135 memset(&buf, 0,
sizeof(buf));
136 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
137 buf.memory = V4L2_MEMORY_MMAP;
139 if (ioctl(videoDev, VIDIOC_QBUF, &buf) == 0) {
140 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
141 if (ioctl (videoDev, VIDIOC_STREAMON, &type) == 0) {
142 memset(&buf, 0,
sizeof(buf));
143 buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
144 buf.memory = V4L2_MEMORY_MMAP;
146 if (ioctl(videoDev, VIDIOC_DQBUF, &buf) == 0) {
147 if (ioctl(videoDev, VIDIOC_STREAMOFF, &type) == 0) {
149 int memsize = fmt.fmt.pix.width * fmt.fmt.pix.height;
150 unsigned char *mem1 = mem;
151 for (
int i = 0; i < memsize; i++) {
152 unsigned char tmp = mem1[2];
161 dsyslog(
"grabbing to %s %d %d %d", Jpeg ?
"JPEG" :
"PNM", Quality, fmt.fmt.pix.width, fmt.fmt.pix.height);
164 result =
RgbToJpeg(mem, fmt.fmt.pix.width, fmt.fmt.pix.height, Size, Quality);
166 esyslog(
"ERROR: failed to convert image to JPEG");
171 snprintf(buf,
sizeof(buf),
"P6\n%d\n%d\n255\n", fmt.fmt.pix.width, fmt.fmt.pix.height);
173 int bytes = memsize * 3;
177 memcpy(result, buf, l);
178 memcpy(result + l, mem, bytes);
181 esyslog(
"ERROR: failed to convert image to PNM");
185 esyslog(
"ERROR: video device VIDIOC_STREAMOFF failed");
188 esyslog(
"ERROR: video device VIDIOC_DQBUF failed");
191 esyslog(
"ERROR: video device VIDIOC_STREAMON failed");
194 esyslog(
"ERROR: video device VIDIOC_QBUF failed");
198 esyslog(
"ERROR: failed to memmap video device");
201 esyslog(
"ERROR: video device VIDIOC_QUERYBUF failed");
204 esyslog(
"ERROR: video device VIDIOC_REQBUFS failed");
207 esyslog(
"ERROR: video device VIDIOC_S_FMT failed");
220 CHECK(ioctl(
fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_LETTER_BOX));
223 switch (VideoDisplayFormat) {
225 CHECK(ioctl(
fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_PAN_SCAN));
228 CHECK(ioctl(
fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_LETTER_BOX));
231 CHECK(ioctl(
fd_video, VIDEO_SET_DISPLAY_FORMAT, VIDEO_CENTER_CUT_OUT));
233 default:
esyslog(
"ERROR: unknown video display format %d", VideoDisplayFormat);
240 CHECK(ioctl(
fd_video, VIDEO_SET_FORMAT, VideoFormat16_9 ? VIDEO_FORMAT_16_9 : VIDEO_FORMAT_4_3));
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)
397 int apid = Channel->
Apid(0);
398 int vpid = Channel->
Vpid();
399 int dpid = Channel->
Dpid(0);
406 bool TurnOffLivePIDs = DoTune
413 && (LiveView &&
HasPid(vpid ? vpid : apid) && (!pidHandlesVideo || (!pidHandlesAudio && (dpid ?
pidHandles[
ptAudio].
pid != dpid :
true)))
414 || !LiveView && (pidHandlesVideo || pidHandlesAudio)
419 bool TurnOnLivePIDs = !StartTransferMode && LiveView;
433 if (TurnOnLivePIDs) {
446 else if (StartTransferMode)
456 return as.channel_select;
470 am.volume_left = am.volume_right = 2 * Volume - Volume * Volume / 255;
487 if (TrackId && TrackId->
id) {
529 CHECK(ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
536 CHECK(ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX));
537 CHECK(ioctl(
fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX));
546 CHECK(ioctl(
fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
549 CHECK(ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
556 CHECK(ioctl(
fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY));
564 CHECK(ioctl(
fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX));
568 CHECK(ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY));
576 default:
esyslog(
"ERROR: unknown playmode %d", PlayMode);
587 if (ioctl(
fd_stc, DMX_GET_STC, &stc) == -1) {
591 return stc.stc / stc.base;
658 if (Data[0] == 0x47) {
662 else if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) {
669 while (i < Length - 6) {
670 if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) {
671 int len = Data[i + 4] * 256 + Data[i + 5];
672 if ((Data[i + 3] & 0xF0) == 0xE0) {
676 if ((Data[i + 6] & 0xC0) == 0x80) {
678 if (Data[i + 8] >= Length)
684 if (len < 0 || offs + len > Length)
689 while (offs < Length && len > 0 && Data[offs] == 0xFF) {
693 if (offs <= Length - 2 && len >= 2 && (Data[offs] & 0xC0) == 0x40) {
697 if (offs <= Length - 5 && len >= 5 && (Data[offs] & 0xF0) == 0x20) {
701 else if (offs <= Length - 10 && len >= 10 && (Data[offs] & 0xF0) == 0x30) {
705 else if (offs < Length && len > 0) {
710 if (blen + len > Length)
712 memcpy(&buf[blen], &Data[offs], len);
716 else if (Data[i + 3] >= 0xBD && Data[i + 3] <= 0xDF)
724 video_still_picture sp = {
buf, blen };
730 video_still_picture sp = { (
char *)Data, Length };
738 return Poller.
Poll(TimeoutMs);
776 static uint32_t SubsystemIds[] = {
790 uint32_t SubsystemId = GetSubsystemId(Adapter, Frontend);
791 for (uint32_t *sid = SubsystemIds; *sid; sid++) {
792 if (*sid == SubsystemId) {
793 dsyslog(
"creating cDvbSdFfDevice");
virtual void Clear(void)
Clears all video and audio data from the device.
static unsigned char buf(long p)
virtual bool ProvidesSource(int Source) const
Returns true if this device can provide the given source.
virtual eVideoSystem GetVideoSystem(void)
Returns the video system of the currently displayed material (default is PAL).
virtual void SetAudioTrackDevice(eTrackType Type)
Sets the current audio track to the given value.
virtual bool IsTunedToTransponder(const cChannel *Channel) const
Returns true if this device is currently tuned to the given Channel's transponder.
void DetachAll(int Pid)
Detaches all receivers from this device for this pid.
virtual int PlayTsAudio(const uchar *Data, int Length)
Plays the given data block as audio.
int Ca(int Index=0) const
virtual void SetVolumeDevice(int Volume)
Sets the audio volume on this device (Volume = 0...255).
void StartDecrypting(void)
Triggers sending all currently active CA_PMT entries to the CAM, so that it will start decrypting...
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)...
virtual int PlayTsVideo(const uchar *Data, int Length)
Plays the given data block as video.
virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect)
Returns the Width, Height and VideoAspect ratio of the currently displayed video material.
virtual void Freeze(void)
Puts the device into "freeze frame" mode.
virtual bool CanReplay(void) const
Returns true if this device can currently start a replay session.
bool Add(int FileHandle, bool Out)
virtual void MakePrimaryDevice(bool On)
Informs a device that it will be the primary device.
virtual ~cDvbSdFfDevice()
virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
Sets the video display format to the given one (only useful if this device has an MPEG decoder)...
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView)
Sets the device to the given channel (actual physical setup).
void DelPid(int Pid, ePidType PidType=ptOther)
Deletes a PID from the set of PIDs this device shall receive.
virtual int PlayAudio(const uchar *Data, int Length, uchar Id)
Plays the given data block as audio.
virtual void TrickSpeed(int Speed)
Sets the device into a mode where replay is done slower.
virtual void Mute(void)
Turns off audio while replaying.
virtual void Play(void)
Sets the device into play mode (after a previous trick mode).
virtual bool AvoidRecording(void) const
Returns true if this device should only be used for recording if no other device is available...
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 ...
virtual void Clear(void)
Clears all video and audio data from the device.
cDvbSpuDecoder * spuDecoder
virtual int64_t GetSTC(void)
Gets the current System Time Counter, which can be used to synchronize audio, video and subtitles...
virtual void MakePrimaryDevice(bool On)
Informs a device that it will be the primary device.
bool Poll(int TimeoutMs=0)
virtual bool ProvidesSource(int Source) const
Returns true if this device can provide the given source.
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 ...
virtual void Play(void)
Sets the device into play mode (after a previous trick mode).
virtual void Mute(void)
Turns off audio while replaying.
virtual bool HasDecoder(void) const
Tells whether this device has an MPEG decoder.
virtual void SetDigitalAudioDevice(bool On)
Tells the actual device that digital audio output shall be switched on or off.
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView)
Sets the device to the given channel (actual physical setup).
virtual void SetAudioChannelDevice(int AudioChannel)
Sets the audio channel to stereo (0), mono left (1) or mono right (2).
static int CurrentVolume(void)
bool IsPrimaryDevice(void) const
cCamSlot * CamSlot(void) const
Returns the CAM slot that is currently used with this device, or NULL if no CAM slot is in use...
virtual void Freeze(void)
Puts the device into "freeze frame" mode.
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...
virtual int NumProvidedSystems(void) const
Returns the number of individual "delivery systems" this device provides.
virtual bool Probe(int Adapter, int Frontend)
Probes for a DVB device at the given Adapter and creates the appropriate object derived from cDvbDevi...
static void SleepMs(int TimeoutMs)
Creates a cCondWait object and uses it to sleep for TimeoutMs milliseconds, immediately giving up the...
virtual void StillPicture(const uchar *Data, int Length)
Displays the given I-frame as a still picture.
#define IS_AUDIO_TRACK(t)
bool SetAudioBypass(bool On)
bool CamDecrypt(tChannelID ChannelID, int CamSlotNumber)
virtual cSpuDecoder * GetSpuDecoder(void)
Returns a pointer to the device's SPU decoder (or NULL, if this device doesn't have an SPU decoder)...
tChannelID GetChannelID(void) const
virtual bool Flush(int TimeoutMs=0)
Returns true if the device's output buffers are empty, i.
static void Launch(cControl *Control)
cDvbSdFfDevice(int Adapter, int Frontend, bool OutputOnly)
static dmx_pes_type_t PesTypes[]
int CardIndex(void) const
Returns the card index of this device (0 ... MAXDEVICES - 1).
virtual int NumProvidedSystems(void) const
Returns the number of individual "delivery systems" this device provides.
void SetPid(int Pid, bool Active)
Sets the given Pid (which has previously been added through a call to AddPid()) to Active...
virtual int PlayVideo(const uchar *Data, int Length)
Plays the given data block as video.
static int setTransferModeForDolbyDigital
void TurnOffLiveMode(bool LiveView)
const tTrackId * GetTrack(eTrackType Type)
Returns a pointer to the given track id, or NULL if Type is not less than ttMaxTrackTypes.
cChannelCamRelations ChannelCamRelations
virtual uchar * GrabImage(int &Size, bool Jpeg=true, int Quality=-1, int SizeX=-1, int SizeY=-1)
Grabs the currently visible screen image.
virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
Sets the video display format to the given one (only useful if this device has an MPEG decoder)...
The cDvbDevice implements a DVB device which can be accessed through the Linux DVB driver API...
virtual bool CanReplay(void) const
Returns true if this device can currently start a replay session.
static int devVideoOffset
bool HasPid(int Pid) const
Returns true if this device is currently receiving the given PID.
virtual bool SetPid(cPidHandle *Handle, int Type, bool On)
Does the actual PID setting on this device.
void ForceTransferMode(void)
Forces the device into transfermode for the current channel.
#define IS_DOLBY_TRACK(t)
cDvbSdFfDeviceProbe(void)
virtual bool SetPlayMode(ePlayMode PlayMode)
Sets the device into the given play mode.
virtual void StillPicture(const uchar *Data, int Length)
Displays the given I-frame as a still picture.
virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect)
Returns the Width, Height and VideoAspect ratio of the currently displayed video material.
cPidHandle pidHandles[MAXPIDHANDLES]
bool AddPid(int Pid, ePidType PidType=ptOther, int StreamType=0)
Adds a PID to the set of PIDs this device shall receive.
int SlotNumber(void)
Returns the number of this CAM slot within the whole system.
virtual int GetAudioChannelDevice(void)
Gets the current audio channel, which is stereo (0), mono left (1) or mono right (2).
static int DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, bool ReportError=false)