MediaTranscoder.PrepareFileTranscodeAsync UnauthorizedAccessException - c#

I have a Button on a Page with the following method on the click event of the button:
StorageFile _sourceFile;
private string _sourceToken;
private async void btnSelect_Click(object sender, RoutedEventArgs e)
{
FileOpenPicker fop = new FileOpenPicker();
fop.FileTypeFilter.Add(".mp4");
StorageFile inFile = await fop.PickSingleFileAsync();
_sourceToken = Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(inFile);
_sourceFile = await Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.GetFileAsync(_sourceToken);
mediaElement.AutoPlay = false;
IRandomAccessStream stream = await _outFile.OpenAsync(FileAccessMode.ReadWrite);
mediaElement.SetSource(stream, _outFile.ContentType);
}
If I click play on the MediaElement the video I select plays fine.
I also have another button which has the following code on its click event:
private async void btnExport_Click(object sender, RoutedEventArgs e)
{
StorageFile outFile = await KnownFolders.VideosLibrary.CreateFileAsync("Outfie.mp4", CreationCollisionOption.ReplaceExisting);
MediaEncodingProfile profile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD1080p);
MediaTranscoder transcoder = new MediaTranscoder();
PrepareTranscodeResult prepareOp = await transcoder.PrepareFileTranscodeAsync(_sourceFile, outFile, profile);
if (prepareOp.CanTranscode)
{
var transcodeOp = prepareOp.TranscodeAsync();
transcodeOp.Progress += new AsyncActionProgressHandler<double>(TranscodeProgress);
transcodeOp.Completed += new AsyncActionWithProgressCompletedHandler<double>(TranscodeComplete);
}
else
{
switch (prepareOp.FailureReason)
{
case TranscodeFailureReason.CodecNotFound:
System.Diagnostics.Debug.WriteLine("Codec not found.");
break;
case TranscodeFailureReason.InvalidProfile:
System.Diagnostics.Debug.WriteLine("Invalid profile.");
break;
default:
System.Diagnostics.Debug.WriteLine("Unknown failure.");
break;
}
}
}
Unfortunately the line transcoder.PrepareFileTranscodeAsync throws an UnauthorizedAccessException. But if I use the following instead of _sourceFile it works:
StorageFile sourceFile = await KnownFolders.VideosLibrary.GetFileAsync("sourceFile.mp4");
The error being thrown is:
System.UnauthorizedAccessException: 'Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))'
To be clear, I am selecting files OUTSIDE the KnownFolders Enumeration, hence I am using Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.
Can anyone explain why?
EDIT:
If I change the source file to be the result of a FileOpenPicker then it works. So it begs the question, why is the FutureAccessList not working??
private async void btnExport_Click(object sender, RoutedEventArgs e)
{
StorageFile outFile = await KnownFolders.VideosLibrary.CreateFileAsync("Outfie.mp4", CreationCollisionOption.ReplaceExisting);
FileOpenPicker fop = new FileOpenPicker();
fop.SuggestedStartLocation = PickerLocationId.ComputerFolder;
fop.FileTypeFilter.Add(".mp4");
StorageFile sourceFile = await fop.PickSingleFileAsync();
MediaEncodingProfile profile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD1080p);
MediaTranscoder transcoder = new MediaTranscoder();
PrepareTranscodeResult prepareOp = await transcoder.PrepareFileTranscodeAsync(sourceFile, outFile, profile);
if (prepareOp.CanTranscode)
{
var transcodeOp = prepareOp.TranscodeAsync();
transcodeOp.Progress += new AsyncActionProgressHandler<double>(TranscodeProgress);
transcodeOp.Completed += new AsyncActionWithProgressCompletedHandler<double>(TranscodeComplete);
}
else
{
switch (prepareOp.FailureReason)
{
case TranscodeFailureReason.CodecNotFound:
System.Diagnostics.Debug.WriteLine("Codec not found.");
break;
case TranscodeFailureReason.InvalidProfile:
System.Diagnostics.Debug.WriteLine("Invalid profile.");
break;
default:
System.Diagnostics.Debug.WriteLine("Unknown failure.");
break;
}
}
}

Do you have access to the file you're trying to write to? Maybe it's read-only or created by another user other than yourself? (Right click + Properties on the file in Explorer should give you a clearer picture of the file permissions)
Also, you might get that exception if you're trying to write to a folder whom you don't have access to.
Check your credentials, I would guess it's something related to that.

So it seems the fact I was opening the source file in ReadWrite mode
IRandomAccessStream stream = await _outFile.OpenAsync(FileAccessMode.ReadWrite);
Was the cause of the issues. According to this page
Use read/write mode only when you're ready to write immediately in order to avoid conflicts with other operations.
So I changed to this and all works well
IRandomAccessStream stream = await _outFile.OpenAsync(FileAccessMode.Read);

