Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RTSP.Tests/Integration/RTSPListenerIntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class RTSPListenerIntegrationTests
public async Task SendOption_WhenSent_Receives200OK(string uri)
{
// arrange
var socket = RtspUtils.CreateRtspTransportFromUrl(new(uri), AcceptAllCertificate);
var socket = RtspUtils.CreateRtspTransportFromUrl(new(uri), new(), AcceptAllCertificate);
var listener = new RtspListener(socket);
var taskCompletionSource = new TaskCompletionSource<RtspResponse>();
listener.MessageReceived += ListenerOnMessageReceived;
Expand Down
2 changes: 1 addition & 1 deletion RTSP/RTSPHttpTransport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ public void Close()
_dataClient?.Close();
}

public Stream GetStream()
public virtual Stream GetStream()
{
if (_dataClient?.Connected != true || _stream is null)
throw new InvalidOperationException("Client is not connected");
Expand Down
18 changes: 18 additions & 0 deletions RTSP/RTSPHttpsTransport.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.IO;
using System.Net.Security;

namespace Rtsp;

public class RTSPHttpsTransport(Uri uri, System.Net.NetworkCredential credentials, RemoteCertificateValidationCallback? userCertificateSelectionCallback = null) : RtspHttpTransport(uri, credentials)
{
private readonly RemoteCertificateValidationCallback? _userCertificateSelectionCallback = userCertificateSelectionCallback;

public override Stream GetStream()
{
var sslStream = new SslStream(base.GetStream(), true, _userCertificateSelectionCallback);

sslStream.AuthenticateAsClient(RemoteAddress);
return sslStream;
}
}
7 changes: 4 additions & 3 deletions RTSP/RTSPUtils.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Net;
using System.Net.Security;

namespace Rtsp
Expand All @@ -16,14 +17,14 @@ public static void RegisterUri()
}
}

public static IRtspTransport CreateRtspTransportFromUrl(Uri uri, RemoteCertificateValidationCallback? userCertificateSelectionCallback = null)
public static IRtspTransport CreateRtspTransportFromUrl(Uri uri, NetworkCredential networkCredential, RemoteCertificateValidationCallback? userCertificateSelectionCallback = null)
{
return uri.Scheme switch
{
"rtsp" => new RtspTcpTransport(uri),
"rtsps" => new RtspTcpTlsTransport(uri, userCertificateSelectionCallback),
"http" => new RtspHttpTransport(uri, new()),
// "https" => new RtspHttpTransport(uri, new()),
"http" => new RtspHttpTransport(uri, networkCredential),
"https" => new RTSPHttpsTransport(uri, networkCredential, userCertificateSelectionCallback),
_ => throw new ArgumentException("The uri scheme is not supported", nameof(uri))
};
}
Expand Down
66 changes: 46 additions & 20 deletions RtspClientExample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ public static class Program
{
private static ILogger logger = null!;

private const string ProfileMJPEG = "JPEG";
private const string ProfileH264 = "H264";
private const string ProfileH265 = "H265";
private const string ProfileMP2T = "MP2T";

private const string ProfilePCMU = "PCMU";
private const string ProfilePCMA = "PCMA";
private const string ProfileAMR = "AMR";
private const string ProfileAAC = "AAC";

private static readonly byte[] halStartCode = [0x00, 0x00, 0x00, 0x01];

static void Main()
{
var loggerFactory = LoggerFactory.Create(builder =>
Expand All @@ -35,13 +47,13 @@ static void Main()

// string url = "rtsp://192.168.0.89/media/video2";

// string url = "http://192.168.3.72/profile1/media.smp";
string url = "http://192.168.3.72/profile1/media.smp";

bool usePlayback = false;
// string url = "rtsp://192.168.3.72/ProfileG/Recording-1/recording/play.smp";

string username = "admin";
string password = "admin";
string password = "Admin123!";
// Axis Tests
//String url = "rtsp://192.168.1.125/onvif-media/media.amp?profile=quality_h264";
//String url = "rtsp://user:password@192.168.1.102/onvif-media/media.amp?profile=quality_h264";
Expand Down Expand Up @@ -69,7 +81,7 @@ static void Main()

// Happytime RTSP Server
//string url = "rtsp://127.0.0.1/screenlive";
string url = "http://127.0.0.1:8044/screenlive";
//string url = "http://127.0.0.1:8044/screenlive";

// MJPEG Tests (Payload 26)
//String url = "rtsp://192.168.1.125/onvif-media/media.amp?profile=mobile_jpeg";
Expand Down Expand Up @@ -178,9 +190,9 @@ private static void NewAACAudioStream(NewStreamEventArgs arg, RTSPClient client)
var config = arg.StreamConfigurationData as AacStreamConfigurationData;
Debug.Assert(config != null, "config is invalid");

client.ReceivedAudioData += (_, args) =>
void ReceiveAudioAAC(RTSPClient client, SimpleDataEventArgs dataArgs)
{
foreach (var data in args.Data)
foreach (var data in dataArgs.Data)
{
// ASDT header format
int protection_absent = 1;
Expand Down Expand Up @@ -214,7 +226,9 @@ private static void NewAACAudioStream(NewStreamEventArgs arg, RTSPClient client)
fs_a.Write(header, 0, header.Length);
fs_a.Write(data.Span);
}
};
}
;
client.SetupAudioPayload(ProfileAAC, ReceiveAudioAAC);
}

private static void NewAMRAudioStream(RTSPClient client)
Expand All @@ -224,27 +238,29 @@ private static void NewAMRAudioStream(RTSPClient client)
string filename = "rtsp_capture_" + now + ".amr";
FileStream fs_a = new(filename, FileMode.Create);
fs_a.Write("#!AMR\n"u8);
client.ReceivedAudioData += (_, args) =>
void ReceiveAudioAMR(RTSPClient client, SimpleDataEventArgs dataArgs)
{
foreach (var data in args.Data)
foreach (var data in dataArgs.Data)
{
fs_a.Write(data.Span);
}
};
client.SetupAudioPayload(ProfileAMR, ReceiveAudioAMR);
}

