예제 #1
0
        // Token: 0x06000945 RID: 2373 RVA: 0x0001B0A0 File Offset: 0x000192A0
        private long ConvertOneBuffer(IMFSinkWriter writer, int streamIndex, IWaveProvider inputProvider, long position, byte[] managedBuffer)
        {
            long           num            = 0L;
            IMFMediaBuffer imfmediaBuffer = MediaFoundationApi.CreateMemoryBuffer(managedBuffer.Length);
            int            count;

            imfmediaBuffer.GetMaxLength(out count);
            IMFSample imfsample = MediaFoundationApi.CreateSample();

            imfsample.AddBuffer(imfmediaBuffer);
            IntPtr destination;
            int    num2;

            imfmediaBuffer.Lock(out destination, out count, out num2);
            int num3 = inputProvider.Read(managedBuffer, 0, count);

            if (num3 > 0)
            {
                num = MediaFoundationEncoder.BytesToNsPosition(num3, inputProvider.WaveFormat);
                Marshal.Copy(managedBuffer, 0, destination, num3);
                imfmediaBuffer.SetCurrentLength(num3);
                imfmediaBuffer.Unlock();
                imfsample.SetSampleTime(position);
                imfsample.SetSampleDuration(num);
                writer.WriteSample(streamIndex, imfsample);
            }
            else
            {
                imfmediaBuffer.Unlock();
            }
            Marshal.ReleaseComObject(imfsample);
            Marshal.ReleaseComObject(imfmediaBuffer);
            return(num);
        }
예제 #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
 public CCapture(IntPtr hVideo, IntPtr hEvent)
     : base(hVideo, hEvent)
 {
     PWriter      = null;
     BFirstSample = false;
     LlBaseTime   = 0;
 }
예제 #4
0
 public CCapture(IntPtr hVideo, IntPtr hEvent)
     : base(hVideo, hEvent)
 {
     PWriter = null;
     BFirstSample = false;
     LlBaseTime = 0;
 }
예제 #5
0
        private void PerformEncode(IMFSinkWriter writer, int streamIndex, MediaFoundationReader inputProvider, int first, int last)
        {
            int maxLength     = inputProvider.WaveFormat.AverageBytesPerSecond * 4;
            var managedBuffer = new byte[maxLength];

            writer.BeginWriting();

            first++;
            bool   flag     = true;
            double time     = Math.Round(inputProvider.TotalTime.TotalSeconds - last, 0);
            long   position = 0;
            long   duration;

            do
            {
                duration  = ConvertOneBuffer(writer, streamIndex, inputProvider, position, managedBuffer, first, ref flag);
                position += duration;

                int percent = (int)(inputProvider.CurrentTime.TotalSeconds / inputProvider.TotalTime.TotalSeconds * 100);
                //LoadProgressChanged.Raise(this, new LoadProgressChangedEventArgs(percent, inputProvider.CurrentTime, inputProvider.TotalTime));
                OnLoadProgressChanged(percent, inputProvider.CurrentTime, inputProvider.TotalTime);

                if (inputProvider.CurrentTime.TotalSeconds >= time)
                {
                    duration = 0;
                }
            } while (duration > 0);

            writer.DoFinalize();
        }
