HttpWebRequest for ShoutCast on Windows Phone7 - httpwebrequest

I tring to stream shoutcast stream in my window phone 7 app
I start an async HttpWebRequest like this
//Init Request
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://ACommonoShoutCastUrl:8000");
myHttpWebRequest.Headers["Icy-MetaData"] = "1";
myHttpWebRequest.UserAgent = "WinampMPEG/5.09";
myHttpWebRequest.AllowReadStreamBuffering = true;
//Call
// Create an instance of the RequestState and assign the previous myHttpWebRequest object to its request field.
RequestState myRequestState = new RequestState();
myRequestState.request = myHttpWebRequest;
// Start the asynchronous request.
IAsyncResult result = (IAsyncResult)myHttpWebRequest.BeginGetResponse(new AsyncCallback(RespCallBack), myRequestState);
The problem is that the CallBack->RespCallBack is never called...
This code worked for me normally in other environments but not on the phone...
I tired also to use WebClient that seems to stream data,
the problem in this case is that it never call the end OpenReadCompleted because of endelss shoutcast stream
Thanks for support
any help would be appreciated

SHOUTcast implements its own protocol so you can't directly access and play it. You can use DownloadStringAsync (you will need a WebClient instance for this) to download the PLS file and read the URL with the help of RegEx.
When you get the URL, you can read the raw audio data by implementing MediaStreamSource and then use a MediaElement to play the contents.
You can find a sample implementation of MediaStreamSource here.

I just put the following on a page and the callback was called in repsonse to the button click. (I set a break point on the throw statement and it was hit.)
private HttpWebRequest myHttpWebRequest;
public MainPage()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//Init Request
//The following URI was chosen at random
myHttpWebRequest = (HttpWebRequest)WebRequest.Create("http://yp.shoutcast.com/sbin/tunein-station.pls?id=1377200");
myHttpWebRequest.Headers["Icy-MetaData"] = "1";
myHttpWebRequest.UserAgent = "WinampMPEG/5.09";
myHttpWebRequest.AllowReadStreamBuffering = true;
// Start the asynchronous request.
myHttpWebRequest.BeginGetResponse(RespCallBack, myHttpWebRequest);
}
private void RespCallBack(IAsyncResult ar)
{
throw new NotImplementedException();
}

I am trying to implement the Shoutcast streaming to my MediaElement via my own MediaStreamSource class. I have a loop in which I am downloading data from Shoutcast server and then set the data to the MediaStreamSource class - this works not perfectly for yet, but I discovered another more important issue. I made a test. I have downloaded a stream to a mp3 (stream is in mp3) file, then put this file to my application and set it to my MediaStreamSource. Here's the code for this:
private void Button_Click(object sender, RoutedEventArgs e)
{
var assembly = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
var res = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("Demo1.sample.mp3");
byte[] data = new byte[res.Length];
res.Read(data, 0, data.Length);
MemoryStream ms = new MemoryStream();
ms.Write(data, 0, data.Length);
ms.Position = 0;
ShoutcastMediaStreamSource ss = new ShoutcastMediaStreamSource(ms);
player.SetSource(ss);
}
my ShoutcastMediaStreamSource based on MenagedMediaHelpers. So when I put this stream to my ShoutcastMediaStreamSource in debbuger I can see that the method OpenMediaAsync() is called properly, then the GetSampleAsync() is called in a loop by MediaElement, here also everything is fine, but when I run this app there is no sound ! Neither on the emulator nor on the device, and there are no errors. I think, the GetSampleAsync() method is running too fast, bacause for the file (and also stream) duration is about 30 sec., and this app ends after ca. 10 sec. But nevertheless, there should be a sound (scratch).
BUT whats suprising - this app works in Silverlight as Web Page ! The music is playing. I am confused.
Here is allso an app
http://timheuer.com/blog/archive/2010/08/16/download-and-store-media-for-playback-in-windows-phone-7-using-mediastreamsource.aspx
and there is a comment:
If Mp3MediaStreamSource is set as a
source for MediaElement then
MediaElement doesn't play that file
and donesn't show any error in Windows
phone 7 sdk RTM version. In previsios
version it was working but it's not
working with Windows phone 7 sdk final
release.

