home *** CD-ROM | disk | FTP | other *** search
- /*
- * VideoRenderer.cpp
- *
- * Copyright (C) Alberto Vigata - July 2000 - ultraflask@yahoo.com
- *
- * This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
- *
- * FlasKMPEG 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, or (at your option)
- * any later version.
- *
- * FlasKMPEG 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 GNU Make; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
- #define INITGUID
- #include "VideoRenderer.h"
-
- #include <stdlib.h>
- #include "error.h"
- #include "FlMemcpy.h"
- #include "Debug.h"
-
-
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
-
- CVideoRenderer::CVideoRenderer(HWND hRenderWnd,bool bFixedFormat, int nFixedFormat)
- {
- m_hRenderWnd = hRenderWnd;
- m_nWidth = 0;
- m_nHeight = 0;
- fTime = 0;
-
- m_bOverlayFlag = m_bDirectDrawFlag = false;
-
- m_nCurrentFormat = bFixedFormat ? nFixedFormat : FRAME_RGB32;
- m_bFixedFormat = bFixedFormat;
-
- m_pDD = NULL;
- m_pDD2= NULL;
- m_pDDSPrimary = NULL;
- m_pDDSOverlay = NULL;
-
- PaintKey();
- StopPlaying();
- }
-
- CVideoRenderer::~CVideoRenderer()
- {
- CloseOverlay();
- CloseDirectDraw();
- }
-
- bool CVideoRenderer::OpenDirectDraw()
- {
- HRESULT hError;
- try
- {
- //Close all
- CloseDirectDraw();
-
- m_bDirectDrawFlag = false;
- ZeroMemory(&m_pDD, sizeof(m_pDD));
- // Create the main DirectDraw object
- if(hError=DirectDrawCreate( NULL, &m_pDD, NULL )==DD_OK)
- {
-
- ZeroMemory(&m_pDD2, sizeof(m_pDD2));
-
- if (hError=m_pDD->QueryInterface(IID_IDirectDraw2, (LPVOID*)&m_pDD2)==DD_OK)
- {
-
- // Request normal cooperative level to put us in windowed mode
- if(hError=m_pDD2->SetCooperativeLevel( m_hRenderWnd, DDSCL_NORMAL )==DD_OK)
- {
- // Get driver capabilities to determine Overlay support.
- ZeroMemory( &m_ddcaps, sizeof(m_ddcaps) );
- m_ddcaps.dwSize = sizeof(m_ddcaps);
-
- // Create the primary surface, which in windowed mode is the desktop.
- ZeroMemory(&m_ddsd,sizeof(m_ddsd));
- m_ddsd.dwSize = sizeof(m_ddsd);
- m_ddsd.dwFlags = DDSD_CAPS;
- m_ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
- if(hError=m_pDD2->CreateSurface( &m_ddsd, &m_pDDSPrimary, NULL )==DD_OK)
- {
- m_bDirectDrawFlag = true;
- return true;
- }
- else
- {
- //DirectDraw initialized, destroy it
- if (m_pDD) SafeRelease( m_pDD);
- if (m_pDD2) SafeRelease( m_pDD2);
- return false;
- }
- }
- else
- {
- if (m_pDD) SafeRelease( m_pDD);
- if (m_pDD2) SafeRelease( m_pDD2);
- return false;
- }
- }
- else
- if (m_pDD) SafeRelease( m_pDD);
- return false;
- }
- else
- return false;
- }
- catch(...) {return false;}
- }
-
- void CVideoRenderer::CloseDirectDraw()
- {
- m_bDirectDrawFlag = false;
- m_bOverlayFlag = false;
- if(m_pDDSOverlay) SafeRelease(m_pDDSOverlay);
- if (m_pDDSPrimary) SafeRelease( m_pDDSPrimary );
- if (m_pDD) SafeRelease( m_pDD);
- if (m_pDD2) SafeRelease( m_pDD2);
- }
-
- bool CVideoRenderer::GetInfoOverlay(DWORD * FccCodes, DDCAPS * Caps)
- {
-
- bool m_bKeepDDrawOpened = m_bDirectDrawFlag;
-
- if (!m_bDirectDrawFlag)
- OpenDirectDraw();
-
- if (m_bDirectDrawFlag)
- {
- ZeroMemory(Caps, sizeof(DDCAPS));
- Caps->dwSize = sizeof(DDCAPS);
- DWORD NbrCodes;
-
- if (!(m_pDD2->GetCaps(Caps, NULL)==DD_OK) ||
- !(m_pDD2->GetFourCCCodes(&NbrCodes,FccCodes)==DD_OK))
- {
- if (!m_bKeepDDrawOpened)
- CloseDirectDraw();
- return false;
- }
-
- if (!m_bKeepDDrawOpened)
- CloseDirectDraw();
- return true;
- }
- else
- return false;
-
- }
-
- bool CVideoRenderer::SetOverlay(int nWidth, int nHeight, long StoreFormat)
- {
- if (OpenDirectDraw())
- if (OpenOverlay(StoreFormat, nWidth, nHeight))
- PaintKey();
-
- return true;
-
- return false;
- }
-
- bool CVideoRenderer::OpenOverlay(long StoreFormat,int nWidth, int nHeight)
- {
- HRESULT hError;
- //Close any other overlay
- CloseOverlay();
-
- DDPIXELFORMAT ddpfOverlayFormat;
-
- bool bSuccess = false;
- //Init Flag
- m_bOverlayFlag = false;
-
- if(m_bDirectDrawFlag)
- {
- ZeroMemory( &ddpfOverlayFormat, sizeof(ddpfOverlayFormat) );
- ddpfOverlayFormat.dwSize = sizeof(ddpfOverlayFormat);
-
- switch(StoreFormat)
- {
- case FRAME_YUY2:
- ddpfOverlayFormat.dwFlags = DDPF_FOURCC;
- ddpfOverlayFormat.dwFourCC = mmioFOURCC('Y','U','Y','2');
- ddpfOverlayFormat.dwYUVBitCount = 16;
- break;
- case FRAME_YV12:
- ddpfOverlayFormat.dwFlags = DDPF_FOURCC;
- ddpfOverlayFormat.dwFourCC = mmioFOURCC('Y','V','1','2');
- break;
- case FRAME_RGB32:
- ddpfOverlayFormat.dwFlags = DDPF_RGB;
- ddpfOverlayFormat.dwRGBBitCount = 32;
- ddpfOverlayFormat.dwRBitMask = 0x00FF0000;
- ddpfOverlayFormat.dwGBitMask = 0x0000FF00;
- ddpfOverlayFormat.dwBBitMask = 0x000000FF;
- break;
- }
-
- // Setup the overlay surface's attributes in the surface descriptor
- ZeroMemory( &m_ddsd, sizeof(m_ddsd) );
- m_ddsd.dwSize = sizeof(m_ddsd);
- m_ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
- m_ddsd.ddsCaps.dwCaps = DDSCAPS_OVERLAY | DDSCAPS_VIDEOMEMORY;
- m_ddsd.dwWidth = nWidth;
- m_ddsd.dwHeight = nHeight;
- m_ddsd.ddpfPixelFormat = ddpfOverlayFormat;
-
- // Attempt to create the surface with theses settings
- if(hError=m_pDD2->CreateSurface( &m_ddsd, &m_pDDSOverlay, NULL)==DD_OK)
- {
- bSuccess = true;
- m_bOverlayFlag = true;
-
- ZeroMemory(&m_OverlayFX, sizeof(DDOVERLAYFX));
- m_OverlayFX.dwSize = sizeof(DDOVERLAYFX);
-
- m_OverlayFX.dckDestColorkey.dwColorSpaceLowValue = DDColorMatch(m_pDDSPrimary, MASKCOLOR);
- m_OverlayFX.dckDestColorkey.dwColorSpaceHighValue = m_OverlayFX.dckDestColorkey.dwColorSpaceLowValue;
-
- if( !m_bFixedFormat )
- m_nCurrentFormat = StoreFormat;
-
- }
- return bSuccess;
- }
- else
- return bSuccess;
- }
-
- // Match the color
- DWORD CVideoRenderer::DDColorMatch(LPDIRECTDRAWSURFACE pdds, COLORREF rgb)
- {
- COLORREF rgbT;
- DWORD dw = CLR_INVALID;
- HRESULT hres;
- HDC hdc;
-
-
- if (IDirectDrawSurface_GetDC(pdds, &hdc)==DD_OK)
- {
- rgbT = GetPixel(hdc, 0, 0);
- SetPixel(hdc, 0, 0, rgb);
- IDirectDrawSurface_ReleaseDC(pdds, hdc);
- }
-
- ZeroMemory(&m_ddsd, sizeof(DDSURFACEDESC));
- m_ddsd.dwSize = sizeof(DDSURFACEDESC);
- while ((hres = IDirectDrawSurface_Lock(pdds, NULL, &m_ddsd, DDLOCK_WAIT, NULL)) == DDERR_WASSTILLDRAWING);
-
- if (hres==DD_OK)
- {
- dw = *(DWORD *) m_ddsd.lpSurface;
- if (m_ddsd.ddpfPixelFormat.dwRGBBitCount < 32)
- dw &= (1 << m_ddsd.ddpfPixelFormat.dwRGBBitCount) - 1;
- IDirectDrawSurface_Unlock(pdds, NULL);
- }
-
- if (IDirectDrawSurface_GetDC(pdds, &hdc)==DD_OK)
- {
- SetPixel(hdc, 0, 0, rgbT);
- IDirectDrawSurface_ReleaseDC(pdds, hdc);
- }
-
- return dw;
- }
-
- void CVideoRenderer::CloseOverlay()
- {
- if(m_pDDSOverlay) SafeRelease(m_pDDSOverlay);
- m_bOverlayFlag = false;
-
- if( !m_bFixedFormat )
- m_nCurrentFormat = FRAME_RGB32;
- }
-
- void CVideoRenderer::SetStaticFrame(CFrame *pFrame)
- {
-
- if(!pFrame)
- return;
- if(!pFrame->IsValid())
- return;
- m_oStaticFrame = *pFrame;
- }
-
- void CVideoRenderer::Update()
- {
- CFlAutoLock lock(&m_csDirectDraw);
- if(m_bOverlayFlag)
- {
- PaintKey();
- UpdateOverlay();
- }
-
-
- if( m_nState == Stopped )
- Draw(&m_oStaticFrame);
-
- }
-
- // Paint the window with the color key
- void CVideoRenderer::PaintKey()
- {
- HPEN hpen, hpenOld;
- HBRUSH hbrush, hbrushOld;
-
- HDC hDC = GetDC( m_hRenderWnd );
- // Create a pen.
- hpen = CreatePen(PS_SOLID, 1, MASKCOLOR);
- // Create a brush.
- hbrush = CreateSolidBrush(MASKCOLOR);
-
- // Select the new pen and brush, and then draw.
- hpenOld = (HPEN )SelectObject(hDC, hpen);
- hbrushOld = (HBRUSH )SelectObject(hDC, hbrush);
-
- RECT sRect;
- GetClientRect( m_hRenderWnd, &sRect );
-
- Rectangle( hDC, sRect.left, sRect.top,
- sRect.right,
- sRect.bottom );
-
- // Do not forget to clean up.
- SelectObject(hDC, hpenOld);
- DeleteObject(hpen);
- SelectObject(hDC, hbrushOld);
- DeleteObject(hbrush);
-
- ReleaseDC( m_hRenderWnd, hDC);
-
- return;
- }
-
-
- void CVideoRenderer::UpdateOverlay()
- {
- POINT point = {0, 0};
- RECT orect,prect;
-
- CFlAutoLock lock(&m_csDirectDraw);
-
- if(!m_bOverlayFlag) return;
-
- SetRect(&orect, 0, 0, m_nWidth, m_nHeight);
-
- ClientToScreen(m_hRenderWnd, &point);
- prect.left = point.x;
- prect.right = point.x + m_nWidth;
- prect.top = point.y;
- prect.bottom = point.y + m_nHeight;
-
- if (prect.left < 0)
- {
- orect.left = -prect.left;
- prect.left = 0;
- }
-
- if (prect.top < 0)
- {
- orect.top = -prect.top;
- prect.top = 0;
- }
-
- if (prect.right > GetSystemMetrics(SM_CXSCREEN))
- {
- orect.right = m_nWidth + GetSystemMetrics(SM_CXSCREEN) - prect.right;
- prect.right = GetSystemMetrics(SM_CXSCREEN);
- }
-
- if (prect.bottom > GetSystemMetrics(SM_CYSCREEN))
- {
- orect.bottom = m_nHeight + GetSystemMetrics(SM_CYSCREEN) - prect.bottom;
- prect.bottom = GetSystemMetrics(SM_CYSCREEN);
- }
-
- m_pDDSOverlay->UpdateOverlay(&orect, m_pDDSPrimary, &prect,
- DDOVER_SHOW | DDOVER_DDFX | DDOVER_KEYDESTOVERRIDE , &m_OverlayFX);
- }
-
-
- void CVideoRenderer::Draw(CFrame *pFrame, int flags )
- {
- HRESULT res;
- DWORD lckflags = flags&VR_WAITFORLOCK ? DDLOCK_WAIT : 0;
-
- if(!pFrame)
- return;
-
- if(!pFrame->IsValid())
- return;
-
- int nWidth = pFrame->GetWidth();
- int nHeight = pFrame->GetHeight();
- int nFrameFormat = pFrame->GetFormat();
-
- CFlAutoLock lock(&m_csDirectDraw);
-
- // if there has been a change in resolution
- // update the overlay
- if(nWidth != m_nWidth ||
- nHeight != m_nHeight )
- {
- SetOverlay( nWidth, nHeight, m_bFixedFormat ? m_nCurrentFormat : nFrameFormat );
- m_nWidth = nWidth;
- m_nHeight = nHeight;
- // Update the rgb frame size
- m_oRgbFrame.Set( m_nWidth, m_nHeight, m_nCurrentFormat );
- }
-
- if( m_nCurrentFormat != nFrameFormat && !m_bFixedFormat )
- {
- SetOverlay( nWidth, nHeight, nFrameFormat );
- }
-
-
-
- switch(nFrameFormat)
- {
- case FRAME_RGB32:
-
- if( 1 ) //For RGB dont use overlays
- {
- HDC hDC;
- hDC = GetDC(m_hRenderWnd);
- SetDIBitsToDevice((HDC) hDC,0,0,nWidth,nHeight,
- 0,0,0,nHeight, pFrame->GetBuffer(), pFrame->GetBmpInfo(), DIB_RGB_COLORS);
- ReleaseDC( m_hRenderWnd, (HDC)hDC);
- }
- else
- {
- try
- {
- int w = nWidth;
- int ww = w*4;
- int h = nHeight;
-
-
- ZeroMemory(&m_ddsd, sizeof(DDSURFACEDESC));
- m_ddsd.dwSize = sizeof(DDSURFACEDESC);
-
- if (m_pDDSOverlay->Lock(0, &m_ddsd, lckflags , 0)==DD_OK)
- {
- unsigned char * src = (unsigned char *)pFrame->GetBuffer() + w*h*4 ;
- unsigned char * dst = (unsigned char *)m_ddsd.lpSurface;
- long Pitch = m_ddsd.lPitch-ww;
-
- for (int i=0; i<h; i++)
- {
- src -= ww;
- flmemcpy(dst, src, ww);
- dst += m_ddsd.lPitch;
- }
- if( m_pDDSOverlay->Unlock(0)==DD_OK ) UpdateOverlay();
- }
- }
- catch(...)
- {
- throw (MyError("RGB DirectDraw Error"));
- }
- }
- break;
-
- case FRAME_YUY2:
- switch( m_nCurrentFormat )
- {
- case FRAME_YUY2:
- try
- {
- int w = nWidth;
- int ww = w*2;
- int h = nHeight;
-
- ZeroMemory(&m_ddsd, sizeof(DDSURFACEDESC));
- m_ddsd.dwSize = sizeof(DDSURFACEDESC);
-
- if (m_pDDSOverlay->Lock(0, &m_ddsd, lckflags, 0)==DD_OK)
- {
- unsigned char *src = (unsigned char *)pFrame->GetBuffer();
- unsigned char *dst = (unsigned char *)m_ddsd.lpSurface;
- long Pitch = m_ddsd.lPitch-ww;
-
- if( Pitch )
- {
- for (int i=0; i<h; i++)
- {
- flmemcpy(dst, src, ww);
- src += ww;
- dst += m_ddsd.lPitch;
- }
- }
- else
- {
- flmemcpy( dst, src, ww*h);
- }
-
- if( m_pDDSOverlay->Unlock(0)==DD_OK ) UpdateOverlay();
- }
- }
- catch(...)
- {
- throw (MyError("YUY2 DirectDraw Error"));
- }
- break;
- }
- break;
- case FRAME_YV12:
- switch( m_nCurrentFormat )
- {
- case FRAME_YV12:
- try
- {
- int w = nWidth;
- int halfW = w >> 1;
- int h = nHeight;
-
-
- ZeroMemory(&m_ddsd, sizeof(DDSURFACEDESC));
- m_ddsd.dwSize = sizeof(DDSURFACEDESC);
-
- if ( (res = m_pDDSOverlay->Lock(0, &m_ddsd, lckflags, 0))==DD_OK )
- {
- unsigned char *src = (unsigned char *)pFrame->GetBuffer();
- unsigned char *src2 = (unsigned char *)pFrame->GetBuffer()+h*w;
- unsigned char *src3 = (unsigned char *)pFrame->GetBuffer()+h*w+ ((h*w)>>2);
- unsigned char *dst = (unsigned char *)m_ddsd.lpSurface;
- int Decal = ((m_ddsd.lPitch-w)>>1);
-
- for (int i=0; i<h; i++)
- {
- flmemcpy(dst, src, w);
- src += w;
- dst += m_ddsd.lPitch;
- }
-
-
- for (i=0; i<h>>1; i+=2)
- {
- flmemcpy(dst,src2, halfW);
- flmemcpy(dst + halfW + Decal,src2, halfW);
- src2 += w;
- dst +=m_ddsd.lPitch;
- }
-
-
- for (i=0; i<h>>1; i+=2)
- {
- flmemcpy(dst,src3, halfW);
- flmemcpy(dst + halfW + Decal,src3, halfW);
- src3 += w;
- dst +=m_ddsd.lPitch;
- }
-
- if( m_pDDSOverlay->Unlock(0)==DD_OK ) UpdateOverlay();
-
- }
- else
- {
- DBG_STR((str, "VideoRenderer - Couldnt lock surface. Was still drawing: %d\n", res==DDERR_WASSTILLDRAWING))
- }
- }
- catch(...)
- {
- throw (MyError("YV12 DirectDraw Error"));
- }
- break;
- case FRAME_RGB32:
- FLASSERT( m_oRgbFrame.GetWidth() == pFrame->GetWidth() &&
- m_oRgbFrame.GetHeight() == pFrame->GetHeight() )
- // Use the RGB frame to do the conversion
- m_oRgbFrame.SetFrame( pFrame );
- // Draw it
- HDC hDC;
- hDC = GetDC(m_hRenderWnd);
- SetDIBitsToDevice((HDC) hDC,0,0,nWidth,nHeight,
- 0,0,0,nHeight, m_oRgbFrame.GetBuffer(),m_oRgbFrame.GetBmpInfo(), DIB_RGB_COLORS);
- ReleaseDC( m_hRenderWnd, (HDC)hDC);
-
- break;
- }
- break;
- }
- }
-