libavcodec/svq3.c
8b82a956
 /*
406792e7
  * Copyright (c) 2003 The FFmpeg Project
8b82a956
  *
b78e7197
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
8b82a956
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
b78e7197
  * version 2.1 of the License, or (at your option) any later version.
8b82a956
  *
b78e7197
  * FFmpeg is distributed in the hope that it will be useful,
8b82a956
  * 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
b78e7197
  * License along with FFmpeg; if not, write to the Free Software
5509bffa
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
e5a389a1
  */
 
 /*
8b82a956
  * How to use this decoder:
  * SVQ3 data is transported within Apple Quicktime files. Quicktime files
89a79364
  * have stsd atoms to describe media trak properties. A stsd atom for a
  * video trak contains 1 or more ImageDescription atoms. These atoms begin
  * with the 4-byte length of the atom followed by the codec fourcc. Some
  * decoders need information in this atom to operate correctly. Such
  * is the case with SVQ3. In order to get the best use out of this decoder,
  * the calling app must make the SVQ3 ImageDescription atom available
8b82a956
  * via the AVCodecContext's extradata[_size] field:
  *
115329f1
  * AVCodecContext.extradata = pointer to ImageDescription, first characters
89a79364
  * are expected to be 'S', 'V', 'Q', and '3', NOT the 4-byte atom length
115329f1
  * AVCodecContext.extradata_size = size of ImageDescription atom memory
  * buffer (which will be the same as the ImageDescription atom size field
89a79364
  * from the QT file, minus 4 bytes since the length is missing)
  *
  * You will know you have these parameters passed correctly when the decoder
  * correctly decodes this file:
ddaf298c
  *  http://samples.mplayerhq.hu/V-codecs/SVQ3/Vertical400kbit.sorenson3.mov
8b82a956
  */
903d58f6
 #include "internal.h"
 #include "dsputil.h"
 #include "avcodec.h"
 #include "mpegvideo.h"
 #include "h264.h"
 
a7d2861d
 #include "h264data.h" // FIXME FIXME FIXME
903d58f6
 
188d3c51
 #include "h264_mvpred.h"
903d58f6
 #include "golomb.h"
 #include "rectangle.h"
 #include "vdpau_internal.h"
 
b250f9c6
 #if CONFIG_ZLIB
c4864924
 #include <zlib.h>
 #endif
 
2be3fe39
 #include "svq1.h"
 
8b82a956
 /**
ba87f080
  * @file
8b82a956
  * svq3 decoder.
  */
 
8811679c
 typedef struct {
     H264Context h;
     int halfpel_flag;
     int thirdpel_flag;
     int unknown_flag;
     int next_slice_index;
     uint32_t watermark_key;
2264c110
     uint8_t *buf;
     int buf_size;
8811679c
 } SVQ3Context;
 
115329f1
 #define FULLPEL_MODE  1
 #define HALFPEL_MODE  2
94d44f45
 #define THIRDPEL_MODE 3
2e26c8d2
 #define PREDICT_MODE  4
115329f1
 
f7a8c179
 /* dual scan (from some older h264 draft)
a7d2861d
  * o-->o-->o   o
  *         |  /|
  * o   o   o / o
  * | / |   |/  |
  * o   o   o   o
  *   /
  * o-->o-->o-->o
  */
76de302d
 static const uint8_t svq3_scan[16] = {
a7d2861d
     0 + 0 * 4, 1 + 0 * 4, 2 + 0 * 4, 2 + 1 * 4,
     2 + 2 * 4, 3 + 0 * 4, 3 + 1 * 4, 3 + 2 * 4,
     0 + 1 * 4, 0 + 2 * 4, 1 + 1 * 4, 1 + 2 * 4,
     0 + 3 * 4, 1 + 3 * 4, 2 + 3 * 4, 3 + 3 * 4,
8b82a956
 };
 
 static const uint8_t svq3_pred_0[25][2] = {
76de302d
     { 0, 0 },
     { 1, 0 }, { 0, 1 },
     { 0, 2 }, { 1, 1 }, { 2, 0 },
     { 3, 0 }, { 2, 1 }, { 1, 2 }, { 0, 3 },
     { 0, 4 }, { 1, 3 }, { 2, 2 }, { 3, 1 }, { 4, 0 },
     { 4, 1 }, { 3, 2 }, { 2, 3 }, { 1, 4 },
     { 2, 4 }, { 3, 3 }, { 4, 2 },
     { 4, 3 }, { 3, 4 },
     { 4, 4 }
8b82a956
 };
 
 static const int8_t svq3_pred_1[6][6][5] = {
a7d2861d
     { { 2, -1, -1, -1, -1 }, { 2, 1, -1, -1, -1 }, { 1, 2, -1, -1, -1 },
       { 2,  1, -1, -1, -1 }, { 1, 2, -1, -1, -1 }, { 1, 2, -1, -1, -1 } },
     { { 0,  2, -1, -1, -1 }, { 0, 2,  1,  4,  3 }, { 0, 1,  2,  4,  3 },
       { 0,  2,  1,  4,  3 }, { 2, 0,  1,  3,  4 }, { 0, 4,  2,  1,  3 } },
     { { 2,  0, -1, -1, -1 }, { 2, 1,  0,  4,  3 }, { 1, 2,  4,  0,  3 },
       { 2,  1,  0,  4,  3 }, { 2, 1,  4,  3,  0 }, { 1, 2,  4,  0,  3 } },
     { { 2,  0, -1, -1, -1 }, { 2, 0,  1,  4,  3 }, { 1, 2,  0,  4,  3 },
       { 2,  1,  0,  4,  3 }, { 2, 1,  3,  4,  0 }, { 2, 4,  1,  0,  3 } },
     { { 0,  2, -1, -1, -1 }, { 0, 2,  1,  3,  4 }, { 1, 2,  3,  0,  4 },
       { 2,  0,  1,  3,  4 }, { 2, 1,  3,  0,  4 }, { 2, 0,  4,  3,  1 } },
     { { 0,  2, -1, -1, -1 }, { 0, 2,  4,  1,  3 }, { 1, 4,  2,  0,  3 },
       { 4,  2,  0,  1,  3 }, { 2, 0,  1,  4,  3 }, { 4, 2,  1,  0,  3 } },
8b82a956
 };
 
a7d2861d
 static const struct {
     uint8_t run;
     uint8_t level;
 } svq3_dct_tables[2][16] = {
76de302d
     { { 0, 0 }, { 0, 1 }, { 1, 1 }, { 2, 1 }, { 0, 2 }, { 3, 1 }, { 4, 1 }, { 5, 1 },
       { 0, 3 }, { 1, 2 }, { 2, 2 }, { 6, 1 }, { 7, 1 }, { 8, 1 }, { 9, 1 }, { 0, 4 } },
     { { 0, 0 }, { 0, 1 }, { 1, 1 }, { 0, 2 }, { 2, 1 }, { 0, 3 }, { 0, 4 }, { 0, 5 },
       { 3, 1 }, { 4, 1 }, { 1, 2 }, { 1, 3 }, { 0, 6 }, { 0, 7 }, { 0, 8 }, { 0, 9 } }
8b82a956
 };
 
 static const uint32_t svq3_dequant_coeff[32] = {
a7d2861d
      3881,  4351,  4890,  5481,   6154,   6914,   7761,   8718,
      9781, 10987, 12339, 13828,  15523,  17435,  19561,  21873,
     24552, 27656, 30847, 34870,  38807,  43747,  49103,  54683,
     61694, 68745, 77615, 89113, 100253, 109366, 126635, 141533
8b82a956
 };
 
