I am trying to construct a UI for Onvif complaint devices. I've been beating my head against the wall for sometime now. I believe I have the custom URI correctly constructed. According to the ONVIF Programmers Guide we need to Get Profiles, GetStreamURI, Request Streaming. http://www.openipcam.com/files/ONVIF/ONVIF_WG-APG-Application_Programmer's_Guide.pdf
Using Wireshark I believe I see HTTP packets being sent (showing the appropriate requests), and what I believe are appropriate responses. The final GetStreamURI gets a successful response from the camera. Then when I try to call _mp.Play I see a few packets over HTTP and a few TCP packets back back from the camera. After this communication stops.
using System;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LibVLCSharp.Shared;
using LibVLCSharp;
using System.ServiceModel.Channels;
using Lib_vlc_CSharp_Onvif.OnvifDevice;
using System.ServiceModel;
using Lib_vlc_CSharp_Onvif.OnvifMedia;
namespace Lib_vlc_CSharp_Onvif
{
public partial class Form1 : Form
{
public LibVLC _libVLC;
public LibVLCSharp.Shared.MediaPlayer _mp;
public LibVLCSharp.Shared.Media media;
//ToDO... make screen size adjustable
public System.Drawing.Size VidSize;
public System.Drawing.Size FormSize;
public System.Drawing.Point OldVidLoc;
//Create Onvif Media Profiles through service references
OnvifMedia.Media2Client Onvif_media;
OnvifMedia.MediaProfile[] profiles;
//Custom URI variable
UriBuilder deviceUri;
public Form1()
{
InitializeComponent();
//LibVLCSharp Specific
Core.Initialize();
this.KeyPreview = true;
//Just controlling the size. TODO: Imp controls
VidSize = videoView.Size;
FormSize = this.Size;
OldVidLoc = videoView.Location;
//Vlc Specific
//Set up the Vlc Lib and then connect the Form1 media window player to the media player of the library.
//videoVew is vlcsharp item in Form1.
_libVLC = new LibVLC();
_mp = new MediaPlayer(_libVLC);
videoView.MediaPlayer = _mp;
}
private void button1_Click(object sender, EventArgs e)
{
//Set up device to get profiles (Onvif Specific)
//Required a custom URI and binding.
deviceUri = new UriBuilder("Http:/onvif/device_service");
System.ServiceModel.Channels.Binding binding;
HttpTransportBindingElement httpTransport = new HttpTransportBindingElement();
httpTransport.AuthenticationScheme = System.Net.AuthenticationSchemes.Digest;
binding = new CustomBinding(new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8), httpTransport);
//Assign IP Address to device URI. TODO: This eventually will be pulled from user entered value in an text box.
deviceUri.Host = "xxx.xxx.x.x";
DeviceClient Onvif_Device = new DeviceClient(binding, new EndpointAddress(deviceUri.ToString()));
OnvifDevice.Service[] service = Onvif_Device.GetServices(false);
//Check if they contain media and that we have made contact TODO wrap in a try catch block
OnvifDevice.Service xmedia = service.FirstOrDefault(s => s.Namespace == "http://www.onvif.org/ver20/media/wsdl");
if (xmedia != null)
{
Onvif_media = new Media2Client(binding, new EndpointAddress(deviceUri.ToString()));
Onvif_media.ClientCredentials.HttpDigest.ClientCredential.UserName = "admin";
Onvif_media.ClientCredentials.HttpDigest.ClientCredential.Password = "admin";
Onvif_media.ClientCredentials.HttpDigest.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
//Get camera Profiles.
profiles = Onvif_media.GetProfiles(null, null);
if (profiles != null)
{
foreach (var p in profiles)
{
listBox.Items.Add(p.Name);
//Profiles listed in box match profiles setup on camera.
}
}
}
//Eventually add a selection option on the list box.
//listBox.SelectedINdexChanged += OnSelectionChanged
//If we have profiles build a custom URI to past to the vlc boject
if (profiles != null)
{
//Building URI to pass to VLCSharp VideoView Item.
//https://www.onvif.org/ver20/media/wsdl/media.wsdl
//GetSreamUri and define RtspUnicast.
//http://www.openipcam.com/files/ONVIF/ONVIF_WG-APG-Application_Programmer's_Guide.pdf on page 57&58
UriBuilder local_uri = new UriBuilder(Onvif_media.GetStreamUri("RtspUnicast", profiles[0].token));
//ToDO: Build list box to allow user to switch between profiles. Just past main profile for now.
local_uri.Host = deviceUri.Host;
local_uri.Port = deviceUri.Port;
local_uri.Scheme = "rtsp";
//List full URI info.
infoBox.Text = local_uri.Host + local_uri.Port + local_uri.Path;
//Past it to VideoView and start playing video.
_mp.Play(new Media(_libVLC, local_uri.Uri));
}
}
}
}
Update: I believe my issue is the URI I have built requires validation. When I take this URI and put it into a web browser I get a 401 Error. I'm not sure why I don't see this error on wire-shark. I assign the user name and password into URI object but when I check "IsWellFormedURIString" I get an "invalid Port Error."