]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/cook.c
Revert "mpegvideo: remove abort() in ff_find_unused_picture()"
[ffmpeg] / libavcodec / cook.c
index 462a8c40fc9765f8ba08fa0dc64a0c498ef73961..b285f88a152cf6bcc56a7048155c0080e9e36f4f 100644 (file)
@@ -3,20 +3,20 @@
  * Copyright (c) 2003 Sascha Sommer
  * Copyright (c) 2005 Benjamin Larsson
  *
- * 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
  */
 
@@ -122,6 +122,7 @@ typedef struct cook {
     void (* saturate_output) (struct cook *q, int chan, float *out);
 
     AVCodecContext*     avctx;
+    AVFrame             frame;
     GetBitContext       gb;
     /* stream data */
     int                 nb_channels;
@@ -131,6 +132,7 @@ typedef struct cook {
     int                 samples_per_channel;
     /* states */
     AVLFG               random_state;
+    int                 discarded_packets;
 
     /* transform data */
     FFTContext          mdct_ctx;
@@ -273,6 +275,10 @@ static av_cold void init_cplscales_table (COOKContext *q) {
  */
 
 static inline int decode_bytes(const uint8_t* inbuffer, uint8_t* out, int bytes){
+    static const uint32_t tab[4] = {
+        AV_BE2NE32C(0x37c511f2), AV_BE2NE32C(0xf237c511),
+        AV_BE2NE32C(0x11f237c5), AV_BE2NE32C(0xc511f237),
+    };
     int i, off;
     uint32_t c;
     const uint32_t* buf;
@@ -285,7 +291,7 @@ static inline int decode_bytes(const uint8_t* inbuffer, uint8_t* out, int bytes)
 
     off = (intptr_t)inbuffer & 3;
     buf = (const uint32_t*) (inbuffer - off);
-    c = av_be2ne32((0x37c511f2 >> (off*8)) | (0x37c511f2 << (32-(off*8))));
+    c = tab[off];
     bytes += 3 + off;
     for (i = 0; i < bytes/4; i++)
         obuf[i] = c ^ buf[i];
@@ -892,7 +898,8 @@ mlt_compensate_output(COOKContext *q, float *decode_buffer,
                       float *out, int chan)
 {
     imlt_gain(q, decode_buffer, gains_ptr, previous_buffer);
-    q->saturate_output (q, chan, out);
+    if (out)
+        q->saturate_output(q, chan, out);
 }
 
 
@@ -949,19 +956,30 @@ static void decode_subpacket(COOKContext *q, COOKSubpacket *p,
  * @param avctx     pointer to the AVCodecContext
  */
 
-static int cook_decode_frame(AVCodecContext *avctx,
-            void *data, int *data_size,
-            AVPacket *avpkt) {
+static int cook_decode_frame(AVCodecContext *avctx, void *data,
+                             int *got_frame_ptr, AVPacket *avpkt)
+{
     const uint8_t *buf = avpkt->data;
     int buf_size = avpkt->size;
     COOKContext *q = avctx->priv_data;
-    int i;
+    float *samples = NULL;
+    int i, ret;
     int offset = 0;
     int chidx = 0;
 
     if (buf_size < avctx->block_align)
         return buf_size;
 
+    /* get output buffer */
+    if (q->discarded_packets >= 2) {
+        q->frame.nb_samples = q->samples_per_channel;
+        if ((ret = avctx->get_buffer(avctx, &q->frame)) < 0) {
+            av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+            return ret;
+        }
+        samples = (float *)q->frame.data[0];
+    }
+
     /* estimate subpacket sizes */
     q->subpacket[0].size = avctx->block_align;
 
@@ -975,21 +993,25 @@ static int cook_decode_frame(AVCodecContext *avctx,
     }
 
     /* decode supbackets */
-    *data_size = 0;
     for(i=0;i<q->num_subpackets;i++){
         q->subpacket[i].bits_per_subpacket = (q->subpacket[i].size*8)>>q->subpacket[i].bits_per_subpdiv;
         q->subpacket[i].ch_idx = chidx;
         av_log(avctx,AV_LOG_DEBUG,"subpacket[%i] size %i js %i %i block_align %i\n",i,q->subpacket[i].size,q->subpacket[i].joint_stereo,offset,avctx->block_align);
-        decode_subpacket(q, &q->subpacket[i], buf + offset, data);
+        decode_subpacket(q, &q->subpacket[i], buf + offset, samples);
         offset += q->subpacket[i].size;
         chidx += q->subpacket[i].num_channels;
         av_log(avctx,AV_LOG_DEBUG,"subpacket[%i] %i %i\n",i,q->subpacket[i].size * 8,get_bits_count(&q->gb));
     }
-    *data_size = q->nb_channels * q->samples_per_channel *
-                 av_get_bytes_per_sample(avctx->sample_fmt);
 
     /* Discard the first two frames: no valid audio. */
-    if (avctx->frame_number < 2) *data_size = 0;
+    if (q->discarded_packets < 2) {
+        q->discarded_packets++;
+        *got_frame_ptr = 0;
+        return avctx->block_align;
+    }
+
+    *got_frame_ptr   = 1;
+    *(AVFrame *)data = q->frame;
 
     return avctx->block_align;
 }
@@ -1070,7 +1092,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
             q->subpacket[s].subbands = bytestream_get_be16(&edata_ptr);
             extradata_size -= 8;
         }
-        if (avctx->extradata_size >= 8){
+        if (extradata_size >= 8) {
             bytestream_get_be32(&edata_ptr);    //Unknown unused
             q->subpacket[s].js_subband_start = bytestream_get_be16(&edata_ptr);
             q->subpacket[s].js_vlc_bits = bytestream_get_be16(&edata_ptr);
@@ -1094,7 +1116,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
             case MONO:
                 if (q->nb_channels != 1) {
                     av_log_ask_for_sample(avctx, "Container channels != 1.\n");
-                    return AVERROR(ENOTSUP);
+                    return AVERROR_PATCHWELCOME;
                 }
                 av_log(avctx,AV_LOG_DEBUG,"MONO\n");
                 break;
@@ -1108,7 +1130,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
             case JOINT_STEREO:
                 if (q->nb_channels != 2) {
                     av_log_ask_for_sample(avctx, "Container channels != 2.\n");
-                    return AVERROR(ENOTSUP);
+                    return AVERROR_PATCHWELCOME;
                 }
                 av_log(avctx,AV_LOG_DEBUG,"JOINT_STEREO\n");
                 if (avctx->extradata_size >= 16){
@@ -1146,7 +1168,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
                 break;
             default:
                 av_log_ask_for_sample(avctx, "Unknown Cook version.\n");
-                return AVERROR(ENOTSUP);
+                return AVERROR_PATCHWELCOME;
         }
 
         if(s > 1 && q->subpacket[s].samples_per_channel != q->samples_per_channel) {
@@ -1162,7 +1184,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
         /* Try to catch some obviously faulty streams, othervise it might be exploitable */
         if (q->subpacket[s].total_subbands > 53) {
             av_log_ask_for_sample(avctx, "total_subbands > 53\n");
-            return AVERROR(ENOTSUP);
+            return AVERROR_PATCHWELCOME;
         }
 
         if ((q->subpacket[s].js_vlc_bits > 6) || (q->subpacket[s].js_vlc_bits < 2*q->subpacket[s].joint_stereo)) {
@@ -1173,7 +1195,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
 
         if (q->subpacket[s].subbands > 50) {
             av_log_ask_for_sample(avctx, "subbands > 50\n");
-            return AVERROR(ENOTSUP);
+            return AVERROR_PATCHWELCOME;
         }
         q->subpacket[s].gains1.now      = q->subpacket[s].gain_1;
         q->subpacket[s].gains1.previous = q->subpacket[s].gain_2;
@@ -1184,7 +1206,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
         s++;
         if (s > MAX_SUBPACKETS) {
             av_log_ask_for_sample(avctx, "Too many subpackets > 5\n");
-            return AVERROR(ENOTSUP);
+            return AVERROR_PATCHWELCOME;
         }
     }
     /* Generate tables */
@@ -1228,7 +1250,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
         av_log_ask_for_sample(avctx,
                               "unknown amount of samples_per_channel = %d\n",
                               q->samples_per_channel);
-        return AVERROR(ENOTSUP);
+        return AVERROR_PATCHWELCOME;
     }
 
     avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
@@ -1237,6 +1259,9 @@ static av_cold int cook_decode_init(AVCodecContext *avctx)
     else
         avctx->channel_layout = (avctx->channels==2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;
 
+    avcodec_get_frame_defaults(&q->frame);
+    avctx->coded_frame = &q->frame;
+
 #ifdef DEBUG
     dump_cook_context(q);
 #endif
@@ -1253,5 +1278,6 @@ AVCodec ff_cook_decoder =
     .init = cook_decode_init,
     .close = cook_decode_close,
     .decode = cook_decode_frame,
+    .capabilities = CODEC_CAP_DR1,
     .long_name = NULL_IF_CONFIG_SMALL("COOK"),
 };