mirror of
https://github.com/holub/mame
synced 2025-05-31 10:01:51 +03:00
-aviio: Added functionality to read RGB24 and YUV420p uncompressed video frames. [Ryan Holtz]
This commit is contained in:
parent
da6da2eeb4
commit
7dc59ce975
@ -365,6 +365,10 @@ public:
|
||||
// HuffYUV helpers
|
||||
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;
|
||||
|
||||
private:
|
||||
struct huffyuv_table
|
||||
{
|
||||
@ -456,6 +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_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;
|
||||
|
||||
@ -1483,6 +1488,73 @@ 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
|
||||
-------------------------------------------------*/
|
||||
|
||||
avi_file::error avi_stream::uncompressed_rgb24_to_rgb32(const std::uint8_t *data, std::uint32_t numbytes, bitmap_rgb32 &bitmap) const
|
||||
{
|
||||
std::uint32_t dataoffs = 0;
|
||||
|
||||
/* uncompressed video */
|
||||
for (int y = 0; y < m_height; y++)
|
||||
{
|
||||
std::uint32_t *dest = &bitmap.pix32(y);
|
||||
|
||||
/* loop over pixels */
|
||||
for (int x = 0; x < m_width; x++)
|
||||
{
|
||||
const uint8_t b = data[dataoffs++];
|
||||
const uint8_t g = data[dataoffs++];
|
||||
const uint8_t r = data[dataoffs++];
|
||||
*dest++ = 0xff << 24 | r << 16 | g << 8 | b;
|
||||
}
|
||||
}
|
||||
|
||||
return avi_file::error::NONE;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
uncompressed_yuv420p_to_rgb32 - convert a
|
||||
YUV420p-encoded frame to an RGB32 bitmap
|
||||
-------------------------------------------------*/
|
||||
|
||||
avi_file::error avi_stream::uncompressed_yuv420p_to_rgb32(const std::uint8_t *data, std::uint32_t numbytes, bitmap_rgb32 &bitmap) const
|
||||
{
|
||||
const int width = bitmap.width();
|
||||
const int height = bitmap.height();
|
||||
const int size_total = width * height;
|
||||
|
||||
/* uncompressed video */
|
||||
for (int y = 0; y < m_height; y++)
|
||||
{
|
||||
std::uint32_t *dest = &bitmap.pix32(y);
|
||||
|
||||
/* loop over pixels */
|
||||
for (int x = 0; x < m_width; x++)
|
||||
{
|
||||
const uint8_t luma = data[y * width + x];
|
||||
const uint8_t u = data[(y / 2) * (width / 2) + x / 2 + size_total];
|
||||
const uint8_t v = data[(y / 2) * (width / 2) + x / 2 + size_total + size_total / 4];
|
||||
|
||||
int r = luma + (1.370705f * (v - 0x80));
|
||||
int g = luma - (0.698001f * (v - 0x80)) - (0.337633f * (u - 0x80));
|
||||
int b = luma + (1.732446f * (u - 0x80));
|
||||
|
||||
r = (r < 0) ? 0 : ((r > 255) ? 255 : r);
|
||||
g = (g < 0) ? 0 : ((g > 255) ? 255 : g);
|
||||
b = (b < 0) ? 0 : ((b > 255) ? 255 : b);
|
||||
|
||||
*dest++ = 0xff << 24 | r << 16 | g << 8 | b;
|
||||
}
|
||||
}
|
||||
|
||||
return avi_file::error::NONE;
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
avi_close - close an AVI movie file
|
||||
-------------------------------------------------*/
|
||||
@ -1602,22 +1674,67 @@ std::uint32_t avi_file_impl::first_sample_in_frame(std::uint32_t framenum) const
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
avi_read_video_frame - read video data
|
||||
for a particular frame from the AVI file,
|
||||
converting to YUY16 format
|
||||
read_uncompressed_video_frame - read raw video
|
||||
data for a particular frame from the AVI file,
|
||||
converting to RGB32 format
|
||||
-------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @fn avi_error avi_read_video_frame(avi_file *file, std::uint32_t framenum, bitmap_yuy16 &bitmap)
|
||||
*
|
||||
* @brief Avi read video frame.
|
||||
*
|
||||
* @param [in,out] file If non-null, the file.
|
||||
* @param framenum The framenum.
|
||||
* @param [in,out] bitmap The bitmap.
|
||||
*
|
||||
* @return An avi_error.
|
||||
*/
|
||||
avi_file::error avi_file_impl::read_uncompressed_video_frame(std::uint32_t framenum, bitmap_rgb32 &bitmap)
|
||||
{
|
||||
/* get the video stream */
|
||||
avi_stream *const stream = get_video_stream();
|
||||
if (!stream)
|
||||
return error::INVALID_STREAM;
|
||||
|
||||
if (stream->format() != FORMAT_UNCOMPRESSED && stream->format() != FORMAT_DIB && stream->format() != FORMAT_RGB && stream->format() != FORMAT_RAW && stream->format() != FORMAT_I420)
|
||||
return error::UNSUPPORTED_VIDEO_FORMAT;
|
||||
|
||||
if (bitmap.width() < stream->width() || bitmap.height() < stream->height())
|
||||
bitmap.resize(stream->width(), stream->height());
|
||||
|
||||
/* assume one chunk == one frame */
|
||||
if (framenum >= stream->chunks())
|
||||
return error::INVALID_FRAME;
|
||||
|
||||
/* we only support YUY-style bitmaps (16bpp) */
|
||||
if (bitmap.width() < stream->width() || bitmap.height() < stream->height())
|
||||
return error::INVALID_BITMAP;
|
||||
|
||||
/* expand the tempbuffer to hold the data if necessary */
|
||||
error avierr = error::NONE;
|
||||
avierr = expand_tempbuffer(stream->chunk(framenum).length);
|
||||
if (avierr != error::NONE)
|
||||
return avierr;
|
||||
|
||||
/* read in the data */
|
||||
std::uint32_t bytes_read;
|
||||
osd_file::error const filerr = m_file->read(&m_tempbuffer[0], stream->chunk(framenum).offset, stream->chunk(framenum).length, bytes_read);
|
||||
if (filerr != osd_file::error::NONE || bytes_read != stream->chunk(framenum).length)
|
||||
return error::READ_ERROR;
|
||||
|
||||
/* validate this is good data */
|
||||
std::uint32_t const chunkid = fetch_32bits(&m_tempbuffer[0]);
|
||||
if (chunkid == get_chunkid_for_stream(stream))
|
||||
{
|
||||
/* uncompressed YUV420p */
|
||||
if (stream->format() == FORMAT_I420)
|
||||
avierr = stream->uncompressed_yuv420p_to_rgb32(&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);
|
||||
}
|
||||
else
|
||||
{
|
||||
avierr = error::INVALID_DATA;
|
||||
}
|
||||
|
||||
return avierr;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
read_video_frame - read video data for a
|
||||
particular frame from the AVI file, converting
|
||||
to YUY16 format
|
||||
-------------------------------------------------*/
|
||||
|
||||
avi_file::error avi_file_impl::read_video_frame(std::uint32_t framenum, bitmap_yuy16 &bitmap)
|
||||
{
|
||||
|
@ -29,7 +29,11 @@
|
||||
#define FORMAT_VYUY AVI_FOURCC('V','Y','U','Y')
|
||||
#define FORMAT_YUY2 AVI_FOURCC('Y','U','Y','2')
|
||||
#define FORMAT_HFYU AVI_FOURCC('H','F','Y','U')
|
||||
|
||||
#define FORMAT_I420 AVI_FOURCC('I','4','2','0')
|
||||
#define FORMAT_DIB AVI_FOURCC('D','I','B',' ')
|
||||
#define FORMAT_RGB AVI_FOURCC('R','G','B',' ')
|
||||
#define FORMAT_RAW AVI_FOURCC('R','A','W',' ')
|
||||
#define FORMAT_UNCOMPRESSED 0x00000000
|
||||
|
||||
|
||||
class avi_file
|
||||
@ -115,6 +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_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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user