X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fdsicinav.c;h=cbf7c4a6f821cfa803a674ce4d7c2184633f3748;hb=ea2bb12e3e47baa0f8d50ef68be678f425c7e4cf;hp=643aed946b6898af82d11568eaee2e4adc426037;hpb=2912e87a6c9264d556734e2bf94a99c64cf9b102;p=ffmpeg diff --git a/libavcodec/dsicinav.c b/libavcodec/dsicinav.c index 643aed946b6..cbf7c4a6f82 100644 --- a/libavcodec/dsicinav.c +++ b/libavcodec/dsicinav.c @@ -26,6 +26,7 @@ #include "avcodec.h" #include "bytestream.h" +#include "mathops.h" typedef enum CinVideoBitmapIndex { @@ -43,7 +44,6 @@ typedef struct CinVideoContext { } CinVideoContext; typedef struct CinAudioContext { - AVCodecContext *avctx; int initial_decode_frame; int delta; } CinAudioContext; @@ -216,7 +216,11 @@ static int cinvideo_decode_frame(AVCodecContext *avctx, bitmap_frame_size = buf_size - 4; /* handle palette */ + if (bitmap_frame_size < palette_colors_count * (3 + (palette_type != 0))) + return AVERROR_INVALIDDATA; if (palette_type == 0) { + if (palette_colors_count > 256) + return AVERROR_INVALIDDATA; for (i = 0; i < palette_colors_count; ++i) { cin->palette[i] = bytestream_get_le24(&buf); bitmap_frame_size -= 3; @@ -304,7 +308,11 @@ static av_cold int cinaudio_decode_init(AVCodecContext *avctx) { CinAudioContext *cin = avctx->priv_data; - cin->avctx = avctx; + if (avctx->channels != 1) { + av_log_ask_for_sample(avctx, "Number of channels is not supported\n"); + return AVERROR_PATCHWELCOME; + } + cin->initial_decode_frame = 1; cin->delta = 0; avctx->sample_fmt = AV_SAMPLE_FMT_S16; @@ -317,53 +325,56 @@ static int cinaudio_decode_frame(AVCodecContext *avctx, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; CinAudioContext *cin = avctx->priv_data; - const uint8_t *src = buf; - int16_t *samples = (int16_t *)data; - - buf_size = FFMIN(buf_size, *data_size/2); + const uint8_t *buf_end = buf + avpkt->size; + int16_t *samples = data; + int delta, out_size; + + out_size = (avpkt->size - cin->initial_decode_frame) * + av_get_bytes_per_sample(avctx->sample_fmt); + if (*data_size < out_size) { + av_log(avctx, AV_LOG_ERROR, "Output buffer is too small\n"); + return AVERROR(EINVAL); + } + delta = cin->delta; if (cin->initial_decode_frame) { cin->initial_decode_frame = 0; - cin->delta = (int16_t)AV_RL16(src); src += 2; - *samples++ = cin->delta; - buf_size -= 2; + delta = sign_extend(AV_RL16(buf), 16); + buf += 2; + *samples++ = delta; } - while (buf_size > 0) { - cin->delta += cinaudio_delta16_table[*src++]; - cin->delta = av_clip_int16(cin->delta); - *samples++ = cin->delta; - --buf_size; + while (buf < buf_end) { + delta += cinaudio_delta16_table[*buf++]; + delta = av_clip_int16(delta); + *samples++ = delta; } + cin->delta = delta; - *data_size = (uint8_t *)samples - (uint8_t *)data; + *data_size = out_size; - return src - buf; + return avpkt->size; } AVCodec ff_dsicinvideo_decoder = { - "dsicinvideo", - AVMEDIA_TYPE_VIDEO, - CODEC_ID_DSICINVIDEO, - sizeof(CinVideoContext), - cinvideo_decode_init, - NULL, - cinvideo_decode_end, - cinvideo_decode_frame, - CODEC_CAP_DR1, + .name = "dsicinvideo", + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_DSICINVIDEO, + .priv_data_size = sizeof(CinVideoContext), + .init = cinvideo_decode_init, + .close = cinvideo_decode_end, + .decode = cinvideo_decode_frame, + .capabilities = CODEC_CAP_DR1, .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN video"), }; AVCodec ff_dsicinaudio_decoder = { - "dsicinaudio", - AVMEDIA_TYPE_AUDIO, - CODEC_ID_DSICINAUDIO, - sizeof(CinAudioContext), - cinaudio_decode_init, - NULL, - NULL, - cinaudio_decode_frame, + .name = "dsicinaudio", + .type = AVMEDIA_TYPE_AUDIO, + .id = CODEC_ID_DSICINAUDIO, + .priv_data_size = sizeof(CinAudioContext), + .init = cinaudio_decode_init, + .decode = cinaudio_decode_frame, .long_name = NULL_IF_CONFIG_SMALL("Delphine Software International CIN audio"), };