www.pudn.com > VirtualVCR-src-v2.6.9.zip > Histogram.cpp
/*
Virtual VCR
Copyright (C) 2002 Shaun Faulds
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.
Acknowledgments:
This application and associated filters are based on the examples
from the Microsoft DirectX DirectShow SDK.
*/
#include
#include
#include
#if (1100 > _MSC_VER)
#include
#else
#include
#endif
#include "HistogramUIDs.h"
#include "iHistogram.h"
#include "HistogramProp.h"
#include "Histogram.h"
#include "resource.h"
#include "../Common/Filter/iFilterProperties.h"
#include "Histogram.version"
#include "colourFormats.h"
// Setup information
const AMOVIESETUP_MEDIATYPE sudPinTypes =
{
&MEDIATYPE_Video, // Major type
&MEDIASUBTYPE_NULL // Minor type
};
const AMOVIESETUP_PIN sudpPins[] =
{
{ L"Input", // Pins string name
FALSE, // Is it rendered
FALSE, // Is it an output
FALSE, // Are we allowed none
FALSE, // And allowed many
&CLSID_NULL, // Connects to filter
NULL, // Connects to pin
1, // Number of types
&sudPinTypes // Pin information
},
{ L"Output", // Pins string name
FALSE, // Is it rendered
TRUE, // Is it an output
FALSE, // Are we allowed none
FALSE, // And allowed many
&CLSID_NULL, // Connects to filter
NULL, // Connects to pin
1, // Number of types
&sudPinTypes // Pin information
}
};
const AMOVIESETUP_FILTER sudHistogram =
{
&CLSID_Histogram, // Filter CLSID
L"Colour Histogram", // String name
MERIT_DO_NOT_USE, // Filter merit
2, // Number of pins
sudpPins // Pin information
};
// List of class IDs and creator functions for the class factory. This
// provides the link between the OLE entry point in the DLL and an object
// being created. The class factory will call the static CreateInstance
CFactoryTemplate g_Templates[] = {
{ L"Colour Histogram"
, &CLSID_Histogram
, CHistogram::CreateInstance
, NULL
, &sudHistogram }
,
{ L"Colour Histogram"
, &CLSID_HistogramPropertyPage
, CHistogramProperties::CreateInstance }
};
int g_cTemplates = sizeof(g_Templates) / sizeof(g_Templates[0]);
//
// DllRegisterServer
//
// Handles sample registry and unregistry
//
STDAPI DllRegisterServer()
{
return AMovieDllRegisterServer2( TRUE );
} // DllRegisterServer
//
// DllUnregisterServer
//
STDAPI DllUnregisterServer()
{
return AMovieDllRegisterServer2( FALSE );
} // DllUnregisterServer
//
// Constructor
//
CHistogram::CHistogram(TCHAR *tszName,
LPUNKNOWN punk,
HRESULT *phr) :
CTransformFilter(tszName, punk, CLSID_Histogram)
{
Channels = true;
ChannelSelection = 7;
output_width = 268;
output_height = 210;
inputColourFormat = 0;
channel01 = new LONG[256];
channel02 = new LONG[256];
channel03 = new LONG[256];
} // (Constructor)
//
// Constructor
//
CHistogram::~CHistogram()
{
// Delete the pixel arrays from the heap
delete[] channel01;
delete[] channel02;
delete[] channel03;
}
//
// CreateInstance
//
// Provide the way for COM to create a EZrgb24 object
//
CUnknown *CHistogram::CreateInstance(LPUNKNOWN punk, HRESULT *phr)
{
CHistogram *pNewObject = new CHistogram(NAME("Colour Histogram"), punk, phr);
if (pNewObject == NULL)
{
*phr = E_OUTOFMEMORY;
}
return pNewObject;
} // CreateInstance
//
// NonDelegatingQueryInterface
//
// Reveals IIPEffect and ISpecifyPropertyPages
//
STDMETHODIMP CHistogram::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
CheckPointer(ppv,E_POINTER);
if (riid == IID_IHistogram)
{
return GetInterface((IHistogram *) this, ppv);
}
else if (riid == IID_IFilterProperties)
{
return GetInterface((IFilterProperties *) this, ppv);
}
else if (riid == IID_ISpecifyPropertyPages)
{
return GetInterface((ISpecifyPropertyPages *) this, ppv);
}
else
{
return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
}
} // NonDelegatingQueryInterface
//
// Transform
//
HRESULT CHistogram::Transform(IMediaSample *pIn, IMediaSample *pOut)
{
//
// Perpare output sample.
// Use the local method to copy sample times etc
// from input sample to the output sample
//
HRESULT result = S_OK;
//result = this->PrepareOutputSample(pIn, pOut);
if (result != S_OK) return result;
int output_size = output_height * output_width * 24;
pOut->SetActualDataLength(output_size);
// Zero all the data in the colour arrays
memset(channel01, 0, 256*sizeof(channel01[0]));
memset(channel02, 0, 256*sizeof(channel02[0]));
memset(channel03, 0, 256*sizeof(channel03[0]));
LONG maxRGB = CountPixels(pIn, channel01, channel02, channel03);
if(inputColourFormat == 1)
result = DrawHistogramRGB(pOut, maxRGB, channel01, channel02, channel03);
else if(inputColourFormat == 2)
result = DrawHistogramLUM(pOut, maxRGB, channel01, channel02, channel03);
return NOERROR;
} // Transform
////////////////////////////////////////////////////////////
// Take the information from the pixel arrays and draw it
// to an output media sample to be rendered to a video
// render filter
////////////////////////////////////////////////////////////
HRESULT CHistogram::DrawHistogramRGB(
IMediaSample *pOutput,
LONG rgbMax,
LONG *pixel01,
LONG *pixel02,
LONG *pixel03)
{
BYTE *pData;
pOutput->GetPointer(&pData);
RGBTRIPLE *prgb;
prgb = (RGBTRIPLE*) pData;
// offset the Histogram in output window
int offsetX = 5;
int offsetY = 5;
LONG maxRGBValue = rgbMax;
for (int y = 0; y < 200; y++)
{
for (int x = 0; x < 256; x++)
{
PlotPixel(0, 0, 0, 0, (x + offsetX), (y + offsetY), prgb, output_width, output_height);
if(Channels)
{
if((ChannelSelection & 1) == 1)
{
if(pixel01[x] > ((maxRGBValue * (200-y)) / 200))
{
PlotPixel(250, 0, 0, 50, (x + offsetX), (y + offsetY), prgb, output_width, output_height);
}
}
if((ChannelSelection & 2) == 2)
{
if(pixel02[x] > ((maxRGBValue * (200-y)) / 200))
{
PlotPixel(0, 250, 0, 50, (x + offsetX), (y + offsetY), prgb, output_width, output_height);
}
}
if((ChannelSelection & 4) == 4)
{
if(pixel03[x] > ((maxRGBValue * (200-y)) / 200))
{
PlotPixel(0, 0, 250, 50, (x + offsetX), (y + offsetY), prgb, output_width, output_height);
}
}
}
else
{
LONG lum = 0;
// Use r%22 g%71 b%7 as the calculation
lum = ((pixel01[x] * 22) + (pixel02[x] * 71) + (pixel03[x] * 7)) / 100;
if(lum > ((maxRGBValue * (200-y)) / 200))
PlotPixel(250, 250, 250, 50, x+offsetX, y+offsetY, prgb, output_width, output_height);
}
// Draw the box around the histogram
// if(x == 0)
// PlotPixel(255, 255, 255, 0, (x + offsetX - 1), (y + offsetY), prgb, output_width, output_height);
// if(x == 255)
// PlotPixel(255, 255, 255, 0, (x + offsetX + 1), (y + offsetY), prgb, output_width, output_height);
if(y == 0 || y == 199)
PlotPixel(255, 255, 255, 0, (x + offsetX), (y + offsetY), prgb, output_width, output_height);
}
}
return NOERROR;
}
HRESULT CHistogram::DrawHistogramLUM(
IMediaSample *pOutput,
LONG rgbMax,
LONG *pixel01,
LONG *pixel02,
LONG *pixel03)
{
BYTE *pData;
pOutput->GetPointer(&pData);
RGBTRIPLE *prgb;
prgb = (RGBTRIPLE*) pData;
// offset the Histogram in output window
int offsetX = 5;
int offsetY = 5;
LONG maxRGBValue = rgbMax;
for (int y = 0; y < 200; y++)
{
for (int x = 0; x < 256; x++)
{
PlotPixel(0, 0, 0, 0, (x + offsetX), (y + offsetY), prgb, output_width, output_height);
if(pixel01[x] > ((maxRGBValue * (200-y)) / 200))
{
PlotPixel(200, 200, 200, 0, (x + offsetX), (y + offsetY), prgb, output_width, output_height);
}
if(y == 0 || y == 199)
PlotPixel(255, 255, 255, 0, (x + offsetX), (y + offsetY), prgb, output_width, output_height);
}
}
return NOERROR;
}
//////////////////////////////////////////////////////
// Count the pixel colour numbers for building the Histogram
//////////////////////////////////////////////////////
LONG CHistogram::CountPixels(IMediaSample *pMediaSample,
LONG *pixelArray01,
LONG *pixelArray02,
LONG *pixelArray03)
{
BYTE *pData;
// long lDataLen;
LONG maxValue = 0;
pMediaSample->GetPointer(&pData);
// lDataLen = pMediaSample->GetSize();
int cxImage = input_width;
int cyImage = input_height;
int numPixels = cxImage * cyImage;
if(inputColourFormat == 1) // RGB24 colour format
{
RGBTRIPLE *prgb;
prgb = (RGBTRIPLE*) pData;
for (int iPixel = 0; iPixel < numPixels; iPixel++, prgb++)
{
//Count all the occurances of the colours to work out frequency for each colour
pixelArray01[prgb->rgbtRed]++;
if(pixelArray01[prgb->rgbtRed] > maxValue) maxValue = pixelArray01[prgb->rgbtRed];
pixelArray02[prgb->rgbtGreen]++;
if(pixelArray02[prgb->rgbtGreen] > maxValue) maxValue = pixelArray02[prgb->rgbtGreen];
pixelArray03[prgb->rgbtBlue]++;
if(pixelArray03[prgb->rgbtBlue] > maxValue) maxValue = pixelArray03[prgb->rgbtBlue];
}
}
else if(inputColourFormat == 2) // YUY2 colour format
{
YUY2 *pyuy2;
pyuy2 = (YUY2*) pData;
for (int iPixel = 0; iPixel < numPixels; iPixel += 2, pyuy2++)
{
// YUY2 colour format
// Y0 V0 Y1 U0
// pixel 1 = Y0 U V
// pixel 2 = Y1 U V
// Y is brightness or luminesces
// U is the colour difference from main luminesces for blue
// V is the colour difference from main luminesces for red
// Green is calculated
/*
Here are some test conversion for YUV to RGB
Very slow at the moment need to MMX them
int red1 = (int)((double)pyuy2->Y0 + (double)((double)1.403 * (double)(pyuy2->V0-128)));
int green1 = pyuy2->Y0 - (0.344 * (double)(pyuy2->U0-128)) - (0.714 * (double)(pyuy2->V0-128));
int blue1 = pyuy2->Y0 + (1.770 * (double)(pyuy2->U0-128));
int red2 = pyuy2->Y1 + (1.403 * (double)pyuy2->V0);
int green2 = pyuy2->Y1 - (0.344 * (double)(pyuy2->U0-128)) - (0.714 * (double)(pyuy2->V0-128));
int blue2 = pyuy2->Y1 + (1.770 * (double)(pyuy2->U0-128));
if(red1 < 0) red1 = 0;
if(red1 > 255) red1 = 255;
if(green1 < 0) green1 = 0;
if(green1 > 255) green1 = 255;
if(blue1 < 0) blue1 = 0;
if(blue1 > 255) blue1 = 255;
//Count all the occurances of the colours to work out frequency for each colour
pixelArray01[red1]++;
if(pixelArray01[red1] > maxValue) maxValue = pixelArray01[red1];
pixelArray02[green1]++;
if(pixelArray02[green1] > maxValue) maxValue = pixelArray02[green1];
pixelArray03[blue1]++;
if(pixelArray03[blue1] > maxValue) maxValue = pixelArray03[blue1];
*/
// First Pixel Lumanence
pixelArray01[pyuy2->Y0]++;
if(pixelArray01[pyuy2->Y0] > maxValue) maxValue = pixelArray01[pyuy2->Y0];
// Second Pixel Lumanence
pixelArray01[pyuy2->Y1]++;
if(pixelArray01[pyuy2->Y1] > maxValue) maxValue = pixelArray01[pyuy2->Y1];
}
}
return maxValue;
}
//////////////////////////////////////////////////////////////
// Plot a pixel to an array of RGB triples, this is raw output
// data in a Media Sample
//////////////////////////////////////////////////////////////
HRESULT CHistogram::PlotPixel(int red, int green, int blue, int alpha, int x, int y, RGBTRIPLE *pixel, int width, int height)
{
y = height - y - 1;
pixel += x + (width * y);
red = ((red * (255-alpha)) / 255) + ((pixel->rgbtRed * alpha) / 255);
blue = ((blue * (255-alpha)) / 255) + ((pixel->rgbtGreen * alpha) / 255);
green = ((green * (255-alpha)) / 255) + ((pixel->rgbtGreen * alpha) / 255);
pixel->rgbtRed = red;
pixel->rgbtGreen = green;
pixel->rgbtBlue = blue;
return NOERROR;
}
// Check the input type is OK - return an error otherwise
HRESULT CHistogram::CheckInputType(const CMediaType *mtIn)
{
// check this is a VIDEOINFOHEADER type
// allow any video format for input
// If this filter does not know how to process
// it it will just give a blnak histogram
if (*mtIn->FormatType() != FORMAT_VideoInfo)
{
return E_INVALIDARG;
}
return S_OK;
}
//
// Checktransform
//
// Check a transform can be done between these formats
//
HRESULT CHistogram::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
{
// Only connect with a valid input and output format
// In this case any video input but only RGB24 video output
if (IsEqualGUID(*mtIn->Type(), MEDIATYPE_Video) &&
IsEqualGUID(*mtOut->Type(), MEDIATYPE_Video) &&
IsEqualGUID(*mtOut->Subtype(), MEDIASUBTYPE_RGB24))
{
return S_OK;
}
return E_FAIL;
} // CheckTransform
//
// DecideBufferSize
//
// Tell the output pin's allocator what size buffers we
// require. Can only do this when the input is connected
//
HRESULT CHistogram::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
{
// Is the input pin connected
if (m_pInput->IsConnected() == FALSE)
{
return E_UNEXPECTED;
}
ASSERT(pAlloc);
ASSERT(pProperties);
HRESULT hr = NOERROR;
pProperties->cBuffers = 1;
pProperties->cbBuffer = m_pInput->CurrentMediaType().GetSampleSize();
ASSERT(pProperties->cbBuffer);
// Ask the allocator to reserve us some sample memory, NOTE the function
// can succeed (that is 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;
}
ASSERT( Actual.cBuffers == 1 );
if (pProperties->cBuffers > Actual.cBuffers ||
pProperties->cbBuffer > Actual.cbBuffer)
{
return E_FAIL;
}
return NOERROR;
} // DecideBufferSize
//
// GetMediaType
//
// I support one type, namely the type of the input pin
// This type is only available if my input is connected
//
HRESULT CHistogram::GetMediaType(int iPosition, CMediaType *pMediaType)
{
if (iPosition < 0)
{
return E_INVALIDARG;
}
// Have we run off the end of types
if (iPosition > 0)
{
return VFW_S_NO_MORE_ITEMS;
}
VIDEOINFO *pvi = (VIDEOINFO *) pMediaType->AllocFormatBuffer(sizeof(VIDEOINFO));
if (NULL == pvi)
{
return(E_OUTOFMEMORY);
}
ZeroMemory(pvi, sizeof(VIDEOINFO));
// Set for 24 bit RGB
pvi->bmiHeader.biCompression = BI_RGB;
pvi->bmiHeader.biBitCount = 24;
pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biWidth = output_width;
pvi->bmiHeader.biHeight = output_height;
pvi->bmiHeader.biPlanes = 1;
pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
pvi->bmiHeader.biClrImportant = 0;
SetRectEmpty(&(pvi->rcSource)); // we want the whole image area rendered.
SetRectEmpty(&(pvi->rcTarget)); // no particular destination rectangle
pMediaType->SetType(&MEDIATYPE_Video);
pMediaType->SetFormatType(&FORMAT_VideoInfo);
pMediaType->SetTemporalCompression(FALSE);
// Work out the GUID for the subtype from the header info.
const GUID SubTypeGUID = GetBitmapSubtype(&pvi->bmiHeader);
pMediaType->SetSubtype(&SubTypeGUID);
pMediaType->SetSampleSize(pvi->bmiHeader.biSizeImage);
return NOERROR;
} // GetMediaType
//
// GetPages
//
// Returns the clsid's of the property pages we support
//
STDMETHODIMP CHistogram::GetPages(CAUUID *pPages)
{
pPages->cElems = 1;
pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID));
if (pPages->pElems == NULL)
{
return E_OUTOFMEMORY;
}
*(pPages->pElems) = CLSID_HistogramPropertyPage;
return NOERROR;
} // GetPages
// Interfave Methods to get set the colour analisys options
STDMETHODIMP CHistogram::get_Channel(BOOL *Channel)
{
*Channel = Channels;
return NOERROR;
}
STDMETHODIMP CHistogram::set_Channel(BOOL Channel)
{
Channels = Channel;
return NOERROR;
}
STDMETHODIMP CHistogram::get_RGBmask(int *mask)
{
*mask = ChannelSelection;
return NOERROR;
}
STDMETHODIMP CHistogram::set_RGBmask(int mask)
{
ChannelSelection = mask;
return NOERROR;
}
//This is for the common interface IFilterProperties
//
// Gets the data properties
//
STDMETHODIMP CHistogram::get_Prop(char*& data)
{
char filterData[1024];
wsprintf(filterData, "none");
data = filterData;
return NOERROR;
}
//
// Sets the Data for properties
//
STDMETHODIMP CHistogram::set_Prop(char* data)
{
return NOERROR;
}
STDMETHODIMP CHistogram::get_Version(char *data)
{
wsprintf(data, "%s", MAIN_VERSION);
return NOERROR;
}
/////////////////////////////////////////////////////////////////////////
// Media type setup functions
//
// SetMediaType is called on the base filter when pins are connected
// the pin direction and a media type object ointer are passed to it.
//
// The GetInputMediaType type is called when the input pin is connected.
// The SetOutputMediaType is called when the output pin is connected.
//
/////////////////////////////////////////////////////////////////////////
//
// Informs when the media type is established for the connection.
// This then calls the SetInputMediaType and SetOutputMediaType
// for each pin direction.
//
HRESULT CHistogram::SetMediaType(PIN_DIRECTION direction, const CMediaType* mediaType)
{
// assertion
CheckPointer (mediaType, E_POINTER);
HRESULT result = 0;
// Call super method, pass it what we got here.
// result = this->CTransformFilter::SetMediaType(direction, mediaType);
if (result != S_OK)
{
return result;
}
// get the input pin media type
if (direction == PINDIR_INPUT)
{
this->GetInputMediaType(mediaType);
}
// set media type for the output pin
else if (direction == PINDIR_OUTPUT)
{
this->SetOutputMediaType(mediaType);
}
// unrecognized pin direction
else
{
return E_FAIL;
}
return S_OK;
}
//
// Gets the input media type, this is called when SetMediaType
// is called with a pin direction of INPUT
// This is a helper function and not part of the base Transform filter
//
HRESULT CHistogram::GetInputMediaType(const CMediaType* mediaType)
{
//MsgBOX(TEXT("GetInputMediaType"));
if(IsEqualGUID(*mediaType->Subtype(), MEDIASUBTYPE_RGB24))
{
inputColourFormat = 1;
//MsgBOX(TEXT("MEDIASUBTYPE_RGB24"));
}
else if(IsEqualGUID(*mediaType->Subtype(), MEDIASUBTYPE_YUY2))
{
inputColourFormat = 2;
//MsgBOX(TEXT("MEDIASUBTYPE_YUY2"));
}
else
{
inputColourFormat = 0;
}
int width = 0;
int height = 0;
int bitsPerPixel = 0;
if (*mediaType->FormatType () == FORMAT_VideoInfo)
{
VIDEOINFOHEADER* header = reinterpret_cast (mediaType->Format ());
if ( header == 0 )
return E_FAIL;
input_width = (int)(header->bmiHeader.biWidth);
input_height = (int)(header->bmiHeader.biHeight);
bitsPerPixel = (int)(header->bmiHeader.biBitCount);
pixel_length_bytes = bitsPerPixel / 8;
}
else
{
return E_FAIL;
}
//Reconnect the output pins to pass the new size downstream
// ReconnectOutputPins();
//MsgBOX(TEXT("Pixel Depth %d width %d height %d"), bitsPerPixel, width, height);
return S_OK;
}
//
// Sets the output media type, this is called when SetMediaType
// is called with a pin direction of OUTPUT
// This is a helper function and not part of the base Transform filter
//
HRESULT CHistogram::SetOutputMediaType(const CMediaType* mediaType)
{
// // copy media type
// this->outputMediaType = *mediaType;
/*
MsgBOX(TEXT("SetOutputMediaType"));
if(IsEqualGUID(*mediaType->Type(), MEDIATYPE_Video))
MsgBOX(TEXT("MEDIATYPE_Video"));
if(IsEqualGUID(*mediaType->Subtype(), MEDIASUBTYPE_RGB24))
MsgBOX(TEXT("MEDIASUBTYPE_RGB24"));
*/
// setup format info
if (*mediaType->FormatType () == FORMAT_VideoInfo)
{
VIDEOINFOHEADER* pvi = reinterpret_cast (mediaType->Format());
if (NULL == pvi)
{
return(E_OUTOFMEMORY);
}
// Set for 24 bit RGB
pvi->bmiHeader.biCompression = BI_RGB;
pvi->bmiHeader.biBitCount = 24;
pvi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pvi->bmiHeader.biWidth = output_width;
pvi->bmiHeader.biHeight = output_height;
pvi->bmiHeader.biPlanes = 1;
pvi->bmiHeader.biSizeImage = GetBitmapSize(&pvi->bmiHeader);
pvi->bmiHeader.biClrImportant = 0;
SetRectEmpty(&(pvi->rcSource)); // we want the whole image area rendered.
SetRectEmpty(&(pvi->rcTarget)); // no particular destination rectangle
}
else
return E_FAIL;
return S_OK;
}
//
// Prepares the output sample.
// This copies the property from the
// input sample to the output sample.
//
HRESULT CHistogram::PrepareOutputSample (IMediaSample* inSample, IMediaSample* outSample)
{
// assertions
CheckPointer(inSample, E_POINTER);
CheckPointer(outSample, E_POINTER);
//.1
// set media type
//
// Copy the media type
//outSample->SetMediaType(&this->outputMediaType);
//.2
// copy the sample times
//
REFERENCE_TIME timeStart = 0;
REFERENCE_TIME timeEnd = 0;
if (inSample->GetTime (&timeStart, &timeEnd) == S_OK)
{
outSample->SetTime (&timeStart, &timeEnd);
}
LONGLONG mediaStart = 0;
LONGLONG mediaEnd = 0;
if (inSample->GetMediaTime (&mediaStart, &mediaEnd) == S_OK)
{
outSample->SetMediaTime (&mediaStart,&mediaEnd);
}
//.3
// copy the sync point property
//
HRESULT result = inSample->IsSyncPoint ();
if (result == S_OK)
{
outSample->SetSyncPoint (TRUE);
}
else if (result == S_FALSE)
{
outSample->SetSyncPoint (FALSE);
}
else
{
return E_UNEXPECTED;
}
//.4
// copy the preroll property
//
result = inSample->IsPreroll ();
if (result == S_OK)
{
outSample->SetPreroll (TRUE);
}
else if (result == S_FALSE)
{
outSample->SetPreroll (FALSE);
}
else
{
return E_UNEXPECTED;
}
//.5
// copy the discontinuity property
//
result = inSample->IsDiscontinuity ();
if (result == S_OK)
{
outSample->SetDiscontinuity (TRUE);
}
else if (result == S_FALSE)
{
outSample->SetDiscontinuity(FALSE);
}
else
{
return E_UNEXPECTED;
}
return S_OK;
}
//
//Reconnect the output pins to pass the new size down the stream
//
BOOL CHistogram::ReconnectOutputPins()
{
FILTER_INFO filerInfo;
HRESULT hr = this->QueryFilterInfo(&filerInfo);
if(filerInfo.pGraph)
{
IPin *pP;
ULONG u;
IEnumPins *pins = NULL;
PIN_INFO pininfo;
hr = this->EnumPins(&pins);
pins->Reset();
while(hr == NOERROR)
{
hr = pins->Next(1, &pP, &u);
if(hr == S_OK && pP)
{
hr = pP->QueryPinInfo(&pininfo);
if(hr == NOERROR)
{
if(pininfo.dir == PINDIR_OUTPUT)
{
filerInfo.pGraph->Reconnect(pP);
}
if(pininfo.pFilter)
pininfo.pFilter->Release();
}
pP->Release();
}
}
if(pins)
pins->Release();
}
if(filerInfo.pGraph)
filerInfo.pGraph->Release();
filerInfo.pGraph = NULL;
return (hr == S_OK);
}
//////////////////////////////////////////////////////////////
//
// Method to display a message box to show data
//
int CHistogram::MsgBOX(LPTSTR sz,...)
{
static TCHAR tach[2000];
va_list va;
va_start(va, sz);
wvsprintf(tach, sz, va);
va_end(va);
MessageBox(HWND_DESKTOP, tach, "Filter Message Box", MB_OK|MB_ICONEXCLAMATION|MB_TASKMODAL);
return FALSE;
}