⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 directxvideotexture.cpp

📁 real-time(实时渲染技术DirectX)30(2)-36
💻 CPP
字号:
/***************************************************************
* DirectXVideoTexture.cpp                                      *
*                                                              *
* This file contains the implementation of the                 *
* CDirectXVideoTexture class.  								   *
* To compile correctly, this file must be linked with:         *
* kernel32.lib                                                 *
* user32.lib                                                   *
* d3dx8dt.lib                                                  *
* d3d8.lib                                                     *
* strmbasd.lib                                                 *
* winmm.lib                                                    *
*                                                              *
***************************************************************/

#include "DirectXVideoTexture.h"

CDirectXVideoTexture::CDirectXVideoTexture() : CBaseVideoRenderer(__uuidof(CLSID_VideoTexture), 
													NAME("Video Texture"), NULL, NULL)
{
	m_pMediaControl  = NULL;
	m_pMediaPosition = NULL;
	m_pMediaEvent    = NULL;
	m_pGraphBuilder  = NULL;
	m_pTexture       = NULL;
}


CDirectXVideoTexture::~CDirectXVideoTexture()
{
    //Stop the video
	if (m_pMediaControl)
		m_pMediaControl->Stop();

    //Let the graph builder clean everything up
	if (m_pGraphBuilder)
		m_pGraphBuilder.Release();

	//Clean up the texture
	if (m_pTexture)
	{
		m_pTexture->Release();
		m_pTexture = NULL;
	}
}

//This is called when the graph builder is trying to make connections
HRESULT CDirectXVideoTexture::CheckMediaType(const CMediaType *pMediaType)
{    
    //Only accept video stuff
	if(*pMediaType->FormatType() != FORMAT_VideoInfo) 
        return E_INVALIDARG;
    
    //Only accept RGB24
	if(IsEqualGUID(*pMediaType->Type(),    MEDIATYPE_Video)  &&
	   IsEqualGUID(*pMediaType->Subtype(), MEDIASUBTYPE_RGB24))
		return S_OK;
    
    return E_FAIL;
}

//Once the connection has been established, the graph builder calls SetMediaType
HRESULT CDirectXVideoTexture::SetMediaType(const CMediaType *pMediaType)
{
    //The video format is in the form of a bitmap info header.
	//Use the bitmap info to set the width and height of the texture
	VIDEOINFO *pVideoFormat = (VIDEOINFO *)pMediaType->Format();
    m_VideoWidth  = pVideoFormat->bmiHeader.biWidth;
    m_VideoHeight = abs(pVideoFormat->bmiHeader.biHeight);

	//The pitch is based on an RGB24 bitmap
    m_VideoPitch = (m_VideoWidth * 3 + 3) & ~(3);

    // Create the texture that maps to this media type
    if(FAILED(D3DXCreateTexture(m_pDevice, m_VideoWidth, m_VideoHeight, 1, 0, 
                                D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_pTexture)))
        return E_FAIL;

    //Make sure that we actually got the format we asked for
    D3DSURFACE_DESC SurfaceDescription;
    m_pTexture->GetLevelDesc(0, &SurfaceDescription);
    if (SurfaceDescription.Format != D3DFMT_A8R8G8B8) 
        return VFW_E_TYPE_NOT_ACCEPTED;

	m_TextureWidth  = SurfaceDescription.Width; 
	m_TextureHeight = SurfaceDescription.Height;

    return S_OK;
}


