Click here to Skip to main content
15,890,438 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi Experts,

Link to my Full source code:
https://docs.google.com/file/d/0B9qC3OVDGTjuM2xaeGx1Q0NUYWs/edit[^]
(in the Debug folder there is Resizer.dll, and need to register it first then in graph edit select any video file(using file source filer), then add "RGB Resizer" and use it to resize the video)


I am creating a new resizer Filter, I added a property page where user can select different outputs (pal(720X576), ntsc(720X480)...)

By default pal is selected and if i played it working fine.
after playing with pal and if i changed the output to ntsc video is not displaying correctly(problem is top part of the header is getting croped.)
If i disconnect the output and input pins of my filter and then change the output settings and after reconnecting it seems to be working fine.

How to fix this issue?(with out disconnecting the pins i need to change the output settings)

below is my code(the code i am using is from a sample i found online, i added the property page)
I guess i need to change ScaleBuf() but i dont have any clues how to fix this.

C++
HRESULT CResizer::CheckInputType(const CMediaType *mtIn)
{
    // check this is a VIDEOINFOHEADER type and RGB
    GUID subtypeIn = *mtIn->Subtype();
    if( *mtIn->FormatType() == FORMAT_VideoInfo &&
        (subtypeIn == MEDIASUBTYPE_RGB555 || subtypeIn == MEDIASUBTYPE_RGB565 ||
        subtypeIn == MEDIASUBTYPE_RGB24 || subtypeIn == MEDIASUBTYPE_RGB32))
    {
        BITMAPINFOHEADER *pbih = &((VIDEOINFOHEADER*)mtIn->Format())->bmiHeader;
        m_inX = pbih->biWidth;
        m_inY = pbih->biHeight;
        m_bMakeTables = true;
        return S_OK;
    }
    return VFW_E_INVALID_MEDIA_TYPE;
}

HRESULT CResizer::CheckTransform(const CMediaType *mtIn, const CMediaType *mtOut)
{
    GUID subtypeIn = *mtIn->Subtype();
    GUID subtypeOut = *mtOut->Subtype();

    if(subtypeIn == subtypeOut && (subtypeIn == MEDIASUBTYPE_RGB555 || subtypeIn == MEDIASUBTYPE_RGB565 || 
       subtypeIn == MEDIASUBTYPE_RGB24 || subtypeIn == MEDIASUBTYPE_RGB32) )
    return S_OK;

    return VFW_E_INVALID_MEDIA_TYPE;
}


HRESULT CResizer::DecideBufferSize(IMemAllocator *pAlloc,ALLOCATOR_PROPERTIES *pProperties)
{
	if (!m_pInput->IsConnected()) 
        return E_UNEXPECTED;

    //HRESULT hr = NOERROR;

	ALLOCATOR_PROPERTIES InputProps;
	IMemAllocator *pAllocInput = 0;
	HRESULT hr = m_pInput->GetAllocator(&pAllocInput);
	if (FAILED(hr))
	{
		return hr;
	}
	hr = pAllocInput->GetProperties(&InputProps);
	pAllocInput->Release();

	if (FAILED(hr)) 
	{
		return hr;
	}

	if (pProperties->cbAlign == 0)
	{
		pProperties->cbAlign = 1;
	}

	if (pProperties->cbBuffer == 0)
	{
		pProperties->cBuffers = 1;
	}

	pProperties->cbBuffer = max(InputProps.cbBuffer, pProperties->cbBuffer);
	ALLOCATOR_PROPERTIES Actual;
	hr = pAlloc->SetProperties(pProperties, &Actual);
	if (FAILED(hr)) 
	{
		return hr;
	}

	if (InputProps.cbBuffer > Actual.cbBuffer) 
	{
		return E_FAIL;
	}

	return S_OK;
}

