/// <summary> /// Creates a byte stream from a URL. /// </summary> /// <param name="sourceResolver">A valid IMFSourceResolver instance.</param> /// <param name="url">A string that contains the URL to resolve.</param> /// <param name="flags">One or more members of the MFResolution enumeration.</param> /// <param name="properties">An instance of the IPropertyStore interface of a property store. The method passes the property store to the scheme handler or byte-stream handler that creates the object.</param> /// <param name="byteStream">Receives a byte stream that can handle the media file targeted by <paramref name="url"/>.</param> /// <returns>If this function succeeds, it returns the S_OK member. Otherwise, it returns another HResult's member that describe the error.</returns> public static HResult CreateObjectFromURL(this IMFSourceResolver sourceResolver, string url, MFResolution flags, IPropertyStore properties, out IMFByteStream byteStream) { if (sourceResolver == null) { throw new ArgumentNullException("sourceResolver"); } flags &= ~MFResolution.MediaSource; flags |= MFResolution.ByteStream; MFObjectType objectType; object tmp; HResult hr = sourceResolver.CreateObjectFromURL(url, flags, properties, out objectType, out tmp); byteStream = hr.Succeeded() ? tmp as IMFByteStream : null; return(hr); }
private static HResult CreateMediaSource(string videoFile, out IMFMediaSource source) { IMFSourceResolver resolver = null; source = null; HResult hr = MF.CreateSourceResolver(out resolver); if (Failed(hr)) { return(hr); } hr = resolver.CreateObjectFromURL(videoFile, MFResolution.MediaSource, null, out source); if (Failed(hr)) { SafeRelease(source); } SafeRelease(resolver); return(hr); }
/// <summary> /// Based on https://docs.microsoft.com/en-us/windows/desktop/medfound/shell-metadata-providers /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void infoToolStripMenuItem_Click(object sender, EventArgs e) { IMFSourceResolver pSourceResolver = null; IMFMediaSource pSource = null; object pPropsObject = null; var url = this.listView1.SelectedItems[0].Text; try { // Create the source resolver. HResult hr = MFExtern.MFCreateSourceResolver(out pSourceResolver); Validate(hr); if (pSourceResolver == null) { throw new Exception("pSourceResolver is null"); } // Get a pointer to the IMFMediaSource interface of the media source. hr = pSourceResolver.CreateObjectFromURL(url, MFResolution.MediaSource, null, out pSource); Validate(hr); if (pSource == null) { throw new Exception("pSource is null"); } hr = MFExtern.MFGetService(pSource, MFServices.MF_PROPERTY_HANDLER_SERVICE, typeof(IPropertyStore).GUID, out pPropsObject); Validate(hr); if (pPropsObject == null) { throw new Exception("pPropsObject is null"); } IPropertyStore pProps = pPropsObject as IPropertyStore; hr = pProps.GetCount(out int cProps); Validate(hr); var audioInfo = new AudioInfo(); var videoInfo = new VideoInfo(); for (int i = 0; i < cProps; ++i) { var key = new MediaFoundation.Misc.PropertyKey(); hr = pProps.GetAt(i, key); Validate(hr); using (PropVariant pv = new PropVariant()) { hr = pProps.GetValue(key, pv); Validate(hr); FillAudioProperty(audioInfo, key, pv); FillVideoProperty(videoInfo, key, pv); } } MessageBox.Show("Audio =\n" + audioInfo + ";\nVideo =\n" + videoInfo); } finally { if (pSource != null) { Marshal.ReleaseComObject(pSource); } if (pSourceResolver != null) { Marshal.ReleaseComObject(pSourceResolver); } if (pPropsObject != null) { Marshal.ReleaseComObject(pPropsObject); } } // MessageBox.Show(url); }
void ValidateMP4OutputFile(string mp4filepath) { ulong duration = 0; uint videoWidth = 0; uint videoHeight = 0; double videoFPS = 0.0; uint videoBitrate = 0; try { IMFMediaSource mediaSource = null; IMFSourceReader sourceReader = null; ulong videoSize = 0; ulong frameRate = 0; MFHelper.IMFMediaType mediaType = null; IMFPresentationDescriptor presentationDescriptor = null; uint objectType = default(uint); object objectSource = null; API.MFStartup(); // Create the media source using source resolver and the input URL IMFSourceResolver sourceResolver = null; API.MFCreateSourceResolver(out sourceResolver); // sourceResolver.CreateObjectFromURL("..\\..\\Apps\\SmartCam\\SmartRecorder\\Output\\VideoWriterTest\\CreateTestWMVFile_640x480_24fps_15s\\TestMP4File_640x480_24fps_15s.mp4", Consts.MF_RESOLUTION_MEDIASOURCE, null, out objectType, out objectSource); sourceResolver.CreateObjectFromURL(mp4filepath, Consts.MF_RESOLUTION_MEDIASOURCE, null, out objectType, out objectSource); mediaSource = (IMFMediaSource)objectSource; API.MFCreateSourceReaderFromMediaSource(mediaSource, null, out sourceReader); mediaSource.CreatePresentationDescriptor(out presentationDescriptor); // Get the duration presentationDescriptor.GetUINT64(new Guid(Consts.MF_PD_DURATION), out duration); // Get the video width and height sourceReader.GetCurrentMediaType(0, out mediaType); mediaType.GetUINT64(Guid.Parse(Consts.MF_MT_FRAME_SIZE), out videoSize); videoWidth = (uint)(videoSize >> 32); videoHeight = (uint)(videoSize & 0x00000000FFFFFFFF); // Get the Frame Rate mediaType.GetUINT64(Guid.Parse(Consts.MF_MT_FRAME_RATE), out frameRate); if ((frameRate & 0x00000000FFFFFFFF) != 0) { videoFPS = (double)(frameRate >> 32) / (double)(frameRate & 0x00000000FFFFFFFF); } // Get the encoding bitrate mediaType.GetUINT32(new Guid(Consts.MF_MT_AVG_BITRATE), out videoBitrate); API.MFShutdown(); } catch (Exception exception) { Console.WriteLine("Exception failure: {0}", exception.ToString()); Assert.IsFalse(true); } Assert.IsFalse(Math.Abs((double)duration - (double)VIDEO_DURATION_IN_100_NS) > (double)VIDEO_DURATION_VAR_IN_100_NS); Assert.IsFalse(videoWidth != VIDEO_WIDTH); Assert.IsFalse(videoHeight != VIDEO_HEIGHT); Assert.IsFalse(Math.Abs(videoFPS - VIDEO_FPS) > VIDEO_FPS_VAR); Assert.IsFalse(Math.Abs((int)videoBitrate - VIDEO_ENCODE_BITRATE) > VIDEO_ENCODE_BITRATE_VAR); }
/// <summary> /// Starts the asychronous encode operation /// </summary> /// <param name="inputURL">Source filename</param> /// <param name="outputURL">Targe filename</param> /// <param name="audioOutput">Audio format that will be used for audio streams</param> /// <param name="videoOutput">Video format that will be used for video streams</param> /// <param name="startPosition">Starting position of the contet</param> /// <param name="endPosition">Position where the new content will end</param> public void Encode(string inputURL, string outputURL, AudioFormat audioOutput, VideoFormat videoOutput, ulong startPosition, ulong endPosition) { // If busy with other operation ignore and return if (this.IsBusy()) { return; } try { this.presentationClock = null; this.startPosition = startPosition; this.endPosition = endPosition; object objectSource = null; // Create the media source using source resolver and the input URL uint objectType = default(uint); this.mediaSource = null; // Init source resolver IMFSourceResolver sourceResolver = null; MFHelper.MFCreateSourceResolver(out sourceResolver); sourceResolver.CreateObjectFromURL(inputURL, Consts.MF_RESOLUTION_MEDIASOURCE, null, out objectType, out objectSource); this.mediaSource = (IMFMediaSource)objectSource; // Create the media session using a global start time so MF_TOPOLOGY_PROJECTSTOP can be used to stop the session this.mediaSession = null; IMFAttributes mediaSessionAttributes = null; MFHelper.MFCreateAttributes(out mediaSessionAttributes, 1); mediaSessionAttributes.SetUINT32(new Guid(Consts.MF_SESSION_GLOBAL_TIME), 1); MFHelper.MFCreateMediaSession(mediaSessionAttributes, out this.mediaSession); // Create the event handler AsyncEventHandler mediaEventHandler = new AsyncEventHandler(this.mediaSession); mediaEventHandler.MediaEvent += this.MediaEvent; // Get the stream descriptor IMFPresentationDescriptor presentationDescriptor = null; mediaSource.CreatePresentationDescriptor(out presentationDescriptor); // Get the duration presentationDescriptor.GetUINT64(new Guid(Consts.MF_PD_DURATION), out this.duration); IMFTranscodeProfile transcodeProfile = null; Guid containerType = new Guid(Consts.MFTranscodeContainerType_MPEG4); if (outputURL.EndsWith(".wmv", StringComparison.OrdinalIgnoreCase) || outputURL.EndsWith(".wma", StringComparison.OrdinalIgnoreCase)) { containerType = new Guid(Consts.MFTranscodeContainerType_ASF); } // Generate the transcoding profile transcodeProfile = SimpleFastEncode.CreateProfile(audioOutput, videoOutput, containerType); // Create the MF topology using the profile IMFTopology topology = null; MFHelper.MFCreateTranscodeTopology(this.mediaSource, outputURL, transcodeProfile, out topology); // Set the end position topology.SetUINT64(new Guid(Consts.MF_TOPOLOGY_PROJECTSTART), 0); topology.SetUINT64(new Guid(Consts.MF_TOPOLOGY_PROJECTSTOP), (endPosition == 0) ? this.duration : endPosition); // Set the session topology this.mediaSession.SetTopology((uint)Enums.MFSESSION_SETTOPOLOGY_FLAGS.None, topology); } catch (Exception ex) { this.mediaSession = null; // Fire the EncodeError event if (this.EncodeError != null) { this.EncodeError(new Exception(ex.Message, ex)); } } }