bool cDvbHdFfDevice::SetPlayMode(ePlayMode PlayMode) { if (PlayMode == pmNone) { if (fd_video == -1) fd_video = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDWR | O_NONBLOCK); if (fd_audio == -1) fd_audio = DvbOpen(DEV_DVB_AUDIO, adapter, frontend, O_RDWR | O_NONBLOCK); mHdffCmdIf->CmdAvSetVideoSpeed(0, 100); mHdffCmdIf->CmdAvSetAudioSpeed(0, 100); mHdffCmdIf->CmdAvEnableVideoAfterStop(0, false); mHdffCmdIf->CmdAvSetPcrPid(0, 0); mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF_VIDEO_STREAM_MPEG1); mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_MPEG1); ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX); mHdffCmdIf->CmdAvSetDecoderInput(0, 0); mHdffCmdIf->CmdAvEnableSync(0, true); mHdffCmdIf->CmdAvSetPlayMode(0, true); mHdffCmdIf->CmdAvMuteAudio(0, false); } else { if (playMode == pmNone) TurnOffLiveMode(true); if (PlayMode == pmExtern_THIS_SHOULD_BE_AVOIDED) { close(fd_video); fd_video = -1; close(fd_audio); fd_audio = -1; } else { isTransferMode = Transferring() || (cTransferControl::ReceiverDevice() == this); mHdffCmdIf->CmdAvSetPlayMode(1, isTransferMode); mHdffCmdIf->CmdAvSetStc(0, 100000); mHdffCmdIf->CmdAvEnableSync(0, false); mHdffCmdIf->CmdAvEnableVideoAfterStop(0, true); playVideoPid = -1; playAudioPid = -1; playPcrPid = -1; audioCounter = 0; videoCounter = 0; freezed = false; trickMode = false; isPlayingVideo = false; mHdffCmdIf->CmdAvSetDecoderInput(0, 2); ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY); } } playMode = PlayMode; return true; }
bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On) { if (Handle->pid) { dmx_pes_filter_params pesFilterParams; memset(&pesFilterParams, 0, sizeof(pesFilterParams)); if (On) { if (Handle->handle < 0) { Handle->handle = DvbOpen(DEV_DVB_DEMUX, CardIndex(), O_RDWR | O_NONBLOCK, true); if (Handle->handle < 0) { LOG_ERROR; return false; } } pesFilterParams.pid = Handle->pid; pesFilterParams.input = DMX_IN_FRONTEND; pesFilterParams.output = (Type <= ptTeletext && Handle->used <= 1) ? DMX_OUT_DECODER : DMX_OUT_TS_TAP; pesFilterParams.pes_type= PesTypes[Type < ptOther ? Type : ptOther]; pesFilterParams.flags = DMX_IMMEDIATE_START; if (ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) { LOG_ERROR; return false; } } else if (!Handle->used) { CHECK(ioctl(Handle->handle, DMX_STOP)); if (Type <= ptTeletext) { pesFilterParams.pid = 0x1FFF; pesFilterParams.input = DMX_IN_FRONTEND; pesFilterParams.output = DMX_OUT_DECODER; pesFilterParams.pes_type= PesTypes[Type]; pesFilterParams.flags = DMX_IMMEDIATE_START; CHECK(ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams)); if (PesTypes[Type] == DMX_PES_VIDEO) // let's only do this once SetPlayMode(pmNone); // necessary to switch a PID from DMX_PES_VIDEO/AUDIO to DMX_PES_OTHER } close(Handle->handle); Handle->handle = -1; } } return true; }
bool cDvbDevice::SetPlayMode(ePlayMode PlayMode) { if (PlayMode != pmExtern_THIS_SHOULD_BE_AVOIDED && fd_video < 0 && fd_audio < 0) { // reopen the devices fd_video = DvbOpen(DEV_DVB_VIDEO, CardIndex(), O_RDWR | O_NONBLOCK); fd_audio = DvbOpen(DEV_DVB_AUDIO, CardIndex(), O_RDWR | O_NONBLOCK); SetVideoFormat(Setup.VideoFormat); } switch (PlayMode) { case pmNone: // special handling to return from PCM replay: CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY)); CHECK(ioctl(fd_video, VIDEO_PLAY)); CHECK(ioctl(fd_video, VIDEO_STOP, true)); CHECK(ioctl(fd_audio, AUDIO_STOP, true)); CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER)); CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER)); CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX)); CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX)); CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true)); CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false)); break; case pmAudioVideo: case pmAudioOnlyBlack: if (playMode == pmNone) TurnOffLiveMode(true); CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY)); CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, PlayMode == pmAudioVideo)); CHECK(ioctl(fd_audio, AUDIO_PLAY)); CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY)); CHECK(ioctl(fd_video, VIDEO_PLAY)); break; case pmAudioOnly: CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); CHECK(ioctl(fd_audio, AUDIO_STOP, true)); CHECK(ioctl(fd_audio, AUDIO_CLEAR_BUFFER)); CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_MEMORY)); CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false)); CHECK(ioctl(fd_audio, AUDIO_PLAY)); CHECK(ioctl(fd_video, VIDEO_SET_BLANK, false)); break; case pmVideoOnly: CHECK(ioctl(fd_video, VIDEO_SET_BLANK, true)); CHECK(ioctl(fd_video, VIDEO_STOP, true)); CHECK(ioctl(fd_audio, AUDIO_SELECT_SOURCE, AUDIO_SOURCE_DEMUX)); CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, false)); CHECK(ioctl(fd_audio, AUDIO_PLAY)); CHECK(ioctl(fd_video, VIDEO_CLEAR_BUFFER)); CHECK(ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_MEMORY)); CHECK(ioctl(fd_video, VIDEO_PLAY)); break; case pmExtern_THIS_SHOULD_BE_AVOIDED: close(fd_video); close(fd_audio); fd_video = fd_audio = -1; break; } playMode = PlayMode; return true; }
cDvbDevice::cDvbDevice(int n) { dvbTuner = NULL; frontendType = fe_type_t(-1); // don't know how else to initialize this - there is no FE_UNKNOWN spuDecoder = NULL; digitalAudio = false; playMode = pmNone; // Devices that are present on all card types: int fd_frontend = DvbOpen(DEV_DVB_FRONTEND, n, O_RDWR | O_NONBLOCK); // Devices that are only present on cards with decoders: fd_osd = DvbOpen(DEV_DVB_OSD, n, O_RDWR); fd_video = DvbOpen(DEV_DVB_VIDEO, n, O_RDWR | O_NONBLOCK); fd_audio = DvbOpen(DEV_DVB_AUDIO, n, O_RDWR | O_NONBLOCK); fd_stc = DvbOpen(DEV_DVB_DEMUX, n, O_RDWR); // The DVR device (will be opened and closed as needed): fd_dvr = -1; // The offset of the /dev/video devices: if (devVideoOffset < 0) { // the first one checks this FILE *f = NULL; char buffer[PATH_MAX]; for (int ofs = 0; ofs < 100; ofs++) { snprintf(buffer, sizeof(buffer), "/proc/video/dev/video%d", ofs); if ((f = fopen(buffer, "r")) != NULL) { if (fgets(buffer, sizeof(buffer), f)) { if (strstr(buffer, "DVB Board")) { // found the _first_ DVB card devVideoOffset = ofs; dsyslog("video device offset is %d", devVideoOffset); break; } } else break; fclose(f); } else break; } if (devVideoOffset < 0) devVideoOffset = 0; if (f) fclose(f); } devVideoIndex = (devVideoOffset >= 0 && HasDecoder()) ? devVideoOffset++ : -1; // Video format: SetVideoFormat(Setup.VideoFormat); // We only check the devices that must be present - the others will be checked before accessing them://XXX if (fd_frontend >= 0) { dvb_frontend_info feinfo; if (ioctl(fd_frontend, FE_GET_INFO, &feinfo) >= 0) { frontendType = feinfo.type; ciHandler = cCiHandler::CreateCiHandler(*cDvbName(DEV_DVB_CA, n)); dvbTuner = new cDvbTuner(fd_frontend, CardIndex(), frontendType, ciHandler); } else LOG_ERROR; } else esyslog("ERROR: can't open DVB device %d", n); StartSectionHandler(); }
cDvbHdFfDevice::cDvbHdFfDevice(int Adapter, int Frontend) :cDvbDevice(Adapter, Frontend) { spuDecoder = NULL; audioChannel = 0; playMode = pmNone; mHdffCmdIf = NULL; // Devices that are only present on cards with decoders: fd_osd = DvbOpen(DEV_DVB_OSD, adapter, frontend, O_RDWR); fd_video = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDWR | O_NONBLOCK); fd_audio = DvbOpen(DEV_DVB_AUDIO, adapter, frontend, O_RDWR | O_NONBLOCK); //TODO missing /dev/video offset calculation isHdffPrimary = false; if (devHdffOffset < 0) { devHdffOffset = adapter; isHdffPrimary = true; mHdffCmdIf = new HDFF::cHdffCmdIf(fd_osd); uint32_t firmwareVersion = mHdffCmdIf->CmdGetFirmwareVersion(NULL, 0); if (firmwareVersion < 0x401) supportsPcrInTransferMode = false; else supportsPcrInTransferMode = true; /* reset some stuff in case the VDR was killed before and had no chance to clean up. */ mHdffCmdIf->CmdOsdReset(); mHdffCmdIf->CmdAvSetVideoSpeed(0, 100); mHdffCmdIf->CmdAvSetAudioSpeed(0, 100); mHdffCmdIf->CmdAvEnableVideoAfterStop(0, false); mHdffCmdIf->CmdAvSetPcrPid(0, 0); mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF_VIDEO_STREAM_MPEG1); mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_MPEG1); ioctl(fd_video, VIDEO_SELECT_SOURCE, VIDEO_SOURCE_DEMUX); mHdffCmdIf->CmdAvSetDecoderInput(0, 0); mHdffCmdIf->CmdAvEnableSync(0, true); mHdffCmdIf->CmdAvSetPlayMode(0, true); /* reset done */ mHdffCmdIf->CmdAvSetAudioDelay(gHdffSetup.AudioDelay); mHdffCmdIf->CmdAvSetAudioDownmix((HdffAudioDownmixMode_t) gHdffSetup.AudioDownmix); mHdffCmdIf->CmdAvSetSyncShift(gHdffSetup.AvSyncShift); mHdffCmdIf->CmdMuxSetVideoOut((HdffVideoOut_t) gHdffSetup.AnalogueVideo); mHdffCmdIf->CmdHdmiSetVideoMode(gHdffSetup.GetVideoMode()); HdffHdmiConfig_t hdmiConfig; memset(&hdmiConfig, 0, sizeof(hdmiConfig)); hdmiConfig.TransmitAudio = true; hdmiConfig.ForceDviMode = false; hdmiConfig.CecEnabled = gHdffSetup.CecEnabled; strcpy(hdmiConfig.CecDeviceName, "VDR"); hdmiConfig.VideoModeAdaption = (HdffVideoModeAdaption_t) gHdffSetup.VideoModeAdaption; mHdffCmdIf->CmdHdmiConfigure(&hdmiConfig); mHdffCmdIf->CmdRemoteSetProtocol((HdffRemoteProtocol_t) gHdffSetup.RemoteProtocol); mHdffCmdIf->CmdRemoteSetAddressFilter(gHdffSetup.RemoteAddress >= 0, gHdffSetup.RemoteAddress); } }
bool cDvbHdFfDevice::SetPid(cPidHandle *Handle, int Type, bool On) { //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); if (Handle->pid) { dmx_pes_filter_params pesFilterParams; memset(&pesFilterParams, 0, sizeof(pesFilterParams)); if (On) { if (Handle->handle < 0) { Handle->handle = DvbOpen(DEV_DVB_DEMUX, adapter, frontend, O_RDWR | O_NONBLOCK, true); if (Handle->handle < 0) { LOG_ERROR; return false; } } if (Type == ptPcr) mHdffCmdIf->CmdAvSetPcrPid(0, Handle->pid); else if (Type == ptVideo) { if (Handle->streamType == 0x1B) mHdffCmdIf->CmdAvSetVideoPid(0, Handle->pid, HDFF_VIDEO_STREAM_H264); else mHdffCmdIf->CmdAvSetVideoPid(0, Handle->pid, HDFF_VIDEO_STREAM_MPEG2); } else if (Type == ptAudio) { if (Handle->streamType == 0x03) mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_MPEG1); else if (Handle->streamType == 0x04) mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_MPEG2); else if (Handle->streamType == SI::AC3DescriptorTag) mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_AC3); else if (Handle->streamType == SI::EnhancedAC3DescriptorTag) mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_EAC3); else if (Handle->streamType == 0x0F) mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_AAC); else if (Handle->streamType == 0x11) mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_HE_AAC); else mHdffCmdIf->CmdAvSetAudioPid(0, Handle->pid, HDFF_AUDIO_STREAM_MPEG1); } if (!(Type <= ptDolby && Handle->used <= 1)) { pesFilterParams.pid = Handle->pid; pesFilterParams.input = DMX_IN_FRONTEND; pesFilterParams.output = DMX_OUT_TS_TAP; pesFilterParams.pes_type= DMX_PES_OTHER; pesFilterParams.flags = DMX_IMMEDIATE_START; if (ioctl(Handle->handle, DMX_SET_PES_FILTER, &pesFilterParams) < 0) { LOG_ERROR; return false; } } } else if (!Handle->used) { CHECK(ioctl(Handle->handle, DMX_STOP)); if (Type == ptPcr) mHdffCmdIf->CmdAvSetPcrPid(0, 0); else if (Type == ptVideo) mHdffCmdIf->CmdAvSetVideoPid(0, 0, HDFF_VIDEO_STREAM_MPEG1); else if (Type == ptAudio) mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_MPEG1); else if (Type == ptDolby) mHdffCmdIf->CmdAvSetAudioPid(0, 0, HDFF_AUDIO_STREAM_AC3); //TODO missing setting to 0x1FFF??? see cDvbDevice::SetPid() close(Handle->handle); Handle->handle = -1; } } return true; }
uchar *cDvbHdFfDevice::GrabImage(int &Size, bool Jpeg, int Quality, int SizeX, int SizeY) { #define BUFFER_SIZE (sizeof(struct v4l2_pix_format) + 1920 * 1080 * 2) int fd; uint8_t * buffer; uint8_t * result = NULL; fd = DvbOpen(DEV_DVB_VIDEO, adapter, frontend, O_RDONLY); if (fd < 0) { esyslog("GrabImage: failed open DVB video device"); return NULL; } buffer = (uint8_t *) malloc(BUFFER_SIZE); if (buffer) { int readBytes; readBytes = read(fd, buffer, BUFFER_SIZE); if (readBytes < (int) sizeof(struct v4l2_pix_format)) esyslog("GrabImage: failed reading from DVB video device"); else { struct v4l2_pix_format * pixfmt; int dataSize; pixfmt = (struct v4l2_pix_format *) buffer; dsyslog("GrabImage: Read image of size %d x %d", pixfmt->width, pixfmt->height); dataSize = readBytes - sizeof(struct v4l2_pix_format); if (dataSize < (int) pixfmt->sizeimage) esyslog("GrabImage: image is not complete"); else { if (Jpeg) { uint8_t * temp; temp = (uint8_t *) malloc(pixfmt->width * 3 * pixfmt->height); if (temp) { int numPixels = pixfmt->width * pixfmt->height; uint8_t * destData = temp; uint8_t * srcData = buffer + sizeof(struct v4l2_pix_format); while (numPixels > 0) { destData[0] = srcData[1]; destData[1] = srcData[0]; destData[2] = srcData[2]; destData[3] = srcData[3]; destData[4] = srcData[0]; destData[5] = srcData[2]; srcData += 4; destData += 6; numPixels -= 2; } if (Quality < 0) Quality = 100; result = YuvToJpeg(temp, pixfmt->width, pixfmt->height, Size, Quality); free(temp); } } else { // convert to PNM: char buf[32]; snprintf(buf, sizeof(buf), "P6\n%d\n%d\n255\n", pixfmt->width, pixfmt->height); int l = strlen(buf); Size = l + pixfmt->width * 3 * pixfmt->height; result = (uint8_t *) malloc(Size); if (result) { memcpy(result, buf, l); uint8_t * destData = result + l; uint8_t * srcData = buffer + sizeof(struct v4l2_pix_format); int numPixels = pixfmt->width * pixfmt->height; while (numPixels > 0) { int cb = srcData[0] - 128; int y1 = srcData[1]; int cr = srcData[2] - 128; int y2 = srcData[3]; int r; int g; int b; r = y1 + (int) (1.402f * cr); g = y1 - (int) (0.344f * cb + 0.714f * cr); b = y1 + (int) (1.772f * cb); destData[0] = r > 255 ? 255 : r < 0 ? 0 : r; destData[1] = g > 255 ? 255 : g < 0 ? 0 : g; destData[2] = b > 255 ? 255 : b < 0 ? 0 : b; r = y2 + (int) (1.402f * cr); g = y2 - (int) (0.344f * cb + 0.714f * cr); b = y2 + (int) (1.772f * cb); destData[3] = r > 255 ? 255 : r < 0 ? 0 : r; destData[4] = g > 255 ? 255 : g < 0 ? 0 : g; destData[5] = b > 255 ? 255 : b < 0 ? 0 : b; srcData += 4; destData += 6; numPixels -= 2; } } } } } free(buffer); } close(fd); return result; }