0

I'm trying to capture video on Windows Phone using the AudioVideoCaptureDevice but when I try to set the captureSource I get a error message saying " Operation not valid due to the state of the object". Can you tell me what to do right in the following code?

Code snippet:

    // Viewfinder for capturing video.
    private VideoBrush videoRecorderBrush;

    // Source and device for capturing video.
    private CaptureSource _cs;
    private VideoCaptureDevice _cd;
    private AudioVideoCaptureDevice vcDevice;
    double w, h;

    // File details for storing the recording.        
    private IsolatedStorageFileStream isoVideoFile;
    private FileSink fileSink;
    private string isoVideoFileName = "iClips_Video.mp4";
    private StorageFile sfVideoFile;

    // For managing button and application state.
    private enum ButtonState { Initialized, Stopped, Ready, Recording, Playback, Paused, NoChange, CameraNotSupported };
    private ButtonState currentAppState;


 // Constructor
    public MainPage()
    {
        try
        {
            InitializeComponent();
            //setup recording
            // Prepare ApplicationBar and buttons.
            PhoneAppBar = (ApplicationBar)ApplicationBar;
            PhoneAppBar.IsVisible = true;
            StartRecording = ((ApplicationBarIconButton)ApplicationBar.Buttons[0]);
            StopPlaybackRecording = ((ApplicationBarIconButton)ApplicationBar.Buttons[1]);
            StartPlayback = ((ApplicationBarIconButton)ApplicationBar.Buttons[2]);
            PausePlayback = ((ApplicationBarIconButton)ApplicationBar.Buttons[3]);

            SetScreenResolution();

            //initialize the camera task
            cameraCaptureTask = new CameraCaptureTask();
            cameraCaptureTask.Completed += new EventHandler<PhotoResult>(cameraCaptureTask_Completed);

            if (isFilePresent("username") && isFilePresent("Password"))
            {
                if (isFilePresent("IsProfilePhotoOnServer"))
                {
                    connectToSocket();
                }
                else
                {
                    SignUpProfilePhoto();
                }  
            }
            else
            {
                SignIn();
            }
        }
        catch (Exception ex)
        {
            this.Dispatcher.BeginInvoke(delegate()
            {
                MessageBox.Show("Constructor Error:\n"+ ex.Message);
            });
        }
    }



    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        // Initialize the video recorder.
        InitializeVideoRecorder();

        //prepare shutter hot keys 
        CameraButtons.ShutterKeyHalfPressed += OnButtonHalfPress;
        CameraButtons.ShutterKeyPressed += OnButtonFullPress;
        CameraButtons.ShutterKeyReleased += OnButtonRelease;
    }
    protected override void OnNavigatedFrom(NavigationEventArgs e)
    {
        // Dispose of camera and media objects.
        DisposeVideoPlayer();
        DisposeVideoRecorder();

        base.OnNavigatedFrom(e);

        CameraButtons.ShutterKeyHalfPressed -= OnButtonHalfPress;
        CameraButtons.ShutterKeyPressed -= OnButtonFullPress;
        CameraButtons.ShutterKeyReleased -= OnButtonRelease;
    }
    protected override void OnOrientationChanged(OrientationChangedEventArgs e)
    {
        if (vcDevice != null)
        {
            if (e.Orientation == PageOrientation.LandscapeLeft)
            {
                txtDebug.Text = "LandscapeLeft";
                videoRecorderBrush.RelativeTransform =
                    new CompositeTransform() { CenterX = 0.5, CenterY = 0.5, Rotation = 90 };

                //rotate logo
                if (logo != null) 
                {
                    RotateTransform rt = new RotateTransform();
                    rt.Angle = 90;
                    //default rotation is around top left corner of the control,
                    //but you sometimes want to rotate around the center of the control
                    //to do that, you need to set the RenderTransFormOrigin
                    //of the item you're going to rotate
                    //I did not test this approach, maybe You're going to need to use actual coordinates
                    //so this bit is for information purposes only
                    logo.RenderTransformOrigin = new Point(0.5, 0.5);
                    logo.RenderTransform = rt;                    
                }

                //rotate sign in link
                if (MyGrid != null)
                {
                    RotateTransform rt = new RotateTransform();
                    rt.Angle = 90;
                    //default rotation is around top left corner of the control,
                    //but you sometimes want to rotate around the center of the control
                    //to do that, you need to set the RenderTransFormOrigin
                    //of the item you're going to rotate
                    //I did not test this approach, maybe You're going to need to use actual coordinates
                    //so this bit is for information purposes only
                    MyGrid.RenderTransformOrigin = new Point(0.5, 0.5);
                    MyGrid.RenderTransform = rt;                    
                }

            }
            if (e.Orientation == PageOrientation.PortraitUp)
            {
                txtDebug.Text = "PortraitUp";
                videoRecorderBrush.RelativeTransform =
                    new CompositeTransform() { CenterX = 0.5, CenterY = 0.5, Rotation = 90 };
                //rotate logo
                if (logo != null)
                {
                    RotateTransform rt = new RotateTransform();
                    rt.Angle = 0;
                    //default rotation is around top left corner of the control,
                    //but you sometimes want to rotate around the center of the control
                    //to do that, you need to set the RenderTransFormOrigin
                    //of the item you're going to rotate
                    //I did not test this approach, maybe You're going to need to use actual coordinates
                    //so this bit is for information purposes only
                    logo.RenderTransformOrigin = new Point(0.5, 0.5);
                    logo.RenderTransform = rt;
                }

                //rotate sign in link
                if (MyGrid != null)
                {
                    RotateTransform rt = new RotateTransform();
                    rt.Angle = 0;
                    //default rotation is around top left corner of the control,
                    //but you sometimes want to rotate around the center of the control
                    //to do that, you need to set the RenderTransFormOrigin
                    //of the item you're going to rotate
                    //I did not test this approach, maybe You're going to need to use actual coordinates
                    //so this bit is for information purposes only
                    MyGrid.RenderTransformOrigin = new Point(0.5, 0.5);
                    MyGrid.RenderTransform = rt;
                }
            }

            if (e.Orientation == PageOrientation.LandscapeRight)
            {
                this.Dispatcher.BeginInvoke(delegate()
                {
                    txtDebug.Text = "LandscapeRight";
                    // Rotate for LandscapeRight orientation.
                    //videoRecorderBrush.RelativeTransform =
                    //new CompositeTransform() { CenterX = 0.5, CenterY = 0.5, Rotation = 180 };
                    //rotate logo
                    if (logo != null)
                    {
                        RotateTransform rt = new RotateTransform();
                        rt.Angle = -90;
                        //default rotation is around top left corner of the control,
                        //but you sometimes want to rotate around the center of the control
                        //to do that, you need to set the RenderTransFormOrigin
                        //of the item you're going to rotate
                        //I did not test this approach, maybe You're going to need to use actual coordinates
                        //so this bit is for information purposes only
                        logo.RenderTransformOrigin = new Point(0.5, 0.5);
                        logo.RenderTransform = rt;
                    }

                    //rotate MyGrid
                    if (MyGrid != null)
                    {
                        RotateTransform rt = new RotateTransform();
                        rt.Angle = -90;
                        //default rotation is around top left corner of the control,
                        //but you sometimes want to rotate around the center of the control
                        //to do that, you need to set the RenderTransFormOrigin
                        //of the item you're going to rotate
                        //I did not test this approach, maybe You're going to need to use actual coordinates
                        //so this bit is for information purposes only
                        MyGrid.RenderTransformOrigin = new Point(0.5, 0.5);
                        MyGrid.RenderTransform = rt;
                    }
                }); 

            }
            if (e.Orientation == PageOrientation.PortraitDown)
            {
                this.Dispatcher.BeginInvoke(delegate()
                {
                    txtDebug.Text = "PortraitDown";
                    videoRecorderBrush.RelativeTransform =
                        new CompositeTransform() { CenterX = 0.5, CenterY = 0.5, Rotation = 270 };
                });
            }
        }
    }

    // Hardware shutter button Hot-Actions.
    private void OnButtonHalfPress(object sender, EventArgs e)
    {
        //toggle between video- play and pause
        try
        {
            this.Dispatcher.BeginInvoke(delegate()
            {
                if (StartPlayback.IsEnabled)
                {
                    PlayVideo();
                }
                if (PausePlayback.IsEnabled)
                {
                    PauseVideo();
                }
            });

        }
        catch (Exception focusError)
        {
            // Cannot focus when a capture is in progress.
            this.Dispatcher.BeginInvoke(delegate()
            {
                txtDebug.Text = focusError.Message;
            });
        }
    }
    private void OnButtonFullPress(object sender, EventArgs e)
    {
        // Focus when a capture is not in progress.
        try
        {
            this.Dispatcher.BeginInvoke(delegate()
            {
                if (vcDevice != null)
                {
                    //stopVideoPlayer if it's playing back
                    if (currentAppState == ButtonState.Playback || currentAppState == ButtonState.Paused)
                    {
                        DisposeVideoPlayer();
                        StartVideoPreview();
                    }

                    if (StartRecording.IsEnabled)
                    {
                        StartVideoRecording();
                    }
                    else
                    {
                        StopVideoRecording();
                    }
                }

            });
        }
        catch (Exception focusError)
        {
            // Cannot focus when a capture is in progress.
            this.Dispatcher.BeginInvoke(delegate()
            {
                txtDebug.Text = focusError.Message;
            });
        }
    }
    private void OnButtonRelease(object sender, EventArgs e)
    {
        try
        {
            this.Dispatcher.BeginInvoke(delegate()
            {

            });

        }
        catch (Exception focusError)
        {
            // Cannot focus when a capture is in progress.
            this.Dispatcher.BeginInvoke(delegate()
            {
                txtDebug.Text = focusError.Message;
            });
        }
    }

    // Update the buttons and text on the UI thread based on app state.
    private void UpdateUI(ButtonState currentButtonState, string statusMessage)
    {
        // Run code on the UI thread.
        Dispatcher.BeginInvoke(delegate
        {

            switch (currentButtonState)
            {
                // When the camera is not supported by the phone.
                case ButtonState.CameraNotSupported:
                    StartRecording.IsEnabled = false;
                    StopPlaybackRecording.IsEnabled = false;
                    StartPlayback.IsEnabled = false;
                    PausePlayback.IsEnabled = false;
                    break;

                // First launch of the application, so no video is available.
                case ButtonState.Initialized:
                    StartRecording.IsEnabled = true;
                    StopPlaybackRecording.IsEnabled = false;
                    StartPlayback.IsEnabled = false;
                    PausePlayback.IsEnabled = false;
                    break;

                // Ready to record, so video is available for viewing.
                case ButtonState.Ready:
                    StartRecording.IsEnabled = true;
                    StopPlaybackRecording.IsEnabled = false;
                    StartPlayback.IsEnabled = true;
                    PausePlayback.IsEnabled = false;
                    break;

                // Video recording is in progress.
                case ButtonState.Recording:
                    StartRecording.IsEnabled = false;
                    StopPlaybackRecording.IsEnabled = true;
                    StartPlayback.IsEnabled = false;
                    PausePlayback.IsEnabled = false;
                    break;

                // Video playback is in progress.
                case ButtonState.Playback:
                    StartRecording.IsEnabled = false;
                    StopPlaybackRecording.IsEnabled = true;
                    StartPlayback.IsEnabled = false;
                    PausePlayback.IsEnabled = true;
                    break;

                // Video playback has been paused.
                case ButtonState.Paused:
                    StartRecording.IsEnabled = false;
                    StopPlaybackRecording.IsEnabled = true;
                    StartPlayback.IsEnabled = true;
                    PausePlayback.IsEnabled = false;
                    break;

                default:
                    break;
            }

            // Display a message.
            txtDebug.Text = statusMessage;

            // Note the current application state.
            currentAppState = currentButtonState;
        });
    }

    public async void InitializeVideoRecorder()
    {
        try
        {
            if (_cs == null)
            {
                _cs = new CaptureSource();
                fileSink = new FileSink();
                _cd = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();

                CameraSensorLocation location = CameraSensorLocation.Back;
                var captureResolutions =
                    AudioVideoCaptureDevice.GetAvailableCaptureResolutions(location);
                vcDevice = await AudioVideoCaptureDevice.OpenAsync(location, captureResolutions[0]);
                vcDevice.RecordingFailed += OnCaptureFailed;
                vcDevice.VideoEncodingFormat = CameraCaptureVideoFormat.H264;
                vcDevice.AudioEncodingFormat = CameraCaptureAudioFormat.Aac;

                // Initialize the camera if it exists on the phone.
                if (vcDevice != null)
                {
                    //initialize fileSink
                    await InitializeFileSink();

                    // Create the VideoBrush for the viewfinder.
                    videoRecorderBrush = new VideoBrush();
                    videoRecorderBrush.SetSource(_cs);

                    // Display the viewfinder image on the rectangle.
                    viewfinderRectangle.Fill = videoRecorderBrush;

                    _cs.Start();

                    // Set the button state and the message.
                    UpdateUI(ButtonState.Initialized, "Tap record to start recording...");
                }
                else
                {
                    // Disable buttons when the camera is not supported by the phone.
                    UpdateUI(ButtonState.CameraNotSupported, "A camera is not supported on this phone.");
                }
            }
        }
        catch(Exception ex)
        {
            MessageBox.Show("InitializeVideoRecorder Error:\n" + ex.Message);
        }
    }
    public async Task InitializeFileSink()
    {
        StorageFolder isoStore = ApplicationData.Current.LocalFolder;
        sfVideoFile = await isoStore.CreateFileAsync(
            isoVideoFileName,
          CreationCollisionOption.ReplaceExisting);
    }
    private void OnCaptureFailed(AudioVideoCaptureDevice sender, CaptureFailedEventArgs args)
    {
        MessageBox.Show(args.ToString());
    }

    private void OnCaptureSourceFailed(object sender, ExceptionRoutedEventArgs e)
    {
        MessageBox.Show(e.ErrorException.Message.ToString());
    }

    // Set the recording state: display the video on the viewfinder.
    private void StartVideoPreview()
    {
        try
        {
            // Display the video on the viewfinder.
            if (_cs.VideoCaptureDevice != null
            && _cs.State == CaptureState.Stopped)
            {
                // Add captureSource to videoBrush.
                videoRecorderBrush.SetSource(_cs);

                // Add videoBrush to the visual tree.
                viewfinderRectangle.Fill = videoRecorderBrush;

                _cs.Start();

                // Set the button states and the message.
                UpdateUI(ButtonState.Ready, "Ready to record.");

                //Create optional Resolutions
            }
        }
        // If preview fails, display an error.
        catch (Exception e)
        {
            this.Dispatcher.BeginInvoke(delegate()
            {
                txtDebug.Text = "ERROR: " + e.Message.ToString();
            });
        }
    }
    // Set recording state: start recording.
    private void StartVideoRecording()
    {
        try
        {
            // Connect fileSink to captureSource.
            if (_cs.VideoCaptureDevice != null
                && _cs.State == CaptureState.Started)
            {
                _cs.Stop();

                // Connect the input and output of fileSink.
                fileSink.CaptureSource = _cs;
                fileSink.IsolatedStorageFileName = isoVideoFileName;
            }

            // Begin recording.
            if (_cs.VideoCaptureDevice != null
                && _cs.State == CaptureState.Stopped)
            {
                _cs.Start();
            }

            // Set the button states and the message.
            UpdateUI(ButtonState.Recording, "Recording...");
            StartTimer();
        }

        // If recording fails, display an error.
        catch (Exception e)
        {
            this.Dispatcher.BeginInvoke(delegate()
            {
                txtDebug.Text = "ERROR: " + e.Message.ToString();
            });
        }
    }
    // Set the recording state: stop recording.
    private void StopVideoRecording()
    {
        try
        {
            // Stop recording.
            if (_cs.VideoCaptureDevice != null
            && _cs.State == CaptureState.Started)
            {
                _cs.Stop();

                // Disconnect fileSink.
                fileSink.CaptureSource = null;
                fileSink.IsolatedStorageFileName = null;

                // Set the button states and the message.
                UpdateUI(ButtonState.Stopped, "Preparing viewfinder...");
                StopTimer();
                StartVideoPreview();
            }
        }
        // If stop fails, display an error.
        catch (Exception e)
        {
            this.Dispatcher.BeginInvoke(delegate()
            {
                txtDebug.Text = "ERROR: " + e.Message.ToString();
            });
        }
    }
    // Start the video recording.
    private void StartRecording_Click(object sender, EventArgs e)
    {
        // Avoid duplicate taps.
        StartRecording.IsEnabled = false;
        StartVideoRecording();
    }
    private void DisposeVideoRecorder()
    {
        if (_cs != null)
        {
            // Stop captureSource if it is running.
            if (_cs.VideoCaptureDevice != null
                && _cs.State == CaptureState.Started)
            {
                _cs.Stop();
            }

            // Remove the event handler for captureSource.
            _cs.CaptureFailed -= OnCaptureFailed;

            // Remove the video recording objects.
            _cs = null;
            vcDevice = null;
            fileSink = null;
            videoRecorderBrush = null;
        }
    }

    private void OnCaptureFailed(object sender, ExceptionRoutedEventArgs e)
    {
        throw new NotImplementedException();
    }

    //STOP WATCH
    private void StartTimer()
    {
        dispatcherTimer = new System.Windows.Threading.DispatcherTimer();

        dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);

        dispatcherTimer.Interval = new TimeSpan(0, 0, 1);

        dispatcherTimer.Start();
        startTime = System.DateTime.Now;
    }
    private void StopTimer()
    {
        dispatcherTimer.Stop();
    }
    private void dispatcherTimer_Tick(object sender, EventArgs e)
    {
        System.DateTime now = System.DateTime.Now;
        txtRecTime.Text = now.Subtract(startTime).ToString();
    } 

