private void createSession(string sFilePath) { try { MFError throwonhr = null; if (m_pSession == null) { throwonhr = MFExtern.MFCreateMediaSession(null, out m_pSession); } else { Stop(); } // Create the media source. CreateMediaSource(sFilePath); if (m_pSource == null) { return; } IMFPresentationDescriptor lPresentationDescriptor = null; m_pSource.CreatePresentationDescriptor(out lPresentationDescriptor); if (lPresentationDescriptor == null) { return; } lPresentationDescriptor.GetUINT64(MFAttributesClsid.MF_PD_DURATION, out mMediaDuration); IMFTopology pTopology = null; // Create a partial topology. CreateTopologyFromSource(out pTopology); HResult hr = HResult.S_OK; // Set the topology on the media session. hr = m_pSession.SetTopology(MFSessionSetTopologyFlags.Immediate, pTopology); StartPlayback(); } catch (Exception) { } }
private static HResult ProcessMediaSession(string VideoFile) { HResult hr = S_OK; IMFMediaSource source = null; IMFTopology topology = null; IMFMediaSinkAlt mediaSink = null; IMFMediaSession mediaSession = null; hr = CreateMediaSource(VideoFile, out source); if (Failed(hr)) { return(hr); } hr = CreateTopology(out topology, out mediaSink, source); if (Failed(hr)) { topology = null; mediaSink = null; source = null; return(hr); } hr = MF.CreateMediaSession(null, out mediaSession); if (Failed(hr)) { topology = null; mediaSink = null; source = null; mediaSession = null; return(hr); } hr = mediaSession.SetTopology(MFSessionSetTopologyFlags.None, topology); if (Failed(hr)) { topology = null; mediaSink = null; source = null; mediaSession = null; return(hr); } hr = RunMediaSession(mediaSession); return(hr); }
//////////////////////////////////////////////////////////////////////////////////////// // Name: CPlayer::QueueNextSegment (Private) // Description: // Queues the next topology on the session. // // Parameter: // pPresentationDescriptor: [in] Presentation descriptor for the next topology // pSegmentId: [out] Receives the corresponding segment identifier for the topology // // Note: The presentation descriptor is received from the MENewPresentation event. // This event tells the session about the next topology in the sequencer. // If NULL is passed, this method queues the first topology on the media session. ///////////////////////////////////////////////////////////////////////////////////////// private void QueueNextSegment( IMFPresentationDescriptor pPresentationDescriptor, out int pSegmentId) { HResult hr; IMFMediaSourceTopologyProvider pMediaSourceTopologyProvider; IMFTopology pTopology; int SegId = 0; // Get the Segment ID. hr = m_pSequencerSource.GetPresentationContext( pPresentationDescriptor, out SegId, out pTopology); MFError.ThrowExceptionForHR(hr); SafeRelease(pTopology); Debug.WriteLine(string.Format("CPlayer::QueueNextSegment: {0}", SegId)); //Get the topology for the presentation descriptor pMediaSourceTopologyProvider = (IMFMediaSourceTopologyProvider)m_pSequencerSource; hr = pMediaSourceTopologyProvider.GetMediaSourceTopology( pPresentationDescriptor, out pTopology); MFError.ThrowExceptionForHR(hr); try { //Set the topology on the media session hr = m_pMediaSession.SetTopology(MFSessionSetTopologyFlags.None, pTopology); MFError.ThrowExceptionForHR(hr); pSegmentId = SegId; } finally { //clean up SafeRelease(pTopology); } }
/// <summary> /// Open from a Url address /// </summary> /// <param name="sURL"></param> /// <returns></returns> public int OpenURL(string sURL) { TRACE("Media::OpenURL"); TRACE("URL = " + sURL); // 1. Create a new media session // 2. Create the media source // 3. Create the topology // 4. Queue the topology [asynchronous] // 5. Start playback [asynchronous - does not happen in this method] int hr = S_Ok; try { IMFTopology pTopology = null; // Create the media session. CreateSession(); // Create the media source. CreateMediaSource(sURL); // Create a partial topology. CreateTopologyFromSource(out pTopology); // Set the topology on the media session. m_pSession.SetTopology(0, pTopology); // Set our state to "open pending" m_state = MediaState.OpenPending; NotifyState(); SafeRelease(pTopology); // If SetTopology succeeded, the media session will queue an // MESessionTopologySet event. } catch (Exception e) { hr = Marshal.GetHRForException(e); NotifyError(hr); m_state = MediaState.Ready; } return(hr); }
private void SetFirstTopology(IMFSequencerSource pSequencerSource, IMFMediaSession pMediaSession) { IMFMediaSource pMediaSource; IMFPresentationDescriptor pPresentationDescriptor; IMFMediaSourceTopologyProvider pMediaSourceTopologyProvider; IMFTopology pTopology; pMediaSource = pSequencerSource as IMFMediaSource; // Create the presentation descriptor for the media source. int hr = pMediaSource.CreatePresentationDescriptor(out pPresentationDescriptor); MFError.ThrowExceptionForHR(hr); // Get the topology provider from the sequencer source. pMediaSourceTopologyProvider = pSequencerSource as IMFMediaSourceTopologyProvider; // Get the first topology from the topology provider. hr = pMediaSourceTopologyProvider.GetMediaSourceTopology(pPresentationDescriptor, out pTopology); MFError.ThrowExceptionForHR(hr); // Set the topology on the media session. hr = pMediaSession.SetTopology(0, pTopology); MFError.ThrowExceptionForHR(hr); }
/// <summary> /// Loads IWaveProvider. /// </summary> /// <param name="waveProvider">The waveProvider to be loaded.</param> public void Init(IWaveProvider waveProvider) { MediaFoundationApi.Startup(); m_sourcewave = waveProvider; int readcount; MemoryStream msByteStrem = new MemoryStream(); byte[] _data; do { readcount = 0; _data = new byte[32767]; readcount = waveProvider.Read(_data, 0, _data.Length); if (readcount < 0) { continue; } msByteStrem.Write(_data, 0, readcount); } while (readcount >= _data.Length | readcount < 0);//Creates a IMFByteStream and fills it with the data in waveProvider. ComStream csByteStream = new ComStream(msByteStrem); IMFByteStream mfByteStream = MediaFoundationApi.CreateByteStream(csByteStream); MediaFoundationInterop.MFCreateSourceResolver(out IMFSourceResolver resolver); IMFAttributes streamattributes = mfByteStream as IMFAttributes; mfByteStream.GetLength(out long _length); resolver.CreateObjectFromByteStream(mfByteStream, null, SourceResolverFlags.MF_RESOLUTION_MEDIASOURCE | SourceResolverFlags.MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE, null, out _, out object _source);//Turns the stream to IMFMediaSource IMFMediaSource source = _source as IMFMediaSource; source.CreatePresentationDescriptor(out IMFPresentationDescriptor descriptor); MediaFoundationInterop.MFCreateTopology(out IMFTopology topo); descriptor.GetStreamDescriptorCount(out uint sdcount); for (uint i = 0; i < sdcount; i++)//For each stream in the source,creates renderer and adds to the topology. { descriptor.GetStreamDescriptorByIndex(i, out bool IsSelected, out IMFStreamDescriptor sd); if (!IsSelected) { if (SelectAllStream) { descriptor.SelectStream(i); } else { continue; } } sd.GetMediaTypeHandler(out IMFMediaTypeHandler typeHandler); typeHandler.GetMajorType(out Guid streamtype); IMFActivate renderer; if (streamtype == MediaTypes.MFMediaType_Audio) { MediaFoundationInterop.MFCreateAudioRendererActivate(out renderer);//Creates renderer for audio streams } else { continue; } //Creats and equips the topology nodes of the certain stream MediaFoundationInterop.MFCreateTopologyNode(MF_TOPOLOGY_TYPE.MF_TOPOLOGY_SOURCESTREAM_NODE, out IMFTopologyNode sourcenode); sourcenode.SetUnknown(MediaFoundationAttributes.MF_TOPONODE_SOURCE, source); sourcenode.SetUnknown(MediaFoundationAttributes.MF_TOPONODE_PRESENTATION_DESCRIPTOR, descriptor); sourcenode.SetUnknown(MediaFoundationAttributes.MF_TOPONODE_STREAM_DESCRIPTOR, sd); topo.AddNode(sourcenode); MediaFoundationInterop.MFCreateTopologyNode(MF_TOPOLOGY_TYPE.MF_TOPOLOGY_OUTPUT_NODE, out IMFTopologyNode outputnode); outputnode.SetObject(renderer); topo.AddNode(outputnode); sourcenode.ConnectOutput(0, outputnode, 0); } MediaFoundationInterop.MFCreateMediaSession(IntPtr.Zero, out m_Session); m_Session.SetTopology(0, topo); m_eventthread = new Thread(ProcessEvent); m_eventthread.Start(); }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Opens prepares the media session and topology and opens the media source /// and media sink. /// /// Once the session and topology are setup, a MESessionTopologySet event /// will be triggered in the callback handler. After that the events there /// trigger other events and everything rolls along automatically. /// </summary> /// <param name="sourceFileName">the source file name</param> /// <param name="outputFileName">the name of the output file</param> /// <history> /// 01 Nov 18 Cynic - Originally Written /// </history> public void PrepareSessionAndTopology(string sourceFileName, string outputFileName) { HResult hr; IMFSourceResolver pSourceResolver = null; IMFTopology pTopology = null; IMFPresentationDescriptor sourcePresentationDescriptor = null; int sourceStreamCount = 0; IMFStreamDescriptor audioStreamDescriptor = null; bool streamIsSelected = false; IMFTopologyNode sourceAudioNode = null; IMFTopologyNode outputSinkNode = null; IMFMediaType currentAudioMediaType = null; int audioStreamIndex = -1; LogMessage("PrepareSessionAndTopology "); // we sanity check the filenames - the existence of the path and if the file already exists // should have been checked before this call if ((sourceFileName == null) || (sourceFileName.Length == 0)) { throw new Exception("PrepareSessionAndTopology: source file name is invalid. Cannot continue."); } if ((outputFileName == null) || (outputFileName.Length == 0)) { throw new Exception("PrepareSessionAndTopology: output file name is invalid. Cannot continue."); } 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()); } if (mediaSession == null) { throw new Exception("PrepareSessionAndTopology call to MFExtern.MFCreateMediaSession failed. mediaSession == null"); } // set up our media session call back handler. mediaSessionAsyncCallbackHandler = new TantaAsyncCallbackHandler(); 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()); } // Create a new topology. A topology describes a collection of media sources, sinks, and transforms that are // connected in a certain order. These objects are represented within the topology by topology nodes, // which expose the IMFTopologyNode interface. A topology describes the path of multimedia data through these nodes. hr = MFExtern.MFCreateTopology(out pTopology); if (hr != HResult.S_OK) { throw new Exception("PrepareSessionAndTopology call to MFExtern.MFCreateTopology failed. Err=" + hr.ToString()); } if (pTopology == null) { throw new Exception("PrepareSessionAndTopology call to MFExtern.MFCreateTopology failed. pTopology == null"); } // #### // #### we now create the media source, this is an audio file // #### // use the file name to create the media source for the audio 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.GetMediaSourceFromFile(sourceFileName); if (mediaSource == null) { throw new Exception("PrepareSessionAndTopology call to mediaSource == null"); } // A presentation is a set of related media streams that share a common presentation time. We now get a copy of the media // source's presentation descriptor. Applications can use the presentation descriptor to select streams // and to get information about the source content. hr = mediaSource.CreatePresentationDescriptor(out sourcePresentationDescriptor); if (hr != HResult.S_OK) { throw new Exception("PrepareSessionAndTopology call to mediaSource.CreatePresentationDescriptor failed. Err=" + hr.ToString()); } if (sourcePresentationDescriptor == null) { throw new Exception("PrepareSessionAndTopology 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. These describe the streams in the presentation. Streams can be either selected or deselected. Only the // selected streams produce data. Deselected streams are not active and do not produce any data. hr = sourcePresentationDescriptor.GetStreamDescriptorCount(out sourceStreamCount); if (hr != HResult.S_OK) { throw new Exception("PrepareSessionAndTopology call to sourcePresentationDescriptor.GetStreamDescriptorCount failed. Err=" + hr.ToString()); } if (sourceStreamCount == 0) { throw new Exception("PrepareSessionAndTopology call to sourcePresentationDescriptor.GetStreamDescriptorCount failed. sourceStreamCount == 0"); } // Look at each stream, there can be more than one stream here // Usually only one is enabled. This app uses the first "selected" // stream we come to which has the appropriate media type for (int i = 0; i < sourceStreamCount; i++) { // we require the major type to be audio Guid guidMajorType = TantaWMFUtils.GetMajorMediaTypeFromPresentationDescriptor(sourcePresentationDescriptor, i); if (guidMajorType != MFMediaType.Audio) { continue; } // we also require the stream to be enabled hr = sourcePresentationDescriptor.GetStreamDescriptorByIndex(i, out streamIsSelected, out audioStreamDescriptor); if (hr != HResult.S_OK) { throw new Exception("PrepareSessionAndTopology call to sourcePresentationDescriptor.GetStreamDescriptorByIndex failed. Err=" + hr.ToString()); } if (audioStreamDescriptor == null) { throw new Exception("PrepareSessionAndTopology call to sourcePresentationDescriptor.GetStreamDescriptorByIndex failed. audioStreamDescriptor == null"); } // if the stream is selected, leave now we will release the audioStream descriptor later if (streamIsSelected == true) { audioStreamIndex = i; // record this break; } // release the one we are not using if (audioStreamDescriptor != null) { Marshal.ReleaseComObject(audioStreamDescriptor); audioStreamDescriptor = null; } audioStreamIndex = -1; } // by the time we get here we should have a audioStreamDescriptor if // we do not, then we cannot proceed if (audioStreamDescriptor == null) { throw new Exception("PrepareSessionAndTopology call to sourcePresentationDescriptor.GetStreamDescriptorByIndex failed. audioStreamDescriptor == null"); } if (audioStreamIndex < 0) { throw new Exception("PrepareSessionAndTopology call to sourcePresentationDescriptor.GetStreamDescriptorByIndex failed. audioStreamIndex < 0"); } // #### // #### we now create the media sink, we need the type from the stream to do // #### this which is why we wait until now to set it up // #### currentAudioMediaType = TantaWMFUtils.GetCurrentMediaTypeFromStreamDescriptor(audioStreamDescriptor); if (currentAudioMediaType == null) { throw new Exception("PrepareSessionAndTopology call to currentAudioMediaType == null"); } mediaSink = OpenMediaFileSink(outputFileName); if (mediaSink == null) { throw new Exception("PrepareSessionAndTopology call to mediaSink == null"); } // #### // #### we now make up a topology branch for the audio stream // #### // Create a source node for this stream. sourceAudioNode = TantaWMFUtils.CreateSourceNodeForStream(mediaSource, sourcePresentationDescriptor, audioStreamDescriptor); if (sourceAudioNode == null) { throw new Exception("PrepareSessionAndTopology call to CreateSourceNodeForStream failed. pSourceNode == null"); } // Create the output node - this is a file sink in this case. outputSinkNode = TantaWMFUtils.CreateSinkNodeForStream(mediaSink); if (outputSinkNode == null) { throw new Exception("PrepareSessionAndTopology call to CreateOutputNodeForStream failed. outputSinkNode == null"); } // Add the nodes to the topology. First the source hr = pTopology.AddNode(sourceAudioNode); if (hr != HResult.S_OK) { throw new Exception("PrepareSessionAndTopology call to pTopology.AddNode(sourceAudioNode) failed. Err=" + hr.ToString()); } // then add the output hr = pTopology.AddNode(outputSinkNode); if (hr != HResult.S_OK) { throw new Exception("PrepareSessionAndTopology call to pTopology.AddNode(outputSinkNode) failed. Err=" + hr.ToString()); } // Connect the output stream from the source node to the input stream of the output node. The parameters are: // dwOutputIndex - Zero-based index of the output stream on this node. // *pDownstreamNode - Pointer to the IMFTopologyNode interface of the node to connect to. // dwInputIndexOnDownstreamNode - Zero-based index of the input stream on the other node. hr = sourceAudioNode.ConnectOutput(0, outputSinkNode, 0); if (hr != HResult.S_OK) { throw new Exception("PrepareSessionAndTopology call to pSourceNode.ConnectOutput failed. Err=" + hr.ToString()); } // Set the topology on the media session. // If SetTopology succeeds, the media session will queue an // MESessionTopologySet event. hr = mediaSession.SetTopology(0, pTopology); MFError.ThrowExceptionForHR(hr); // Release the topology if (pTopology != null) { Marshal.ReleaseComObject(pTopology); } } catch (Exception ex) { LogMessage("Error: " + ex.Message); OISMessageBox(ex.Message); } finally { // Clean up if (pSourceResolver != null) { Marshal.ReleaseComObject(pSourceResolver); } if (sourcePresentationDescriptor != null) { Marshal.ReleaseComObject(sourcePresentationDescriptor); } if (audioStreamDescriptor != null) { Marshal.ReleaseComObject(audioStreamDescriptor); } if (sourceAudioNode != null) { Marshal.ReleaseComObject(sourceAudioNode); } if (outputSinkNode != null) { Marshal.ReleaseComObject(outputSinkNode); } if (currentAudioMediaType != null) { Marshal.ReleaseComObject(currentAudioMediaType); } } }
private void Load() { MediaFoundationInterop.MFCreateSourceResolver(out IMFSourceResolver resolver); object unknown; try { resolver.CreateObjectFromURL(URL, SourceResolverFlags.MF_RESOLUTION_MEDIASOURCE | SourceResolverFlags.MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE, null, out _, out unknown); } catch { throw new ArgumentException("Unsupported type."); } MediaFoundationInterop.MFCreateMediaSession(IntPtr.Zero, out m_Session); MediaFoundationInterop.MFCreateTopology(out IMFTopology topo); IMFMediaSource source = unknown as IMFMediaSource; source.CreatePresentationDescriptor(out m_pDescriptor); m_pDescriptor.GetUINT64(MediaFoundationAttributes.MF_PD_DURATION, out long dur); m_Duration = dur / 10000000; m_pDescriptor.GetStreamDescriptorCount(out uint sdcount); m_streamcount = (int)sdcount; for (uint i = 0; i < m_streamcount; i++) { m_pDescriptor.GetStreamDescriptorByIndex(i, out bool IsSelected, out IMFStreamDescriptor sd); m_DefaultStreamSelect.Add(IsSelected); switch (StreamSelectFlag) { case StreamSelectFlags.SelectAllStream: if (!IsSelected) { m_pDescriptor.SelectStream(i); } break; case StreamSelectFlags.SelectNone: if (IsSelected) { m_pDescriptor.DeselectStream(i); } break; } sd.GetMediaTypeHandler(out IMFMediaTypeHandler typeHandler); typeHandler.GetMediaTypeByIndex(0, out IMFMediaType mediaType); mediaType.GetMajorType(out Guid streamtype); IMFActivate renderer; if (streamtype == MediaTypes.MFMediaType_Audio) { MediaFoundationInterop.MFCreateAudioRendererActivate(out renderer); mediaType.GetUINT32(MediaFoundationAttributes.MF_MT_AUDIO_SAMPLES_PER_SECOND, out int rate);//SampleRate mediaType.GetUINT32(MediaFoundationAttributes.MF_MT_AUDIO_NUM_CHANNELS, out int channelcount); int samplesize; try { mediaType.GetUINT32(MediaFoundationAttributes.MF_MT_AUDIO_BITS_PER_SAMPLE, out samplesize); } catch (COMException e) { if ((uint)e.HResult != 0xC00D36E6) { throw e; } else { samplesize = 8; } } m_format.Add(new WaveFormat(rate, samplesize, channelcount)); } else { continue; } MediaFoundationInterop.MFCreateTopologyNode(MF_TOPOLOGY_TYPE.MF_TOPOLOGY_SOURCESTREAM_NODE, out IMFTopologyNode sourcenode); sourcenode.SetUnknown(MediaFoundationAttributes.MF_TOPONODE_SOURCE, source); sourcenode.SetUnknown(MediaFoundationAttributes.MF_TOPONODE_PRESENTATION_DESCRIPTOR, m_pDescriptor); sourcenode.SetUnknown(MediaFoundationAttributes.MF_TOPONODE_STREAM_DESCRIPTOR, sd); topo.AddNode(sourcenode); MediaFoundationInterop.MFCreateTopologyNode(MF_TOPOLOGY_TYPE.MF_TOPOLOGY_OUTPUT_NODE, out IMFTopologyNode outputnode); outputnode.SetObject(renderer); topo.AddNode(outputnode); sourcenode.ConnectOutput(0, outputnode, 0); } m_Session.SetTopology(0, topo); m_Eventthread = new Thread(ProcessEvent); m_Eventthread.Start(); }