Related

load image from PC as stream

I am trying to load a picture from my PC as a raw image in order to use it with the Microsoft cognitive services emotion (UWP).
below is a piece of my code:
//Chose Image from PC
private async void chosefile_Click(object sender, RoutedEventArgs e)
{
//Open Dialog
FileOpenPicker open = new FileOpenPicker();
open.ViewMode = PickerViewMode.Thumbnail;
open.SuggestedStartLocation = PickerLocationId.Desktop;
open.FileTypeFilter.Add(".jpg");
open.FileTypeFilter.Add(".jpeg");
open.FileTypeFilter.Add(".gif");
open.FileTypeFilter.Add(".png");
file = await open.PickSingleFileAsync();
if (file != null)
{//imagestream is declared as IRandomAccessStream.
imagestream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
var image = new BitmapImage();
image.SetSource(imagestream);
imageView.Source = image;
}
else
{
//
}
}
The part above works fine, it selects a photo from the pc (dialog box) and displays it in Image box.
private async void analyse_Click(object sender, RoutedEventArgs e)
{
try
{
emotionResult = await emotionServiceClient.RecognizeAsync(imagestream.AsStream());
}
catch
{
output.Text = "something is wrong in stream";
}
try {
if(emotionResult!= null)
{
Scores score = emotionResult[0].Scores;
output.Text = "Your emotions are: \n" +
"Happiness: " + score.Happiness + "\n" +
"Sadness: " + score.Sadness;
}
}
catch
{
output.Text = "Something went wrong";
}
}
I think the error is due to imagestream.AsStream()
imagestream is declared as IRandomAccessStream.
Can someone please tell me how to fix that part and if the error is in fact due to not loading the image correctly?
EDIT:
Also is there a better way to do this, instead of using stream to pass the emotionServiceClient a saved file instead of a stream?
Your problem is that you've advanced the stream position by virtue of creating the BitmapImage, so your read position is at the end by the time you call emotionServiceClient.RecognizeAsync. So you'll need to 'rewind':
var stream = imagestream.AsStreamForRead();
stream.Position = 0;
emotionResult = await emotionServiceClient.RecognizeAsync(stream);
Why not use their example, instead of trying to hold the file in memory, why don't you hold a path, and then use the path to read the stream at the time.
https://www.microsoft.com/cognitive-services/en-us/Emotion-api/documentation/GetStarted
In there example;
using (Stream imageFileStream = File.OpenRead(imageFilePath))
{
//
// Detect the emotions in the URL
//
emotionResult = await emotionServiceClient.RecognizeAsync(imageFileStream);
return emotionResult;
}
So you would be capturing imageFilePath as the result of the open file dialog.

Wp 8.1 app crashing when its not connected to debugger

Application works when its connected to PC and run with debugger. The problem starts when I disconnect phone from PC, run app from phone and try to open gallery and set image to image control. I tried to write error in a file on try/catch but catch is never called, like there is no error on app executing.
This is code where i select img:
private async void galleryBtn_Click(object sender, RoutedEventArgs e)
{
try
{
FileOpenPicker filePicker = new FileOpenPicker();
filePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
filePicker.ViewMode = PickerViewMode.Thumbnail;
// Filter to include a sample subset of file types
filePicker.FileTypeFilter.Clear();
filePicker.FileTypeFilter.Add(".bmp");
filePicker.FileTypeFilter.Add(".png");
filePicker.FileTypeFilter.Add(".jpeg");
filePicker.FileTypeFilter.Add(".jpg");
filePicker.PickSingleFileAndContinue();
view.Activated += viewActivated;
}
catch (Exception err)
{
string error = err.StackTrace.ToString();
await saveStringToLocalFile("test11", error);
}
}
And than it goes to :
private async void viewActivated(CoreApplicationView sender, IActivatedEventArgs args1)
{
try
{
FileOpenPickerContinuationEventArgs args = args1 as FileOpenPickerContinuationEventArgs;
if (args != null)
{
if (args.Files.Count == 0) return;
view.Activated -= viewActivated;
StorageFile storageFile = args.Files[0];
var stream = await storageFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
var bitmapImage = new Windows.UI.Xaml.Media.Imaging.BitmapImage();
await bitmapImage.SetSourceAsync(stream);
var decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(stream);
var obj = App.Current as App;
obj.ImageToEdit = bitmapImage;
obj.fileTransfer = storageFile;
checkTorch = -1;
await newCapture.StopPreviewAsync();
Frame.Navigate(typeof(EditImage));
}
}
catch (Exception err) {
string error = err.StackTrace.ToString();
await saveStringToLocalFile("test11", error);
}
}
When img is selected i open screen for image editing and run this
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
try
{
var obj = App.Current as App;
slika = obj.ImageToEdit;
original = obj.ImageToEdit;
ImagePreview.Source = slika;
RotateTransform myRotateTransform = new RotateTransform();
myRotateTransform.Angle = 0;
ImagePreview.RenderTransform = myRotateTransform;
var localSettings = ApplicationData.Current.LocalSettings;
}
catch (Exception err)
{
string error = err.StackTrace.ToString();
await saveStringToLocalFile("test11", error);
}
}
That is all, any advice is appreciated;
Problem was with my MediaCapture. First use mediaCapture.stopPreviewAsync(); to stop preview and than you must release the mediaCapture.
Before you call fileOpener use this code:
newCapture.Dispose();
In order to catch unhandled exceptions you can use a global exception catcher,
in App.xaml.cs file define:
public App()
{
this.InitializeComponent();
this.Suspending += this.OnSuspending;
this.UnhandledException += UnhandledExceptionHandler;
}
private void UnhandledExceptionHandler(object sender, UnhandledExceptionEventArgs e)
{
log.Critical(e.Exception);
}
It's important to understand that not all exceptions can be caught using try\catch such as Corrupt State Exceptions:
https://msdn.microsoft.com/en-us/magazine/dd419661.aspx#id0070035
In this case you can debug the issue by viewing the .dmp file generated by your application found in: {Phone}\Documents\Debug

