Операция не разрешена Windows Phone 8 устройства захвата
У меня есть приложение для Windows Phone 8, которое я обновляю, чтобы добавить возможности загрузки / выгрузки видео. У меня проблема с той частью, где я размещаю поток видеофайлов на IsolatedStorageFileStream
, который бросает необработанные исключения.
Ранее я использовал простой API для видеосъемки (VideoCaptureDevice
в сочетании с использованием FileSink
), и не было никаких проблем при сохранении файла в изолированное хранилище. Это было хорошо, но наше приложение нуждается в большем контроле над сжатием видео, поэтому я переключился, используя передовой API камеры для захвата видео, AudioVideoCaptureDevice
, который использует IRandomAccessStream
в качестве потоковой поддержки файла.
У меня не было проблем с получением самого видео с помощью расширенных API, ТОЛЬКО проблема заключается в том, когда IsolatedStorageFileStream
used генерирует необработанное исключение, которое указывает на объект исключения:
System.IO.IsolatedStorageException: Operation not permitted on IsolatedStorageFileStream.
Исключение выдается каждый раз, когда я открываю / создаю IsolatedStorageFileStream
файл, который уже использовался ранее. Я попробовал все от закрытия IsolatedStorageFileStream
, утилизировать его и даже установить объект на ноль.
Это фрагмент кода для моих реализаций видеосъемки, а также код для получения IsolatedStorageFileStream
получить экземпляр IRandomAccessStream
для использования с API видео (все в одном классе) (проблемный код здесь в методе StartOptimizedRecord(), который при вызове в другой раз, то есть, когда пользователь пытается перезаписать видео, вызывает необработанное исключение System.IO.IsolatedStorageException
и / или System.ObjectDisposedException
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using System.Windows.Media;
using System.IO.IsolatedStorage;
using System.Diagnostics;
using System.Windows.Threading;
using System.IO;
using System.Globalization;
using Policelink.Models;
using System.Windows.Media.Imaging;
using Windows.Phone.Media.Capture;
using Microsoft.Devices;
using Windows.Storage.Streams;
using Windows.Storage;
namespace Policelink.Views
{
public partial class VideoCapturePage : PhoneApplicationPage
{
private VideoBrush videoBrush;
private IsolatedStorageFileStream isoVidFile;
private EyeWitnessReportVideo reportVideo;
//static readonly string videoFileName = "video1.mp4";
string videoFileName = "";
bool recording = false;
TimeSpan timeElapsed;
BitmapImage pauseImage;
BitmapImage playImage;
BitmapImage thumbnailImage;
MemoryStream thumbnailStream;
private const int maxLength = 60;
bool playing = false;
DispatcherTimer timer = new DispatcherTimer();
public VideoCapturePage()
{
InitializeComponent();
timer.Tick += timer_Tick;
timer.Interval = TimeSpan.FromSeconds(1);
pauseImage = new BitmapImage();
//pauseImage = new BitmapImage(new Uri("Assets/media-pause.png",UriKind.RelativeOrAbsolute));
var pauseStream = Application.GetResourceStream(new Uri("Assets/media-pause.png", UriKind.RelativeOrAbsolute)).Stream;
pauseImage.SetSource(pauseStream);
playImage = (BitmapImage) PlayPauseButtonImage.Source;
reportVideo = new EyeWitnessReportVideo();
GenerateCurrentVideoFileName();
CameraButtons.ShutterKeyPressed += CameraButtons_ShutterKeyPressed;
}
void CameraButtons_ShutterKeyPressed(object sender, EventArgs e)
{
ToggleRecordVideo();
}
void timer_Tick(object sender, EventArgs e)
{
timeElapsed = timeElapsed.Add(TimeSpan.FromSeconds(1));
TimeText.Text = timeElapsed.ToString(@"mm\:ss");
if (timeElapsed.TotalSeconds >= maxLength)
{
timer.Stop();
StopOptimizedRecord();
recording = false;
ToggleAcceptButton(true);
}
}
void ResetElapsed()
{
timeElapsed = TimeSpan.FromSeconds(0);
}
void StartTimer()
{
timer.Start();
}
void StopTimer()
{
timer.Stop();
}
private const string VideoFormatExt = ".mp4";
void GenerateCurrentVideoFileName()
{
string timestamp = DateTime.Now.ToBinary().ToString();
videoFileName = timestamp + VideoFormatExt;
Debug.WriteLine("Timestamp for currentvideo filename: " + timestamp);
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
InitializeOptimizedCamera();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
base.OnNavigatedFrom(e);
UninitializeOptimizedCamera();
}
AudioVideoCaptureDevice vidCaptureDevice;
async void InitializeOptimizedCamera()
{
if (AudioVideoCaptureDevice.AvailableSensorLocations.Contains(CameraSensorLocation.Back))
{
var res = GetLowestVideoResolution();
var resPrev = GetLowestPreviewResolution();
vidCaptureDevice = await AudioVideoCaptureDevice.OpenAsync(CameraSensorLocation.Back, res);
vidCaptureDevice.AudioEncodingFormat = CameraCaptureAudioFormat.Aac;
vidCaptureDevice.VideoEncodingFormat = CameraCaptureVideoFormat.H264;
await vidCaptureDevice.SetPreviewResolutionAsync(resPrev);
vidCaptureDevice.RecordingFailed += openedCam_RecordingFailed;
vidCaptureDevice.PreviewFrameAvailable += vidCaptureDevice_PreviewFrameAvailable;
SetCaptureDeviceProperties();
videoBrush = new VideoBrush();
videoBrush.SetSource(vidCaptureDevice);
RecordViewFinder.Fill = videoBrush;
}
}
void vidCaptureDevice_PreviewFrameAvailable(ICameraCaptureDevice sender, object args)
{
//throw new NotImplementedException();
}
IRandomAccessStream videoStream;
async void StartOptimizedRecord()
{
if (vidCaptureDevice != null)
{
OpenIsoVideoFile();
await vidCaptureDevice.StartRecordingToStreamAsync(videoStream);
ResetElapsed();
StartTimer();
//thumbnailStream = new MemoryStream();
}
}
void GetStreamFromIsolatedStorageVideoFile()
{
using (var isoFile = IsolatedStorageFile.GetUserStoreForApplication())
{
isoVidFile = isoFile.OpenFile(videoFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite);
videoStream = (IRandomAccessStream)isoVidFile.AsOutputStream();
}
}
// calling this method also, but unhandled exception still continues..
void ResetIsoVideoStreamFile()
{
if (videoStream != null)
{
videoStream.Dispose();
videoStream = null;
}
if (isoVidFile != null)
{
isoVidFile.Dispose();
isoVidFile.Close();
//isoVidFile = null;
}
}
void OpenIsoVideoFile()
{
using (var isoFile = IsolatedStorageFile.GetUserStoreForApplication())
{
if (isoFile.FileExists(videoFileName))
{
isoFile.DeleteFile(videoFileName);
}
// THIS is where the exception starts, on the call of new IsolatedStorageFileStream, when OpenIsoVideoFile() is being called again after first call..
isoVidFile = new IsolatedStorageFileStream(videoFileName, FileMode.Create,FileAccess.ReadWrite,FileShare.ReadWrite, isoFile);
// Codes below commented doesn't work either, throws the same exception as above...
//ResetIsoVideoStreamFile();
//isoVidFile = isoFile.CreateFile(videoFileName);
//isoVidFile = isoFile.OpenFile(videoFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
videoStream = (IRandomAccessStream)isoVidFile.AsOutputStream();
}
}
// attempts to fix the error of the unhandled exception, but this one to no avail...
void CloseIsoVideoFile()
{
if (videoStream != null)
{
videoStream.Dispose();
}
if (isoVidFile != null)
{
isoVidFile.Dispose();
isoVidFile.Close();
}
}
async void StopOptimizedRecord()
{
if (vidCaptureDevice != null)
{
StopTimer();
await vidCaptureDevice.StopRecordingAsync();
LoadVideoPlayerFromIsoFile();
TogglePlayPauseButtonVisibility(true);
TogglePlayPauseButton(true);
}
}
void SetCaptureDeviceProperties()
{
if (vidCaptureDevice != null)
{
var profile = KnownCameraAudioVideoProperties.H264EncodingProfile;
var level = KnownCameraAudioVideoProperties.H264EncodingLevel;
var profileProp = H264EncoderProfile.Extended;
var levelProp = H264EncoderLevel.Level1_3;
vidCaptureDevice.SetProperty(profile, profileProp);
vidCaptureDevice.SetProperty(level, levelProp);
}
}
void UninitializeOptimizedCamera()
{
if (vidCaptureDevice != null)
{
vidCaptureDevice.PreviewFrameAvailable -= vidCaptureDevice_PreviewFrameAvailable;
vidCaptureDevice.RecordingFailed -= openedCam_RecordingFailed;
vidCaptureDevice.Dispose();
vidCaptureDevice = null;
videoBrush = null;
recording = false;
}
}
void openedCam_RecordingFailed(AudioVideoCaptureDevice sender, CaptureFailedEventArgs args)
{
}
Windows.Foundation.Size GetLowestVideoResolution()
{
var camOkay = AudioVideoCaptureDevice.GetAvailableCaptureResolutions(CameraSensorLocation.Back);
var sorted = camOkay.OrderBy(s => s.Width);
var lowest = sorted.First();
return lowest;
}
Windows.Foundation.Size GetLowestPreviewResolution()
{
var res = AudioVideoCaptureDevice.GetAvailablePreviewResolutions(CameraSensorLocation.Back);
var sorted = res.OrderBy(s => s.Width);
return sorted.First();
}
void TogglePlayPauseButton(bool play)
{
playing = play;
PlayPauseButtonImage.Source = playing ? playImage : pauseImage;
}
void TogglePlayPauseButtonVisibility(bool visible)
{
PlayPauseButton.Visibility = visible ? Visibility.Visible : Visibility.Collapsed;
}
void LoadVideoPlayerFromIsoFile()
{
if (isoVidFile != null)
{
this.RecorderMediaElement.SetSource(isoVidFile);
}
}
private void RecordClick(object sender, EventArgs e)
{
ToggleRecordVideo();
}
void ToggleRecordVideo()
{
if (!recording)
{
ToggleRecordViewFinderAndPreviewDisplay(true);
TogglePlayPauseButtonVisibility(false);
ToggleAcceptButton(false);
StartOptimizedRecord();
recording = true;
}
else
{
StopOptimizedRecord();
recording = false;
ToggleAcceptButton(true);
ToggleRecordViewFinderAndPreviewDisplay(false);
TogglePlayPauseButtonVisibility(true);
TogglePlayPauseButton(true);
}
}
private void RecorderMediaElement_MediaEnded(object sender, RoutedEventArgs e)
{
this.TogglePlayPauseButton(true);
}
private void SaveToGlobal()
{
reportVideo.VideoLocalUrl = videoFileName;
//GetThumbnailFromVideoPreview();
App.ArgHelper.CurrentTakenVideo = reportVideo;
}
private void GetThumbnailFromVideoPreview()
{
if (thumbnailStream == null)
{
var wb = new WriteableBitmap(this.RecorderMediaElement, null);
wb.SaveJpeg(thumbnailStream, (int)currentFormat.PixelWidth, (int)currentFormat.PixelHeight, 0, 60);
}
reportVideo.Thumbnail = thumbnailStream;
}
private void PlayClick(object sender, EventArgs e)
{
if (videoStream != null)
{
this.RecorderMediaElement.Play();
}
}
private void PlayPauseButton_Click(object sender, RoutedEventArgs e)
{
if (playing)
{
if (videoStream != null)
{
this.RecorderMediaElement.Play();
}
}
else
{
RecorderMediaElement.Pause();
}
TogglePlayPauseButton(!playing);
}
private void ToggleAcceptButton(bool toggle)
{
var acceptBtn = this.ApplicationBar.Buttons[1] as ApplicationBarIconButton;
acceptBtn.IsEnabled = toggle;
}
private void AcceptClick(object sender, EventArgs e)
{
SaveToGlobal();
this.NavigationService.GoBack();
}
void ToggleRecordViewFinderAndPreviewDisplay(bool toggleRecordViewFinder)
{
this.RecorderMediaElement.Visibility = !toggleRecordViewFinder ? Visibility.Visible : Visibility.Collapsed;
this.RecordViewFinder.Visibility = toggleRecordViewFinder ? Visibility.Visible : Visibility.Collapsed;
}
}
}