1

我有一个 Windows Phone 8 应用程序,我正在更新它以添加视频上传/拍摄功能。我在放置视频文件流的部分有问题 IsolatedStorageFileStream,这会引发未处理的异常。

我之前使用了简单的视频拍摄 API(VideoCaptureDevice与 using 结合使用FileSink),并且在将文件另存为独立存储时没有任何问题。这很好,但是我们的应用程序需要更多地控制视频的压缩,这就是为什么我使用高级相机 API 进行视频拍摄的原因AudioVideoCaptureDevice,它IRandomAccessStream用作文件的流支持。

使用高级 API 拍摄视频本身没有问题,只有问题是当IsolatedStorageFileStream使用抛出未处理的异常时,该异常在异常对象中指示:

System.IO.IsolatedStorageException: Operation not permitted on IsolatedStorageFileStream.

每当我打开/创建IsolatedStorageFileStream以前已经使用过的文件时,都会引发异常。我尝试了一切,从关闭IsolatedStorageFileStream、处理它,甚至将对象设置为 null。

这是我的视频拍摄实现的代码片段,也是获取用于视频 APIIsolatedStorageFileStream的实例的代码(都在同一个类中)(这里有问题的代码在 StartOptimizedRecord()IRandomAccessStream当另一个时间调用该方法时,即当用户尝试重新录制视频时,会导致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;
        }
    }
}
4

0 回答 0