/*
 * AVI Decompressor (VFW decompressors wrapper)
 *
 * Copyright 2004-2005 Christian Costa
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "config.h"

#include "quartz_private.h"
#include "control_private.h"
#include "pin.h"

#include "uuids.h"
#include "aviriff.h"
#include "mmreg.h"
#include "vfwmsgs.h"
#include "amvideo.h"
#include "windef.h"
#include "winbase.h"
#include "dshow.h"
#include "strmif.h"
#include "vfwmsgs.h"
#include "evcode.h"
#include "vfw.h"

#include <assert.h>

#include "wine/unicode.h"
#include "wine/debug.h"

#include "transform.h"

WINE_DEFAULT_DEBUG_CHANNEL(quartz);

typedef struct AVIDecImpl
{
    TransformFilterImpl tf;
    HIC hvid;
    BITMAPINFOHEADER* pBihIn;
    BITMAPINFOHEADER* pBihOut;
} AVIDecImpl;

static DWORD AVIDec_SendSampleData(TransformFilterImpl* pTransformFilter, LPBYTE data, DWORD size)
{
    AVIDecImpl* This = (AVIDecImpl*)pTransformFilter;
    VIDEOINFOHEADER* format;
    AM_MEDIA_TYPE amt;
    HRESULT hr;
    DWORD res;
    IMediaSample* pSample = NULL;
    DWORD cbDstStream;
    LPBYTE pbDstStream;

    TRACE("(%p)->(%p,%ld)\n", This, data, size);
    
    hr = IPin_ConnectionMediaType(This->tf.ppPins[0], &amt);
    if (FAILED(hr)) {
	ERR("Unable to retrieve media type\n");
	goto error;
    }
    format = (VIDEOINFOHEADER*)amt.pbFormat;

    /* Update input size to match sample size */
    This->pBihIn->biSizeImage = size;

    hr = OutputPin_GetDeliveryBuffer((OutputPin*)This->tf.ppPins[1], &pSample, NULL, NULL, 0);
    if (FAILED(hr)) {
	ERR("Unable to get delivery buffer (%lx)\n", hr);
	goto error;
    }

    hr = IMediaSample_SetActualDataLength(pSample, 0);
    assert(hr == S_OK);

    hr = IMediaSample_GetPointer(pSample, &pbDstStream);
    if (FAILED(hr)) {
	ERR("Unable to get pointer to buffer (%lx)\n", hr);
	goto error;
    }
    cbDstStream = IMediaSample_GetSize(pSample);
    if (cbDstStream < This->pBihOut->biSizeImage) {
        ERR("Sample size is too small %ld < %ld\n", cbDstStream, This->pBihOut->biSizeImage);
	hr = E_FAIL;
	goto error;
    }

    res = ICDecompress(This->hvid, 0, This->pBihIn, data, This->pBihOut, pbDstStream);
    if (res != ICERR_OK)
        ERR("Error occurred during the decompression (%lx)\n", res);

    hr = OutputPin_SendSample((OutputPin*)This->tf.ppPins[1], pSample);
    if (hr != S_OK && hr != VFW_E_NOT_CONNECTED) {
        ERR("Error sending sample (%lx)\n", hr);
	goto error;
    }

error:
    if (pSample)
        IMediaSample_Release(pSample);

    return hr;
}

