Guest Diefenthal Posted October 20, 2016 Share Posted October 20, 2016 no order! had one Hauppage USB DVB T 70019 buyed and tested Link to comment Share on other sites More sharing options...
Nikolaech 32 Posted October 20, 2016 Share Posted October 20, 2016 no order! OK Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted October 27, 2016 Share Posted October 27, 2016 (edited) sadly is my sparetime much more limited as i wish so will i now share some code for anyone that will Play with it _udpclient = new UdpClient(_device.RtspSession.RtpPort); _remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); /* Say the Sat>IP server we want Receives the ServiceDescriptionTable */ _device.RtspSession.Play("&addpids=17"); List<ServiceDescription> sdt ; GetSDT(_udpclient, _remoteEndPoint,out sdt ); /* Say the Sat>IP server we want not more Receives the ServiceDescriptionTable */ _device.RtspSession.Play(string.Format("&delpids=17")); public class ServiceDescription { public ushort ServiceID; public byte Reserved; public bool EitScheduleFlag; public bool EitPresentFollowingFlag; public RunningStatus RunningStatus; public bool FreeCaMode; public ushort DescriptorsLoopLength; public string ProviderName; public string ServiceName; } private bool GetSDT(UdpClient client, IPEndPoint endpoint,out List<ServiceDescription> services) { services = new List<ServiceDescription>(); bool retval = false; while (!retval) { var receivedbytes = client.Receive(ref endpoint); RtpHeader h = new RtpHeader(receivedbytes); if ((receivedbytes.Length > 12) && ((receivedbytes.Length - 12) % 188) == 0) { double num9 = (((double)(receivedbytes.Length - 12)) / 188.0) - 1.0; for (double j = 0.0; j <= num9; j++) { byte[] destinationarray = (byte[])Array.CreateInstance(typeof(byte), 188); Array.Copy(receivedbytes, (int)Math.Round((double)(12.0 + (j * 188))), destinationarray, 0, 188); SDTParser parser = new SDTParser(); parser.OnTsPacket(destinationarray); int[] vals= parser.Services; foreach(var val in vals) { var s =parser.GetService(val); services.Add(s); } retval = parser.IsReady; } } } return retval; } public class SDTParser { private TsSectionDecoder dec1; private TsSectionDecoder dec2; public bool IsReady; private Dictionary<int, ServiceDescription> _services = new Dictionary<int, ServiceDescription>(); private ServiceDescription servicedescription = null; public SDTParser() { IsReady = false; this.dec1 = new TsSectionDecoder(0x11, 0x42); this.dec1.OnSectionDecoded += new TsSectionDecoder.MethodOnSectionDecoded(this.OnNewSection); this.dec2 = new TsSectionDecoder(0x11, 0x46); this.dec2.OnSectionDecoded += new TsSectionDecoder.MethodOnSectionDecoded(this.OnNewSection); } public int[] Services { get { int[] retServices = new int[ServiceCount]; int i = 0; foreach (int key in _services.Keys) { retServices[i] = key; i++; } return retServices; } } public int ServiceCount { get { return _services.Keys.Count; } } public ServiceDescription GetService(int service_id) { return _services[service_id]; } public void OnNewSection(TsSection section) { int num = section.table_id_extension; int OriginalNetworkID = (section.Data[8] << 8) + section.Data[9]; int offset = 11; while (offset < section.section_length - 4) { servicedescription = new ServiceDescription(); servicedescription.ServiceID = (ushort)((section.Data[offset] << 8) + section.Data[offset + 1]); servicedescription.EitScheduleFlag = ((section.Data[offset + 2] & 0x02) != 0); servicedescription.EitPresentFollowingFlag = ((section.Data[offset + 2] & 0x01) != 0); servicedescription.RunningStatus = (RunningStatus)((section.Data[offset + 3] >> 5) & 0x07); servicedescription.FreeCaMode = (((section.Data[offset + 3] >> 4) & 0x01) != 0); servicedescription.DescriptorsLoopLength = (ushort)(((section.Data[offset + 3] << 8) | section.Data[offset + 4]) & 0xfff); offset += 5; int descOffset = offset; offset += servicedescription.DescriptorsLoopLength; while (descOffset < offset) { var descriptor_tag = section.Data[descOffset]; var descriptor_length = section.Data[descOffset]; switch (descriptor_tag) { case 0x42: break; case 0x48: ReadServiceDescriptor(section.Data, descOffset+2); break; case 0x49: break; case 0x4A: break; case 0x4B: break; case 0x4C: break; case 0x50: break; case 0x51: break; case 0x53: break; case 0x57: break; case 0x5D: break; case 0x5F: break; case 0x64: break; case 0x6E: break; case 0x71: break; case 0x72: break; case 0x73: break; case 0x7D: break; case 0x7E: break; case 0x7F: break; default: break; } descOffset += descriptor_length + 2; } if (!_services.ContainsKey(servicedescription.ServiceID)) { _services.Add(servicedescription.ServiceID,servicedescription); } } IsReady = true; } public void OnTsPacket(byte[] tsPacket) { this.dec1.OnTsPacket(tsPacket); this.dec2.OnTsPacket(tsPacket); } public void ReadServiceDescriptor(byte[] data, int offset) { byte ProviderNameLength = data[offset + 1]; servicedescription.ProviderName = ReadString(data, offset + 2, (int)ProviderNameLength); byte ServiceNameLength = data[offset + 2 + ProviderNameLength]; servicedescription.ServiceName = ReadString(data, offset + 3 + ProviderNameLength, ServiceNameLength); } protected string ReadString(byte[] data, int offset, int length) { string encoding = "utf-8"; // Standard latin alphabet List<byte> bytes = new List<byte>(); for (int i = 0; i < length; i++) { byte character = data[ offset + i]; bool notACharacter = false; if (i == 0) { // Look for a character table definition if (character < 0x20) { switch (character) { case 0x00: break; case 0x01: encoding = "iso-8859-5"; break; case 0x02: encoding = "iso-8859-6"; break; case 0x03: encoding = "iso-8859-7"; break; case 0x04: encoding = "iso-8859-8"; break; case 0x05: encoding = "iso-8859-9"; break; default: break; } notACharacter = true; } } if (character < 0x20 || (character >= 0x80 && character <= 0x9F)) { notACharacter = true; } if (!notACharacter) { bytes.Add(character); } } Encoding enc = Encoding.GetEncoding(encoding); ASCIIEncoding destEnc = new ASCIIEncoding(); byte[] destBytes = Encoding.Convert(enc, destEnc, bytes.ToArray()); return destEnc.GetString(destBytes); } } public class TsSectionDecoder { public static uint incompleteSections; private ushort _pid; private TsSection _section; private int _tableId; public event MethodOnSectionDecoded OnSectionDecoded; public TsSectionDecoder() { _pid = 8191; _tableId = -1; _section = new TsSection(); } public TsSectionDecoder(ushort pid, int table_id) { _pid = pid; _tableId = table_id; _section = new TsSection(); } private int AddToSection(byte[] tsPacket, int index, int sectionLen) { int num = -1; int length = -1; if ((index + sectionLen) < 0xb9) { length = sectionLen + 3; num = (index + sectionLen) + 3; } else { num = 0xbc; length = 0xbc - index; } Array.Copy(tsPacket, index, _section.Data, _section.BufferPos, length); _section.BufferPos += length; _section.DecodeHeader(); return num; } public virtual void OnNewSection(TsSection section) { } public virtual void OnTsPacket(byte[] tsPacket) { TsHeader header = TsHeader.Decode(tsPacket); if (((_pid < 0x1fff) && (header.Pid == _pid)) && header.HasPayload) { int payLoadStart = header.PayLoadStart; int num2 = 0; if (header.PayloadUnitStartIndicator) { num2 = (payLoadStart + tsPacket[payLoadStart]) + 1; if (_section.BufferPos == 0) { payLoadStart += tsPacket[payLoadStart] + 1; } else { payLoadStart++; } } while (payLoadStart < 0xbc) { if (_section.BufferPos == 0) { if (!header.PayloadUnitStartIndicator) { return; } if (tsPacket[payLoadStart] == 0xff) { return; } int sectionLen = this.SnapshotSectionLength(tsPacket, payLoadStart); payLoadStart = this.StartNewTsSection(tsPacket, payLoadStart, sectionLen); } else { if (_section.section_length == -1) { _section.CalcSectionLength(tsPacket, payLoadStart); } if (_section.section_length == 0) { _section.Reset(); return; } int num4 = _section.section_length - _section.BufferPos; if ((num2 != 0) && ((payLoadStart + num4) > num2)) { num4 = num2 - payLoadStart; payLoadStart = this.AddToSection(tsPacket, payLoadStart, num4); _section.section_length = _section.BufferPos - 1; payLoadStart = num2; incompleteSections++; } else { payLoadStart = this.AddToSection(tsPacket, payLoadStart, num4); } } if (_section.SectionComplete() && (_section.section_length > 0)) { this.OnNewSection(_section); if (this.OnSectionDecoded != null) { this.OnSectionDecoded(_section); } _section.Reset(); } num2 = 0; } } } public void Reset() { _section.Reset(); } private int SnapshotSectionLength(byte[] tsPacket, int start) { if (start > 0xb8) { return -1; } return (((tsPacket[start + 1] & 15) << 8) + tsPacket[start + 2]); } private int StartNewTsSection(byte[] tsPacket, int index, int sectionLen) { int num = -1; int length = -1; if (sectionLen > -1) { if ((index + sectionLen) < 0xb9) { length = sectionLen + 3; num = (index + sectionLen) + 3; } else { num = 0xbc; length = 0xbc - index; } } else { num = 0xbc; length = 0xbc - index; } _section.Reset(); Array.Copy(tsPacket, index, _section.Data, 0, length); _section.BufferPos = length; _section.DecodeHeader(); return num; } public ushort Pid { get { return _pid; } set { _pid = value; } } public int TableId { get { return _tableId; } set { _tableId = value; } } public delegate void MethodOnSectionDecoded(TsSection section); } public class TsSection { public int BufferPos; public byte[] Data = new byte[MAX_SECTION_LENGTH * 5]; public int last_section_number; public static int MAX_SECTION_LENGTH = 0x10cc; public int section_length; public int section_number; public int section_syntax_indicator; public int table_id; public int table_id_extension; public int version_number; public TsSection() { this.Reset(); } public int CalcSectionLength(byte[] tsPacket, int start) { if (this.BufferPos < 3) { byte num = 0; byte num2 = 0; if (this.BufferPos == 1) { num = tsPacket[start]; num2 = tsPacket[start + 1]; } else if (this.BufferPos == 2) { num = this.Data[1]; num2 = tsPacket[start]; } this.section_length = ((num & 15) << 8) + num2; } else { this.section_length = ((this.Data[1] & 15) << 8) + this.Data[2]; } return this.section_length; } public bool DecodeHeader() { if (this.BufferPos < 8) { return false; } this.table_id = this.Data[0]; this.section_syntax_indicator = (this.Data[1] >> 7) & 1; if (this.section_length == -1) { this.section_length = ((this.Data[1] & 15) << 8) + this.Data[2]; } this.table_id_extension = (this.Data[3] << 8) + this.Data[4]; this.version_number = (this.Data[5] >> 1) & 0x1f; this.section_number = this.Data[6]; this.section_syntax_indicator = (this.Data[1] >> 7) & 1; return true; } public void Reset() { this.table_id = -1; this.table_id_extension = -1; this.section_length = -1; this.section_number = -1; this.version_number = -1; this.section_syntax_indicator = -1; this.BufferPos = 0; for (int i = 0; i < this.Data.Length; i++) { this.Data[i] = 0xff; } } public bool SectionComplete() { if ((!this.DecodeHeader() && (this.BufferPos > this.section_length)) && (this.section_length > 0)) { return true; } if (!this.DecodeHeader()) { return false; } return (this.BufferPos >= this.section_length); } } public class TsHeader { public byte SyncByte; public bool TransportErrorIndicator; public bool PayloadUnitStartIndicator; public bool TransportPriority; public int Pid; public byte TransportScramblingControl; public byte AdaptionFieldControl; public byte ContinuityCounter; public byte AdaptionFieldLength; public byte PayLoadStart; public bool HasAdaptionField; public bool HasPayload; public TsHeader() { TransportErrorIndicator = true; } public static TsHeader Decode(byte[] buffer) { var header = new TsHeader(); header.SyncByte = buffer[0]; if (header.SyncByte != 0x47) { header.TransportErrorIndicator = true; } header.TransportErrorIndicator = ((buffer[1] & 0x80) == 0x80); if (!header.TransportErrorIndicator) { header.PayloadUnitStartIndicator = ((buffer[1] & 0x40) == 0x40); header.TransportPriority = ((buffer[1] & 0x20) == 0x20); header.Pid = (((buffer[1] & 0x1F) << 8) + buffer[2]); header.TransportScramblingControl = (byte)(buffer[3] & 0xC0); header.AdaptionFieldControl = (byte)((buffer[3] >> 4) & 0x3); header.HasAdaptionField = (buffer[3] & 0x20) == 0x20; header.HasPayload = (buffer[3] & 0x10) == 0x10; header.ContinuityCounter = (byte)(buffer[3] & 0x0F); header.AdaptionFieldLength = 0; header.PayLoadStart = 4; if (header.HasAdaptionField) { header.AdaptionFieldLength = buffer[4]; header.PayLoadStart = (byte)(5 + header.AdaptionFieldLength); } return header; } return (null); } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.AppendFormat("Transportstream Header .\n"); sb.AppendFormat("Sync Byte: {0} .\n", SyncByte.ToString()); sb.AppendFormat("Transport Error Indicator: {0} .\n", TransportErrorIndicator); sb.AppendFormat("Payload Unit Start Indicator: {0} .\n",PayloadUnitStartIndicator); sb.AppendFormat("Transport Priority: {0} .\n", TransportPriority); sb.AppendFormat("PID: {0} .\n", Pid); sb.AppendFormat("Transport Scrambling Control: {0} .\n", TransportScramblingControl); sb.AppendFormat("Adaption Field Control: {0} .\n", AdaptionFieldControl); sb.AppendFormat("Continuity Counter: {0} .\n" , ContinuityCounter); sb.AppendFormat(".\n"); return sb.ToString(); } } Edited October 27, 2016 by Diefenthal 1 Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted November 1, 2016 Share Posted November 1, 2016 Looks like i write here only for me Link to comment Share on other sites More sharing options...
Luke 37024 Posted November 1, 2016 Share Posted November 1, 2016 Looks like i write here only for me 01.11.2016.PNG So this is able to query channels now? Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted November 1, 2016 Share Posted November 1, 2016 short test results says yes the ServiceDescriptionTable parsing is working with that had we this values avaible ServiceType ServiceName ServiceProviderName ServiceId EitScheduleFlag EitPresentFollowingFlag ScrambeldFlag RunningStatus but now is the nextsteps are if found more time Parsing of PMT to get PCR, Audio, Video, TTX and Subtitle Pids for adding to Channel Object Parsing of NIT to get exact Tuning Informations for TransportStreamId for adding to Channel Object 1 Link to comment Share on other sites More sharing options...
Luke 37024 Posted November 1, 2016 Share Posted November 1, 2016 Parsing of PMT to get PCR, Audio, Video, TTX and Subtitle Pids for adding to Channel Object What is this for? Once we open the live stream can't we just probe with ffmpeg? Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted November 1, 2016 Share Posted November 1, 2016 sure but we must the satip Server say that we wont this data streams and so must tell this pids over rtsp Play request to the server 1 Link to comment Share on other sites More sharing options...
Master of Tragedy 0 Posted November 6, 2016 Share Posted November 6, 2016 So it seems the SAT>IP-Server support is no more than finding and listing the server for now but not being able to actually use it? I was pretty happy to see that it found my Kathrein SAT>IP-Server when I clicked on Live-TV but it's not doing anything. I could configure it but that's it. And now I can't even delete it anymore. Once deleted and back to the Live-TV configuration it shows up again. Is there any way to get rid of it? For now I've added the DVBLink-Plugin which works although extremely slow (needs about 30 seconds to actually show a channel). Is there any way to sort the EPG by channel number or anything other than completely unsorted? Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted November 6, 2016 Share Posted November 6, 2016 (edited) Yes Sat>Ip Support is more than discover the devices and read an m3u and Play an stream that is the reason why in the SatIp Spec is describe what an Client should can do Discovery (SSDP + Parsing Device Description) Start Modify Stop Streams (RTSP RTCP RTP) Service / Channel Search (Read Transport Streams Data from RTP Listener) Collecting Guide Data Manage Services Channels EMBY can at time only Discover the Devices and send RTSP Request to the Server all other things (Service Channel Search, Collecting Guide Data and Manage Services Channels) are not given in the current state and for Users that ask why i share and work here on an Winform Project (Binary + Source ) it is so for me easier to test written code and if it stable enough, give i @@Luke the info for porting it to Emby PS if anyone would help for speedup the Progress the source is avaible on github and would anyone make an Code Review is that welcome too Edited November 6, 2016 by Diefenthal Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted November 7, 2016 Share Posted November 7, 2016 it Looks like that it give Problems by device Discovery i ask me why it not was previous reported i work for you and this is not an oneway, i need Test Results without this is the Sat>Ip Support for emby dead so once more ,i share test apps to get an true it works or false it crashplease test any version what i share here if one build crash in your config let it me Knowthis helps emby in any case here 2 Tools two Show where the discovery (ssdp) has Problems with device xyz the first GetSSDPUnicast Response send 3 M-Search Messages to "239.255.255.250:1900" with searchterm "urn:ses-com:device:SatIPServer:1" and should recieve HTTP/1.1 200 OK Responses check is Test the Regex Match for HTTP/1.1 200 OK check is Test the Regex Match for UUID check is Test for Searchtearm if all 3 passed with true than can you test the second Tool there put you the Location: value into the TextBox and Show it the Description Fields are filled if there Textboxes filled should it work thanx Link to comment Share on other sites More sharing options...
Master of Tragedy 0 Posted November 8, 2016 Share Posted November 8, 2016 I appreciate your work but I'm on MacOS so I can't test your tool. I will see if I can set up a windows VM for that. Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted November 8, 2016 Share Posted November 8, 2016 was your Sat>Ip Server not the Kathrein Ex? then had the discovery working for you or was an device missed ? Link to comment Share on other sites More sharing options...
Master of Tragedy 0 Posted November 8, 2016 Share Posted November 8, 2016 Yes, it was a Kathrein EXIP414E and it was discovered correctly. Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted November 8, 2016 Share Posted November 8, 2016 Parsing of PMT to get PCR, Audio, Video, TTX and Subtitle Pids for adding to Channel Object What is this for? Once we open the live stream can't we just probe with ffmpeg? you can it try SDT give you the Basic informations Link to comment Share on other sites More sharing options...
rechner123 12 Posted November 10, 2016 Share Posted November 10, 2016 (edited) Hi There is a new DVB-Viewer Recording Service available, with maybe some important changes for satip?! and security fixes. "Change/Fix: RTSP Server: Fixes and enhanced Sat>IP 1.2.2 compatibility concerning data sent through the RTCP channel and as response to DESCRIBE commands. Proprietary RTCP data for DVBViewer & Co clients is not sent to other Sat>IP clients anymore. More about it here." I hope this could be useful. Edited November 10, 2016 by rechner123 Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted November 11, 2016 Share Posted November 11, 2016 Hi There is a new DVB-Viewer Recording Service available, with maybe some important changes for satip?! and security fixes. "Change/Fix: RTSP Server: Fixes and enhanced Sat>IP 1.2.2 compatibility concerning data sent through the RTCP channel and as response to DESCRIBE commands. Proprietary RTCP data for DVBViewer & Co clients is not sent to other Sat>IP clients anymore. More about it here." I hope this could be useful. helpfull yes but DVBViewer send s not specified Parameters in there RTCP APP and Describe Responses think that they mean this with this info Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted November 19, 2016 Share Posted November 19, 2016 any reason why in dev or beta no satip is more avaible ? Link to comment Share on other sites More sharing options...
Luke 37024 Posted November 19, 2016 Share Posted November 19, 2016 I'll look at restoring it, thanks. Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted November 19, 2016 Share Posted November 19, 2016 is your Thing if you would restore it or not had my fork of emby deleted after the commit was not success Link to comment Share on other sites More sharing options...
Luke 37024 Posted November 19, 2016 Share Posted November 19, 2016 It was inadvertent due to restructuring for .net core, so not intentional. Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted November 19, 2016 Share Posted November 19, 2016 (edited) think this Topic is dead there was an info in emby Repro "remove dead code" ande the source code lines behind this Info was Sat>Ip related @@Luke you can delete my account all attachments are deleted Edited December 18, 2016 by Diefenthal Link to comment Share on other sites More sharing options...
Commerzpunk 5 Posted January 25, 2017 Share Posted January 25, 2017 Hello, i am from germany and very interested to get SAT>IP working in Emby. Right now i got Emby and TVHeadend running on a Synology DS115. I hope to only have Emby in the future to get recording of my series perfectly running. My device is a Digibit R1 which is a 4-Tuner in and LAN out SAT>Ip Server. Works perfectly with TVHeadend. I can offer to test, provide logs, and so on. @Diegenthal: Youre still here and reading? Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted February 9, 2017 Share Posted February 9, 2017 (edited) Hello, i am from germany and very interested to get SAT>IP working in Emby. Right now i got Emby and TVHeadend running on a Synology DS115. I hope to only have Emby in the future to get recording of my series perfectly running. My device is a Digibit R1 which is a 4-Tuner in and LAN out SAT>Ip Server. Works perfectly with TVHeadend. I can offer to test, provide logs, and so on. @Diegenthal: Youre still here and reading? yes i m there and read somethings but nothing more @@Luke had add some classes Import back but in MediaBrowser.Server.Startup.Common i ask me why there Edited February 9, 2017 by Diefenthal 1 Link to comment Share on other sites More sharing options...
Commerzpunk 5 Posted February 11, 2017 Share Posted February 11, 2017 Hi Kai ;-) nice to hear that. I could help testing or providing logs. But seems there is no action in sat>ip and emby right now. Thats sad. But you can send me messages, of course in german too. Cheers Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now