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

📄 teletextoutputpin.cpp

📁 Teletext module usually used in the DVB area.
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* 

(C) Luke Paton 2004.

Copyright notice:

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/
#include "stdafx.h"
#include "resource.h"
#include "DVBTeletextSubtitles.h"
#include "DVBSubtitlesFilter.h"
#include "DVBTeletextSubtitlesPropertiesPage1.h"

CTeletextOutputPin::CTeletextOutputPin
(
    TCHAR       *pObjectName,
    CBaseFilter *pFilter,
	CCritSec	*pLock,
    HRESULT     *phr,
    LPCWSTR     pName
) 
: 
    CSourceStream(pObjectName, phr, (CSource*)pFilter, pName)
    ,m_rtFrameLength(FPS_1) // Display 5 bitmap frames per second
    , m_nWidth(768)
    , m_nHeight(576)
    , m_DC(NULL)
    , m_OldObject(NULL)
	,m_CurrentFont(NULL)
	,m_SupplementaryFont(NULL)
	,m_OldFont(NULL)
	,m_Bitmap(NULL)
	,m_TextMode(OPAQUE)
    ,m_EventDataReady(TRUE) // must be manual-reset
	, m_FirstReferenceTimeMilliseconds(0)
{
}

CTeletextOutputPin::~CTeletextOutputPin(void)
{
    if( m_OldObject )
    {
        SelectObject(m_DC, m_OldObject);
        m_OldObject = NULL;
    }
	
	if (m_OldFont != NULL)
	{
        SelectObject(m_DC, m_OldFont);
        m_OldFont = NULL;
	}

	if (m_CurrentFont != NULL)
	{
		DeleteObject(m_CurrentFont);
	}

	if (m_SupplementaryFont != NULL)
	{
		DeleteObject(m_SupplementaryFont);
	}

    if (m_DC != NULL)
    {
        DeleteDC(m_DC);
        m_DC = NULL;
    }

	if (m_Bitmap)
    {
        DeleteObject(m_Bitmap);
        m_Bitmap = NULL;
    }
}

//
// GetMediaType
//
// Prefer 5 formats - 8, 16 (*2), 24 or 32 bits per pixel
//
// Prefered types should be ordered by quality, with zero as highest quality.
// Therefore, iPosition =
//      0    Return a 32bit mediatype
//      1    Return a 24bit mediatype
//      2    Return 16bit RGB565
//      3    Return a 16bit mediatype (rgb555)
//      4    Return 8 bit palettised format
//      >4   Invalid
//
HRESULT CTeletextOutputPin::GetMediaType(int iPosition, CMediaType *pmt)
{
    CheckPointer(pmt,E_POINTER);
    CAutoLock cAutoLock(m_pLock);

    if(iPosition < 0)
        return E_INVALIDARG;

    // Have we run off the end of types?
    if(iPosition > 4)
        return VFW_S_NO_MORE_ITEMS;

    VIDEOINFO *pvi = (VIDEOINFO *) pmt->AllocFormatBuffer(sizeof(VIDEOINFO));
    if(NULL == pvi)
        return(E_OUTOFMEMORY);

    // Initialize the VideoInfo structure before configuring its members
    ZeroMemory(pvi, sizeof(VIDEOINFO));

    switch(iPosition)
    {
        case 0:
        {    
            // Return our highest quality 32bit format

            // Since we use RGB888 (the default for 32 bit), there is
            // no reason to use BI_BITFIELDS to specify the RGB
            // masks. Also, not everything supports BI_BITFIELDS
            pvi->bmiHeader.biCompression = BI_RGB;
            pvi->bmiHeader.biBitCount    = 32;
            break;
        }

        case 1:
        {   // Return our 24bit format
            pvi->bmiHeader.biCompression = BI_RGB;
            pvi->bmiHeader.biBitCount    = 24;
            break;
        }

        case 2:
        {       
            // 16 bit per pixel RGB565

            // Place the RGB masks as the first 3 doublewords in the palette area
            for(int i = 0; i < 3; i++)
                pvi->TrueColorInfo.dwBitMasks[i] = bits565[i];

            pvi->bmiHeader.biCompression = BI_BITFIELDS;
            pvi->bmiHeader.biBitCount    = 16;
            break;
        }

        case 3:
        {   // 16 bits per pixel RGB555

            // Place the RGB masks as the first 3 doublewords in the palette area
            for(int i = 0; i < 3; i++)
                pvi->TrueColorInfo.dwBitMasks[i] = bits555[i];

            pvi->bmiHeader.biCompression = BI_BITFIELDS;
            pvi->bmiHeader.biBitCount    = 16;
            break;
        }

        case 4:
        {   // 8 bit palettised

            pvi->bmiHeader.biCompression = BI_RGB;
            pvi->bmiHeader.biBitCount    = 8;
            pvi->bmiHeader.biClrUsed     = iPALETTE_COLORS;
            break;
        }
    }

    // Adjust the parameters common to all formats
    pvi->bmiHeader.biSize       = sizeof(BITMAPINFOHEADER);
    pvi->bmiHeader.biWidth      = m_nWidth;
    pvi->bmiHeader.biHeight     = m_nHeight;
    pvi->bmiHeader.biPlanes     = 1;
    pvi->bmiHeader.biSizeImage  = GetBitmapSize(&pvi->bmiHeader);
    pvi->bmiHeader.biClrImportant = 0;

    SetRectEmpty(&(pvi->rcSource)); // we want the whole image area rendered.
	pvi->rcSource.right = m_nWidth;
	pvi->rcSource.bottom = m_nHeight;

    SetRectEmpty(&(pvi->rcTarget)); // no particular destination rectangle
	pvi->rcTarget.right = m_nWidth;
	pvi->rcTarget.bottom = m_nHeight;

    pmt->SetType(&MEDIATYPE_Video);
    pmt->SetFormatType(&FORMAT_VideoInfo);
    pmt->SetTemporalCompression(FALSE);

    // Work out the GUID for the subtype from the header info.
    const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
    pmt->SetSubtype(&SubTypeGUID);
    pmt->SetSampleSize(pvi->bmiHeader.biSizeImage);

    return NOERROR;

} // GetMediaType


