John S
John S

Reputation: 573

UWP The stream number provided was invalid PreviewState

I am trying to set up a preview stream and recording loop with buttons to save the last 10 mins, 30 secs etc. This was working just fine until I started adding the code to handle rotation.

This is the line that throws.

await _mediaCapture.SetEncodingPropertiesAsync(MediaStreamType.VideoPreview, 
videoEncodingProperties, mediaPropertySet);

here is the whole method

public async Task<MediaCapture> PrepareRecordingAsync() {
            try {
                _mediaCapture = new MediaCapture();
                var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
                var desiredDevice = allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == Panel.Back);
                _cameraDevice = desiredDevice ?? allVideoDevices.FirstOrDefault();
                _rotationHelper = new CameraRotationHelper(_cameraDevice.EnclosureLocation);

                _mediaCapture.Failed += MediaCapture_Failed;

                var settings = new MediaCaptureInitializationSettings { VideoDeviceId = _cameraDevice.Id };
                await _mediaCapture.InitializeAsync(settings);

                var encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto);

                var rotationAngle = CameraRotationHelper.ConvertSimpleOrientationToClockwiseDegrees(_rotationHelper.GetCameraCaptureOrientation());
                Guid RotationKey = new Guid("C380465D-2271-428C-9B83-ECEA3B4A85C1");
                encodingProfile.Video.Properties.Add(RotationKey, PropertyValue.CreateInt32(rotationAngle));
                var videoEncodingProperties = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview);
                MediaPropertySet mediaPropertySet = new MediaPropertySet();
                await _mediaCapture.SetEncodingPropertiesAsync(MediaStreamType.VideoPreview, videoEncodingProperties, mediaPropertySet);

                _ras = new InMemoryRandomAccessStream();
                _recording = await _mediaCapture.PrepareLowLagRecordToStreamAsync(encodingProfile, _ras);

                DisplayInformation.AutoRotationPreferences = DisplayOrientations.Portrait;
                ConcurrentRecordAndPhotoSupported = _mediaCapture.MediaCaptureSettings.ConcurrentRecordAndPhotoSupported;
            } catch (UnauthorizedAccessException) {
                // This will be thrown if the user denied access to the camera in privacy settings
                System.Diagnostics.Debug.WriteLine("The app was denied access to the camera");
            } catch (Exception ex) {
                System.Diagnostics.Debug.WriteLine("MediaCapture initialization failed. {0}", ex.Message);
            }
            return _mediaCapture;
        }

None of the solutions found via google search are any help.

This is basically a modification of the MSDN How-to's.

EDIT: If I change the offending line to the following then it works fine.

_mediaCapture.SetPreviewRotation(VideoRotation.Clockwise90Degrees);

Upvotes: 2

Views: 1093

Answers (1)

Sunteen Wu
Sunteen Wu

Reputation: 10627

I can reproduce your issue on my side, it will throw the error exception at code line await _mediaCapture.SetEncodingPropertiesAsync(...);

The stream number provided was invalid. PreviewState

According to the SetEncodingPropertiesAsync method

Note that this rotation is performed by the consumer of the stream, such as the CaptureElement or a video player app, while the actual pixels in the stream still retain their original orientation.

This method performed by the consumer of the stream. It seems like that you need to invoke StartPreviewAsync() firstly before you setting the preview rotation so that you have preview stream. More details please reference the "Add orientation data to the camera preview stream" section of Handle device orientation with MediaCapture.

After starting the preview, call the helper method SetPreviewRotationAsync to set the preview rotation.

So updating your code snippet as follows it will work.

_mediaCapture = new MediaCapture();
var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
var desiredDevice = allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back);
_cameraDevice = desiredDevice ?? allVideoDevices.FirstOrDefault();
_rotationHelper = new CameraRotationHelper(_cameraDevice.EnclosureLocation);
_mediaCapture.Failed += MediaCapture_Failed;
var settings = new MediaCaptureInitializationSettings { VideoDeviceId = _cameraDevice.Id };
await _mediaCapture.InitializeAsync(settings);

//Add the preview code snippet
PreviewControl.Source = _mediaCapture;
await _mediaCapture.StartPreviewAsync(); 

var encodingProfile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto);
var rotationAngle = CameraRotationHelper.ConvertSimpleOrientationToClockwiseDegrees(_rotationHelper.GetCameraCaptureOrientation());
Guid RotationKey = new Guid("C380465D-2271-428C-9B83-ECEA3B4A85C1");
encodingProfile.Video.Properties.Add(RotationKey, PropertyValue.CreateInt32(rotationAngle));
var videoEncodingProperties = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview);
MediaPropertySet mediaPropertySet = new MediaPropertySet();
await _mediaCapture.SetEncodingPropertiesAsync(MediaStreamType.VideoPreview, videoEncodingProperties, mediaPropertySet);

More details please reference the official sample.

Upvotes: 2

Related Questions