예제 #1
0
파일: AudioWMA.cs 프로젝트: zxc120/GARbro
        private static long GetDuration(IMFSourceReader reader)
        {
            var variantPtr = Marshal.AllocHGlobal(MarshalHelpers.SizeOf <PropVariant>());

            try
            {
                int hResult = reader.GetPresentationAttribute(MediaFoundationInterop.MF_SOURCE_READER_MEDIASOURCE,
                                                              MediaFoundationAttributes.MF_PD_DURATION, variantPtr);
                if (hResult == MediaFoundationErrors.MF_E_ATTRIBUTENOTFOUND)
                {
                    return(0);
                }
                if (hResult != 0)
                {
                    Marshal.ThrowExceptionForHR(hResult);
                }

                var variant = MarshalHelpers.PtrToStructure <PropVariant> (variantPtr);
                return((long)variant.Value);
            }
            finally
            {
                PropVariant.Clear(variantPtr);
                Marshal.FreeHGlobal(variantPtr);
            }
        }
예제 #2
0
파일: frmMain.cs 프로젝트: yudigh/Tanta
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// A centralized place to close down all media devices.
        /// </summary>
        /// <history>
        ///    01 Nov 18  Cynic - Started
        /// </history>
        private void CloseAllMediaDevices()
        {
            //HResult hr;
            LogMessage("CloseAllMediaDevices");

            // Shut down the source reader
            if (sourceReader != null)
            {
                Marshal.ReleaseComObject(sourceReader);
                sourceReader = null;
            }

            // close the sink writer
            if (sinkWriter != null)
            {
                // note we could Finalize_() this here but there
                // is no need. That is done when the stream ends
                Marshal.ReleaseComObject(sinkWriter);
                sinkWriter = null;
            }

            if (sourceReaderNativeVideoMediaType != null)
            {
                Marshal.ReleaseComObject(sourceReaderNativeVideoMediaType);
                sourceReaderNativeVideoMediaType = null;
            }

            if (sourceReaderNativeAudioMediaType != null)
            {
                Marshal.ReleaseComObject(sourceReaderNativeAudioMediaType);
                sourceReaderNativeAudioMediaType = null;
            }
        }
예제 #3
0
        private long GetLength(IMFSourceReader reader)
        {
            var variantPtr = Marshal.AllocHGlobal(MarshalHelpers.SizeOf <PropVariant>());

            try
            {
                // http://msdn.microsoft.com/en-gb/library/windows/desktop/dd389281%28v=vs.85%29.aspx#getting_file_duration
                int hResult = reader.GetPresentationAttribute(MediaFoundationInterop.MF_SOURCE_READER_MEDIASOURCE,
                                                              MediaFoundationAttributes.MF_PD_DURATION, variantPtr);
                if (hResult == MediaFoundationErrors.MF_E_ATTRIBUTENOTFOUND)
                {
                    // this doesn't support telling us its duration (might be streaming)
                    return(0);
                }
                if (hResult != 0)
                {
                    Marshal.ThrowExceptionForHR(hResult);
                }
                var variant = MarshalHelpers.PtrToStructure <PropVariant>(variantPtr);

                var lengthInBytes = (((long)variant.Value) * waveFormat.AverageBytesPerSecond) / 10000000L;
                return(lengthInBytes);
            }
            finally
            {
                PropVariant.Clear(variantPtr);
                Marshal.FreeHGlobal(variantPtr);
            }
        }
        /// <summary>
        ///     Use Source Reader to allocate a sample
        /// </summary>
        /// <param name="sourceReader">The Source Reader</param>
        /// <param name="dwStreamIndex">The stream to pull data from</param>
        /// <param name="dwControlFlags">A bitwise OR of zero or more flags from the MF_SOURCE_READER_CONTROL_FLAG enumeration</param>
        /// <param name="pdwActualStreamIndex">Receives the zero-based index of the stream</param>
        /// <param name="pdwStreamFlags">Receives a bitwise OR of zero or more flags from the MF_SOURCE_READER_FLAG enumeration</param>
        /// <param name="pllTimestamp">Receives the time stamp of the sample, or the time of the stream event indicated in pdwStreamFlags. The time is given in 100-nanosecond units</param>
        public void ReadSampleFrom(
            IMFSourceReader sourceReader,
            uint dwStreamIndex,
            uint dwControlFlags,
            out uint pdwActualStreamIndex,
            out uint pdwStreamFlags,
            out ulong pllTimestamp)
        {
            // Once a sample is read avoid reading more samples
            if (this.read)
            {
                throw new InvalidOperationException("Already holding a sample");
            }

            sourceReader.ReadSample(dwStreamIndex, dwControlFlags, out pdwActualStreamIndex, out pdwStreamFlags, out pllTimestamp, out this.sample);

            if (this.sample != null)
            {
                // Get the size of the media sample in bytes
                IMFMediaBuffer buffer = null;
                this.sample.GetBufferByIndex(0, out buffer);
                buffer.GetCurrentLength(out this.bufferSize);

                // Add the memory pressure of unmanaged memory to improve the garbage collector performance
                GC.AddMemoryPressure(this.bufferSize);
            }

            this.read = true;
        }
