1. 程式人生 > >使用VMR9+D3D解碼和播放視訊

使用VMR9+D3D解碼和播放視訊

#include "stdafx.h"
#include "Decoder.h"


CDecoder::CDecoder(LPCWSTR fileName, HWND d3dHwnd, IDirect3DDevice9* device) :
	m_d3dHwnd(d3dHwnd),
	m_device(device)
{
	HRESULT hr;
	hr = m_vmr9.CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC_SERVER);
	hr = m_graph.CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER);
	hr = m_graph.QueryInterface(&m_control);

	hr = m_graph->AddFilter(m_vmr9, L"VMR9");
	hr = m_graph->AddSourceFilter(fileName, L"Source", &m_source);
	
	// 設定呈現器
	CComPtr<IVMRFilterConfig9> vmrConfig;
	hr = m_vmr9.QueryInterface(&vmrConfig);
	hr = vmrConfig->SetRenderingMode(VMR9Mode_Renderless);
	hr = m_vmr9.QueryInterface(&m_vmrNotify);
	hr = m_vmrNotify->AdviseSurfaceAllocator(0, this);
	hr = AdviseNotify(m_vmrNotify);

	// 連線源和渲染器
	CComPtr<IEnumPins> enumPins;
	CComPtr<IPin> sourcePin, renderPin;
	PIN_DIRECTION pinDir;

	m_source->EnumPins(&enumPins);
	while (enumPins->Next(1, &sourcePin, NULL) == S_OK)
	{
		sourcePin->QueryDirection(&pinDir);
		if (pinDir == PINDIR_OUTPUT)
			break;
		sourcePin.Release();
	}
	enumPins.Release();

	m_vmr9->EnumPins(&enumPins);
	while (enumPins->Next(1, &renderPin, NULL) == S_OK)
	{
		renderPin->QueryDirection(&pinDir);
		if (pinDir == PINDIR_INPUT)
			break;
		renderPin.Release();
	}
	enumPins.Release();

	hr = m_graph->Connect(sourcePin, renderPin);
}

void CDecoder::Run()
{
	TRACE(_T("Run\n"));
	HRESULT hr = m_control->Run();
}

void CDecoder::Pause()
{
	TRACE(_T("Pause\n"));
	HRESULT hr = m_control->Pause();
}

void CDecoder::Stop()
{
	TRACE(_T("Stop\n"));
	HRESULT hr = m_control->Stop();
}

void CDecoder::GetVideoSize(SIZE& size)
{
	size = m_videoSize;
}

void CDecoder::SetOnPresent(std::function<void(VMR9PresentationInfo*)>&& onPresent)
{
	m_onPresent = std::move(onPresent);
}

// IUnknown

