/// <summary> /// Sends the PMT to the CI module /// </summary> /// <param name="subChannel">The sub channel.</param> /// <param name="channel">channel on which we are tuned</param> /// <param name="PMT">byte array containing the PMT</param> /// <param name="pmtLength">length of the pmt array</param> /// <param name="audioPid">pid of the current audio stream</param> /// <returns></returns> public bool SendPMT(int subChannel, DVBBaseChannel channel, byte[] PMT, int pmtLength, int audioPid) { try { if (!_useCam) return true; if (channel.FreeToAir) return true; //no need to descramble this one... AddSubChannel(subChannel, channel); ConditionalAccessContext context = _mapSubChannels[subChannel]; context.CamType = _CamType; context.Channel = channel; if (_CamType == CamType.Astoncrypt2) { int newLength; context.PMT = PatchPMT_AstonCrypt2(PMT, pmtLength, out newLength); context.PMTLength = newLength; } else { context.PMT = PMT; context.PMTLength = pmtLength; } context.AudioPid = audioPid; context.ServiceId = channel.ServiceId; if (_winTvCiModule != null) { int hr = _winTvCiModule.SendPMT(PMT, pmtLength); if (hr != 0) { Log.Log.Info("Conditional Access: sendPMT to WinTVCI failed"); return false; } Log.Log.Info("Conditional Access: sendPMT to WinTVCI succeeded"); return true; } if (_knc != null) { ChannelInfo info = new ChannelInfo(); info.DecodePmt(PMT); int caPmtLen; byte[] caPmt = info.caPMT.CaPmtStruct(out caPmtLen); return _knc.SendPMT(caPmt, caPmtLen); } if (_DigitalDevices != null) { return _DigitalDevices.SendServiceIdToCam(channel.ServiceId); } if (_digitalEveryWhere != null) { return _digitalEveryWhere.SendPMTToFireDTV(_mapSubChannels); } if (_technoTrend != null) { return _technoTrend.DescrambleMultiple(_mapSubChannels); // return _technoTrend.SendPMT(PMT, pmtLength); } if (_twinhan != null) { ChannelInfo info = new ChannelInfo(); info.DecodePmt(PMT); int caPmtLen; byte[] caPmt = info.caPMT.CaPmtStruct(out caPmtLen); return _twinhan.SendPMT(caPmt, caPmtLen); } } catch (Exception ex) { Log.Log.Write(ex); } return true; }
private bool HandlePmt() { IntPtr pmtMem = Marshal.AllocCoTaskMem(4096); // max. size for pmt try { _pmtLength = _tsFilterInterface.PmtGetPMTData(_subChannelIndex, pmtMem); if (_pmtLength < 6) { return false; } // Check the program number. _pmtData = new byte[_pmtLength]; Marshal.Copy(pmtMem, _pmtData, 0, _pmtLength); int version = ((_pmtData[5] >> 1) & 0x1F); int pmtProgramNumber = (_pmtData[3] << 8) + _pmtData[4]; Log.Log.Info("HDPVR: PMT sid=0x{0:X} pid=0x{1:X} version=0x{2:X}", pmtProgramNumber, _pmtPid, version); if (pmtProgramNumber != SERVICE_ID) { throw new TvException("HDPVRChannel: PMT program number doesn't match expected service ID"); } // Get the program PIDs. _pmtVersion = version; _channelInfo = new ChannelInfo(); _channelInfo.DecodePmt(_pmtData); _channelInfo.serviceID = pmtProgramNumber; _channelInfo.network_pmt_PID = _pmtPid; SetMpegPidMapping(_channelInfo); return true; } finally { Marshal.FreeCoTaskMem(pmtMem); } }
/// <summary> /// Decodes the PMT and sends the PMT to cam. /// </summary> protected virtual bool SendPmtToCam(out bool updatePids, out int waitInterval) { ThrowExceptionIfTuneCancelled(); lock (this) { DVBBaseChannel channel = _currentChannel as DVBBaseChannel; updatePids = false; waitInterval = 100; bool foundCA = false; if (_mdplugs != null) { if (channel != null) { //HACK: Currently Premiere Direkt Feeds (nid=133) have the free_ca flag in SDT set to true (means not scrambled), so we have to override this if ((!channel.FreeToAir) || (channel.NetworkId == 133 && !channel.Provider.Equals("BetaDigital"))) { DateTime dtNow = DateTime.Now; foundCA = false; //Log.Log.Info("subch:{0} listen for CA", _listenCA); if (!_eventCA.WaitOne(10000, true)) //wait 10 sec for CA to arrive. { TimeSpan ts = DateTime.Now - dtNow; Log.Log.Info("subch:{0} SendPmt:no CA found after {1} seconds", _subChannelId, ts.TotalSeconds); return false; } else { ThrowExceptionIfTuneCancelled(); foundCA = true; TimeSpan ts = DateTime.Now - dtNow; Log.Log.Info("subch:{0} SendPmt:CA found after {1} seconds", _subChannelId, ts.TotalSeconds); } } } } if (channel == null) { Log.Log.Info("subch:{0} SendPmt:no channel set", _subChannelId); return true; } IntPtr pmtMem = Marshal.AllocCoTaskMem(4096); // max. size for pmt IntPtr catMem = Marshal.AllocCoTaskMem(4096); // max. size for cat try { _pmtLength = _tsFilterInterface.PmtGetPMTData(_subChannelIndex, pmtMem); if (_pmtLength > 6) { _pmtData = new byte[_pmtLength]; Marshal.Copy(pmtMem, _pmtData, 0, _pmtLength); int version = ((_pmtData[5] >> 1) & 0x1F); int pmtProgramNumber = (_pmtData[3] << 8) + _pmtData[4]; Log.Log.Info("subch:{0} SendPmt:{1:X} {2:X} {3:X} {4:X}", _subChannelId, pmtProgramNumber, channel.ServiceId, _pmtVersion, version); if (pmtProgramNumber == channel.ServiceId) { if (_pmtVersion == version) //already received this pmt return true; _pmtVersion = version; _channelInfo = new ChannelInfo(); _channelInfo.DecodePmt(_pmtData); _channelInfo.network_pmt_PID = channel.PmtPid; _channelInfo.serviceID = channel.ServiceId; // update any service scrambled / unscambled changes if (_channelInfo.scrambled == channel.FreeToAir) { channel.FreeToAir = !_channelInfo.scrambled; Log.Log.Info("subch:{0} SendPMT: Channel FTA information changed to {1} according to CAIDs in PMT.", _subChannelId, channel.FreeToAir); } if ((_mdplugs != null) && (foundCA)) { try { int catLength = _tsFilterInterface.CaGetCaData(_subChannelIndex, catMem); if (catLength > 0) { byte[] cat = new byte[catLength]; Marshal.Copy(catMem, cat, 0, catLength); _channelInfo.DecodeCat(cat, catLength); } } catch (Exception ex) { Log.Log.Write(ex); } } updatePids = true; if (_conditionalAccess == null) { Log.Log.Info("subch:{0} SendPMT: No cam in use, nothing to do.", _subChannelId); return true; } if (channel.FreeToAir) { Log.Log.Info("subch:{0} SendPMT: Channel is FTA, nothing to do.", _subChannelId); return true; } Log.Log.WriteFile("subch:{0} SendPMT version:{1} len:{2} {3}", _subChannelId, version, _pmtLength, _channelInfo.caPMT.ProgramNumber); int audioPid = -1; if (_currentAudioStream != null) { audioPid = _currentAudioStream.Pid; } if (_conditionalAccess.SendPMT(_subChannelId, channel, _pmtData, _pmtLength, audioPid)) { Log.Log.WriteFile("subch:{0} cam flags:{1}", _subChannelId, _conditionalAccess.IsCamReady()); return true; } else { //cam is not ready yet Log.Log.WriteFile("subch:{0} SendPmt failed cam flags:{1}", _subChannelId, _conditionalAccess.IsCamReady()); _pmtVersion = -1; waitInterval = 3000; return false; } } } } catch (Exception ex) { Log.Log.Write(ex); } finally { Marshal.FreeCoTaskMem(pmtMem); Marshal.FreeCoTaskMem(catMem); } } return false; }