Search code examples
c#uwpmjpegmediacapture

MediaFrameReader throws ArgementException when setting MJPG format?


I'm trying to get each frame's bitmap from the webcam.

I followed this Microsoft tutorial Process media frames with MediaFrameReader. Some other video formats (YUY2, NV12...) are working fine, but selecting and setting MJPG format will cause ArgumentException: 'Value does not fall within the expected range.' at MediaFrameReader.TryAcquireLatestFrame().

This is my working code for setting up webcam media source and handling FrameArrived event:

private async Task StartReadFrameAsync()
{
    MediaFrameSourceInfo colorSourceInfo = null;
    MediaFrameSourceGroup selectedGroup = null;
    var frameSourceGroups = await MediaFrameSourceGroup.FindAllAsync();
    foreach (var sourceGroup in frameSourceGroups)
    {
        foreach (var sourceInfo in sourceGroup.SourceInfos)
        {
            if (sourceInfo.MediaStreamType == MediaStreamType.VideoRecord && sourceInfo.SourceKind == MediaFrameSourceKind.Color)
            {
                colorSourceInfo = sourceInfo;
                break;
            }
        }
        if (colorSourceInfo != null)
        {
            selectedGroup = sourceGroup;
            break;
        }
    }

    var settings = new MediaCaptureInitializationSettings
            {
                VideoDeviceId = deviceId, 
                SourceGroup = selectedGroup, 
                MemoryPreference = MediaCaptureMemoryPreference.Cpu
            };
    var mediaCapture = new MediaCapture();
    await mediaCapture.InitializeAsync(settings);

    var colorFrameSource = mediaCapture.FrameSources[colorSourceInfo.Id];
    var preferredFormat = colorFrameSource.SupportedFormats.FirstOrDefault(format =>
    {
        return format.Subtype == MediaEncodingSubtypes.Mjpg && format.VideoFormat.Width >= 720;
    });
    if (preferredFormat == null)    
         return;    

    await colorFrameSource.SetFormatAsync(preferredFormat);
    mediaFrameReader = await mediaCapture.CreateFrameReaderAsync(colorFrameSource, MediaEncodingSubtypes.Mjpg);
    mediaFrameReader.FrameArrived += MediaFrameReader_FrameArrived;
    await mediaFrameReader.StartAsync();
}

private async void MediaFrameReader_FrameArrived(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
    var mediaFrameReference = sender.TryAcquireLatestFrame();  // <- throws ArgementException 
    var videoMediaFrame = mediaFrameReference?.VideoMediaFrame;
    var softwareBitmap = videoMediaFrame?.SoftwareBitmap;
    //...
}

I tested two webcam cameras, they had MJPG format support, and I also checked that previewing MJPG format in a CaptureElement control does work. Only TryAcquireLatestFrame() in event MediaFrameReader_FrameArrived will throw.

Question:

What am I doing wrong, that MediaFrameReader cannot acquire a MJPG frame?


Solution

  • MediaFrameReader throws ArgementException when setting MJPG format?

    Please refer to official code sample here. For color sources, we accept anything and request that it be converted to Bgra8

    If you want to set FrameSource as mjpg for camera, please call SetFormatAsync method.

     if (format != null && !format.HasSameFormat(_source.CurrentFormat))
     {
        await _source.SetFormatAsync(format.Format);
        _logger.Log($"Format set to {format.DisplayName}");
     }
    

    And you could also use above code sample test if your camera support mjpg frame. (my device: logic camera c310 not support mjpg).