#include "nsv_h264_decoder.h"
#include "../nsv/nsvlib.h"
#include "../nsv/dec_if.h"
#include <assert.h>
#include <Mferror.h>

H264_Decoder::H264_Decoder()
{
	vidbufdec=0;
	last_pic = 0;
	decoder.Open();
}

H264_Decoder::~H264_Decoder()
{	
	for (size_t i=0;i<buffered_frames.size();i++) {
		nullsoft_h264_frame_data frame_data = buffered_frames[i];
		decoder.FreeFrame((YV12_PLANES *)frame_data.data, frame_data.decoder_data);
	}

	decoder.FreeFrame(vidbufdec, last_pic);
}

int H264_Decoder::decode(int need_kf, 
						 void *_in, int _in_len,
						 void **out, // out is set to a pointer to data
						 unsigned int *out_type, // 'Y','V','1','2' is currently defined
						 int *is_kf)
{
	*out_type=NSV_MAKETYPE('Y','V','1','2');

	if (last_pic)
	{
		decoder.FreeFrame(vidbufdec, last_pic);
		vidbufdec=0;
		last_pic=0;
	}

	if (_in_len) {
		for (;;) {
			HRESULT hr = decoder.FeedRaw(_in, _in_len, 0);
			if (hr == MF_E_NOTACCEPTING) {
				nullsoft_h264_frame_data frame_data;
				if (FAILED(decoder.GetFrame((YV12_PLANES **)&frame_data.data, &frame_data.decoder_data, &frame_data.local_timestamp))) {
					continue;
				}
				buffered_frames.push_back(frame_data);
			} else if (FAILED(hr)) {
				return -1;
			} else {
				break;
			}
		}
	} else {
		decoder.Drain();
	}

	if (SUCCEEDED(decoder.GetFrame(&vidbufdec, &last_pic, 0))) {
		*out = vidbufdec;
		*is_kf = 1;
	} else {
		*out = 0;
	}

	return 0;
}

void H264_Decoder::flush()
{
	for ( size_t i = 0; i < buffered_frames.size(); i++ )
	{
		nullsoft_h264_frame_data frame_data = buffered_frames[ i ];
		decoder.FreeFrame( (YV12_PLANES *)frame_data.data, frame_data.decoder_data );
	}

	decoder.Flush();
}