예제 #6
0
        HResult ConfigureEncoder(
            EncodingParameters eparams,
            IMFMediaType pType,
            IMFSinkWriter pWriter,
            out int pdwStreamIndex
            )
        {
            HResult hr = HResult.S_OK;

            IMFMediaType pType2 = null;

            hr = MFExtern.MFCreateMediaType(out pType2);

            if (Succeeded(hr))
            {
                hr = pType2.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Video);
            }

            if (Succeeded(hr))
            {
                hr = pType2.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, eparams.subtype);
            }

            if (Succeeded(hr))
            {
                hr = pType2.SetUINT32(MFAttributesClsid.MF_MT_AVG_BITRATE, eparams.bitrate);
            }

            if (Succeeded(hr))
            {
                hr = CopyAttribute(pType, pType2, MFAttributesClsid.MF_MT_FRAME_SIZE);
            }

            if (Succeeded(hr))
            {
                hr = CopyAttribute(pType, pType2, MFAttributesClsid.MF_MT_FRAME_RATE);
            }

            if (Succeeded(hr))
            {
                hr = CopyAttribute(pType, pType2, MFAttributesClsid.MF_MT_PIXEL_ASPECT_RATIO);
            }

            if (Succeeded(hr))
            {
                hr = CopyAttribute(pType, pType2, MFAttributesClsid.MF_MT_INTERLACE_MODE);
            }

            pdwStreamIndex = 0;
            if (Succeeded(hr))
            {
                hr = pWriter.AddStream(pType2, out pdwStreamIndex);
            }

            SafeRelease(pType2);

            return(hr);
        }
 private void ClearAll()
 {
     this.streamsInfo.Clear();
     this.sourceFilename  = string.Empty;
     this.targetFilename  = string.Empty;
     this.sourceReader    = null;
     this.sinkWriter      = null;
     this.selectedStreams = 0;
 }
        /// <summary>
        /// Indicates a gap in an input streamIndex.
        /// </summary>
        /// <param name="sinkWriter">A valid IMFSinkWriter instance.</param>
        /// <param name="streamIndex">The zero-based index of the streamIndex.</param>
        /// <param name="timestamp">The position in the streamIndex where the gap in the data occurs, relative to the start of the streamIndex.</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 SendStreamTick(this IMFSinkWriter sinkWriter, int streamIndex, TimeSpan timestamp)
        {
            if (sinkWriter == null)
            {
                throw new ArgumentNullException("sinkWriter");
            }

            return(sinkWriter.SendStreamTick(streamIndex, timestamp.Ticks));
        }
예제 #9
0
 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;
 }
예제 #10
0
 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;
 }
예제 #11
0
        private long ConvertOneBuffer(IMFSinkWriter writer, int streamIndex, IWaveProvider inputProvider, long position, byte[] managedBuffer, int seconds, ref bool flag)
        {
            long           durationConverted = 0;
            int            maxLength;
            IMFMediaBuffer buffer = MediaFoundationApi.CreateMemoryBuffer(managedBuffer.Length);

            buffer.GetMaxLength(out maxLength);

            IMFSample sample = MediaFoundationApi.CreateSample();

            sample.AddBuffer(buffer);

            IntPtr ptr;
            int    currentLength;

            buffer.Lock(out ptr, out maxLength, out currentLength);
            int oneLength = inputProvider.WaveFormat.AverageBytesPerSecond;
            int read      = 0;

            if (flag)
            {
                for (int i = 0; i < seconds; i++)
                {
                    read = inputProvider.Read(managedBuffer, 0, oneLength);
                }
                flag = false;
            }
            else
            {
                read = inputProvider.Read(managedBuffer, 0, oneLength);
            }

            if (read > 0)
            {
                durationConverted = BytesToNsPosition(read, inputProvider.WaveFormat);
                Marshal.Copy(managedBuffer, 0, ptr, read);
                buffer.SetCurrentLength(read);
                buffer.Unlock();
                sample.SetSampleTime(position);
                sample.SetSampleDuration(durationConverted);
                writer.WriteSample(streamIndex, sample);
                //writer.Flush(streamIndex);
            }
            else
            {
                buffer.Unlock();
            }

            Marshal.ReleaseComObject(sample);
            Marshal.ReleaseComObject(buffer);
            return(durationConverted);
        }
예제 #12
0
        public static ComObject <T> GetServiceForStream <T>(this IMFSinkWriter input, uint streamIndex, Guid serviceId, Guid interfaceId)
        {
            if (input == null)
            {
                throw new ArgumentNullException(nameof(input));
            }

            if (input.GetServiceForStream(streamIndex, serviceId, interfaceId, out var ppv).IsError)
            {
                return(null);
            }

            return(new ComObject <T>((T)ppv));
        }
예제 #13
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()
        {
            // 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;
        }
예제 #14
0
파일: frmMain.cs 프로젝트: yudigh/Tanta
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Close the Media sink
        /// </summary>
        /// <param name="writerObject">the media source object</param>
        /// <history>
        ///    01 Nov 18  Cynic - Started
        /// </history>
        private void CloseSinkWriter(IMFSinkWriter writerObject)
        {
            // End any active captures
            if (writerObject == null)
            {
                LogMessage("CloseSinkWriter rwriterObject == null");
                return;
            }

            // close and release
            HResult hr = writerObject.Finalize_();

            Marshal.ReleaseComObject(writerObject);
        }
