HRESULT WMFReader::CreateSourceReader() { HRESULT hr; RefPtr<IMFAttributes> attr; hr = wmf::MFCreateAttributes(byRef(attr), 1); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); hr = attr->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, mSourceReaderCallback); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); if (mUseHwAccel) { hr = attr->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, mDXVA2Manager->GetDXVADeviceManager()); if (FAILED(hr)) { DECODER_LOG("Failed to set DXVA2 D3D Device manager on source reader attributes"); mUseHwAccel = false; } } hr = wmf::MFCreateSourceReaderFromByteStream(mByteStream, attr, byRef(mSourceReader)); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); hr = ConfigureVideoDecoder(); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); hr = ConfigureAudioDecoder(); NS_ENSURE_TRUE(SUCCEEDED(hr), hr); if (mUseHwAccel && mInfo.HasVideo()) { RefPtr<IMFTransform> videoDecoder; hr = mSourceReader->GetServiceForStream(MF_SOURCE_READER_FIRST_VIDEO_STREAM, GUID_NULL, IID_IMFTransform, (void**)(IMFTransform**)(byRef(videoDecoder))); if (SUCCEEDED(hr)) { ULONG_PTR manager = ULONG_PTR(mDXVA2Manager->GetDXVADeviceManager()); hr = videoDecoder->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, manager); if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) { // Ignore MF_E_TRANSFORM_TYPE_NOT_SET. Vista returns this here // on some, perhaps all, video cards. This may be because activating // DXVA changes the available output types. It seems to be safe to // ignore this error. hr = S_OK; } } if (FAILED(hr)) { DECODER_LOG("Failed to set DXVA2 D3D Device manager on decoder hr=0x%x", hr); mUseHwAccel = false; } } return hr; }
nsresult WMFReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) { NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); LOG("WMFReader::ReadMetadata()"); HRESULT hr; RefPtr<IMFAttributes> attr; hr = wmf::MFCreateAttributes(byRef(attr), 1); NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); hr = attr->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, mSourceReaderCallback); NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); if (mUseHwAccel) { hr = attr->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, mDXVA2Manager->GetDXVADeviceManager()); if (FAILED(hr)) { LOG("Failed to set DXVA2 D3D Device manager on source reader attributes"); mUseHwAccel = false; } } hr = wmf::MFCreateSourceReaderFromByteStream(mByteStream, attr, byRef(mSourceReader)); NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); hr = ConfigureVideoDecoder(); NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); hr = ConfigureAudioDecoder(); NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); if (mUseHwAccel && mInfo.mVideo.mHasVideo) { RefPtr<IMFTransform> videoDecoder; hr = mSourceReader->GetServiceForStream(MF_SOURCE_READER_FIRST_VIDEO_STREAM, GUID_NULL, IID_IMFTransform, (void**)(IMFTransform**)(byRef(videoDecoder))); if (SUCCEEDED(hr)) { ULONG_PTR manager = ULONG_PTR(mDXVA2Manager->GetDXVADeviceManager()); hr = videoDecoder->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, manager); if (hr == MF_E_TRANSFORM_TYPE_NOT_SET) { // Ignore MF_E_TRANSFORM_TYPE_NOT_SET. Vista returns this here // on some, perhaps all, video cards. This may be because activating // DXVA changes the available output types. It seems to be safe to // ignore this error. hr = S_OK; } } if (FAILED(hr)) { LOG("Failed to set DXVA2 D3D Device manager on decoder hr=0x%x", hr); mUseHwAccel = false; // Re-run the configuration process, so that the output video format // is set correctly to reflect that hardware acceleration is disabled. // Without this, we'd be running with !mUseHwAccel and the output format // set to NV12, which is the format we expect when using hardware // acceleration. This would cause us to misinterpret the frame contents. hr = ConfigureVideoDecoder(); } } if (mInfo.HasVideo()) { LOG("Using DXVA: %s", (mUseHwAccel ? "Yes" : "No")); } // Abort if both video and audio failed to initialize. NS_ENSURE_TRUE(mInfo.HasValidMedia(), NS_ERROR_FAILURE); // Get the duration, and report it to the decoder if we have it. int64_t duration = 0; hr = GetSourceReaderDuration(mSourceReader, duration); if (SUCCEEDED(hr)) { ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); mDecoder->SetMediaDuration(duration); } // We can seek if we get a duration *and* the reader reports that it's // seekable. bool canSeek = false; if (FAILED(hr) || FAILED(GetSourceReaderCanSeek(mSourceReader, canSeek)) || !canSeek) { mDecoder->SetMediaSeekable(false); } *aInfo = mInfo; *aTags = nullptr; // aTags can be retrieved using techniques like used here: // http://blogs.msdn.com/b/mf/archive/2010/01/12/mfmediapropdump.aspx return NS_OK; }
nsresult WMFReader::ReadMetadata(VideoInfo* aInfo, MetadataTags** aTags) { NS_ASSERTION(mDecoder->OnDecodeThread(), "Should be on decode thread."); LOG("WMFReader::ReadMetadata()"); HRESULT hr; RefPtr<IMFAttributes> attr; hr = wmf::MFCreateAttributes(byRef(attr), 1); NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); hr = attr->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK, mSourceReaderCallback); NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); if (mUseHwAccel) { hr = attr->SetUnknown(MF_SOURCE_READER_D3D_MANAGER, mDXVA2Manager->GetDXVADeviceManager()); if (FAILED(hr)) { LOG("Failed to set DXVA2 D3D Device manager on source reader attributes"); mUseHwAccel = false; } } hr = wmf::MFCreateSourceReaderFromByteStream(mByteStream, attr, byRef(mSourceReader)); NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); hr = ConfigureVideoDecoder(); NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); hr = ConfigureAudioDecoder(); NS_ENSURE_TRUE(SUCCEEDED(hr), NS_ERROR_FAILURE); if (mUseHwAccel && mInfo.mHasVideo) { RefPtr<IMFTransform> videoDecoder; hr = mSourceReader->GetServiceForStream(MF_SOURCE_READER_FIRST_VIDEO_STREAM, GUID_NULL, IID_IMFTransform, (void**)(IMFTransform**)(byRef(videoDecoder))); if (SUCCEEDED(hr)) { ULONG_PTR manager = ULONG_PTR(mDXVA2Manager->GetDXVADeviceManager()); hr = videoDecoder->ProcessMessage(MFT_MESSAGE_SET_D3D_MANAGER, manager); } if (FAILED(hr)) { LOG("Failed to set DXVA2 D3D Device manager on decoder"); mUseHwAccel = false; } } if (mInfo.mHasVideo) { LOG("Using DXVA: %s", (mUseHwAccel ? "Yes" : "No")); } // Abort if both video and audio failed to initialize. NS_ENSURE_TRUE(mInfo.mHasAudio || mInfo.mHasVideo, NS_ERROR_FAILURE); int64_t duration = 0; if (SUCCEEDED(GetSourceReaderDuration(mSourceReader, duration))) { ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); mDecoder->SetMediaDuration(duration); } hr = GetSourceReaderCanSeek(mSourceReader, mCanSeek); NS_ASSERTION(SUCCEEDED(hr), "Can't determine if resource is seekable"); *aInfo = mInfo; *aTags = nullptr; // aTags can be retrieved using techniques like used here: // http://blogs.msdn.com/b/mf/archive/2010/01/12/mfmediapropdump.aspx return NS_OK; }