//
// CheckMediaType
//
// We will accept 8, 16, 24 or 32 bit video formats, in any
// image size that gives room to bounce.
// Returns E_INVALIDARG if the mediatype is not acceptable
//
HRESULT CTeletextOutputPin::CheckMediaType(const CMediaType *pMediaType)
{
    CheckPointer(pMediaType,E_POINTER);

    if((*(pMediaType->Type()) != MEDIATYPE_Video) ||   // we only output video
        !(pMediaType->IsFixedSize()))                  // in fixed size samples
    {                                                  
        return E_INVALIDARG;
    }

    // Check for the subtypes we support
    const GUID *SubType = pMediaType->Subtype();
    if (SubType == NULL)
        return E_INVALIDARG;

    if(    (*SubType != MEDIASUBTYPE_RGB8)
        && (*SubType != MEDIASUBTYPE_RGB565)
        && (*SubType != MEDIASUBTYPE_RGB555)
        && (*SubType != MEDIASUBTYPE_RGB24)
        && (*SubType != MEDIASUBTYPE_RGB32))
    {
        return E_INVALIDARG;
    }

    // Get the format area of the media type
    VIDEOINFO *pvi = (VIDEOINFO *) pMediaType->Format();

    if(pvi == NULL)
        return E_INVALIDARG;

    // Check if the image width & height have changed
    if
    (
        (pvi->bmiHeader.biWidth != m_nWidth)
        || 
        (abs(pvi->bmiHeader.biHeight) != m_nHeight)
    )
    {
        // If the image width/height is changed, fail CheckMediaType() to force
        // the renderer to resize the image.
        return E_INVALIDARG;
    }

    // Don't accept formats with negative height, which would cause the desktop
    // image to be displayed upside down.
    if (pvi->bmiHeader.biHeight < 0)
        return E_INVALIDARG;

    return S_OK;  // This format is acceptable.

}