예제 #15
0
 private void PerformEncode(IMFSinkWriter writer, int streamIndex, IWaveProvider inputProvider)
 {
     int num = inputProvider.WaveFormat.AverageBytesPerSecond * 4;
     byte[] managedBuffer = new byte[num];
     writer.BeginWriting();
     long num2 = 0L;
     long num3;
     do
     {
         num3 = this.ConvertOneBuffer(writer, streamIndex, inputProvider, num2, managedBuffer);
         num2 += num3;
     }
     while (num3 > 0L);
     writer.DoFinalize();
 }
예제 #16
0
        public int StopCapture()
        {
            var hr = S_Ok;

            lock (LockSync)
            {
                if (PWriter != null)
                {
                    hr = PWriter.Finalize_();
                    SafeRelease(PWriter);
                    PWriter = null;
                }
            }

            return(hr);
        }
예제 #17
0
파일: frmMain.cs 프로젝트: yudigh/Tanta
        /// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
        /// <summary>
        /// Opens the Sink Writer object
        /// </summary>
        /// <param name="outputFileName">the filename we write out to</param>
        /// <returns>an IMFSinkWriter object or null for fail</returns>
        /// <history>
        ///    01 Nov 18  Cynic - Started
        /// </history>
        private IMFSinkWriter OpenSinkWriter(string outputFileName)
        {
            HResult       hr;
            IMFSinkWriter workingWriter = null;

            if ((outputFileName == null) || (outputFileName.Length == 0))
            {
                // we failed
                throw new Exception("OpenSinkWriter: Invalid filename specified");
            }

            try
            {
                // Create the sink writer. This takes the URL of an output file or a pointer to a byte stream and
                // creates the media sink internally. You could also use the more round-about
                // MFCreateSinkWriterFromMediaSink takes a pointer to a media sink that has already been created by
                // the application. If you are using one of the built-in media sinks, the MFCreateSinkWriterFromURL
                // function is preferable, because the caller does not need to configure the media sink.
                hr = MFExtern.MFCreateSinkWriterFromURL(outputFileName, null, null, out workingWriter);
                if (hr != HResult.S_OK)
                {
                    // we failed
                    throw new Exception("OpenSinkWriter: Failed on call to MFCreateSinkWriterFromURL, retVal=" + hr.ToString());
                }
                if (workingWriter == null)
                {
                    // we failed
                    throw new Exception("OpenSinkWriter: Failed to create Sink Writer, Nothing will work.");
                }
            }
            catch (Exception ex)
            {
                // note this clean up is in the Catch block not the finally block.
                // if there are no errors we return it to the caller. The caller
                // is expected to clean up after itself
                if (workingWriter != null)
                {
                    // clean up. Nothing else has this yet
                    Marshal.ReleaseComObject(workingWriter);
                    workingWriter = null;
                }
                workingWriter = null;
                throw ex;
            }

            return(workingWriter);
        }
예제 #18
0
        // Constructor
        public CPreview(IntPtr hVideo, IntPtr hEvent)
        {
            m_pReader = null;
            m_hwndEvent = hEvent;
            m_pwszSymbolicLink = null;
            m_draw = new DrawDevice();

            m_pWriter = null;
            m_bFirstSample = false;
            m_llBaseTime = 0;

            int hr = MFExtern.MFStartup(0x20070, MFStartup.Lite);
            MFError.ThrowExceptionForHR(hr);

            hr = m_draw.CreateDevice(hVideo);
            MFError.ThrowExceptionForHR(hr);
        }
예제 #19
0
        // Constructor
        public CPreview(IntPtr hVideo, IntPtr hEvent)
        {
            m_pReader          = null;
            m_hwndEvent        = hEvent;
            m_pwszSymbolicLink = null;
            m_draw             = new DrawDevice();

            m_pWriter      = null;
            m_bFirstSample = false;
            m_llBaseTime   = 0;

            HResult hr = MFExtern.MFStartup(0x20070, MFStartup.Lite);

            MFError.ThrowExceptionForHR(hr);

            hr = m_draw.CreateDevice(hVideo);
            MFError.ThrowExceptionForHR(hr);
        }
