summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/aviio.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/aviio.cpp')
-rw-r--r--src/lib/util/aviio.cpp145
1 files changed, 131 insertions, 14 deletions
diff --git a/src/lib/util/aviio.cpp b/src/lib/util/aviio.cpp
index 47c8023d3a0..b7849ee36cc 100644
--- a/src/lib/util/aviio.cpp
+++ b/src/lib/util/aviio.cpp
@@ -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;
@@ -1484,6 +1489,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)
{