The callback gets called if you disable read stream buffering:
webRequest.AllowReadStreamBuffering = false;

Related

Receive video from a source, preprocess and stream live preview to the client | ASP.NET Core

I need to implement a server that gets video from some source for example IPCamera
then preprocess the image and streams it down to the client (if requested).
I already implemented the part with processing, it accepts a single frame (bitmap) and returns the processed bitmap. What I'm struggling with is the part of receiving video from the camera and then streaming it to the client.
What would be the right way to do it?
What libraries do you recommend using?
I use ASP.NET Core for the Server part, and Angular/React for the Client.
I tried to implement gRPC but a gRPC-Web client for typescript seems to be a pain in the ass.
Edit: 02.08.2022
What I achieved so far:
I figured out how to receive image output from the camera.
I found out RTSP Client for C#. Source: C# RTSP Client for .NET
It works pretty fine. I can receive output with small to no delay, and I use my phone to emulate the RTSP camera/server.
So RTSP Client receives raw frames (in my case H.264 IFrame/PFrame). The problem is I need to decode those frames preferably to Bitmap because I use YoloV4 ONXX Model for object detection.
Here's how I set up YoloV4 with ML.Net. Source: Machine Learning with ML.NET – Object detection with YOLO
To decode raw frames I use FFMpeg (sadly I didn't find any working FFMpeg package that would work with .NET Core, I tried AForge.Net, Accord but in both packages, the FFMPEG namespace is missing after installing for some reason, so I dug through Github and took this project FrameDecoderCore). It's not the best solution but it works. Now I can receive the output and decode it to Bitmap.
Now I'm facing three major issues:
How to detect objects without delaying the process of receiving camera output. And how to properly build an onnx model just to predict without training.
How to convert processed bitmaps back to a video stream. I also need to be able to save part of it as a video file on disk (video format doesn't matter) whenever the desired object was detected.
How to stream processed or unprocessed output to the client when the client wants to see the camera output. - I'm thinking of gRPC here and sending bitmaps and then displaying it on HTML Canvas.
Here's how my service looks at the moment:
public class CCTVService : BackgroundService
{
private readonly RtspClient _rtspClient;
private readonly ILogger<CCTVService> _logger;
private const int streamWidth = 480;
private const int streamHeight = 640;
private static readonly FrameDecoder FrameDecoder = new FrameDecoder();
private static readonly FrameTransformer FrameTransformer = new FrameTransformer(streamWidth, streamHeight);
public CCTVService(ILogger<CCTVService> logger)
{
_logger = logger;
_rtspClient = new RtspClient(new ConnectionParameters(new Uri("rtsp://192.168.0.99:5540/ch0")));
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using (_rtspClient)
{
try
{
await _rtspClient.ConnectAsync(stoppingToken);
_logger.LogInformation("Connecting to RTSP");
}
catch(RtspClientException clientException)
{
_logger.LogError(clientException.Message);
//throw;
}
_rtspClient.FrameReceived += (obj, rawFrame) =>
{
if (rawFrame is not RawVideoFrame rawVideoFrame)
return;
var decodedFrame = FrameDecoder.TryDecode(rawVideoFrame);
if (decodedFrame == null)
return;
using var bitmap = FrameTransformer.TransformToBitmap(decodedFrame);
_logger.LogInformation($"Timestamp: {new DateTimeOffset(rawFrame.Timestamp).ToUnixTimeSeconds()} Timestamp-diff: {new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds() - new DateTimeOffset(rawFrame.Timestamp).ToUnixTimeSeconds()}");
// save bitmaps | Test
//var t = new Thread(() =>
//{
// using var bitmap = FrameTransformer.TransformToBitmap(decodedFrame);
// var name = "./test/" + new DateTimeOffset(rawFrame.Timestamp).ToUnixTimeMilliseconds().ToString() + " - " + new Random().NextInt64().ToString() + ".bmp";
// bitmap.Save(name);
//});
//t.Priority = ThreadPriority.Highest;
//t.Start();
};
try
{
await _rtspClient.ReceiveAsync(stoppingToken);
}
catch
{
// swallow
}
}
}
}
So I can't really help with part 2 and 3 of your question but with ML.NET, one of the things you might consider is batching the predictions. Instead of preprocessing them one at a time, you could collect 10-20 frames and then instead of using PredictionEngine, use the Transform passing it in an IDataView instead of a Bitmap.
Here are some samples of using ONNX models inside applications. The WPF sample might be of interest since it uses a webcam to capture inputs. I believe it uses the native Windows APIs, so different than how you'd do it for web but it might be worth looking at anyway.
https://github.com/dotnet/machinelearning-samples/tree/main/samples/csharp/end-to-end-apps/ObjectDetection-Onnx

How to take an xml response received from a web service and make it a datasource

I'm making a windows 8.1 phone app and I have a listbox that I'm trying to populate with data. My problem is that I am using a web service and I finally figured out how to get the data but it is in an xml format and I don't know how to make that into the itemssource for the listbox. I'm sorry if this is a stupid question but this is my first time doing this and I can't seem to find any information online.
Below is a very simple example which requests an XML document from a URI over HTTPS.
It downloads the XML asynchronously as a string and then uses XDocument.Parse() to load it.
private void button2_Click(object sender, RoutedEventArgs e)
{
WebClient wc = new WebClient();
wc.DownloadStringCompleted += HttpsCompleted;
wc.DownloadStringAsync(new Uri("https://domain/path/file.xml"));
}
private void HttpsCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
XDocument xdoc = XDocument.Parse(e.Result, LoadOptions.None);
this.textBox1.Text = xdoc.FirstNode.ToString();
}
}
Have a look over this thread.
Hope it helps!
If the data coming back is always the same type you can always use XmlSerializer to deserialize the data the data to a class you can bind to. If you copy a sample of the data coming back to the clip board you can use paste xml as classes to paste the class you can deserialize into
Deserialize XML in a WP8 Application

