eddiepropane 2 Posted August 14, 2016 Share Posted August 14, 2016 Hi all, Didn't want to start a new thread as it discussed quite heavily in here. Lifetime supporter which is all I can really do apart from test unfortunately as I have no coding skills - Spent the last Cpl of hours looking at emby and VLC's GitHub to see if I can see why it works on VLC and not emby (I think I know it is ffdshow related but was trying to see how it parsed the m3u) and realised I know far less than I thought!! Has there been any updates/movement on the Dvbviewer RS Sat-Ip support? I can see that the server parses the m3u file a bit better since I last checked a few months ago but still does not get playback. The live TV plugins are good and well developed but each have their strengths and weaknesses and to be able to use sat-ip and schedules direct on the server without and additional software would be awesome!! Thanks, B. Link to comment Share on other sites More sharing options...
Luke 37994 Posted August 14, 2016 Share Posted August 14, 2016 There hasn't been any movement lately for built-in sat-ip support. It's still a possibility for the future. 1 Link to comment Share on other sites More sharing options...
pir8radio 1301 Posted August 14, 2016 Share Posted August 14, 2016 What is needed for the developers to make this happen? Other than time... A device for testing? Link to comment Share on other sites More sharing options...
Luke 37994 Posted August 14, 2016 Share Posted August 14, 2016 Yes there's that too. Link to comment Share on other sites More sharing options...
pir8radio 1301 Posted August 14, 2016 Share Posted August 14, 2016 (edited) I can probably stand one up online for testing.... so you don't have to deal with antenna aiming and what not. If that helps.. Give you an IP and DMZ it... If that's something you would be interested in. Edited August 14, 2016 by pir8radio Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted August 20, 2016 Share Posted August 20, 2016 (edited) one please dont only Support the m3u way if emby really want Support the sat>ip protocol then should it both ways Support that was since my Suggestion with ssdp for device discovery (is done in the sample) rtsp for start, keepalive, stop the mediastream(is done in the sample) rtp for receiving the mediastream(is done in the sample) rtcp for mediastream informations ( Recieption Details Signal Level Quality , Lost packets ....)(is done in the sample) parsing of Mpeg2TS (PAT, PMT, SDT, NIT, EIT) for Channel / Service Scan (not finshed far away from stable) Edited August 20, 2016 by Diefenthal 2 Link to comment Share on other sites More sharing options...
Luke 37994 Posted August 20, 2016 Share Posted August 20, 2016 I would love to support both ways. 2 Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted August 21, 2016 Share Posted August 21, 2016 I would love to support both ways. to the PSI Parsing if you find an way in the PSI.cs class in Method public static PSISection[] GetPSITable(int pid, int tableId, IMpeg2Data mpeg2Data)to replace IMpeg2Data with an alternative way for raw ts Byte[] can this an Option https://github.com/dgis/CodeTV/tree/master/DvbPsi Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted August 28, 2016 Share Posted August 28, 2016 @@Luke i had here create an patch and had it pulled https://github.com/MediaBrowser/Emby/pull/2115 let me know what you think of it 1 Link to comment Share on other sites More sharing options...
Luke 37994 Posted August 28, 2016 Share Posted August 28, 2016 Thanks, will take a look! Link to comment Share on other sites More sharing options...
Luke 37994 Posted August 28, 2016 Share Posted August 28, 2016 I merged the first pull request. Second one needs to be rebased now. Thanks. Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted August 28, 2016 Share Posted August 28, 2016 should i rebased the second ? or will you it do ? it contains the receiving rtp rtcp classes Link to comment Share on other sites More sharing options...
Luke 37994 Posted August 28, 2016 Share Posted August 28, 2016 I can handle it, thanks. Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted August 28, 2016 Share Posted August 28, 2016 the underscore before capabilities is the Problem, was fixed in the second one ;-) sorry about that Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted September 1, 2016 Share Posted September 1, 2016 (edited) @@Luke had here 2 questions for what stands the integer TunerHostInfo.Tuners? if i build emby with vs 2015 on Windows 10 wich is the commonstartup Project for testing ? https://github.com/MediaBrowser/Emby/pull/2116 Edited September 1, 2016 by Diefenthal Link to comment Share on other sites More sharing options...
Luke 37994 Posted September 1, 2016 Share Posted September 1, 2016 @@Luke had here 2 questions for what stands the integer TunerHostInfo.Tuners? if i build emby with vs 2015 on Windows 10 wich is the commonstartup Project for testing ? https://github.com/MediaBrowser/Emby/pull/2116 Total number of tuners. The startup project for windows is mediabrowser.ServerApplication Thanks! Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted September 1, 2016 Share Posted September 1, 2016 ok _tunerCountDVBS integer is working so should it work with _tunerCountDVBT and _tunerCountDVBC too but i am must now look why only one of two Satip Servers are listed in the UI Link to comment Share on other sites More sharing options...
Luke 37994 Posted September 2, 2016 Share Posted September 2, 2016 Thanks! I have merged all current changes into the dev branch as well as posted a dev build for Windows users. So any of you with Sat/IP can help test it out. For those who run beta, it will be in tomorrow's beta. Thanks. 1 Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted September 2, 2016 Share Posted September 2, 2016 @@Luke had set an Breakpoint in method GetChannelsInternal() from SatipHost.cs but this is never triggert Link to comment Share on other sites More sharing options...
Luke 37994 Posted September 2, 2016 Share Posted September 2, 2016 @@Luke had set an Breakpoint in method GetChannelsInternal() from SatipHost.cs but this is never triggert Did you try running the refresh guide scheduled task? Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted September 2, 2016 Share Posted September 2, 2016 for an channel / Service scan an guideupdate Task ? ok Link to comment Share on other sites More sharing options...
Luke 37994 Posted September 2, 2016 Share Posted September 2, 2016 Yea it refreshes everything. Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted September 2, 2016 Share Posted September 2, 2016 (edited) in futuere should it splittet or controlled with one more Parameter the channel scan is much faster without reading guide data (DVB EIT) rtsp session is feed with an wrong Url Format there is only the address needed no Schema(Http://) no port(:x) from the description possible fix can be use two fields one called Device Description Url the other Device Url for an channel Change must the session not terminated (Teardown) an simple Play request with updated Tuning string, addpids or delpids to the Server is enough see it in the wireshark capture wich is inside attached zip Edited September 2, 2016 by Diefenthal Link to comment Share on other sites More sharing options...
Guest Diefenthal Posted September 7, 2016 Share Posted September 7, 2016 what think you over this each tuner inside an Sat>ip device had an own rtsp rtp rtcp session sure this code snippet isnt complete but it sould only illustrade what for other ways it give public abstract class Tuner:IDisposable { private static readonly Regex REGEX_DESCRIBE_RESPONSE_SIGNAL_INFO = new Regex(@";tuner=\d+,(\d+),(\d+),(\d+),", RegexOptions.Singleline | RegexOptions.IgnoreCase); private static readonly Regex REGEX_RTSP_SESSION_HEADER = new Regex(@"\s*([^\s;]+)(;timeout=(\d+))?"); private static readonly TimeSpan DEFAULT_RTSP_SESSION_TIMEOUT = new TimeSpan(0, 0, 60); private static readonly TimeSpan RTCP_REPORT_WAIT_TIMEOUT = new TimeSpan(0, 0, 0, 0, 400); #region Private Fields /// <summary> /// An RTSP client, used to communicate with the SAT>IP server. /// </summary> private RtspClient _rtspClient = null; /// <summary> /// The time after which the SAT>IP server will stop streaming if it does /// not receive some kind of interaction. /// </summary> private TimeSpan _rtspSessionTimeout = TimeSpan.Zero; /// <summary> /// The current RTSP session ID. Used in the header of all RTSP messages /// sent to the server. /// </summary> private string _rtspSessionId = string.Empty; /// <summary> /// A thread, used to periodically send RTSP OPTIONS to tell the SAT>IP /// server not to stop streaming. /// </summary> private Thread _keepAliveThread = null; /// <summary> /// An event, used to stop the streaming keep-alive thread. /// </summary> private AutoResetEvent _keepAliveThreadStopEvent = null; /// <summary> /// A thread, used to listen for RTP Packets containing the Transportstream /// </summary> private Thread _rtpListenerThread = null; /// <summary> /// An event, used to stop the RTP listener thread. /// </summary> private AutoResetEvent _rtpListenerThreadStopEvent = null; /// <summary> /// A thread, used to listen for RTCP reports containing signal status /// updates. /// </summary> private Thread _rtcpListenerThread = null; /// <summary> /// An event, used to stop the RTCP listener thread. /// </summary> private AutoResetEvent _rtcpListenerThreadStopEvent = null; /// <summary> /// /// </summary> private TransmissionMode _transmissionMode = TransmissionMode.Unicast; /// <summary> /// The Address on which the RTP RTCP listener thread listens. /// </summary> private string _destination; /// <summary> /// The Address that the RTP RTCP listener thread listens to. /// </summary> private string _source; /// <summary> /// The port on which the RTP listener thread listens. /// </summary> private int _rtpClientPort; /// <summary> /// The port that the RTP listener thread listens to. /// </summary> private int _rtpServerPort; /// <summary> /// The port on which the RTCP listener thread listens. /// </summary> private int _rtcpClientPort; /// <summary> /// The port that the RTCP listener thread listens to. /// </summary> private int _rtcpServerPort; /// <summary> /// /// </summary> private bool _signalLocked = false; /// <summary> /// /// </summary> private int _signalLevel = -1; /// <summary> /// /// </summary> private int _signalQuality = -1; #endregion #region Properties /// <summary> /// The Address on which the RTP RTCP listener thread listens. /// </summary> public string Destination { get { return _destination; } set { _destination = value; } } /// <summary> /// The Address that the RTP RTCP listener thread listens to. /// </summary> public string Source { get { return _source; } set { _source = value; } } /// <summary> /// The port on which the RTP listener thread listens. /// </summary> public int RtpClientPort { get { return _rtpClientPort; } set { _rtpClientPort = value; } } /// <summary> /// The port that the RTP listener thread listens to. /// </summary> public int RtpServerPort { get { return _rtpServerPort; } set { _rtpServerPort = value; } } /// <summary> /// The port on which the RTCP listener thread listens. /// </summary> public int RtcpClientPort { get { return _rtcpClientPort; } set { _rtcpClientPort = value; } } /// <summary> /// The port that the RTCP listener thread listens to. /// </summary> public int RtcpServerPort { get { return _rtcpServerPort; } set { _rtcpServerPort = value; } } /// <summary> /// /// </summary> public bool SignalLocked { get { return _signalLocked; } set { _signalLocked = value; } } /// <summary> /// /// </summary> public int SignalLevel { get { return _signalLevel; } set { _signalLevel = value; } } /// <summary> /// /// </summary> public int SignalQuality { get { return _signalQuality; } set { _signalQuality = value; } } #endregion #region KeepAlive Thread private void StartKeepAliveThread() { // Kill the existing thread if it is in "zombie" state. if (_keepAliveThread != null && !_keepAliveThread.IsAlive) { StopKeepAliveThread(); } if (_keepAliveThread == null) { Logger.Info("SAT>IP : starting new keep-alive thread"); _keepAliveThreadStopEvent = new AutoResetEvent(false); _keepAliveThread = new Thread(new ThreadStart(KeepAlive)); _keepAliveThread.Name = string.Format("SAT>IP tuner keep-alive"); _keepAliveThread.IsBackground = true; _keepAliveThread.Priority = ThreadPriority.Lowest; _keepAliveThread.Start(); } } private void StopKeepAliveThread() { if (_keepAliveThread != null) { if (!_keepAliveThread.IsAlive) { Logger.Critical("SAT>IP : aborting old keep-alive thread"); _keepAliveThread.Abort(); } else { _keepAliveThreadStopEvent.Set(); if (!_keepAliveThread.Join((int)_rtspSessionTimeout.TotalMilliseconds * 2)) { Logger.Critical("SAT>IP : failed to join keep-alive thread, aborting thread"); _keepAliveThread.Abort(); } } _keepAliveThread = null; if (_keepAliveThreadStopEvent != null) { _keepAliveThreadStopEvent.Close(); _keepAliveThreadStopEvent = null; } } } private void KeepAlive() { try { while (!_keepAliveThreadStopEvent.WaitOne((int)(_rtspSessionTimeout - new TimeSpan(0, 0, 5)).TotalMilliseconds * 1000)) // -5 seconds to avoid timeout { RtspRequest request = new RtspRequest(RtspMethod.Options, string.Format("rtsp://{0}/", Source),1,0); request.Headers.Add("Session", _rtspSessionId); RtspResponse response; if (_rtspClient.SendRequest(request, out response) != RtspStatusCode.Ok) { Logger.Critical("SAT>IP : keep-alive request/response failed, non-OK RTSP OPTIONS status code {0} {1}", response.StatusCode, response.ReasonPhrase); } } } catch (ThreadAbortException) { } catch (Exception ex) { Logger.Error(ex.ToString(), "SAT>IP : keep-alive thread exception"); return; } Logger.Info("SAT>IP : keep-alive thread stopping"); } #endregion #region RTP listener Thread public void StartRtpListenerThread() { // Kill the existing thread if it is in "zombie" state. if (_rtpListenerThread != null && !_rtpListenerThread.IsAlive) { StopRtpListenerThread(); } if (_rtpListenerThread == null) { Logger.Info("SAT>IP : starting new RTP listener thread"); _rtpListenerThreadStopEvent = new AutoResetEvent(false); _rtpListenerThread = new Thread(new ThreadStart(RtpListenerThread)); _rtpListenerThread.Name = string.Format("SAT>IP tuner RTP listener"); _rtpListenerThread.IsBackground = true; _rtpListenerThread.Priority = ThreadPriority.Lowest; _rtpListenerThread.Start(); } } public void StopRtpListenerThread() { if (_rtpListenerThread != null) { if (!_rtpListenerThread.IsAlive) { Logger.Warn("SAT>IP : aborting old RTP listener thread"); _rtpListenerThread.Abort(); } else { _rtpListenerThreadStopEvent.Set(); if (!_rtpListenerThread.Join(400 * 2)) { Logger.Warn("SAT>IP : failed to join RTP listener thread, aborting thread"); _rtpListenerThread.Abort(); } } _rtpListenerThread = null; if (_rtpListenerThreadStopEvent != null) { _rtpListenerThreadStopEvent.Close(); _rtpListenerThreadStopEvent = null; } } } private void RtpListenerThread() { UdpClient rtpClient = null; IPEndPoint serverEndPoint = null; IPEndPoint multicastEndPoint = null; try { switch (_transmissionMode) { case TransmissionMode.Unicast: rtpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(Destination), RtpClientPort)); serverEndPoint = new IPEndPoint(IPAddress.Any, 0); break; case TransmissionMode.Multicast: multicastEndPoint = new IPEndPoint(IPAddress.Parse(Destination), RtpClientPort); serverEndPoint = null; rtpClient = new UdpClient(); rtpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); rtpClient.ExclusiveAddressUse = false; rtpClient.Client.Bind(new IPEndPoint(IPAddress.Any, multicastEndPoint.Port)); rtpClient.JoinMulticastGroup(multicastEndPoint.Address); break; } try { while (!receivedGoodBye && !_rtpListenerThreadStopEvent.WaitOne(1)) { byte[] receivedbytes = rtpClient.Receive(ref serverEndPoint); RtpPacket packet = RtpPacket.Decode(receivedbytes); //OnPacketReceived(new RtpPacketReceivedArgs(packet)); } } finally { switch (_transmissionMode) { case TransmissionMode.Multicast: rtpClient.DropMulticastGroup(multicastEndPoint.Address); rtpClient.Close(); break; case TransmissionMode.Unicast: rtpClient.Close(); break; } } } catch (ThreadAbortException) { } catch (Exception ex) { Logger.Error(string.Format("SAT>IP : RTP listener thread exception"), ex); return; } Logger.Warn("SAT>IP : RTP listener thread stopping"); } #endregion #region RTCP listener Thread private void StartRtcpListenerThread() { // Kill the existing thread if it is in "zombie" state. if (_rtcpListenerThread != null && !_rtcpListenerThread.IsAlive) { StopRtcpListenerThread(); } if (_rtcpListenerThread == null) { Logger.Info("SAT>IP base: starting new RTCP listener thread"); _rtcpListenerThreadStopEvent = new AutoResetEvent(false); _rtcpListenerThread = new Thread(new ThreadStart(RtcpListener)); _rtcpListenerThread.Name = string.Format("SAT>IP tuner RTCP listener"); _rtcpListenerThread.IsBackground = true; _rtcpListenerThread.Priority = ThreadPriority.Lowest; _rtcpListenerThread.Start(); } } private void StopRtcpListenerThread() { if (_rtcpListenerThread != null) { if (!_rtcpListenerThread.IsAlive) { Logger.Critical("SAT>IP base: aborting old RTCP listener thread"); _rtcpListenerThread.Abort(); } else { _rtcpListenerThreadStopEvent.Set(); if (!_rtcpListenerThread.Join((int)RTCP_REPORT_WAIT_TIMEOUT.TotalMilliseconds * 2)) { Logger.Critical("SAT>IP base: failed to join RTCP listener thread, aborting thread"); _rtcpListenerThread.Abort(); } } _rtcpListenerThread = null; if (_rtcpListenerThreadStopEvent != null) { _rtcpListenerThreadStopEvent.Close(); _rtcpListenerThreadStopEvent = null; } } } private void RtcpListener() { UdpClient rtcpClient = null; IPEndPoint serverEndPoint = null; IPEndPoint multicastEndPoint = null; try { switch (_transmissionMode) { case TransmissionMode.Unicast: rtcpClient = new UdpClient(new IPEndPoint(IPAddress.Parse(Destination), RtcpClientPort)); rtcpClient.Client.ReceiveTimeout = 5000; serverEndPoint = new IPEndPoint(IPAddress.Any, 0); break; case TransmissionMode.Multicast: multicastEndPoint = new IPEndPoint(IPAddress.Parse(Destination), RtcpClientPort); serverEndPoint = new IPEndPoint(IPAddress.Any, 0); rtcpClient = new UdpClient(); rtcpClient.Client.ReceiveTimeout = 5000; rtcpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1); rtcpClient.ExclusiveAddressUse = false; rtcpClient.Client.Bind(new IPEndPoint(IPAddress.Any, RtcpClientPort)); rtcpClient.JoinMulticastGroup(multicastEndPoint.Address); break; } bool receivedGoodBye = false; try { while (!receivedGoodBye && !_rtcpListenerThreadStopEvent.WaitOne(1)) { byte[] packets = null; try { packets = rtcpClient.Receive(ref serverEndPoint); } catch (Exception ex) { Logger.Critical(ex.ToString(), "SAT>IP base: failed to receive RTCP packets"); } if (packets == null) { continue; } int offset = 0; while (offset < packets.Length) { switch (packets[offset + 1]) { case 200: //sr var sr = new RtcpSenderReportPacket(); sr.Parse(packets, offset); offset += sr.Length; break; case 201: //rr var rr = new RtcpReceiverReportPacket(); rr.Parse(packets, offset); offset += rr.Length; break; case 202: //sd var sd = new RtcpSourceDescriptionPacket(); sd.Parse(packets, offset); offset += sd.Length; break; case 203: // bye var bye = new RtcpByePacket(); bye.Parse(packets, offset); receivedGoodBye = true; offset += bye.Length; break; case 204: // app var app = new RtcpAppPacket(); app.Parse(packets, offset); var m = REGEX_DESCRIBE_RESPONSE_SIGNAL_INFO.Match(app.Data); if (m.Success) { _signalLocked = m.Groups[2].Captures[0].Value.Equals("1"); _signalLevel = int.Parse(m.Groups[1].Captures[0].Value) * 100 / 255; // level: 0..255 => 0..100 _signalQuality = int.Parse(m.Groups[3].Captures[0].Value) * 100 / 15; // quality: 0..15 => 0..100 } offset += app.Length; break; } } } } finally { switch (_transmissionMode) { case TransmissionMode.Multicast: rtcpClient.DropMulticastGroup(multicastEndPoint.Address); rtcpClient.Close(); break; case TransmissionMode.Unicast: rtcpClient.Close(); break; } } } catch (ThreadAbortException) { } catch (Exception ex) { Logger.Error(ex.ToString(), "SAT>IP base: RTCP listener thread exception"); return; } Logger.Info("SAT>IP base: RTCP listener thread stopping"); } #endregion #region IDisposable Members /// <summary> /// Release and dispose all resources. /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// Release and dispose all resources. /// </summary> /// <param name="isDisposing"><c>True</c> if the instance is being disposed.</param> private void Dispose(bool isDisposing) { if (isDisposing) { if (_rtspClient != null) { _rtspClient.Dispose(); _rtspClient = null; } } } #endregion } Link to comment Share on other sites More sharing options...
Luke 37994 Posted September 8, 2016 Share Posted September 8, 2016 I think that should be fine. 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