private HResult OpenMediaSource(IMFMediaSource pSource) { HResult hr = HResult.S_OK; IMFAttributes pAttributes = null; hr = MFExtern.MFCreateAttributes(out pAttributes, 2); if (Succeeded(hr)) { hr = pAttributes.SetUnknown(MFAttributesClsid.MF_SOURCE_READER_ASYNC_CALLBACK, this); } if (Succeeded(hr)) { IMFSourceReader pReader; hr = MFExtern.MFCreateSourceReaderFromMediaSource( pSource, pAttributes, out pReader ); m_pReader = (IMFSourceReaderAsync)pReader; } SafeRelease(pAttributes); return(hr); }
private int OpenMediaSource(IMFMediaSource pSource, ref IMFSourceReaderAsync pReaderAsync) { // Create an attribute store to hold initialization settings. IMFAttributes pAttributes; var hr = MFExtern.MFCreateAttributes(out pAttributes, 2); //if (Succeeded(hr)) //{ // hr = pAttributes.SetUINT32(MFAttributesClsid.MF_READWRITE_DISABLE_CONVERTERS, 1); //} if (Succeeded(hr)) { hr = pAttributes.SetUnknown(MFAttributesClsid.MF_SOURCE_READER_ASYNC_CALLBACK, this); } if (Succeeded(hr)) { IMFSourceReader pReader; hr = MFExtern.MFCreateSourceReaderFromMediaSource(pSource, pAttributes, out pReader); // ReSharper disable once SuspiciousTypeConversion.Global pReaderAsync = (IMFSourceReaderAsync)pReader; } SafeRelease(pAttributes); return(hr); }
private void CloseAllMediaDevices() { HResult hr; Console.WriteLine("CloseAllMediaDevices"); // close and release our call back handler if (mediaSessionAsyncCallbackHandler != null) { // stop any messaging or events in the call back handler mediaSessionAsyncCallbackHandler.ShutDown(); mediaSessionAsyncCallbackHandler = null; } // Shut down the source reader if (StreamReader != null) { Marshal.ReleaseComObject(StreamReader); StreamReader = null; } // close the session (this is NOT the same as shutting it down) if (mediaSession != null) { hr = mediaSession.Close(); if (hr != HResult.S_OK) { // just log it Console.WriteLine("CloseAllMediaDevices call to mediaSession.Close failed. Err=" + hr.ToString()); } } // Shut down the media source if (MediaSource != null) { hr = MediaSource.Shutdown(); if (hr != HResult.S_OK) { // just log it Console.WriteLine("CloseAllMediaDevices call to mediaSource.Shutdown failed. Err=" + hr.ToString()); } Marshal.ReleaseComObject(MediaSource); MediaSource = null; } // Shut down the media session (note we only closed it before). if (mediaSession != null) { hr = mediaSession.Shutdown(); if (hr != HResult.S_OK) { // just log it Console.WriteLine("CloseAllMediaDevices call to mediaSession.Shutdown failed. Err=" + hr.ToString()); } Marshal.ReleaseComObject(mediaSession); mediaSession = null; } if (currentVideoMediaType != null) { Marshal.ReleaseComObject(currentVideoMediaType); currentVideoMediaType = null; } }
public CCapture(IntPtr hwnd, int iMessageID) { m_pReader = null; m_pWriter = null; m_hwndEvent = hwnd; m_iMessageID = iMessageID; m_bFirstSample = false; m_llBaseTime = 0; m_pwszSymbolicLink = null; }
public CCapture(IntPtr hwnd, int iMessageID) { m_pReader = null; m_pWriter = null; m_hwndEvent = hwnd; m_iMessageID = iMessageID; m_bFirstSample = false; m_llBaseTime = 0; m_pwszSymbolicLink = null; }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Close the Media Source /// </summary> /// <param name=" readerObject">the media source object</param> /// <history> /// 01 Nov 18 Cynic - Started /// </history> private void CloseSourceReader(IMFSourceReaderAsync readerObject) { // End any active captures if (readerObject == null) { LogMessage("CloseSourceReader readerObject == null"); return; } // close and release Marshal.ReleaseComObject(readerObject); }
//------------------------------------------------------------------- // CloseDevice // // Releases all resources held by this object. //------------------------------------------------------------------- public int CloseDevice() { lock (this) { SafeRelease(m_pReader); m_pReader = null; m_pwszSymbolicLink = null; } return S_Ok; }
//------------------------------------------------------------------- // CloseDevice // // Releases all resources held by this object. //------------------------------------------------------------------- public HResult CloseDevice() { lock (this) { SafeRelease(m_pReader); m_pReader = null; m_pwszSymbolicLink = null; } return(HResult.S_OK); }
private void SetCurrentMediaType(IMFSourceReaderAsync reader, int IndexOfSelectSource, int StreamIndex) { List <IMFMediaType> list = new List <IMFMediaType>(); HResult hr = reader.GetNativeMediaType(StreamIndex, list.Count, out IMFMediaType ppMediaType); while (hr != HResult.MF_E_NO_MORE_TYPES) { list.Add(ppMediaType); hr = reader.GetNativeMediaType(StreamIndex, list.Count, out ppMediaType); } reader.SetCurrentMediaType(StreamIndex, null, list[IndexOfSelectSource]); }
//------------------------------------------------------------------- // CloseDevice // // Releases all resources held by this object. //------------------------------------------------------------------- public virtual int CloseDevice() { lock (LockSync) { SafeRelease(PReader); PReader = null; pActivate?.ShutdownObject(); pActivate = null; PwszSymbolicLink = null; Draw.DrawNullFrame(); } return(S_Ok); }
// Constructor public CPreview(IntPtr hVideo, IntPtr hEvent) { m_pReader = null; m_hwndEvent = hEvent; m_pwszSymbolicLink = null; m_draw = new DrawDevice(); int hr = MFExtern.MFStartup(0x20070, MFStartup.Lite); MFError.ThrowExceptionForHR(hr); hr = m_draw.CreateDevice(hVideo); MFError.ThrowExceptionForHR(hr); }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// A centralized place to close down all media devices /// </summary> /// <history> /// 01 Nov 18 Cynic - Started /// </history> private void CloseAllMediaDevices() { // close the async call back handler CloseAsyncCallBackHandler(workingSourceReaderCallBackHandler); workingSourceReaderCallBackHandler = null; // close the media sink CloseSinkWriter(workingSinkWriter); workingSinkWriter = null; // Close the media source CloseSourceReader(workingSourceReader); workingSourceReader = null; }
// Constructor public CPreview(IntPtr hVideo, IntPtr hEvent) { m_pReader = null; m_hwndEvent = hEvent; m_pwszSymbolicLink = null; m_draw = new DrawDevice(); HResult hr = MFExtern.MFStartup(0x20070, MFStartup.Lite); MFError.ThrowExceptionForHR(hr); hr = m_draw.CreateDevice(hVideo); MFError.ThrowExceptionForHR(hr); }
// Constructor protected CProcess(IntPtr hVideo, IntPtr hEvent) { this.hVideo = hVideo; PReader = null; HwndEvent = hEvent; PwszSymbolicLink = null; var hr = MFExtern.MFStartup(0x20070, MFStartup.Lite); MFError.ThrowExceptionForHR(hr); Draw = new DrawDevice(); hr = Draw.CreateDevice(hVideo); MFError.ThrowExceptionForHR(hr); }
// Constructor protected CProcess(IntPtr hVideo, IntPtr hEvent) { this.hVideo = hVideo; PReader = null; HwndEvent = hEvent; PwszSymbolicLink = null; var hr = MFExtern.MFStartup(0x20070, MFStartup.Lite); MFError.ThrowExceptionForHR(hr); Draw = new DrawDevice(); hr = Draw.CreateDevice(hVideo); MFError.ThrowExceptionForHR(hr); }
//------------------------------------------------------------------- // CloseDevice // // Releases all resources held by this object. //------------------------------------------------------------------- public HResult CloseDevice() { lock (this) { if (m_pWriter != null) { m_pWriter.Finalize_(); SafeRelease(m_pWriter); m_pWriter = null; } SafeRelease(m_pReader); m_pReader = null; m_pwszSymbolicLink = null; } return(HResult.S_OK); }
public HResult EndCaptureSession() { HResult hr = HResult.S_OK; lock (this) { if (m_pWriter != null) { hr = m_pWriter.Finalize_(); SafeRelease(m_pWriter); m_pWriter = null; } if (m_pReader != null) { SafeRelease(m_pReader); m_pReader = null; } } return(hr); }
int ConfigureSourceReader(IMFSourceReaderAsync pReader) { // The list of acceptable types. Guid[] subtypes = { MFMediaType.NV12, MFMediaType.YUY2, MFMediaType.UYVY, MFMediaType.RGB32, MFMediaType.RGB24, MFMediaType.IYUV }; int hr = S_Ok; bool bUseNativeType = false; Guid subtype; IMFMediaType pType = null; // If the source's native format matches any of the formats in // the list, prefer the native format. // Note: The camera might support multiple output formats, // including a range of frame dimensions. The application could // provide a list to the user and have the user select the // camera's output format. That is outside the scope of this // sample, however. hr = pReader.GetNativeMediaType( MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, // Type index out pType ); if (Failed(hr)) { goto done; } hr = pType.GetGUID(MFAttributesClsid.MF_MT_SUBTYPE, out subtype); if (Failed(hr)) { goto done; } for (int i = 0; i < subtypes.Length; i++) { if (subtype == subtypes[i]) { hr = pReader.SetCurrentMediaType( MF_SOURCE_READER_FIRST_VIDEO_STREAM, IntPtr.Zero, pType ); bUseNativeType = true; break; } } if (!bUseNativeType) { // None of the native types worked. The camera might offer // output of a compressed type such as MJPEG or DV. // Try adding a decoder. for (int i = 0; i < subtypes.Length; i++) { hr = pType.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, subtypes[i]); if (Failed(hr)) { goto done; } hr = pReader.SetCurrentMediaType( MF_SOURCE_READER_FIRST_VIDEO_STREAM, IntPtr.Zero, pType ); if (Succeeded(hr)) { break; } } } done: SafeRelease(pType); return hr; }
public int EndCaptureSession() { int hr = S_Ok; lock (this) { if (m_pWriter != null) { hr = m_pWriter.Finalize_(); SafeRelease(m_pWriter); m_pWriter = null; } if (m_pReader != null) { SafeRelease(m_pReader); m_pReader = null; } } return hr; }
//------------------------------------------------------------------- // SetDevice // // Set up preview for a specified video capture device. //------------------------------------------------------------------- public int SetDevice(MFDevice pDevice) { int hr = S_Ok; IMFActivate pActivate = pDevice.Activator; IMFMediaSource pSource = null; IMFAttributes pAttributes = null; object o = null; lock (this) { try { // Release the current device, if any. hr = CloseDevice(); if (Succeeded(hr)) { // Create the media source for the device. hr = pActivate.ActivateObject(typeof(IMFMediaSource).GUID, out o); } if (Succeeded(hr)) { pSource = (IMFMediaSource)o; } // Get Symbolic device link m_pwszSymbolicLink = pDevice.SymbolicName; // // Create the source reader. // // Create an attribute store to hold initialization settings. if (Succeeded(hr)) { hr = MFExtern.MFCreateAttributes(out pAttributes, 2); } if (Succeeded(hr)) { hr = pAttributes.SetUINT32(MFAttributesClsid.MF_READWRITE_DISABLE_CONVERTERS, 1); } if (Succeeded(hr)) { hr = pAttributes.SetUnknown(MFAttributesClsid.MF_SOURCE_READER_ASYNC_CALLBACK, this); } IMFSourceReader pRead = null; if (Succeeded(hr)) { hr = MFExtern.MFCreateSourceReaderFromMediaSource(pSource, pAttributes, out pRead); } if (Succeeded(hr)) { m_pReader = (IMFSourceReaderAsync)pRead; } if (Succeeded(hr)) { // Try to find a suitable output type. for (int i = 0; ; i++) { IMFMediaType pType; hr = m_pReader.GetNativeMediaType((int)MF_SOURCE_READER.FirstVideoStream, i, out pType); if (Failed(hr)) { break; } try { hr = TryMediaType(pType); if (Succeeded(hr)) { // Found an output type. break; } } finally { SafeRelease(pType); } } } if (Succeeded(hr)) { // Ask for the first sample. hr = m_pReader.ReadSample((int)MF_SOURCE_READER.FirstVideoStream, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); } if (Failed(hr)) { if (pSource != null) { pSource.Shutdown(); // NOTE: The source reader shuts down the media source // by default, but we might not have gotten that far. } CloseDevice(); } } finally { SafeRelease(pSource); SafeRelease(pAttributes); } } return hr; }
//------------------------------------------------------------------- // CloseDevice // // Releases all resources held by this object. //------------------------------------------------------------------- public int CloseDevice() { lock (this) { if (m_pWriter != null) { m_pWriter.Finalize_(); SafeRelease(m_pWriter); m_pWriter = null; } SafeRelease(m_pReader); m_pReader = null; m_pwszSymbolicLink = null; } return S_Ok; }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <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; } } }
//------------------------------------------------------------------- // SetDevice // // Set up preview for a specified video capture device. //------------------------------------------------------------------- public HResult SetDevice(MFDevice pDevice) { HResult hr = HResult.S_OK; IMFActivate pActivate = pDevice.Activator; IMFMediaSource pSource = null; IMFAttributes pAttributes = null; object o = null; lock (this) { try { // Release the current device, if any. hr = CloseDevice(); if (Succeeded(hr)) { // Create the media source for the device. hr = pActivate.ActivateObject(typeof(IMFMediaSource).GUID, out o); } if (Succeeded(hr)) { pSource = (IMFMediaSource)o; } // Get Symbolic device link m_pwszSymbolicLink = pDevice.SymbolicName; // // Create the source reader. // // Create an attribute store to hold initialization settings. if (Succeeded(hr)) { hr = MFExtern.MFCreateAttributes(out pAttributes, 2); } if (Succeeded(hr)) { hr = pAttributes.SetUINT32(MFAttributesClsid.MF_READWRITE_DISABLE_CONVERTERS, 1); } if (Succeeded(hr)) { hr = pAttributes.SetUnknown(MFAttributesClsid.MF_SOURCE_READER_ASYNC_CALLBACK, this); } IMFSourceReader pRead = null; if (Succeeded(hr)) { hr = MFExtern.MFCreateSourceReaderFromMediaSource(pSource, pAttributes, out pRead); } if (Succeeded(hr)) { m_pReader = (IMFSourceReaderAsync)pRead; } if (Succeeded(hr)) { // Try to find a suitable output type. for (int i = 0; ; i++) { IMFMediaType pType; hr = m_pReader.GetNativeMediaType((int)MF_SOURCE_READER.FirstVideoStream, i, out pType); if (Failed(hr)) { break; } try { hr = TryMediaType(pType); if (Succeeded(hr)) { // Found an output type. break; } } finally { SafeRelease(pType); } } } if (Succeeded(hr)) { // Ask for the first sample. hr = m_pReader.ReadSample((int)MF_SOURCE_READER.FirstVideoStream, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); } if (Failed(hr)) { if (pSource != null) { pSource.Shutdown(); // NOTE: The source reader shuts down the media source // by default, but we might not have gotten that far. } CloseDevice(); } } finally { SafeRelease(pSource); SafeRelease(pAttributes); } } return(hr); }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Starts capture of the data to a file. /// /// Because this code is intended for demo purposes and in the interests of /// reducing complexity it is extremely linear and step-by-step. Doubtless /// there is much refactoring that could be done. /// /// </summary> /// <history> /// 01 Nov 18 Cynic - Started /// </history> private void CaptureToFile() { HResult hr; IMFMediaType videoType = null; IMFMediaType encoderType = null; TantaMFDevice currentDevice = null; try { // get the current video device. currentDevice = ctlTantaVideoPicker1.CurrentDevice; if (currentDevice == null) { MessageBox.Show("No current video device. Are there any video devices on this system?"); return; } // check our output filename is correct and usable if ((textBoxCaptureFileNameAndPath == null) || (textBoxCaptureFileNameAndPath.Text.Length == 0)) { MessageBox.Show("No Capture Filename and path. Cannot continue."); return; } string pwszFileName = textBoxCaptureFileNameAndPath.Text; // check the path is rooted if (Path.IsPathRooted(pwszFileName) == false) { MessageBox.Show("No Capture Filename and path is not rooted. A full directory and path is required. Cannot continue."); return; } // create a new call back handler. This, once we get it all wired up, will act // as a pump to move the data from the source to the sink workingSourceReaderCallBackHandler = new TantaSourceReaderCallbackHandler(); // the following code will create a SourceReader which is tied to a camera on the system, // a SinkWriter which is tied to a file output and will hook up the two. Because we are using // a SourceReader and SourceWriter we do not have the usual Topology or Pipeline. The SourceReader // and SourceWriter are connected directly (input to output) in the code below and transfer their // data via the callback handler. The callback handler also requests the next sample from // the SourceReader when it has written the data to the sink. Note however it is possible // that the SourceReader can automatically bring in a Transform for format conversion. This // is done internally and you never deal with it - other than perhaps making it available // to the process if it is not globally available. // create the source reader workingSourceReader = TantaWMFUtils.CreateSourceReaderAsyncFromDevice(currentDevice, workingSourceReaderCallBackHandler); if (workingSourceReader == null) { MessageBox.Show("CreateSourceReaderAsyncFromDevice did not return a media source. Cannot continue."); return; } // open up the sink Writer workingSinkWriter = OpenSinkWriter(pwszFileName); if (workingSinkWriter == null) { MessageBox.Show("OpenSinkWriter workingSinkWriter == null. Cannot continue."); return; } // now set the source and the sink in the callback handler. It needs to know these // in order to operate workingSourceReaderCallBackHandler.SourceReader = workingSourceReader; workingSourceReaderCallBackHandler.SinkWriter = workingSinkWriter; workingSourceReaderCallBackHandler.InitForFirstSample(); workingSourceReaderCallBackHandler.SourceReaderAsyncCallBackError = HandleSourceReaderAsyncCallBackErrors; // now we configure the video source. It will probably offer a lot of different types // this example offers two modes: one mode where you choose the format and mode and // effectively just say "Use this one". The other uses the general case where we // present a list of reasonable types we can accept and then let it auto // configure itself from one of those. Of course if it autoconfigures itself we // don't know which one it has chosen. This is why, you will later see the video // source being interrogated after the configuration so we know which one we hit. if (radioButtonUseSpecified.Checked == true) { // we saved the video format container here - this is just the last one that came in if ((radioButtonUseSpecified.Tag == null) || ((radioButtonUseSpecified.Tag is TantaMFVideoFormatContainer) == false)) { MessageBox.Show("No source video device and format selected. Cannot continue."); return; } // get the container TantaMFVideoFormatContainer videoFormatCont = (radioButtonUseSpecified.Tag as TantaMFVideoFormatContainer); // configure the Source Reader to use this format hr = TantaWMFUtils.ConfigureSourceReaderWithVideoFormat(workingSourceReader, videoFormatCont); if (hr != HResult.S_OK) { // we failed MessageBox.Show("Failed on call to ConfigureSourceAsyncReaderWithVideoFormat (a), retVal=" + hr.ToString()); return; } } else { // prepare a list of subtypes we are prepared to accept from the video source // device. These will be tested in order - the first match will be used. List <Guid> subTypes = new List <Guid>(); subTypes.Add(MFMediaType.NV12); subTypes.Add(MFMediaType.YUY2); subTypes.Add(MFMediaType.UYVY); subTypes.Add(MFMediaType.RGB32); subTypes.Add(MFMediaType.RGB24); subTypes.Add(MFMediaType.IYUV); // make sure the default Media Type is one of the above video formats hr = TantaWMFUtils.ConfigureSourceReaderWithVideoFormat(workingSourceReader, subTypes, false); if (hr != HResult.S_OK) { // we failed MessageBox.Show("Failed on call to ConfigureSourceAsyncReaderWithVideoFormat (b), retVal=" + hr.ToString()); return; } } // if we get here we know the source reader now has a configured format but we might not // know which one it is. So we ask it. It will return a video type // we will use this later on to configure our sink writer. Note, we have to properly dispose // of the videoType object after we use it. hr = workingSourceReader.GetCurrentMediaType(TantaWMFUtils.MF_SOURCE_READER_FIRST_VIDEO_STREAM, out videoType); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed on call to GetCurrentMediaType, retVal=" + hr.ToString()); } // now we configure the encoder. This sets up the sink writer so that it knows what format // the output data should be written in. The format we give the writer does not // need to be the same as the format it outputs to disk - however to make life easier for ourselves // we will copy a lot of the settings from the videoType retrieved above // create a new empty media type for us to populate hr = MFExtern.MFCreateMediaType(out encoderType); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed on call to MFCreateMediaType, retVal=" + hr.ToString()); } // The major type defines the overall category of the media data. Major types include video, audio, script & etc. hr = encoderType.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Video); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed setting the MF_MT_MAJOR_TYPE, retVal=" + hr.ToString()); } // The subtype GUID defines a specific media format type within a major type. For example, within video, // the subtypes include MFMediaType.H264 (MP4), MFMediaType.WMV3 (WMV), MJPEG & etc. Within audio, the // subtypes include PCM audio, Windows Media Audio 9, & etc. hr = encoderType.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, MEDIA_TYPETO_WRITE); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed setting the MF_MT_SUBTYPE, retVal=" + hr.ToString()); } // this is the approximate data rate of the video stream, in bits per second, for a video media type // in the MF.Net sample code this is 240000 but I found 2000000 to be much better. I am not sure, // at this time, how this value is derived or what the tradeoffs are. hr = encoderType.SetUINT32(MFAttributesClsid.MF_MT_AVG_BITRATE, TARGET_BIT_RATE); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed setting the MF_MT_AVG_BITRATE, retVal=" + hr.ToString()); } // populate our new encoding type with the frame size of the videoType selected earlier hr = TantaWMFUtils.CopyAttributeData(videoType, encoderType, MFAttributesClsid.MF_MT_FRAME_SIZE); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed copying the MF_MT_FRAME_SIZE, retVal=" + hr.ToString()); } // populate our new encoding type with the frame rate of the video type selected earlier hr = TantaWMFUtils.CopyAttributeData(videoType, encoderType, MFAttributesClsid.MF_MT_FRAME_RATE); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed copying the MF_MT_FRAME_RATE, retVal=" + hr.ToString()); } // populate our new encoding type with the pixel aspect ratio of the video type selected earlier hr = TantaWMFUtils.CopyAttributeData(videoType, encoderType, MFAttributesClsid.MF_MT_PIXEL_ASPECT_RATIO); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed copying the MF_MT_PIXEL_ASPECT_RATIO, retVal=" + hr.ToString()); } // populate our new encoding type with the interlace mode of the video type selected earlier hr = TantaWMFUtils.CopyAttributeData(videoType, encoderType, MFAttributesClsid.MF_MT_INTERLACE_MODE); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed copying the MF_MT_INTERLACE_MODE, retVal=" + hr.ToString()); } // add a stream to the sink writer. The encoderType specifies the format of the samples that will be written // to the file. Note that it does not necessarily need to match the input format. To set the input format // use SetInputMediaType. int sink_stream = 0; hr = workingSinkWriter.AddStream(encoderType, out sink_stream); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed adding the output stream, retVal=" + hr.ToString()); } // Windows 10, by default, provides an adequate set of codecs which the Sink Writer can // find to write out the MP4 file. This is not true on Windows 7. // If we are not on Windows 10 we register (locally) a codec // the Sink Writer can find and use. The ColorConvertDMO is supplied by // microsoft it is just not available to enumerate on Win7 etc. // Making it available locally does not require administrator privs // but only this process can see it and it disappears when the process // closes OperatingSystem os = Environment.OSVersion; int versionID = ((os.Version.Major * 10) + os.Version.Minor); if (versionID < 62) { Guid ColorConvertDMOGUID = new Guid("98230571-0087-4204-b020-3282538e57d3"); // Register the color converter DSP for this process, in the video // processor category. This will enable the sink writer to enumerate // the color converter when the sink writer attempts to match the // media types. hr = MFExtern.MFTRegisterLocalByCLSID( ColorConvertDMOGUID, MFTransformCategory.MFT_CATEGORY_VIDEO_PROCESSOR, "", MFT_EnumFlag.SyncMFT, 0, null, 0, null ); } // Set the input format for a stream on the sink writer. Note the use of the stream index here // The input format does not have to match the target format that is written to the media sink // If the formats do not match, this call attempts to load an transform // that can convert from the input format to the target format. If it cannot find one, and this is not // a sure thing, it will throw an exception. hr = workingSinkWriter.SetInputMediaType(sink_stream, videoType, null); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed on calling SetInputMediaType on the writer, retVal=" + hr.ToString()); } // now we initialize the sink writer for writing. We call this method after configuring the // input streams but before we send any data to the sink writer. The underlying media sink must // have at least one input stream and we know it does because we set it up earlier hr = workingSinkWriter.BeginWriting(); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed on calling BeginWriting on the writer, retVal=" + hr.ToString()); } // Request the first video frame from the media source. The TantaSourceReaderCallbackHandler // set up earlier will be invoked and it will continue requesting and processing video // frames after that. hr = workingSourceReader.ReadSample( TantaWMFUtils.MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero ); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed on calling the first ReadSample on the reader, retVal=" + hr.ToString()); } // we are ready to start, flag this buttonStartStopCapture.Text = STOP_CAPTURE; // disable our screen controls SetEnableStateOnScreenControls(false); } finally { // setting this to null will cause it to be cleaned up currentDevice = null; // close and release if (videoType != null) { Marshal.ReleaseComObject(videoType); videoType = null; } if (encoderType != null) { Marshal.ReleaseComObject(encoderType); encoderType = null; } } }
//------------------------------------------------------------------- // CloseDevice // // Releases all resources held by this object. //------------------------------------------------------------------- public virtual int CloseDevice() { lock (LockSync) { SafeRelease(PReader); PReader = null; pActivate?.ShutdownObject(); pActivate = null; PwszSymbolicLink = null; Draw.DrawNullFrame(); } return S_Ok; }
HResult ConfigureSourceReader(IMFSourceReaderAsync pReader) { // The list of acceptable types. Guid[] subtypes = { MFMediaType.NV12, MFMediaType.YUY2, MFMediaType.UYVY, MFMediaType.RGB32, MFMediaType.RGB24, MFMediaType.IYUV }; HResult hr = HResult.S_OK; bool bUseNativeType = false; Guid subtype; IMFMediaType pType = null; // If the source's native format matches any of the formats in // the list, prefer the native format. // Note: The camera might support multiple output formats, // including a range of frame dimensions. The application could // provide a list to the user and have the user select the // camera's output format. That is outside the scope of this // sample, however. hr = pReader.GetNativeMediaType( MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, // Type index out pType ); if (Failed(hr)) { goto done; } hr = pType.GetGUID(MFAttributesClsid.MF_MT_SUBTYPE, out subtype); if (Failed(hr)) { goto done; } for (int i = 0; i < subtypes.Length; i++) { if (subtype == subtypes[i]) { hr = pReader.SetCurrentMediaType( MF_SOURCE_READER_FIRST_VIDEO_STREAM, null, pType ); bUseNativeType = true; break; } } if (!bUseNativeType) { // None of the native types worked. The camera might offer // output of a compressed type such as MJPEG or DV. // Try adding a decoder. for (int i = 0; i < subtypes.Length; i++) { hr = pType.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, subtypes[i]); if (Failed(hr)) { goto done; } hr = pReader.SetCurrentMediaType( MF_SOURCE_READER_FIRST_VIDEO_STREAM, null, pType ); if (Succeeded(hr)) { break; } } } done: SafeRelease(pType); return(hr); }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <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); }
private int OpenMediaSource(IMFMediaSource pSource) { int hr = S_Ok; IMFAttributes pAttributes = null; hr = MFExtern.MFCreateAttributes(out pAttributes, 2); if (Succeeded(hr)) { hr = pAttributes.SetUnknown(MFAttributesClsid.MF_SOURCE_READER_ASYNC_CALLBACK, this); } if (Succeeded(hr)) { IMFSourceReader pReader; hr = MFExtern.MFCreateSourceReaderFromMediaSource( pSource, pAttributes, out pReader ); m_pReader = (IMFSourceReaderAsync)pReader; } SafeRelease(pAttributes); return hr; }
private int OpenMediaSource(IMFMediaSource pSource, ref IMFSourceReaderAsync pReaderAsync) { // Create an attribute store to hold initialization settings. IMFAttributes pAttributes; var hr = MFExtern.MFCreateAttributes(out pAttributes, 2); //if (Succeeded(hr)) //{ // hr = pAttributes.SetUINT32(MFAttributesClsid.MF_READWRITE_DISABLE_CONVERTERS, 1); //} if (Succeeded(hr)) { hr = pAttributes.SetUnknown(MFAttributesClsid.MF_SOURCE_READER_ASYNC_CALLBACK, this); } if (Succeeded(hr)) { IMFSourceReader pReader; hr = MFExtern.MFCreateSourceReaderFromMediaSource(pSource, pAttributes, out pReader); // ReSharper disable once SuspiciousTypeConversion.Global pReaderAsync = (IMFSourceReaderAsync)pReader; } SafeRelease(pAttributes); return hr; }
public override void StartStream() { Task.Run(() => { // check our source filename is correct and usable StreamReaderHandler = new StreamHandler(ProcessFrame, MFBPressed); HResult hr; IMFSourceResolver pSourceResolver = null; IMFPresentationDescriptor sourcePresentationDescriptor = null; IMFStreamDescriptor videoStreamDescriptor = null; try { // reset everything CloseAllMediaDevices(); // Create the media session. hr = MFExtern.MFCreateMediaSession(null, out mediaSession); if (hr != HResult.S_OK) { throw new Exception("PrepareSessionAndTopology call to MFExtern.MFCreateMediaSession failed. Err=" + hr.ToString()); } // set up our media session call back handler. mediaSessionAsyncCallbackHandler = new AsyncCallbackHandler(); mediaSessionAsyncCallbackHandler.Initialize(); mediaSessionAsyncCallbackHandler.MediaSession = mediaSession; mediaSessionAsyncCallbackHandler.MediaSessionAsyncCallBackError = HandleMediaSessionAsyncCallBackErrors; mediaSessionAsyncCallbackHandler.MediaSessionAsyncCallBackEvent = HandleMediaSessionAsyncCallBackEvent; // Register the callback handler with the session and tell it that events can // start. This does not actually trigger an event it just lets the media session // know that it can now send them if it wishes to do so. hr = mediaSession.BeginGetEvent(mediaSessionAsyncCallbackHandler, null); if (hr != HResult.S_OK) { throw new Exception("PrepareSessionAndTopology call to mediaSession.BeginGetEvent failed. Err=" + hr.ToString()); } StreamReader = WMFUtils.CreateSourceReaderAsyncFromDevice(UnderlyingDevice, StreamReaderHandler); try { SetCurrentMediaType(StreamReader, IMFStreamIndex, 0); } catch { } try { SetCurrentMediaType(StreamReader, IMFSnapIndex, 1); } catch { } StreamReaderHandler.StreamReader = StreamReader; StreamReader.GetCurrentMediaType(1, out IMFMediaType ppMediaType); StreamReader.GetNativeMediaType(1, 0, out IMFMediaType PPMediaType); StreamReader.GetCurrentMediaType(0, out IMFMediaType ppMediaType1); StreamReader.GetNativeMediaType(0, 0, out IMFMediaType PPMediaType1); ppMediaType.GetMajorType(out Guid ppMediaTypeMGUID); PPMediaType.GetMajorType(out Guid PPMediaTypeMGUID); ppMediaType.GetGUID(MFAttributesClsid.MF_MT_SUBTYPE, out Guid ppMediaTypeSGUID); PPMediaType.GetGUID(MFAttributesClsid.MF_MT_SUBTYPE, out Guid PPMediaTypeSGUID); Console.WriteLine(WMFUtils.ConvertGuidToName(ppMediaTypeMGUID)); Console.WriteLine(WMFUtils.ConvertGuidToName(PPMediaTypeMGUID)); Console.WriteLine(WMFUtils.ConvertGuidToName(ppMediaTypeSGUID)); Console.WriteLine(WMFUtils.ConvertGuidToName(PPMediaTypeSGUID)); ppMediaType1.GetMajorType(out Guid ppMediaTypeMGUID1); PPMediaType1.GetMajorType(out Guid PPMediaTypeMGUID1); ppMediaType1.GetGUID(MFAttributesClsid.MF_MT_SUBTYPE, out Guid ppMediaTypeSGUID1); PPMediaType1.GetGUID(MFAttributesClsid.MF_MT_SUBTYPE, out Guid PPMediaTypeSGUID1); Console.WriteLine(WMFUtils.ConvertGuidToName(ppMediaTypeMGUID1)); Console.WriteLine(WMFUtils.ConvertGuidToName(PPMediaTypeMGUID1)); Console.WriteLine(WMFUtils.ConvertGuidToName(ppMediaTypeSGUID1)); Console.WriteLine(WMFUtils.ConvertGuidToName(PPMediaTypeSGUID1)); Paused = false; StreamReader.SetStreamSelection(0, true); StreamReader.SetStreamSelection(1, true); hr = StreamReader.ReadSample( 0, MediaFoundation.ReadWrite.MF_SOURCE_READER_CONTROL_FLAG.None, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero ); hr = StreamReader.ReadSample(1, MediaFoundation.ReadWrite.MF_SOURCE_READER_CONTROL_FLAG.None, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero ); if (hr != HResult.S_OK) { // we failed throw new Exception("Failed on calling the first ReadSample on the reader, retVal=" + hr.ToString()); } } catch (Exception ex) { Console.WriteLine("PrepareSessionAndTopology Error: " + ex.Message); } finally { // Clean up if (pSourceResolver != null) { Marshal.ReleaseComObject(pSourceResolver); } if (sourcePresentationDescriptor != null) { Marshal.ReleaseComObject(sourcePresentationDescriptor); } if (videoStreamDescriptor != null) { Marshal.ReleaseComObject(videoStreamDescriptor); } } }); }