예제 #5
0
        private static MediaType GetCurrentMediaType(IMFSourceReader reader)
        {
            IMFMediaType mediaType;

            reader.GetCurrentMediaType(-3, out mediaType);
            return(new MediaType(mediaType));
        }
예제 #6
0
        private long GetLength(IMFSourceReader reader)
        {
            IntPtr intPtr = Marshal.AllocHGlobal(MarshalHelpers.SizeOf <PropVariant>());
            long   result;

            try
            {
                int presentationAttribute = reader.GetPresentationAttribute(-1, MediaFoundationAttributes.MF_PD_DURATION, intPtr);
                if (presentationAttribute == -1072875802)
                {
                    result = 0L;
                }
                else
                {
                    if (presentationAttribute != 0)
                    {
                        Marshal.ThrowExceptionForHR(presentationAttribute);
                    }
                    result = (long)MarshalHelpers.PtrToStructure <PropVariant>(intPtr).Value *(long)this.waveFormat.AverageBytesPerSecond / 10000000L;
                }
            }
            finally
            {
                PropVariant.Clear(intPtr);
                Marshal.FreeHGlobal(intPtr);
            }
            return(result);
        }
예제 #7
0
        private WaveFormat GetCurrentWaveFormat(IMFSourceReader reader)
        {
            IMFMediaType uncompressedMediaType;

            reader.GetCurrentMediaType(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, out uncompressedMediaType);

            // Two ways to query it, first is to ask for properties (second is to convert into WaveFormatEx using MFCreateWaveFormatExFromMFMediaType)
            var  outputMediaType = new MediaType(uncompressedMediaType);
            Guid actualMajorType = outputMediaType.MajorType;

            Debug.Assert(actualMajorType == MediaTypes.MFMediaType_Audio);
            Guid audioSubType = outputMediaType.SubType;
            int  channels     = outputMediaType.ChannelCount;
            int  bits         = outputMediaType.BitsPerSample;
            int  sampleRate   = outputMediaType.SampleRate;

            if (audioSubType == AudioSubtypes.MFAudioFormat_PCM)
            {
                return(new WaveFormat(sampleRate, bits, channels));
            }
            if (audioSubType == AudioSubtypes.MFAudioFormat_Float)
            {
                return(WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channels));
            }
            var subTypeDescription = FieldDescriptionHelper.Describe(typeof(AudioSubtypes), audioSubType);

            throw new InvalidDataException(String.Format("Unsupported audio sub Type {0}", subTypeDescription));
        }
예제 #8
0
        private static MediaType GetCurrentMediaType(IMFSourceReader reader)
        {
            IMFMediaType mediaType;

            reader.GetCurrentMediaType(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, out mediaType);
            return(new MediaType(mediaType));
        }
예제 #9
0
        /// <summary>
        /// Reads from this wave stream
        /// </summary>
        /// <param name="buffer">Buffer to read into</param>
        /// <param name="offset">Offset in buffer</param>
        /// <param name="count">Bytes required</param>
        /// <returns>Number of bytes read; 0 indicates end of stream</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (pReader == null)
            {
                pReader = CreateReader(settings);
            }
            if (repositionTo != -1)
            {
                Reposition(repositionTo);
            }
            int bytesWritten = 0;

            // read in any leftovers from last time
            if (decoderOutputCount > 0)
            {
                bytesWritten += ReadFromDecoderBuffer(buffer, offset, count - bytesWritten);
            }
            while (bytesWritten < count)
            {
                IMFSample             pSample;
                MF_SOURCE_READER_FLAG dwFlags;
                ulong timestamp;
                int   actualStreamIndex;
                pReader.ReadSample(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, out actualStreamIndex, out dwFlags, out timestamp, out pSample);
                if ((dwFlags & MF_SOURCE_READER_FLAG.MF_SOURCE_READERF_ENDOFSTREAM) != 0)
                {
                    // reached the end of the stream
                    break;
                }
                else if ((dwFlags & MF_SOURCE_READER_FLAG.MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) != 0)
                {
                    Console.WriteLine("SAMPLE SETTINGS CHANGED!");
                    waveFormat = GetCurrentWaveFormat(pReader, false, 0, 0, 0);
                    OnWaveFormatChanged();
                    // carry on, but user must handle the change of format
                }
                else
                if (dwFlags != 0)
                {
                    throw new InvalidOperationException(String.Format("MediaFoundationReadError {0}", dwFlags));
                }
                IMFMediaBuffer pBuffer;
                pSample.ConvertToContiguousBuffer(out pBuffer);
                IntPtr pAudioData;
                int    cbBuffer;
                int    pcbMaxLength;
                pBuffer.Lock(out pAudioData, out pcbMaxLength, out cbBuffer);
                EnsureBuffer(cbBuffer);
                Marshal.Copy(pAudioData, decoderOutputBuffer, 0, cbBuffer);
                decoderOutputOffset = 0;
                decoderOutputCount  = cbBuffer;
                bytesWritten       += ReadFromDecoderBuffer(buffer, offset + bytesWritten, count - bytesWritten);
                pBuffer.Unlock();
                Marshal.ReleaseComObject(pBuffer);
                Marshal.ReleaseComObject(pSample);
            }
            position += bytesWritten;
            return(bytesWritten);
        }
