I'm trying to play the video stream "https://s2.moidom-stream.ru/s/public/0000000087.m3u8" using LibVlc, but I only get a black screen. Other threads work fine, but I need this particular thread.
code used:
using Android.App;
using Android.OS;
using Android.Widget;
using LibVLCSharp.Shared;
using System;
using System.Linq;
using WebCamTst.Helpers;
namespace WebCamTst
{
[Activity(Label = "PanelActivity")]
public class PanelActivity : Activity
{
LibVLCSharp.Platforms.Android.VideoView videoView;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.videopanel);
videoView = FindViewById<LibVLCSharp.Platforms.Android.VideoView>(Resource.Id.videoView1);
}
protected override void OnResume()
{
base.OnResume();
PlayVideo("https://s2.moidom-stream.ru/s/public/0000000087.m3u8");
}
private void PlayVideo(string url)
{
Core.Initialize();
using (var libVLC = new LibVLC())
using (var mPlayer = new MediaPlayer(libVLC) { EnableHardwareDecoding = true })
{
videoView.MediaPlayer = mPlayer;
var _media = new Media(libVLC, url, FromType.FromLocation);
_media.Parse(MediaParseOptions.ParseNetwork);
mPlayer.Play(_media);
}
}
}
}
but it doesn't work.
Please help!
Please start with one of the official android samples.
It doesn't work because Play() is not a synchronous method. It actually starts the libvlc thread in the background.
This means that your libvlc and your player are disposed too early and your video is stopped immediately.
Other remarks:
You can Dispose() your media immediately after having passed into the media player.
Your call to Parse is useless because it's also asynchronous and isn't required (Play calls it anyway)
In addition to cube45's answer, m3u8 are played differently than regular media...
var libVLC = new LibVLC();
var media = new Media(libVLC, "https://s2.moidom-stream.ru/s/public/0000000087.m3u8", FromType.FromLocation);
await media.Parse(MediaParseOptions.ParseNetwork);
var mp = new MediaPlayer(media.SubItems.First());
mp.Play();
Related
I am trying to write a simple player application using LibVLCSharp and I am wondering how to stop the app when player closes. Currently, it just freezes and doesn't stop the app even though I added SetExitHandler callback.
using System;
using System.Threading;
using LibVLCSharp.Shared;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Core.Initialize();
using var libVlc = new LibVLC();
using var mediaPlayer = new MediaPlayer(libVlc);
libVlc.SetExitHandler(() =>
{
Environment.Exit(1);
});
var media = new Media(libVlc, "v4l2:///dev/video0", FromType.FromLocation);
media.AddOption(":v4l2-standard=ALL :live-caching=300");
mediaPlayer.Play(media);
Thread.Sleep(TimeSpan.FromSeconds(10));
}
}
}
Log after I close the window:
[00007fa164004790] gl gl: Initialized libplacebo v2.72.0 (API v72)
[00007fa17400a7c0] main decoder error: buffer deadlock prevented
[00007fa1600429a0] xcb_window window error: X server failure
The following code example from LibVLCSharp GitHub Page shows how to play the video in a console application.
Core.Initialize();
using var libvlc = new LibVLC(enableDebugLogs: true);
using var media = new Media(libvlc, new Uri(#"C:\tmp\big_buck_bunny.mp4"));
using var mediaplayer = new MediaPlayer(media);
mediaplayer.Play();
Console.ReadKey();
Note the use of Console.ReadKey() to wait for the user to press a key before closing the application and subsequently closing the player.
To exit the application automatically when the video ends, you can use MediaPlayer.EndReached event as shown here:
Core.Initialize();
using var libvlc = new LibVLC(enableDebugLogs: true);
using var media = new Media(libvlc, new Uri(#"C:\tmp\big_buck_bunny.mp4"));
using var mediaplayer = new MediaPlayer(media);
mediaplayer.EndReached += (s, e) => Environment.Exit(0);
mediaplayer.Play();
Console.ReadKey();
I'm currently working on Xamarin using Visual Studio to try and build and create an app that reads a bar code and saves the integer it gets from it in a .txt file. I have managed to make the code both read the bar code and save it however i was wondering if there is a way i could save it in a more accessible file, as right now its saving in internal storage and the only way i can reach it is through adb console.
Is there a way for me to perhaps save the integers on a .txt file on my laptop? I'm currently testing it on my physical phone and its connected to my laptop via a USB cable.
Here is my code:
using Android.App;
using Android.Widget;
using Android.OS;
using System;
using Android.Content;
using ZXing.Mobile;
using System.IO;
namespace Scanner
{
[Activity(Label = "Scanner", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
Button buttonScan = FindViewById<Button>(Resource.Id.buttonScan);
TextView scanText = FindViewById<TextView>(Resource.Id.scanText);
var documents = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var BarcodesFile = Path.Combine(documents, "Barcodes.txt");
buttonScan.Click += async (sender, e) =>
{
MobileBarcodeScanner.Initialize(Application);
var scanner = new ZXing.Mobile.MobileBarcodeScanner();
var result = await scanner.Scan();
if (result != null)
File.AppendAllText(BarcodesFile, "Scanned Barcode: " + result.Text);
scanText.Text = File.ReadAllText(BarcodesFile);
};
}
}
}
So if api is an idea. I have not used any api yet for those requirements but when I think about txt I immediately thought about pastebin.
https://pastebin.com/api enter code here
That might be usefull to check out. Goodluck!;)
I am trying to get QRCode reader in unity that works on ios and Android.
Unity Zxing QR code scanner integration
Using above answer I Have added Vuforia (Working perfectly alone). then i also have added Zxing.unity.dll in plugins folder, then added this script to ARCamera in a scene.
using UnityEngine;
using System;
using System.Collections;
using Vuforia;
using System.Threading;
using ZXing;
using ZXing.QrCode;
using ZXing.Common;
[AddComponentMenu("System/VuforiaScanner")]
public class VuforiaScanner : MonoBehaviour
{
private bool cameraInitialized;
private BarcodeReader barCodeReader;
void Start()
{
barCodeReader = new BarcodeReader();
StartCoroutine(InitializeCamera());
}
private IEnumerator InitializeCamera()
{
// Waiting a little seem to avoid the Vuforia's crashes.
yield return new WaitForSeconds(1.25f);
var isFrameFormatSet = CameraDevice.Instance.SetFrameFormat(Image.PIXEL_FORMAT.RGB888, true);
Debug.Log(String.Format("FormatSet : {0}", isFrameFormatSet));
// Force autofocus.
var isAutoFocus = CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_CONTINUOUSAUTO);
if (!isAutoFocus)
{
CameraDevice.Instance.SetFocusMode(CameraDevice.FocusMode.FOCUS_MODE_NORMAL);
}
Debug.Log(String.Format("AutoFocus : {0}", isAutoFocus));
cameraInitialized = true;
}
private void Update()
{
if (cameraInitialized)
{
try
{
var cameraFeed = CameraDevice.Instance.GetCameraImage(Image.PIXEL_FORMAT.RGB888);
if (cameraFeed == null)
{
return;
}
var data = barCodeReader.Decode(cameraFeed.Pixels, cameraFeed.BufferWidth, cameraFeed.BufferHeight, RGBLuminanceSource.BitmapFormat.RGB24);
if (data != null)
{
// QRCode detected.
Debug.Log(data.Text);
}
else
{
Debug.Log("No QR code detected !");
}
}
catch (Exception e)
{
Debug.LogError(e.Message);
}
}
}
}
But it is still not detecting any QRCode. Is there any other way to do QRcode reading and writing except Zxing? or any working sample project you have?
I also tried to implement a QRCode Reader with Vuforia and XZing using almost the same code you used. For me it worked, but it took very very long to detect the QRCode.
When I used a Color32 array instead of cameraFeed.pixels it was much quicker:
GUI.DrawTexture(screenRect, webCamTexture, ScaleMode.ScaleToFit);
try
{
IBarcodeReader barcodeReader = new BarcodeReader();
var result = barcodeReader.Decode(webCamTexture.GetPixels32(),
webCamTexture.width, webCamTexture.height);
if (result != null)
{
Debug.Log("DECODED TEXT FROM QR: " + result.Text);
loadNewPoi(Convert.ToInt32(result.Text));
PlayerPrefs.SetInt("camera_enabled", Convert.ToInt32(false));
webCamTexture.Stop();
}
}
But in this example I was using a WebCamTexture instead of Vuforia.
Unluckily it isn't possible to get a Color32 array with GetPixels32() from the Vuforia camera.
Another option is to use the QRCodes as Image-Targets, but I have a lot of wrong detections doing this.
For me there is no fitting solution for XZing together with Vuforia at the moment.
I'm trying to create a simple test app to take photos in Android, using Xamarin. When I get this app working (or so I hope), i'll use the code in a real app that I'm working on. I'm using the following recipe from Xamarin as my basis:
http://docs.xamarin.com/recipes/android/other_ux/camera_intent/take_a_picture_and_save_using_camera_app/
The major difference is that I need to store images locally, and not on the SD card. I'm able to successfully take a picture (with the Android simulator). I can see the file in the file structure using ADB and can successfully copy and open the file on my PC. However, I'm unsuccessfull in accessing the file in the app, probably due to user rights.
Please note that I was successfull in creating my own .txt files, and reading them back using either System.IO and Java.IO.
Please review the following code. My app crashes when using "System.IO.File.ReadAllText" and gives me "Access to the path "/data/data/CameraAppDemo.CameraAppDemo/files/photo.jpg" is denied.". And whatever I try (absolute, relative paths, uri's), objBitmap is always null.
ADB says that "photo.jpg" has -rwxrwx--- rights, and though I'm not entirely sure, I think that should be more than sufficient
On the other hand, maybe the intent still has a lock on "photo.jpg"? Or something else is going on...
And one final note, I'm using System.IO.File.ReadAllText just for testing purposes. I experimented with stream readers as well, but with the same result. Also, though I believe this step is unnecessary, I enabled "WriteExternalStore" in the Manifest
namespace CameraAppDemo
{
using System;
using System.Collections.Generic;
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.Graphics;
using Android.OS;
using Android.Provider;
using Android.Widget;
using Java.IO;
using Environment = Android.OS.Environment;
using Uri = Android.Net.Uri;
[Activity(Label = "Camera App Demo", MainLauncher = true)]
public class MainActivity : Activity
{
private File _file;
private string _basePath;
private ImageView _imageView;
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
var objBitmap = BitmapFactory.DecodeFile(_file.AbsolutePath) ;
Console.WriteLine ("objBitmap = null : " + (objBitmap == null).ToString ());
var strOutput = System.IO.File.ReadAllText (FileManager.BasePath + "/photo.jpg");
Console.WriteLine (strOutput);
}
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
SetContentView(Resource.Layout.Main);
FileManager.SetupFolderStructure();
if (IsThereAnAppToTakePictures())
{
Button button = FindViewById<Button>(Resource.Id.myButton);
_imageView = FindViewById<ImageView>(Resource.Id.imageView1);
button.Click += TakeAPicture;
}
}
private bool IsThereAnAppToTakePictures()
{
Intent intent = new Intent(MediaStore.ActionImageCapture);
IList<ResolveInfo> availableActivities = PackageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly);
return availableActivities != null && availableActivities.Count > 0;
}
private void TakeAPicture(object sender, EventArgs eventArgs)
{
System.IO.Directory.Delete (FileManager.BasePath, true);
_basePath = FileManager.BasePath;
_file = new Java.IO.File (_basePath, "photo.jpg");
Intent intent = new Intent(MediaStore.ActionImageCapture);
intent.PutExtra(MediaStore.ExtraOutput, Uri.FromFile(_file));
StartActivityForResult(intent, 0);
}
}
}
//Part of the FileManager class:
using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Android.Graphics;
namespace CameraAppDemo
{
public class FileManager
{
public static string BasePath {
get {
var libraryPath = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
if (Directory.Exists (libraryPath) == false) {
Directory.CreateDirectory (libraryPath);
}
return libraryPath;
}
}
}
}
==== Edit ====
It seems that I'm simply not able to read the file. As an ex-webdeveloper, I'm fairly new to programming for mobile, let alone the combo of C# and Java and I'm still learning a lot.
Anyway, I added the following lines:
Console.WriteLine("Setting file :" + _file.SetReadable (true));
Console.WriteLine("Can read :" + _file.CanRead());
Both cases return False. I can't read the file, and I am unable to give read access.
So, any ideas? Is this by design? Can I tell the Intent for taking images to give me read access, or is there another workaround?
If everything fails, I'm hoping to workaround the problem by saving to the SD card first and then copying the file to the local filesystem. But that's something I rather would not do; I can't guarantee that the end users have an SD card, and the pictures should not be deleted by accident.
Monotouch 5.0.2.
Running the simple code below I get this in the output panel:
objc[20283]: Object 0x9c08110 of class __NSCFString autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug
objc[20283]: Object 0x9c07840 of class __NSCFData autoreleased with no pool in place - just leaking - break on objc_autoreleaseNoPool() to debug
Which NSStrings are leaking here and why? It seems to be enough to just create a new Uri() and a new WebClient() objetc. The event handler doesn't even have to be attached.
using System;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Net;
using System.IO;
namespace DownloadTest
{
[Register ("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate
{
UIWindow window;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
window = new UIWindow (UIScreen.MainScreen.Bounds);
UIButton btn = UIButton.FromType (UIButtonType.RoundedRect);
btn.Frame = new System.Drawing.RectangleF (40, 40, 100, 30);
btn.TouchUpInside += delegate {
// These two lines seem to caus the leak.
Uri uri = new Uri ("http://silverlightinaction.com/video3.wmv");
WebClient webClient = new WebClient ();
// This line does not matter, the info about the leaking NSString alsp appears without an event being attached.
webClient.OpenReadAsync (uri);
};
window.AddSubview (btn);
window.MakeKeyAndVisible ();
return true;
}
void HandleWebClientOpenReadCompleted (object sender, OpenReadCompletedEventArgs e)
{
using (var pool = new NSAutoreleasePool())
{
using (Stream stream = e.Result)
using (FileStream fileStream = File.OpenWrite(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "download.bin")))
{
stream.CopyTo (fileStream, 30000);
stream.Close ();
fileStream.Close ();
}
}
}
}
}
This is a MonoTouch bug. WebClient uses Thread which does not automagically creates an NSAutoreleasePool around the code being executed (e.g. like you did in your delegate). That can cause some leaks - just like you're seeing with the warning messages.
Note that using (threads from) ThreadPool is already ensuring that an NSAutoreleasePool covers the thread's execution.
I created a new class deriving from WebClient and overrode the "OnDownloadedCompleted" and created my own pool within a using block. This seemed to get rid of the debug messages, not sure if it's the perfect fix though.
using(var a = new MonoTouch.Foundation.NSAutoreleasePool())
{
base.OnDownloadDataCompleted (args);
}