How to cancel HttpClient GET Web request

Is it possible to cancel HttpClient GET web request in Windows 8. I am looking for a solution to cancel my web request if the user press back key from the page. In my app i am using a static class for creating web request.
Alos i am using MVVM Light, and static viewmodels inside the app.
In the current situation, even if the user press the back button,
the vm stay alive and the call back reaches and executes in the VM.
So i am looking for a solution to cancel the request on back press.
Try this
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
await HttpGetRequest();
}
public CancellationTokenSource cts = new CancellationTokenSource();
private async Task HttpGetRequest()
{
try
{
DateTime now = DateTime.Now;
var httpClient = new HttpClient();
var message = new HttpRequestMessage(HttpMethod.Get, "https://itunes.apple.com/us/rss/toppaidapplications/limit=400/genre=6000/json");
var response = await httpClient.SendAsync(message, cts.Token);
System.Diagnostics.Debug.WriteLine("HTTP Get request completed. Time taken : " + (DateTime.Now - now).TotalSeconds + " seconds.");
}
catch (TaskCanceledException)
{
System.Diagnostics.Debug.WriteLine("HTTP Get request canceled.");
}
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
cts.Cancel();
}
The answer by #Farhan Ghumra is correct. Since we have moved to .Net 6 just like to add the following to the answer.
After you’re completely done with the CancellationTokenSource, dispose it directly E.g use cts.Dispose() (because you’ll most likely be using this with UI code and needing to share it with click event handling code, which means you wouldn’t be able to dispose of it with a using block)
More information can be found here.

Trouble Attaching File Programmatically to Email in Windows Metro App C#/XAML using Share Charm

