Red de conocimiento informático - Conocimiento informático - Cómo diseñar un filtro de transformación personalizado

Cómo diseñar un filtro de transformación personalizado

Para los principiantes en DIrectShow, diseñar filtros personalizados es la mayor dificultad.

Es difícil diseñar un filtro de transformación personalizado

Porque, en primer lugar, el filtro es un dll (con extensión .ax) y escribir un proyecto dll requiere ciertos conocimientos de VC. Por lo tanto, se recomienda que primero aumente sus conocimientos sobre dll. En primer lugar, el filtro es un dll (extensión .ax). Para escribir un proyecto dll, debe tener ciertos conocimientos de VC, por lo que se recomienda agregar primero un poco de conocimiento de dll.

En segundo lugar, el registro de dll y la configuración del proyecto también son problemáticos.

Por cierto, crear un proyecto dll también es difícil.

En segundo lugar, el registro de dll, la generación de GUID y la configuración del proyecto serán muy problemáticos.

Además, faltan ejemplos listos para usar de filtros de conversión en Internet. El código fuente proporcionado por DirectShow (como NULLINPLACE y CONTRAST) es demasiado complejo y tiene muchos cuadros de diálogo y páginas de propiedades. y no es adecuado para principiantes. Además, estos ejemplos ninguno implica conversión de formato de imagen y los filtros de conversión desempeñan el papel más importante en la conversión de medios. La función más importante de los filtros es la conversión de tipos de medios, por lo que estos ejemplos no son aplicables.

Como principiante, estos problemas me preocupaban profundamente. Después de estudiar mucho, finalmente salí del atolladero y de repente me iluminó. . Espero que pueda ser de ayuda para todos y también pueda considerarse como un resumen de 2008.

Mi ejemplo es diseñar un filtro de conversión para convertir medios YUY2 de 16 bits al tipo RGB24 de 24 bits.

La razón es que mi cámara web solo admite YUY2 de 16 bits y quiero obtener el mapa de bits. Quiero obtener un mapa de bits. Por cierto, quiero aprender a diseñar filtros

Los pasos específicos son los siguientes:

Configurar el entorno de desarrollo

1. En Herramientas->Opciones ->Directorios Establezca la ruta al archivo de encabezado y la biblioteca del SDK de DirectX en VC

2. Compile el código fuente de la clase base y genere strmbasd. Genere strmbasd.lib (versión de depuración), strmbase.lib (versión de lanzamiento)

3. El asistente de VC crea un nuevo proyecto win32 DLL (vacío)

4. Configuración->Enlace - >Nombre del archivo de salida. YUV2RGBfilter.ax

5. Configuración->Enlace Agregar strmbasd.lib winmm.lib quartz.lib vfw32.lib (tenga en cuenta la ruta)

6. Defina un archivo .def con el mismo nombre y agregar al proyecto, el contenido es el siguiente:

LIBRARY YUV2RGBfilter.ax

EXPORTACIONES

DllMain PRIVATE

DllGetClassObject PRIVATE

DllCanUnloadNow PRIVATE

DllRegisterServer PRIVATE

DllUnregisterServer PRIVATE

7. Cree la clase YUV2RGBfilter y cree su archivo cpp y h.

8. Defina la función de entrada y registro de la DLL en YUV2RGBfilter.cpp. Defina la función de entrada y registro de la DLL en YUV2RGBfilter.cpp.

cpp colóquelo al final del archivo cpp

//p>

// DllEntryPoint

//

extern "C " BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

BOOL APIENTRY DllMain(HANDLE hModule,

DWORD dwReason,

LPVOID lpReserved)

{

return DllEntryPoint((HINSTANCE)( hModule), dwReason, lpReserved);

}

///////// / ///////////////////////////////////////////////// ///// ////////////

//

// Exportar punto de entrada para registro y baja

/ /( En este caso simplemente llaman a la implementación predeterminada).

