/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Constructor, The '1' indicates there should only be 1 processing thread. /// While you *can* set this higher, Grayscaling doesn't really /// benefit from it. See the TypeConverter for an MFT that does. /// </summary> /// <history> /// 01 Nov 18 Cynic - Ported In /// </history> public MFTTantaGrayscale_Async() : base(1) { DebugMessage("MFTTantaGrayscale_Async Constructor"); TransformImageFunction = null; // build our list of guids of the Media Subtypes // we are prepared to accept m_MediaSubtypes = new Guid[] { FOURCC_NV12.ToMediaSubtype(), FOURCC_YUY2.ToMediaSubtype(), FOURCC_UYVY.ToMediaSubtype() }; }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Called when the input type gets set. We record the basic image /// size and format information here. /// /// Expects the InputType variable to have been set. This will have been /// done in the base class immediately before this routine gets called /// /// An override of the virtual stub in TantaMFTBase_Async. /// </summary> /// <history> /// 01 Nov 18 Cynic - Ported In /// </history> override protected void OnSetInputType() { MFError throwonhr; m_imageWidthInPixels = 0; m_imageHeightInPixels = 0; m_videoFOURCC = new FourCC(0); m_cbImageSize = 0; m_lStrideIfContiguous = 0; TransformImageFunction = null; IMFMediaType pmt = InputType; // type can be null to clear if (pmt != null) { Guid subtype; throwonhr = pmt.GetGUID(MFAttributesClsid.MF_MT_SUBTYPE, out subtype); throwonhr = MFExtern.MFGetAttributeSize(pmt, MFAttributesClsid.MF_MT_FRAME_SIZE, out m_imageWidthInPixels, out m_imageHeightInPixels); m_videoFOURCC = new FourCC(subtype); if (m_videoFOURCC == FOURCC_YUY2) { TransformImageFunction = Update_YUY2; m_lStrideIfContiguous = m_imageWidthInPixels * 2; } else if (m_videoFOURCC == FOURCC_UYVY) { TransformImageFunction = Update_UYVY; m_lStrideIfContiguous = m_imageWidthInPixels * 2; } else if (m_videoFOURCC == FOURCC_NV12) { TransformImageFunction = Update_NV12; m_lStrideIfContiguous = m_imageWidthInPixels; } else { throw new COMException("Unrecognized type", (int)HResult.E_UNEXPECTED); } // Calculate the image size (not including padding) int lImageSize; if (Succeeded(pmt.GetUINT32(MFAttributesClsid.MF_MT_SAMPLE_SIZE, out lImageSize))) { m_cbImageSize = lImageSize; } else { m_cbImageSize = GetImageSize(m_videoFOURCC, m_imageWidthInPixels, m_imageHeightInPixels); } int lStrideIfContiguous; if (Succeeded(pmt.GetUINT32(MFAttributesClsid.MF_MT_DEFAULT_STRIDE, out lStrideIfContiguous))) { m_lStrideIfContiguous = lStrideIfContiguous; } // If the output type isn't set yet, we can pre-populate it, // since output must always exactly equal input. This can // save a (tiny) bit of time in negotiating types. OnSetOutputType(); } else { // Since the input must be set before the output, nulling the // input must also clear the output. Note that nulling the // input is only valid if we are not actively streaming. OutputType = null; } }
/// +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+= /// <summary> /// Called when the input type gets set. We record the basic image /// size and format information here. /// /// Expects the InputType variable to have been set. This will have been /// done in the base class immediately before this routine gets called /// /// An override of the virtual stub in TantaMFTBase_Sync. /// </summary> /// <history> /// 01 Nov 18 Cynic - Ported In /// </history> override protected void OnSetInputType() { int lImageSize; int lStrideIfContiguous; Guid subtype; HResult hr; // init some things m_imageWidthInPixels = 0; m_imageHeightInPixels = 0; m_videoFOURCC = new FourCC(0); m_cbImageSize = 0; m_lStrideIfContiguous = 0; TransformImageFunction = null; // get this now, the type can be null to clear IMFMediaType pmt = InputType; if (pmt == null) { // Since the input must be set before the output, nulling the // input must also clear the output. Note that nulling the // input is only valid if we are not actively streaming. OutputType = null; return; } // get the subtype GUID hr = pmt.GetGUID(MFAttributesClsid.MF_MT_SUBTYPE, out subtype); if (hr != HResult.S_OK) { throw new Exception("OnSetInputType call to get the subtype guid failed. Err=" + hr.ToString()); } // get the image width and height in pixels. These will become // very important later when the time comes to convert to grey scale // Note that changing the size of the image on the screen, by resizing // the EVR control does not change this image size. The EVR will // remove various rows and columns as necssary for display purposes hr = MFExtern.MFGetAttributeSize(pmt, MFAttributesClsid.MF_MT_FRAME_SIZE, out m_imageWidthInPixels, out m_imageHeightInPixels); if (hr != HResult.S_OK) { throw new Exception("OnSetInputType call to get the image size failed failed. Err=" + hr.ToString()); } // create a working FourCC subtype from the Guid. This only works because we can always // figure out the FOURCC code from the subtype Guid - it is the first four hex digits in // reverse order m_videoFOURCC = new FourCC(subtype); // switch based on the supported formats and set our transform function // and other format specific based info if (m_videoFOURCC == FOURCC_YUY2) { TransformImageFunction = TransformImageOfTypeYUY2; m_lStrideIfContiguous = m_imageWidthInPixels * 2; } else if (m_videoFOURCC == FOURCC_UYVY) { TransformImageFunction = TransformImageOfTypeUYVY; m_lStrideIfContiguous = m_imageWidthInPixels * 2; } else if (m_videoFOURCC == FOURCC_NV12) { TransformImageFunction = TransformImageOfTypeNV12; m_lStrideIfContiguous = m_imageWidthInPixels; } else { throw new Exception("OnSetInputType Unrecognized type. Type =" + m_videoFOURCC.ToString()); } // Calculate the image size (not including padding) hr = pmt.GetUINT32(MFAttributesClsid.MF_MT_SAMPLE_SIZE, out lImageSize); if (hr == HResult.S_OK) { // we have an attribute with the image size use that m_cbImageSize = lImageSize; } else { // we calculate the image size from the format m_cbImageSize = GetImageSize(m_videoFOURCC, m_imageWidthInPixels, m_imageHeightInPixels); } // get the default stride. The stride is the number of bytes from one row of pixels in memory // to the next row of pixels in memory. If padding bytes are present, the stride is wider // than the width of the image. We will need this if the frames come in IMFMediaBuffers, // if the frames come in IMF2DBuffers we can get the stride directly from the buffer hr = pmt.GetUINT32(MFAttributesClsid.MF_MT_DEFAULT_STRIDE, out lStrideIfContiguous); if (hr != HResult.S_OK) { throw new Exception("OnSetInputType call to MFAttributesClsid.MF_MT_DEFAULT_STRIDE failed. Err=" + hr.ToString()); } // we have an attribute with the default stride m_lStrideIfContiguous = lStrideIfContiguous; // If the output type isn't set yet, we can pre-populate it, // since output must always exactly equal input. This can // save a (tiny) bit of time in negotiating types. OnSetOutputType(); }