// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/*********************************************************************

    avivideo.cpp

    Image device for AVI video.

*********************************************************************/

#include "emu.h"
#include "avivideo.h"
#include "aviio.h"

/***************************************************************************
    TYPE DEFINITIONS
***************************************************************************/

// device type definition
DEFINE_DEVICE_TYPE(IMAGE_AVIVIDEO, avivideo_image_device, "avivideo_image", "AVI Video Image")

//-------------------------------------------------
//  avivideo_image_device - constructor
//-------------------------------------------------

avivideo_image_device::avivideo_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
	device_t(mconfig, IMAGE_AVIVIDEO, tag, owner, clock),
	device_image_interface(mconfig, *this),
	m_frame(),
	m_avi(),
	m_frame_timer(nullptr),
	m_frame_count(0),
	m_frame_num(0)
{
}

//-------------------------------------------------
//  avivideo_image_device - destructor
//-------------------------------------------------

avivideo_image_device::~avivideo_image_device()
{
	call_unload();
}


void avivideo_image_device::device_start()
{
	m_frame_timer = timer_alloc(FUNC(avivideo_image_device::frame_timer), this);
	m_frame_timer->adjust(attotime::never);

	save_item(NAME(m_frame_count));
	save_item(NAME(m_frame_num));
}

void avivideo_image_device::device_reset()
{
	m_frame_num = 0;
}

TIMER_CALLBACK_MEMBER(avivideo_image_device::frame_timer)
{
	if (m_avi)
	{
		avi_file::error avierr = m_avi->read_uncompressed_video_frame(m_frame_num, *m_frame);
		if (avierr != avi_file::error::NONE)
		{
			m_frame_timer->adjust(attotime::never);
			return;
		}
		m_frame_num++;
		if (m_frame_num >= m_frame_count)
		{
			m_frame_num = 0;
		}
	}
	else
	{
		m_frame_timer->adjust(attotime::never);
	}
}

std::pair<std::error_condition, std::string> avivideo_image_device::call_load()
{
	m_frame.reset(new bitmap_argb32);
	avi_file::error avierr = avi_file::open(filename(), m_avi);
	if (avierr != avi_file::error::NONE)
	{
		m_frame.reset();
		return std::make_pair(image_error::UNSPECIFIED, std::string());
	}

	const avi_file::movie_info &aviinfo = m_avi->get_movie_info();
	float frame_rate = (float)aviinfo.video_timescale / (float)aviinfo.video_sampletime;
	attotime frame_time = attotime::from_hz((int)round(frame_rate));
	m_frame_timer->adjust(frame_time, 0, frame_time);
	m_frame_count = aviinfo.video_numsamples;
	m_frame_num = 0;
	return std::make_pair(std::error_condition(), std::string());
}

void avivideo_image_device::call_unload()
{
	m_frame.reset();
	m_avi.reset();
}