a7d2861d
 void ff_svq3_luma_dc_dequant_idct_c(DCTELEM *output, DCTELEM *input, int qp)
 {
76de302d
     const int qmul = svq3_dequant_coeff[qp];
8b82a956
 #define stride 16
     int i;
     int temp[16];
a7d2861d
     static const uint8_t x_offset[4] = { 0, 1 * stride, 4 * stride, 5 * stride };
 
     for (i = 0; i < 4; i++) {
         const int z0 = 13 * (input[4 * i + 0] +      input[4 * i + 2]);
         const int z1 = 13 * (input[4 * i + 0] -      input[4 * i + 2]);
         const int z2 =  7 *  input[4 * i + 1] - 17 * input[4 * i + 3];
         const int z3 = 17 *  input[4 * i + 1] +  7 * input[4 * i + 3];
 
         temp[4 * i + 0] = z0 + z3;
         temp[4 * i + 1] = z1 + z2;
         temp[4 * i + 2] = z1 - z2;
         temp[4 * i + 3] = z0 - z3;
8b82a956
     }
 
a7d2861d
     for (i = 0; i < 4; i++) {
         const int offset = x_offset[i];
         const int z0     = 13 * (temp[4 * 0 + i] +      temp[4 * 2 + i]);
         const int z1     = 13 * (temp[4 * 0 + i] -      temp[4 * 2 + i]);
         const int z2     =  7 *  temp[4 * 1 + i] - 17 * temp[4 * 3 + i];
         const int z3     = 17 *  temp[4 * 1 + i] +  7 * temp[4 * 3 + i];
 
af1ede06
         output[stride *  0 + offset] = (z0 + z3) * qmul + 0x80000 >> 20;
         output[stride *  2 + offset] = (z1 + z2) * qmul + 0x80000 >> 20;
         output[stride *  8 + offset] = (z1 - z2) * qmul + 0x80000 >> 20;
         output[stride * 10 + offset] = (z0 - z3) * qmul + 0x80000 >> 20;
8b82a956
     }
 }
 #undef stride
 
a7d2861d
 void ff_svq3_add_idct_c(uint8_t *dst, DCTELEM *block,
                         int stride, int qp, int dc)
7f8205da
 {
76de302d
     const int qmul = svq3_dequant_coeff[qp];
8b82a956
     int i;
 
     if (dc) {
af1ede06
         dc       = 13 * 13 * (dc == 1 ? 1538 * block[0]
                                       : qmul * (block[0] >> 3) / 2);
8b82a956
         block[0] = 0;
     }
 
76de302d
     for (i = 0; i < 4; i++) {
a7d2861d
         const int z0 = 13 * (block[0 + 4 * i] +      block[2 + 4 * i]);
         const int z1 = 13 * (block[0 + 4 * i] -      block[2 + 4 * i]);
         const int z2 =  7 *  block[1 + 4 * i] - 17 * block[3 + 4 * i];
         const int z3 = 17 *  block[1 + 4 * i] +  7 * block[3 + 4 * i];
 
         block[0 + 4 * i] = z0 + z3;
         block[1 + 4 * i] = z1 + z2;
         block[2 + 4 * i] = z1 - z2;
         block[3 + 4 * i] = z0 - z3;
8b82a956
     }
 
76de302d
     for (i = 0; i < 4; i++) {
a7d2861d
         const int z0 = 13 * (block[i + 4 * 0] +      block[i + 4 * 2]);
         const int z1 = 13 * (block[i + 4 * 0] -      block[i + 4 * 2]);
         const int z2 =  7 *  block[i + 4 * 1] - 17 * block[i + 4 * 3];
         const int z3 = 17 *  block[i + 4 * 1] +  7 * block[i + 4 * 3];
76de302d
         const int rr = (dc + 0x80000);
 
af1ede06
         dst[i + stride * 0] = av_clip_uint8(dst[i + stride * 0] + ((z0 + z3) * qmul + rr >> 20));
         dst[i + stride * 1] = av_clip_uint8(dst[i + stride * 1] + ((z1 + z2) * qmul + rr >> 20));
         dst[i + stride * 2] = av_clip_uint8(dst[i + stride * 2] + ((z1 - z2) * qmul + rr >> 20));
         dst[i + stride * 3] = av_clip_uint8(dst[i + stride * 3] + ((z0 - z3) * qmul + rr >> 20));
8b82a956
     }
 }
 
7f8205da
 static inline int svq3_decode_block(GetBitContext *gb, DCTELEM *block,
                                     int index, const int type)
 {
76de302d
     static const uint8_t *const scan_patterns[4] =
     { luma_dc_zigzag_scan, zigzag_scan, svq3_scan, chroma_dc_scan };
8b82a956
 
5c076205
     int run, level, sign, limit;
9a2e7911
     unsigned vlc;
af1ede06
     const int intra           = 3 * type >> 2;
76de302d
     const uint8_t *const scan = scan_patterns[type];
8b82a956
 
76de302d
     for (limit = (16 >> intra); index < 16; index = limit, limit += 8) {
         for (; (vlc = svq3_get_ue_golomb(gb)) != 0; index++) {
7dee5f04
             if ((int32_t)vlc < 0)
a7d2861d
                 return -1;
8b82a956
 
5c076205
             sign     = (vlc & 1) ? 0 : -1;
9a2e7911
             vlc      = vlc + 1 >> 1;
a7d2861d
 
             if (type == 3) {
                 if (vlc < 3) {
                     run   = 0;
                     level = vlc;
                 } else if (vlc < 4) {
                     run   = 1;
                     level = 1;
                 } else {
af1ede06
                     run   = vlc & 0x3;
                     level = (vlc + 9 >> 2) - run;
a7d2861d
                 }
             } else {
0e097616
                 if (vlc < 16U) {
a7d2861d
                     run   = svq3_dct_tables[intra][vlc].run;
                     level = svq3_dct_tables[intra][vlc].level;
                 } else if (intra) {
af1ede06
                     run   = vlc & 0x7;
0e097616
                     level = (vlc >> 3) + ((run == 0) ? 8 : ((run < 2) ? 2 : ((run < 5) ? 0 : -1)));
a7d2861d
                 } else {
af1ede06
                     run   = vlc & 0xF;
0e097616
                     level = (vlc >> 4) + ((run == 0) ? 4 : ((run < 3) ? 2 : ((run < 10) ? 1 : 0)));
a7d2861d
                 }
             }
8b82a956
 
0e097616
 
a7d2861d
             if ((index += run) >= limit)
                 return -1;
 
             block[scan[index]] = (level ^ sign) - sign;
76de302d
         }
8b82a956
 
76de302d
         if (type != 2) {
             break;
         }
8b82a956
     }
 
76de302d
     return 0;
8b82a956
 }
 
7f8205da
 static inline void svq3_mc_dir_part(MpegEncContext *s,
                                     int x, int y, int width, int height,
                                     int mx, int my, int dxy,
                                     int thirdpel, int dir, int avg)
 {
76de302d
     const Picture *pic = (dir == 0) ? &s->last_picture : &s->next_picture;
     uint8_t *src, *dest;
     int i, emu = 0;
a7d2861d
     int blocksize = 2 - (width >> 3); // 16->0, 8->1, 4->2
76de302d
 
     mx += x;
     my += y;
8b82a956
 
af1ede06
     if (mx < 0 || mx >= s->h_edge_pos - width  - 1 ||
         my < 0 || my >= s->v_edge_pos - height - 1) {
a7d2861d
         if ((s->flags & CODEC_FLAG_EMU_EDGE))
76de302d
             emu = 1;
8b82a956
 
af1ede06
         mx = av_clip(mx, -16, s->h_edge_pos - width  + 15);
         my = av_clip(my, -16, s->v_edge_pos - height + 15);
8b82a956
     }
 
76de302d
     /* form component predictions */
a7d2861d
     dest = s->current_picture.f.data[0] + x + y * s->linesize;
     src  = pic->f.data[0] + mx + my * s->linesize;
76de302d
 
     if (emu) {
8c53d39e
         s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize,
                                  width + 1, height + 1,
                                  mx, my, s->h_edge_pos, s->v_edge_pos);
a7d3e772
         src = s->edge_emu_buffer;
8b82a956
     }