private static void NewGenericAudio(RTSPClient client, string extension)
{
string now = DateTime.Now.ToString("yyyyMMdd_HHmmss");
string filename = "rtsp_capture_" + now + "." + extension;
FileStream fs_a = new(filename, FileMode.Create);
client.ReceivedAudioData += (_, args) =>
void ReceiveAudioPCMA(RTSPClient client, SimpleDataEventArgs dataArgs)
{
foreach (var data in args.Data)
foreach (var data in dataArgs.Data)
{
fs_a.Write(data.Span);
}
};
client.SetupAudioPayload(ProfilePCMA, ReceiveAudioPCMA);
}

private static void NewMP2Stream(RTSPClient client)
Expand All @@ -253,13 +269,15 @@ private static void NewMP2Stream(RTSPClient client)

string filename = "rtsp_capture_" + now + ".mp2";
FileStream fs_v = new(filename, FileMode.Create);
client.ReceivedVideoData += (_, args) =>
void ReceivedVideoData_MPT2(RTSPClient client, SimpleDataEventArgs dataArgs)
{
foreach (var data in args.Data)
foreach (var data in dataArgs.Data)
{
fs_v?.Write(data.Span);
}
};
}
;
client.SetupVideoPayload(ProfileMP2T, ReceivedVideoData_MPT2);
}

private static void NewMJPEGStream(RTSPClient client)
Expand All @@ -268,18 +286,21 @@ private static void NewMJPEGStream(RTSPClient client)

Directory.CreateDirectory("rtsp_capture_" + now);
var indexImg = 0;
client.ReceivedVideoData += (_, args) =>
void ReceivedVideoData_MJPEG(RTSPClient client, SimpleDataEventArgs dataArgs)
{
// Ugly to do it each time.
// The interface need to change have an event on new file

foreach (var data in args.Data)

foreach (var data in dataArgs.Data)
{
string filename = Path.Combine("rtsp_capture_" + now, indexImg++ + ".jpg");
using var fs = new FileStream(filename, FileMode.Create);
fs.Write(data.Span);
}
};
}
;
client.SetupVideoPayload(ProfileMJPEG, ReceivedVideoData_MJPEG);
}

private static void NewH265Stream(NewStreamEventArgs args, RTSPClient client)
Expand All @@ -293,7 +314,7 @@ private static void NewH265Stream(NewStreamEventArgs args, RTSPClient client)
WriteNalToFile(fs_v, h265StreamConfigurationData.SPS);
WriteNalToFile(fs_v, h265StreamConfigurationData.PPS);
}
client.ReceivedVideoData += (_, dataArgs) =>
void ReceivedVideoData_H265(RTSPClient client, SimpleDataEventArgs dataArgs)
{
if (fs_v != null)
{
Expand All @@ -319,7 +340,9 @@ private static void NewH265Stream(NewStreamEventArgs args, RTSPClient client)
fs_v.Write(nalUnit);
}
}
};
}
;
client.SetupVideoPayload(ProfileH265, ReceivedVideoData_H265);
}

private static void NewH264Stream(NewStreamEventArgs args, RTSPClient client)
Expand All @@ -332,7 +355,8 @@ private static void NewH264Stream(NewStreamEventArgs args, RTSPClient client)
WriteNalToFile(fs_v, h264StreamConfigurationData.SPS);
WriteNalToFile(fs_v, h264StreamConfigurationData.PPS);
}
client.ReceivedVideoData += (_, dataArgs) =>

void ReceivedVideoData_H264(RTSPClient client, SimpleDataEventArgs dataArgs)
{
foreach (var nalUnitMem in dataArgs.Data)
{
Expand All @@ -356,7 +380,9 @@ private static void NewH264Stream(NewStreamEventArgs args, RTSPClient client)
}
fs_v.Write(nalUnit);
}
};
}
;
client.SetupVideoPayload(ProfileH264, ReceivedVideoData_H264);
}

private static void WriteNalToFile(FileStream fs_v, ReadOnlySpan<byte> nal)
Expand Down
Loading