Evr9VideoWindowControl::Evr9VideoWindowControl(QObject *parent) : QVideoWindowControl(parent) , m_windowId(0) , m_dirtyValues(0) , m_aspectRatioMode(Qt::KeepAspectRatio) , m_brightness(0) , m_contrast(0) , m_hue(0) , m_saturation(0) , m_fullScreen(false) , m_currentActivate(0) , m_evrSink(0) , m_displayControl(0) { if (FAILED(MFCreateVideoRendererActivate(0, &m_currentActivate))) { qWarning() << "Failed to create evr video renderer activate!"; return; } if (FAILED(m_currentActivate->ActivateObject(IID_IMFMediaSink, (LPVOID*)(&m_evrSink)))) { qWarning() << "Failed to activate evr media sink!"; return; } if (FAILED(MFGetService(m_evrSink, MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(&m_displayControl)))) { qWarning() << "Failed to get display control from evr media sink!"; return; } if (FAILED(MFGetService(m_evrSink, MR_VIDEO_MIXER_SERVICE, IID_PPV_ARGS(&m_processor)))) { qWarning() << "Failed to get video processor from evr media sink!"; return; } }
QByteArray MFTransform::dataFromBuffer(IMFMediaBuffer *buffer, int height, int *bytesPerLine) { QByteArray array; BYTE *bytes; DWORD length; HRESULT hr = buffer->Lock(&bytes, NULL, &length); if (SUCCEEDED(hr)) { array = QByteArray((const char *)bytes, (int)length); buffer->Unlock(); } else { // try to lock as Direct3DSurface IDirect3DSurface9 *surface = 0; do { if (FAILED(MFGetService(buffer, MR_BUFFER_SERVICE, IID_IDirect3DSurface9, (void**)&surface))) break; D3DLOCKED_RECT rect; if (FAILED(surface->LockRect(&rect, NULL, D3DLOCK_READONLY))) break; if (bytesPerLine) *bytesPerLine = (int)rect.Pitch; array = QByteArray((const char *)rect.pBits, rect.Pitch * height); surface->UnlockRect(); } while (false); if (surface) { surface->Release(); surface = 0; } } return array; }
HRESULT CPlayer::GetBufferProgress(DWORD *pProgress) { IPropertyStore *pProp = NULL; PROPVARIANT var; // Get the property store from the media session. HRESULT hr = MFGetService( m_pSession, MFNETSOURCE_STATISTICS_SERVICE, IID_PPV_ARGS(&pProp) ); if (SUCCEEDED(hr)) { PROPERTYKEY key; key.fmtid = MFNETSOURCE_STATISTICS; key.pid = MFNETSOURCE_BUFFERPROGRESS_ID; hr = pProp->GetValue(key, &var); } if (SUCCEEDED(hr)) { *pProgress = var.lVal; // cout << "buff prog " << *pProgress << endl; } PropVariantClear(&var); SafeRelease(&pProp); return hr; }
HRESULT CPlayer::setVolume(float vol) { //Should we lock here as well ? if (m_pSession == NULL) { ofLogError("ofxWMFVideoPlayer", "setVolume: Error session is null"); return E_FAIL; } if (m_pVolumeControl == NULL) { HRESULT hr = MFGetService(m_pSession, MR_STREAM_VOLUME_SERVICE, __uuidof(IMFAudioStreamVolume), (void**)&m_pVolumeControl); _currentVolume = vol; if (FAILED(hr)) { ofLogError("ofxWMFVideoPlayer", "setVolume: Error while getting sound control interface"); return E_FAIL; } } UINT32 nChannels; m_pVolumeControl->GetChannelCount(&nChannels); for (int i = 0; i < nChannels; i++) { m_pVolumeControl->SetChannelVolume(i, vol); } _currentVolume = vol; return S_OK; }
HRESULT D3DPresentEngine::PresentSample(IMFSample* pSample, LONGLONG llTarget) { HRESULT hr = S_OK; IMFMediaBuffer* pBuffer = NULL; IDirect3DSurface9* pSurface = NULL; IDirect3DSwapChain9* pSwapChain = NULL; if (pSample) { // Get the buffer from the sample. CHECK_HR(hr = pSample->GetBufferByIndex(0, &pBuffer)); // Get the surface from the buffer. CHECK_HR(hr = MFGetService(pBuffer, MR_BUFFER_SERVICE, __uuidof(IDirect3DSurface9), (void**)&pSurface)); } else if (m_pSurfaceRepaint) { // Redraw from the last surface. pSurface = m_pSurfaceRepaint; pSurface->AddRef(); } if (pSurface) { // Get the swap chain from the surface. CHECK_HR(hr = pSurface->GetContainer(__uuidof(IDirect3DSwapChain9), (LPVOID*)&pSwapChain)); // Present the swap chain. CHECK_HR(hr = PresentSwapChain(pSwapChain, pSurface)); // Store this pointer in case we need to repaint the surface. CopyComPointer(m_pSurfaceRepaint, pSurface); } done: SAFE_RELEASE(pSwapChain); SAFE_RELEASE(pSurface); SAFE_RELEASE(pBuffer); if (FAILED(hr)) { if (hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET || hr == D3DERR_DEVICEHUNG) { // Ignore. We need to reset or re-create the device, but this method // is probably being called from the scheduler thread, which is not the // same thread that created the device. The Reset(Ex) method must be // called from the thread that created the device. // The presenter will detect the state when it calls CheckDeviceState() // on the next sample. hr = S_OK; } } return hr; }
HRESULT CTedPlayer::SetRate(float flRate) { HRESULT hr = S_OK; CComPtr<IMFRateControl> spRateControl = NULL; IFC( MFGetService( m_spSession, MF_RATE_CONTROL_SERVICE, IID_IMFRateControl, (void**) &spRateControl )); IFC( spRateControl->SetRate( FALSE, flRate ) ); Cleanup: return( hr ); }
HRESULT CTedPlayer::GetRateBounds(MFRATE_DIRECTION eDirection, float* pflSlowest, float* pflFastest) { HRESULT hr = S_OK; CComPtr<IMFRateSupport> spRateSupport; assert(pflSlowest != NULL); assert(pflFastest != NULL); IFC( MFGetService( m_spSession, MF_RATE_CONTROL_SERVICE, IID_IMFRateSupport, (void**) &spRateSupport ) ); IFC( spRateSupport->GetSlowestRate( eDirection, FALSE, pflSlowest ) ); IFC( spRateSupport->GetFastestRate( eDirection, FALSE, pflFastest ) ); Cleanup: return( hr ); }
// Presents a video frame. HRESULT D3DPresentEngine::PresentSample(IMFSample* pSample, LONGLONG llTarget) { HRESULT hr = S_OK; IMFMediaBuffer* pBuffer = NULL; IDirect3DTexture9* pTexture = NULL; if (pSample) { // Get the buffer from the sample. hr = pSample->GetBufferByIndex(0, &pBuffer); if (SUCCEEDED(hr)) { // Get the surface from the buffer. IDirect3DSurface9* pSurface = NULL; hr = MFGetService(pBuffer, MR_BUFFER_SERVICE, __uuidof(IDirect3DSurface9), (void**)&pSurface); if (SUCCEEDED(hr)) { // Get the texture from the buffer. pSurface->GetContainer(IID_IDirect3DTexture9, (void**)&pTexture); } } if (hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET || hr == D3DERR_DEVICEHUNG) { // We failed because the device was lost. // This case is ignored. The Reset(Ex) method must be called from the thread that created the device. // The presenter will detect the state when it calls CheckDeviceState() on the next sample. hr = S_OK; } } else if (m_pTextureRepaint) { // Redraw from the last surface. pTexture = m_pTextureRepaint; pTexture->AddRef(); } hr = m_EVRCallback->PresentSurface(m_Width, m_Height, m_ArX, m_ArY, (DWORD)&pTexture); // Return reference, so C# side can modify the pointer after Dispose() to avoid duplicated releasing. SAFE_RELEASE(pTexture); SAFE_RELEASE(pBuffer); return hr; }
void D3DPresentEngine::presentSample(void *opaque, qint64) { HRESULT hr = S_OK; IMFSample *sample = reinterpret_cast<IMFSample*>(opaque); IMFMediaBuffer* buffer = NULL; IDirect3DSurface9* surface = NULL; if (m_surface && m_surface->isActive()) { if (sample) { // Get the buffer from the sample. hr = sample->GetBufferByIndex(0, &buffer); if (FAILED(hr)) goto done; // Get the surface from the buffer. hr = MFGetService(buffer, MR_BUFFER_SERVICE, IID_PPV_ARGS(&surface)); if (FAILED(hr)) goto done; } if (surface && updateTexture(surface)) { QVideoFrame frame = QVideoFrame(new TextureVideoBuffer(m_glTexture), m_surfaceFormat.frameSize(), m_surfaceFormat.pixelFormat()); // WMF uses 100-nanosecond units, Qt uses microseconds LONGLONG startTime = -1; if (SUCCEEDED(sample->GetSampleTime(&startTime))) { frame.setStartTime(startTime * 0.1); LONGLONG duration = -1; if (SUCCEEDED(sample->GetSampleDuration(&duration))) frame.setEndTime((startTime + duration) * 0.1); } m_surface->present(frame); } } done: qt_wmf_safeRelease(&surface); qt_wmf_safeRelease(&buffer); qt_wmf_safeRelease(&sample); }
void Player_::OnTopologyStatus(IMFMediaEventPtr pEvent) { UINT32 status; THROW_IF_ERR(pEvent->GetUINT32(MF_EVENT_TOPOLOGY_STATUS, &status)); if (status == MF_TOPOSTATUS_READY) { safe_release(m_pVideoDisplay); // Get the IMFVideoDisplayControl interface from EVR. This call is // expected to fail if the media file does not have a video stream. (void)MFGetService(m_pSession.Get(), MR_VIDEO_RENDER_SERVICE, IID_PPV_ARGS(m_pVideoDisplay.GetAddressOf())); static_cast<this_type&>(*this).process_event(ev::OpenComplete()); //StartPlayback(); } }
HRESULT CPlayer::OnTopologyReady(IMFMediaEvent *pEvent) { TRACE((L"CPlayer::OnTopologyReady\n")); // Ask for the IMFVideoDisplayControl interface. // This interface is implemented by the EVR and is // exposed by the media session as a service. // Note: This call is expected to fail if the source // does not have video. MFGetService( m_pSession, MR_VIDEO_RENDER_SERVICE, __uuidof(IMFVideoDisplayControl), (void**)&m_pVideoDisplay ); HRESULT hr = StartPlayback(); return S_OK; }
HRESULT MediaInfo::InternalOpen(IUnknown* punk) { ComPtr<IMFMediaSource> source; HRESULT hr = punk->QueryInterface(IID_PPV_ARGS(&source)); if (FAILED(hr)) return hr; ComPtr<IMFPresentationDescriptor> ppd; hr = source->CreatePresentationDescriptor(&ppd); if (FAILED(hr)) return hr; DWORD streamCount = 0; ppd->GetStreamDescriptorCount(&streamCount); if (streamCount == 0) return E_UNEXPECTED; UINT64 duration = MFGetAttributeUINT64(ppd.Get(), MF_PD_DURATION, 0); UINT64 fileSize = MFGetAttributeUINT64(ppd.Get(), MF_PD_TOTAL_FILE_SIZE, 0); WCHAR mimeType[128] = {0}; ppd->GetString(MF_PD_MIME_TYPE, mimeType, _countof(mimeType), NULL); memset(&_info, 0, sizeof(_info)); _info.streamCount = streamCount; _info.duration = double(duration) / 10000000.0; _info.totalFileSize = fileSize; WideCharToMultiByte(CP_ACP, 0, mimeType, -1, _info.mimeType, _countof(_info.mimeType), NULL, NULL); hr = InternalLoadStreams(ppd.Get()); if (FAILED(hr)) return hr; MFGetService(source.Get(), MF_SCRUBBING_SERVICE, IID_PPV_ARGS(&_seekInfo)); _mediaSource = source; return S_OK; }
void MediaSource::LoadMetadataFromSource() { IMFMetadataProvider* mfMetadataProvider = nullptr; IMFMetadata* mfMetadata = nullptr; PROPVARIANT metadataKeys, metadataValue; PWSTR *metadataPropertyKeys = nullptr; HRESULT hr; _metadataPropertyCount = 0; PropVariantInit(&metadataKeys); PropVariantInit(&metadataValue); do { if (!SUCCEEDED(hr = MFGetService(_mfMediaSource, MF_METADATA_PROVIDER_SERVICE, IID_PPV_ARGS(&mfMetadataProvider)))) { // Can't get the metadata provider service for this media source, but that's ok... we'll just skip reading metadata hr = S_OK; break; } if (!SUCCEEDED(hr = mfMetadataProvider->GetMFMetadata(_mfPresentationDescriptor, 0, 0, &mfMetadata))) break; if (!SUCCEEDED(hr = mfMetadata->GetAllPropertyNames(&metadataKeys))) break; if (!SUCCEEDED(hr = PropVariantToStringVectorAlloc(metadataKeys, &metadataPropertyKeys, &_metadataPropertyCount))) break; _metadata = (MetadataKeyValuePair *)malloc(_metadataPropertyCount * sizeof(MetadataKeyValuePair)); for (ULONG i = 0; i < _metadataPropertyCount; i++) { PWSTR metadataKey = *(metadataPropertyKeys + i); if (!SUCCEEDED(hr = mfMetadata->GetProperty(metadataKey, &metadataValue))) break; (_metadata + i)->Key = metadataKey; if (!SUCCEEDED(hr = PropVariantToStringAlloc(metadataValue, &((_metadata + i)->Value)))) break; PropVariantClear(&metadataValue); } if (FAILED(hr)) break; } while (0); if (metadataPropertyKeys) CoTaskMemFree(metadataPropertyKeys); if (mfMetadata) mfMetadata->Release(); if (mfMetadataProvider) mfMetadataProvider->Release(); if (FAILED(hr)) { throw std::exception("Error occurred reading metadata from media source"); } }
HRESULT D3DPresentEngine::PresentSample(IMFSample* pSample, LONGLONG llTarget) { HRESULT hr = S_OK; IMFMediaBuffer* pBuffer = NULL; IDirect3DSurface9* pSurface = NULL; // IDirect3DSwapChain9* pSwapChain = NULL; IDirect3DSurface9 * back_buffer = NULL; if (pSample) { // Get the buffer from the sample. CHECK_HR(hr = pSample->GetBufferByIndex(0, &pBuffer)); // Get the surface from the buffer. CHECK_HR(hr = MFGetService(pBuffer, MR_BUFFER_SERVICE, __uuidof(IDirect3DSurface9), (void**)&pSurface)); } else if (m_pSurfaceRepaint) { // Redraw from the last surface. pSurface = m_pSurfaceRepaint; pSurface->AddRef(); } if (pSurface) { // Get the swap chain from the surface. // CHECK_HR(hr = pSurface->GetContainer(__uuidof(IDirect3DSwapChain9), (LPVOID*)&pSwapChain)); // Present the swap chain. // CHECK_HR(hr = PresentSwapChain(pSwapChain, pSurface)); CHECK_HR(hr = m_pDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &back_buffer)); CHECK_HR(hr = m_pDevice->StretchRect(pSurface, NULL, back_buffer, NULL, D3DTEXF_LINEAR)); CHECK_HR(hr = m_pDevice->Present(NULL, NULL, NULL, NULL)); // Store this pointer in case we need to repaint the surface. CopyComPointer(m_pSurfaceRepaint, pSurface); } else { // No surface. All we can do is paint a black rectangle. PaintFrameWithGDI(); } done: // SAFE_RELEASE(pSwapChain); SAFE_RELEASE(pSurface); SAFE_RELEASE(pBuffer); SAFE_RELEASE(back_buffer); if (FAILED(hr)) { if (hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET || hr == D3DERR_DEVICEHUNG) { // We failed because the device was lost. Fill the destination rectangle. PaintFrameWithGDI(); // Ignore. We need to reset or re-create the device, but this method // is probably being called from the scheduler thread, which is not the // same thread that created the device. The Reset(Ex) method must be // called from the thread that created the device. // The presenter will detect the state when it calls CheckDeviceState() // on the next sample. hr = S_OK; } } return hr; }