//

/////////////////////////////////// // ////////////////////////////////////////

STDAPI DllRegisterServer()

{

return AMovieDllRegisterServer2( TRUE );

}

STDAPI DllUnregisterServer()

{

return AMovieDllRegisterServer2( FALSE );

}

9. Archivos de encabezado que se incluirán en el archivo cpp

#include < streams.h>

#include

#include

#include "YUV2RGBfilter.h"

Dos Desarrollo del filtro

1. Generar GUID (ejecutar la herramienta Guiden en modo de línea de comando) Crear un archivo Y2Ruids.h para él como referencia única

#endif

#endif

#include Referencia

#include

// Objeto de filtro YUV2toRGB24

// {F91FC8FD-B1A6-49b0-A308-D6Edeaf405DA}

Definir_ GUID (CLSID_UV2TORGB24,

0xb1a6, 0x49b0, 0xd6, 0xd6, 0xd6, 0xed, 0xea , 0xf4, 0x5, 0xda);

2. Cree la clase CYUV2RGBfilter que hereda de CTransformFilter escrito en TransformFilter.

h

// ---------------------------------------- ------------------------------------

//Definición de clase de CYUV2RGBfilter

// ------------------------------------------ --- ----------------------------------

//

//

clase CYUV2RGBfilter: public CTransformFilter

{

public:

static CUnknown * WINAPI CreateInstance(LPUNKNOWN punk, HRESULT *phr );

STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);

DECLARE_IUNKNOWN;

// anular la función virtual pura

HRESULT CheckInputType(const CMediaType *mtIn);

HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut

HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp); );

HRESULT GetMediaType(int iPosition, CMediaType *pMediaType);

HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut);

privado:

//Constructor

CYUV2RGBfilter(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr);

//Función miembro

VOID ChangeFormat( AM_MEDIA_TYPE* ​​

CCritSec m_Y2RLock; // Acceso serializado.

};

3. Reescribe el formato del constructor

//

/// CNullInPlace::Constructor

///

.>CYUV2RGBfilter::CYUV2RGBfilter(TCHAR *tszName,LPUNKNOWN punk,HRESULT *phr) :

CTransformFilter(tszName, punk, CLSID_YUV2toRGB24),

m_lBufferRequest(1)

{

ASSERT(tszName);

ASSERT(phr);

}.// CYUV2RGBfilter

4. Reescribe las cinco funciones virtuales puras de CTransformFilter (la parte más importante)

HRESULT CheckInputType(const CMediaType *mtIn);

p>

HRESULT CheckTransform(const CMediaType *mtIn, const CMediaType * mtOut);

HRESULT DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProp);

HRESULT GetMediaType(int iPosition, const CMediaType *pMediaType);

HRESULT Transform(IMediaSample *pIn, IMediaSample *pOut);

5. Diseñe sus propias funciones privadas para implementar funciones específicas

6. Información del filtro de registro

//Información de registro

//Establecer datos

const AMOVIESETUP_MEDIATYPE

sudPinTypes = { &MEDIATYPE_Video / / clsMajorType

, & MEDIASUBTYPE_NULL }; // clsMinorType

const AMOVIESETUP_PIN

psudPins[] = { L "Entrada" // strName

, FALSE // bRenderizado

, FALSE // bSalida

, FALSE // bCero

, FALSE // bMuchos

, &CLSID_NULL // clsConnectsToFilter

, L "Salida" // strConnectsToPin

, 1 // nTypes

, &sudPinTypes } if(iPosition < 0)

{

return E_INVALIDARG;

}

// ¿Tenemos más artículos para ofrecer?

si (iPosition < 0)

{

return VFW_S_NO_MORE_ITEMS;

}

CheckPointer(pMediaType,E_POINTER);

si (iPosit

ion == 0)

{

HRESULT hr = m _pInput->ConnectionMediaType(pMediaType);

if (FAILED(hr))

{

return hr;

}

}