HRESULT CResizer::GetMediaType(int iPosition, CMediaType *pMediaType)
{
    // Is the input pin connected
    if (!m_pInput->IsConnected()) 
        return E_UNEXPECTED;

    if (iPosition < 0)
        return E_INVALIDARG;

    // Do we have more items to offer
    if (iPosition > 0)
        return VFW_S_NO_MORE_ITEMS;

	// get input dimensions
	CMediaType *inMediaType = &m_pInput->CurrentMediaType();
    VIDEOINFOHEADER *vihIn = (VIDEOINFOHEADER*)inMediaType->Format();
    m_bytesPerPixel = vihIn->bmiHeader.biBitCount / 8;
	pMediaType->SetFormatType(&FORMAT_VideoInfo);
	pMediaType->SetType(&MEDIATYPE_Video);
	pMediaType->SetSubtype(inMediaType->Subtype());
	pMediaType->SetSampleSize(RowWidth(m_outX) * m_outY * m_bytesPerPixel);
	pMediaType->SetTemporalCompression(FALSE);
	VIDEOINFOHEADER *vihOut = (VIDEOINFOHEADER *)pMediaType->ReallocFormatBuffer(sizeof(VIDEOINFOHEADER));

	// set VIDEOINFOHEADER
	memset(vihOut, 0, sizeof(VIDEOINFOHEADER));
	double frameRate = vihIn->AvgTimePerFrame / 10000000.0;
	vihOut->dwBitRate = (int)(frameRate * m_outY * m_outX * m_bytesPerPixel);
	vihOut->AvgTimePerFrame = vihIn->AvgTimePerFrame;

	// set BITMAPINFOHEADER
	vihOut->bmiHeader.biBitCount = m_bytesPerPixel * 8;
	vihOut->bmiHeader.biCompression = BI_RGB;
	vihOut->bmiHeader.biHeight = m_outY;
    vihOut->bmiHeader.biWidth = m_outX;
	vihOut->bmiHeader.biPlanes = 1;
	vihOut->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	vihOut->bmiHeader.biSizeImage = RowWidth(m_outX) * m_outY * m_bytesPerPixel;

    return NOERROR;
}

//////////////////////////////////////////////////////////////////////////
// Build the lookup tables used for scaling the input into the output
// For each destination pixel x and y the corresponding offset in the
// source buffer is stored
//////////////////////////////////////////////////////////////////////////
void CResizer::MakeScaleTables()
{
    double xStep = (double)m_inX / m_outX;
    double yStep = (double)m_inY / m_outY;

    int inRowBytes = RowWidth(m_inX * m_bytesPerPixel);
    int inY, inX;
    for(int y = 0; y < m_outY; ++y)    
    {
        inY = y * yStep;
        m_iSrcScanLine[y] = (inY * inRowBytes);
    }

    for(int x = 0; x < m_outX; ++x)
    {
        inX = x * xStep;
        m_iSrcPixelOffset[x] = (inX * m_bytesPerPixel);
    }

}

//////////////////////////////////////////////////////////////////////////
// This method scales the bitmap data from the input to output buffer
// When either of the formats change, the tables are rebuilt
//////////////////////////////////////////////////////////////////////////
void CResizer::ScaleBuf(BYTE *in, BYTE *out)
{
    UCHAR *dstPixel = out;
    UCHAR *srcScanLine, *srcPixel;
    // separate loops for each bpp
    for(int y = 0; y < m_outY; ++y)
    {
        srcScanLine = in + m_iSrcScanLine[y];
        switch(m_bytesPerPixel)
        {
            case 4: 
            for(int x = 0; x < m_outX; ++x)
            {
                srcPixel = srcScanLine + m_iSrcPixelOffset[x];
                *dstPixel++ = *srcPixel++;
                *dstPixel++ = *srcPixel++;
                *dstPixel++ = *srcPixel++;
                *dstPixel++ = *srcPixel++;
            }
            break;

            case 3: 
            for(int x = 0; x < m_outX; ++x)
            {
                srcPixel = srcScanLine + m_iSrcPixelOffset[x];
                *dstPixel++ = *srcPixel++;
                *dstPixel++ = *srcPixel++;
                *dstPixel++ = *srcPixel++;
            }
            break;
                
            case 2: 
            for(int x = 0; x < m_outX; ++x)
            {
                srcPixel = srcScanLine + m_iSrcPixelOffset[x];
                *dstPixel++ = *srcPixel++;
                *dstPixel++ = *srcPixel++;
            }
            break;
                
            case 1: 
            for(int x = 0; x < m_outX; ++x)
            {
                srcPixel = srcScanLine + m_iSrcPixelOffset[x];
                *dstPixel++ = *srcPixel++;
            }
            break;
        }
    }
}
Posted
Updated 5-Feb-13 1:13am
v3
Comments
Matthew Faithfull 5-Feb-13 6:52am    
With a code dump of that size you might be better asking the original author. It will take quite a while for anyone else to understand what all that is doing. Given that it runs and produces output we aren't looking for a syntax error here. You could try adding a link to the original source as well, if someone can download the complete sample themselves and run it they might be able to help you more easily.
ask0596 5-Feb-13 7:14am    
Hi Matthew Faithfull thanks for the reply, I added the link for source.

1 solution

Hello,
Once you change output resolution manually you should notify output pin that output format has been changed, otherwise connected filter still expect data with previous resolution: to do so simplify reconnect ouput pin if it already connected.

Issues in the code:
- You should not set the input width and height in CheckInputType method as it is to just figure out accepted type or not and may be called during graph running, use for taht SetMediaType instead, NOTE you should handle that pbFormat can be NULL.
- Your code not care about dynamic format changes actually it pass the changes but ignore that (I think your issue is bcs of that as if you connected to renderer it performs changing the pitch for surfaces allocating).
- In code along with dynamic format handling you should correct the output pitch.

Regards,
Maxim.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900