-avivideo.cpp: Added an image device to provide looping uncompressed AVI frames as input. [Ryan Holtz]

-vino.cpp: Adapted to support both avivideo_image_device and picture_image_device. [Ryan Holtz]
This commit is contained in:
mooglyguy 2019-09-23 17:42:03 +02:00 committed by MooglyGuy
parent 15dfa918a7
commit 1a5bf558cc
9 changed files with 248 additions and 38 deletions

View File

@ -65,6 +65,8 @@ files {
MAME_DIR .. "src/devices/imagedev/snapquik.h",
MAME_DIR .. "src/devices/imagedev/wafadrive.cpp",
MAME_DIR .. "src/devices/imagedev/wafadrive.h",
MAME_DIR .. "src/devices/imagedev/avivideo.cpp",
MAME_DIR .. "src/devices/imagedev/avivideo.h",
}

View File

@ -0,0 +1,118 @@
// 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(nullptr),
m_avi(nullptr),
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(TIMER_FRAME);
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;
}
void avivideo_image_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
if (id == TIMER_FRAME)
{
if (m_avi != nullptr)
{
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);
}
}
}
image_init_result avivideo_image_device::call_load()
{
m_frame = new bitmap_argb32;
avi_file::error avierr = avi_file::open(filename(), m_avi);
if (avierr != avi_file::error::NONE)
{
delete m_frame;
m_frame = nullptr;
return image_init_result::FAIL;
}
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 image_init_result::PASS;
}
void avivideo_image_device::call_unload()
{
if (m_frame)
{
delete m_frame;
m_frame = nullptr;
}
if (m_avi)
{
m_avi.release();
m_avi = nullptr;
}
}

View File

@ -0,0 +1,67 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
/*********************************************************************
avivideo.h
Image device for AVI video.
*********************************************************************/
#ifndef MAME_DEVICES_IMAGEDEV_AVIVIDEO_H
#define MAME_DEVICES_IMAGEDEV_AVIVIDEO_H
#pragma once
#include "bitmap.h"
#include "aviio.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
// ======================> avivideo_image_device
class avivideo_image_device : public device_t, public device_image_interface
{
public:
// construction/destruction
avivideo_image_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
virtual ~avivideo_image_device();
// image-level overrides
virtual image_init_result call_load() override;
virtual void call_unload() override;
virtual iodevice_t image_type() const override { return IO_VIDEO; }
virtual bool is_readable() const override { return 1; }
virtual bool is_writeable() const override { return 0; }
virtual bool is_creatable() const override { return 0; }
virtual bool must_be_loaded() const override { return 0; }
virtual bool is_reset_on_load() const override { return 0; }
virtual const char *file_extensions() const override { return "avi"; }
bitmap_argb32 &get_frame() { return *m_frame; }
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private:
static constexpr device_timer_id TIMER_FRAME = 0;
bitmap_argb32 *m_frame;
avi_file::ptr m_avi;
emu_timer *m_frame_timer;
uint32_t m_frame_count;
uint32_t m_frame_num;
};
// device type definition
DECLARE_DEVICE_TYPE(IMAGE_AVIVIDEO, avivideo_image_device)
#endif // MAME_DEVICES_IMAGEDEV_AVIVIDEO_H

View File