예제 #10
0
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Gets a list of all supported video formats from a video source device
        /// as a nice displayable bit of text. outSb will never be null but can be
        /// empty. There will be one line per mediaType
        ///
        /// </summary>
        /// <returns>S_OK for success, nz for fail</returns>
        /// <param name="sourceReader">the source reader object</param>
        /// <param name="maxFormatsToTestFor">the max number of formats we test for</param>
        /// <history>
        ///    01 Nov 18  Cynic - Started
        /// </history>
        public static HResult GetSupportedVideoFormatsFromSourceReaderAsText(IMFSourceReader sourceReader, int maxFormatsToTestFor, out StringBuilder outSb)
        {
            IMFMediaType mediaTypeObj = null;
            HResult      hr;

            // we always return something here
            outSb = new StringBuilder();

            // sanity check
            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("GetSupportedVideoFormatsFromSourceReaderAsText failed on call to GetNativeMediaType, retVal=" + hr.ToString());
                    }

                    // get the formats for this type
                    StringBuilder tmpSb;
                    hr = GetSupportedFormatsFromMediaTypeAsText(mediaTypeObj, out tmpSb);
                    if (hr != HResult.S_OK)
                    {
                        // we failed
                        throw new Exception("GetSupportedVideoFormatsFromSourceReaderAsText failed on call to GetSupportedFormatsFromMediaTypeAsText, retVal=" + hr.ToString());
                    }
                    // add it here
                    outSb.Append(typeIndex.ToString() + " ");
                    outSb.Append(tmpSb);
                    outSb.Append("\r\n");
                    outSb.Append("\r\n");
                }
            }
            finally
            {
                // always release our mediaType if we have one
                if (mediaTypeObj != null)
                {
                    Marshal.ReleaseComObject(mediaTypeObj);
                    mediaTypeObj = null;
                }
            }

            // all done
            return(HResult.S_OK);
        }
        /// <summary>
        /// Gets an attribute from the underlying media source.
        /// </summary>
        /// <param name="sourceReader">A valid IMFSourceReader instance.</param></param>
        /// <param name="streamIndex">The streamIndex to query.</param>
        /// <param name="mediaTypeIndex">The zero-based index of the media type to retrieve.</param>
        /// <param name="mediaType">Receives an instance of the IMFMediaType interface.</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 GetPresentationAttribute(this IMFSourceReader sourceReader, SourceReaderFirstStreamOrMediaSource streamIndex, Guid guidAttribute, PropVariant attribute)
        {
            if (sourceReader == null)
            {
                throw new ArgumentNullException("sourceReader");
            }

            return(sourceReader.GetPresentationAttribute((int)streamIndex, guidAttribute, attribute));
        }
 private void ClearAll()
 {
     this.streamsInfo.Clear();
     this.sourceFilename  = string.Empty;
     this.targetFilename  = string.Empty;
     this.sourceReader    = null;
     this.sinkWriter      = null;
     this.selectedStreams = 0;
 }
        /// <summary>
        /// Gets a format that is supported natively by the media source.
        /// </summary>
        /// <param name="sourceReader">A valid IMFSourceReader instance.</param></param>
        /// <param name="streamIndex">The streamIndex to query.</param>
        /// <param name="mediaTypeIndex">The zero-based index of the media type to retrieve.</param>
        /// <param name="mediaType">Receives an instance of the IMFMediaType interface.</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 GetNativeMediaType(this IMFSourceReader sourceReader, SourceReaderFirstStream streamIndex, int mediaTypeIndex, out IMFMediaType mediaType)
        {
            if (sourceReader == null)
            {
                throw new ArgumentNullException("sourceReader");
            }

            return(sourceReader.GetNativeMediaType((int)streamIndex, mediaTypeIndex, out mediaType));
        }