76de302d
     if (thirdpel)
a7d2861d
         (avg ? s->dsp.avg_tpel_pixels_tab
              : s->dsp.put_tpel_pixels_tab)[dxy](dest, src, s->linesize,
                                                 width, height);
76de302d
     else
a7d2861d
         (avg ? s->dsp.avg_pixels_tab
              : s->dsp.put_pixels_tab)[blocksize][dxy](dest, src, s->linesize,
                                                       height);
76de302d
 
     if (!(s->flags & CODEC_FLAG_GRAY)) {
af1ede06
         mx     = mx + (mx < (int) x) >> 1;
         my     = my + (my < (int) y) >> 1;
         width  = width  >> 1;
         height = height >> 1;
76de302d
         blocksize++;
 
         for (i = 1; i < 3; i++) {
657ccb5a
             dest = s->current_picture.f.data[i] + (x >> 1) + (y >> 1) * s->uvlinesize;
             src  = pic->f.data[i] + mx + my * s->uvlinesize;
76de302d
 
             if (emu) {
8c53d39e
                 s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src, s->uvlinesize,
                                          width + 1, height + 1,
                                          mx, my, (s->h_edge_pos >> 1),
                                          s->v_edge_pos >> 1);
76de302d
                 src = s->edge_emu_buffer;
             }
             if (thirdpel)
a7d2861d
                 (avg ? s->dsp.avg_tpel_pixels_tab
                      : s->dsp.put_tpel_pixels_tab)[dxy](dest, src,
                                                         s->uvlinesize,
                                                         width, height);
76de302d
             else
a7d2861d
                 (avg ? s->dsp.avg_pixels_tab
                      : s->dsp.put_pixels_tab)[blocksize][dxy](dest, src,
                                                               s->uvlinesize,
                                                               height);
76de302d
         }
     }
8b82a956
 }
 
a7d2861d
 static inline int svq3_mc_dir(H264Context *h, int size, int mode,
                               int dir, int avg)
7f8205da
 {
76de302d
     int i, j, k, mx, my, dx, dy, x, y;
a7d2861d
     MpegEncContext *const s = (MpegEncContext *)h;
     const int part_width    = ((size & 5) == 4) ? 4 : 16 >> (size & 1);
     const int part_height   = 16 >> ((unsigned)(size + 1) / 3);
     const int extra_width   = (mode == PREDICT_MODE) ? -16 * 6 : 0;
     const int h_edge_pos    = 6 * (s->h_edge_pos - part_width)  - extra_width;
     const int v_edge_pos    = 6 * (s->v_edge_pos - part_height) - extra_width;
 
     for (i = 0; i < 16; i += part_height)
76de302d
         for (j = 0; j < 16; j += part_width) {
a7d2861d
             const int b_xy = (4 * s->mb_x + (j >> 2)) +
                              (4 * s->mb_y + (i >> 2)) * h->b_stride;
76de302d
             int dxy;
a7d2861d
             x = 16 * s->mb_x + j;
             y = 16 * s->mb_y + i;
af1ede06
             k = (j >> 2 & 1) + (i >> 1 & 2) +
                 (j >> 1 & 4) + (i      & 8);
76de302d
 
             if (mode != PREDICT_MODE) {
af1ede06
                 pred_motion(h, k, part_width >> 2, dir, 1, &mx, &my);
76de302d
             } else {
657ccb5a
                 mx = s->next_picture.f.motion_val[0][b_xy][0] << 1;
                 my = s->next_picture.f.motion_val[0][b_xy][1] << 1;
76de302d
 
                 if (dir == 0) {
af1ede06
                     mx = mx * h->frame_num_offset /
                          h->prev_frame_num_offset + 1 >> 1;
                     my = my * h->frame_num_offset /
                          h->prev_frame_num_offset + 1 >> 1;
76de302d
                 } else {
af1ede06
                     mx = mx * (h->frame_num_offset - h->prev_frame_num_offset) /
                          h->prev_frame_num_offset + 1 >> 1;
                     my = my * (h->frame_num_offset - h->prev_frame_num_offset) /
                          h->prev_frame_num_offset + 1 >> 1;
76de302d
                 }
             }
 
             /* clip motion vector prediction to frame border */
a7d2861d
             mx = av_clip(mx, extra_width - 6 * x, h_edge_pos - 6 * x);
             my = av_clip(my, extra_width - 6 * y, v_edge_pos - 6 * y);
76de302d
 
             /* get (optional) motion vector differential */
             if (mode == PREDICT_MODE) {
                 dx = dy = 0;
             } else {
                 dy = svq3_get_se_golomb(&s->gb);
                 dx = svq3_get_se_golomb(&s->gb);
 
                 if (dx == INVALID_VLC || dy == INVALID_VLC) {
                     av_log(h->s.avctx, AV_LOG_ERROR, "invalid MV vlc\n");
                     return -1;
                 }
             }
 
             /* compute motion vector */
             if (mode == THIRDPEL_MODE) {
                 int fx, fy;
af1ede06
                 mx  = (mx + 1 >> 1) + dx;
                 my  = (my + 1 >> 1) + dy;
                 fx  = (unsigned)(mx + 0x3000) / 3 - 0x1000;
                 fy  = (unsigned)(my + 0x3000) / 3 - 0x1000;
a7d2861d
                 dxy = (mx - 3 * fx) + 4 * (my - 3 * fy);
 
                 svq3_mc_dir_part(s, x, y, part_width, part_height,
                                  fx, fy, dxy, 1, dir, avg);
76de302d
                 mx += mx;
                 my += my;
             } else if (mode == HALFPEL_MODE || mode == PREDICT_MODE) {
af1ede06
                 mx  = (unsigned)(mx + 1 + 0x3000) / 3 + dx - 0x1000;
                 my  = (unsigned)(my + 1 + 0x3000) / 3 + dy - 0x1000;
a7d2861d
                 dxy = (mx & 1) + 2 * (my & 1);
76de302d
 
a7d2861d
                 svq3_mc_dir_part(s, x, y, part_width, part_height,
                                  mx >> 1, my >> 1, dxy, 0, dir, avg);
76de302d
                 mx *= 3;
                 my *= 3;
             } else {
af1ede06
                 mx = (unsigned)(mx + 3 + 0x6000) / 6 + dx - 0x1000;
                 my = (unsigned)(my + 3 + 0x6000) / 6 + dy - 0x1000;
76de302d
 
a7d2861d
                 svq3_mc_dir_part(s, x, y, part_width, part_height,
                                  mx, my, 0, 0, dir, avg);
76de302d
                 mx *= 6;
                 my *= 6;
             }
 
             /* update mv_cache */
             if (mode != PREDICT_MODE) {
a7d2861d
                 int32_t mv = pack16to32(mx, my);
76de302d
 
                 if (part_height == 8 && i < 8) {
a7d2861d
                     AV_WN32A(h->mv_cache[dir][scan8[k] + 1 * 8], mv);
76de302d
 
a7d2861d
                     if (part_width == 8 && j < 8)
                         AV_WN32A(h->mv_cache[dir][scan8[k] + 1 + 1 * 8], mv);
76de302d
                 }
a7d2861d
                 if (part_width == 8 && j < 8)
366b72f1
                     AV_WN32A(h->mv_cache[dir][scan8[k] + 1], mv);
a7d2861d
                 if (part_width == 4 || part_height == 4)
366b72f1
                     AV_WN32A(h->mv_cache[dir][scan8[k]], mv);
76de302d
             }
 
             /* write back motion vectors */
657ccb5a
             fill_rectangle(s->current_picture.f.motion_val[dir][b_xy],
                            part_width >> 2, part_height >> 2, h->b_stride,
                            pack16to32(mx, my), 4);
bb270c08
         }
2e26c8d2
 
76de302d
     return 0;
2e26c8d2
 }
 
