📄 teletextoutputpin.cpp
字号:
/*
(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 + -