override protected void OnProcessSample(IMFSample pInputSample, bool Discontinuity, int InputMessageNumber) { MFError throwonhr; IMFMediaBuffer pInput; // Set the Discontinuity flag on the sample that's going to OutputSample. HandleDiscontinuity(Discontinuity, pInputSample); // Get the data buffer from the input sample. If the sample has // multiple buffers, you might be able to get (slightly) better // performance processing each buffer in turn rather than forcing // a new, full-sized buffer to get created. throwonhr = pInputSample.ConvertToContiguousBuffer(out pInput); try { // Process it. DoWork(pInput); // Send the modified input sample to the output sample queue. OutputSample(pInputSample, InputMessageNumber); m_FrameCount++; } finally { // If (somewhere) there is .Net code that is holding on to an instance of // the same buffer as pInput, this will yank the RCW out from underneath // it, probably causing it to crash. But if we don't release it, our memory // usage explodes. SafeRelease(pInput); } }
public static byte[] GetDataFromMediaSample(IMFSample sample) { IMFMediaBuffer pMediaBuffer = null; IntPtr pBuffer; int maxLen = 0, curLen = 0; //HResult hr = sample.LockStore(); HResult hr = sample.ConvertToContiguousBuffer(out pMediaBuffer); MFError.ThrowExceptionForHR(hr); try { hr = pMediaBuffer.Lock(out pBuffer, out maxLen, out curLen); MFError.ThrowExceptionForHR(hr); try { byte[] data = new byte[curLen]; Marshal.Copy(pBuffer, data, 0, curLen); return(data); } finally { hr = pMediaBuffer.Unlock(); } } finally { //hr = sample.UnlockStore(); COMBase.SafeRelease(pMediaBuffer); } }
override protected void OnProcessSample(IMFSample pInputSample, bool Discontinuity, int InputMessageNumber) { MFError throwonhr; // Set the Discontinuity flag on the sample that's going to OutputSample. HandleDiscontinuity(Discontinuity, pInputSample); int cb; int cbBytesProcessed = 0; // How much data we processed. int cbInputLength; IntPtr pbInputData = IntPtr.Zero; IMFMediaBuffer pInputBuffer; // Convert to a single contiguous buffer. // NOTE: This does not cause a copy unless there are multiple buffers throwonhr = pInputSample.ConvertToContiguousBuffer(out pInputBuffer); try { // Lock the input buffer. throwonhr = pInputBuffer.Lock(out pbInputData, out cb, out cbInputLength); // Round to the next lowest multiple of nBlockAlign. cbBytesProcessed = cbInputLength - (cbInputLength % m_Alignment); // Process the data. ProcessAudio(pbInputData, pbInputData, cbBytesProcessed / m_Alignment); // Set the data length on the output buffer. throwonhr = pInputBuffer.SetCurrentLength(cbBytesProcessed); long hnsTime = 0; // Ignore failure if the input sample does not have a time stamp. This is // not an error condition. The client may not care about time stamps, and // we don't need them. if (Succeeded(pInputSample.GetSampleTime(out hnsTime))) { long hnsDuration = (cbBytesProcessed / m_AvgBytesPerSec) * UNITS; m_rtTimestamp = hnsTime + hnsDuration; } else { m_rtTimestamp = -1; } OutputSample(pInputSample, InputMessageNumber); } finally { if (pbInputData != IntPtr.Zero) { pInputBuffer.Unlock(); } SafeRelease(pInputBuffer); } }
override protected void OnProcessSample(IMFSample pInputSample, bool Discontinuity, int InputMessageNumber) { MFError throwonhr; IMFMediaBuffer pInput; // While we accept types that *might* be interlaced, if we actually receive // an interlaced sample, reject it. if (m_MightBeInterlaced) { int ix; // Returns a bool: true = interlaced, false = progressive throwonhr = pInputSample.GetUINT32(MFAttributesClsid.MFSampleExtension_Interlaced, out ix); if (ix != 0) { SafeRelease(pInputSample); return; } } // Set the Discontinuity flag on the sample that's going to OutputSample. HandleDiscontinuity(Discontinuity, pInputSample); int i = MFExtern.MFGetAttributeUINT32(Attributes, ClsidRotate, 0); bool IsOdd = (i & 1) == 1; // Does the specified rotation give a different orientation than // the old one? if (IsOdd != m_WasOdd) { // Yes, change the output type. OutputSample(null, InputMessageNumber); m_WasOdd = IsOdd; } // Get the data buffer from the input sample. If the sample has // multiple buffers, you might be able to get (slightly) better // performance processing each buffer in turn rather than forcing // a new, full-sized buffer to get created. throwonhr = pInputSample.ConvertToContiguousBuffer(out pInput); try { // Process it. DoWork(pInput, (RotateFlipType)i); // Send the modified input sample to the output sample queue. OutputSample(pInputSample, InputMessageNumber); } finally { // If (somewhere) there is .Net code that is holding on to an instance of // the same buffer as pInput, this will yank the RCW out from underneath // it, probably causing it to crash. But if we don't release it, our memory // usage explodes. SafeRelease(pInput); } }
//todo: put the process work to background thread to speed up. public HResult ProcessSample(IMFSample videoSample) { HResult hr = HResult.S_OK; MFTOutputStatusFlags mftOutFlags; MFTOutputStreamInfo StreamInfo; if (videoSample == null) { return(hr); } pDecoderTransform.ProcessInput(0, videoSample, 0); pDecoderTransform.GetOutputStatus(out mftOutFlags); pDecoderTransform.GetOutputStreamInfo(0, out StreamInfo); while (true) { IMFMediaBuffer resultBuffer; //reset the cache buffer. MFExtern.MFCreateMemoryBuffer(StreamInfo.cbSize, out resultBuffer); _mftOutSample.RemoveAllBuffers(); _mftOutSample.AddBuffer(resultBuffer); ProcessOutputStatus outputStatus; var mftProcessOutput = pDecoderTransform.ProcessOutput(0, 1, _mftOutBufferContainer, out outputStatus); if (mftProcessOutput == HResult.MF_E_TRANSFORM_NEED_MORE_INPUT) { //continue provice input data. break; } else if (_mftOutBufferContainer[0].dwStatus == MFTOutputDataBufferFlags.Incomplete) { //todo: the decoded data include more than one samples,we need to receive all data items. } else { IMFMediaBuffer buffer; _mftOutSample.ConvertToContiguousBuffer(out buffer); invokeDecodeComplete(buffer, StreamInfo.cbSize); } } return(hr); }
protected override void OnProcessSample(IMFSample pInputSample, bool Discontinuity, int InputMessageNumber) { MFError throwonhr; // While we accept types that *might* be interlaced, if we actually receive // an interlaced sample, reject it. if (m_MightBeInterlaced) { int ix; // Returns a bool: true = interlaced, false = progressive HResult hr = pInputSample.GetUINT32(MFAttributesClsid.MFSampleExtension_Interlaced, out ix); // Can be S_False. if (hr != HResult.S_OK || ix != 0) { throw new COMException("Interlaced", (int)HResult.E_FAIL); } } IMFMediaBuffer pInput = null; IMFMediaBuffer pOutput = null; IMFSample pOutSample = null; // Get the data buffer from the input sample. If the sample has // multiple buffers, you might be able to get (slightly) better // performance processing each buffer in turn rather than forcing // a new, full-sized buffer to get created. throwonhr = pInputSample.ConvertToContiguousBuffer(out pInput); try { // Make a duplicate of the input sample DuplicateSample(pInputSample, out pOutSample); // Set the Discontinuity flag on the sample that's going to OutputSample. HandleDiscontinuity(Discontinuity, pOutSample); throwonhr = pOutSample.ConvertToContiguousBuffer(out pOutput); // Process it. DoWork(pInput, pOutput); // Send the new output sample to the output sample queue. OutputSample(pOutSample, InputMessageNumber); } catch { SafeRelease(pOutSample); throw; } finally { // If (somewhere) there is .Net code that is holding on to an instance of // the same buffer as pInput, this will yank the RCW out from underneath // it, probably causing it to crash. But if we don't release it, our memory // usage explodes. SafeRelease(pInput); SafeRelease(pOutput); SafeRelease(pInputSample); } }
override protected HResult OnProcessOutput(ref MFTOutputDataBuffer pOutputSamples) { HResult hr = HResult.S_OK; MFError throwonhr; // Since we don't specify MFTOutputStreamInfoFlags.ProvidesSamples, this can't be null. if (pOutputSamples.pSample != IntPtr.Zero) { long hnsDuration; long hnsTime; IMFMediaBuffer pInput = null; IMFMediaBuffer pOutput = null; IMFSample pOutSample = null; try { // Get the data buffer from the input sample. If the sample has // multiple buffers, you might be able to get (slightly) better // performance processing each buffer in turn rather than forcing // a new, full-sized buffer to get created. throwonhr = InputSample.ConvertToContiguousBuffer(out pInput); // Turn pointer to interface pOutSample = Marshal.GetUniqueObjectForIUnknown(pOutputSamples.pSample) as IMFSample; // Get the output buffer. throwonhr = pOutSample.ConvertToContiguousBuffer(out pOutput); OnProcessOutput(pInput, pOutput); // Set status flags. pOutputSamples.dwStatus = MFTOutputDataBufferFlags.None; // Copy the duration and time stamp from the input sample, // if present. hr = InputSample.GetSampleDuration(out hnsDuration); if (Succeeded(hr)) { throwonhr = pOutSample.SetSampleDuration(hnsDuration); } hr = InputSample.GetSampleTime(out hnsTime); if (Succeeded(hr)) { throwonhr = pOutSample.SetSampleTime(hnsTime); } } finally { SafeRelease(pInput); SafeRelease(pOutput); SafeRelease(pOutSample); // Release the current input sample so we can get another one. InputSample = null; } } else { return(HResult.E_INVALIDARG); } return(HResult.S_OK); }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// This is the routine that performs the transform. Assumes InputSample is set. /// /// An override of the abstract version in TantaMFTBase_Sync. /// </summary> /// <param name="outputSampleDataStruct">The structure to populate with output data.</param> /// <returns>S_Ok unless error.</returns> /// <history> /// 01 Nov 18 Cynic - Ported In /// </history> protected override HResult OnProcessOutput(ref MFTOutputDataBuffer outputSampleDataStruct) { long hnsDuration; long hnsTime; HResult hr = HResult.S_OK; IMFMediaBuffer inputMediaBuffer = null; IMFMediaBuffer outputMediaBuffer = null; IMFSample outputSample = null; // Since we don't specify MFTOutputStreamInfoFlags.ProvidesSamples, this can't be null. // we expect the caller to have allocated the memory for this if (outputSampleDataStruct.pSample == IntPtr.Zero) { return(HResult.E_INVALIDARG); } try { // Get the data buffer from the input sample. If the sample contains more than one buffer, // this method copies the data from the original buffers into a new buffer, and replaces // the original buffer list with the new buffer. The new buffer is returned in the inputMediaBuffer parameter. // If the sample contains a single buffer, this method returns a pointer to the original buffer. // In typical use, most samples do not contain multiple buffers. hr = InputSample.ConvertToContiguousBuffer(out inputMediaBuffer); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to InputSample.ConvertToContiguousBuffer failed. Err=" + hr.ToString()); } // Turn pointer into an interface. The GetUniqueObjectForIUnknown method ensures that we // receive a unique Runtime Callable Wrapper, because it does not match an IUnknown pointer // to an existing object. Use this method when you have to create a unique RCW that is not // impacted by other code that calls the ReleaseComObject method. outputSample = Marshal.GetUniqueObjectForIUnknown(outputSampleDataStruct.pSample) as IMFSample; if (outputSample == null) { throw new Exception("OnProcessOutput call to GetUniqueObjectForIUnknown failed. outputSample == null"); } // Now get the output buffer. A media sample contains zero or more buffers. Each buffer manages a block of // memory, and is represented by the IMFMediaBuffer interface. A sample can have multiple buffers. // The buffers are kept in an ordered list and accessed by index value. This call gets us a single // pointer to a single contigous buffer which is much more useful. hr = outputSample.ConvertToContiguousBuffer(out outputMediaBuffer); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to InputSample.ConvertToContiguousBuffer failed. Err=" + hr.ToString()); } // now that we have an input and output buffer, do the work to convert them to grayscale. // Writing into outputMediaBuffer will write to the approprate location in the outputSample // since we took care to Marshal it that way ConvertMediaBufferToGrayscale(inputMediaBuffer, outputMediaBuffer); // Set status flags. outputSampleDataStruct.dwStatus = MFTOutputDataBufferFlags.None; // Copy the duration from the input sample, if present. The // Media Session needs these in order to keep everything sync'ed hr = InputSample.GetSampleDuration(out hnsDuration); if (hr == HResult.S_OK) { hr = outputSample.SetSampleDuration(hnsDuration); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to OutSample.SetSampleDuration failed. Err=" + hr.ToString()); } } // Copy the time stamp from the input sample, if present. hr = InputSample.GetSampleTime(out hnsTime); if (hr == HResult.S_OK) { hr = outputSample.SetSampleTime(hnsTime); if (hr != HResult.S_OK) { throw new Exception("OnProcessOutput call to OutSample.SetSampleTime failed. Err=" + hr.ToString()); } } } finally { // clean up SafeRelease(inputMediaBuffer); SafeRelease(outputMediaBuffer); SafeRelease(outputSample); // Release the current input sample so we can get another one. // the act of setting it to null releases it because the property // is coded that way InputSample = null; } return(HResult.S_OK); }