SharpDX相机流媒体设置MediaType后分辨率未生效问题求助
我正在尝试将网络摄像头流接入应用,目前通过读取最高分辨率帧后自行缩放的方式适配不同分辨率,但希望利用摄像头原生能力直接获取对应分辨率的图像。
当前临时实现(Workaround)
ReadSample(); // 始终读取最高分辨率 var bmp = UnpackTheFrameIntoBitmap(); if(some_different_resolution_set) { bmp = ResizeImageToNewResolution(bmp); } DrawBitmapOnCanvas(bmp);
我尝试遍历摄像头的原生媒体类型,找到支持目标分辨率的nativeType后设置为当前媒体类型,但设置后帧分辨率并未改变——比如我的摄像头最高分辨率为1920x1080,设置800x600对应的MediaType后,获取的采样依然是1920x1080。
尝试的原生分辨率设置代码
var nativeType = FindNativeTypeSupportingResolution(resolution); sourceReader.SetCurrentMediaType(0, nativeType); sourceReader.SetStreamSelection(0, true); while(true) { var sample = sourceReader.ReadSample(0, SourceReaderControlFlags.None, out int readStreamIndex, out SourceReaderFlags readFlags, out long timestamp); if(sample != null) { var mediaBuffer = sample.GetBufferByIndex(0); var sourcePointer = mediaBuffer.Lock(out int maxLength, out int currentLength); var data = new byte[sample.TotalLength]; Marshal.Copy(sourcePointer, data, 0, frameWidth * frameHeight * 4); /// 将数据转换为位图 } }
请问我哪里操作错误?为何设置MediaType对采样无影响?
可能的问题及解决办法
检查
FindNativeTypeSupportingResolution的匹配逻辑
确保找到的nativeType不仅匹配分辨率,还要同时匹配摄像头实际支持的像素格式、帧率等参数。很多摄像头对同一分辨率会提供多个媒体类型(比如YUY2、MJPEG编码格式),如果选了摄像头无法在该分辨率下输出的格式,设置会静默失败,继续使用默认的最高分辨率。可以在找到类型后,调试查看该MediaType的MF_MT_FRAME_SIZE、MF_MT_SUBTYPE、MF_MT_FRAME_RATE等参数是否符合预期。设置媒体类型的时机错误
如果在调用ReadSample之后再修改媒体类型,此时流已经处于活跃状态,修改不会生效。必须在第一次读取样本之前完成媒体类型的设置。如果已经开始读取,需要先关闭流,设置媒体类型后再重新开启:// 先停止流 sourceReader.SetStreamSelection(0, false); // 设置媒体类型 var hr = sourceReader.SetCurrentMediaType(0, nativeType); // 检查设置是否成功 if (hr != S_OK) { /* 处理错误,比如打印错误码 */ } // 重新开启流 sourceReader.SetStreamSelection(0, true);忽略了
SetCurrentMediaType的返回值
这个方法会返回HRESULT结果码,必须检查是否返回S_OK。如果返回失败(比如MF_E_INVALIDMEDIATYPE表示媒体类型不支持,MF_E_STREAMINACTIVE表示流未激活),说明设置未成功,需要根据错误码针对性排查。摄像头实际不支持该分辨率的原生输出
部分摄像头标注的“支持分辨率”是软件缩放实现的,而非硬件原生输出。可以通过IMFMediaTypeHandler::GetMediaTypeByIndex枚举摄像头的所有支持媒体类型,逐一确认是否存在目标分辨率的原生输出类型。流选择的调用顺序问题
确保先关闭流选择,再设置媒体类型,最后重新开启流。如果流处于活跃选中状态,修改媒体类型可能会被拒绝。
内容的提问来源于stack exchange,提问作者Robert

