I am trying to use the Windows.Graphics.Capture namespace to capture screenshot from a comaptible application.
I based my code on the official examples here: MS sample screenshot code
The code in question is the following:
private async void btnCapture_Click(object sender, EventArgs e)
{
process = Process.GetProcesses().Where(p => p.ProcessName == "xxxxxxxxxxx").Single();
hwnd = process.MainWindowHandle;
GraphicsCaptureItem item = CaptureHelper.CreateItemForWindow(hwnd);
device = Direct3D11Helper.CreateDevice();
capture = new BasicCapture(device, item);
framePool = Direct3D11CaptureFramePool.Create(device, DirectXPixelFormat.B8G8R8A8UIntNormalized, 1, item.Size);
session = framePool.CreateCaptureSession(item);
session.StartCapture();
using (frame = framePool.TryGetNextFrame())
{
var bmp = await SoftwareBitmap.CreateCopyFromSurfaceAsync(frame.Surface);
StorageFolder pictureFolder = KnownFolders.CameraRoll;
StorageFile file = await pictureFolder.CreateFileAsync("test.png", CreationCollisionOption.ReplaceExisting);
using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, fileStream);
encoder.SetSoftwareBitmap(bmp);
await encoder.FlushAsync();
}
}
}
If i put a breakpoint in line using (frame = framePool.TryGetNextFrame()) the frame is populated and the file is saved normally by the code that follows.
If i just run the app then frame is null and an error occurs. I cant use await on the framePool.TryGetNextFrame()
I feel that this is a Frankenstein code as i am learning the new capturing paradigm. Any help how to make this code work?
Eventually i will need this code to work with a timer taking screenshots at a regular interval.
Direct3D11CaptureFramePool has a FrameArrived event, which you could listen for before trying to get the frame:
var cts = new TaskCompletionSource<object>();
framePool.FrameArrived += (s, e) => cts.SetResult(null);
session.StartCapture();
await cts.Task;
// Frame should now be available
using (frame = framePool.TryGetNextFrame())
Related
I want to open multiple audio files in UWP using the FileOpenPicker but I am getting an error that I cant Cannot Convert. How can I fix this?
And if this is fixed, will all the audio files play in order or all at the same time?
public MainPage()
{
this.InitializeComponent();
}
MediaSource media_source;
MediaPlayer media_player;
public async System.Threading.Tasks.Task OpenfileAsync()
{
var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
filePicker.FileTypeFilter.Add(".mp3");
filePicker.FileTypeFilter.Add(".mp4");
filePicker.FileTypeFilter.Add(".ogg");
filePicker.FileTypeFilter.Add(".wav");
filePicker.FileTypeFilter.Add(".wma");
filePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.MusicLibrary;
StorageFile file = await filePicker.PickSingleFileAsync();
if (file != null)
{
media_source = MediaSource.CreateFromStorageFile(file);
media_player = new MediaPlayer();
media_player.Source = media_source;
mediaPlayerElement.SetMediaPlayer(media_player);
media_player.Play();
}
}
private async void Select_track_Click(object sender, RoutedEventArgs e)
{
await OpenfileAsync();
}
public async System.Threading.Tasks.Task OpenMultipleAsync()
{
var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
filePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.MusicLibrary;
filePicker.FileTypeFilter.Add(".mp3");
filePicker.FileTypeFilter.Add(".mp4");
filePicker.FileTypeFilter.Add(".ogg");
filePicker.FileTypeFilter.Add(".wav");
filePicker.FileTypeFilter.Add(".wma");
filePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.MusicLibrary;
StorageFile file = await filePicker.PickMultipleFilesAsync();
if (file != null)
{
media_source = MediaSource.CreateFromStorageFile(file);
media_player = new MediaPlayer();
media_player.Source = media_source;
mediaPlayerElement.SetMediaPlayer(media_player);
media_player.Play();
}
}
private async void playlist_Click(object sender, RoutedEventArgs e)
{
await OpenMultipleAsync();
}
I am getting the error at StorageFile file = await filepicker.PickmultiplefilesAsync();
The FileOpenPicker.PickMultipleFilesAsync method has the following signature:
IAsyncOperation<IReadOnlyList<StorageFile>> PickMultipleFilesAsync()
In contrast to PickFileAsync it returns a IReadOnlyList<StorageFile>, so you will actually get a list of multiple files the user selected. You should update the code like this:
var files = await filePicker.PickMultipleFilesAsync();
foreach (var file in files)
{
if (file != null)
{
media_source = MediaSource.CreateFromStorageFile(file);
media_player = new MediaPlayer();
media_player.Source = media_source;
mediaPlayerElement.SetMediaPlayer(media_player);
media_player.Play();
}
}
This solution will play all the sounds at once. For one by one playback you can use #touseefbsb solution :-) .
for playing a list of files its best that you use MediaPlaybackList
Also you only need to set the SuggestedStartLocation once, and when you use PickMultipleFilesAsync() you get a List of files returned so you need that iterate through that list to get all files and add them to your MediaPlaybackList
Modify your OpenMultipleAsync method like this :
public async System.Threading.Tasks.Task OpenMultipleAsync()
{
var filePicker = new Windows.Storage.Pickers.FileOpenPicker();
filePicker.FileTypeFilter.Add(".mp3");
filePicker.FileTypeFilter.Add(".mp4");
filePicker.FileTypeFilter.Add(".ogg");
filePicker.FileTypeFilter.Add(".wav");
filePicker.FileTypeFilter.Add(".wma");
filePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.MusicLibrary;
_mediaPlaybackList = new MediaPlaybackList();
var files = await filePicker.PickMultipleFilesAsync();
foreach (var file in files)
{
var mediaPlaybackItem = new MediaPlaybackItem(MediaSource.CreateFromStorageFile(file));
_mediaPlaybackList.Items.Add(mediaPlaybackItem);
}
_mediaPlayer = new MediaPlayer();
_mediaPlayer.Source = _mediaPlaybackList;
mediaPlayerElement.SetMediaPlayer(_mediaPlayer);
}
More details about MediaPlaybackItem can be seen here
and to answer 'will these media files play together at the same time or one after the other' : they will play one after the other in a row, that is the purpose if MediaPlaybackList, it supports gapless playback for playlists.
we are trying to automatically capture an image from the webcam using MediaCapture class. We are trying to create an application which opens the camera, waits for a moment and captures the image in front of it without someone to tap the screen to capture. we tried using LowLagPhotoCapture class but does not work as desired. Sample code -
async private void InitMediaCapture()
{
MediaCapture _mediaCapture = new MediaCapture();
await _mediaCapture.InitializeAsync();
_displayRequest.RequestActive();
PreviewControlCheckIn.Source = _mediaCapture;
await _mediaCapture.StartPreviewAsync();
await Task.delay(500);
CaptureImage();
}
async private void CaptureImage()
{
storeFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync ("TestPhoto.jpg",CreationCollisionOption.GenerateUniqueName);
ImageEncodingProperties imgFormat = ImageEncodingProperties.CreateJpeg();
await _mediaCapture.CapturePhotoToStorageFileAsync(imgFormat, storeFile);
await _mediaCapture.StopPreviewAsync();
}
Any info would be great, thanks in advance for the help.
I have completed your provided code and achieved your requirement. Please refer to the following code. Please note that you should declare camera and the microphone capabilities in your Universal Windows Platform (UWP) app's package manifest to access certain API.
async private void InitMediaCapture()
{
_mediaCapture = new MediaCapture();
var cameraDevice = await FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel.Back);
var settings = new MediaCaptureInitializationSettings { VideoDeviceId = cameraDevice.Id };
await _mediaCapture.InitializeAsync(settings);
_displayRequest.RequestActive();
PreviewControl.Source = _mediaCapture;
await _mediaCapture.StartPreviewAsync();
var picturesLibrary = await StorageLibrary.GetLibraryAsync(KnownLibraryId.Pictures);
_captureFolder = picturesLibrary.SaveFolder ?? ApplicationData.Current.LocalFolder;
await Task.Delay(500);
CaptureImage();
}
async private void CaptureImage()
{
var storeFile = await _captureFolder.CreateFileAsync("PreviewFrame.jpg", CreationCollisionOption.GenerateUniqueName);
ImageEncodingProperties imgFormat = ImageEncodingProperties.CreateJpeg();
await _mediaCapture.CapturePhotoToStorageFileAsync(imgFormat, storeFile);
await _mediaCapture.StopPreviewAsync();
}
private static async Task<DeviceInformation> FindCameraDeviceByPanelAsync(Windows.Devices.Enumeration.Panel desiredPanel)
{
// Get available devices for capturing pictures
var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
// Get the desired camera by panel
DeviceInformation desiredDevice = allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == desiredPanel);
// If there is no device mounted on the desired panel, return the first device found
return desiredDevice ?? allVideoDevices.FirstOrDefault();
}
The photo will be saved to Pictures library. And I have upload the code sample to github. Please check!
In the Windows OCR avalaible here : https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/OCR
In OcrCapturedImage.xaml.cs, I can't figure out why in the line :
using (var currentFrame = await mediaCapture.GetPreviewFrameAsync(videoFrame))
I'm getting the following issue :
System exception
System.ArgumentException: 'Parametre incorrect.
Invalid subtype'
Here's the full method :
private async void ExtractButton_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
//Get information about the preview.
var previewProperties = mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties;
int videoFrameWidth = (int)previewProperties.Width;
int videoFrameHeight = (int)previewProperties.Height;
// Create the video frame to request a SoftwareBitmap preview frame.
var videoFrame = new VideoFrame(BitmapPixelFormat.Bgra8, videoFrameWidth, videoFrameHeight);
// Capture the preview frame.
using (var currentFrame = await mediaCapture.GetPreviewFrameAsync(videoFrame))
{
// Collect the resulting frame.
SoftwareBitmap bitmap = currentFrame.SoftwareBitmap;
OcrEngine ocrEngine = OcrEngine.TryCreateFromLanguage(ocrLanguage);
if (ocrEngine == null)
{
rootPage.NotifyUser(ocrLanguage.DisplayName + " is not supported.", NotifyType.ErrorMessage);
return;
}
var imgSource = new WriteableBitmap(bitmap.PixelWidth, bitmap.PixelHeight);
bitmap.CopyToBuffer(imgSource.PixelBuffer);
PreviewImage.Source = imgSource;
var ocrResult = await ocrEngine.RecognizeAsync(bitmap);
}
}
Thanks for any help
I have currently 2 buttons, Audi TT RS and Audi R8
when the user clicks on button TT RS it plays a mp3, when user clicks on button R8 it opens a different mp3 file.
This works, however... if the user clicks on one of them, and then clicks on the other. both mp3 files will open and it will sound terrible.
those are my functions :
async void Audir8_Click(object sender, RoutedEventArgs e)
{
MediaElement mediaplayer = new MediaElement();
if (mediaplayer.CurrentState == MediaElementState.Playing)
{
mediaplayer.Stop();
}
// get folder app is installed to
var installFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
// get folders mp3 files are installed to.
var resourcesFolder = await installFolder.GetFolderAsync("Resources");
var mp3FilesFolder = await resourcesFolder.GetFolderAsync("mp3Files");
// open the mp3 file async
var audioFile = await mp3FilesFolder.GetFileAsync("audir8.mp3");
// var stream = await audioFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
using (var stream = await audioFile.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
// play dat funky music
// MediaElement mediaplayer = new MediaElement();
mediaplayer.SetSource(stream, audioFile.ContentType);
var tcs = new TaskCompletionSource<bool>();
mediaplayer.CurrentStateChanged += (_, __) =>
{
if (mediaplayer.CurrentState != MediaElementState.Opening &&
mediaplayer.CurrentState != MediaElementState.Playing &&
mediaplayer.CurrentState != MediaElementState.Buffering)
// mediaplayer.CurrentState != MediaElementState.AcquiringLicense)
{
// Any other state should mean we're done playing
tcs.TrySetResult(true);
}
};
mediaplayer.Play();
await tcs.Task; // Asynchronously wait for media to finish
}
}
and the other one, actually the same..
async void Audittrs_Click(object sender, RoutedEventArgs e)
{
MediaElement mediaplayer = new MediaElement();
if (mediaplayer.CurrentState == MediaElementState.Playing)
{
mediaplayer.Stop();
}
// get folder app is installed to
var installFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
// get folders mp3 files are installed to.
var resourcesFolder = await installFolder.GetFolderAsync("Resources");
var mp3FilesFolder = await resourcesFolder.GetFolderAsync("mp3Files");
// open the mp3 file async
var audioFile = await mp3FilesFolder.GetFileAsync("ttrs.mp3");
// var stream = await audioFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
using (var stream = await audioFile.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
// play dat funky music
// MediaElement mediaplayer = new MediaElement();
mediaplayer.SetSource(stream, audioFile.ContentType);
var tcs = new TaskCompletionSource<bool>();
mediaplayer.CurrentStateChanged += (_, __) =>
{
if (mediaplayer.CurrentState != MediaElementState.Opening &&
mediaplayer.CurrentState != MediaElementState.Playing &&
mediaplayer.CurrentState != MediaElementState.Buffering)
// mediaplayer.CurrentState != MediaElementState.AcquiringLicense)
{
// Any other state should mean we're done playing
tcs.TrySetResult(true);
}
};
mediaplayer.Play();
await tcs.Task; // Asynchronously wait for media to finish
}
}
I thought this should not happen since I am using
MediaElement mediaplayer = new MediaElement();
if (mediaplayer.CurrentState == MediaElementState.Playing)
{
mediaplayer.Stop();
}
When you set up your mediaplayer local variable, you're creating a new mediaplayer, not re-using the one you've previously created. If you re-use the previously-created one (say by making it a field plus property in your class), then the .Stop() call should stop the previous sound.
If you do this, you'll have to change the first line of each of your ..._Click methods to use the persistent MediaElement.
For example, in your class you can do something like this:
private MediaElement _mediaplayer;
public MediaElement Mediaplayer
{
get{
if( _mediaplayer == null )
{
_mediaplayer = new MediaElement();
}
return _mediaplayer;
}
}
Then in your ..._Click methods, swap out this:
MediaElement mediaplayer = new MediaElement();
... for this:
MediaElement mediaplayer = this.Mediaplayer;
The getter should do the rest, making sure that you're always using the same MediaElement for the various sounds you play, allowing you to stop previously-playing sounds as you desire.
Im currently writing my first app for WP8.1. The app just need to scan a barcode.
public async void ScanBarcodeAsync(Windows.Storage.StorageFile Afile)
{
WriteableBitmap bitmap;
BitmapDecoder decoder;
using (IRandomAccessStream str = await Afile.OpenReadAsync())
{
decoder = await BitmapDecoder.CreateAsync(str);
bitmap = new WriteableBitmap(Convert.ToInt32(decoder.PixelWidth),
Convert.ToInt32(decoder.PixelHeight));
await bitmap.SetSourceAsync(str);
}
ZXing.BarcodeReader reader = new BarcodeReader();
/*reader.Options.PossibleFormats = new ZXing.BarcodeFormat[]
{
ZXing.BarcodeFormat.CODE_128,
ZXing.BarcodeFormat.CODE_39
};*/
reader.Options.TryHarder = true;
reader.AutoRotate = true;
var results = reader.Decode(bitmap);
if (results != null)
{
edtBarcode.Text = results.Text;
}
else
{
edtBarcode.Text = "Error";
}
}
The file for this method is created this way
async void StartCapture()
{
var cameraID = await GetCameraID(Windows.Devices.Enumeration.Panel.Back);
MediaCaptureInitializationSettings settings = new MediaCaptureInitializationSettings();
settings.PhotoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.VideoPreview;
settings.StreamingCaptureMode = Windows.Media.Capture.StreamingCaptureMode.Video;
settings.AudioDeviceId = string.Empty;
settings.VideoDeviceId = cameraID.Id;
captureManager = new MediaCapture(); //Define MediaCapture object
await captureManager.InitializeAsync(settings); //Initialize MediaCapture and
var focusSettings = new FocusSettings();
focusSettings.AutoFocusRange = AutoFocusRange.Macro;
focusSettings.Mode = FocusMode.Auto;
focusSettings.WaitForFocus = true;
focusSettings.DisableDriverFallback = false;
captureManager.VideoDeviceController.FocusControl.Configure(focusSettings);
captureManager.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
capturePreview.Source = captureManager; //Start preiving on CaptureElement
await captureManager.StartPreviewAsync(); //Start camera capturing
}
async private void Capture_Photo_Click(object sender, RoutedEventArgs e)
{
//Create JPEG image Encoding format for storing image in JPEG type
ImageEncodingProperties imgFormat = ImageEncodingProperties.CreateJpeg();
// create storage file in local app storage
if (ImageIndex > 0)
{
StorageFile delFile = await ApplicationData.Current.LocalFolder.GetFileAsync("Photo" + Convert.ToString(ImageIndex - 1) + ".jpg");
await delFile.DeleteAsync();
}
file = await ApplicationData.Current.LocalFolder.CreateFileAsync("Photo" + Convert.ToString(ImageIndex++) + ".jpg", CreationCollisionOption.ReplaceExisting);
// take photo and store it on file location.
await captureManager.CapturePhotoToStorageFileAsync(imgFormat, file);
//// create storage file in Picture Library
//StorageFile file = await KnownFolders.PicturesLibrary.CreateFileAsync("Photo.jpg",CreationCollisionOption.GenerateUniqueName);
// Get photo as a BitmapImage using storage file path.
bmpImage = new BitmapImage();
bmpImage.CreateOptions = BitmapCreateOptions.None;
bmpImage.UriSource = new Uri(file.Path);
ImageTaken = true;
Frame.Navigate(typeof(MainPage));
Frame.Navigate(typeof(MainPage));
}
I dont get an error running this code. But the result from ZXing is always null. The ScanBarcodeAsync-Function is directly run after taking the picture. The image the app takes is not sharp. Can this cause the problem?
Im happy to get any suggestions to solve my problem.