the error is thrown inside initializeVideoRecorder().

John Saunders
  • 160,644
  • 26
  • 247
  • 397

2 Answers2

1

Seems like you're code is too long to analyze as @john mentioned in the comment. But since you've suggested to post some helpful links here you go: Following these steps here in msdn, would work without any issues as I've tried it once.

If you really need a sample to kick off, there's one from msdn. Hope you'll maximize the utilities.

Kulasangar
  • 9,046
  • 5
  • 51
  • 82
  • . There is only one place you have to look in the above code and it's in InitializeVideoRecorder() method because that is where the error is thrown. I did start with that tutorial but the functionality is limited. I want to use AudioVideoCaptureDevice from using Windows.Phone.Media.Capture instead of VideoCaptureDevice. from Microsoft.Devices to capture video because I can change the resolution, format ect. If you can help THANK YOU in advance. – Clint William Theron Feb 19 '15 at 12:38
  • 1
    http://stackoverflow.com/questions/16906456/ & http://developer.nokia.com/community/wiki/Audio_recording_and_playback_options_in_Windows_Phone#Other_available_audio_APIs – Kulasangar Feb 19 '15 at 14:36
  • I'm not sure how to set the capture source, the filesink and the AudioVideoCaptureDevice(AVCD). I set the videobrush.setsource =AVCD so the preview is working. Since the videobrush source is AVCD I'm not sure what to do with CaptureSource _cs=new CaptureSource and _cd = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice(); What should I do with those two references? The second link you gave Kulasangar is about capturing audio and I want both Audio and Video. Thank you. – Clint William Theron Feb 20 '15 at 07:46
0

I figured out I have to pass the capture device to the videobrush to make it work. I'm still not sure where and if I should use CaptureSource when capturing with AudioVideoCaptureDevice. Anyway here is the solution code:

                // Create the VideoBrush for the viewfinder.
                videoRecorderBrush = new VideoBrush();
                videoRecorderBrush.SetSource(vcDevice); //substitute vcDevice with captureSource - vcDevice is the reference of AudioVideoCaptureDevice

                // Display the viewfinder image on the rectangle.
                viewfinderRectangle.Fill = videoRecorderBrush;