Universal App hangs at CreateFileAsync (possible deadlock?)

I'm making a program that capture photo from camera and perform some actions with it. So I have the following code (handler for camera button and "some actions"):
private async void btnCamera_Click(object sender, RoutedEventArgs e)
{
btnCamera.IsEnabled = false;
var imgFormat = ImageEncodingProperties.CreateJpeg();
var ocrFolder = Windows.Storage.ApplicationData.Current.TemporaryFolder;
var imgFileRaw = await ocrFolder.CreateFileAsync("ocr_raw.jpg", CreationCollisionOption.ReplaceExisting);
var imgFileFull = await ocrFolder.CreateFileAsync("ocr_full.jpg", CreationCollisionOption.ReplaceExisting);
var imgFilePart = await ocrFolder.CreateFileAsync("ocr_part.jpg", CreationCollisionOption.ReplaceExisting);
await camera.CapturePhotoToStorageFileAsync(imgFormat, imgFileRaw);
await camera.StopPreviewAsync();
await SaveImageEx(imgFileRaw, imgFileFull, false);
await SaveImageEx(imgFileRaw, imgFilePart, true);
this.Frame.GoBack();
}
private async Task SaveImageEx(StorageFile SourceFile, StorageFile TargetFile, bool Partial)
{
using (var sourceStream = await SourceFile.OpenAsync(FileAccessMode.Read))
using (var targetStream = await TargetFile.OpenAsync(FileAccessMode.ReadWrite))
{
var decoder = await BitmapDecoder.CreateAsync(BitmapDecoder.JpegDecoderId, sourceStream);
var encoder = await BitmapEncoder.CreateForTranscodingAsync(targetStream, decoder);
bool rotated90Degrees = false;
switch (previewOrientation)
{
case DisplayOrientations.Portrait:
{
encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees;
rotated90Degrees = true;
break;
}
case DisplayOrientations.PortraitFlipped:
{
encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise270Degrees;
rotated90Degrees = true;
break;
}
case DisplayOrientations.LandscapeFlipped:
{
encoder.BitmapTransform.Rotation = BitmapRotation.Clockwise180Degrees;
break;
}
case DisplayOrientations.Landscape:
case DisplayOrientations.None:
default:
{
encoder.BitmapTransform.Rotation = BitmapRotation.None;
break;
}
}
if (Partial)
{
encoder.BitmapTransform.Bounds = rotated90Degrees ?
RecognitionArea1.GetImageRegion(decoder.PixelHeight, decoder.PixelWidth) :
RecognitionArea1.GetImageRegion(decoder.PixelWidth, decoder.PixelHeight);
}
await encoder.FlushAsync();
}
}
The problem is that 1 of 5-10 times camera button clicked code hangs at line:
var imgFileRaw = await ocrFolder.CreateFileAsync("ocr_raw.jpg",
CreationCollisionOption.ReplaceExisting);
Please, somebody explain me what is so wrong with my code? I've read lots of examples how to avoid deadlocks with async/await operations and I still don't know where the problem is.
UPDATE. It seems without calling "SaveImageEx" there is no hanging, still don't see anything dangerous inside this method.
UPDATE2. I made minimal hanging example with the code which I'm really using in the app. Just click camera button for several times and you will see deadlock on "CreateFileAsync":
HangSample (Visual Studio 2013 solution)