I'm simply trying to attach a file named Document.pdf in the DocumentsLibrary to an email using the Share Charm. My code below works perfectly on the Local Machine:
private async void OnDataRequestedFiles(DataTransferManager sender, DataRequestedEventArgs e)
{
List<IStorageItem> shares = new List<IStorageItem>();
StorageFile filetoShare = await Windows.Storage.KnownFolders.DocumentsLibrary.GetFileAsync("Document.pdf");
if (filetoShare != null)
{
shares.Add(filetoShare);
filetoShare = null;
}
if (shares != null)
{
DataPackage requestData = e.Request.Data;
requestData.Properties.Title = "Title";
requestData.Properties.Description = "Description"; // The description is optional.
requestData.SetStorageItems(shares);
shares = null;
}
else
{
e.Request.FailWithDisplayText("File not Found.");
}
}
But when I run the exact same code on a Windows Surface Tablet, I get the dreaded "There's nothing to share right now." on the right in the Charms flyout area.
Here's a little more background to help:
I'm not looking to use a File Picker...I know the exact file I'm looking for
I've enabled the Documents Library Capability in the manifest
I've added a File Type Association for pdf in the manifest
and yes, the file does exist and is in the Documents Library
an email account is properly setup in the Mail App on the surface
I can successfully send text emails from the Tablet...just not emails with attachments
Like I said, this works on my Win 8 Development Machine as expected...just not on the Surface. I'm wondering if the Surface has different file or folder permissions?
Thanks for the help...this is driving me CRAZY
I finally figured it out - the problem was that my Event Handler was async (so that I could use await to set the StorageFile variable).
I solved it by setting the StorageFile variable earlier in my code so that it was already available when the Event Handler was called.
I still have no idea why it worked on my development machine, but no on the WinRT surface...
The handler can be an async method. In this case, it is critical to use DataTransferManager. Please refer to the MSDN page specifically for this scenario. For your convenience, the code from the page is copied to here:
private void RegisterForShare()
{
DataTransferManager dataTransferManager = DataTransferManager.GetForCurrentView();
dataTransferManager.DataRequested += new TypedEventHandler<DataTransferManager,
DataRequestedEventArgs>(this.ShareStorageItemsHandler);
}
private async void ShareStorageItemsHandler(DataTransferManager sender,
DataRequestedEventArgs e)
{
DataRequest request = e.Request;
request.Data.Properties.Title = "Share StorageItems Example";
request.Data.Properties.Description = "Demonstrates how to share files.";
// Because we are making async calls in the DataRequested event handler,
// we need to get the deferral first.
DataRequestDeferral deferral = request.GetDeferral();
// Make sure we always call Complete on the deferral.
try
{
StorageFile logoFile =
await Package.Current.InstalledLocation.GetFileAsync("Assets\\Logo.png");
List<IStorageItem> storageItems = new List<IStorageItem>();
storageItems.Add(logoFile);
request.Data.SetStorageItems(storageItems);
}
finally
{
deferral.Complete();
}
}
It is critical to place the following statement before any async method is called:
DataTransferManager dataTransferManager = DataTransferManager.GetForCurrentView();
You only have half a second to get the whole job done (getting the file, attaching...etc.). If the half-second deadline occurs you'll get this "driving crazy" message. Consider implementing some resumable logic and replace the message with "the attachment is being prepared please try again in a few seconds" (or else).
Your WinRT device might be just slower than your development machine. The latter just does the job before the deadline...

Downloading video files with a larger size

I have developed a movie website and I have it hosted in a private webserver.
I had also developed a windows app through which I wanna download my movies from my site.
The movies are of file size 400mb to 700mb. I tried using WebClient but it doesn't works for large file sizes.
private void btnDownload_Click(object sender, EventArgs e)
{
try
{
WebClient wb = new WebClient();
wb.Credentials = CredentialCache.DefaultCredentials;
wb.Headers.Add(HttpRequestHeader.UserAgent, "Loading");
wb.DownloadFileAsync(new Uri("http://www.mysite.com/2D MOVIES/ColdSteel.mkv"), "D:\\ren.mkv");
wb.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wb_DownloadProgressChanged);
wb.DownloadFileCompleted += new AsyncCompletedEventHandler(wb_DownloadFileCompleted);
}
catch (WebException ex)
{
MessageBox.Show(ex.InnerException.ToString());
}
}
I'm a newbie so please guide me with code snippets in what way I can make it happen. I need the whole movie to be downloaded.
Anyone know how to implement this?
Did you see this? I think it can be good and it is open source.