예제 #14
0
 /// <summary>
 /// Cleans up after finishing with this reader
 /// </summary>
 /// <param name="disposing">true if called from Dispose</param>
 protected override void Dispose(bool disposing)
 {
     if (pReader != null)
     {
         Marshal.ReleaseComObject(pReader);
         pReader = null;
     }
     base.Dispose(disposing);
 }
        /// <summary>
        /// Flushes one or more streams.
        /// </summary>
        /// <param name="sourceReader">A valid IMFSourceReader instance.</param></param>
        /// <param name="streamIndex">The streamIndex(s) to flush.</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 Flush(this IMFSourceReader sourceReader, SourceReaderStreams stream)
        {
            if (sourceReader == null)
            {
                throw new ArgumentNullException("sourceReader");
            }

            return(sourceReader.Flush((int)stream));
        }
        /// <summary>
        /// Selects or deselects one or more streams.
        /// </summary>
        /// <param name="sourceReader">A valid IMFSourceReader instance.</param></param></param>
        /// <param name="streamIndex">The stream to set.</param>
        /// <param name="selected">Specify True to select streams or False to deselect streams. If a stream is deselected, it will not generate data.</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 SetStreamSelection(this IMFSourceReader sourceReader, SourceReaderStreams streamIndex, bool selected)
        {
            if (sourceReader == null)
            {
                throw new ArgumentNullException("sourceReader");
            }

            return(sourceReader.SetStreamSelection((int)streamIndex, selected));
        }
        /// <summary>
        /// Sets the media type for a stream.
        /// </summary>
        /// <param name="sourceReader">A valid IMFSourceReader instance.</param></param></param>
        /// <param name="streamIndex">The stream to configure.</param>
        /// <param name="mediaType">An instance of the IMFMediaType interface of the media type.</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 SetCurrentMediaType(this IMFSourceReader sourceReader, SourceReaderFirstStream streamIndex, IMFMediaType mediaType)
        {
            if (sourceReader == null)
            {
                throw new ArgumentNullException("sourceReader");
            }

            return(sourceReader.SetCurrentMediaType((int)streamIndex, null, mediaType));
        }
예제 #18
0
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (this.pReader == null)
            {
                this.pReader = this.CreateReader(this.settings);
            }
            if (this.repositionTo != -1L)
            {
                this.Reposition(this.repositionTo);
            }
            int i = 0;

            if (this.decoderOutputCount > 0)
            {
                i += this.ReadFromDecoderBuffer(buffer, offset, count - i);
            }
            while (i < count)
            {
                int num;
                MF_SOURCE_READER_FLAG mF_SOURCE_READER_FLAG;
                ulong     num2;
                IMFSample iMFSample;
                this.pReader.ReadSample(-3, 0, out num, out mF_SOURCE_READER_FLAG, out num2, out iMFSample);
                if ((mF_SOURCE_READER_FLAG & MF_SOURCE_READER_FLAG.MF_SOURCE_READERF_ENDOFSTREAM) != MF_SOURCE_READER_FLAG.None)
                {
                    break;
                }
                if ((mF_SOURCE_READER_FLAG & MF_SOURCE_READER_FLAG.MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) != MF_SOURCE_READER_FLAG.None)
                {
                    this.waveFormat = this.GetCurrentWaveFormat(this.pReader);
                    this.OnWaveFormatChanged();
                }
                else if (mF_SOURCE_READER_FLAG != MF_SOURCE_READER_FLAG.None)
                {
                    throw new InvalidOperationException(string.Format("MediaFoundationReadError {0}", mF_SOURCE_READER_FLAG));
                }
                IMFMediaBuffer iMFMediaBuffer;
                iMFSample.ConvertToContiguousBuffer(out iMFMediaBuffer);
                IntPtr source;
                int    num3;
                int    bytesRequired;
                iMFMediaBuffer.Lock(out source, out num3, out bytesRequired);
                this.EnsureBuffer(bytesRequired);
                Marshal.Copy(source, this.decoderOutputBuffer, 0, bytesRequired);
                this.decoderOutputOffset = 0;
                this.decoderOutputCount  = bytesRequired;
                i += this.ReadFromDecoderBuffer(buffer, offset + i, count - i);
                iMFMediaBuffer.Unlock();
                Marshal.ReleaseComObject(iMFMediaBuffer);
                Marshal.ReleaseComObject(iMFSample);
            }
            this.position += (long)i;
            return(i);
        }
        /// <summary>
        /// Seeks to a new position in the media source.
        /// </summary>
        /// <param name="sourceReader">A valid IMFSourceReader instance.</param></param></param>
        /// <param name="position">The position from which playback will be started.</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 SetCurrentPosition(this IMFSourceReader sourceReader, TimeSpan position)
        {
            if (sourceReader == null)
            {
                throw new ArgumentNullException("sourceReader");
            }

            using (PropVariant value = new PropVariant(position.Ticks))
            {
                return(sourceReader.SetCurrentPosition(Guid.Empty, value));
            }
        }
예제 #20
0
        protected override IMFSourceReader CreateReader(MediaFoundationReader.MediaFoundationReaderSettings settings)
        {
            IMFSourceReader expr_15 = MediaFoundationApi.CreateSourceReaderFromByteStream(MediaFoundationApi.CreateByteStream(new ComStream(this.stream)));

            expr_15.SetStreamSelection(-2, false);
            expr_15.SetStreamSelection(-3, true);
            expr_15.SetCurrentMediaType(-3, IntPtr.Zero, new MediaType
            {
                MajorType = MediaTypes.MFMediaType_Audio,
                SubType   = settings.RequestFloatOutput ? AudioSubtypes.MFAudioFormat_Float : AudioSubtypes.MFAudioFormat_PCM
            }.MediaFoundationObject);
            return(expr_15);
        }