//
// DecideBufferSize
//
// This will always be called after the format has been sucessfully
// negotiated. So we have a look at m_mt to see what size image we agreed.
// Then we can ask for buffers of the correct size to contain them.
//
HRESULT CTeletextOutputPin::DecideBufferSize
(
    IMemAllocator *pAlloc,
    ALLOCATOR_PROPERTIES *pProperties
)
{
    CheckPointer(pAlloc,E_POINTER);
    CheckPointer(pProperties,E_POINTER);

    CAutoLock cAutoLock(m_pLock);
    HRESULT hr = NOERROR;

    VIDEOINFO *pvi = (VIDEOINFO *) m_mt.Format();
    pProperties->cBuffers = 1;
    pProperties->cbBuffer = pvi->bmiHeader.biSizeImage;

    ASSERT(pProperties->cbBuffer);

    // Ask the allocator to reserve us some sample memory. NOTE: the function
    // can succeed (return NOERROR) but still not have allocated the
    // memory that we requested, so we must check we got whatever we wanted.
    ALLOCATOR_PROPERTIES Actual;
    hr = pAlloc->SetProperties(pProperties,&Actual);
    if(FAILED(hr))
    {
        return hr;
    }

    // Is this allocator unsuitable?
    if(Actual.cbBuffer < pProperties->cbBuffer)
    {
        return E_FAIL;
    }

    // Make sure that we have only 1 buffer (we erase the ball in the
    // old buffer to save having to zero a 200k+ buffer every time
    // we draw a frame)
    ASSERT(Actual.cBuffers == 1);
    return NOERROR;

} // DecideBufferSize

//
// SetMediaType
//
// Called when a media type is agreed between filters
//
HRESULT CTeletextOutputPin::SetMediaType(const CMediaType *pMediaType)
{
    CAutoLock cAutoLock(m_pLock);

    // Pass the call up to my base class
    HRESULT hr = CSourceStream::SetMediaType(pMediaType);

    if(SUCCEEDED(hr))
    {
        VIDEOINFO * pvi = (VIDEOINFO *) m_mt.Format();
        if (pvi == NULL)
            return E_UNEXPECTED;

        switch(pvi->bmiHeader.biBitCount)
        {
            case 8:     // 8-bit palettized
            case 16:    // RGB565, RGB555
            case 24:    // RGB24
            case 32:    // RGB32
                hr = S_OK;
                break;

            default:
                // We should never agree any other media types
                ASSERT(FALSE);
                hr = E_INVALIDARG;
                break;
        }
    } 

    return hr;

} // SetMediaType

// This is where we insert the DIB bits into the video stream.
// FillBuffer is called once for every sample in the stream.
HRESULT CTeletextOutputPin::FillBuffer(IMediaSample *pSample)
{
	CheckPointer(pSample, E_POINTER);

	CAutoLock cAutoLockShared(&m_cSharedState);

	// Check that we're still using video
	ASSERT(m_mt.formattype == FORMAT_VideoInfo);

	int column_width = m_nWidth / 40;
	int row_height = m_nHeight / 25;



	if (m_Bitmap == NULL)
	{
		CComPtr<IBaseFilter> overlay_mixer;
		((CDVBTeletextSubtitles*)m_pFilter)->m_pGraph->FindFilterByName(L"Overlay Mixer", &overlay_mixer);

        if (overlay_mixer != NULL)
        {
		    CComPtr<IEnumPins> pEnumPins;
		    overlay_mixer->EnumPins(&pEnumPins);

		    ULONG fetched;

		    int count = 0;

		    HRESULT hr = pEnumPins->Reset();

		    CComPtr<IPin> overlay_mixer_input_pin;
		    while (overlay_mixer_input_pin.Release(), S_OK == pEnumPins->Next(1, &overlay_mixer_input_pin, &fetched))
		    {
			    PIN_DIRECTION dir;
			    hr = overlay_mixer_input_pin->QueryDirection( &dir );
			    if (FAILED(hr) || (PINDIR_OUTPUT == dir))
			    {
				    continue;
			    }

			    if (count == 0)
			    {
				    CComPtr<IMixerPinConfig> mix_config;
				    overlay_mixer_input_pin->QueryInterface(IID_IMixerPinConfig2, (LPVOID*)&mix_config) ;
				    if (mix_config != NULL)
				    {
					    hr = mix_config->SetZOrder(0);
					    hr = mix_config->SetRelativePosition(0, 0, 10000, 10000);

					    COLORKEY cc;
					    COLORREF result;
					    hr = mix_config->GetColorKey(&cc, &result);

                        ((CDVBTeletextSubtitles*)m_pFilter)->m_Colours[Colour_Key] = result;
				    }

				    count++;
				    continue;
			    }

			    if (count == 1)
			    {
				    CComPtr<IMixerPinConfig> mix_config;
				    overlay_mixer_input_pin->QueryInterface(IID_IMixerPinConfig2, (LPVOID*)&mix_config) ;
				    if (mix_config != NULL)
				    {
					    hr = mix_config->SetStreamTransparent(TRUE);
					    hr = mix_config->SetZOrder(1);

⌨️ 快捷键说明

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