mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
-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:
parent
15dfa918a7
commit
1a5bf558cc
@ -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",
|
||||
}
|
||||
|
||||
|
||||
|
118
src/devices/imagedev/avivideo.cpp
Normal file
118
src/devices/imagedev/avivideo.cpp
Normal 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;
|
||||
}
|
||||
}
|
67
src/devices/imagedev/avivideo.h
Normal file
67
src/devices/imagedev/avivideo.h
Normal 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
|
@ -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 */
|
||||
};
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user