//This is called every time there is a new frame from the video
HRESULT CDirectXVideoTexture::DoRenderSample(IMediaSample * pSample)
{
    BYTE  *pVideoBuffer;
	BYTE  *pTextureBuffer;
    long  TexturePitch;
    
    //The the image buffer for the video frames
    pSample->GetPointer(&pVideoBuffer);

    //Lock the Texture buffer for writing
    D3DLOCKED_RECT LockedRect;
    if (FAILED(m_pTexture->LockRect(0, &LockedRect, 0, 0)))
        return E_FAIL;
    
    // Get the texture buffer & pitch
    pTextureBuffer = static_cast<byte *>(LockedRect.pBits);
    TexturePitch = LockedRect.Pitch;
    
    //If we've gotten this far, we are dealing with 24bit frames.
	//Walk through row by row
	for(long y = 0; y < m_VideoHeight; y++) 
	{
        BYTE *pVideoRowStart = pVideoBuffer;
        BYTE *pTextureRowStart = pTextureBuffer;  
		
		//walk through each pixel of the row
        for (int x = 0; x < m_VideoWidth; x++) 
		{
            pTextureBuffer[0] = pVideoBuffer[0];
            pTextureBuffer[1] = pVideoBuffer[1];
            pTextureBuffer[2] = pVideoBuffer[2];
            pTextureBuffer[3] = 0xff;

            pTextureBuffer += 4;
            pVideoBuffer   += 3;
        }

        //Increment to the next row
		pVideoBuffer   = pVideoRowStart   + m_VideoPitch;
        pTextureBuffer = pTextureRowStart + TexturePitch;
    }

    //unlock the texture
	if (FAILED(m_pTexture->UnlockRect(0)))
        return E_FAIL;

    return S_OK;
}

HRESULT CDirectXVideoTexture::CreateFromAVIFile(LPDIRECT3DDEVICE8 pDevice, TCHAR *pFileName)
{
    //Make sure the device is set
	m_pDevice = pDevice;
	
	//Reformat the filename parameter so that it will be accepted by AddSourceFilter
	WCHAR wFileName[MAX_PATH];
	MultiByteToWideChar(CP_ACP, 0, pFileName, -1, wFileName, MAX_PATH);

    //These are some working objects used to build the filter graph
	CComPtr<IPin>           pPinIn;
    CComPtr<IBaseFilter>    pSourceFilter;
    CComPtr<IPin>           pPinOut;

	//Add a reference so that the graph builder does not delete this object.
	//That causes badness because the object is destroyed too early
	AddRef();

    //initialize the COM library
	CoInitialize(NULL) ;

	// Create the filter graph
	if (SUCCEEDED(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IFilterGraph, (void **)&m_pGraphBuilder)))
	{
		//Add this filter to the bag of tricks
		if (SUCCEEDED(m_pGraphBuilder->AddFilter(this, L"TEXTURERENDERER")))
		{
			//Add a source filter for the AVI file
			if (SUCCEEDED(m_pGraphBuilder->AddSourceFilter (wFileName, L"SOURCE", &pSourceFilter)))
			{
				//Get the input pin for this filter
				if (SUCCEEDED(FindPin(L"In", &pPinIn)))
				{
					//Get the output pin of the source filter
					if (SUCCEEDED(pSourceFilter->FindPin(L"Output", &pPinOut)))
					{
						//Let the graph builder figure out how to connect them
						if (SUCCEEDED(m_pGraphBuilder->Connect(pPinOut, pPinIn)))
						{
							//If the graph was successful, retreive all the interfaces
							m_pGraphBuilder.QueryInterface(&m_pMediaControl);
							m_pGraphBuilder.QueryInterface(&m_pMediaEvent);
							m_pGraphBuilder.QueryInterface(&m_pMediaPosition);

							//This is for audio. Some files may not have audio and the following
							//code may not work for all media types. Check the graph builder tool
							CComPtr<IBaseFilter>    pSplitterFilter;
						    CComPtr<IPin>           pAudioPin;

							//Find the a/v splitter in the graph
							if (SUCCEEDED(m_pGraphBuilder->FindFilterByName(L"AVI Splitter", &pSplitterFilter)))
							{
								//Find the pin for the first audio stream and render it. If it's not there,
								//it's OK, just move on...
								if (SUCCEEDED(pSplitterFilter->FindPin(L"Stream 01", &pAudioPin)))
									m_pGraphBuilder->Render(pAudioPin);
							}

							//If everything was successful, start retrieving frames
							if (SUCCEEDED(m_pMediaControl->Run()))
								return S_OK;
						}
					}
				}
			}
		}
	}

	//If you're here, something was bad
	return E_FAIL;
}

void CDirectXVideoTexture::CheckForLoop()
{
    long lEventCode;
    long lParam1;
    long lParam2;

    //If the video is complete, loop back to the start
    m_pMediaEvent->GetEvent(&lEventCode, &lParam1, &lParam2, 0);
    if (EC_COMPLETE == lEventCode)
        m_pMediaPosition->put_CurrentPosition(0);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -