From 1a5bf558cc9889c2f45a6c0eea68a00615ac5e1e Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Mon, 23 Sep 2019 17:42:03 +0200 Subject: [PATCH] -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] --- scripts/src/machine.lua | 2 + src/devices/imagedev/avivideo.cpp | 118 ++++++++++++++++++++++++++++++ src/devices/imagedev/avivideo.h | 67 +++++++++++++++++ src/emu/diimage.cpp | 41 ++++++----- src/emu/diimage.h | 3 +- src/lib/util/aviio.cpp | 26 +++---- src/lib/util/aviio.h | 2 +- src/mame/machine/vino.cpp | 25 ++++++- src/mame/machine/vino.h | 2 + 9 files changed, 248 insertions(+), 38 deletions(-) create mode 100644 src/devices/imagedev/avivideo.cpp create mode 100644 src/devices/imagedev/avivideo.h diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua index 7986a41f2b4..fb14dd8ba3a 100644 --- a/scripts/src/machine.lua +++ b/scripts/src/machine.lua @@ -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", } diff --git a/src/devices/imagedev/avivideo.cpp b/src/devices/imagedev/avivideo.cpp new file mode 100644 index 00000000000..0c3559a127a --- /dev/null +++ b/src/devices/imagedev/avivideo.cpp @@ -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; + } +} diff --git a/src/devices/imagedev/avivideo.h b/src/devices/imagedev/avivideo.h new file mode 100644 index 00000000000..8feb78b262e --- /dev/null +++ b/src/devices/imagedev/avivideo.h @@ -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 diff --git a/src/emu/diimage.cpp b/src/emu/diimage.cpp index cdbcbb1edf4..953e89dc42c 100644 --- a/src/emu/diimage.cpp +++ b/src/emu/diimage.cpp @@ -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 */ }; diff --git a/src/emu/diimage.h b/src/emu/diimage.h index 4a3ed06d6cc..437546f27c6 100644 --- a/src/emu/diimage.h +++ b/src/emu/diimage.h @@ -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 diff --git a/src/lib/util/aviio.cpp b/src/lib/util/aviio.cpp index 728781dd8fc..bd93cbe1847 100644 --- a/src/lib/util/aviio.cpp +++ b/src/lib/util/aviio.cpp @@ -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 { diff --git a/src/lib/util/aviio.h b/src/lib/util/aviio.h index 8497a039a53..c951f71b22f 100644 --- a/src/lib/util/aviio.h +++ b/src/lib/util/aviio.h @@ -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; diff --git a/src/mame/machine/vino.cpp b/src/mame/machine/vino.cpp index 5b0c8e0f74c..5e7280bb881 100644 --- a/src/mame/machine/vino.cpp +++ b/src/mame/machine/vino.cpp @@ -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) diff --git a/src/mame/machine/vino.h b/src/mame/machine/vino.h index 3214f1f9d48..2de5da5996c 100644 --- a/src/mame/machine/vino.h +++ b/src/mame/machine/vino.h @@ -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 m_picture; + required_device m_avivideo; required_address_space m_space; bitmap_argb32 *m_input_bitmap;