예제 #21
0
        protected void Init(MediaFoundationReader.MediaFoundationReaderSettings initialSettings)
        {
            MediaFoundationApi.Startup();
            this.settings = (initialSettings ?? new MediaFoundationReader.MediaFoundationReaderSettings());
            IMFSourceReader iMFSourceReader = this.CreateReader(this.settings);

            this.waveFormat = this.GetCurrentWaveFormat(iMFSourceReader);
            iMFSourceReader.SetStreamSelection(-3, true);
            this.length = this.GetLength(iMFSourceReader);
            if (this.settings.SingleReaderObject)
            {
                this.pReader = iMFSourceReader;
            }
        }
        /// <summary>
        /// Reads the next sample from the media source.
        /// </summary>
        /// <param name="sourceReader">A valid IMFSourceReader instance.</param></param></param>
        /// <param name="streamIndex">The stream to pull data from.</param>
        /// <param name="controlFlags">One or more members of the MF_SOURCE_READER_CONTROL_FLAG enumeration.</param>
        /// <param name="actualStreamIndex">Receives the zero-based index of the stream.</param>
        /// <param name="streamFlags">Receives one or more members of the MF_SOURCE_READER_FLAG enumeration.</param>
        /// <param name="timestamp">Receives the time stamp of the sample, or the time of the stream event indicated in <paramref name="streamFlags"/>.</param>
        /// <param name="sample">Receives an instance of the IMFSample interface or the value null.</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 ReadSample(this IMFSourceReader sourceReader, SourceReaderStreams streamIndex, MF_SOURCE_READER_CONTROL_FLAG controlFlags, out int actualStreamIndex, out MF_SOURCE_READER_FLAG streamFlags, out TimeSpan timestamp, out IMFSample sample)
        {
            if (sourceReader == null)
            {
                throw new ArgumentNullException("sourceReader");
            }

            long tmp = 0;

            HResult hr = sourceReader.ReadSample((int)streamIndex, controlFlags, out actualStreamIndex, out streamFlags, out tmp, out sample);

            timestamp = hr.Succeeded() ? TimeSpan.FromTicks(tmp) : default(TimeSpan);

            return(hr);
        }