8811679c
 static int svq3_decode_mb(SVQ3Context *svq3, unsigned int mb_type)
7f8205da
 {
8811679c
     H264Context *h = &svq3->h;
76de302d
     int i, j, k, m, dir, mode;
     int cbp = 0;
     uint32_t vlc;
     int8_t *top, *left;
a7d2861d
     MpegEncContext *const s = (MpegEncContext *)h;
     const int mb_xy         = h->mb_xy;
     const int b_xy          = 4 * s->mb_x + 4 * s->mb_y * h->b_stride;
76de302d
 
     h->top_samples_available      = (s->mb_y == 0) ? 0x33FF : 0xFFFF;
     h->left_samples_available     = (s->mb_x == 0) ? 0x5F5F : 0xFFFF;
     h->topright_samples_available = 0xFFFF;
 
     if (mb_type == 0) {           /* SKIP */
a7d2861d
         if (s->pict_type == AV_PICTURE_TYPE_P ||
             s->next_picture.f.mb_type[mb_xy] == -1) {
             svq3_mc_dir_part(s, 16 * s->mb_x, 16 * s->mb_y, 16, 16,
                              0, 0, 0, 0, 0, 0);
76de302d
 
a7d2861d
             if (s->pict_type == AV_PICTURE_TYPE_B)
                 svq3_mc_dir_part(s, 16 * s->mb_x, 16 * s->mb_y, 16, 16,
                                  0, 0, 0, 0, 1, 1);
76de302d
 
             mb_type = MB_TYPE_SKIP;
         } else {
657ccb5a
             mb_type = FFMIN(s->next_picture.f.mb_type[mb_xy], 6);
76de302d
             if (svq3_mc_dir(h, mb_type, PREDICT_MODE, 0, 0) < 0)
                 return -1;
             if (svq3_mc_dir(h, mb_type, PREDICT_MODE, 1, 1) < 0)
                 return -1;
8b82a956
 
76de302d
             mb_type = MB_TYPE_16x16;
bb270c08
         }
76de302d
     } else if (mb_type < 8) {     /* INTER */
a7d2861d
         if (svq3->thirdpel_flag && svq3->halfpel_flag == !get_bits1(&s->gb))
76de302d
             mode = THIRDPEL_MODE;
a7d2861d
         else if (svq3->halfpel_flag &&
                  svq3->thirdpel_flag == !get_bits1(&s->gb))
76de302d
             mode = HALFPEL_MODE;
a7d2861d
         else
76de302d
             mode = FULLPEL_MODE;
8b82a956
 
76de302d
         /* fill caches */
         /* note ref_cache should contain here:
a7d2861d
          *  ????????
          *  ???11111
          *  N??11111
          *  N??11111
          *  N??11111
          */
76de302d
 
         for (m = 0; m < 2; m++) {
a7d2861d
             if (s->mb_x > 0 && h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - 1] + 6] != -1) {
                 for (i = 0; i < 4; i++)
                     AV_COPY32(h->mv_cache[m][scan8[0] - 1 + i * 8],
                               s->current_picture.f.motion_val[m][b_xy - 1 + i * h->b_stride]);
76de302d
             } else {
a7d2861d
                 for (i = 0; i < 4; i++)
                     AV_ZERO32(h->mv_cache[m][scan8[0] - 1 + i * 8]);
76de302d
             }
             if (s->mb_y > 0) {
a7d2861d
                 memcpy(h->mv_cache[m][scan8[0] - 1 * 8],
                        s->current_picture.f.motion_val[m][b_xy - h->b_stride],
                        4 * 2 * sizeof(int16_t));
                 memset(&h->ref_cache[m][scan8[0] - 1 * 8],
                        (h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1, 4);
76de302d
 
af1ede06
                 if (s->mb_x < s->mb_width - 1) {
a7d2861d
                     AV_COPY32(h->mv_cache[m][scan8[0] + 4 - 1 * 8],
                               s->current_picture.f.motion_val[m][b_xy - h->b_stride + 4]);
                     h->ref_cache[m][scan8[0] + 4 - 1 * 8] =
                         (h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride + 1] + 6] == -1 ||
                          h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride]] == -1) ? PART_NOT_AVAILABLE : 1;
                 } else
                     h->ref_cache[m][scan8[0] + 4 - 1 * 8] = PART_NOT_AVAILABLE;
76de302d
                 if (s->mb_x > 0) {
a7d2861d
                     AV_COPY32(h->mv_cache[m][scan8[0] - 1 - 1 * 8],
                               s->current_picture.f.motion_val[m][b_xy - h->b_stride - 1]);
                     h->ref_cache[m][scan8[0] - 1 - 1 * 8] =
                         (h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride - 1] + 3] == -1) ? PART_NOT_AVAILABLE : 1;
                 } else
                     h->ref_cache[m][scan8[0] - 1 - 1 * 8] = PART_NOT_AVAILABLE;
             } else
                 memset(&h->ref_cache[m][scan8[0] - 1 * 8 - 1],
                        PART_NOT_AVAILABLE, 8);
76de302d
 
ce5e49b0
             if (s->pict_type != AV_PICTURE_TYPE_B)
76de302d
                 break;
bb270c08
         }
8b82a956
 
76de302d
         /* decode motion vector(s) and form prediction(s) */
ce5e49b0
         if (s->pict_type == AV_PICTURE_TYPE_P) {
af1ede06
             if (svq3_mc_dir(h, mb_type - 1, mode, 0, 0) < 0)
76de302d
                 return -1;
ce5e49b0
         } else {        /* AV_PICTURE_TYPE_B */
76de302d
             if (mb_type != 2) {
                 if (svq3_mc_dir(h, 0, mode, 0, 0) < 0)
                     return -1;
             } else {
a7d2861d
                 for (i = 0; i < 4; i++)
                     memset(s->current_picture.f.motion_val[0][b_xy + i * h->b_stride],
                            0, 4 * 2 * sizeof(int16_t));
76de302d
             }
             if (mb_type != 1) {
af1ede06
                 if (svq3_mc_dir(h, 0, mode, 1, mb_type == 3) < 0)
76de302d
                     return -1;
             } else {
a7d2861d
                 for (i = 0; i < 4; i++)
                     memset(s->current_picture.f.motion_val[1][b_xy + i * h->b_stride],
                            0, 4 * 2 * sizeof(int16_t));
76de302d
             }
bb270c08
         }
8b82a956
 