File Save Picker - Save Edited Image (C# Metro app)

I want to open an image, edit it, and then save it. I am able to open a file, but I have problems saving it. The way I have written the code, I can only save a file with .jpg but there is nothing in it.
Please explain to me how to save the image I have opened and edited(not made yet).
public sealed partial class MainPage : Page
{
BitmapImage originalImage = new BitmapImage();
public MainPage()
{
this.InitializeComponent();
}
private async void OpenButton_Click(object sender, RoutedEventArgs e)
{
var filePicker = new FileOpenPicker();
filePicker.FileTypeFilter.Add(".jpg");
filePicker.FileTypeFilter.Add(".jpeg");
filePicker.FileTypeFilter.Add(".gif");
filePicker.ViewMode = PickerViewMode.Thumbnail;
filePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
filePicker.SettingsIdentifier = "PicturePicker";
filePicker.CommitButtonText = "Select File";
StorageFile selectedFile = await filePicker.PickSingleFileAsync();
var stream = await selectedFile.OpenAsync(FileAccessMode.Read);
if (selectedFile != null)
{
originalImage.SetSource(stream);
pictureBox.Source = originalImage;
}
}
private async void SaveButton_Click(object sender, RoutedEventArgs e)
{
FileSavePicker savePicker = new FileSavePicker();
savePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
savePicker.FileTypeChoices.Add("jpeg image", new List<string>() { ".jpg" });
savePicker.SuggestedFileName = "EditedImage";
StorageFile file = await savePicker.PickSaveFileAsync();
}
}
After creating an Images file you need to Update it see FileSavePicker class.
Add the following code in your SaveButton_Click method and try modify it.
This will let you update your created file into real image file.
if (file != null)
{
// Prevent updates to the remote version of the file until we finish making changes and call CompleteUpdatesAsync.
CachedFileManager.DeferUpdates(file);
// write to file
await FileIO.WriteTextAsync(file, file.Name);
// Let Windows know that we're finished changing the file so the other app can update the remote version of the file.
// Completing updates may require Windows to ask for user input.
FileUpdateStatus status = await CachedFileManager.CompleteUpdatesAsync(file);
if (status == FileUpdateStatus.Complete)
{
OutputTextBlock.Text = "File " + file.Name + " was saved.";
}
else
{
OutputTextBlock.Text = "File " + file.Name + " couldn't be saved.";
}
}
else
{
OutputTextBlock.Text = "Operation cancelled.";
}

UnauthorizedAccessException when using FileOpenPicker

I have a CommandBar in my Windows Store app, and when I click the Open button on my CommandBar, it runs the OpenFile handler as follows:
private async void OpenFile(object sender, RoutedEventArgs e)
{
MessageDialog dialog = new MessageDialog("You are about to open a new file. Do you want to save your work first?");
dialog.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(SaveAndOpen)));
dialog.Commands.Add(new UICommand("No", new UICommandInvokedHandler(Open)));
await dialog.ShowAsync();
}
private async void SaveAndOpen(IUICommand command)
{
await SaveFile();
Open(command);
}
private async void Open(IUICommand command)
{
FileOpenPicker fileOpenPicker = new FileOpenPicker();
fileOpenPicker.ViewMode = PickerViewMode.List;
fileOpenPicker.FileTypeFilter.Add(".txt");
StorageFile file = await fileOpenPicker.PickSingleFileAsync();
await LoadFile(file);
}
I see the message just fine, but only when I hit Yes do I get presented with the FileOpenPicker. When I hit No I get an UnauthorizedAccessException: Access is denied. at the following line: StorageFile file = await fileOpenPicker.PickSingleFileAsync();
I'm baffled...does anyone know why this is happening? I even tried running it in a dispatcher on the off-chance that the handler was being called on a different thread, but...unfortunately, same thing:
await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.High, async () =>
{
StorageFile file = await fileOpenPicker.PickSingleFileAsync();
await LoadFile(file);
});
Yes, it was due to RT's dialog race conditions. The solution was for me to literally make use of the MessageDialog class the same way you would use MessageBox.Show in WinForms:
private async void OpenFile(object sender, RoutedEventArgs e)
{
MessageDialog dialog = new MessageDialog("You are about to open a new file. Do you want to save your work first?");
IUICommand result = null;
dialog.Commands.Add(new UICommand("Yes", (x) =>
{
result = x;
}));
dialog.Commands.Add(new UICommand("No", (x) =>
{
result = x;
}));
await dialog.ShowAsync();
if (result.Label == "Yes")
{
await SaveFile();
}
FileOpenPicker fileOpenPicker = new FileOpenPicker();
fileOpenPicker.ViewMode = PickerViewMode.List;
fileOpenPicker.FileTypeFilter.Add(".txt");
StorageFile file = await fileOpenPicker.PickSingleFileAsync();
await LoadFile(file);
}

Categories

Resources