13 #include <linux/videodev2.h>
14 #include <linux/dvb/audio.h>
15 #include <linux/dvb/dmx.h>
16 #include <linux/dvb/video.h>
17 #include <sys/ioctl.h>
19 #include <vdr/eitscan.h>
20 #include <vdr/transfer.h>
66 ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX);
79 memset(&hdmiConfig, 0,
sizeof(hdmiConfig));
124 #define BUFFER_SIZE (sizeof(struct v4l2_pix_format) + 1920 * 1080 * 2)
127 uint8_t * result = NULL;
131 esyslog(
"GrabImage: failed open DVB video device");
141 if (readBytes < (
int)
sizeof(
struct v4l2_pix_format))
142 esyslog(
"GrabImage: failed reading from DVB video device");
144 struct v4l2_pix_format * pixfmt;
147 pixfmt = (
struct v4l2_pix_format *) buffer;
148 dsyslog(
"GrabImage: Read image of size %d x %d",
149 pixfmt->width, pixfmt->height);
150 dataSize = readBytes -
sizeof(
struct v4l2_pix_format);
151 if (dataSize < (
int) pixfmt->sizeimage)
152 esyslog(
"GrabImage: image is not complete");
156 temp = (uint8_t *) malloc(pixfmt->width * 3 * pixfmt->height);
158 int numPixels = pixfmt->width * pixfmt->height;
159 uint8_t * destData = temp;
160 uint8_t * srcData = buffer +
sizeof(
struct v4l2_pix_format);
161 while (numPixels > 0)
163 destData[0] = srcData[1];
164 destData[1] = srcData[0];
165 destData[2] = srcData[2];
166 destData[3] = srcData[3];
167 destData[4] = srcData[0];
168 destData[5] = srcData[2];
175 result =
YuvToJpeg(temp, pixfmt->width, pixfmt->height, Size, Quality);
182 snprintf(buf,
sizeof(buf),
"P6\n%d\n%d\n255\n",
183 pixfmt->width, pixfmt->height);
185 Size = l + pixfmt->width * 3 * pixfmt->height;
186 result = (uint8_t *) malloc(Size);
189 memcpy(result, buf, l);
190 uint8_t * destData = result + l;
191 uint8_t * srcData = buffer +
sizeof(
struct v4l2_pix_format);
192 int numPixels = pixfmt->width * pixfmt->height;
193 while (numPixels > 0)
195 int cb = srcData[0] - 128;
197 int cr = srcData[2] - 128;
203 r = y1 + (int) (1.402f * cr);
204 g = y1 - (int) (0.344f * cb + 0.714f * cr);
205 b = y1 + (int) (1.772f * cb);
206 destData[0] = r > 255 ? 255 : r < 0 ? 0 : r;
207 destData[1] = g > 255 ? 255 : g < 0 ? 0 : g;
208 destData[2] = b > 255 ? 255 : b < 0 ? 0 : b;
209 r = y2 + (int) (1.402f * cr);
210 g = y2 - (int) (0.344f * cb + 0.714f * cr);
211 b = y2 + (int) (1.772f * cb);
212 destData[3] = r > 255 ? 255 : r < 0 ? 0 : r;
213 destData[4] = g > 255 ? 255 : g < 0 ? 0 : g;
214 destData[5] = b > 255 ? 255 : b < 0 ? 0 : b;
253 if (ioctl(
fd_video, VIDEO_GET_SIZE, &vs) == 0) {
254 if (vs.h == 480 || vs.h == 240)
267 if (ioctl(
fd_video, VIDEO_GET_SIZE, &vs) == 0) {
270 switch (vs.aspect_ratio) {
272 case VIDEO_FORMAT_4_3: VideoAspect = 4.0 / 3.0;
break;
273 case VIDEO_FORMAT_16_9: VideoAspect = 16.0 / 9.0;
break;
274 case VIDEO_FORMAT_221_1: VideoAspect = 2.21;
break;
293 dmx_pes_filter_params pesFilterParams;
294 memset(&pesFilterParams, 0,
sizeof(pesFilterParams));
327 if (!(Type <= ptDolby && Handle->used <= 1)) {
328 pesFilterParams.pid = Handle->
pid;
329 pesFilterParams.input = DMX_IN_FRONTEND;
330 pesFilterParams.output = DMX_OUT_TS_TAP;
331 pesFilterParams.pes_type= DMX_PES_OTHER;
332 pesFilterParams.flags = DMX_IMMEDIATE_START;
333 if (ioctl(Handle->
handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
339 else if (!Handle->
used) {
374 int apid = Channel->
Apid(0);
375 int vpid = Channel->
Vpid();
376 int dpid = Channel->
Dpid(0);
383 bool TurnOffLivePIDs = DoTune
390 && (LiveView &&
HasPid(vpid ? vpid : apid) && (!pidHandlesVideo || (!pidHandlesAudio && (dpid ?
pidHandles[
ptAudio].
pid != dpid :
true)))
391 || !LiveView && (pidHandlesVideo || pidHandlesAudio)
398 bool TurnOnLivePIDs = !StartTransferMode && LiveView;
412 if (TurnOnLivePIDs) {
418 else if (StartTransferMode)
449 if (TrackId && TrackId->
id) {
495 ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX);
528 ioctl(
fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY);
541 if (ioctl(
fd_video, VIDEO_GET_PTS, &pts) == -1) {
553 if (ioctl(
fd_audio, AUDIO_GET_PTS, &pts) == -1) {
581 double osdPixelAspect;
583 GetOsdSize(osdWidth, osdHeight, osdPixelAspect);
588 int x = (Rect.
X() * 1000 + osdWidth / 2) / osdWidth;
589 int y = (Rect.
Y() * 1000 + osdHeight / 2) / osdHeight;
590 int w = (Rect.
Width() * 1000 + osdWidth / 2) / osdWidth;
591 int h = (Rect.
Height() * 1000 + osdHeight / 2) / osdHeight;
670 if (Data[0] == 0x47) {
674 else if (Data[0] == 0x00 && Data[1] == 0x00 && Data[2] == 0x01 && (Data[3] & 0xF0) == 0xE0) {
676 char *buf =
MALLOC(
char, Length);
681 while (i < Length - 6) {
682 if (Data[i] == 0x00 && Data[i + 1] == 0x00 && Data[i + 2] == 0x01) {
683 int len = Data[i + 4] * 256 + Data[i + 5];
684 if ((Data[i + 3] & 0xF0) == 0xE0) {
688 if ((Data[i + 6] & 0xC0) == 0x80) {
690 if (Data[i + 8] >= Length)
696 if (len < 0 || offs + len > Length)
701 while (offs < Length && len > 0 && Data[offs] == 0xFF) {
705 if (offs <= Length - 2 && len >= 2 && (Data[offs] & 0xC0) == 0x40) {
709 if (offs <= Length - 5 && len >= 5 && (Data[offs] & 0xF0) == 0x20) {
713 else if (offs <= Length - 10 && len >= 10 && (Data[offs] & 0xF0) == 0x30) {
717 else if (offs < Length && len > 0) {
722 if (blen + len > Length)
724 memcpy(&buf[blen], &Data[offs], len);
728 else if (Data[i + 3] >= 0xBD && Data[i + 3] <= 0xDF)
748 return Poller.
Poll(TimeoutMs);
760 TsBuffer[1] = PusiSet ? 0x40 : 0x00;
761 TsBuffer[1] |= Pid >> 8;
762 TsBuffer[2] = Pid & 0xFF;
765 TsBuffer[3] = 0x10 | Counter;
766 memcpy(TsBuffer + 4, Data, 184);
770 uint8_t adaptationLength;
772 TsBuffer[3] = 0x30 | Counter;
773 adaptationLength = 183 - Length;
774 TsBuffer[4] = adaptationLength;
775 if (adaptationLength > 0)
778 memset(TsBuffer + 6, 0xFF, adaptationLength - 1);
780 memcpy(TsBuffer + 5 + adaptationLength, Data, Length);
793 BuildTsPacket(TsBuffer + tsOffset, i == 0, Pid, Counter, Data + i * 184, Length);
798 Counter = (Counter + 1) & 15;
842 if (streamId >= 0xC0 && streamId <= 0xDF)
846 else if (streamId == 0xBD)
848 const uint8_t * payload = Data + 9 + Data[8];
849 if ((payload[0] & 0xF8) == 0xA0)
854 else if ((payload[0] & 0xF8) == 0x88)
859 else if ((payload[0] & 0xF8) == 0x80)
869 pid = 200 + (int) streamType;
891 int pid =
TsPid(Data);
919 int pid =
TsPid(Data);
922 int AudioStreamType = -1;
929 if (AudioStreamType < 0) {
957 static uint32_t SubsystemIds[] = {
965 uint32_t SubsystemId = 0;
966 FileName =
cString::sprintf(
"/sys/class/dvb/dvb%d.frontend%d/device/subsystem_vendor", Adapter, Frontend);
967 if ((f = fopen(FileName,
"r")) != NULL) {
968 if (
char *s = ReadLine.
Read(f))
969 SubsystemId = strtoul(s, NULL, 0) << 16;
972 FileName =
cString::sprintf(
"/sys/class/dvb/dvb%d.frontend%d/device/subsystem_device", Adapter, Frontend);
973 if ((f = fopen(FileName,
"r")) != NULL) {
974 if (
char *s = ReadLine.
Read(f))
975 SubsystemId |= strtoul(s, NULL, 0);
978 for (uint32_t *sid = SubsystemIds; *sid; sid++) {
979 if (*sid == SubsystemId) {
981 int fd = open(FileName, O_RDWR);
984 dsyslog(
"creating cDvbHdFfDevice");
998 #define JPEGCOMPRESSMEM 4000000
1018 int Used = jcd->
size;
1020 if (
uchar *NewBuffer = (
uchar *)realloc(jcd->
mem, NewSize)) {
1021 jcd->
size = NewSize;
1022 jcd->
mem = NewBuffer;
1025 esyslog(
"ERROR: out of memory");
1029 cinfo->dest->next_output_byte = jcd->
mem + Used;
1030 cinfo->dest->free_in_buffer = jcd->
size - Used;
1041 int Used = cinfo->dest->next_output_byte - jcd->
mem;
1042 if (Used < jcd->size) {
1045 jcd->
mem = NewBuffer;
1048 esyslog(
"ERROR: out of memory");
1057 else if (Quality > 100)
1060 jpeg_destination_mgr jdm;
1066 struct jpeg_compress_struct cinfo;
1067 struct jpeg_error_mgr jerr;
1068 cinfo.err = jpeg_std_error(&jerr);
1069 jpeg_create_compress(&cinfo);
1072 cinfo.client_data = &jcd;
1073 cinfo.image_width = Width;
1074 cinfo.image_height = Height;
1075 cinfo.input_components = 3;
1076 cinfo.in_color_space = JCS_YCbCr;
1078 jpeg_set_defaults(&cinfo);
1079 jpeg_set_quality(&cinfo, Quality,
true);
1080 jpeg_start_compress(&cinfo,
true);
1083 JSAMPROW rp[Height];
1084 for (
int k = 0; k < Height; k++)
1085 rp[k] = &Mem[rs * k];
1086 jpeg_write_scanlines(&cinfo, rp, Height);
1087 jpeg_finish_compress(&cinfo);
1088 jpeg_destroy_compress(&cinfo);
virtual void MakePrimaryDevice(bool On)
Informs a device that it will be the primary device.
virtual int PlayTsVideo(const uchar *Data, int Length)
Plays the given data block as video.
void CmdAvSetDecoderInput(uint8_t DecoderIndex, uint8_t DemultiplexerIndex)
void CmdMuxSetVolume(uint8_t Volume)
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...
virtual int64_t GetSTC(void)
Gets the current System Time Counter, which can be used to synchronize audio, video and subtitles...
virtual void StillPicture(const uchar *Data, int Length)
Displays the given I-frame as a still picture.
virtual bool IsTunedToTransponder(const cChannel *Channel) const
Returns true if this device is currently tuned to the given Channel's transponder.
static cDevice * ReceiverDevice(void)
void DetachAll(int Pid)
Detaches all receivers from this device for this pid.
virtual void SetDigitalAudioDevice(bool On)
Tells the actual device that digital audio output shall be switched on or off.
void CmdRemoteSetAddressFilter(bool Enable, uint32_t Address)
cTSBuffer * tsBuffer
< Controls how the DVB device handles Transfer Mode when replaying Dolby Digital audio.
int Ca(int Index=0) const
void StartDecrypting(void)
Triggers sending all currently active CA_PMT entries to the CAM, so that it will start decrypting...
virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect)
Returns the Width, Height and VideoAspect ratio of the currently displayed video material.
virtual void TrickSpeed(int Speed)
Sets the device into a mode where replay is done slower.
HdffVideoModeAdaption_t VideoModeAdaption
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 ...
static cString sprintf(const char *fmt,...) __attribute__((format(printf
virtual bool HasDecoder(void) const
Tells whether this device has an MPEG decoder.
void CmdAvSetPlayMode(uint8_t PlayMode, bool Realtime)
virtual void Freeze(void)
Puts the device into "freeze frame" mode.
bool Add(int FileHandle, bool Out)
virtual void MakePrimaryDevice(bool On)
Informs a device that it will be the primary device.
virtual int GetAudioChannelDevice(void)
Gets the current audio channel, which is stereo (0), mono left (1) or mono right (2).
virtual bool CanReplay(void) const
Returns true if this device can currently start a replay session.
static void JpegCompressTermDestination(j_compress_ptr cinfo)
virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
Sets the video display format to the given one (only useful if this device has an MPEG decoder)...
static cDevice * GetDevice(int Index)
Gets the device with the given Index.
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.
void CmdAvSetAudioPid(uint8_t DecoderIndex, uint16_t AudioPid, HdffAudioStreamType_t StreamType, HdffAvContainerType_t ContainerType=HDFF_AV_CONTAINER_PES)
virtual void Play(void)
Sets the device into play mode (after a previous trick mode).
virtual void Clear(void)
Clears all video and audio data from the device.
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 int PlayVideo(const uchar *Data, int Length)
Plays the given data block as video.
virtual void Clear(void)
Clears all video and audio data from the device.
void CmdAvShowStillImage(uint8_t DecoderIndex, const uint8_t *pStillImage, int Size, HdffVideoStreamType_t StreamType)
void CmdAvSetVideoFormat(uint8_t DecoderIndex, const HdffVideoFormat_t *pVideoFormat)
static HdffAudioStreamType_t MapAudioStreamTypes(int Atype)
static boolean JpegCompressEmptyOutputBuffer(j_compress_ptr cinfo)
virtual void Play(void)
Sets the device into play mode (after a previous trick mode).
bool Poll(int TimeoutMs=0)
virtual void Mute(void)
Turns off audio while replaying.
void CmdHdmiSetVideoMode(HdffVideoMode_t VideoMode)
void CmdAvSetVideoPid(uint8_t DecoderIndex, uint16_t VideoPid, HdffVideoStreamType_t StreamType, bool PlaybackMode=false)
void CmdAvEnableVideoAfterStop(uint8_t DecoderIndex, bool EnableVideoAfterStop)
int TsPid(const uchar *p)
void CmdAvSetAudioDelay(int16_t Delay)
bool IsPrimaryDevice(void) const
virtual void SetVideoDisplayFormat(eVideoDisplayFormat VideoDisplayFormat)
Sets the video display format to the given one (only useful if this device has an MPEG decoder)...
cCamSlot * CamSlot(void) const
Returns the CAM slot that is currently used with this device, or NULL if no CAM slot is in use...
bool Transferring(void) const
Returns true if we are currently in Transfer Mode.
virtual void Freeze(void)
Puts the device into "freeze frame" mode.
HdffVideoMode_t GetVideoMode(void)
uint32_t PesToTs(uint8_t *TsBuffer, uint16_t Pid, uint8_t &Counter, const uint8_t *Data, uint32_t Length)
static int CurrentChannel(void)
Returns the number of the current channel on the primary device.
cDvbHdFfDevice(int Adapter, int Frontend)
virtual eVideoSystem GetVideoSystem(void)
Returns the video system of the currently displayed material (default is PAL).
static void JpegCompressInitDestination(j_compress_ptr cinfo)
void CmdHdmiConfigure(const HdffHdmiConfig_t *pConfig)
HDFF::cHdffCmdIf * mHdffCmdIf
virtual bool SetChannelDevice(const cChannel *Channel, bool LiveView)
Sets the device to the given channel (actual physical setup).
void BuildTsPacket(uint8_t *TsBuffer, bool PusiSet, uint16_t Pid, uint8_t Counter, const uint8_t *Data, uint32_t Length)
void CmdAvSetSyncShift(int16_t SyncShift)
virtual ~cDvbHdFfDevice()
virtual bool SetPlayMode(ePlayMode PlayMode)
Sets the device into the given play mode.
#define IS_AUDIO_TRACK(t)
virtual int PlayTsAudio(const uchar *Data, int Length)
Plays the given data block as audio.
bool CamDecrypt(tChannelID ChannelID, int CamSlotNumber)
tChannelID GetChannelID(void) const
virtual int PlayAudio(const uchar *Data, int Length, uchar Id)
Plays the given data block as audio.
virtual void GetVideoSize(int &Width, int &Height, double &VideoAspect)
Returns the Width, Height and VideoAspect ratio of the currently displayed video material.
static void Launch(cControl *Control)
const cPatPmtParser * PatPmtParser(void) const
Returns a pointer to the patPmtParser, so that a derived device can use the stream information from i...
void GetOsdSize(int &Width, int &Height, double &PixelAspect)
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)...
int CardIndex(void) const
Returns the card index of this device (0 ... MAXDEVICES - 1).
void CmdAvSetAudioChannel(uint8_t AudioChannel)
virtual bool Flush(int TimeoutMs=0)
Returns true if the device's output buffers are empty, i.
void SetPid(int Pid, bool Active)
Sets the given Pid (which has previously been added through a call to AddPid()) to Active...
void CmdRemoteSetProtocol(HdffRemoteProtocol_t Protocol)
cDvbSpuDecoder * spuDecoder
void CmdAvSetVideoWindow(uint8_t DecoderIndex, bool Enable, uint16_t X, uint16_t Y, uint16_t Width, uint16_t Height)
virtual void SetAudioChannelDevice(int AudioChannel)
Sets the audio channel to stereo (0), mono left (1) or mono right (2).
void CmdMuxSetVideoOut(HdffVideoOut_t VideoOut)
void CmdAvSetVideoSpeed(uint8_t DecoderIndex, int32_t Speed)
cChannel * GetByNumber(int Number, int SkipGap=0)
The cDvbHdFfDevice implements a DVB device which can be accessed through the Linux DVB driver API...
const tTrackId * GetTrack(eTrackType Type)
Returns a pointer to the given track id, or NULL if Type is not less than ttMaxTrackTypes.
cChannelCamRelations ChannelCamRelations
void CmdAvSetStc(uint8_t DecoderIndex, uint64_t Stc)
virtual uchar * GrabImage(int &Size, bool Jpeg=true, int Quality=-1, int SizeX=-1, int SizeY=-1)
Grabs the currently visible screen image.
The cDvbDevice implements a DVB device which can be accessed through the Linux DVB driver API...
void TurnOffLiveMode(bool LiveView)
virtual void SetAudioTrackDevice(eTrackType Type)
Sets the current audio track to the given value.
virtual bool Probe(int Adapter, int Frontend)
Probes for a DVB device at the given Adapter and creates the appropriate object derived from cDvbDevi...
virtual bool CanReplay(void) const
Returns true if this device can currently start a replay session.
static HDFF::cHdffCmdIf * GetHdffCmdHandler(void)
void CmdAvSetAudioDownmix(HdffAudioDownmixMode_t DownmixMode)
bool HasPid(int Pid) const
Returns true if this device is currently receiving the given PID.
static HdffVideoStreamType_t MapVideoStreamTypes(int Vtype)
virtual void SetVolumeDevice(int Volume)
Sets the audio volume on this device (Volume = 0...255).
#define IS_DOLBY_TRACK(t)
static uchar * YuvToJpeg(uchar *Mem, int Width, int Height, int &Size, int Quality)
void CmdAvSetPcrPid(uint8_t DecoderIndex, uint16_t PcrPid)
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 void StillPicture(const uchar *Data, int Length)
Displays the given I-frame as a still picture.
void CmdAvSetAudioSpeed(uint8_t DecoderIndex, int32_t Speed)
virtual bool SetPid(cPidHandle *Handle, int Type, bool On)
Does the actual PID setting on this device.
cPidHandle pidHandles[MAXPIDHANDLES]
void CmdAvMuteAudio(uint8_t DecoderIndex, bool Mute)
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.
static int DvbOpen(const char *Name, int Adapter, int Frontend, int Mode, bool ReportError=false)
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...
void CmdAvEnableSync(uint8_t DecoderIndex, bool EnableSync)
static cDevice * device[MAXDEVICES]
virtual void Mute(void)
Turns off audio while replaying.