/* ***** BEGIN LICENSE BLOCK *****
 * Source last modified: $Id: vidsurf2.cpp,v 1.1.1.1.42.1 2004/07/09 01:59:28 hubbe Exp $
 * 
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 * 
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 * 
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 * 
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK ***** */

#include "hxcom.h"
#include "hxtypes.h"
#include "hxwintyp.h"
#include "hxthread.h"

#include "basesite.h"

#if defined(_WINDOWS)
#include "winsurf.h"

#if defined (HELIX_FEATURE_VS2)
#include "winsurf2.h"
#endif

#include "winroot.h"	// must be included before colormap.h
#endif

#include "vidsurf2.h"
#include "colormap.h"

CVideoSurface2::CVideoSurface2(IUnknown* pIUnkOuter)
 :  m_pIUnknown(pIUnkOuter)
{
}

CVideoSurface2::~CVideoSurface2()
{
}


STDMETHODIMP CVideoSurface2::QueryInterface(REFIID riid, void** ppvObj)
{
    if (IsEqualIID(riid, IID_IHXVideoSurface2))
    {
        m_pIUnknown->AddRef();
        *ppvObj = (IUnknown*)(IHXVideoSurface2*)this;
        return HXR_OK;
    }
   
    *ppvObj = NULL;
    return HXR_NOINTERFACE;
}

STDMETHODIMP_(ULONG32) CVideoSurface2::AddRef()
{
    return m_pIUnknown->AddRef();
}

STDMETHODIMP_(ULONG32) CVideoSurface2::Release()
{
    return m_pIUnknown->Release();
}

STDMETHODIMP CVideoSurface2::SetProperties(HXBitmapInfoHeader* pRequest,
                                          REF(UINT32) ulNumBuffers,
                                          IHXRenderTimeLine* pTimeLine)
{
    return HXR_NOTIMPL;
}

STDMETHODIMP CVideoSurface2::GetVideoMem(VideoMemStruct* pVidMem,
                                        UINT32 ulFlags)
{
    return HXR_NOTIMPL;
}

STDMETHODIMP CVideoSurface2::ReleaseVideoMem(VideoMemStruct* pVidMem)
{
    return HXR_NOTIMPL;
}

STDMETHODIMP CVideoSurface2::Present(VideoMemStruct* pVidMem,
                                    INT32 lTime,
                                    UINT32 ulFlags,
                                    HXxRect* prDestRect,
                                    HXxRect* prSrcRect)
                                   
{
    return HXR_NOTIMPL;
}