HRESULT STDMETHODCALLTYPE CDecoder::QueryInterface(REFIID riid, _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject)
{
	if (riid == IID_IUnknown)
	{
		*ppvObject = (IUnknown*)(IVMRSurfaceAllocator9*)this;
		return S_OK;
	}
	if (riid == IID_IVMRSurfaceAllocator9)
	{
		*ppvObject = (IVMRSurfaceAllocator9*)this;
		return S_OK;
	}
	if (riid == IID_IVMRImagePresenter9)
	{
		*ppvObject = (IVMRImagePresenter9*)this;
		return S_OK;
	}
	return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE CDecoder::AddRef(void)
{
	return 0;
}

ULONG STDMETHODCALLTYPE CDecoder::Release(void)
{
	return 0; // 沒有嚴格實現COM元件,防止多次析構
}

// IVMRSurfaceAllocator9

HRESULT STDMETHODCALLTYPE CDecoder::AdviseNotify(IVMRSurfaceAllocatorNotify9 *lpIVMRSurfAllocNotify)
{
	TRACE(_T("AdviseNotify\n"));
	return lpIVMRSurfAllocNotify->SetD3DDevice(m_device, MonitorFromWindow(m_d3dHwnd, MONITOR_DEFAULTTOPRIMARY));
}

HRESULT STDMETHODCALLTYPE CDecoder::InitializeDevice(DWORD_PTR dwUserID, VMR9AllocationInfo *lpAllocInfo, DWORD *lpNumBuffers)
{
	TRACE(_T("InitializeDevice\n"));
	m_videoSize = lpAllocInfo->szNativeSize;

	m_surfaces.resize(*lpNumBuffers);
	lpAllocInfo->dwFlags |= VMR9AllocFlag_OffscreenSurface; // 直接建立紋理表面很可能失敗,所以建立離屏表面再複製到紋理表面
	HRESULT hr = m_vmrNotify->AllocateSurfaceHelper(lpAllocInfo, lpNumBuffers, &m_surfaces[0]);
	if (FAILED(hr))
		m_surfaces.clear();
	return hr;
}

HRESULT STDMETHODCALLTYPE CDecoder::TerminateDevice(DWORD_PTR dwID)
{
	TRACE(_T("TerminateDevice\n"));
	if (!m_surfaces.empty())
	{
		for (auto& i : m_surfaces)
			i->Release();
		m_surfaces.clear();
	}
	return S_OK;
}

HRESULT STDMETHODCALLTYPE CDecoder::GetSurface(DWORD_PTR dwUserID, DWORD SurfaceIndex, DWORD SurfaceFlags, IDirect3DSurface9 **lplpSurface)
{
	TRACE(_T("GetSurface(%u)\n"), SurfaceIndex);
	if (SurfaceIndex < 0 || SurfaceIndex >= m_surfaces.size())
	{
		*lplpSurface = NULL;
		return E_FAIL;
	}
	*lplpSurface = m_surfaces[SurfaceIndex];
	(*lplpSurface)->AddRef();
	return S_OK;
}

// IVMRImagePresenter9

HRESULT STDMETHODCALLTYPE CDecoder::StartPresenting(DWORD_PTR dwUserID)
{
	TRACE(_T("StartPresenting\n"));
	return S_OK;
}

HRESULT STDMETHODCALLTYPE CDecoder::StopPresenting(DWORD_PTR dwUserID)
{
	TRACE(_T("StopPresenting\n"));
	return S_OK;
}

HRESULT STDMETHODCALLTYPE CDecoder::PresentImage(DWORD_PTR dwUserID, VMR9PresentationInfo *lpPresInfo)
{
	//TRACE(_T("PresentImage(%I64d)\n"), lpPresInfo->rtStart);
	if (!m_onPresent._Empty())
		m_onPresent(lpPresInfo);
	return S_OK;
}

相關推薦

使用VMR9+D3D解碼播放視訊

#include "stdafx.h" #include "Decoder.h" CDecoder::CDecoder(LPCWSTR fileName, HWND d3dHwnd, IDirect3DDevice9* device) : m_d3dHwnd(d3dHwnd), m_device(de

FFmpeg 4.0.2解碼播放視訊

在上一篇文章中我們知道了如何將FFmpeg4.0.2原始碼編譯成so庫,並且如何在Android Studio中配置並使用so庫,那麼這篇文章我們將介紹如何使用FFmpeg在Android ndk中介面視訊檔案並繪製到螢幕上。 我們先來看下效果一睹為快。 總體

IJKPlayer使用MediaCodec解碼渲染視訊過程分析

IJKMediaCodec 解碼分析 1.func_run_sync(IJKFF_Pipenode *node) /ffpipenode_android_mediacodec_vdec.c —-drain_output_buffer(env,

android通過webView載入第三方h5應用,無法載入圖片播放視訊的解決方法

只需給webview的配置中加上下面這段程式碼即可解決 這是Android5.0 WebView中Http和Https混合問題,在Android5.0 以及以上的系統,當WebView載入的連結為Https開頭,但是連結裡面的內容,比如圖片為Http連結,這時

9.基於FFMPEG+SDL2播放視訊解碼執行緒播放執行緒分開)

參考資料: 1.雷博部落格 2. An ffmpeg and SDL Tutorial 繼續FFMPEG學習之路。。。 文章目錄 1 綜述 2 程式碼1(基礎程式碼) 3 程式碼2(播放執行緒和解碼執行緒分開) 3.1 幾個結構體

最簡單的基於FFMPEG+SDL的視訊播放器:拆分-解碼播放

=====================================================最簡單的基於FFmpeg的視訊播放器系列文章列表:=====================================================本文補充記錄《

語音/短視訊 :錄製(編碼)播放解碼

  IM軟體就需要即時通訊技術、視訊軟體就需要視訊編解碼技術、遊戲就需要引擎技術。   檢視原始碼的工具:sourceinsight , 不瞭解JNI的一定要學習下,否則只能在JAVA層搞,太狹隘了。 音視訊採集–壓縮編碼–封裝–推流–分發–流媒體協議觀看.  音視訊流程

Android 利用傳送Intent播放本地視訊網路視訊 (轉載)

http://blog.sina.com.cn/s/blog_a000da9d01011y85.html Android中除了利用VideoView、Mediaplayer播放視訊檔案外,還可以用傳送Intent來呼叫視訊播放模組。   方法如下: &nb

使用FFMPEG解碼OpenAL播放音樂

使用FFMPEG解碼和OpenAL播放音樂 OpenAL是一個開源的音效庫,然而這裡只用它來播放音樂。  FFMPEG負責把音樂解碼並轉換成指定的編碼和取樣率,然後送到OpenAL中播放。  (已在windows和iOS平臺簡單測試通過) A

使用MediaCodec硬解碼h.265視訊及音訊進行播放

h.265這個視訊是很多播放器不支援的,就算是bilibili開源的ijkplayer也不能直接播放,需要自己去重新編譯 才可以支援。 這裡通過這個demo來演示一下如何硬解碼視訊,播放h.265視訊,其實編碼的視訊同樣道理。 視訊的播放主要在surfaceView中顯示,而解碼

多媒體之播放視訊——VideoViewMediaPlayer(MediaPlayerSurfaceView結合)

VideoView 一、簡介: 後面講解SurfaceView。 VideoView將視訊的顯示和控制集於一身,它的用法和MediaPlayer很相似,因為VideoView只是做好了一個封裝而已,它的背後仍然是MediaPlayer來對視訊檔案進

【SoaringLee_fighting的技術專欄】專注於音視訊解碼AI技術領域,開源分享,不忘初心,追求卓越!

【關於博主】   目前就職於國內知名安防企業,從事於編解碼演算法開發和優化工作,對音視訊編解碼、機器視覺和深度學習有很大興趣,期待與有識之士共同交流學習! 座標: 浙江杭州 Email: [email protected] 【推薦部落格】  編解碼: h

SoaringLee_fighting的技術專欄(專注於音視訊解碼AI技術領域,開源分享,不忘初心,追求卓越!)

【關於博主】   目前就職於國內知名安防企業,從事於編解碼演算法開發和優化工作,對音視訊編解碼、機器視覺和深度學習有很大興趣,期待與有識之士共同交流學習! 座標: 浙江杭州 Email: [email protected] 【推薦部落格】  編解碼: h

HTML 播放視訊的embed標籤Object標籤(轉)

原文地址:https://blog.csdn.net/qq_19865749/article/details/65631472 一、object元素 標籤用於包含物件,比如影象、音訊、視訊、Java applets、ActiveX、PDF 以及 Flash。 1、object標籤屬

SurfaceViewMediaplayer實現播放網路本地視訊

程式碼是最好的老師!!直接上程式碼 package com.example.yaoan.surfaceviewtest; import android.media.MediaPlayer; import android.net.Uri; import a

Android兩種播放視訊的方法(SurfaceView、MediaPlayer、SeekBar)(VideoView、MediaController)等兩種方法。

package com.example.android_playmusic;import android.media.MediaPlayer;import android.net.Uri;import android.support.v7.app.AppCompatActivity;import

22_Android中的本地音樂播放網路音樂播放器的編寫,本地視訊播放網路視訊播放器,照相機案例,偷拍案例實現

1 編寫以下案例:當點選了”播放”之後,在手機上的/mnt/sdcard2/natural.mp3就會播放。2 編寫佈局檔案activity_main.xml<LinearLayout xmlns

Android邊緩衝邊播放視訊(ijkplayer的編譯使用)

當你看到這篇博文的時候希望你先對這個開源專案有所瞭解。 github上的地址: https://github.com/Bilibili/ijkplayer 感謝嗶哩嗶哩團隊不吝開放出來。此文主要用於幫助之後需要編譯ijkplayer的同學,少走一點彎路。 轉載請註明出處:CSD

Android中視訊檔案的下載播放

String path = "http:.........."; // 下載地址 // 建立資料夾,在儲存卡下

webview是用軟解碼或者硬解碼可能導致視訊播放有聲音沒有影象

//Rendering mode // //                    if (Build.VERSION.SDK_INT >= 11) { //