74 lines
2.5 KiB
C#
74 lines
2.5 KiB
C#
|
using System;
|
|||
|
using System.IO;
|
|||
|
using System.Net;
|
|||
|
using System.Threading;
|
|||
|
using System.Threading.Tasks;
|
|||
|
|
|||
|
namespace IPCamLib.Base
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Abstract base class for IP cameras reading an HTTP stream.
|
|||
|
/// </summary>
|
|||
|
public abstract class BaseHTTPStreamCamera : ICamera
|
|||
|
{
|
|||
|
private readonly Uri streamUri;
|
|||
|
|
|||
|
|
|||
|
/// <param name="streamUri">The URI to the camera stream.
|
|||
|
/// Can include basic credentials in the standard 'username:password@' format.</param>
|
|||
|
protected BaseHTTPStreamCamera(Uri streamUri)
|
|||
|
{
|
|||
|
this.streamUri = streamUri;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <inheritdoc />
|
|||
|
public async Task Fetch(ICameraObserver observer, CancellationToken cancellationToken)
|
|||
|
{
|
|||
|
var request = WebRequest.CreateHttp(streamUri);
|
|||
|
|
|||
|
if (!string.IsNullOrEmpty(streamUri.UserInfo))
|
|||
|
{
|
|||
|
var parts = streamUri.UserInfo.Split(':');
|
|||
|
request.Credentials = new NetworkCredential(parts[0], parts.Length > 1 ? parts[1] : "");
|
|||
|
}
|
|||
|
|
|||
|
request.ReadWriteTimeout = (int)TimeSpan.FromMinutes(1).TotalMilliseconds;
|
|||
|
try
|
|||
|
{
|
|||
|
HttpWebResponse response;
|
|||
|
|
|||
|
using (cancellationToken.Register(() => request.Abort(), false))
|
|||
|
{
|
|||
|
response = (HttpWebResponse)await request.GetResponseAsync();
|
|||
|
cancellationToken.ThrowIfCancellationRequested();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (response.StatusCode != HttpStatusCode.OK)
|
|||
|
throw new WebException(response.StatusDescription);
|
|||
|
|
|||
|
|
|||
|
using var responseStream = response.GetResponseStream();
|
|||
|
await ReadFrames(observer, responseStream, cancellationToken);
|
|||
|
}
|
|||
|
catch (TaskCanceledException)
|
|||
|
{
|
|||
|
}
|
|||
|
finally
|
|||
|
{
|
|||
|
request.Abort();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// <summary>
|
|||
|
/// Implement in concrete descendants to continuously read frames from the HTTP stream.
|
|||
|
/// </summary>
|
|||
|
/// <param name="observer">The observer implementation passed to Fetch which should receive the decoded frames.</param>
|
|||
|
/// <param name="stream">The HTTP response stream.</param>
|
|||
|
/// <param name="cancellationToken">Stop reading frames when this token is cancelled.</param>
|
|||
|
protected abstract Task ReadFrames(ICameraObserver observer, Stream stream, CancellationToken cancellationToken);
|
|||
|
}
|
|||
|
}
|