예제 #23
0
        /// <summary>
        /// Creates a new MediaFoundationReader based on the supplied file
        /// </summary>
        /// <param name="file">Filename</param>
        /// <param name="settings">Advanced settings</param>
        public MediaFoundationReaderX(string file, MediaFoundationReaderSettings settings)
        {
            MediaFoundationApi.Startup();
            this.settings = settings;
            this.file     = file;
            var reader = CreateReader(settings);

            waveFormat = GetCurrentWaveFormat(reader, false, 0, 0, 0);
            reader.SetStreamSelection(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
            length = GetLength(reader);
            if (settings.SingleReaderObject)
            {
                pReader = reader;
            }
        }
예제 #24
0
        public MediaFoundationReader(string file, MediaFoundationReader.MediaFoundationReaderSettings settings)
        {
            MediaFoundationApi.Startup();
            this.settings = settings;
            this.file     = file;
            IMFSourceReader imfsourceReader = this.CreateReader(settings);

            this.waveFormat = this.GetCurrentWaveFormat(imfsourceReader);
            imfsourceReader.SetStreamSelection(-3, true);
            this.length = this.GetLength(imfsourceReader);
            if (settings.SingleReaderObject)
            {
                this.pReader = imfsourceReader;
            }
        }
예제 #25
0
        /// <summary>
        /// Gets a pointer to the underlying Source Reader object.
        /// </summary>
        /// <param name="captureSource">A valid IMFCaptureSource instance.</param>
        /// <param name="sourceReader">Receives an instance of the underlying Source Reader.</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 GetService(this IMFCaptureSource captureSource, out IMFSourceReader sourceReader)
        {
            if (captureSource == null)
            {
                throw new ArgumentNullException("captureSource");
            }

            object tmp;

            HResult hr = captureSource.GetService(Guid.Empty, typeof(IMFSourceReader).GUID, out tmp);

            sourceReader = hr.Succeeded() ? tmp as IMFSourceReader : null;

            return(hr);
        }
예제 #26
0
        /// <summary>
        /// Creates a new MediaFoundationReader based on the supplied file
        /// </summary>
        /// <param name="file">Filename</param>
        /// <param name="settings">Advanced settings</param>
        public MediaFoundationReaderX(string file, bool useOverrides, int sampleRate, int numChannels, int bitDepth)
        {
            MediaFoundationApi.Startup();
            this.settings = new MediaFoundationReaderSettings();
            this.file     = file;
            var reader = CreateReader(settings);

            waveFormat = GetCurrentWaveFormat(reader, useOverrides, sampleRate, numChannels, bitDepth);
            reader.SetStreamSelection(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
            length = GetLength(reader);
            if (settings.SingleReaderObject)
            {
                pReader = reader;
            }
        }
        /// <summary>
        /// Initializes
        /// </summary>
        protected void Init(MediaFoundationReaderSettings initialSettings)
        {
            MediaFoundationApi.Startup();
            settings = initialSettings ?? new MediaFoundationReaderSettings();
            var reader = CreateReader(settings);

            waveFormat = GetCurrentWaveFormat(reader);

            reader.SetStreamSelection(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
            length = GetLength(reader);

            if (settings.SingleReaderObject)
            {
                pReader = reader;
            }
        }
예제 #28
0
        /// <summary>
        /// Creates the reader (overridable by )
        /// </summary>
        protected virtual IMFSourceReader CreateReader2(byte[] buffer, MediaFoundationReaderSettings settings)
        {
            IMFSourceReader reader = null;

            //MediaFoundationInterop.MFCreateSourceReaderFromURL(file, null, out reader);
            reader = MediaFoundationApi.CreateSourceReaderFromByteStream(MediaFoundationApi.CreateByteStream(new ComStream(new MemoryStream(buffer))));

            reader.SetStreamSelection(MediaFoundationInterop.MF_SOURCE_READER_ALL_STREAMS, false);
            reader.SetStreamSelection(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);

            // Create a partial media type indicating that we want uncompressed PCM audio

            var partialMediaType = new MediaType();

            partialMediaType.MajorType = MediaTypes.MFMediaType_Audio;
            partialMediaType.SubType   = settings.RequestFloatOutput ? AudioSubtypes.MFAudioFormat_Float : AudioSubtypes.MFAudioFormat_PCM;

            var currentMediaType = GetCurrentMediaType(reader);

            // mono, low sample rate files can go wrong on Windows 10 unless we specify here
            partialMediaType.ChannelCount = currentMediaType.ChannelCount;
            partialMediaType.SampleRate   = currentMediaType.SampleRate;

            try
            {
                // set the media type
                // can return MF_E_INVALIDMEDIATYPE if not supported
                reader.SetCurrentMediaType(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, IntPtr.Zero, partialMediaType.MediaFoundationObject);
            }
            catch (COMException ex) when(ex.GetHResult() == MediaFoundationErrors.MF_E_INVALIDMEDIATYPE)
            {
                // HE-AAC (and v2) seems to halve the samplerate
                if (currentMediaType.SubType == AudioSubtypes.MFAudioFormat_AAC && currentMediaType.ChannelCount == 1)
                {
                    partialMediaType.SampleRate   = currentMediaType.SampleRate *= 2;
                    partialMediaType.ChannelCount = currentMediaType.ChannelCount *= 2;
                    reader.SetCurrentMediaType(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, IntPtr.Zero, partialMediaType.MediaFoundationObject);
                }
                else
                {
                    throw;
                }
            }

            Marshal.ReleaseComObject(currentMediaType.MediaFoundationObject);
            return(reader);
        }
예제 #29
0
        /// <summary>
        /// Creates a new MediaFoundationReader based on the supplied file
        /// </summary>
        /// <param name="inputStream">The input stream containing a WAV.</param>
        /// <param name="settings">Advanced settings</param>
        public MediaFoundationReader(System.IO.Stream inputStream, MediaFoundationReaderSettings settings)
        {
            MediaFoundationApi.Startup();
            this.settings = settings;
            _inputStream  = inputStream;
            var reader = CreateReader(settings);

            waveFormat = GetCurrentWaveFormat(reader);

            reader.SetStreamSelection(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
            length = GetLength(reader);

            if (settings.SingleReaderObject)
            {
                pReader = reader;
            }
        }
        /// <summary>
        /// Creates a new MediaFoundationReader based on the supplied file
        /// </summary>
        /// <param name="file">Filename</param>
        /// <param name="settings">Advanced settings</param>
        public MediaFoundationReader(string file, MediaFoundationReaderSettings settings)
        {
            MediaFoundationApi.Startup();
            this.settings = settings;
            this.file = file;
            var reader = CreateReader(settings);

            waveFormat = GetCurrentWaveFormat(reader);

            reader.SetStreamSelection(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
            length = GetLength(reader);

            if (settings.SingleReaderObject)
            {
                pReader = reader;
            }
        }
예제 #31
0
        private long GetLength(IMFSourceReader reader)
        {
            PropVariant propVariant;
            int         presentationAttribute = reader.GetPresentationAttribute(-1, MediaFoundationAttributes.MF_PD_DURATION, out propVariant);

            if (presentationAttribute == -1072875802)
            {
                return(0L);
            }
            if (presentationAttribute != 0)
            {
                Marshal.ThrowExceptionForHR(presentationAttribute);
            }
            long result = (long)propVariant.Value * (long)this.waveFormat.AverageBytesPerSecond / 10000000L;

            propVariant.Clear();
            return(result);
        }
        /// <summary>
        /// Reads from this wave stream
        /// </summary>
        /// <param name="buffer">Buffer to read into</param>
        /// <param name="offset">Offset in buffer</param>
        /// <param name="count">Bytes required</param>
        /// <returns>Number of bytes read; 0 indicates end of stream</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (pReader == null)
            {
                pReader = CreateReader(settings);
            }
            if (repositionTo != -1)
            {
                Reposition(repositionTo);
            }

            int bytesWritten = 0;
            // read in any leftovers from last time
            if (decoderOutputCount > 0)
            {
                bytesWritten += ReadFromDecoderBuffer(buffer, offset, count - bytesWritten);
            }

            while (bytesWritten < count)
            {
                IMFSample pSample;
                int dwFlags;
                ulong timestamp;
                int actualStreamIndex;
                pReader.ReadSample(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, out actualStreamIndex, out dwFlags, out timestamp, out pSample);
                if (dwFlags != 0)
                {
                    // reached the end of the stream or media type changed
                    break;
                }/*
                if (dwFlags & MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED)
                {
                    printf("Type change - not supported by WAVE file format.\n");
                    break;
                }
                if (dwFlags & MF_SOURCE_READERF_ENDOFSTREAM)
                {
                    printf("End of input file.\n");
                    break;
                }*/

                IMFMediaBuffer pBuffer;
                pSample.ConvertToContiguousBuffer(out pBuffer);
                IntPtr pAudioData = IntPtr.Zero;
                int cbBuffer;
                int pcbMaxLength;
                pBuffer.Lock(out pAudioData, out pcbMaxLength, out cbBuffer);
                EnsureBuffer(cbBuffer);
                Marshal.Copy(pAudioData, decoderOutputBuffer, 0, cbBuffer);
                decoderOutputOffset = 0;
                decoderOutputCount = cbBuffer;

                bytesWritten += ReadFromDecoderBuffer(buffer, offset + bytesWritten, count - bytesWritten);

                pBuffer.Unlock();
                Marshal.ReleaseComObject(pBuffer);
                Marshal.ReleaseComObject(pSample);
            }
            position += bytesWritten;
            return bytesWritten;
        }
        /// <summary>
        /// Creates a new MediaFoundationReader based on the supplied file
        /// </summary>
        /// <param name="file">Filename</param>
        /// <param name="settings">Advanced settings</param>
        public MediaFoundationReader(string file, MediaFoundationReaderSettings settings)
        {
            MediaFoundationApi.Startup();
            this.settings = settings;
            this.file = file;
            var reader = CreateReader(settings);

            /* IMFMediaType currentMediaType;
            reader.GetCurrentMediaType(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, out currentMediaType);
            var current = new MediaType(currentMediaType);
            IMFMediaType nativeMediaType;
            reader.GetNativeMediaType(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, out nativeMediaType);
            var native = new MediaType(nativeMediaType);*/

            // now let's find out what we actually got
            IMFMediaType uncompressedMediaType;
            reader.GetCurrentMediaType(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, out uncompressedMediaType);

            // Two ways to query it, first is to ask for properties (second is to convert into WaveFormatEx using MFCreateWaveFormatExFromMFMediaType)
            var outputMediaType = new MediaType(uncompressedMediaType);
            Guid actualMajorType = outputMediaType.MajorType;
            Debug.Assert(actualMajorType == MediaTypes.MFMediaType_Audio);
            Guid audioSubType = outputMediaType.SubType;
            int channels = outputMediaType.ChannelCount;
            int bits = outputMediaType.BitsPerSample;
            int sampleRate = outputMediaType.SampleRate;

            waveFormat = audioSubType == AudioSubtypes.MFAudioFormat_PCM
                             ? new WaveFormat(sampleRate, bits, channels)
                             : WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channels);

            reader.SetStreamSelection(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, true);
            length = GetLength(reader);

            if (settings.SingleReaderObject)
            {
                pReader = reader;
            }
        }
예제 #34
0
        private WaveFormat GetCurrentWaveFormat(IMFSourceReader reader)
        {
            IMFMediaType uncompressedMediaType;
            reader.GetCurrentMediaType(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, out uncompressedMediaType);

            // Two ways to query it, first is to ask for properties (second is to convert into WaveFormatEx using MFCreateWaveFormatExFromMFMediaType)
            var outputMediaType = new MediaType(uncompressedMediaType);
            Guid actualMajorType = outputMediaType.MajorType;
            Debug.Assert(actualMajorType == MediaTypes.MFMediaType_Audio);
            Guid audioSubType = outputMediaType.SubType;
            int channels = outputMediaType.ChannelCount;
            int bits = outputMediaType.BitsPerSample;
            int sampleRate = outputMediaType.SampleRate;

            if (audioSubType == AudioSubtypes.MFAudioFormat_PCM)
                return new WaveFormat(sampleRate, bits, channels);
            if (audioSubType == AudioSubtypes.MFAudioFormat_Float)
                return WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channels);
            var subTypeDescription = FieldDescriptionHelper.Describe(typeof (AudioSubtypes), audioSubType);
            throw new InvalidDataException(String.Format("Unsupported audio sub Type {0}", subTypeDescription));
        }
예제 #35
0
 public static void MFCreateSourceReaderFromMediaSource(
     IMFMediaSource mediaSource,
     IMFAttributes attributes,
     out IMFSourceReader sourceReader)
 {
     int result = ExternMFCreateSourceReaderFromMediaSource(mediaSource, attributes, out sourceReader);
     if (result < 0)
     {
         throw new COMException("Exception from HRESULT: 0x" + result.ToString("X", System.Globalization.NumberFormatInfo.InvariantInfo) + " (MFCreateTranscodeTopology failed)", result);
     }
 }
예제 #36
0
 /// <summary>
 /// Cleans up after finishing with this reader
 /// </summary>
 /// <param name="disposing">true if called from Dispose</param>
 protected override void Dispose(bool disposing)
 {
     if (pReader != null)
     {
         Marshal.ReleaseComObject(pReader);
         pReader = null;
     }
     base.Dispose(disposing);
 }
예제 #37
0
        /// <summary>
        /// Reads from this wave stream
        /// </summary>
        /// <param name="buffer">Buffer to read into</param>
        /// <param name="offset">Offset in buffer</param>
        /// <param name="count">Bytes required</param>
        /// <returns>Number of bytes read; 0 indicates end of stream</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            if (pReader == null)
            {
                pReader = CreateReader(settings);
            }
            if (repositionTo != -1)
            {
                Reposition(repositionTo);
            }

            int bytesWritten = 0;
            // read in any leftovers from last time
            if (decoderOutputCount > 0)
            {
                bytesWritten += ReadFromDecoderBuffer(buffer, offset, count - bytesWritten);
            }

            while (bytesWritten < count)
            {
                IMFSample pSample;
                MF_SOURCE_READER_FLAG dwFlags;
                ulong timestamp;
                int actualStreamIndex;
                pReader.ReadSample(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, 0, out actualStreamIndex, out dwFlags, out timestamp, out pSample);
                if ((dwFlags & MF_SOURCE_READER_FLAG.MF_SOURCE_READERF_ENDOFSTREAM) != 0)
                {
                    // reached the end of the stream
                    break;
                }
                else if ((dwFlags & MF_SOURCE_READER_FLAG.MF_SOURCE_READERF_CURRENTMEDIATYPECHANGED) != 0)
                {
                    waveFormat = GetCurrentWaveFormat(pReader);
                    OnWaveFormatChanged();
                    // carry on, but user must handle the change of format
                }
                else if (dwFlags != 0)
                {
                    throw new InvalidOperationException(String.Format("MediaFoundationReadError {0}", dwFlags));
                }

                IMFMediaBuffer pBuffer;
                pSample.ConvertToContiguousBuffer(out pBuffer);
                IntPtr pAudioData;
                int cbBuffer;
                int pcbMaxLength;
                pBuffer.Lock(out pAudioData, out pcbMaxLength, out cbBuffer);
                EnsureBuffer(cbBuffer);
                Marshal.Copy(pAudioData, decoderOutputBuffer, 0, cbBuffer);
                decoderOutputOffset = 0;
                decoderOutputCount = cbBuffer;

                bytesWritten += ReadFromDecoderBuffer(buffer, offset + bytesWritten, count - bytesWritten);


                pBuffer.Unlock();
                Marshal.ReleaseComObject(pBuffer);
                Marshal.ReleaseComObject(pSample);
            }
            position += bytesWritten;
            return bytesWritten;
        }
예제 #38
0
 private long GetLength(IMFSourceReader reader)
 {
     PropVariant variant;
     // http://msdn.microsoft.com/en-gb/library/windows/desktop/dd389281%28v=vs.85%29.aspx#getting_file_duration
     int hResult = reader.GetPresentationAttribute(MediaFoundationInterop.MF_SOURCE_READER_MEDIASOURCE,
         MediaFoundationAttributes.MF_PD_DURATION, out variant);
     if (hResult == MediaFoundationErrors.MF_E_ATTRIBUTENOTFOUND)
     {
         // this doesn't support telling us its duration (might be streaming)
         return 0;
     }
     if (hResult != 0)
     {
         Marshal.ThrowExceptionForHR(hResult);
     }
     var lengthInBytes = (((long)variant.Value) * waveFormat.AverageBytesPerSecond) / 10000000L;
     variant.Clear();
     return lengthInBytes;
 }
예제 #39
0
 private static MediaType GetCurrentMediaType(IMFSourceReader reader)
 {
     IMFMediaType mediaType;
     reader.GetCurrentMediaType(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, out mediaType);
     return new MediaType(mediaType);
 }
        private WaveFormat GetCurrentWaveFormat(IMFSourceReader reader)
        {
            IMFMediaType uncompressedMediaType;
            reader.GetCurrentMediaType(MediaFoundationInterop.MF_SOURCE_READER_FIRST_AUDIO_STREAM, out uncompressedMediaType);

            // Two ways to query it, first is to ask for properties (second is to convert into WaveFormatEx using MFCreateWaveFormatExFromMFMediaType)
            var outputMediaType = new MediaType(uncompressedMediaType);
            Guid actualMajorType = outputMediaType.MajorType;
            Debug.Assert(actualMajorType == MediaTypes.MFMediaType_Audio);
            Guid audioSubType = outputMediaType.SubType;
            int channels = outputMediaType.ChannelCount;
            int bits = outputMediaType.BitsPerSample;
            int sampleRate = outputMediaType.SampleRate;

            return audioSubType == AudioSubtypes.MFAudioFormat_PCM
                ? new WaveFormat(sampleRate, bits, channels)
                : WaveFormat.CreateIeeeFloatWaveFormat(sampleRate, channels);
        }