76de302d
         mb_type = MB_TYPE_16x16;
     } else if (mb_type == 8 || mb_type == 33) {   /* INTRA4x4 */
a7d2861d
         memset(h->intra4x4_pred_mode_cache, -1, 8 * 5 * sizeof(int8_t));
76de302d
 
         if (mb_type == 8) {
             if (s->mb_x > 0) {
a7d2861d
                 for (i = 0; i < 4; i++)
                     h->intra4x4_pred_mode_cache[scan8[0] - 1 + i * 8] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - 1] + 6 - i];
                 if (h->intra4x4_pred_mode_cache[scan8[0] - 1] == -1)
76de302d
                     h->left_samples_available = 0x5F5F;
             }
             if (s->mb_y > 0) {
a7d2861d
                 h->intra4x4_pred_mode_cache[4 + 8 * 0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride] + 0];
                 h->intra4x4_pred_mode_cache[5 + 8 * 0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride] + 1];
                 h->intra4x4_pred_mode_cache[6 + 8 * 0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride] + 2];
                 h->intra4x4_pred_mode_cache[7 + 8 * 0] = h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride] + 3];
76de302d
 
a7d2861d
                 if (h->intra4x4_pred_mode_cache[4 + 8 * 0] == -1)
76de302d
                     h->top_samples_available = 0x33FF;
             }
 
             /* decode prediction codes for luma blocks */
a7d2861d
             for (i = 0; i < 16; i += 2) {
76de302d
                 vlc = svq3_get_ue_golomb(&s->gb);
 
0e097616
                 if (vlc >= 25U) {
76de302d
                     av_log(h->s.avctx, AV_LOG_ERROR, "luma prediction:%d\n", vlc);
                     return -1;
                 }
 
a7d2861d
                 left = &h->intra4x4_pred_mode_cache[scan8[i] - 1];
                 top  = &h->intra4x4_pred_mode_cache[scan8[i] - 8];
76de302d
 
                 left[1] = svq3_pred_1[top[0] + 1][left[0] + 1][svq3_pred_0[vlc][0]];
                 left[2] = svq3_pred_1[top[1] + 1][left[1] + 1][svq3_pred_0[vlc][1]];
 
a7d2861d
                 if (left[1] == -1 || left[2] == -1) {
76de302d
                     av_log(h->s.avctx, AV_LOG_ERROR, "weird prediction\n");
                     return -1;
                 }
             }
         } else {    /* mb_type == 33, DC_128_PRED block type */
a7d2861d
             for (i = 0; i < 4; i++)
                 memset(&h->intra4x4_pred_mode_cache[scan8[0] + 8 * i], DC_PRED, 4);
884182b3
         }
8b82a956
 
3b7ebeb4
         write_back_intra_pred_mode(h);
8b82a956
 
76de302d
         if (mb_type == 8) {
2bedc0e8
             ff_h264_check_intra4x4_pred_mode(h);
da3b9756
 
76de302d
             h->top_samples_available  = (s->mb_y == 0) ? 0x33FF : 0xFFFF;
             h->left_samples_available = (s->mb_x == 0) ? 0x5F5F : 0xFFFF;
         } else {
a7d2861d
             for (i = 0; i < 4; i++)
                 memset(&h->intra4x4_pred_mode_cache[scan8[0] + 8 * i], DC_128_PRED, 4);
da3b9756
 
76de302d
             h->top_samples_available  = 0x33FF;
             h->left_samples_available = 0x5F5F;
         }
da3b9756
 
76de302d
         mb_type = MB_TYPE_INTRA4x4;
     } else {                      /* INTRA16x16 */
         dir = i_mb_type_info[mb_type - 8].pred_mode;
a7d2861d
         dir = (dir >> 1) ^ 3 * (dir & 1) ^ 1;
8b82a956
 
aeca97a7
         if ((h->intra16x16_pred_mode = ff_h264_check_intra_pred_mode(h, dir, 0)) < 0) {
             av_log(h->s.avctx, AV_LOG_ERROR, "ff_h264_check_intra_pred_mode < 0\n");
             return h->intra16x16_pred_mode;
76de302d
         }
8b82a956
 
a7d2861d
         cbp     = i_mb_type_info[mb_type - 8].cbp;
76de302d
         mb_type = MB_TYPE_INTRA16x16;
884182b3
     }
8b82a956
 
ce5e49b0
     if (!IS_INTER(mb_type) && s->pict_type != AV_PICTURE_TYPE_I) {
a7d2861d
         for (i = 0; i < 4; i++)
             memset(s->current_picture.f.motion_val[0][b_xy + i * h->b_stride],
                    0, 4 * 2 * sizeof(int16_t));
ce5e49b0
         if (s->pict_type == AV_PICTURE_TYPE_B) {
a7d2861d
             for (i = 0; i < 4; i++)
                 memset(s->current_picture.f.motion_val[1][b_xy + i * h->b_stride],
                        0, 4 * 2 * sizeof(int16_t));
76de302d
         }
8b82a956
     }
76de302d
     if (!IS_INTRA4x4(mb_type)) {
a7d2861d
         memset(h->intra4x4_pred_mode + h->mb2br_xy[mb_xy], DC_PRED, 8);
da3b9756
     }
ce5e49b0
     if (!IS_SKIP(mb_type) || s->pict_type == AV_PICTURE_TYPE_B) {
a7d2861d
         memset(h->non_zero_count_cache + 8, 0, 14 * 8 * sizeof(uint8_t));
         s->dsp.clear_blocks(h->mb +   0);
         s->dsp.clear_blocks(h->mb + 384);
884182b3
     }
2e26c8d2
 
a7d2861d
     if (!IS_INTRA16x16(mb_type) &&
         (!IS_SKIP(mb_type) || s->pict_type == AV_PICTURE_TYPE_B)) {
979bea13
         if ((vlc = svq3_get_ue_golomb(&s->gb)) >= 48U){
76de302d
             av_log(h->s.avctx, AV_LOG_ERROR, "cbp_vlc=%d\n", vlc);
             return -1;
         }
8b82a956
 
a7d2861d
         cbp = IS_INTRA(mb_type) ? golomb_to_intra4x4_cbp[vlc]
                                 : golomb_to_inter_cbp[vlc];
884182b3
     }
a7d2861d
     if (IS_INTRA16x16(mb_type) ||
         (s->pict_type != AV_PICTURE_TYPE_I && s->adaptive_quant && cbp)) {
76de302d
         s->qscale += svq3_get_se_golomb(&s->gb);
8b82a956
 
a7d2861d
         if (s->qscale > 31u) {
76de302d
             av_log(h->s.avctx, AV_LOG_ERROR, "qscale:%d\n", s->qscale);
bb270c08
             return -1;
         }
8b82a956
     }
76de302d
     if (IS_INTRA16x16(mb_type)) {
a7d2861d
         AV_ZERO128(h->mb_luma_dc[0] + 0);
         AV_ZERO128(h->mb_luma_dc[0] + 8);
         if (svq3_decode_block(&s->gb, h->mb_luma_dc[0], 0, 1)) {
             av_log(h->s.avctx, AV_LOG_ERROR,
                    "error while decoding intra luma dc\n");
76de302d
             return -1;
884182b3
         }
76de302d
     }
8b82a956
 