@ -27,26 +27,27 @@
//**************************************************************************
const image_device_type_info device_image_interface::m_device_info_array[] =
{
{ IO_UNKNOWN, "unknown", "unkn" },
{ IO_CARTSLOT, "cartridge", "cart" }, /* 0 */
{ IO_FLOPPY, "floppydisk", "flop" }, /* 1 */
{ IO_HARDDISK, "harddisk", "hard" }, /* 2 */
{ IO_CYLINDER, "cylinder", "cyln" }, /* 3 */
{ IO_CASSETTE, "cassette", "cass" }, /* 4 */
{ IO_PUNCHCARD, "punchcard", "pcrd" }, /* 5 */
{ IO_PUNCHTAPE, "punchtape", "ptap" }, /* 6 */
{ IO_PRINTER, "printout", "prin" }, /* 7 */
{ IO_SERIAL, "serial", "serl" }, /* 8 */
{ IO_PARALLEL, "parallel", "parl" }, /* 9 */
{ IO_SNAPSHOT, "snapshot", "dump" }, /* 10 */
{ IO_QUICKLOAD, "quickload", "quik" }, /* 11 */
{ IO_MEMCARD, "memcard", "memc" }, /* 12 */
{ IO_CDROM, "cdrom", "cdrm" }, /* 13 */
{ IO_MAGTAPE, "magtape", "magt" }, /* 14 */
{ IO_ROM, "romimage", "rom" }, /* 15 */
{ IO_MIDIIN, "midiin", "min" }, /* 16 */
{ IO_MIDIOUT, "midiout", "mout" }, /* 17 */
{ IO_PICTURE, "picture", "pic" } /* 18 */
{ IO_UNKNOWN, "unknown", "unkn" }, /* 0 */
{ IO_CARTSLOT, "cartridge", "cart" }, /* 1 */
{ IO_FLOPPY, "floppydisk", "flop" }, /* 2 */
{ IO_HARDDISK, "harddisk", "hard" }, /* 3 */
{ IO_CYLINDER, "cylinder", "cyln" }, /* 4 */
{ IO_CASSETTE, "cassette", "cass" }, /* 5 */
{ IO_PUNCHCARD, "punchcard", "pcrd" }, /* 6 */
{ IO_PUNCHTAPE, "punchtape", "ptap" }, /* 7 */
{ IO_PRINTER, "printout", "prin" }, /* 8 */
{ IO_SERIAL, "serial", "serl" }, /* 9 */
{ IO_PARALLEL, "parallel", "parl" }, /* 10 */
{ IO_SNAPSHOT, "snapshot", "dump" }, /* 11 */
{ IO_QUICKLOAD, "quickload", "quik" }, /* 12 */
{ IO_MEMCARD, "memcard", "memc" }, /* 13 */
{ IO_CDROM, "cdrom", "cdrm" }, /* 14 */
{ IO_MAGTAPE, "magtape", "magt" }, /* 15 */
{ IO_ROM, "romimage", "rom" }, /* 16 */
{ IO_MIDIIN, "midiin", "min" }, /* 17 */
{ IO_MIDIOUT, "midiout", "mout" }, /* 18 */
{ IO_PICTURE, "picture", "pic" }, /* 19 */
{ IO_VIDEO, "vidfile", "vid" } /* 20 */
};

View File

@ -51,7 +51,8 @@ enum iodevice_t
IO_MIDIIN, /* 17 - MIDI In port */
IO_MIDIOUT, /* 18 - MIDI Out port */
IO_PICTURE, /* 19 - A single-frame image */
IO_COUNT /* 20 - Total Number of IO_devices for searching */
IO_VIDEO, /* 20 - A video file */
IO_COUNT /* 21 - Total Number of IO_devices for searching */
};
enum image_error_t

View File