STDMETHODIMP CVideoSurface2::ColorConvert(INT32    fourCCIn, 
                                         HXxSize *pSrcSize,
                                         HXxRect *prSrcRect,
                                         SourceInputStruct *pInput,
                                         INT32    fourCCOut,
                                         UCHAR   *pDestBuffer, 
                                         HXxSize *pDestSize, 
                                         HXxRect *prDestRect, 
                                         int      nDestPitch)
{
    BOOL bConverter = FALSE;
    BOOL bConverter2 = FALSE;
    HXBitmapInfoHeader bmiFrame;
    UCHAR* pucBuff   = NULL;
    UCHAR* pucYFrame = NULL;
    UCHAR* pucUFrame = NULL;
    UCHAR* pucVFrame = NULL;
    UINT32 nYFramePitch = 0;
    UINT32 nUFramePitch = 0;
    UINT32 nVFramePitch = 0;
    UINT32 nFrameWidth  = 0;
    UINT32 nFrameHeight = 0;
    
    HX_ASSERT( pDestBuffer );

    if (!pInput || pInput->nNumInputs < 1 || !pDestBuffer)
        return HXR_INVALID_PARAMETER;

    int nRet   = -1;
    int cIdIn  = MapFourCCtoCID(fourCCIn);
    int cIdOut = MapFourCCtoCID(fourCCOut);

    CHXBaseSite* pSite = GetSite();

    //Set up input frame pointers for padded and non-padded data
    pucYFrame    = pInput->aSrcInput[0];
    nYFramePitch = pInput->aSrcPitch[0];
    if( pInput->nNumInputs > 1)
    {
        pucUFrame    = pInput->aSrcInput[1];
        nUFramePitch = pInput->aSrcPitch[1];
        pucVFrame    = pInput->aSrcInput[2];
        nVFramePitch = pInput->aSrcPitch[2];
    }
    nFrameWidth  = pSrcSize->cx;
    nFrameHeight = pSrcSize->cy;

    // RGB values are CIDs not FourCCs
    if (CID_UNKNOWN == cIdIn)
        cIdIn = fourCCIn;

    if (CID_UNKNOWN == cIdOut)
        cIdOut = fourCCOut;

    //Grab the converters....
    if( pInput->nNumInputs > 1 )
    {
        //grab the padded converters...
        bConverter2 = GetColorConverter2(cIdIn, cIdOut);
    }
    else
    {
        //grab the non padded converters...
        bConverter = GetColorConverter(cIdIn, cIdOut);
    }
    
    //If we don't have a color converter then we need to do a 2 step process.
    //we will do cIdIn-->I420-->cIdOut.
    if( !bConverter && !bConverter2 )
    {
        // If we don't have a converter to match the source, do an AU
        // otherwise, continue with the 2 step.
        bConverter = GetColorConverter(cIdIn, cIdOut);
        if (!bConverter)
        {
            pSite->ColorConverterRequest(cIdIn, cIdOut, bConverter);
            return HXR_FAILED;
        }
        
        int nResult     = 0;
        int nFramePitch = 0;
        
#ifdef _WIN32
        nResult = MakeBitmap( (LPBITMAPINFO)&bmiFrame,
                              sizeof(bmiFrame),
                              CID_I420,
                              prDestRect->right - prDestRect->left,
                              prDestRect->bottom - prDestRect->top,
                              NULL,
                              0);
#else
        nResult = MakeBitmap( (HXBitmapInfo*)&bmiFrame,
                              sizeof(bmiFrame),
                              CID_I420,
                              prDestRect->right - prDestRect->left,
                              prDestRect->bottom - prDestRect->top,
                              NULL,
                              0);
#endif

        HX_ASSERT( nResult != 0 );

        pucBuff      = (UCHAR*)new char[bmiFrame.biSizeImage*sizeof(UCHAR)];
        nFramePitch  = GETBITMAPPITCH( &bmiFrame );
        nFrameWidth  = bmiFrame.biWidth;
        nFrameHeight = bmiFrame.biHeight;

        HXxSize size   = { nFrameWidth, nFrameHeight };
        HXxRect destRc = { prDestRect->left,
                           prDestRect->top,
                           prDestRect->right-prDestRect->left,
                           prDestRect->bottom-prDestRect->top };
        
        nResult = ColorConvert( fourCCIn,
                                pSrcSize,
                                prSrcRect,
                                pInput,
                                MAKEFOURCC('I','4','2','0'),
                                pucBuff,
                                &size,
                                &destRc,
                                GETBITMAPPITCH( &bmiFrame )
                                );

        if( nResult < 0 )
        {
            HX_VECTOR_DELETE( pucBuff );
            return HXR_FAILED;
        }

        //change pointers for 2nd stage below.....
        if( pInput->nNumInputs > 1 )
        {
            bConverter2 = GetColorConverter2(CID_I420, cIdOut);
            cIdIn        = CID_I420;
            pucYFrame    = pucBuff;
            nYFramePitch = nFramePitch;
        }
        else
        {
            bConverter = GetColorConverter(CID_I420, cIdOut);

            cIdIn        = CID_I420;
            pucYFrame    = pucBuff;
            nYFramePitch = nFramePitch;
        }
    }


    //
    // Normal 1-stage converts....
    //
    if (bConverter2 )
    {
        nRet = ColorConvert2( cIdOut, 
                              pDestBuffer,
                              pDestSize->cx, pDestSize->cy,
                              nDestPitch,
                              prDestRect->left, prDestRect->top, 
                              prDestRect->right-prDestRect->left,
                              prDestRect->bottom-prDestRect->top,
                              cIdIn,
                              pucYFrame,
                              pucUFrame,
                              pucVFrame,
                              nFrameWidth, nFrameHeight,
                              nYFramePitch,
                              nUFramePitch,
                              nVFramePitch,
                              prSrcRect->left, prSrcRect->top, 
                              prSrcRect->right-prSrcRect->left,
                              prSrcRect->bottom-prSrcRect->top
                            );
    }
    else if( bConverter )
    {
        nRet = ColorConvert( cIdOut,
                             pDestBuffer,
                             pDestSize->cx, pDestSize->cy,
                             nDestPitch,
                             prDestRect->left, prDestRect->top,
                             prDestRect->right-prDestRect->left, 
                             prDestRect->bottom-prDestRect->top,
                             cIdIn,
                             pucYFrame,
                             nFrameWidth, nFrameHeight,
                             nYFramePitch,
                             prSrcRect->left, prSrcRect->top,
                             prSrcRect->right-prSrcRect->left, 
                             prSrcRect->bottom-prSrcRect->top
                           );
    }

    HX_VECTOR_DELETE( pucBuff );

    if (nRet == -1)
        return HXR_FAILED;
    
    return HXR_OK;
}

STDMETHODIMP_(void) CVideoSurface2::Flush()
{
}

STDMETHODIMP CVideoSurface2::PresentIfReady()
{
    return HXR_NOTIMPL;
}
