]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/svq1dec.c
mpegaudiodec: move imdct and windowing function to mpegaudiodsp
[ffmpeg] / libavcodec / svq1dec.c
index 666be9e640a7de7a83e03799221ebfaf00717e0a..69dbd1b25d52f9c6b5434829a30a0cce15b0e27f 100644 (file)
@@ -8,35 +8,35 @@
  *
  * SVQ1 Encoder (c) 2004 Mike Melanson <melanson@pcisys.net>
  *
- * This file is part of FFmpeg.
+ * This file is part of Libav.
  *
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav 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.
  *
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav 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 FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 /**
- * @file svq1.c
+ * @file
  * Sorenson Vector Quantizer #1 (SVQ1) video codec.
  * For more information of the SVQ1 algorithm, visit:
  *   http://www.pcisys.net/~melanson/codecs/
  */
 
 
-//#define DEBUG_SVQ1
 #include "avcodec.h"
 #include "dsputil.h"
 #include "mpegvideo.h"
+#include "mathops.h"
 
 #include "svq1.h"
 
@@ -56,7 +56,7 @@ static VLC svq1_inter_mean;
 typedef struct svq1_pmv_s {
   int           x;
   int           y;
-} svq1_pmv_t;
+} svq1_pmv;
 
 static const uint16_t checksum_table[256] = {
   0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
@@ -195,7 +195,8 @@ static const uint8_t string_table[256] = {
 
 #define SVQ1_CALC_CODEBOOK_ENTRIES(cbook)\
       codebook = (const uint32_t *) cbook[level];\
-      bit_cache = get_bits (bitbuf, 4*stages);\
+      if (stages > 0)\
+        bit_cache = get_bits (bitbuf, 4*stages);\
       /* calculate codebook entries for this vector */\
       for (j=0; j < stages; j++) {\
         entries[j] = (((bit_cache >> (4*(stages - j - 1))) & 0xF) + 16*j) << (level + 1);\
@@ -237,9 +238,9 @@ static int svq1_decode_block_intra (GetBitContext *bitbuf, uint8_t *pixels, int
     }
 
     if ((stages > 0) && (level >= 4)) {
-#ifdef DEBUG_SVQ1
-    av_log(s->avctx, AV_LOG_INFO, "Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i\n",stages,level);
-#endif
+      av_dlog(NULL,
+              "Error (svq1_decode_block_intra): invalid vector: stages=%i level=%i\n",
+              stages, level);
       return -1;        /* invalid vector */
     }
 
@@ -287,9 +288,9 @@ static int svq1_decode_block_non_intra (GetBitContext *bitbuf, uint8_t *pixels,
     if (stages == -1) continue; /* skip vector */
 
     if ((stages > 0) && (level >= 4)) {
-#ifdef DEBUG_SVQ1
-    av_log(s->avctx, AV_LOG_INFO, "Error (svq1_decode_block_non_intra): invalid vector: stages=%i level=%i\n",stages,level);
-#endif
+      av_dlog(NULL,
+              "Error (svq1_decode_block_non_intra): invalid vector: stages=%i level=%i\n",
+              stages, level);
       return -1;        /* invalid vector */
     }
 
@@ -301,7 +302,7 @@ static int svq1_decode_block_non_intra (GetBitContext *bitbuf, uint8_t *pixels,
   return 0;
 }
 
-static int svq1_decode_motion_vector (GetBitContext *bitbuf, svq1_pmv_t *mv, svq1_pmv_t **pmv) {
+static int svq1_decode_motion_vector (GetBitContext *bitbuf, svq1_pmv *mv, svq1_pmv **pmv) {
   int        diff;
   int        i;
 
@@ -317,9 +318,9 @@ static int svq1_decode_motion_vector (GetBitContext *bitbuf, svq1_pmv_t *mv, svq
 
     /* add median of motion vector predictors and clip result */
     if (i == 1)
-      mv->y = ((diff + mid_pred(pmv[0]->y, pmv[1]->y, pmv[2]->y)) << 26) >> 26;
+      mv->y = sign_extend(diff + mid_pred(pmv[0]->y, pmv[1]->y, pmv[2]->y), 6);
     else
-      mv->x = ((diff + mid_pred(pmv[0]->x, pmv[1]->x, pmv[2]->x)) << 26) >> 26;
+      mv->x = sign_extend(diff + mid_pred(pmv[0]->x, pmv[1]->x, pmv[2]->x), 6);
   }
 
   return 0;
@@ -342,11 +343,11 @@ static void svq1_skip_block (uint8_t *current, uint8_t *previous, int pitch, int
 
 static int svq1_motion_inter_block (MpegEncContext *s, GetBitContext *bitbuf,
                                uint8_t *current, uint8_t *previous, int pitch,
-                               svq1_pmv_t *motion, int x, int y) {
+                               svq1_pmv *motion, int x, int y) {
   uint8_t    *src;
   uint8_t    *dst;
-  svq1_pmv_t  mv;
-  svq1_pmv_t *pmv[3];
+  svq1_pmv    mv;
+  svq1_pmv   *pmv[3];
   int         result;
 
   /* predict and decode motion vector */
@@ -377,13 +378,6 @@ static int svq1_motion_inter_block (MpegEncContext *s, GetBitContext *bitbuf,
   if(x + (mv.x >> 1)<0)
      mv.x= 0;
 
-#if 0
-  int w= (s->width+15)&~15;
-  int h= (s->height+15)&~15;
-  if(x + (mv.x >> 1)<0 || y + (mv.y >> 1)<0 || x + (mv.x >> 1) + 16 > w || y + (mv.y >> 1) + 16> h)
-      av_log(s->avctx, AV_LOG_INFO, "%d %d %d %d\n", x, y, x + (mv.x >> 1), y + (mv.y >> 1));
-#endif
-
   src = &previous[(x + (mv.x >> 1)) + (y + (mv.y >> 1))*pitch];
   dst = current;
 
@@ -394,11 +388,11 @@ static int svq1_motion_inter_block (MpegEncContext *s, GetBitContext *bitbuf,
 
 static int svq1_motion_inter_4v_block (MpegEncContext *s, GetBitContext *bitbuf,
                                   uint8_t *current, uint8_t *previous, int pitch,
-                                  svq1_pmv_t *motion,int x, int y) {
+                                  svq1_pmv *motion,int x, int y) {
   uint8_t    *src;
   uint8_t    *dst;
-  svq1_pmv_t  mv;
-  svq1_pmv_t *pmv[4];
+  svq1_pmv    mv;
+  svq1_pmv   *pmv[4];
   int         i, result;
 
   /* predict and decode motion vector (0) */
@@ -460,12 +454,6 @@ static int svq1_motion_inter_4v_block (MpegEncContext *s, GetBitContext *bitbuf,
     if(x + (mvx >> 1)<0)
        mvx= 0;
 
-#if 0
-  int w= (s->width+15)&~15;
-  int h= (s->height+15)&~15;
-  if(x + (mvx >> 1)<0 || y + (mvy >> 1)<0 || x + (mvx >> 1) + 8 > w || y + (mvy >> 1) + 8> h)
-      av_log(s->avctx, AV_LOG_INFO, "%d %d %d %d\n", x, y, x + (mvx >> 1), y + (mvy >> 1));
-#endif
     src = &previous[(x + (mvx >> 1)) + (y + (mvy >> 1))*pitch];
     dst = current;
 
@@ -484,7 +472,7 @@ static int svq1_motion_inter_4v_block (MpegEncContext *s, GetBitContext *bitbuf,
 
 static int svq1_decode_delta_block (MpegEncContext *s, GetBitContext *bitbuf,
                         uint8_t *current, uint8_t *previous, int pitch,
-                        svq1_pmv_t *motion, int x, int y) {
+                        svq1_pmv *motion, int x, int y) {
   uint32_t block_type;
   int      result = 0;
 
@@ -511,9 +499,7 @@ static int svq1_decode_delta_block (MpegEncContext *s, GetBitContext *bitbuf,
 
     if (result != 0)
     {
-#ifdef DEBUG_SVQ1
-    av_log(s->avctx, AV_LOG_INFO, "Error in svq1_motion_inter_block %i\n",result);
-#endif
+      av_dlog(s->avctx, "Error in svq1_motion_inter_block %i\n", result);
       break;
     }
     result = svq1_decode_block_non_intra (bitbuf, current, pitch);
@@ -524,9 +510,7 @@ static int svq1_decode_delta_block (MpegEncContext *s, GetBitContext *bitbuf,
 
     if (result != 0)
     {
-#ifdef DEBUG_SVQ1
-    av_log(s->avctx, AV_LOG_INFO, "Error in svq1_motion_inter_4v_block %i\n",result);
-#endif
+      av_dlog(s->avctx, "Error in svq1_motion_inter_4v_block %i\n", result);
       break;
     }
     result = svq1_decode_block_non_intra (bitbuf, current, pitch);
@@ -540,7 +524,7 @@ static int svq1_decode_delta_block (MpegEncContext *s, GetBitContext *bitbuf,
   return result;
 }
 
-static uint16_t svq1_packet_checksum (const uint8_t *data, const int length, int value) {
+uint16_t ff_svq1_packet_checksum (const uint8_t *data, const int length, int value) {
   int i;
 
   for (i=0; i < length; i++) {
@@ -566,22 +550,21 @@ static void svq1_parse_string (GetBitContext *bitbuf, uint8_t *out) {
 
 static int svq1_decode_frame_header (GetBitContext *bitbuf,MpegEncContext *s) {
   int frame_size_code;
-  int temporal_reference;
 
-  temporal_reference = get_bits (bitbuf, 8);
+  skip_bits(bitbuf, 8); /* temporal_reference */
 
   /* frame type */
   s->pict_type= get_bits (bitbuf, 2)+1;
   if(s->pict_type==4)
       return -1;
 
-  if (s->pict_type == FF_I_TYPE) {
+  if (s->pict_type == AV_PICTURE_TYPE_I) {
 
     /* unknown fields */
     if (s->f_code == 0x50 || s->f_code == 0x60) {
       int csum = get_bits (bitbuf, 16);
 
-      csum = svq1_packet_checksum (bitbuf->buffer, bitbuf->size_in_bits>>3, csum);
+      csum = ff_svq1_packet_checksum (bitbuf->buffer, bitbuf->size_in_bits>>3, csum);
 
 //      av_log(s->avctx, AV_LOG_INFO, "%s checksum (%02x) for packet data\n",
 //              (csum == 0) ? "correct" : "incorrect", csum);
@@ -641,12 +624,15 @@ static int svq1_decode_frame_header (GetBitContext *bitbuf,MpegEncContext *s) {
 
 static int svq1_decode_frame(AVCodecContext *avctx,
                              void *data, int *data_size,
-                             const uint8_t *buf, int buf_size)
+                             AVPacket *avpkt)
 {
+  const uint8_t *buf = avpkt->data;
+  int buf_size = avpkt->size;
   MpegEncContext *s=avctx->priv_data;
   uint8_t        *current, *previous;
   int             result, i, x, y, width, height;
   AVFrame *pict = data;
+  svq1_pmv *pmv;
 
   /* initialize bit buffer */
   init_get_bits(&s->gb,buf,buf_size*8);
@@ -670,66 +656,65 @@ static int svq1_decode_frame(AVCodecContext *avctx,
 
   if (result != 0)
   {
-#ifdef DEBUG_SVQ1
-    av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_frame_header %i\n",result);
-#endif
+    av_dlog(s->avctx, "Error in svq1_decode_frame_header %i\n",result);
     return result;
   }
+  avcodec_set_dimensions(avctx, s->width, s->height);
 
   //FIXME this avoids some confusion for "B frames" without 2 references
   //this should be removed after libavcodec can handle more flexible picture types & ordering
-  if(s->pict_type==FF_B_TYPE && s->last_picture_ptr==NULL) return buf_size;
+  if(s->pict_type==AV_PICTURE_TYPE_B && s->last_picture_ptr==NULL) return buf_size;
 
-  if(avctx->hurry_up && s->pict_type==FF_B_TYPE) return buf_size;
-  if(  (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==FF_B_TYPE)
-     ||(avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=FF_I_TYPE)
+  if(  (avctx->skip_frame >= AVDISCARD_NONREF && s->pict_type==AV_PICTURE_TYPE_B)
+     ||(avctx->skip_frame >= AVDISCARD_NONKEY && s->pict_type!=AV_PICTURE_TYPE_I)
      || avctx->skip_frame >= AVDISCARD_ALL)
       return buf_size;
 
   if(MPV_frame_start(s, avctx) < 0)
       return -1;
 
+  pmv = av_malloc((FFALIGN(s->width, 16)/8 + 3) * sizeof(*pmv));
+  if (!pmv)
+      return -1;
+
   /* decode y, u and v components */
   for (i=0; i < 3; i++) {
     int linesize;
     if (i == 0) {
-      width  = (s->width+15)&~15;
-      height = (s->height+15)&~15;
+      width  = FFALIGN(s->width, 16);
+      height = FFALIGN(s->height, 16);
       linesize= s->linesize;
     } else {
       if(s->flags&CODEC_FLAG_GRAY) break;
-      width  = (s->width/4+15)&~15;
-      height = (s->height/4+15)&~15;
+      width  = FFALIGN(s->width/4, 16);
+      height = FFALIGN(s->height/4, 16);
       linesize= s->uvlinesize;
     }
 
-    current  = s->current_picture.data[i];
+    current = s->current_picture.f.data[i];
 
-    if(s->pict_type==FF_B_TYPE){
-        previous = s->next_picture.data[i];
+    if(s->pict_type==AV_PICTURE_TYPE_B){
+        previous = s->next_picture.f.data[i];
     }else{
-        previous = s->last_picture.data[i];
+        previous = s->last_picture.f.data[i];
     }
 
-    if (s->pict_type == FF_I_TYPE) {
+    if (s->pict_type == AV_PICTURE_TYPE_I) {
       /* keyframe */
       for (y=0; y < height; y+=16) {
         for (x=0; x < width; x+=16) {
           result = svq1_decode_block_intra (&s->gb, &current[x], linesize);
           if (result != 0)
           {
-//#ifdef DEBUG_SVQ1
             av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_block %i (keyframe)\n",result);
-//#endif
-            return result;
+            goto err;
           }
         }
         current += 16*linesize;
       }
     } else {
-      svq1_pmv_t pmv[width/8+3];
       /* delta frame */
-      memset (pmv, 0, ((width / 8) + 3) * sizeof(svq1_pmv_t));
+      memset (pmv, 0, ((width / 8) + 3) * sizeof(svq1_pmv));
 
       for (y=0; y < height; y+=16) {
         for (x=0; x < width; x+=16) {
@@ -737,10 +722,8 @@ static int svq1_decode_frame(AVCodecContext *avctx,
                                             linesize, pmv, x, y);
           if (result != 0)
           {
-#ifdef DEBUG_SVQ1
-    av_log(s->avctx, AV_LOG_INFO, "Error in svq1_decode_delta_block %i\n",result);
-#endif
-            return result;
+            av_dlog(s->avctx, "Error in svq1_decode_delta_block %i\n",result);
+            goto err;
           }
         }
 
@@ -758,13 +741,17 @@ static int svq1_decode_frame(AVCodecContext *avctx,
   MPV_frame_end(s);
 
   *data_size=sizeof(AVFrame);
-  return buf_size;
+  result = buf_size;
+err:
+  av_free(pmv);
+  return result;
 }
 
 static av_cold int svq1_decode_init(AVCodecContext *avctx)
 {
     MpegEncContext *s = avctx->priv_data;
     int i;
+    int offset = 0;
 
     MPV_decode_defaults(s);
 
@@ -777,30 +764,38 @@ static av_cold int svq1_decode_init(AVCodecContext *avctx)
     s->flags= avctx->flags;
     if (MPV_common_init(s) < 0) return -1;
 
-    init_vlc(&svq1_block_type, 2, 4,
+    INIT_VLC_STATIC(&svq1_block_type, 2, 4,
         &ff_svq1_block_type_vlc[0][1], 2, 1,
-        &ff_svq1_block_type_vlc[0][0], 2, 1, 1);
+        &ff_svq1_block_type_vlc[0][0], 2, 1, 6);
 
-    init_vlc(&svq1_motion_component, 7, 33,
+    INIT_VLC_STATIC(&svq1_motion_component, 7, 33,
         &mvtab[0][1], 2, 1,
-        &mvtab[0][0], 2, 1, 1);
+        &mvtab[0][0], 2, 1, 176);
 
     for (i = 0; i < 6; i++) {
+        static const uint8_t sizes[2][6] = {{14, 10, 14, 18, 16, 18}, {10, 10, 14, 14, 14, 16}};
+        static VLC_TYPE table[168][2];
+        svq1_intra_multistage[i].table = &table[offset];
+        svq1_intra_multistage[i].table_allocated = sizes[0][i];
+        offset += sizes[0][i];
         init_vlc(&svq1_intra_multistage[i], 3, 8,
             &ff_svq1_intra_multistage_vlc[i][0][1], 2, 1,
-            &ff_svq1_intra_multistage_vlc[i][0][0], 2, 1, 1);
+            &ff_svq1_intra_multistage_vlc[i][0][0], 2, 1, INIT_VLC_USE_NEW_STATIC);
+        svq1_inter_multistage[i].table = &table[offset];
+        svq1_inter_multistage[i].table_allocated = sizes[1][i];
+        offset += sizes[1][i];
         init_vlc(&svq1_inter_multistage[i], 3, 8,
             &ff_svq1_inter_multistage_vlc[i][0][1], 2, 1,
-            &ff_svq1_inter_multistage_vlc[i][0][0], 2, 1, 1);
+            &ff_svq1_inter_multistage_vlc[i][0][0], 2, 1, INIT_VLC_USE_NEW_STATIC);
     }
 
-    init_vlc(&svq1_intra_mean, 8, 256,
+    INIT_VLC_STATIC(&svq1_intra_mean, 8, 256,
         &ff_svq1_intra_mean_vlc[0][1], 4, 2,
-        &ff_svq1_intra_mean_vlc[0][0], 4, 2, 1);
+        &ff_svq1_intra_mean_vlc[0][0], 4, 2, 632);
 
-    init_vlc(&svq1_inter_mean, 9, 512,
+    INIT_VLC_STATIC(&svq1_inter_mean, 9, 512,
         &ff_svq1_inter_mean_vlc[0][1], 4, 2,
-        &ff_svq1_inter_mean_vlc[0][0], 4, 2, 1);
+        &ff_svq1_inter_mean_vlc[0][0], 4, 2, 1434);
 
     return 0;
 }
@@ -814,17 +809,16 @@ static av_cold int svq1_decode_end(AVCodecContext *avctx)
 }
 
 
-AVCodec svq1_decoder = {
-    "svq1",
-    CODEC_TYPE_VIDEO,
-    CODEC_ID_SVQ1,
-    sizeof(MpegEncContext),
-    svq1_decode_init,
-    NULL,
-    svq1_decode_end,
-    svq1_decode_frame,
-    CODEC_CAP_DR1,
+AVCodec ff_svq1_decoder = {
+    .name           = "svq1",
+    .type           = AVMEDIA_TYPE_VIDEO,
+    .id             = CODEC_ID_SVQ1,
+    .priv_data_size = sizeof(MpegEncContext),
+    .init           = svq1_decode_init,
+    .close          = svq1_decode_end,
+    .decode         = svq1_decode_frame,
+    .capabilities   = CODEC_CAP_DR1,
     .flush= ff_mpeg_flush,
-    .pix_fmts= (enum PixelFormat[]){PIX_FMT_YUV410P, -1},
-    .long_name= "Sorenson Vector Quantizer 1",
+    .pix_fmts= (const enum PixelFormat[]){PIX_FMT_YUV410P, PIX_FMT_NONE},
+    .long_name= NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"),
 };