]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/shorten.c
Set more KMVC palettes opaque.
[ffmpeg] / libavcodec / shorten.c
index 5ffd634e245fa8dcb1257db87d02f5edf56f9dcc..ee01e886a979ffecb3e31e6069653b6e9ff729d2 100644 (file)
@@ -2,20 +2,20 @@
  * Shorten decoder
  * Copyright (c) 2005 Jeff Muizelaar
  *
- * This file is part of Libav.
+ * This file is part of FFmpeg.
  *
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2.1 of the License, or (at your option) any later version.
  *
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
@@ -102,6 +102,8 @@ typedef struct ShortenContext {
     int blocksize;
     int bitindex;
     int32_t lpcqoffset;
+    int got_header;
+    int got_quit_command;
 } ShortenContext;
 
 static av_cold int shorten_decode_init(AVCodecContext * avctx)
@@ -250,12 +252,13 @@ static int decode_wave_header(AVCodecContext *avctx, const uint8_t *header,
     return 0;
 }
 
-static int16_t * interleave_buffer(int16_t *samples, int nchan, int blocksize, int32_t **buffer) {
+static void interleave_buffer(int16_t *samples, int nchan, int blocksize,
+                              int32_t **buffer)
+{
     int i, chan;
     for (i=0; i<blocksize; i++)
         for (chan=0; chan < nchan; chan++)
-            *samples++ = FFMIN(buffer[chan][i], 32768);
-    return samples;
+            *samples++ = av_clip_int16(buffer[chan][i]);
 }
 
 static const int fixed_coeffs[3][3] = {
@@ -386,6 +389,8 @@ static int read_header(ShortenContext *s)
     s->cur_chan = 0;
     s->bitshift = 0;
 
+    s->got_header = 1;
+
     return 0;
 }
 
@@ -422,13 +427,15 @@ static int shorten_decode_frame(AVCodecContext *avctx,
             memmove(s->bitstream, &s->bitstream[s->bitstream_index], s->bitstream_size);
             s->bitstream_index=0;
         }
-        memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf, buf_size);
+        if (buf)
+            memcpy(&s->bitstream[s->bitstream_index + s->bitstream_size], buf, buf_size);
         buf= &s->bitstream[s->bitstream_index];
         buf_size += s->bitstream_size;
         s->bitstream_size= buf_size;
 
-        /* do not decode until buffer has at least max_framesize bytes */
-        if(buf_size < s->max_framesize){
+        /* do not decode until buffer has at least max_framesize bytes or
+           the end of the file has been reached */
+        if (buf_size < s->max_framesize && avpkt->data) {
             *data_size = 0;
             return input_buf_size;
         }
@@ -438,25 +445,35 @@ static int shorten_decode_frame(AVCodecContext *avctx,
     skip_bits(&s->gb, s->bitindex);
 
     /* process header or next subblock */
-    if (!s->blocksize)
-    {
+    if (!s->got_header) {
         if ((ret = read_header(s)) < 0)
             return ret;
         *data_size = 0;
+        goto finish_frame;
     }
-    else
-    {
+
+    /* if quit command was read previously, don't decode anything */
+    if (s->got_quit_command) {
+        *data_size = 0;
+        return avpkt->size;
+    }
+
+    s->cur_chan = 0;
+    while (s->cur_chan < s->channels) {
         int cmd;
         int len;
+
+        if (get_bits_left(&s->gb) < 3+FNSIZE) {
+            *data_size = 0;
+            break;
+        }
+
         cmd = get_ur_golomb_shorten(&s->gb, FNSIZE);
 
         if (cmd > FN_VERBATIM) {
             av_log(avctx, AV_LOG_ERROR, "unknown shorten function %d\n", cmd);
-            if (s->bitstream_size > 0) {
-                s->bitstream_index++;
-                s->bitstream_size--;
-            }
-            return -1;
+            *data_size = 0;
+            break;
         }
 
         if (!is_audio_command[cmd]) {
@@ -486,9 +503,13 @@ static int shorten_decode_frame(AVCodecContext *avctx,
                     break;
                 }
                 case FN_QUIT:
+                    s->got_quit_command = 1;
                     break;
             }
-            *data_size = 0;
+            if (cmd == FN_BLOCKSIZE || cmd == FN_QUIT) {
+                *data_size = 0;
+                break;
+            }
         } else {
             /* process audio command */
             int residual_size = 0;
@@ -550,15 +571,21 @@ static int shorten_decode_frame(AVCodecContext *avctx,
             /* if this is the last channel in the block, output the samples */
             s->cur_chan++;
             if (s->cur_chan == s->channels) {
-                samples = interleave_buffer(samples, s->channels, s->blocksize, s->decoded);
-                s->cur_chan = 0;
-                *data_size = (int8_t *)samples - (int8_t *)data;
-            } else {
-                *data_size = 0;
+                int out_size = s->blocksize * s->channels *
+                               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);
+                }
+                interleave_buffer(samples, s->channels, s->blocksize, s->decoded);
+                *data_size = out_size;
             }
         }
     }
+    if (s->cur_chan < s->channels)
+        *data_size = 0;
 
+finish_frame:
     s->bitindex = get_bits_count(&s->gb) - 8*((get_bits_count(&s->gb))/8);
     i= (get_bits_count(&s->gb))/8;
     if (i > buf_size) {
@@ -598,5 +625,6 @@ AVCodec ff_shorten_decoder = {
     .init           = shorten_decode_init,
     .close          = shorten_decode_close,
     .decode         = shorten_decode_frame,
+    .capabilities   = CODEC_CAP_DELAY,
     .long_name= NULL_IF_CONFIG_SMALL("Shorten"),
 };