@ -366,8 +366,8 @@ public:
avi_file::error huffyuv_decompress_to_yuy16(const std::uint8_t *data, std::uint32_t numbytes, bitmap_yuy16 &bitmap) const;
// Uncompressed helpers
avi_file::error uncompressed_rgb24_to_rgb32(const std::uint8_t *data, std::uint32_t numbytes, bitmap_rgb32 &bitmap) const;
avi_file::error uncompressed_yuv420p_to_rgb32(const std::uint8_t *data, std::uint32_t numbytes, bitmap_rgb32 &bitmap) const;
avi_file::error uncompressed_rgb24_to_argb32(const std::uint8_t *data, std::uint32_t numbytes, bitmap_argb32 &bitmap) const;
avi_file::error uncompressed_yuv420p_to_argb32(const std::uint8_t *data, std::uint32_t numbytes, bitmap_argb32 &bitmap) const;
private:
struct huffyuv_table
@ -460,7 +460,7 @@ public:
virtual movie_info const &get_movie_info() const override;
virtual std::uint32_t first_sample_in_frame(std::uint32_t framenum) const override;
virtual error read_uncompressed_video_frame(std::uint32_t framenum, bitmap_rgb32 &bitmap) override;
virtual error read_uncompressed_video_frame(std::uint32_t framenum, bitmap_argb32 &bitmap) override;
virtual error read_video_frame(std::uint32_t framenum, bitmap_yuy16 &bitmap) override;
virtual error read_sound_samples(int channel, std::uint32_t firstsample, std::uint32_t numsamples, std::int16_t *output) override;
@ -1489,11 +1489,11 @@ avi_file::error avi_stream::huffyuv_decompress_to_yuy16(const std::uint8_t *data
/*-------------------------------------------------
uncompressed_rgb24_to_rgb32 - convert a raw
RGB24-encoded frame to an RGB32 bitmap
uncompressed_rgb24_to_argb32 - convert a raw
RGB24-encoded frame to an ARGB32 bitmap
-------------------------------------------------*/
avi_file::error avi_stream::uncompressed_rgb24_to_rgb32(const std::uint8_t *data, std::uint32_t numbytes, bitmap_rgb32 &bitmap) const
avi_file::error avi_stream::uncompressed_rgb24_to_argb32(const std::uint8_t *data, std::uint32_t numbytes, bitmap_argb32 &bitmap) const
{
std::uint32_t dataoffs = 0;
@ -1517,11 +1517,11 @@ avi_file::error avi_stream::uncompressed_rgb24_to_rgb32(const std::uint8_t *data
/*-------------------------------------------------
uncompressed_yuv420p_to_rgb32 - convert a
YUV420p-encoded frame to an RGB32 bitmap
uncompressed_yuv420p_to_argb32 - convert a
YUV420p-encoded frame to an ARGB32 bitmap
-------------------------------------------------*/
avi_file::error avi_stream::uncompressed_yuv420p_to_rgb32(const std::uint8_t *data, std::uint32_t numbytes, bitmap_rgb32 &bitmap) const
avi_file::error avi_stream::uncompressed_yuv420p_to_argb32(const std::uint8_t *data, std::uint32_t numbytes, bitmap_argb32 &bitmap) const
{
const int width = bitmap.width();
const int height = bitmap.height();
@ -1676,10 +1676,10 @@ std::uint32_t avi_file_impl::first_sample_in_frame(std::uint32_t framenum) const
/*-------------------------------------------------
read_uncompressed_video_frame - read raw video
data for a particular frame from the AVI file,
converting to RGB32 format
converting to ARGB32 format
-------------------------------------------------*/
avi_file::error avi_file_impl::read_uncompressed_video_frame(std::uint32_t framenum, bitmap_rgb32 &bitmap)
avi_file::error avi_file_impl::read_uncompressed_video_frame(std::uint32_t framenum, bitmap_argb32 &bitmap)
{
/* get the video stream */
avi_stream *const stream = get_video_stream();
@ -1718,9 +1718,9 @@ avi_file::error avi_file_impl::read_uncompressed_video_frame(std::uint32_t frame
{
/* uncompressed YUV420p */
if (stream->format() == FORMAT_I420)
avierr = stream->uncompressed_yuv420p_to_rgb32(&m_tempbuffer[8], stream->chunk(framenum).length - 8, bitmap);
avierr = stream->uncompressed_yuv420p_to_argb32(&m_tempbuffer[8], stream->chunk(framenum).length - 8, bitmap);
else
avierr = stream->uncompressed_rgb24_to_rgb32(&m_tempbuffer[8], stream->chunk(framenum).length - 8, bitmap);
avierr = stream->uncompressed_rgb24_to_argb32(&m_tempbuffer[8], stream->chunk(framenum).length - 8, bitmap);
}
else
{

View File

@ -119,7 +119,7 @@ public:
virtual movie_info const &get_movie_info() const = 0;
virtual std::uint32_t first_sample_in_frame(std::uint32_t framenum) const = 0;
virtual error read_uncompressed_video_frame(std::uint32_t framenum, bitmap_rgb32 &bitmap) = 0;
virtual error read_uncompressed_video_frame(std::uint32_t framenum, bitmap_argb32 &bitmap) = 0;
virtual error read_video_frame(std::uint32_t framenum, bitmap_yuy16 &bitmap) = 0;
virtual error read_sound_samples(int channel, std::uint32_t firstsample, std::uint32_t numsamples, std::int16_t *output) = 0;

View File

@ -37,6 +37,7 @@ vino_device::vino_device(const machine_config &mconfig, const char *tag, device_
, m_i2c_stop(*this)
, m_interrupt_cb(*this)
, m_picture(*this, "srcimg")
, m_avivideo(*this, "srcavi")
, m_space(*this, finder_base::DUMMY_TAG, -1)
, m_input_bitmap(nullptr)
{
@ -142,6 +143,7 @@ void vino_device::device_reset()
void vino_device::device_add_mconfig(machine_config &config)
{
IMAGE_PICTURE(config, m_picture);
IMAGE_AVIVIDEO(config, m_avivideo);
}
void vino_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
@ -494,12 +496,14 @@ void vino_device::end_of_field(int channel)
}
else if (is_even_field(channel))
{
LOGMASKED(LOG_FIELDS, "Even field ended, setting page index to %08x\n", chan.m_line_size + 8);
line_count_w(channel, 0);
page_index_w(channel, chan.m_line_size + 8);
next_desc_w(channel, chan.m_start_desc_ptr);
}
else // odd field
{
LOGMASKED(LOG_FIELDS, "Odd field ended, setting page index to %08x\n", 0);
line_count_w(channel, 0);
page_index_w(channel, 0);
chan.m_start_desc_ptr = chan.m_next_desc_ptr;
@ -729,8 +733,14 @@ uint32_t vino_device::bilinear_pixel(float s, float t)
if (m_input_bitmap == nullptr)
return 0xff000000;
const uint32_t width = m_input_bitmap->width() - 1;
const uint32_t height = m_input_bitmap->height() - 1;
uint32_t width = m_input_bitmap->width();
uint32_t height = m_input_bitmap->height();
if (width == 0 || height == 0)
return 0xff000000;
width--;
height--;
int32_t s0 = (int32_t)floorf(s * width);
int32_t s1 = (int32_t)floorf(s * width + 1);
@ -763,7 +773,7 @@ uint32_t vino_device::bilinear_pixel(float s, float t)
void vino_device::input_pixel(int channel, int32_t &y, int32_t &u, int32_t &v)
{
m_input_bitmap = &m_picture->get_bitmap();
m_input_bitmap = &m_avivideo->get_frame();
if (m_input_bitmap)
{
channel_t &chan = m_channels[channel];
@ -804,6 +814,15 @@ void vino_device::fetch_pixel(int channel)
input_pixel(channel, y, u, v);
process_pixel(channel, y, u, v);
}
else
{
count_pixel(channel);
if (chan.m_end_of_field)
{
end_of_field(channel);
chan.m_end_of_field = false;
}
}
}
attotime vino_device::calculate_field_rate(int channel)

View File

@ -15,6 +15,7 @@
#include "bitmap.h"
#include "imagedev/picture.h"
#include "imagedev/avivideo.h"
class vino_device : public device_t
{
@ -247,6 +248,7 @@ private:
devcb_write_line m_interrupt_cb;
required_device<picture_image_device> m_picture;
required_device<avivideo_image_device> m_avivideo;
required_address_space m_space;
bitmap_argb32 *m_input_bitmap;