예제 #20
0
        private void PerformEncode(IMFSinkWriter writer, int streamIndex, IWaveProvider inputProvider)
        {
            int maxLength     = inputProvider.WaveFormat.AverageBytesPerSecond * 4;
            var managedBuffer = new byte[maxLength];

            writer.BeginWriting();

            long position = 0;
            long duration = 0;

            do
            {
                duration  = ConvertOneBuffer(writer, streamIndex, inputProvider, position, managedBuffer);
                position += duration;
            } while (duration > 0);

            writer.DoFinalize();
        }
예제 #21
0
        //-------------------------------------------------------------------
        //  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);
        }
예제 #22
0
 /// <summary>
 ///  stops the process of recording. finalizes and then releases the sink writer
 /// </summary>
 /// <returns>z success, nz fail</returns>
 public int StopRecording()
 {
     LogMessage("StopRecording called");
     // End any active captures
     if (workingSinkWriter != null)
     {
         lock (sinkWriterLockObject)
         {
             // close and release
             workingSinkWriter.Finalize_();
             Marshal.ReleaseComObject(workingSinkWriter);
             workingSinkWriter = null;
         }
     }
     // reset these
     sinkWriterVideoStreamId = -1;
     isFirstSample           = true;
     firstSampleBaseTime     = 0;
     wantTimebaseRebase      = false;
     return(0);
 }
예제 #23
0
 public void Encode(string outputFile, IWaveProvider inputProvider)
 {
     if (inputProvider.WaveFormat.Encoding != WaveFormatEncoding.Pcm && inputProvider.WaveFormat.Encoding != WaveFormatEncoding.IeeeFloat)
     {
         throw new ArgumentException("Encode input format must be PCM or IEEE float");
     }
     MediaType mediaType = new MediaType(inputProvider.WaveFormat);
     IMFSinkWriter imfsinkWriter = MediaFoundationEncoder.CreateSinkWriter(outputFile);
     try
     {
         int num;
         imfsinkWriter.AddStream(this.outputMediaType.MediaFoundationObject, out num);
         imfsinkWriter.SetInputMediaType(num, mediaType.MediaFoundationObject, null);
         this.PerformEncode(imfsinkWriter, num, inputProvider);
     }
     finally
     {
         Marshal.ReleaseComObject(imfsinkWriter);
         Marshal.ReleaseComObject(mediaType.MediaFoundationObject);
     }
 }
        private void CreateReaderAndWriter()
        {
            object        sourceReaderObject = null;
            object        sinkWriterObject   = null;
            IMFAttributes attributes         = null;

            // Create the class factory
            IMFReadWriteClassFactory factory = (IMFReadWriteClassFactory)(new MFReadWriteClassFactory());

            // Create the attributes
            MFHelper.MFCreateAttributes(out attributes, 1);
            attributes.SetUINT32(new Guid(Consts.MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS), 1);

            // Use the factory to create the Source Reader
            factory.CreateInstanceFromURL(new Guid(CLSID.MFSourceReader), this.sourceFilename, attributes, new Guid(IID.IMFSourceReader), out sourceReaderObject);
            this.sourceReader = (IMFSourceReader)sourceReaderObject;

            // Use the factory to create the Sink Writer
            factory.CreateInstanceFromURL(new Guid(CLSID.MFSinkWriter), this.targetFilename, attributes, new Guid(IID.IMFSinkWriter), out sinkWriterObject);
            this.sinkWriter = (IMFSinkWriter)sinkWriterObject;
        }
        /// <summary>
        /// Queries the underlying media sink or encoder for an interface.
        /// </summary>
        /// <typeparam name="T">The COM interface being requested.</typeparam>
        /// <param name="sinkWriter">A valid IMFSinkWriter instance.</param>
        /// <param name="streamIndex">The zero-based index of a streamIndex to query or -1 to query the media sink itself.</param>
        /// <param name="guidService">A service identifier GUID.</param>
        /// <param name="service">Receives an instance of the requested 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 GetServiceForStream <T>(this IMFSinkWriter sinkWriter, int streamIndex, Guid guidService, out T service) where T : class
        {
            if (sinkWriter == null)
            {
                throw new ArgumentNullException("sinkWriter");
            }

            Type typeOfT = typeof(T);

            if (!typeOfT.IsInterface)
            {
                throw new ArgumentOutOfRangeException("T", "T must be a COM visible interface.");
            }

            object tmp;

            HResult hr = sinkWriter.GetServiceForStream(streamIndex, guidService, typeOfT.GUID, out tmp);

            service = hr.Succeeded() ? tmp as T : null;

            return(hr);
        }
