MediaElement.Stop doesn't work when playing a live streaming source in windows store app - mediaelement

I want to make a Windows Store App play a live-streaming source. The source plays fine but I can't stop the source from playing once it has begun. When I call Stop() on the instance of Windows.UI.Xaml.Controls.MediaElement nothing happens.
Below is my code:
public MainPage(){
this.InitializeComponent();
this.mediaplayer.AutoPlay = true;
this.mediaplayer.Source = new Uri("mms://somedomain/mylive");
}
...
void StopButton_Click(object sender, RoutedEventArgs e)
{
//I can reach here when I set a breakpoint
this.mediaplayer.Stop();
}

I just came across the same problem... and was able to solve it by calling MediaElement.Pause() instead.

Related

Xamarin iOS Bluetooth peripheral scanning never sees any peripherals

I am trying to create a Xamarin.Forms app that will run on both iOS and Android. Eventually I need instances of the app to communicate with each other via Bluetooth, but I'm stuck on getting the iOS side to do anything with Bluetooth. I originally tried to work with Plugin.BluetoothLE and Plugin.BLE, but after a week and a half I was not able to get advertising or scanning to work on either OS with either plugin, so I decided to try implementing simple Bluetooth interaction using the .NET wrappers of the platform APIs, which at least are well documented. I did get scanning to work fine on the Android side. With iOS, though, what I have right now builds just fine, and runs on my iPad without errors, but the DiscoveredPeripheral handler is never called, even though the iPad is just a few inches from the Android tablet and presumably should be able to see the same devices. I have verified this by setting a breakpoint in that method, which is never reached; and when I open the Bluetooth Settings on the iPad to make it discoverable the app version on the Android tablet can see it, so I don't think it's an iPad hardware issue.
It seems obvious that there is simply some part of the process I don't know to do, but it's not obvious (to me) where else to look to find out what it is. Here is the code for the class that interacts with the CBCentralManager (as far as I understand from what I've read, this should include everything necessary to return a list of peripherals):
using MyBluetoothApp.Shared; // for the interfaces and constants
using CoreBluetooth;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xamarin.Forms;
[assembly: Dependency(typeof(MyBluetoothApp.iOS.PeripheralScanner))]
namespace MyBluetoothApp.iOS
{
public class PeripheralScanner : IPeripheralScanner
{
private readonly CBCentralManager manager;
private List<IPeripheral> foundPeripherals;
public PeripheralScanner()
{
this.foundPeripherals = new List<IPeripheral>();
this.manager = new CBCentralManager();
this.manager.DiscoveredPeripheral += this.DiscoveredPeripheral;
this.manager.UpdatedState += this.UpdatedState;
}
public async Task<List<IPeripheral>> ScanForService(string serviceUuid)
{
return await this.ScanForService(serviceUuid, BluetoothConstants.DEFAULT_SCAN_TIMEOUT);
}
public async Task<List<IPeripheral>> ScanForService(string serviceUuid, int duration)
{
CBUUID uuid = CBUUID.FromString(serviceUuid);
//this.manager.ScanForPeripherals(uuid);
this.manager.ScanForPeripherals((CBUUID)null); // For now I'd be happy to see ANY peripherals
await Task.Delay(duration);
this.manager.StopScan();
return this.foundPeripherals;
}
private void DiscoveredPeripheral(object sender, CBDiscoveredPeripheralEventArgs args)
{
this.foundPeripherals.Add(new CPeripheral(args.Peripheral));
}
private void UpdatedState(object sender, EventArgs args)
{
CBCentralManagerState state = ((CBCentralManager)sender).State;
if (CBCentralManagerState.PoweredOn != state)
{
throw new Exception(state.ToString());
}
}
}
}
Can anyone point me in the direction of understanding what I'm missing?
EDIT: O...K, I've discovered quite by accident that if I do this in the shared code:
IPeripheralScanner scanner = DependencyService.Get<IPeripheralScanner>();
List<IPeripheral> foundPeripherals = await scanner.ScanForService(BluetoothConstants.VITL_SERVICE_UUID);
twice in a row, it works the second time. I feel both more hopeful and much more confused.
The underlying problem was that in the first instantiation of PeripheralScanner, ScanForService was being called before State was updated. I tried many ways of waiting for that event to be raised so I could be sure the state was PoweredOn, but nothing seemed to work; polling loops simply never reached the desired state, but if I threw an Exception in the UpdatedState handler it was thrown within milliseconds of launch and the state at that time was always PoweredOn. (Breakpoints in that handler caused the debugging to freeze with the output Resolved pending breakpoint, which not even the VS team seems to be able to explain).
Reading some of the Apple developer blogs I found that this situation is most often avoided by having the desired action occur within the UpdatedState handler. It finally soaked into my thick head that I was never seeing any effects from that handler running because the event was being raised and handled on a different thread. I really need to pass the service UUID to the scanning logic, and to interact with a generic List that I can return from ScanForService, so just moving it all to the handler didn't seem like a promising direction. So I created a singleton for flagging the state:
internal sealed class ManagerState // .NET makes singletons easy - Lazy<T> FTW
{
private static readonly Lazy<ManagerState> lazy = new Lazy<ManagerState>(() => new ManagerState());
internal static ManagerState Instance { get { return ManagerState.lazy.Value; } }
internal bool IsPoweredOn { get; set; }
private ManagerState()
{
this.IsPoweredOn = false;
}
}
and update it in the handler:
private void updatedState(object sender, EventArgs args)
{
ManagerState.Instance.IsPoweredOn = CBCentralManagerState.PoweredOn == ((CBCentralManager) sender).State;
}
then poll that at the beginning of ScanForService (in a separate thread each time because, again, I will not see the updates in my base thread):
while (false == await Task.Run(() => ManagerState.Instance.IsPoweredOn)) { }
I'm not at all sure this is the best solution, but it does work, at least in my case. I guess I could move the logic to the handler and create a fancier singleton class for moving all the state back and forth, but that doesn't feel as good to me.

smeared/corrupted capture of RTSP streams

i've using emgu cv 2.4.10 to create a RTSP stream viewer that will eventually be used with IP cameras. as i don't have the camera/s as yet, i'm testing using VLC (the windows GUI) to create the stream from a video file.
:sout=#duplicate{dst=rtp{sdp=rtsp://:8554/stream},dst=display} :sout-all :sout-keep
i'm doing this all testing on localhost.
here's my capture code:
private void ProcessFrame(object sender, EventArgs arg) {
try {
frame = _capture.QueryFrame();
pictureBox1.Image = frame.ToBitmap();
}
catch (Exception ex) {
MessageBox.Show(ex.Message.ToString());
}
}
this method is called using this eventhandler:
_capture = new Capture("rtsp://localhost:8554/stream");
Application.Idle += ProcessFrame;
_capture.Start();
the capture is corrupted with random occurrences of "smearing" that always occurs in the lower portion of the frame:
i've seen several others online have reported this problem as recently as last december but no solution has been found or that would work for me:
http://workingwithcomputervision.blogspot.co.uk/2012/06/issues-with-opencv-and-rtsp.html
EMGU QueryFrame returns "streaky" Image over RTSP
http://www.emgu.com/forum/viewtopic.php?f=7&t=4882&p=10110&hilit=rtsp#p10069
to narrow down the problem, i've run ffplay from the commandline and the capture is perfect. i've run another instance of VLC to capture the RTSP stream and it displays perfectly. so this is clearly a problem in open cv/emgu cv.
on a whim, i changed VLC to stream using HTTP.
:sout=#duplicate{dst=http{mux=ffmpeg{mux=flv},dst=:8080/stream},dst=display} :sout-all :sout-keep
this displays fine in my code, but at a noticeably lower frame rate that won't work for my application. i'd really appreciate any tips to fixing this problem. thanks.
I don't know if you solved your problem but i suggest you not to make your process in application.idle event. Instead, use thread. Create another thread and make your proccess in it. Example c# code:
Thread t = new Thread(new ThreadStart(()=>{ while(true) {frame = _capture.QueryFrame();
pictureBox1.Image = frame.ToBitmap();}})); t.IsBackGround = true; t.Start();

JavaFX WebEngine timeout handling

I'm wondering if anyone has figured out a way to properly handle timeouts in the JavaFX 8 (jdk 1.8.0_31) WebView. The problem is the following:
Consider you have an instance of WebView and you tell it to load a specific URL. Furthermore, you want to process the document once it's loaded, so you attach a listener to the stateProperty of the LoadWorker of the WebEngine powering the web view. However, a certain website times out during loading, which causes the stateProperty to transition into Worker.State.RUNNING and remain stuck there.
The web engine is then completely stuck. I want to implement a system that detects a timeout and cancels the load. To that end, I was thinking of adding a listener to the progressProperty and using some form of Timer. The idea is the following:
We start a load request on the web view. A timeout timer starts running immediately. On every progress update, the timer is reset. If the progress reaches 100%, the timer is invalidated and stopped. However, if the timer finishes (because there are no progress updates in a certain time frame we assume a time out), the load request is cancelled and an error is thrown.
Does anyone know the best way to implement this?
Kind regards
UPDATE
I've produced a code snippet with behavior described in the question. The only thing still troubling me is that I can't cancel the LoadWorker: calling LoadWorker#cancel hangs (the function never returns).
public class TimeOutWebEngine implements Runnable{
private final WebEngine engine = new WebEngine();
private ScheduledExecutorService exec;
private ScheduledFuture<?> future;
private long timeOutPeriod;
private TimeUnit timeOutTimeUnit;
public TimeOutWebEngine() {
engine.getLoadWorker().progressProperty().addListener((ObservableValue<? extends Number> observable, Number oldValue, Number newValue) -> {
if (future != null) future.cancel(false);
if (newValue.doubleValue() < 1.0) scheduleTimer();
else cleanUp();
});
}
public void load(String s, long timeOutPeriod, TimeUnit timeOutTimeUnit){
this.timeOutPeriod = timeOutPeriod;
this.timeOutTimeUnit = timeOutTimeUnit;
exec = Executors.newSingleThreadScheduledExecutor();
engine.load(s);
}
private void scheduleTimer(){
future = exec.schedule(TimeOutWebEngine.this, timeOutPeriod, timeOutTimeUnit);
}
private void cleanUp(){
future = null;
exec.shutdownNow();
}
#Override
public void run() {
System.err.println("TIMED OUT");
// This function call stalls...
// engine.getLoadWorker().cancel();
cleanUp();
}
}
I don't think that you can handle timeouts properly now. Looks at this method. As you can see it has hardcoded value for setReadTimeout method. Is it mean that SocketTimeoutException exception will be raised after one hour of loading site. And state will be changed to FAILED only after that event.
So, you have only one way now: try to hack this problem use Timers as you described above.
P.S.
Try to create issue in JavaFX issue tracker. May be anyone fixed it after 5 years...
I have the same problem and used a simple PauseTransition. Same behavior, not so complicated. =)

