diff options
Diffstat (limited to 'Src/bmp/avi_rgb_decoder.cpp')
-rw-r--r-- | Src/bmp/avi_rgb_decoder.cpp | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/Src/bmp/avi_rgb_decoder.cpp b/Src/bmp/avi_rgb_decoder.cpp new file mode 100644 index 00000000..e93b9ff1 --- /dev/null +++ b/Src/bmp/avi_rgb_decoder.cpp @@ -0,0 +1,175 @@ +#include "avi_rgb_decoder.h" +#include "../Winamp/wa_ipc.h" +#include <bfc/error.h> +#include <limits.h> +#include <intsafe.h> + +int BMP_GetMallocSize(int32_t height, int32_t width, int32_t bits_per_pixel, size_t *out_frame_bytes) +{ + if (height < 0 || width < 0) + { + return NErr_Error; + } + + uint64_t frame_size = (uint64_t)height * (uint64_t)width; + if (frame_size > SIZE_MAX) + return NErr_IntegerOverflow; + + uint64_t frame_bytes = frame_size * (uint64_t)bits_per_pixel; + if (frame_bytes > SIZE_MAX || frame_bytes < frame_size) + return NErr_IntegerOverflow; + + *out_frame_bytes = (size_t)(frame_bytes / 8); + return NErr_Success; +} + +AVIRGB *AVIRGB::CreateDecoder(nsavi::video_format *stream_format) +{ + + AVIRGB *decoder = new AVIRGB(stream_format); + if (!decoder) + { + return 0; + } + + if (decoder->Initialize() != NErr_Success) + { + delete decoder; + return 0; + } + + return decoder; +} + + +AVIRGB::AVIRGB(nsavi::video_format *stream_format) : stream_format(stream_format) +{ + palette_retrieved=false; + video_frame=0; + video_frame_size_bytes=0; + + + if (stream_format->size_bytes == 1064) + { + memset(palette, 0, sizeof(palette)); + memcpy(palette, (uint8_t *)stream_format + 44, 1024); + } + o=false; +} + +AVIRGB::~AVIRGB() +{ + free(video_frame); +} + +int AVIRGB::Initialize() +{ + size_t frame_bytes; + int ret = BMP_GetMallocSize(stream_format->height, stream_format->width, stream_format->bits_per_pixel, &frame_bytes); + if (ret != NErr_Success) + return ret; + + video_frame=malloc(frame_bytes); + if (!video_frame) + return NErr_OutOfMemory; + + video_frame_size_bytes = frame_bytes; + + return NErr_Success; +} + +int AVIRGB::GetPalette(RGB32 **palette) +{ + if (!palette_retrieved) + { + *palette = (RGB32 *)(this->palette); + palette_retrieved=true; + return AVI_SUCCESS; + } + else + { + return AVI_FAILURE; + } + +} + +int AVIRGB::GetOutputProperties(int *x, int *y, int *color_format, double *aspect_ratio, int *flip) +{ + if (stream_format) + { + *x = stream_format->width; + *y = stream_format->height; + *flip = 1; + switch(stream_format->bits_per_pixel) + { + case 8: + *color_format = '8BGR'; + break; + // TODO: + //case 16: + //*color_format = '8GBR'; + case 24: + *color_format = '42GR'; + break; + case 32: + *color_format = '23GR'; + break; + default: + return AVI_FAILURE; + } + return AVI_SUCCESS; + } + + return AVI_FAILURE; +} + +int AVIRGB::DecodeChunk(uint16_t type, const void *inputBuffer, size_t inputBufferBytes) +{ + if (stream_format) + { + if (video_frame_size_bytes < inputBufferBytes) + return AVI_FAILURE; + memcpy(video_frame, inputBuffer, inputBufferBytes); + //video_frame = inputBuffer; // heh + o=true; + return AVI_SUCCESS; + } + + return AVI_FAILURE; +} + +void AVIRGB::Flush() +{ + +} + +int AVIRGB::GetPicture(void **data, void **decoder_data) +{ + if (o && video_frame) + { + *data =(void *) video_frame; + *decoder_data=0; + //video_frame=0; + o=false; + //video_outputted=true; + return AVI_SUCCESS; + } + + return AVI_FAILURE; +} + +void AVIRGB::Close() +{ + delete this; +} + +#define CBCLASS AVIRGB +START_DISPATCH; +CB(GET_OUTPUT_PROPERTIES, GetOutputProperties) +CB(DECODE_CHUNK, DecodeChunk) +VCB(FLUSH, Flush) +VCB(CLOSE, Close) +CB(GET_PICTURE, GetPicture) +CB(GET_PALETTE, GetPalette) +END_DISPATCH; +#undef CBCLASS |