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?