#include "flv_vp6_decoder.h"
#include "../nsv/nsvlib.h"
#include "../libvp6/include/vp6.h"
int FLVDecoderCreator::CreateVideoDecoder(int format_type, int width, int height, ifc_flvvideodecoder **decoder)
{
	if (format_type == FLV::VIDEO_FORMAT_VP6 || format_type == FLV::VIDEO_FORMAT_VP62)
	{
		//DXL_XIMAGE_HANDLE xim = DXL_CreateXImageOfType((unsigned char *)"" , format_type == FLV::VIDEO_FORMAT_VP6?NSV_MAKETYPE('V','P','6','0'):NSV_MAKETYPE('V','P','6','2'));
		DXL_XIMAGE_HANDLE xim = DXL_AlterXImage( NULL, (unsigned char *)"" ,NSV_MAKETYPE('V','P','6','0'), DXRGBNULL, 0, 0);
		if (!xim)
			return CREATEDECODER_FAILURE;
		*decoder = new FLVVP6(xim);
		return CREATEDECODER_SUCCESS;
	}
	return CREATEDECODER_NOT_MINE;
}

int FLVDecoderCreator::HandlesVideo(int format_type)
{
	if (format_type == FLV::VIDEO_FORMAT_VP6 || format_type == FLV::VIDEO_FORMAT_VP62)
	{
		return CREATEDECODER_SUCCESS;
	}
	return CREATEDECODER_NOT_MINE;
}

#define CBCLASS FLVDecoderCreator
START_DISPATCH;
CB(CREATE_VIDEO_DECODER, CreateVideoDecoder)
CB(HANDLES_VIDEO, HandlesVideo)
END_DISPATCH;
#undef CBCLASS

static const int vp6_postProcess=6;
static const int vp6_cpuFree=70;
static const int vp6_deInterlace=0;
static const int vp6_addNoise=1;

 enum
{
	PBC_SET_POSTPROC,
	PBC_SET_CPUFREE,
    PBC_MAX_PARAM,
	PBC_SET_TESTMODE,
	PBC_SET_PBSTRUCT,
	PBC_SET_BLACKCLAMP,
	PBC_SET_WHITECLAMP,
	PBC_SET_REFERENCEFRAME,
    PBC_SET_DEINTERLACEMODE,
    PBC_SET_ADDNOISE

} ;

 extern "C" 
 {
  void GetImageBufs(DXL_XIMAGE_HANDLE x, YV12_PLANES *p);
  void vp60_SetParameter(DXL_XIMAGE_HANDLE src, int Command, uintptr_t Parameter );
};

FLVVP6::FLVVP6(DXL_XIMAGE_HANDLE xim) : xim(xim)
{
	decoded=0;

	if(vp6_cpuFree)
		vp60_SetParameter(xim, PBC_SET_CPUFREE, vp6_cpuFree);
	else
		vp60_SetParameter(xim, PBC_SET_POSTPROC, vp6_postProcess);

	vp60_SetParameter(xim, PBC_SET_DEINTERLACEMODE, vp6_deInterlace );
	vp60_SetParameter(xim, PBC_SET_ADDNOISE, vp6_addNoise);
  vp60_SetParameter(xim, PBC_SET_BLACKCLAMP,0);
	vp60_SetParameter(xim, PBC_SET_WHITECLAMP,0);
}

int FLVVP6::GetOutputFormat(int *x, int *y, int *color_format)
{
	if (xim)
	{
		if (vp60_getWH(xim, x, y) == DXL_OK)
		{
			*color_format = NSV_MAKETYPE('Y','V','1','2');
			return FLV_VIDEO_SUCCESS;
		}
	}
	return FLV_VIDEO_FAILURE;
}

int FLVVP6::DecodeSample(const void *inputBuffer, size_t inputBufferBytes, int32_t timestamp)
{
	uint8_t *vp6_data = (uint8_t *)inputBuffer;
	if (inputBufferBytes)
	{
		// skip first byte
		vp6_data++;
		inputBufferBytes--;
	
		DXL_AlterXImageData(xim, (unsigned char *)vp6_data);
		DXL_SetXImageCSize(xim, inputBufferBytes);
		if (!vp60_decompress(xim))
		{
			decoded=1;
			return FLV_VIDEO_SUCCESS;
		}
	}

	return FLV_VIDEO_FAILURE;

}

void FLVVP6::Close()
{
	if (xim)
		DXL_DestroyXImage(xim);

	delete this;
}

int FLVVP6::GetPicture(void **data, void **decoder_data, uint64_t *timestamp)
{
	if (decoded)
	{
		GetImageBufs(xim,&vidbufdec);
		*data=&vidbufdec;
		*decoder_data = 0;
		decoded = 0;
		return FLV_VIDEO_SUCCESS;
	}

	return FLV_VIDEO_FAILURE;
}


#define CBCLASS FLVVP6
START_DISPATCH;
CB(FLV_VIDEO_GETOUTPUTFORMAT, GetOutputFormat)
CB(FLV_VIDEO_DECODE, DecodeSample)
VCB(FLV_VIDEO_CLOSE, Close)
CB(FLV_VIDEO_GET_PICTURE, GetPicture)
END_DISPATCH;
#undef CBCLASS