// Realiza los cambios apropiados

ASSERT (pMediaType->formattype == FORMAT_VideoInfo);

pMediaType->subtipo = MEDIASUBTYPE_RGB24;

VIDEOINFOHEADER *pVih =

reinterpret_cast(pMediaType->pbFormat);

pVih->bmiHeader.biCompression = 0;

pVih->bmiHeader.biSizeImage = DIBSIZE(pVih->bmiHeader);

pVih->bmiHeader. biBitCount = 24;

pVih->bmiHeader.biHeight = 480;

pVih->bmiHeader.biWidth = 640;

devuelve S_OK;

}. // GetMediaType

//

// CheckInputType

//

// Compruebe si el tipo de entrada es normal; de lo contrario, se devuelve el error

//

HRESULT CYUV2RGBfilter:: CheckInputType( const CMediaType *mtIn)

{

CheckPointer(mtIn,E_POINTER );

p>

// Compruebe que este sea un tipo VIDEOINFO

if(*mtIn->FormatType( ) != FORMAT_VideoInfo)

{

Devuelve E_INVALIDARG ;

}

if((IsEqualGUID(*mtIn->Type( ), MEDIATYPE_Video)) &&

(IsEqualGUID( *mtIn->Subtipo( ), MEDIASUBTYPE_YUY2)))

{

VIDEOINFO *pvi = (VIDEOINFO *) mtIn->Formato();

if ((pvi ->bmiHeader .biBitCount == 16)

&&(pvi ->bmiHeader.biCompression==0))

Devuelve S_OK;

De lo contrario

Devuelve FALSO;

}

En caso contrario

{

Devuelve FALSO;

}

}

}// CheckInputType

/// CheckTransform

/////////// ////// ////// Los formatos que se pueden convertir deben ser compatibles.

Los formatos que se pueden convertir deben ser compatibles

//mtIn YUV2 16bit

//mtOut RGB24 24bit

HRESULT CYUV2RGBfilter::.CheckTransform(const CMediaType * mtIn, const CMediaType *mtOut)