예제 #26
0
        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);
        }
예제 #27
0
        private static void WriteAudioFrame(long frameDuration, IMFSinkWriter writer, int audioStreamIndex, long rtStart, byte[] audioFrameBuffer)
        {
            Marshal.ThrowExceptionForHR((int)MFExtern.MFCreateSample(out IMFSample sample));

            try
            {
                Marshal.ThrowExceptionForHR((int)MFExtern.MFCreateMemoryBuffer(audioFrameBuffer.Length, out IMFMediaBuffer buffer));

                try
                {
                    Marshal.ThrowExceptionForHR((int)buffer.Lock(out IntPtr pData, out int maxLength, out int currentLength));

                    try
                    {
                        Marshal.Copy(audioFrameBuffer, 0, pData, audioFrameBuffer.Length);
                    }
                    finally
                    {
                        Marshal.ThrowExceptionForHR((int)buffer.Unlock());
                    }

                    Marshal.ThrowExceptionForHR((int)buffer.SetCurrentLength(audioFrameBuffer.Length));
                    Marshal.ThrowExceptionForHR((int)sample.AddBuffer(buffer));
                }
                finally
                {
                    Marshal.ReleaseComObject(buffer);
                }

                Marshal.ThrowExceptionForHR((int)sample.SetSampleTime(rtStart));
                Marshal.ThrowExceptionForHR((int)sample.SetSampleDuration(frameDuration));
                Marshal.ThrowExceptionForHR((int)writer.WriteSample(audioStreamIndex, sample));
            }
            finally
            {
                Marshal.ReleaseComObject(sample);
            }
        }
예제 #28
0
 public static extern HRESULT MFCreateSinkWriterFromMediaSink(IMFMediaSink pMediaSink, IMFAttributes pAttributes, out IMFSinkWriter ppSinkWriter);
예제 #29
0
 public static extern void MFCreateSinkWriterFromURL([In, MarshalAs(UnmanagedType.LPWStr)] string pwszOutputURL,
                                                     [In] IMFByteStream pByteStream, [In] IMFAttributes pAttributes, [Out] out IMFSinkWriter ppSinkWriter);
예제 #30
0
        //-------------------------------------------------------------------
        //  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;
        }
예제 #31
0
        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;
        }