76de302d
     if (cbp) {
         const int index = IS_INTRA16x16(mb_type) ? 1 : 0;
a7d2861d
         const int type  = ((s->qscale < 24 && IS_INTRA4x4(mb_type)) ? 2 : 1);
76de302d
 
a7d2861d
         for (i = 0; i < 4; i++)
76de302d
             if ((cbp & (1 << i))) {
                 for (j = 0; j < 4; j++) {
a7d2861d
                     k = index ? (1 * (j & 1) + 2 * (i & 1) +
                                  2 * (j & 2) + 4 * (i & 2))
                               : (4 * i + j);
                     h->non_zero_count_cache[scan8[k]] = 1;
 
                     if (svq3_decode_block(&s->gb, &h->mb[16 * k], index, type)) {
                         av_log(h->s.avctx, AV_LOG_ERROR,
                                "error while decoding block\n");
76de302d
                         return -1;
                     }
                 }
             }
8b82a956
 
76de302d
         if ((cbp & 0x30)) {
a7d2861d
             for (i = 1; i < 3; ++i)
                 if (svq3_decode_block(&s->gb, &h->mb[16 * 16 * i], 0, 3)) {
                     av_log(h->s.avctx, AV_LOG_ERROR,
                            "error while decoding chroma dc block\n");
                     return -1;
                 }
76de302d
 
             if ((cbp & 0x20)) {
11177a4d
                 for (i = 1; i < 3; i++) {
                     for (j = 0; j < 4; j++) {
a7d2861d
                         k                                 = 16 * i + j;
                         h->non_zero_count_cache[scan8[k]] = 1;
11177a4d
 
a7d2861d
                         if (svq3_decode_block(&s->gb, &h->mb[16 * k], 1, 1)) {
                             av_log(h->s.avctx, AV_LOG_ERROR,
                                    "error while decoding chroma ac block\n");
11177a4d
                             return -1;
                         }
76de302d
                     }
                 }
             }
bb270c08
         }
8b82a956
     }
 
a7d2861d
     h->cbp                              = cbp;
657ccb5a
     s->current_picture.f.mb_type[mb_xy] = mb_type;
8b82a956
 
a7d2861d
     if (IS_INTRA(mb_type))
45b7bd7c
         h->chroma_pred_mode = ff_h264_check_intra_pred_mode(h, DC_PRED8x8, 1);
8b82a956
 
76de302d
     return 0;
8b82a956
 }
 
8811679c
 static int svq3_decode_slice_header(AVCodecContext *avctx)
7f8205da
 {
8811679c
     SVQ3Context *svq3 = avctx->priv_data;
a7d2861d
     H264Context *h    = &svq3->h;
8811679c
     MpegEncContext *s = &h->s;
a7d2861d
     const int mb_xy   = h->mb_xy;
76de302d
     int i, header;
288bb3da
     unsigned slice_id;
da3b9756
 
76de302d
     header = get_bits(&s->gb, 8);
da3b9756
 
76de302d
     if (((header & 0x9F) != 1 && (header & 0x9F) != 2) || (header & 0x60) == 0) {
         /* TODO: what? */
8811679c
         av_log(avctx, AV_LOG_ERROR, "unsupported slice header (%02X)\n", header);
76de302d
         return -1;
     } else {
af1ede06
         int length = header >> 5 & 3;
da3b9756
 
a7d2861d
         svq3->next_slice_index = get_bits_count(&s->gb) +
                                  8 * show_bits(&s->gb, 8 * length) +
                                  8 * length;
da3b9756
 
8811679c
         if (svq3->next_slice_index > s->gb.size_in_bits) {
             av_log(avctx, AV_LOG_ERROR, "slice after bitstream end\n");
76de302d
             return -1;
a7d2861d
         }
da3b9756
 
a7d2861d
         s->gb.size_in_bits = svq3->next_slice_index - 8 * (length - 1);
76de302d
         skip_bits(&s->gb, 8);
da3b9756
 
8811679c
         if (svq3->watermark_key) {
a7d2861d
             uint32_t header = AV_RL32(&s->gb.buffer[(get_bits_count(&s->gb) >> 3) + 1]);
             AV_WL32(&s->gb.buffer[(get_bits_count(&s->gb) >> 3) + 1],
                     header ^ svq3->watermark_key);
76de302d
         }
         if (length > 0) {
             memcpy((uint8_t *) &s->gb.buffer[get_bits_count(&s->gb) >> 3],
af1ede06
                    &s->gb.buffer[s->gb.size_in_bits >> 3], length - 1);
76de302d
         }
db794291
         skip_bits_long(&s->gb, 0);
da3b9756
     }
 
288bb3da
     if ((slice_id = svq3_get_ue_golomb(&s->gb)) >= 3) {
         av_log(h->s.avctx, AV_LOG_ERROR, "illegal slice type %d \n", slice_id);
76de302d
         return -1;
     }
da3b9756
 
288bb3da
     h->slice_type = golomb_to_pict_type[slice_id];
da3b9756
 
76de302d
     if ((header & 0x9F) == 2) {
a7d2861d
         i              = (s->mb_num < 64) ? 6 : (1 + av_log2(s->mb_num - 1));
         s->mb_skip_run = get_bits(&s->gb, i) -
af1ede06
                          (s->mb_y * s->mb_width + s->mb_x);
76de302d
     } else {
         skip_bits1(&s->gb);
         s->mb_skip_run = 0;
     }
da3b9756
 
a7d2861d
     h->slice_num      = get_bits(&s->gb, 8);
     s->qscale         = get_bits(&s->gb, 5);
76de302d
     s->adaptive_quant = get_bits1(&s->gb);
da3b9756
 
76de302d
     /* unknown fields */
     skip_bits1(&s->gb);
da3b9756
 
a7d2861d
     if (svq3->unknown_flag)
76de302d
         skip_bits1(&s->gb);
da3b9756
 
76de302d
     skip_bits1(&s->gb);
     skip_bits(&s->gb, 2);
da3b9756
 
a7d2861d
     while (get_bits1(&s->gb))
76de302d
         skip_bits(&s->gb, 8);
da3b9756
 
76de302d
     /* reset intra predictors and invalidate motion vector references */
da3b9756
     if (s->mb_x > 0) {
a7d2861d
         memset(h->intra4x4_pred_mode + h->mb2br_xy[mb_xy - 1] + 3,
                -1, 4 * sizeof(int8_t));
         memset(h->intra4x4_pred_mode + h->mb2br_xy[mb_xy - s->mb_x],
                -1, 8 * sizeof(int8_t) * s->mb_x);
76de302d
     }
     if (s->mb_y > 0) {
a7d2861d
         memset(h->intra4x4_pred_mode + h->mb2br_xy[mb_xy - s->mb_stride],
                -1, 8 * sizeof(int8_t) * (s->mb_width - s->mb_x));
76de302d
 
a7d2861d
         if (s->mb_x > 0)
             h->intra4x4_pred_mode[h->mb2br_xy[mb_xy - s->mb_stride - 1] + 3] = -1;
da3b9756
     }
 
76de302d
     return 0;
da3b9756
 }
 
5ef251e5
 static av_cold int svq3_decode_init(AVCodecContext *avctx)
