Console template application MediaCapture fails to record video

3

I'm trying to use MediaCapture on a minimal C# UWP console template - based application to capture video. Initializing the MediaCapture with InitializeAsync() works, but actually starting the recording fails with error code 0xc00d3e82 / MF_E_INVALID_STATE_TRANSITION.

I've installed C# UWP console application templates to Visual Studio 2017 to work on a minimal application (GUI is unnecessary in this case, thus console application) that would capture video using MediaCapture. The minimum target is Windows build 1803, since that's the minimum required by the C# UWP console applications.

I have tried running the methods that require await with ConfigureAwait(false), but this doesn't seem to make any difference.

Regarding the capabilities, as UWP console applications will not display permission prompts for acquiring access to camera, microphone etc, I'm granting them manually via the application's settings before running it. I believe all necessary capabilities are included in the manifest, as the application does work under some circumstances (see paragraph after the code block).

Minimal reproducible example, should build and run with C# UWP console application template:

using System;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Media.Capture;
using Windows.Media.MediaProperties;
using Windows.Storage;

namespace MinimalMediaCaptureConsoleTest
{
    class Program
    {
        private static void MediaCapture_Failed(MediaCapture sender, MediaCaptureFailedEventArgs errorEventArgs)
        {
            Console.WriteLine("Media capture failed: error message: '" + errorEventArgs.Message + "', code: " + errorEventArgs.Code.ToString("X"));
        }
        static void Main(string[] args)
        {
            Task t = MainAsync(args);
            t.Wait();
            Task.Delay(2000).Wait(); // give time to see result before exiting
        }
        static async Task MainAsync(string[] args)
        {
            var videoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
            var cameraDevice = videoDevices[0];
            if (cameraDevice == null)
            {
                Console.WriteLine("No camera device found!");
                return;
            }

            MediaCapture mc = new MediaCapture();
            MediaCaptureInitializationSettings mcSettings = new MediaCaptureInitializationSettings
            {
                AudioDeviceId = "",
                VideoDeviceId = cameraDevice.Id,
                StreamingCaptureMode = StreamingCaptureMode.Video,
                PhotoCaptureSource = PhotoCaptureSource.VideoPreview
            };
            mc.Failed += MediaCapture_Failed;
            try
            {
                await mc.InitializeAsync(mcSettings);

            } catch (UnauthorizedAccessException e)
            {
                Console.WriteLine("No access to the camera: " + e);
            }

            LowLagMediaRecording mediaRecording = null;
            var myVideos = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Videos);
            StorageFile file = await myVideos.SaveFolder.CreateFileAsync("mytestvid.mp4", CreationCollisionOption.GenerateUniqueName);
            mediaRecording = await mc.PrepareLowLagRecordToStorageFileAsync(
                      MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto), file);

            await mediaRecording.StartAsync();
            Console.WriteLine("Started recording, press enter to stop");
            Console.ReadLine();
            await mediaRecording.StopAsync();
        }
    }
}

The code is run in a separate async task launched from the console application's Main(), however I've also tried making the Main itself an async task and running the MediaCapture code directly from there, with no difference in behaviour.

Interestingly, if I run the application with the Visual Studio's debugger or attach the debugger to the process before attempting to record video, the video capture works just fine. However, if run from command prompt / Powershell or start menu, calling LowLagMediaRecording instance's StartAsync() method will result to aforementioned error code 0xc00d3e82 / MF_E_INVALID_STATE_TRANSITION and no video is recorded.

Any ideas what's the problem when run without the debugger and how to fix it are very much appreciated.

c#
uwp
mediacapture
asked on Stack Overflow May 31, 2019 by ExplodingDeveloper • edited Jun 6, 2019 by ExplodingDeveloper

1 Answer

0

Is there any particular reason for this to be a UWP app? (there may be certain issues/complications with UWP console apps and background recording) If UWP is not important, you can use MediaCapture in a Win32 console app as well which seems better suited (and a simpler solution) in this situation- for C# refer to - https://github.com/microsoft/WindowsVisionSkillsPreview/blob/master/samples/SentimentAnalyzerCustomSkill/cs/Apps/FaceSentimentAnalysisApp_.NETCore3.0/FaceSentimentAnalysisApp_.NETCore3.0.csproj

Note- This C# sample does more than just Windows MediaCapture. However, you can ignore the other stuff and refer to just the project configuration in the sample and use the same C# code that you have at present. You will require .Net Core 3.0 and Visual Studio 2019 preview to use this.
The following lines from the above .csproj file are improtant: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETCore\v4.5\System.Runtime.WindowsRuntime.dll

<Reference Include="Windows">
  <HintPath>C:\Program Files (x86)\Windows Kits\10\UnionMetadata\Facade\Windows.WinMD</HintPath>
  <IsWinMDFile>true</IsWinMDFile>
</Reference>

<Reference Include="Windows.Foundation.FoundationContract">
  <HintPath>C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd</HintPath>
  <IsWinMDFile>true</IsWinMDFile>
</Reference>

<Reference Include="Windows.Foundation.UniversalApiContract">
  <HintPath>C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Foundation.UniversalApiContract\7.0.0.0\Windows.Foundation.UniversalApiContract.winmd</HintPath>
  <IsWinMDFile>true</IsWinMDFile>
</Reference>

Alternatively for C++ refer to - https://github.com/microsoft/Windows-Camera/tree/master/Samples/WMCConsole_winrtcpp

answered on Stack Overflow Jun 4, 2019 by SpeedCoder

User contributions licensed under CC BY-SA 3.0