예제 #32
0
        int ConfigureEncoder(
            IMFMediaType pType,
            IMFSinkWriter pWriter,
            out int pdwStreamIndex
            )
        {
            int hr = S_Ok;

            IMFMediaType pType2 = null;

            hr = MFExtern.MFCreateMediaType(out pType2);

            if (Succeeded(hr))
            {
                hr = pType2.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Video);
            }

            if (Succeeded(hr))
            {
                hr = pType2.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, MEDIATYPE);
            }

            if (Succeeded(hr))
            {
                hr = pType2.SetUINT32(MFAttributesClsid.MF_MT_AVG_BITRATE, TARGET_BIT_RATE);
            }

            if (Succeeded(hr))
            {
                hr = CopyAttribute(pType, pType2, MFAttributesClsid.MF_MT_FRAME_SIZE);
            }

            if (Succeeded(hr))
            {
                hr = CopyAttribute(pType, pType2, MFAttributesClsid.MF_MT_FRAME_RATE);
            }

            if (Succeeded(hr))
            {
                hr = CopyAttribute(pType, pType2, MFAttributesClsid.MF_MT_PIXEL_ASPECT_RATIO);
            }

            if (Succeeded(hr))
            {
                hr = CopyAttribute(pType, pType2, MFAttributesClsid.MF_MT_INTERLACE_MODE);
            }

            pdwStreamIndex = 0;
            if (Succeeded(hr))
            {
                hr = pWriter.AddStream(pType2, out pdwStreamIndex);
            }

            SafeRelease(pType2);

            return hr;
        }
        private void PerformEncode(IMFSinkWriter writer, int streamIndex, IWaveProvider inputProvider)
        {
            int maxLength = inputProvider.WaveFormat.AverageBytesPerSecond * 4;
            var managedBuffer = new byte[maxLength];

            writer.BeginWriting();

            long position = 0;
            long duration = 0;
            do
            {
                duration = ConvertOneBuffer(writer, streamIndex, inputProvider, position, managedBuffer);
                position += duration;
            } while (duration > 0);

            writer.DoFinalize();
        }
        private long ConvertOneBuffer(IMFSinkWriter writer, int streamIndex, IWaveProvider inputProvider, long position, byte[] managedBuffer)
        {
            long durationConverted = 0;
            int maxLength;
            IMFMediaBuffer buffer = MediaFoundationApi.CreateMemoryBuffer(managedBuffer.Length);
            buffer.GetMaxLength(out maxLength);

            IMFSample sample = MediaFoundationApi.CreateSample();
            sample.AddBuffer(buffer);

            IntPtr ptr;
            int currentLength;
            buffer.Lock(out ptr, out maxLength, out currentLength);
            int read = inputProvider.Read(managedBuffer, 0, maxLength);
            if (read > 0)
            {
                durationConverted = BytesToNsPosition(read, inputProvider.WaveFormat);
                Marshal.Copy(managedBuffer, 0, ptr, read);
                buffer.SetCurrentLength(read);
                buffer.Unlock();
                sample.SetSampleTime(position);
                sample.SetSampleDuration(durationConverted);
                writer.WriteSample(streamIndex, sample);
                //writer.Flush(streamIndex);
            }
            else
            {
                buffer.Unlock();
            }

            Marshal.ReleaseComObject(sample);
            Marshal.ReleaseComObject(buffer);
            return durationConverted;
        }
예제 #35
0
 public static extern HRESULT MFCreateSinkWriterFromURL([MarshalAs(UnmanagedType.LPWStr)] string pwszOutputURL, IMFByteStream pByteStream, IMFAttributes pAttributes, out IMFSinkWriter ppSinkWriter);
예제 #36
0
 public static ComObject <T> GetServiceForStream <T>(this IMFSinkWriter input, uint streamIndex) => GetServiceForStream <T>(input, streamIndex, Guid.Empty, typeof(T).GUID);
예제 #37
0
        public int StopCapture()
        {
            var hr = S_Ok;

            lock (LockSync)
            {
                if (PWriter != null)
                {
                    hr = PWriter.Finalize_();
                    SafeRelease(PWriter);
                    PWriter = null;
                }
            }

            return hr;
        }