7f8205da
 {
8811679c
     SVQ3Context *svq3 = avctx->priv_data;
a7d2861d
     H264Context *h    = &svq3->h;
8811679c
     MpegEncContext *s = &h->s;
f4cca718
     int m;
76de302d
     unsigned char *extradata;
9e1db721
     unsigned char *extradata_end;
76de302d
     unsigned int size;
9e1db721
     int marker_found = 0;
76de302d
 
903d58f6
     if (ff_h264_decode_init(avctx) < 0)
f4cca718
         return -1;
 
a7d2861d
     s->flags           = avctx->flags;
     s->flags2          = avctx->flags2;
76de302d
     s->unrestricted_mv = 1;
a7d2861d
     h->is_complex      = 1;
28a613b0
     h->sps.chroma_format_idc = 1;
a7d2861d
     avctx->pix_fmt     = avctx->codec->pix_fmts[0];
76de302d
 
     if (!s->context_initialized) {
8811679c
         h->chroma_qp[0] = h->chroma_qp[1] = 4;
 
8dfc6d1f
         svq3->halfpel_flag  = 1;
8811679c
         svq3->thirdpel_flag = 1;
8dfc6d1f
         svq3->unknown_flag  = 0;
76de302d
 
 
         /* prowl for the "SEQH" marker in the extradata */
a7d2861d
         extradata     = (unsigned char *)avctx->extradata;
9e1db721
         extradata_end = avctx->extradata + avctx->extradata_size;
         if (extradata) {
             for (m = 0; m + 8 < avctx->extradata_size; m++) {
                 if (!memcmp(extradata, "SEQH", 4)) {
                     marker_found = 1;
                     break;
                 }
                 extradata++;
             }
76de302d
         }
8b82a956
 
76de302d
         /* if a match was found, parse the extra data */
9e1db721
         if (marker_found) {
76de302d
             GetBitContext gb;
faccfeec
             int frame_size_code;
8b82a956
 
76de302d
             size = AV_RB32(&extradata[4]);
9e1db721
             if (size > extradata_end - extradata - 8)
                 return AVERROR_INVALIDDATA;
a7d2861d
             init_get_bits(&gb, extradata + 8, size * 8);
8b82a956
 
76de302d
             /* 'frame size code' and optional 'width, height' */
faccfeec
             frame_size_code = get_bits(&gb, 3);
             switch (frame_size_code) {
a7d2861d
             case 0:
                 avctx->width  = 160;
                 avctx->height = 120;
                 break;
             case 1:
                 avctx->width  = 128;
                 avctx->height =  96;
                 break;
             case 2:
                 avctx->width  = 176;
                 avctx->height = 144;
                 break;
             case 3:
                 avctx->width  = 352;
                 avctx->height = 288;
                 break;
             case 4:
                 avctx->width  = 704;
                 avctx->height = 576;
                 break;
             case 5:
                 avctx->width  = 240;
                 avctx->height = 180;
                 break;
             case 6:
                 avctx->width  = 320;
                 avctx->height = 240;
                 break;
             case 7:
                 avctx->width  = get_bits(&gb, 12);
                 avctx->height = get_bits(&gb, 12);
                 break;
76de302d
             }
8b82a956
 
8811679c
             svq3->halfpel_flag  = get_bits1(&gb);
             svq3->thirdpel_flag = get_bits1(&gb);
8b82a956
 
76de302d
             /* unknown fields */
             skip_bits1(&gb);
             skip_bits1(&gb);
             skip_bits1(&gb);
             skip_bits1(&gb);
8b82a956
 
76de302d
             s->low_delay = get_bits1(&gb);
1e002b60
 
76de302d
             /* unknown field */
             skip_bits1(&gb);
 
a7d2861d
             while (get_bits1(&gb))
76de302d
                 skip_bits(&gb, 8);
 
a7d2861d
             svq3->unknown_flag  = get_bits1(&gb);
76de302d
             avctx->has_b_frames = !s->low_delay;
8811679c
             if (svq3->unknown_flag) {
b250f9c6
 #if CONFIG_ZLIB
76de302d
                 unsigned watermark_width  = svq3_get_ue_golomb(&gb);
                 unsigned watermark_height = svq3_get_ue_golomb(&gb);
a7d2861d
                 int u1                    = svq3_get_ue_golomb(&gb);
                 int u2                    = get_bits(&gb, 8);
                 int u3                    = get_bits(&gb, 2);
                 int u4                    = svq3_get_ue_golomb(&gb);
                 unsigned long buf_len     = watermark_width *
                                             watermark_height * 4;
af1ede06
                 int offset                = get_bits_count(&gb) + 7 >> 3;
76de302d
                 uint8_t *buf;
 
829e4301
                 if (watermark_height <= 0 ||
3ee5458a
                     (uint64_t)watermark_width * 4 > UINT_MAX / watermark_height)
76de302d
                     return -1;
 
                 buf = av_malloc(buf_len);
a7d2861d
                 av_log(avctx, AV_LOG_DEBUG, "watermark size: %dx%d\n",
                        watermark_width, watermark_height);
                 av_log(avctx, AV_LOG_DEBUG,
                        "u1: %x u2: %x u3: %x compressed data size: %d offset: %d\n",
                        u1, u2, u3, u4, offset);
                 if (uncompress(buf, &buf_len, extradata + 8 + offset,
                                size - offset) != Z_OK) {
                     av_log(avctx, AV_LOG_ERROR,
                            "could not uncompress watermark logo\n");
76de302d
                     av_free(buf);
                     return -1;
                 }
8811679c
                 svq3->watermark_key = ff_svq1_packet_checksum(buf, buf_len, 0);
a7d2861d
                 svq3->watermark_key = svq3->watermark_key << 16 |
                                       svq3->watermark_key;
                 av_log(avctx, AV_LOG_DEBUG,
                        "watermark key %#x\n", svq3->watermark_key);
76de302d
                 av_free(buf);
1e002b60
 #else
a7d2861d
                 av_log(avctx, AV_LOG_ERROR,
                        "this svq3 file contains watermark which need zlib support compiled in\n");
76de302d
                 return -1;
1e002b60
 #endif
76de302d
             }
         }
cdca7c37
 
         s->width  = avctx->width;
         s->height = avctx->height;
 
efd29844
         if (ff_MPV_common_init(s) < 0)
cdca7c37
             return -1;
 
a7d2861d
         h->b_stride = 4 * s->mb_width;
cdca7c37
 
a3e215cd
         if (ff_h264_alloc_tables(h) < 0) {
             av_log(avctx, AV_LOG_ERROR, "svq3 memory allocation failed\n");
             return AVERROR(ENOMEM);
         }
da3b9756
     }
76de302d
 
f4cca718
     return 0;
 }
 
a7d2861d
 static int svq3_decode_frame(AVCodecContext *avctx, void *data,
df9b9567
                              int *got_frame, AVPacket *avpkt)
f4cca718
 {
a7d2861d
     SVQ3Context *svq3  = avctx->priv_data;
     H264Context *h     = &svq3->h;
     MpegEncContext *s  = &h->s;
     int buf_size       = avpkt->size;
5c076205
     int m, left;
2264c110
     uint8_t *buf;
f4cca718
 
76de302d
     /* special case for last picture */
     if (buf_size == 0) {
         if (s->next_picture_ptr && !s->low_delay) {
324deaa2
             *(AVFrame *) data   = s->next_picture.f;
76de302d
             s->next_picture_ptr = NULL;
df9b9567
             *got_frame          = 1;
76de302d
         }
         return 0;
da3b9756
     }
8b82a956
 
76de302d
     s->mb_x = s->mb_y = h->mb_xy = 0;
8b82a956
 
2264c110
     if (svq3->watermark_key) {
f44967b1
         av_fast_malloc(&svq3->buf, &svq3->buf_size,
                        buf_size+FF_INPUT_BUFFER_PADDING_SIZE);
2264c110
         if (!svq3->buf)
             return AVERROR(ENOMEM);
         memcpy(svq3->buf, avpkt->data, buf_size);
         buf = svq3->buf;
     } else {
         buf = avpkt->data;
     }
 
0e097616
     init_get_bits(&s->gb, buf, 8 * buf_size);
2264c110
 
8811679c
     if (svq3_decode_slice_header(avctx))
76de302d
         return -1;
8b82a956
 
a7d2861d
     s->pict_type      = h->slice_type;
76de302d
     s->picture_number = h->slice_num;
8b82a956
 
a7d2861d
     if (avctx->debug & FF_DEBUG_PICT_INFO)
         av_log(h->s.avctx, AV_LOG_DEBUG,
                "%c hpel:%d, tpel:%d aqp:%d qp:%d, slice_num:%02X\n",
                av_get_picture_type_char(s->pict_type),
                svq3->halfpel_flag, svq3->thirdpel_flag,
76de302d
                s->adaptive_quant, s->qscale, h->slice_num);
8b82a956
 
8ed2ae09
     /* for skipping the frame */
657ccb5a
     s->current_picture.f.pict_type = s->pict_type;
     s->current_picture.f.key_frame = (s->pict_type == AV_PICTURE_TYPE_I);
76de302d
 
     /* Skip B-frames if we do not have reference frames. */
ce5e49b0
     if (s->last_picture_ptr == NULL && s->pict_type == AV_PICTURE_TYPE_B)
76de302d
         return 0;
af1ede06
     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)
