diff options
author | 2008-05-13 03:02:11 +0000 | |
---|---|---|
committer | 2008-05-13 03:02:11 +0000 | |
commit | 86dd599aa8887e656f50d70e3e6318d6c05360c1 (patch) | |
tree | aad3806efbc62954adfcf22473aecb5131edbc22 /src/lib | |
parent | 5c918815e4b16c623a313e983f38d8febebf1526 (diff) |
Added uncompressed AVI recording. Extended aviio to be able
to write RGB bitmaps. Unfortunately, the only option is fully
uncompressed, which means the resulting AVIs are *HUGE* and
may not play correctly in realtime due to high data rate. The
intention is that these uncompressed AVIs are post-processed
by other utilities to compress the video and produce a
realtime playable result.
Added new command-line option -aviwrite which works just like
-mngwrite, except it produces AVIs and streams sound to them.
Updated documentation accordingly.
Shift+F12 still produces MNGs for now, though this might change
in the future.
Modified fileio.c to retain the full pathname to the file so
that it can be queried while the file is open.
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/util/aviio.c | 116 | ||||
-rw-r--r-- | src/lib/util/aviio.h | 3 |
2 files changed, 112 insertions, 7 deletions
diff --git a/src/lib/util/aviio.c b/src/lib/util/aviio.c index c4edafd9b3c..80484524f5c 100644 --- a/src/lib/util/aviio.c +++ b/src/lib/util/aviio.c @@ -52,11 +52,6 @@ #define HANDLER_DIB AVI_FOURCC('D','I','B',' ') #define HANDLER_HFYU AVI_FOURCC('h','f','y','u') -#define FORMAT_UYVY AVI_FOURCC('U','Y','V','Y') -#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') - /* main AVI header files */ #define AVIF_HASINDEX 0x00000010 #define AVIF_MUSTUSEINDEX 0x00000020 @@ -224,6 +219,9 @@ static avi_error soundbuf_initialize(avi_file *file); static avi_error soundbuf_write_chunk(avi_file *file, UINT32 framenum); static avi_error soundbuf_flush(avi_file *file, int only_flush_full); +/* RGB helpers */ +static avi_error rgb32_compress_to_rgb(avi_stream *stream, const bitmap_t *bitmap, UINT8 *data, UINT32 numbytes); + /* YUY helpers */ static avi_error yuv_decompress_to_yuy16(avi_stream *stream, const UINT8 *data, UINT32 numbytes, bitmap_t *bitmap); static avi_error yuy16_compress_to_yuy(avi_stream *stream, const bitmap_t *bitmap, UINT8 *data, UINT32 numbytes); @@ -928,6 +926,10 @@ avi_error avi_append_video_frame_yuy16(avi_file *file, const bitmap_t *bitmap) avi_error avierr; UINT32 maxlength; + /* validate our ability to handle the data */ + if (stream->format != FORMAT_UYVY && stream->format != FORMAT_VYUY && stream->format != FORMAT_YUY2 && stream->format != FORMAT_HFYU) + return AVIERR_UNSUPPORTED_VIDEO_FORMAT; + /* double check bitmap format */ if (bitmap->format != BITMAP_FORMAT_YUY16) return AVIERR_INVALID_BITMAP; @@ -960,11 +962,61 @@ avi_error avi_append_video_frame_yuy16(avi_file *file, const bitmap_t *bitmap) /*------------------------------------------------- + avi_append_video_frame_rgb32 - append a frame + of video in RGB32 format +-------------------------------------------------*/ + +avi_error avi_append_video_frame_rgb32(avi_file *file, const bitmap_t *bitmap) +{ + avi_stream *stream = get_video_stream(file); + avi_error avierr; + UINT32 maxlength; + + /* validate our ability to handle the data */ + if (stream->format != 0) + return AVIERR_UNSUPPORTED_VIDEO_FORMAT; + + /* depth must be 24 */ + if (stream->depth != 24) + return AVIERR_UNSUPPORTED_VIDEO_FORMAT; + + /* double check bitmap format */ + if (bitmap->format != BITMAP_FORMAT_RGB32) + return AVIERR_INVALID_BITMAP; + + /* write out any sound data first */ + avierr = soundbuf_write_chunk(file, stream->chunks); + if (avierr != AVIERR_NONE) + return avierr; + + /* make sure we have enough room */ + maxlength = 3 * stream->width * stream->height; + avierr = expand_tempbuffer(file, maxlength); + if (avierr != AVIERR_NONE) + return avierr; + + /* copy the RGB data to the destination */ + avierr = rgb32_compress_to_rgb(stream, bitmap, file->tempbuffer, maxlength); + if (avierr != AVIERR_NONE) + return avierr; + + /* set the info for this new chunk */ + avierr = set_stream_chunk_info(stream, stream->chunks, file->writeoffs, maxlength + 8); + if (avierr != AVIERR_NONE) + return avierr; + stream->samples = file->info.video_numsamples = stream->chunks; + + /* write the data */ + return chunk_write(file, get_chunkid_for_stream(file, stream), file->tempbuffer, maxlength); +} + + +/*------------------------------------------------- avi_append_sound_samples - append sound samples -------------------------------------------------*/ -avi_error avi_append_sound_samples(avi_file *file, int channel, const INT16 *samples, UINT32 numsamples) +avi_error avi_append_sound_samples(avi_file *file, int channel, const INT16 *samples, UINT32 numsamples, UINT32 sampleskip) { UINT32 sampoffset = file->soundbuf_chansamples[channel]; UINT32 sampnum; @@ -977,6 +1029,7 @@ avi_error avi_append_sound_samples(avi_file *file, int channel, const INT16 *sam for (sampnum = 0; sampnum < numsamples; sampnum++) { INT16 data = *samples++; + samples += sampleskip; data = LITTLE_ENDIANIZE_INT16(data); file->soundbuf[sampoffset++ * file->info.audio_channels + channel] = data; } @@ -2240,6 +2293,57 @@ static avi_error soundbuf_flush(avi_file *file, int only_flush_full) /*------------------------------------------------- + rgb32_compress_to_rgb - "compress" an RGB32 + bitmap to an RGB encoded frame +-------------------------------------------------*/ + +static avi_error rgb32_compress_to_rgb(avi_stream *stream, const bitmap_t *bitmap, UINT8 *data, UINT32 numbytes) +{ + int height = MIN(stream->height, bitmap->height); + int width = MIN(stream->width, bitmap->width); + UINT8 *dataend = data + numbytes; + int x, y; + + /* compressed video */ + for (y = 0; y < height; y++) + { + const UINT32 *source = (UINT32 *)bitmap->base + y * bitmap->rowpixels; + UINT8 *dest = data + (stream->height - 1 - y) * stream->width * 3; + + for (x = 0; x < width && dest < dataend; x++) + { + UINT32 pix = *source++; + *dest++ = RGB_BLUE(pix); + *dest++ = RGB_GREEN(pix); + *dest++ = RGB_RED(pix); + } + + /* fill in any blank space on the right */ + for ( ; x < stream->width && dest < dataend; x++) + { + *dest++ = 0; + *dest++ = 0; + *dest++ = 0; + } + } + + /* fill in any blank space on the bottom */ + for ( ; y < stream->height; y++) + { + UINT8 *dest = data + (stream->height - 1 - y) * stream->width * 3; + for (x = 0; x < stream->width && dest < dataend; x++) + { + *dest++ = 0; + *dest++ = 0; + *dest++ = 0; + } + } + + return AVIERR_NONE; +} + + +/*------------------------------------------------- yuv_decompress_to_yuy16 - decompress a YUV encoded frame to a YUY16 bitmap -------------------------------------------------*/ diff --git a/src/lib/util/aviio.h b/src/lib/util/aviio.h index 37e949e6961..9c9e938893e 100644 --- a/src/lib/util/aviio.h +++ b/src/lib/util/aviio.h @@ -118,6 +118,7 @@ avi_error avi_read_video_frame_yuy16(avi_file *file, UINT32 framenum, bitmap_t * avi_error avi_read_sound_samples(avi_file *file, int channel, UINT32 firstsample, UINT32 numsamples, INT16 *output); avi_error avi_append_video_frame_yuy16(avi_file *file, const bitmap_t *bitmap); -avi_error avi_append_sound_samples(avi_file *file, int channel, const INT16 *samples, UINT32 numsamples); +avi_error avi_append_video_frame_rgb32(avi_file *file, const bitmap_t *bitmap); +avi_error avi_append_sound_samples(avi_file *file, int channel, const INT16 *samples, UINT32 numsamples, UINT32 sampleskip); #endif |