timeout when connecting if streaming source is unavailable

I am trying to figure out a way of timing out a connection to my streaming http source if it becomes unavailable. I do have checks in place which verify if I'm connected to the internet, either WIFI or Data. I did find some example using a Handler and I got to the point where it actually times out, but it doesn't stop the actual service which is in a different class. This causes a ANR in emulator. Any suggestions or different approaches on how this issue can be handled? Thank you for your time !
public Runnable mUpdateTimeTask = new Runnable() {
public void run() {
Toast.makeText(MainActivity.this, "Running Thread", Toast.LENGTH_LONG).show();
if (RadioService.isMusicActive()==false){
stopPlaying();
}
}
};
private void stopPlaying() {
buttonPlay.setEnabled(true);
buttonStopPlay.setEnabled(false);
stopService(new Intent(this, RadioService.class));//
}
if (v == buttonPlay) {
startPlaying();
mHandler.postDelayed(mUpdateTimeTask, 5000);}
After playing more with it and some minor modifications, this code worked the way I expected. Maybe it will help somebody else down the road.

Help - Blackberrry BrowserField2, Media Player and Threads

In my application, I have BrowserField2 added to MainScreen and Media player based on Streaming media - Start to finish. I am trying to open media player from Browser using extended javascript. My plan is that when user clicks on some links in web page, I call extended javascript function with some parameters like url of the video to stream. This function in turn pushes media player screen with the url passed. Media player works very well and streams video when used stand alone. But it doesn't play video when coupled with BrowserField using extended javascript.
I suspect that the issue is synchronizing with Event thread or related to threading. I push screen containing media player using runnable. The screen is displayed. But when I click on play button (which starts some threads to fetch video and play it), nothing happens and my application freezes. I am not able to figure out exact problem. Will appreciate if someone can pin point the problem.
Thank you.
Some relevant code listings as below:
public void extendJavaScript() throws Exception
{
ScriptableFunction playVideo = new ScriptableFunction()
{
public Object invoke(Object thiz, Object[] args) throws Exception
{
openMediaPlayer(args[0].toString());
return Boolean.FALSE;
}
};
_bf2.extendScriptEngine("bb.playVideo", playVideo);
}
private void openMediaPlayer(final String url){
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
PlayerScreen _playerScreen = new PlayerScreen(url + ";deviceside=true");
UiApplication.getUiApplication().pushScreen(_playerScreen);
}
});
}
Never mind. Got it resolved. It turned out that the video that I was trying to access from the web page was in incompatible format and hence throwing an error and freezing the media player.

Resources