HRESULT WMFVideoMFTManager::ConfigureVideoFrameGeometry() { RefPtr<IMFMediaType> mediaType; HRESULT hr = mDecoder->GetOutputMediaType(mediaType); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); // Verify that the video subtype is what we expect it to be. // When using hardware acceleration/DXVA2 the video format should // be NV12, which is DXVA2's preferred format. For software decoding // we use YV12, as that's easier for us to stick into our rendering // pipeline than NV12. NV12 has interleaved UV samples, whereas YV12 // is a planar format. GUID videoFormat; hr = mediaType->GetGUID(MF_MT_SUBTYPE, &videoFormat); NS_ENSURE_TRUE(videoFormat == MFVideoFormat_NV12 || !mUseHwAccel, E_FAIL); NS_ENSURE_TRUE(videoFormat == MFVideoFormat_YV12 || mUseHwAccel, E_FAIL); nsIntRect pictureRegion; hr = GetPictureRegion(mediaType, pictureRegion); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); UINT32 width = 0, height = 0; hr = MFGetAttributeSize(mediaType, MF_MT_FRAME_SIZE, &width, &height); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); uint32_t aspectNum = 0, aspectDenom = 0; hr = MFGetAttributeRatio(mediaType, MF_MT_PIXEL_ASPECT_RATIO, &aspectNum, &aspectDenom); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); // Calculate and validate the picture region and frame dimensions after // scaling by the pixel aspect ratio. nsIntSize frameSize = nsIntSize(width, height); nsIntSize displaySize = nsIntSize(pictureRegion.width, pictureRegion.height); ScaleDisplayByAspectRatio(displaySize, float(aspectNum) / float(aspectDenom)); if (!IsValidVideoRegion(frameSize, pictureRegion, displaySize)) { // Video track's frame sizes will overflow. Ignore the video track. return E_FAIL; } // Success! Save state. mVideoInfo.mDisplay = displaySize; mVideoInfo.mHasVideo = true; GetDefaultStride(mediaType, &mVideoStride); mVideoWidth = width; mVideoHeight = height; mPictureRegion = pictureRegion; LOG("WMFVideoMFTManager frame geometry frame=(%u,%u) stride=%u picture=(%d, %d, %d, %d) display=(%d,%d) PAR=%d:%d", width, height, mVideoStride, mPictureRegion.x, mPictureRegion.y, mPictureRegion.width, mPictureRegion.height, displaySize.width, displaySize.height, aspectNum, aspectDenom); return S_OK; }
HRESULT WMFVideoMFTManager::ConfigureVideoFrameGeometry() { RefPtr<IMFMediaType> mediaType; HRESULT hr = mDecoder->GetOutputMediaType(mediaType); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); // If we enabled/disabled DXVA in response to a resolution // change then we need to renegotiate our media types, // and resubmit our previous frame (since the MFT appears // to lose it otherwise). if (mUseHwAccel && !CanUseDXVA(mediaType)) { mDXVAEnabled = false; if (!Init()) { return E_FAIL; } mDecoder->Input(mLastInput); return S_OK; } // Verify that the video subtype is what we expect it to be. // When using hardware acceleration/DXVA2 the video format should // be NV12, which is DXVA2's preferred format. For software decoding // we use YV12, as that's easier for us to stick into our rendering // pipeline than NV12. NV12 has interleaved UV samples, whereas YV12 // is a planar format. GUID videoFormat; hr = mediaType->GetGUID(MF_MT_SUBTYPE, &videoFormat); NS_ENSURE_TRUE(videoFormat == MFVideoFormat_NV12 || !mUseHwAccel, E_FAIL); NS_ENSURE_TRUE(videoFormat == MFVideoFormat_YV12 || mUseHwAccel, E_FAIL); UINT32 width = mVideoInfo.mImage.width; UINT32 height = mVideoInfo.mImage.height; nsIntRect pictureRegion = mVideoInfo.mImage; // Calculate and validate the picture region and frame dimensions after // scaling by the pixel aspect ratio. nsIntSize frameSize = nsIntSize(width, height); nsIntSize displaySize = nsIntSize(mVideoInfo.mDisplay.width, mVideoInfo.mDisplay.height); if (!IsValidVideoRegion(frameSize, pictureRegion, displaySize)) { // Video track's frame sizes will overflow. Ignore the video track. return E_FAIL; } if (mDXVA2Manager) { hr = mDXVA2Manager->ConfigureForSize(width, height); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); } // Success! Save state. GetDefaultStride(mediaType, width, &mVideoStride); LOG("WMFVideoMFTManager frame geometry frame=(%u,%u) stride=%u picture=(%d, %d, %d, %d) display=(%d,%d)", width, height, mVideoStride, pictureRegion.x, pictureRegion.y, pictureRegion.width, pictureRegion.height, mVideoInfo.mDisplay.width, mVideoInfo.mDisplay.height); return S_OK; }
// Called by the DecoderMF class when the media type // changes. // // Thread context: decoder thread bool PreviewWindow::SetMediaType(IMFMediaType* mediaType) { HRESULT hr; bool ret = false; GUID subtype; UINT width, height; LONG defaultStride; MFRatio PAR = { 0 }; EnterCriticalSection(&m_criticalSection); hr = mediaType->GetGUID(MF_MT_SUBTYPE, &subtype); if (FAILED(hr)) goto bail; hr = MFGetAttributeSize(mediaType, MF_MT_FRAME_SIZE, &width, &height); if (FAILED(hr)) goto bail; // TODO: get if it's interlaced / progressive (MF_MT_INTERLACE_MODE) hr = GetDefaultStride(mediaType, &defaultStride); if (FAILED(hr)) goto bail; // Get the pixel aspect ratio. Default: Assume square pixels (1:1) hr = MFGetAttributeRatio(mediaType, MF_MT_PIXEL_ASPECT_RATIO, (UINT32*)&PAR.Numerator, (UINT32*)&PAR.Denominator); if (FAILED(hr)) { PAR.Numerator = PAR.Denominator = 1; } // Creates a new RGBA (32bpp) buffer for the converted frame m_width = width; m_height = height; m_defaultStride = defaultStride; m_newTextureInBuffer = false; ret = true; bail: LeaveCriticalSection(&m_criticalSection); return ret; }
HRESULT InitMFStreamer() { printf("InitMFStreamer.\n"); CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); CHECK_HR(InitVPXEncoder(&_vpxConfig, &_vpxCodec, WIDTH, HEIGHT), L"Failed to intialise the VPX encoder.\n"); // Create an attribute store to hold the search criteria. CHECK_HR(MFCreateAttributes(&videoConfig, 1), L"Error creating video configuation."); //CHECK_HR(MFCreateAttributes(&audioConfig, 1), L"Error creating audio configuation.");; // Request video capture devices. CHECK_HR(videoConfig->SetGUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID), L"Error initialising video configuration object."); // Request audio capture devices. /*CHECK_HR(audioConfig->SetGUID( MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_AUDCAP_GUID), L"Error initialising audio configuration object.");*/ // Enumerate the devices, CHECK_HR(MFEnumDeviceSources(videoConfig, &videoDevices, &videoDeviceCount), L"Error enumerating video devices."); //CHECK_HR(MFEnumDeviceSources(audioConfig, &audioDevices, &audioDeviceCount), L"Error enumerating audio devices."); //printf("Video device Count: %i, Audio device count: %i.\n", videoDeviceCount, audioDeviceCount); printf("Video device Count: %i.\n", videoDeviceCount); CHECK_HR(videoDevices[0]->ActivateObject(IID_PPV_ARGS(&videoSource)), L"Error activating video device."); //CHECK_HR(audioDevices[0]->ActivateObject(IID_PPV_ARGS(&audioSource)), L"Error activating audio device."); // Initialize the Media Foundation platform. CHECK_HR(MFStartup(MF_VERSION), L"Error on Media Foundation startup."); /*WCHAR *pwszFileName = L"sample.mp4"; IMFSinkWriter *pWriter;*/ /*CHECK_HR(MFCreateSinkWriterFromURL( pwszFileName, NULL, NULL, &pWriter), L"Error creating mp4 sink writer.");*/ // Create the source readers. CHECK_HR(MFCreateSourceReaderFromMediaSource( videoSource, videoConfig, &videoReader), L"Error creating video source reader."); //ListModes(videoReader); /*CHECK_HR(MFCreateSourceReaderFromMediaSource( audioSource, audioConfig, &audioReader), L"Error creating audio source reader.");*/ FindVideoMode(videoReader, MF_INPUT_FORMAT, WIDTH, HEIGHT, desiredInputVideoType); if (desiredInputVideoType == NULL) { printf("The specified media type could not be found for the MF video reader.\n"); } else { CHECK_HR(videoReader->SetCurrentMediaType((DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, NULL, desiredInputVideoType), L"Error setting video reader media type.\n"); CHECK_HR(videoReader->GetCurrentMediaType( (DWORD)MF_SOURCE_READER_FIRST_VIDEO_STREAM, &videoType), L"Error retrieving current media type from first video stream."); CMediaTypeTrace *videoTypeMediaTrace = new CMediaTypeTrace(videoType); printf("Video input media type: %s.\n", videoTypeMediaTrace->GetString()); LONG pStride = 0; GetDefaultStride(videoType, &pStride); printf("Stride %i.\n", pStride); /*printf("Press any key to continue..."); getchar();*/ /*audioReader->GetCurrentMediaType( (DWORD)MF_SOURCE_READER_FIRST_AUDIO_STREAM, &audioType);*/ //CMediaTypeTrace *audioTypeMediaTrace = new CMediaTypeTrace(audioType); //printf("Audio input media type: %s.\n", audioTypeMediaTrace->GetString()); //printf("Configuring H.264 sink.\n"); // Set up the H.264 sink. /*CHECK_HR(ConfigureEncoder(videoType, &videoStreamIndex, &audioStreamIndex, pWriter), L"Error configuring encoder."); printf("Video stream index %i, audio stream index %i.\n", videoStreamIndex, audioStreamIndex);*/ // 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. CHECK_HR(MFTRegisterLocalByCLSID( __uuidof(CColorConvertDMO), MFT_CATEGORY_VIDEO_PROCESSOR, L"", MFT_ENUM_FLAG_SYNCMFT, 0, NULL, 0, NULL ), L"Error registering colour converter DSP."); // Add the input types to the H.264 sink writer. /*CHECK_HR(pWriter->SetInputMediaType(videoStreamIndex, videoType, NULL), L"Error setting the sink writer video input type."); videoType->Release(); CHECK_HR(pWriter->SetInputMediaType(audioStreamIndex, audioType, NULL), L"Error setting the sink writer audio input type."); audioType->Release();*/ //CHECK_HR(pWriter->BeginWriting(), L"Failed to begin writing on the H.264 sink."); //InitializeCriticalSection(&critsec); } }
HRESULT DrawDevice::SetVideoType(IMFMediaType *pType) { HRESULT hr = S_OK; GUID subtype = { 0 }; MFRatio PAR = { 0 }; // Find the video subtype. hr = pType->GetGUID(MF_MT_SUBTYPE, &subtype); if (FAILED(hr)) { goto done; } // Choose a conversion function. // (This also validates the format type.) hr = SetConversionFunction(subtype); if (FAILED(hr)) { goto done; } // // Get some video attributes. // // Get the frame size. hr = MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &m_width, &m_height); if (FAILED(hr)) { goto done; } // Get the interlace mode. Default: assume progressive. m_interlace = (MFVideoInterlaceMode)MFGetAttributeUINT32( pType, MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive ); // Get the image stride. hr = GetDefaultStride(pType, &m_lDefaultStride); if (FAILED(hr)) { goto done; } // Get the pixel aspect ratio. Default: Assume square pixels (1:1) hr = MFGetAttributeRatio( pType, MF_MT_PIXEL_ASPECT_RATIO, (UINT32*)&PAR.Numerator, (UINT32*)&PAR.Denominator ); if (SUCCEEDED(hr)) { m_PixelAR = PAR; } else { m_PixelAR.Numerator = m_PixelAR.Denominator = 1; } m_format = (D3DFORMAT)subtype.Data1; // Create Direct3D swap chains. hr = CreateSwapChains(); if (FAILED(hr)) { goto done; } // Update the destination rectangle for the correct // aspect ratio. UpdateDestinationRect(); if (m_pBuf) delete [] m_pBuf; m_pBuf = new BYTE[m_height * m_width * 3]; done: if (FAILED(hr)) { m_format = D3DFMT_UNKNOWN; m_convertFn = NULL; } return hr; }
bool WinCaptureDevice::InitializeFirst(std::string& error) { HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); if (!SUCCEEDED(hr)) { return false; error = "CoInitializeEx failed"; } hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); if (!SUCCEEDED(hr)) { error = "MFStartup failed"; return false; } Close(); memset(&InputType, 0, sizeof(InputType)); IMFActivate* activate = WinCaptureDevice::ChooseFirst(error); if (!activate) return false; IMFMediaSource *pSource = NULL; IMFAttributes *pAttributes = NULL; IMFMediaType *pType = NULL; UINT32 m_cchSymbolicLink = 0; // Create the media source for the device. if (SUCCEEDED(hr)) hr = activate->ActivateObject(__uuidof(IMFMediaSource), (void**) &pSource); // Get the symbolic link. if (SUCCEEDED(hr)) hr = activate->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &SymbolicLink, &m_cchSymbolicLink); // // Create the source reader. // // Create an attribute store to hold initialization settings. if (SUCCEEDED(hr)) hr = MFCreateAttributes(&pAttributes, 2); if (SUCCEEDED(hr)) hr = pAttributes->SetUINT32(MF_READWRITE_DISABLE_CONVERTERS, TRUE); // Set the callback pointer. if (SUCCEEDED(hr)) hr = pAttributes->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, this); if (SUCCEEDED(hr)) hr = MFCreateSourceReaderFromMediaSource(pSource, pAttributes, &Reader); // Try to find a suitable input type. if (SUCCEEDED(hr)) { for (uint i = 0; ; i++) { hr = Reader->GetNativeMediaType((DWORD) MF_SOURCE_READER_FIRST_VIDEO_STREAM, i, &pType); if (FAILED(hr)) { error = "Failed to find a supported output format (ie RGB24)"; break; } memset(&InputType, 0, sizeof(InputType)); bool isTypeOK = IsMediaTypeSupported(pType, InputType); if (isTypeOK) { // Get the frame size. hr = MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &InputWidth, &InputHeight); // Get the image stride. hr = GetDefaultStride(pType, &InputDefaultStride); // Get the interlace mode. Default: assume progressive. InputInterlaceMode = (MFVideoInterlaceMode) MFGetAttributeUINT32(pType, MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); } SafeRelease(&pType); if (isTypeOK) break; } } if (SUCCEEDED(hr)) { // Ask for the first sample. EnableCapture = 1; hr = Reader->ReadSample((DWORD) MF_SOURCE_READER_FIRST_VIDEO_STREAM, 0, NULL, NULL, NULL, NULL); } if (FAILED(hr)) { if (pSource) { pSource->Shutdown(); // NOTE: The source reader shuts down the media source by default, but we might not have gotten that far. } Close(); } SafeRelease(&pSource); SafeRelease(&pAttributes); SafeRelease(&pType); SafeRelease(&activate); if (FAILED(hr) && error.length() == 0) error = ErrorMessage(L"Failed to initialize video capture device", hr); return SUCCEEDED(hr); }