예제 #38
0
        /// <summary>
        /// Opens the Sink Writer object
        /// </summary>
        /// <param name="outputFileName">the filename we write out to</param>
        /// <param name="wantDisableThrottling">if true we set a flag that disabled throttling</param>
        /// <returns>an IMFSinkWriter object or null for fail</returns>
        private IMFSinkWriter OpenSinkWriter(string outputFileName, bool wantDisableThrottling)
        {
            HResult       hr;
            IMFSinkWriter workingWriter      = null;
            IMFAttributes attributeContainer = null;

            if ((outputFileName == null) || (outputFileName.Length == 0))
            {
                // we failed
                throw new Exception("OpenSinkWriter: Invalid filename specified");
            }
            try
            {
                if (wantDisableThrottling == true)
                {
                    // Initialize an attribute store. We will use this to
                    // specify the enumeration parameters.
                    hr = MFExtern.MFCreateAttributes(out attributeContainer, 1);
                    if (hr != HResult.S_OK)
                    {
                        // we failed
                        throw new Exception("OpenSinkWriter: failed on call to MFCreateAttributes, retVal=" + hr.ToString());
                    }
                    if (attributeContainer == null)
                    {
                        // we failed
                        throw new Exception("OpenSinkWriter: attributeContainer == MFAttributesClsid.null");
                    }
                    // setup the attribute container
                    hr = attributeContainer.SetUINT32(MFAttributesClsid.MF_SINK_WRITER_DISABLE_THROTTLING, 1);
                    if (hr != HResult.S_OK)
                    {
                        // we failed
                        throw new Exception("OpenSinkWriter: failed setting up the attributes, retVal=" + hr.ToString());
                    }
                }
                try
                {
                    // Create the sink writer. This takes the URL of an output file or a pointer to a byte stream and
                    // creates the media sink internally. You could also use the more round-about
                    // MFCreateSinkWriterFromMediaSink takes a pointer to a media sink that has already been created by
                    // the application. If you are using one of the built-in media sinks, the MFCreateSinkWriterFromURL
                    // function is preferable, because the caller does not need to configure the media sink.
                    hr = MFExtern.MFCreateSinkWriterFromURL(outputFileName, null, null, out workingWriter);
                    if (hr != HResult.S_OK)
                    {
                        // we failed
                        throw new Exception("OpenSinkWriter: Failed on call to MFCreateSinkWriterFromURL, retVal=" + hr.ToString());
                    }
                    if (workingWriter == null)
                    {
                        // we failed
                        throw new Exception("OpenSinkWriter: Failed to create Sink Writer, Nothing will work.");
                    }
                }
                catch (Exception ex)
                {
                    // note this clean up is in the Catch block not the finally block.
                    // if there are no errors we return it to the caller. The caller
                    // is expected to clean up after itself
                    if (workingWriter != null)
                    {
                        // clean up. Nothing else has this yet
                        Marshal.ReleaseComObject(workingWriter);
                        workingWriter = null;
                    }
                    workingWriter = null;
                    throw ex;
                }
            }
            finally
            {
                if (attributeContainer != null)
                {
                    // clean up.
                    Marshal.ReleaseComObject(attributeContainer);
                }
            }
            return(workingWriter);
        }
예제 #39
0
        private static int ConfigureEncoder(EncodingParameters eparams, IMFMediaType pType, IMFSinkWriter pWriter,
            out int pdwStreamIndex)
        {
            IMFMediaType pType2;

            var hr = MFExtern.MFCreateMediaType(out pType2);

            if (Succeeded(hr))
            {
                hr = pType2.SetGUID(MFAttributesClsid.MF_MT_MAJOR_TYPE, MFMediaType.Video);
            }

            if (Succeeded(hr))
            {
                hr = pType2.SetGUID(MFAttributesClsid.MF_MT_SUBTYPE, eparams.Subtype);
            }

            if (Succeeded(hr))
            {
                hr = pType2.SetUINT32(MFAttributesClsid.MF_MT_AVG_BITRATE, eparams.Bitrate);
            }

            if (Succeeded(hr))
            {
                hr = CopyAttribute(pType, pType2, MFAttributesClsid.MF_MT_FRAME_SIZE);
            }

            if (Succeeded(hr))
            {
                hr = CopyAttribute(pType, pType2, MFAttributesClsid.MF_MT_FRAME_RATE);
            }

            if (Succeeded(hr))
            {
                hr = CopyAttribute(pType, pType2, MFAttributesClsid.MF_MT_PIXEL_ASPECT_RATIO);
            }

            if (Succeeded(hr))
            {
                hr = CopyAttribute(pType, pType2, MFAttributesClsid.MF_MT_INTERLACE_MODE);
            }

            pdwStreamIndex = 0;
            if (Succeeded(hr))
            {
                hr = pWriter.AddStream(pType2, out pdwStreamIndex);
            }

            SafeRelease(pType2);

            return hr;
        }
