#include <Uncompressed.h>
#include <except.h>
#include <cstdio> // sprintf

#define __MODULE__ "Unc_Decoder"

Unc_Decoder::Unc_Decoder(const CodecInfo& info, const BITMAPINFOHEADER& h, int flip)
    :IVideoDecoder(info, h)
{
    fourcc_t c = (fourcc_t) m_bh->biCompression;
    if (!flip && c != 0 && c != 3)
	m_bh->biHeight *= -1;
    // do not change order
    m_obh = *m_bh;
    m_decoder = m_obh;
    switch (c)
    {
    case fccYUY2:
	m_Cap = CAP_YUY2;
        break;
    case fccYV12:
	m_Cap = CAP_YV12;
	break;
    case 0:
    case 3:
	m_Cap = CAP_NONE;
	break;
    default:
        char msg[100];
	sprintf(msg, "unsupported format: 0x%x  (%.4s)!", c, (char*)&c);
        throw FATAL(msg);
    }

    VBUFSIZE = 4;
    QMARKHI = 2;
    QMARKLO = 0;
    m_fQuality = 1.0f; // it's uncompressed - so 100%
}

Unc_Decoder::~Unc_Decoder()
{
    Stop();
}

int Unc_Decoder::DecodeInternal(void* src, size_t size, int is_keyframe, CImage* pImage)
{
    int add = 0;

    BitmapInfo bi(*m_bh);
    CImage* ci = new CImage(&bi, (uint8_t*)src, false);
    pImage->Convert(ci);
    ci->Release();
    return 0;
}

int Unc_Decoder::SetDestFmt(int bits, fourcc_t csp)
{
    if (!CImage::Supported(csp, bits))
	return -1;

    //printf("SETDESTFMT %d   %.4s\n", bits, (char*) &csp);
    if (csp)
    {
	switch (csp)
	{
	case fccYV12:
	case fccYUY2:
	    m_obh.SetSpace(csp);
	    break;
	default:
	    return 1;
	}
    }
    else if (bits)
    {
	switch(bits)
	{
	case 15:
	case 16:
	case 24:
	case 32:
	    m_obh.SetBits(bits);
	    break;
	default:
	    return 1;
	}
    }
    m_decoder = m_obh;
    Restart();
    return 0;
}

void Unc_Decoder::StartInternal()
{
}

void Unc_Decoder::StopInternal()
{
}


Unc_Encoder::Unc_Encoder(const CodecInfo& info, fourcc_t compressor, const BITMAPINFOHEADER& header)
    :IVideoEncoder(info), head(header)
{
    head.biCompression = compressor;
    switch (compressor)
    {
    case fccYUY2:
    case fccYV12:
	head.SetSpace(compressor);
	break;
    }
    chead = head;
    //head.biHeight = labs(head.biHeight);
}

int Unc_Encoder::QueryOutputSize() const
{
    return head.biSizeImage;
}

const BITMAPINFOHEADER& Unc_Encoder::QueryOutputFormat() const
{
    head.Print();
    return head;
}

int Unc_Encoder::EncodeFrame(CImage* src, void* dest, int* is_keyframe, size_t* size, int* lpckid)
{
    if (!src)
	return -1;
    if (head.biCompression == src->GetFmt()->biCompression)
    {
	memcpy(dest, src->Data(), src->Bytes());
    }
    else
    {
	CImage* ci = new CImage(&chead, (uint8_t*)dest, false);
        ci->Convert(src);
        ci->Release();
    }
    if (size)
	*size = head.biSizeImage;
    if (is_keyframe)
	*is_keyframe = 16;//AVIIF_KEYFRAME
    return 0;
}
