]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/dsicinav.c
Merge remote-tracking branch 'qatar/master'
[ffmpeg] / libavcodec / dsicinav.c
index 27f42041ba0c844a29006518fcd71f96e7983d96..53d4f90d2e5fea6780f9331db86877ed846fe579 100644 (file)
@@ -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;
@@ -217,7 +217,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;
@@ -305,7 +309,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;
@@ -318,29 +326,35 @@ 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;
 }