static HRESULT AVIDec_ConnectInput(TransformFilterImpl* pTransformFilter, const AM_MEDIA_TYPE * pmt)
{
    AVIDecImpl* This = (AVIDecImpl*)pTransformFilter;

    TRACE("(%p)->(%p)\n", This, pmt);

    if ((IsEqualIID(&pmt->majortype, &MEDIATYPE_Video)) &&
        (!memcmp(((char*)&pmt->subtype)+4, ((char*)&MEDIATYPE_Video)+4, sizeof(GUID)-4)) && /* Check root (GUID w/o FOURCC) */
        (IsEqualIID(&pmt->formattype, &FORMAT_VideoInfo)))
    {
        HIC drv;
        VIDEOINFOHEADER* format = (VIDEOINFOHEADER*)pmt->pbFormat;

        drv = ICLocate(pmt->majortype.Data1, pmt->subtype.Data1, &format->bmiHeader, NULL, ICMODE_DECOMPRESS);
        if (drv)
        {
            AM_MEDIA_TYPE* outpmt = &((OutputPin*)This->tf.ppPins[1])->pin.mtCurrent;
            const CLSID* outsubtype;
            DWORD bih_size;

            switch(format->bmiHeader.biBitCount)
            {
                case 32: outsubtype = &MEDIASUBTYPE_RGB32; break;
                case 24: outsubtype = &MEDIASUBTYPE_RGB24; break;
                case 16: outsubtype = &MEDIASUBTYPE_RGB565; break;
                case 8:  outsubtype = &MEDIASUBTYPE_RGB8; break;
                default:
                    FIXME("Depth %d not supported\n", format->bmiHeader.biBitCount);
                    ICClose(drv);
                    return S_FALSE;
            }
            CopyMediaType(outpmt, pmt);
            outpmt->subtype = *outsubtype;
            This->hvid = drv;

            /* Copy bitmap header from media type to 1 for input and 1 for output */
            if (This->pBihIn) {
                CoTaskMemFree(This->pBihIn);
                CoTaskMemFree(This->pBihOut);
            }
            bih_size = format->bmiHeader.biSize + format->bmiHeader.biClrUsed * 4;
            This->pBihIn = (BITMAPINFOHEADER*)CoTaskMemAlloc(bih_size);
            if (!This->pBihIn)
            {
                ICClose(drv);
                return E_OUTOFMEMORY;
            }
            This->pBihOut = (BITMAPINFOHEADER*)CoTaskMemAlloc(bih_size);
            if (!This->pBihOut)
            {
                CoTaskMemFree(This->pBihIn);
                This->pBihIn = NULL;
                ICClose(drv);
                return E_OUTOFMEMORY;
            }
            memcpy(This->pBihIn, &format->bmiHeader, bih_size);
            memcpy(This->pBihOut, &format->bmiHeader, bih_size);

            /* Update output format as non compressed bitmap */
            This->pBihOut->biCompression = 0;
            This->pBihOut->biSizeImage = This->pBihOut->biWidth * This->pBihOut->biHeight * This->pBihOut->biBitCount / 8;

            /* Update buffer size of media samples in output */
            ((OutputPin*)This->tf.ppPins[1])->allocProps.cbBuffer = This->pBihOut->biSizeImage;

            TRACE("Connection accepted\n");
            return S_OK;
        }
        TRACE("Unable to find a suitable VFW decompressor\n");
    }

    TRACE("Connection refused\n");
    return S_FALSE;
}

static HRESULT AVIDec_Cleanup(TransformFilterImpl* pTransformFilter)
{
    AVIDecImpl* This = (AVIDecImpl*)pTransformFilter;

    TRACE("(%p)->()\n", This);
    
    if (This->hvid)
        ICClose(This->hvid);

    if (This->pBihIn) {
        CoTaskMemFree(This->pBihIn);
        CoTaskMemFree(This->pBihOut);
    }

    This->hvid = NULL;
    This->pBihIn = NULL;

    return S_OK;
}

HRESULT AVIDec_create(IUnknown * pUnkOuter, LPVOID * ppv)
{
    HRESULT hr;
    AVIDecImpl * This;

    TRACE("(%p, %p)\n", pUnkOuter, ppv);

    *ppv = NULL;

    if (pUnkOuter)
        return CLASS_E_NOAGGREGATION;

    /* Note: This memory is managed by the transform filter once created */
    This = CoTaskMemAlloc(sizeof(AVIDecImpl));

    This->hvid = NULL;
    This->pBihIn = NULL;

    hr = TransformFilter_Create(&(This->tf), &CLSID_AVIDec, AVIDec_SendSampleData, AVIDec_ConnectInput, AVIDec_Cleanup);

    if (FAILED(hr))
        return hr;

    *ppv = (LPVOID)This;

    return hr;
}