76de302d
         return 0;
 
     if (s->next_p_frame_damaged) {
ce5e49b0
         if (s->pict_type == AV_PICTURE_TYPE_B)
76de302d
             return 0;
         else
             s->next_p_frame_damaged = 0;
     }
da3b9756
 
903d58f6
     if (ff_h264_frame_start(h) < 0)
76de302d
         return -1;
8b82a956
 
ce5e49b0
     if (s->pict_type == AV_PICTURE_TYPE_B) {
af1ede06
         h->frame_num_offset = h->slice_num - h->prev_frame_num;
8b82a956
 
a7d2861d
         if (h->frame_num_offset < 0)
76de302d
             h->frame_num_offset += 256;
a7d2861d
         if (h->frame_num_offset == 0 ||
             h->frame_num_offset >= h->prev_frame_num_offset) {
76de302d
             av_log(h->s.avctx, AV_LOG_ERROR, "error in B-frame picture id\n");
             return -1;
         }
     } else {
a7d2861d
         h->prev_frame_num        = h->frame_num;
         h->frame_num             = h->slice_num;
af1ede06
         h->prev_frame_num_offset = h->frame_num - h->prev_frame_num;
da3b9756
 
a7d2861d
         if (h->prev_frame_num_offset < 0)
76de302d
             h->prev_frame_num_offset += 256;
da3b9756
     }
 
a7d2861d
     for (m = 0; m < 2; m++) {
76de302d
         int i;
a7d2861d
         for (i = 0; i < 4; i++) {
76de302d
             int j;
             for (j = -1; j < 4; j++)
a7d2861d
                 h->ref_cache[m][scan8[0] + 8 * i + j] = 1;
76de302d
             if (i < 3)
a7d2861d
                 h->ref_cache[m][scan8[0] + 8 * i + j] = PART_NOT_AVAILABLE;
76de302d
         }
da3b9756
     }
 
76de302d
     for (s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++) {
         for (s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++) {
9a2e7911
             unsigned mb_type;
a7d2861d
             h->mb_xy = s->mb_x + s->mb_y * s->mb_stride;
da3b9756
 
a7d2861d
             if ((get_bits_count(&s->gb) + 7) >= s->gb.size_in_bits &&
                 ((get_bits_count(&s->gb) & 7) == 0 ||
af1ede06
                  show_bits(&s->gb, -get_bits_count(&s->gb) & 7) == 0)) {
8811679c
                 skip_bits(&s->gb, svq3->next_slice_index - get_bits_count(&s->gb));
a7d2861d
                 s->gb.size_in_bits = 8 * buf_size;
da3b9756
 
8811679c
                 if (svq3_decode_slice_header(avctx))
76de302d
                     return -1;
da3b9756
 
76de302d
                 /* TODO: support s->mb_skip_run */
             }
da3b9756
 
76de302d
             mb_type = svq3_get_ue_golomb(&s->gb);
da3b9756
 
a7d2861d
             if (s->pict_type == AV_PICTURE_TYPE_I)
76de302d
                 mb_type += 8;
a7d2861d
             else if (s->pict_type == AV_PICTURE_TYPE_B && mb_type >= 4)
76de302d
                 mb_type += 4;
9a2e7911
             if (mb_type > 33 || svq3_decode_mb(svq3, mb_type)) {
a7d2861d
                 av_log(h->s.avctx, AV_LOG_ERROR,
                        "error while decoding MB %d %d\n", s->mb_x, s->mb_y);
76de302d
                 return -1;
             }
8b82a956
 
a7d2861d
             if (mb_type != 0)
                 ff_h264_hl_decode_mb(h);
8b82a956
 
a7d2861d
             if (s->pict_type != AV_PICTURE_TYPE_B && !s->low_delay)
657ccb5a
                 s->current_picture.f.mb_type[s->mb_x + s->mb_y * s->mb_stride] =
ce5e49b0
                     (s->pict_type == AV_PICTURE_TYPE_P && mb_type < 8) ? (mb_type - 1) : -1;
76de302d
         }
2e26c8d2
 
a7d2861d
         ff_draw_horiz_band(s, 16 * s->mb_y, 16);
8b82a956
     }
4c701ac8
 
b0e7a932
     left = buf_size*8 - get_bits_count(&s->gb);
 
     if (s->mb_y != s->mb_height || s->mb_x != s->mb_width) {
         av_log(avctx, AV_LOG_INFO, "frame num %d incomplete pic x %d y %d left %d\n", avctx->frame_number, s->mb_y, s->mb_x, left);
         //av_hex_dump(stderr, buf+buf_size-8, 8);
     }
 
     if (left < 0) {
         av_log(avctx, AV_LOG_ERROR, "frame num %d left %d\n", avctx->frame_number, left);
         return -1;
     }
 
efd29844
     ff_MPV_frame_end(s);
8b82a956
 
a7d2861d
     if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay)
         *(AVFrame *)data = s->current_picture.f;
     else
         *(AVFrame *)data = s->last_picture.f;
da3b9756
 
76de302d
     /* Do not output the last pic after seeking. */
a7d2861d
     if (s->last_picture_ptr || s->low_delay)
df9b9567
         *got_frame = 1;
da3b9756
 
76de302d
     return buf_size;
8b82a956
 }
 
8811679c
 static int svq3_decode_end(AVCodecContext *avctx)
 {
     SVQ3Context *svq3 = avctx->priv_data;
a7d2861d
     H264Context *h    = &svq3->h;
8811679c
     MpegEncContext *s = &h->s;
 
     ff_h264_free_context(h);
 
efd29844
     ff_MPV_common_end(s);
8811679c
 
2264c110
     av_freep(&svq3->buf);
     svq3->buf_size = 0;
 
8811679c
     return 0;
 }
8b82a956
 
e7e2df27
 AVCodec ff_svq3_decoder = {
ec6402b7
     .name           = "svq3",
     .type           = AVMEDIA_TYPE_VIDEO,
36ef5369
     .id             = AV_CODEC_ID_SVQ3,
ec6402b7
     .priv_data_size = sizeof(SVQ3Context),
     .init           = svq3_decode_init,
     .close          = svq3_decode_end,
     .decode         = svq3_decode_frame,
a7d2861d
     .capabilities   = CODEC_CAP_DRAW_HORIZ_BAND |
                       CODEC_CAP_DR1             |
00c3b67b
                       CODEC_CAP_DELAY,
     .long_name      = NULL_IF_CONFIG_SMALL("Sorenson Vector Quantizer 3 / Sorenson Video 3 / SVQ3"),
a7d2861d
     .pix_fmts       = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P,
                                                      AV_PIX_FMT_NONE},
8b82a956
 };