예제 #40
0
        private void PerformEncode(IMFSinkWriter writer, int streamIndex, IWaveProvider inputProvider)
        {
            int maxLength = inputProvider.WaveFormat.AverageBytesPerSecond*4;
            var managedBuffer = new byte[maxLength];

            writer.BeginWriting();

            long position = 0;
            long duration = 0;
            do
            {
                duration = ConvertOneBuffer(writer, streamIndex, inputProvider, position, managedBuffer);
                position += duration;
            } while (duration > 0);

            //We are going to check the stats of the writer and ensure no more bytes are queued before we call DoFinalize()
            MF_SINK_WRITER_STATISTICS stats = new MF_SINK_WRITER_STATISTICS();
            stats.cb = Marshal.SizeOf(stats);
            bool finished = false;

            const int sleepMs = 10;
            const int maxTimeInSeconds = 5;
            const int maxTries = (maxTimeInSeconds*1000)/sleepMs;

            var tries = 0;

            try
            {
                while (!finished)
                {
                    writer.GetStatistics(streamIndex, stats);

                    if (tries == maxTries)
                    {
                        var msg =
                            string.Format(
                                "Unable to save the MP3 file. Sink writer still has {0} bytes in the queue after waiting for {1} seconds.",
                                stats.dwByteCountQueued,
                                maxTimeInSeconds);
                        throw new Exception(msg);
                    }

                    if (stats.dwByteCountQueued == 0)
                    {
                        finished = true;
                    }
                    else
                    {
                        //sleeping could be optional, but don't want to hog the CPU
                        System.Threading.Thread.Sleep(sleepMs);
                    }

                    tries++;
                }
            }
            finally
            {
                writer.DoFinalize();
            }
        }
예제 #41
0
        /// <summary>
        ///  Starts the process of recording. creates the sink writer. We do not
        ///  check to see if the filename is viable or already exists. This is
        ///  assumed to have been done before this call.
        /// </summary>
        /// <param name="outputFileName">the output file name</param>
        /// <param name="incomingVideoMediaType">the incoming media type</param>
        /// <param name="wantTimebaseRebaseIn">if true we rebase all incoming sample
        /// times to zero from the point we started recording and send a copy of the
        /// sample to the sink writer instead of the input sample</param>
        /// <returns>z success, nz fail</returns>
        public int StartRecording(string outputFileName, IMFMediaType incomingVideoMediaType, bool wantTimebaseRebaseIn)
        {
            HResult hr;

            LogMessage("MFTSampleGrabber_Sync, StartRecording called");
            // first stop any recordings now
            StopRecording();
            // check the output file name for sanity
            if ((outputFileName == null) || (outputFileName.Length == 0))
            {
                LogMessage("StartRecording (outputFileName==null)|| (outputFileName.Length==0)");
                return(100);
            }
            // check the media type for sanity
            if (incomingVideoMediaType == null)
            {
                LogMessage("StartRecording videoMediaType == null");
                return(150);
            }
            lock (sinkWriterLockObject)
            {
                // create the sink writer
                workingSinkWriter = OpenSinkWriter(outputFileName, true);
                if (workingSinkWriter == null)
                {
                    LogMessage("StartRecording failed to create sink writer");
                    return(200);
                }
                // now configure the SinkWriter. 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 receives as input - 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 IMFMediaType 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. The choice here is somewhat arbitrary but seems to work well.
                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 = WMFUtils.CopyAttributeData(incomingVideoMediaType, 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 = WMFUtils.CopyAttributeData(incomingVideoMediaType, 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 = WMFUtils.CopyAttributeData(incomingVideoMediaType, 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 = WMFUtils.CopyAttributeData(incomingVideoMediaType, 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 for the output Media type. The
                // incomingVideoMediaType 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.
                hr = workingSinkWriter.AddStream(encoderType, out sinkWriterVideoStreamId);
                if (hr != HResult.S_OK)
                {
                    // we failed
                    throw new Exception("StartRecording Failed adding the output stream(v), 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 ColorConverterDMOGUID = 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(
                        ColorConverterDMOGUID,
                        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(sinkWriterVideoStreamId, incomingVideoMediaType, null);
                if (hr != HResult.S_OK)
                {
                    // we failed
                    throw new Exception("StartRecording Failed on calling SetInputMediaType(v) on the writer, retVal=" + hr.ToString());
                }
                // set this flag now
                wantTimebaseRebase = wantTimebaseRebaseIn;
                // 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 above
                hr = workingSinkWriter.BeginWriting();
                if (hr != HResult.S_OK)
                {
                    // we failed
                    throw new Exception("StartRecording Failed on calling BeginWriting on the writer, retVal=" + hr.ToString());
                }
            }
            return(0);
        }