
#include "AviWrite.h"
#include <cstring>

//#include "AviVideoWriteStream.h"

using namespace Creators;
using namespace std;

AviVideoWriteStream::AviVideoWriteStream(AviWriteFile* file, int ckid,
					 fourcc_t fourcc,
					 BITMAPINFOHEADER* srchdr,
					 int frame_rate, int flags)
    :AviWriteStream(file, ckid, Video, fourcc, frame_rate, flags ),
    m_vstatus(0), m_local_buffer(0)
{
    m_pIEnc = CreateVideoEncoder(fourcc, *srchdr);
    if (!m_pIEnc)
	throw FATAL("Could not create encoder");
}

AviVideoWriteStream::~AviVideoWriteStream()
{
    if (m_pIEnc)
	FreeVideoEncoder(m_pIEnc);
    if (m_local_buffer)
	delete[] m_local_buffer;
}
//    void Create(int fourcc, BITMAPINFOHEADER* srchdr)
//    {
//	m_encoder.Init(fourcc, (const char*)srchdr);
//	m_vstatus=1;
//	m_fourcc=fourcc;
//	SetType(Video);
//        return;
//    }
//    virtual void SetHeader(int frame_rate,
//            int flags=0)
//    {
//	if(m_vstatus!=1)throw FATAL("Bad status");
//	AviWriteStream::SetHeader(m_fourcc, frame_rate, 0, m_encoder.GetQuality(), flags);
//    }

HRESULT AviVideoWriteStream::Start()
{
    if (m_vstatus)
	return -1;
    BITMAPINFOHEADER bh = m_pIEnc->QueryOutputFormat();
    m_forsize = sizeof(BITMAPINFOHEADER);
    m_format = new uint8_t[m_forsize];
    memcpy(m_format, &bh, m_forsize);
    m_pIEnc->Start();
    m_local_buffer = new uint8_t[m_pIEnc->QueryOutputSize()];
    SetVideoData(m_pIEnc->GetQuality(), bh.biWidth, bh.biHeight);
    m_vstatus = 1;
    return 0;
}

HRESULT AviVideoWriteStream::Stop()
{
    m_pIEnc->Stop();
    return 0;
}

HRESULT AviVideoWriteStream::AddFrame(CImage* chunk, size_t* pSize = 0, int* pKeyframe = 0)
{
    if (m_vstatus != 1)
    {
	if(pSize)
	    *pSize = 0;
	return -1;
    }

    size_t size = 0;
    int is_keyframe=0;
    HRESULT hr;
    if (chunk)
    {
	hr = m_pIEnc->EncodeFrame(chunk, m_local_buffer, &is_keyframe, &size);
	if (hr == 0)
	{
	    hr = AviWriteStream::AddChunk(m_local_buffer, size, is_keyframe);
	}
	else
	{
	    size = 0;
            is_keyframe = 0;
	}

    }
    else
	hr = AviWriteStream::AddChunk(NULL, 0);

    if (pSize)
	*pSize = size;
    if (pKeyframe)
	if(is_keyframe & 16)
	    *pKeyframe = 1;
	else
	    *pKeyframe = 0;
    return hr;
}

HRESULT AviVideoWriteStream::SetQuality(int quality)
{
    return m_pIEnc->SetQuality(quality);
}

HRESULT AviVideoWriteStream::SetKeyFrame(int frequency)
{
    return m_pIEnc->SetKeyFrame(frequency);
}

unsigned int AviVideoWriteStream::GetLength() const
{
    return AviWriteStream::GetLength();
}
