/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Displays the video formats for the currently selected video device. This /// is more complicated than it looks. We have to open the video source, convert /// that to a Media Source and then interrogate the that source to find a list /// of video formats. /// </summary> /// <history> /// 01 Nov 18 Cynic - Started /// </history> private void DisplayVideoFormatsForCurrentCaptureDevice() { IMFSourceReaderAsync tmpSourceReader = null; List <TantaMFVideoFormatContainer> formatList; HResult hr; try { // clear what we have now listViewSupportedFormats.Clear(); // reset this listViewSupportedFormats.ListViewItemSorter = null; // get the currently selected device TantaMFDevice currentDevice = (TantaMFDevice)comboBoxCaptureDevices.SelectedItem; if (currentDevice == null) { return; } // open up the media source tmpSourceReader = TantaWMFUtils.CreateSourceReaderAsyncFromDevice(currentDevice, null); if (tmpSourceReader == null) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice, CreateSourceReaderAsyncFromDevice did not return a media source. Cannot continue."); } // now get a list of all supported formats from the video device hr = TantaMediaTypeInfo.GetSupportedVideoFormatsFromSourceReaderInFormatContainers(currentDevice, tmpSourceReader, 100, out formatList); if (hr != HResult.S_OK) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice, GetSupportedVideoFormatsFromSourceReaderInFormatContainers failed. HR=" + hr.ToString()); } if (formatList == null) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice, GetSupportedVideoFormatsFromSourceReaderInFormatContainers did not return a format list. Cannot continue."); } // now display the formats foreach (TantaMFVideoFormatContainer videoFormat in formatList) { ListViewItem lvi = new ListViewItem(new[] { videoFormat.SubTypeAsString, videoFormat.FrameSizeAsString, videoFormat.FrameRateAsString, videoFormat.FrameRateMaxAsString, videoFormat.AllAttributes }); lvi.Tag = videoFormat; listViewSupportedFormats.Items.Add(lvi); } listViewSupportedFormats.Columns.Add("Type", 70); listViewSupportedFormats.Columns.Add("FrameSize WxH", 100); listViewSupportedFormats.Columns.Add("FrameRate f/s", 100); listViewSupportedFormats.Columns.Add("FrameRateMax f/s", 100); listViewSupportedFormats.Columns.Add("All Attributes", 2500); } finally { if (tmpSourceReader != null) { // close and release Marshal.ReleaseComObject(tmpSourceReader); tmpSourceReader = null; } } }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Gets a TantaMFVideoFormatContainer from an IMFMediaType /// </summary> /// <returns>S_OK for success, nz for fail</returns> /// <param name="mediaTypeObj">the media type object</param> /// <param name="currentDevice">the video device that created the source reader</param> /// <history> /// 01 Nov 18 Cynic - Started /// </history> public static TantaMFVideoFormatContainer GetVideoFormatContainerFromMediaTypeObject(IMFMediaType mediaTypeObj, TantaMFDevice currentDevice) { HResult hr; Guid majorType; Guid subType; int attributeCount; int frameSizeWidth; int frameSizeHeight; int frameRate; int frameRateDenominator; int frameRateMin; int frameRateMinDenominator; int frameRateMax; int frameRateMaxDenominator; if (mediaTypeObj == null) { // we failed throw new Exception("GetVideoFormatContainerFromMediaTypeObject failedmediaTypeObj == null"); } if (currentDevice == null) { // we failed throw new Exception("GetVideoFormatContainerFromMediaTypeObject currentDevice == null"); } // get the formats for this type hr = GetSupportedFormatsFromMediaType(mediaTypeObj, out majorType, out subType, out attributeCount, out frameSizeWidth, out frameSizeHeight, out frameRate, out frameRateDenominator, out frameRateMin, out frameRateMinDenominator, out frameRateMax, out frameRateMaxDenominator); if (hr != HResult.S_OK) { // we failed throw new Exception("GetSupportedVideoFormatsFromSourceReaderInFormatContainers failed on call to GetSupportedFormatsFromMediaType, retVal=" + hr.ToString()); } // enumerate all of the possible Attributes so we can see which ones are present that we did not report on StringBuilder allAttrs = new StringBuilder(); hr = EnumerateAllAttributeNamesInMediaTypeAsText(mediaTypeObj, attributeCount, out allAttrs); if (hr != HResult.S_OK) { // we failed throw new Exception("GetSupportedVideoFormatsFromSourceReaderInFormatContainers failed on call to EnumerateAllAttributeNamesInMediaTypeAsText, retVal=" + hr.ToString()); } // create the container here TantaMFVideoFormatContainer tmpContainer = new TantaMFVideoFormatContainer(); tmpContainer.MajorType = majorType; tmpContainer.SubType = subType; tmpContainer.AttributeCount = attributeCount; tmpContainer.FrameSizeWidth = frameSizeWidth; tmpContainer.FrameSizeHeight = frameSizeHeight; tmpContainer.FrameRate = frameRate; tmpContainer.FrameRateDenominator = frameRateDenominator; tmpContainer.FrameRateMin = frameRateMin; tmpContainer.FrameRateMinDenominator = frameRateMinDenominator; tmpContainer.FrameRateMax = frameRateMax; tmpContainer.FrameRateMaxDenominator = frameRateMaxDenominator; tmpContainer.AllAttributes = allAttrs.ToString(); // we also record the video device here - it is useful to have tmpContainer.VideoDevice = currentDevice; return(tmpContainer); }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Displays the video formats for the currently selected video device. This /// is more complicated than it looks. We have to open the video source, convert /// that to a Media Source and then interrogate the that source to find a list /// of video formats. /// /// NOTE: this function will throw exceptions - caller must trap them /// </summary> /// <history> /// 01 Nov 18 Cynic - Started /// </history> private void DisplayVideoFormatsForCurrentCaptureDevice() { IMFPresentationDescriptor sourcePresentationDescriptor = null; int sourceStreamCount = 0; bool streamIsSelected = false; IMFStreamDescriptor videoStreamDescriptor = null; IMFMediaTypeHandler typeHandler = null; int mediaTypeCount = 0; List <TantaMFVideoFormatContainer> formatList = new List <TantaMFVideoFormatContainer>(); HResult hr; IMFMediaSource mediaSource = null; try { // clear what we have now listViewSupportedFormats.Clear(); // reset this listViewSupportedFormats.ListViewItemSorter = null; // get the currently selected device TantaMFDevice currentDevice = (TantaMFDevice)comboBoxCaptureDevices.SelectedItem; if (currentDevice == null) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice currentDevice == null"); } // use the device symbolic name to create the media source for the video device. Media sources are objects that generate media data. // For example, the data might come from a video file, a network stream, or a hardware device, such as a camera. Each // media source contains one or more streams, and each stream delivers data of one type, such as audio or video. mediaSource = TantaWMFUtils.GetMediaSourceFromTantaDevice(currentDevice); if (mediaSource == null) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice call to mediaSource == null"); } // A presentation is a set of related media streams that share a common presentation time. // we don't need that functionality in this app but we do need to presentation descriptor // to find out the stream descriptors, these will give us the media types on offer hr = mediaSource.CreatePresentationDescriptor(out sourcePresentationDescriptor); if (hr != HResult.S_OK) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice call to mediaSource.CreatePresentationDescriptor failed. Err=" + hr.ToString()); } if (sourcePresentationDescriptor == null) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice call to mediaSource.CreatePresentationDescriptor failed. sourcePresentationDescriptor == null"); } // Now we get the number of stream descriptors in the presentation. // A presentation descriptor contains a list of one or more // stream descriptors. hr = sourcePresentationDescriptor.GetStreamDescriptorCount(out sourceStreamCount); if (hr != HResult.S_OK) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice call to sourcePresentationDescriptor.GetStreamDescriptorCount failed. Err=" + hr.ToString()); } if (sourceStreamCount == 0) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice call to sourcePresentationDescriptor.GetStreamDescriptorCount failed. sourceStreamCount == 0"); } // look for the video stream for (int i = 0; i < sourceStreamCount; i++) { // we require the major type to be video Guid guidMajorType = TantaWMFUtils.GetMajorMediaTypeFromPresentationDescriptor(sourcePresentationDescriptor, i); if (guidMajorType != MFMediaType.Video) { continue; } // we also require the stream to be enabled hr = sourcePresentationDescriptor.GetStreamDescriptorByIndex(i, out streamIsSelected, out videoStreamDescriptor); if (hr != HResult.S_OK) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice call to sourcePresentationDescriptor.GetStreamDescriptorByIndex(v) failed. Err=" + hr.ToString()); } if (videoStreamDescriptor == null) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice call to sourcePresentationDescriptor.GetStreamDescriptorByIndex(v) failed. videoStreamDescriptor == null"); } // if the stream is not selected (enabled) look for the next if (streamIsSelected == false) { Marshal.ReleaseComObject(videoStreamDescriptor); videoStreamDescriptor = null; continue; } // Get the media type handler for the stream. IMFMediaTypeHandler // interface is a standard way of looking at the media types on an stream hr = videoStreamDescriptor.GetMediaTypeHandler(out typeHandler); if (hr != HResult.S_OK) { throw new Exception("call to videoStreamDescriptor.GetMediaTypeHandler failed. Err=" + hr.ToString()); } if (typeHandler == null) { throw new Exception("call to videoStreamDescriptor.GetMediaTypeHandler failed. typeHandler == null"); } // Now we get the number of media types in the stream descriptor. hr = typeHandler.GetMediaTypeCount(out mediaTypeCount); if (hr != HResult.S_OK) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice call to typeHandler.GetMediaTypeCount failed. Err=" + hr.ToString()); } if (mediaTypeCount == 0) { throw new Exception("DisplayVideoFormatsForCurrentCaptureDevice call to typeHandler.GetMediaTypeCount failed. mediaTypeCount == 0"); } // now loop through each media type for (int mediaTypeId = 0; mediaTypeId < mediaTypeCount; mediaTypeId++) { // Now we have the handler, get the media type. IMFMediaType workingMediaType = null; hr = typeHandler.GetMediaTypeByIndex(mediaTypeId, out workingMediaType); if (hr != HResult.S_OK) { throw new Exception("GetMediaTypeFromStreamDescriptorById call to typeHandler.GetMediaTypeByIndex failed. Err=" + hr.ToString()); } if (workingMediaType == null) { throw new Exception("GetMediaTypeFromStreamDescriptorById call to typeHandler.GetMediaTypeByIndex failed. workingMediaType == null"); } TantaMFVideoFormatContainer tmpContainer = TantaMediaTypeInfo.GetVideoFormatContainerFromMediaTypeObject(workingMediaType, currentDevice); if (tmpContainer == null) { // we failed throw new Exception("GetSupportedVideoFormatsFromSourceReaderInFormatContainers failed on call to GetVideoFormatContainerFromMediaTypeObject"); } // now add it formatList.Add(tmpContainer); Marshal.ReleaseComObject(workingMediaType); workingMediaType = null; } // NOTE: we only do the first enabled video stream we find. // it is possible to have more but our control // cannot cope with that break; } // now display the formats foreach (TantaMFVideoFormatContainer videoFormat in formatList) { ListViewItem lvi = new ListViewItem(new[] { videoFormat.SubTypeAsString, videoFormat.FrameSizeAsString, videoFormat.FrameRateAsString, videoFormat.FrameRateMaxAsString, videoFormat.AllAttributes }); lvi.Tag = videoFormat; listViewSupportedFormats.Items.Add(lvi); } listViewSupportedFormats.Columns.Add("Type", 70); listViewSupportedFormats.Columns.Add("FrameSize WxH", 100); listViewSupportedFormats.Columns.Add("FrameRate f/s", 100); listViewSupportedFormats.Columns.Add("FrameRateMax f/s", 100); listViewSupportedFormats.Columns.Add("All Attributes", 2500); } finally { // close and release if (mediaSource != null) { Marshal.ReleaseComObject(mediaSource); mediaSource = null; } if (sourcePresentationDescriptor != null) { Marshal.ReleaseComObject(sourcePresentationDescriptor); sourcePresentationDescriptor = null; } if (videoStreamDescriptor != null) { Marshal.ReleaseComObject(videoStreamDescriptor); videoStreamDescriptor = null; } if (typeHandler != null) { Marshal.ReleaseComObject(typeHandler); typeHandler = null; } } }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Gets a list of all supported video formats from a video source device /// as a list of TantaMFVideoFormatContainer's /// /// </summary> /// <returns>S_OK for success, nz for fail</returns> /// <param name="currentDevice">the video device that created the source reader</param> /// <param name="sourceReader">the source reader object</param> /// <param name="maxFormatsToTestFor">the max number of formats we test for</param> /// <param name="formatList">the list of video formats supported by the SourceReader</param> /// <history> /// 01 Nov 18 Cynic - Started /// </history> public static HResult GetSupportedVideoFormatsFromSourceReaderInFormatContainers(TantaMFDevice currentDevice, IMFSourceReaderAsync sourceReader, int maxFormatsToTestFor, out List <TantaMFVideoFormatContainer> formatList) { IMFMediaType mediaTypeObj = null; HResult hr; // init this, we never return null here formatList = new List <TantaMFVideoFormatContainer>(); // sanity check if (currentDevice == null) { return(HResult.E_FAIL); } if (sourceReader == null) { return(HResult.E_FAIL); } try { for (int typeIndex = 0; typeIndex < maxFormatsToTestFor; typeIndex++) { // test this hr = sourceReader.GetNativeMediaType(TantaWMFUtils.MF_SOURCE_READER_FIRST_VIDEO_STREAM, typeIndex, out mediaTypeObj); if (hr == HResult.MF_E_NO_MORE_TYPES) { // we are all done. The outSb container has been populated return(HResult.S_OK); } else if (hr != HResult.S_OK) { // we failed throw new Exception("GetSupportedVideoFormatsFromSourceReaderInFormatContainers failed on call to GetNativeMediaType, retVal=" + hr.ToString()); } // get a format container from the media type TantaMFVideoFormatContainer tmpContainer = GetVideoFormatContainerFromMediaTypeObject(mediaTypeObj, currentDevice); if (tmpContainer == null) { // we failed throw new Exception("GetSupportedVideoFormatsFromSourceReaderInFormatContainers failed on call to GetVideoFormatContainerFromMediaTypeObject"); } // now add it formatList.Add(tmpContainer); } } finally { // always release our mediaType if we have one if (mediaTypeObj != null) { Marshal.ReleaseComObject(mediaTypeObj); mediaTypeObj = null; } } // all done return(HResult.S_OK); }