{

CheckPointer(mtIn,E_POINTER);

CheckPointer(mtOut,E_POINTER);

HRESULT hora ;

if(FAILED(hr = CheckInputType(mtIn)))

{

return hora;

}

// el formato debe ser VIDEOINFOHEADER

if((*mtOut->FormatType() != FORMAT_VideoInfo)

||(mtOut->cbFormat

|(mtOut->subtype!=MEDIASUBTYPE_RGB24))

{

return E_INVALIDARG;

}

BITMAPINFOHEADER *pBmiOut = HEADER(mtOut->pbFormat);

if ((pBmiOut->biPlanes!=1)

||(pBmiOut ->biBitCount !=24)

||(pBmiOut->biCompression!=0)

||(pBmiOut->biWidth!=640)

||( pBmiOut->biHeight! gt;biHeight! =480))

{

Regresar E_INVALIDARG;

}

Regresar S_OK;

}

// CheckTransform

HRESULT CYUV2RGBfilter:: DecideBufferSize(IMemAllocator *pAlloc, ALLOCATOR_PROPERTIES *pProperties)

{

CheckPointer(pAlloc,E_ POINTER);

CheckPointer(pProperties,E_POINTER);

// Si el pin de entrada está conectado

if(m_pInput ->IsConnected() == FALSE)

{

Devuelve E_UNEXPECTED;

}

HRESULT hr = NOERROR ;

p>

pProperties->cBuffers = 1;

pProperties->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize()*2 // La salida es el doble de la entrada; sample

ASSERT(pProperties->cbBuffer);

// Si no tenemos un tamaño de muestra fijo, tenemos que adivinar algún tamaño<

/p>

if(!m_pInput->CurrentMediaType().bFixedSizeSamples)

{

if(! pProperties->cbBuffer < 100000)

{

// ¡¡¡Sólo una suposición!!!!!

pProperties->cbBuffer = 100000;

}

}

}

// Requerir reserva del asignador algunos ejemplos de memoria para nosotros, tenga en cuenta la función

// pProperties->cbBuffer = 100000.

// El asignador puede tener éxito (es decir, devolver NOERROR) pero aún no asignar a la memoria solicitamos

// Entonces tenemos que verificar si obtuvimos la memoria que queríamos

ALLOCATOR_PROPERTIES Actual;

hr = pAlloc->SetProperties( pProperties,&Actual );

if(FAILED(hr))

{

return hr;

}

ASERT (Actual.cBuffers == 1);

if(pProperties->cBuffers > Actual.cBuffers ||

pProperties->.// DecideBufferSize

/

/

// Transformar

//

// Copiar la muestra de entrada en la muestra de salida

///

///

HRESULT CYUV2RGBfilter::Transform( IMediaSample *pIn, IMediaSample *pOut)

{

CheckPointer(pIn,E_POINTER);

CheckPointer(pOut,E_POINTER);

// Copiar datos de muestra

BYTE *pSourceBuffer, *pDestBuffer

largo lSourceSize = pIn->GetActualDataLength();

largo lDestSize = (largo) ( lSourceSize*1.5);

pIn->GetPointer(&pSourceBuffer) ;

pOut->GetPointer(&pDestBuffer);

//Cambiar datos

ConvertYUV2toRGB(pSourceBuffer,pDestBuffer,lSourceSize);

/memset( pDestBuffer,100,lDestSize);

REFERENCE_TIME TimeStart, TimeEnd;

if(NOERROR == pIn->GetTime(&TimeStart, &TimeEnd))

{

pOut->SetTime(&TimeStart, &TimeEnd

); & amp;TimeEnd);

}

LARGO MediaStart, MediaEnd;

if(pIn->GetMediaTime(&MediaStart,&MediaEnd) == NOERROR)

{

pOut->SetMediaTime(&MediaStart,&MediaEnd);

}

// Copiar atributos del punto de sincronización

HRESULT hr = pIn-> IsSyncPoint();

if(hr == S_OK)

{

pOut->SetSyncPoint(TRUE) ;

}

else if(hr == S_FALSE)

{

pOut ->SetSyncPoint(FALSE);

}

else

{ // Se produjo un error inesperado. ..

return E_UNEXPECTED;

}

//

AM_MEDIA_TYPE* ​​​​pMediaType;

pIn -> GetMediaType(& pMediaType);

ChangeFormat(pMediaType);

// Copiar tipo de medio

pOut->SetMediaType(pMediaType);

// Copiar atributos pre-roll

hr = pIn->IsPreroll();

if(hr == S_OK)

{

pOut->SetPreroll(TRUE);

}

else if(hr == S_FALSE)

{

pOut- >SetPreroll( FALSE);

}

else

{ // Se produjo un error inesperado. ..

return E_UNEXPECTED;

}

// Copiar atributos discontinuos

hr = pIn->IsDiscontinuity();

p>

if(hr == S_OK)

{

pOut->SetDiscontinuity(TRUE);

}

else if(hr == S_FALSE)

{

pOut->SetDiscontinuity(FALSE);

p> }

else

{ // Se produjo un error inesperado. ..

Devuelve E_UNEXPECTED;

}

// Copia la longitud real de los datos

//KASSERT((long)lDestSize < = pOut->GetSize());

pOut->SetActualDataLength(lDestSize);

Devuelve S_OK;

}. // Transformación

Después de seguir estos pasos, puede obtener un filtro de transformación que cumpla con los requisitos funcionales

Además, después de seguir estos pasos, también podrá comprender cómo desarrollar el filtro.

De /s/blog_693301190100vusf.html

Estos pasos le brindarán una descripción general de cómo desarrollar un filtro.