// Formats protected void CreateOptimalVideoType(IMFMediaType pProposed, out IMFMediaType ppOptimal) { try { MFRect rcOutput; MFVideoArea displayArea; IMFMediaType pOptimalType = null; // Create the helper object to manipulate the optimal type. VideoTypeBuilder pmtOptimal = new VideoTypeBuilder(); // Clone the proposed type. pmtOptimal.CopyFrom(pProposed); // Modify the new type. // For purposes of this SDK sample, we assume // 1) The monitor's pixels are square. // 2) The presenter always preserves the pixel aspect ratio. // Set the pixel aspect ratio (PAR) to 1:1 (see assumption #1, above) pmtOptimal.SetPixelAspectRatio(1, 1); // Get the output rectangle. rcOutput = m_pD3DPresentEngine.GetDestinationRect(); if (rcOutput.IsEmpty()) { // Calculate the output rectangle based on the media type. CalculateOutputRectangle(pProposed, out rcOutput); } // Set the extended color information: Use BT.709 pmtOptimal.SetYUVMatrix(MFVideoTransferMatrix.BT709); pmtOptimal.SetTransferFunction(MFVideoTransferFunction.Func709); pmtOptimal.SetVideoPrimaries(MFVideoPrimaries.BT709); pmtOptimal.SetVideoNominalRange(MFNominalRange.MFNominalRange_16_235); pmtOptimal.SetVideoLighting(MFVideoLighting.Dim); // Set the target rect dimensions. pmtOptimal.SetFrameDimensions(rcOutput.right, rcOutput.bottom); // Set the geometric aperture, and disable pan/scan. displayArea = new MFVideoArea(0, 0, rcOutput.right, rcOutput.bottom); pmtOptimal.SetPanScanEnabled(false); pmtOptimal.SetGeometricAperture(displayArea); // Set the pan/scan aperture and the minimum display aperture. We don't care // about them per se, but the mixer will reject the type if these exceed the // frame dimentions. pmtOptimal.SetPanScanAperture(displayArea); pmtOptimal.SetMinDisplayAperture(displayArea); // Return the pointer to the caller. pmtOptimal.GetMediaType(out pOptimalType); pmtOptimal.Dispose(); ppOptimal = pOptimalType; } finally { //SafeRelease(pOptimalType); //SafeRelease(pmtOptimal); } }
protected void IsMediaTypeSupported(IMFMediaType pMediaType) { VideoTypeBuilder pProposed = null; bool bCompressed = false; MFVideoInterlaceMode InterlaceMode = MFVideoInterlaceMode.Unknown; MFVideoArea VideoCropArea; int width = 0, height = 0; try { // Helper object for reading the proposed type. pProposed = new VideoTypeBuilder(pMediaType); // Reject compressed media types. pProposed.IsCompressedFormat(out bCompressed); if (bCompressed) { throw new COMException("Compressed formats not supported", MFError.MF_E_INVALIDMEDIATYPE); } // Validate the format. int i; pProposed.GetFourCC(out i); // The D3DPresentEngine checks whether the format can be used as // the back-buffer format for the swap chains. m_pD3DPresentEngine.CheckFormat(i); // Reject interlaced formats. pProposed.GetInterlaceMode(out InterlaceMode); if (InterlaceMode != MFVideoInterlaceMode.Progressive) { throw new COMException("Interlaced formats not supported", MFError.MF_E_INVALIDMEDIATYPE); } pProposed.GetFrameDimensions(out width, out height); // Validate the various apertures (cropping regions) against the frame size. // Any of these apertures may be unspecified in the media type, in which case // we ignore it. We just want to reject invalid apertures. try { pProposed.GetPanScanAperture(out VideoCropArea); ValidateVideoArea(VideoCropArea, width, height); } catch { } try { pProposed.GetGeometricAperture(out VideoCropArea); ValidateVideoArea(VideoCropArea, width, height); } catch { } try { pProposed.GetMinDisplayAperture(out VideoCropArea); ValidateVideoArea(VideoCropArea, width, height); } catch { } } finally { pProposed.Dispose(); //SafeRelease(pMediaType); } }
protected void CalculateOutputRectangle(IMFMediaType pProposed, out MFRect prcOutput) { int srcWidth = 0, srcHeight = 0; MFRatio inputPAR; MFRatio outputPAR; MFRect rcOutput = new MFRect(); MFVideoArea displayArea; VideoTypeBuilder pmtProposed = null; // Helper object to read the media type. pmtProposed = new VideoTypeBuilder(pProposed); // Get the source's frame dimensions. pmtProposed.GetFrameDimensions(out srcWidth, out srcHeight); // Get the source's display area. pmtProposed.GetVideoDisplayArea(out displayArea); // Calculate the x,y offsets of the display area. int offsetX = (int)displayArea.OffsetX.GetOffset(); int offsetY = (int)displayArea.OffsetY.GetOffset(); // Use the display area if valid. Otherwise, use the entire frame. if (displayArea.Area.Width != 0 && displayArea.Area.Height != 0 && offsetX + displayArea.Area.Width <= (srcWidth) && offsetY + displayArea.Area.Height <= (srcHeight)) { rcOutput.left = offsetX; rcOutput.right = offsetX + displayArea.Area.Width; rcOutput.top = offsetY; rcOutput.bottom = offsetY + displayArea.Area.Height; } else { rcOutput.left = 0; rcOutput.top = 0; rcOutput.right = srcWidth; rcOutput.bottom = srcHeight; } // rcOutput is now either a sub-rectangle of the video frame, or the entire frame. // If the pixel aspect ratio of the proposed media type is different from the monitor's, // letterbox the video. We stretch the image rather than shrink it. inputPAR = pmtProposed.GetPixelAspectRatio(); // Defaults to 1:1 outputPAR.Denominator = outputPAR.Numerator = 1; // This is an assumption of the sample. // Adjust to get the correct picture aspect ratio. prcOutput = CorrectAspectRatio(rcOutput, inputPAR, outputPAR); pmtProposed.Dispose(); }