Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * LucasArts Smush video decoder
  3.  * Copyright (c) 2006 Cyril Zorin
  4.  * Copyright (c) 2011 Konstantin Shishkov
  5.  *
  6.  * This file is part of FFmpeg.
  7.  *
  8.  * FFmpeg is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Lesser General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2.1 of the License, or (at your option) any later version.
  12.  *
  13.  * FFmpeg is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Lesser General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Lesser General Public
  19.  * License along with FFmpeg; if not, write to the Free Software
  20.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21.  */
  22.  
  23. #include "libavutil/avassert.h"
  24. #include "libavutil/bswap.h"
  25. #include "libavutil/imgutils.h"
  26.  
  27. #include "avcodec.h"
  28. #include "bytestream.h"
  29. #include "copy_block.h"
  30. #include "internal.h"
  31.  
  32. #define NGLYPHS 256
  33. #define GLYPH_COORD_VECT_SIZE 16
  34. #define PALETTE_SIZE 256
  35. #define PALETTE_DELTA 768
  36.  
  37. static const int8_t glyph4_x[GLYPH_COORD_VECT_SIZE] = {
  38.     0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 1, 2, 2, 1
  39. };
  40.  
  41. static const int8_t glyph4_y[GLYPH_COORD_VECT_SIZE] = {
  42.     0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 1, 1, 2, 2
  43. };
  44.  
  45. static const int8_t glyph8_x[GLYPH_COORD_VECT_SIZE] = {
  46.     0, 2, 5, 7, 7, 7, 7, 7, 7, 5, 2, 0, 0, 0, 0, 0
  47. };
  48.  
  49. static const int8_t glyph8_y[GLYPH_COORD_VECT_SIZE] = {
  50.     0, 0, 0, 0, 1, 3, 4, 6, 7, 7, 7, 7, 6, 4, 3, 1
  51. };
  52.  
  53. static const int8_t motion_vectors[256][2] = {
  54.     {   0,   0 }, {  -1, -43 }, {   6, -43 }, {  -9, -42 }, {  13, -41 },
  55.     { -16, -40 }, {  19, -39 }, { -23, -36 }, {  26, -34 }, {  -2, -33 },
  56.     {   4, -33 }, { -29, -32 }, {  -9, -32 }, {  11, -31 }, { -16, -29 },
  57.     {  32, -29 }, {  18, -28 }, { -34, -26 }, { -22, -25 }, {  -1, -25 },
  58.     {   3, -25 }, {  -7, -24 }, {   8, -24 }, {  24, -23 }, {  36, -23 },
  59.     { -12, -22 }, {  13, -21 }, { -38, -20 }, {   0, -20 }, { -27, -19 },
  60.     {  -4, -19 }, {   4, -19 }, { -17, -18 }, {  -8, -17 }, {   8, -17 },
  61.     {  18, -17 }, {  28, -17 }, {  39, -17 }, { -12, -15 }, {  12, -15 },
  62.     { -21, -14 }, {  -1, -14 }, {   1, -14 }, { -41, -13 }, {  -5, -13 },
  63.     {   5, -13 }, {  21, -13 }, { -31, -12 }, { -15, -11 }, {  -8, -11 },
  64.     {   8, -11 }, {  15, -11 }, {  -2, -10 }, {   1, -10 }, {  31, -10 },
  65.     { -23,  -9 }, { -11,  -9 }, {  -5,  -9 }, {   4,  -9 }, {  11,  -9 },
  66.     {  42,  -9 }, {   6,  -8 }, {  24,  -8 }, { -18,  -7 }, {  -7,  -7 },
  67.     {  -3,  -7 }, {  -1,  -7 }, {   2,  -7 }, {  18,  -7 }, { -43,  -6 },
  68.     { -13,  -6 }, {  -4,  -6 }, {   4,  -6 }, {   8,  -6 }, { -33,  -5 },
  69.     {  -9,  -5 }, {  -2,  -5 }, {   0,  -5 }, {   2,  -5 }, {   5,  -5 },
  70.     {  13,  -5 }, { -25,  -4 }, {  -6,  -4 }, {  -3,  -4 }, {   3,  -4 },
  71.     {   9,  -4 }, { -19,  -3 }, {  -7,  -3 }, {  -4,  -3 }, {  -2,  -3 },
  72.     {  -1,  -3 }, {   0,  -3 }, {   1,  -3 }, {   2,  -3 }, {   4,  -3 },
  73.     {   6,  -3 }, {  33,  -3 }, { -14,  -2 }, { -10,  -2 }, {  -5,  -2 },
  74.     {  -3,  -2 }, {  -2,  -2 }, {  -1,  -2 }, {   0,  -2 }, {   1,  -2 },
  75.     {   2,  -2 }, {   3,  -2 }, {   5,  -2 }, {   7,  -2 }, {  14,  -2 },
  76.     {  19,  -2 }, {  25,  -2 }, {  43,  -2 }, {  -7,  -1 }, {  -3,  -1 },
  77.     {  -2,  -1 }, {  -1,  -1 }, {   0,  -1 }, {   1,  -1 }, {   2,  -1 },
  78.     {   3,  -1 }, {  10,  -1 }, {  -5,   0 }, {  -3,   0 }, {  -2,   0 },
  79.     {  -1,   0 }, {   1,   0 }, {   2,   0 }, {   3,   0 }, {   5,   0 },
  80.     {   7,   0 }, { -10,   1 }, {  -7,   1 }, {  -3,   1 }, {  -2,   1 },
  81.     {  -1,   1 }, {   0,   1 }, {   1,   1 }, {   2,   1 }, {   3,   1 },
  82.     { -43,   2 }, { -25,   2 }, { -19,   2 }, { -14,   2 }, {  -5,   2 },
  83.     {  -3,   2 }, {  -2,   2 }, {  -1,   2 }, {   0,   2 }, {   1,   2 },
  84.     {   2,   2 }, {   3,   2 }, {   5,   2 }, {   7,   2 }, {  10,   2 },
  85.     {  14,   2 }, { -33,   3 }, {  -6,   3 }, {  -4,   3 }, {  -2,   3 },
  86.     {  -1,   3 }, {   0,   3 }, {   1,   3 }, {   2,   3 }, {   4,   3 },
  87.     {  19,   3 }, {  -9,   4 }, {  -3,   4 }, {   3,   4 }, {   7,   4 },
  88.     {  25,   4 }, { -13,   5 }, {  -5,   5 }, {  -2,   5 }, {   0,   5 },
  89.     {   2,   5 }, {   5,   5 }, {   9,   5 }, {  33,   5 }, {  -8,   6 },
  90.     {  -4,   6 }, {   4,   6 }, {  13,   6 }, {  43,   6 }, { -18,   7 },
  91.     {  -2,   7 }, {   0,   7 }, {   2,   7 }, {   7,   7 }, {  18,   7 },
  92.     { -24,   8 }, {  -6,   8 }, { -42,   9 }, { -11,   9 }, {  -4,   9 },
  93.     {   5,   9 }, {  11,   9 }, {  23,   9 }, { -31,  10 }, {  -1,  10 },
  94.     {   2,  10 }, { -15,  11 }, {  -8,  11 }, {   8,  11 }, {  15,  11 },
  95.     {  31,  12 }, { -21,  13 }, {  -5,  13 }, {   5,  13 }, {  41,  13 },
  96.     {  -1,  14 }, {   1,  14 }, {  21,  14 }, { -12,  15 }, {  12,  15 },
  97.     { -39,  17 }, { -28,  17 }, { -18,  17 }, {  -8,  17 }, {   8,  17 },
  98.     {  17,  18 }, {  -4,  19 }, {   0,  19 }, {   4,  19 }, {  27,  19 },
  99.     {  38,  20 }, { -13,  21 }, {  12,  22 }, { -36,  23 }, { -24,  23 },
  100.     {  -8,  24 }, {   7,  24 }, {  -3,  25 }, {   1,  25 }, {  22,  25 },
  101.     {  34,  26 }, { -18,  28 }, { -32,  29 }, {  16,  29 }, { -11,  31 },
  102.     {   9,  32 }, {  29,  32 }, {  -4,  33 }, {   2,  33 }, { -26,  34 },
  103.     {  23,  36 }, { -19,  39 }, {  16,  40 }, { -13,  41 }, {   9,  42 },
  104.     {  -6,  43 }, {   1,  43 }, {   0,   0 }, {   0,   0 }, {   0,   0 },
  105. };
  106.  
  107. static const int8_t c37_mv[] = {
  108.     0,   0,   1,   0,   2,   0,   3,   0,   5,   0,
  109.     8,   0,  13,   0,  21,   0,  -1,   0,  -2,   0,
  110.    -3,   0,  -5,   0,  -8,   0, -13,   0, -17,   0,
  111.   -21,   0,   0,   1,   1,   1,   2,   1,   3,   1,
  112.     5,   1,   8,   1,  13,   1,  21,   1,  -1,   1,
  113.    -2,   1,  -3,   1,  -5,   1,  -8,   1, -13,   1,
  114.   -17,   1, -21,   1,   0,   2,   1,   2,   2,   2,
  115.     3,   2,   5,   2,   8,   2,  13,   2,  21,   2,
  116.    -1,   2,  -2,   2,  -3,   2,  -5,   2,  -8,   2,
  117.   -13,   2, -17,   2, -21,   2,   0,   3,   1,   3,
  118.     2,   3,   3,   3,   5,   3,   8,   3,  13,   3,
  119.    21,   3,  -1,   3,  -2,   3,  -3,   3,  -5,   3,
  120.    -8,   3, -13,   3, -17,   3, -21,   3,   0,   5,
  121.     1,   5,   2,   5,   3,   5,   5,   5,   8,   5,
  122.    13,   5,  21,   5,  -1,   5,  -2,   5,  -3,   5,
  123.    -5,   5,  -8,   5, -13,   5, -17,   5, -21,   5,
  124.     0,   8,   1,   8,   2,   8,   3,   8,   5,   8,
  125.     8,   8,  13,   8,  21,   8,  -1,   8,  -2,   8,
  126.    -3,   8,  -5,   8,  -8,   8, -13,   8, -17,   8,
  127.   -21,   8,   0,  13,   1,  13,   2,  13,   3,  13,
  128.     5,  13,   8,  13,  13,  13,  21,  13,  -1,  13,
  129.    -2,  13,  -3,  13,  -5,  13,  -8,  13, -13,  13,
  130.   -17,  13, -21,  13,   0,  21,   1,  21,   2,  21,
  131.     3,  21,   5,  21,   8,  21,  13,  21,  21,  21,
  132.    -1,  21,  -2,  21,  -3,  21,  -5,  21,  -8,  21,
  133.   -13,  21, -17,  21, -21,  21,   0,  -1,   1,  -1,
  134.     2,  -1,   3,  -1,   5,  -1,   8,  -1,  13,  -1,
  135.    21,  -1,  -1,  -1,  -2,  -1,  -3,  -1,  -5,  -1,
  136.    -8,  -1, -13,  -1, -17,  -1, -21,  -1,   0,  -2,
  137.     1,  -2,   2,  -2,   3,  -2,   5,  -2,   8,  -2,
  138.    13,  -2,  21,  -2,  -1,  -2,  -2,  -2,  -3,  -2,
  139.    -5,  -2,  -8,  -2, -13,  -2, -17,  -2, -21,  -2,
  140.     0,  -3,   1,  -3,   2,  -3,   3,  -3,   5,  -3,
  141.     8,  -3,  13,  -3,  21,  -3,  -1,  -3,  -2,  -3,
  142.    -3,  -3,  -5,  -3,  -8,  -3, -13,  -3, -17,  -3,
  143.   -21,  -3,   0,  -5,   1,  -5,   2,  -5,   3,  -5,
  144.     5,  -5,   8,  -5,  13,  -5,  21,  -5,  -1,  -5,
  145.    -2,  -5,  -3,  -5,  -5,  -5,  -8,  -5, -13,  -5,
  146.   -17,  -5, -21,  -5,   0,  -8,   1,  -8,   2,  -8,
  147.     3,  -8,   5,  -8,   8,  -8,  13,  -8,  21,  -8,
  148.    -1,  -8,  -2,  -8,  -3,  -8,  -5,  -8,  -8,  -8,
  149.   -13,  -8, -17,  -8, -21,  -8,   0, -13,   1, -13,
  150.     2, -13,   3, -13,   5, -13,   8, -13,  13, -13,
  151.    21, -13,  -1, -13,  -2, -13,  -3, -13,  -5, -13,
  152.    -8, -13, -13, -13, -17, -13, -21, -13,   0, -17,
  153.     1, -17,   2, -17,   3, -17,   5, -17,   8, -17,
  154.    13, -17,  21, -17,  -1, -17,  -2, -17,  -3, -17,
  155.    -5, -17,  -8, -17, -13, -17, -17, -17, -21, -17,
  156.     0, -21,   1, -21,   2, -21,   3, -21,   5, -21,
  157.     8, -21,  13, -21,  21, -21,  -1, -21,  -2, -21,
  158.    -3, -21,  -5, -21,  -8, -21, -13, -21, -17, -21,
  159.     0,   0,  -8, -29,   8, -29, -18, -25,  17, -25,
  160.     0, -23,  -6, -22,   6, -22, -13, -19,  12, -19,
  161.     0, -18,  25, -18, -25, -17,  -5, -17,   5, -17,
  162.   -10, -15,  10, -15,   0, -14,  -4, -13,   4, -13,
  163.    19, -13, -19, -12,  -8, -11,  -2, -11,   0, -11,
  164.     2, -11,   8, -11, -15, -10,  -4, -10,   4, -10,
  165.    15, -10,  -6,  -9,  -1,  -9,   1,  -9,   6,  -9,
  166.   -29,  -8, -11,  -8,  -8,  -8,  -3,  -8,   3,  -8,
  167.     8,  -8,  11,  -8,  29,  -8,  -5,  -7,  -2,  -7,
  168.     0,  -7,   2,  -7,   5,  -7, -22,  -6,  -9,  -6,
  169.    -6,  -6,  -3,  -6,  -1,  -6,   1,  -6,   3,  -6,
  170.     6,  -6,   9,  -6,  22,  -6, -17,  -5,  -7,  -5,
  171.    -4,  -5,  -2,  -5,   0,  -5,   2,  -5,   4,  -5,
  172.     7,  -5,  17,  -5, -13,  -4, -10,  -4,  -5,  -4,
  173.    -3,  -4,  -1,  -4,   0,  -4,   1,  -4,   3,  -4,
  174.     5,  -4,  10,  -4,  13,  -4,  -8,  -3,  -6,  -3,
  175.    -4,  -3,  -3,  -3,  -2,  -3,  -1,  -3,   0,  -3,
  176.     1,  -3,   2,  -3,   4,  -3,   6,  -3,   8,  -3,
  177.   -11,  -2,  -7,  -2,  -5,  -2,  -3,  -2,  -2,  -2,
  178.    -1,  -2,   0,  -2,   1,  -2,   2,  -2,   3,  -2,
  179.     5,  -2,   7,  -2,  11,  -2,  -9,  -1,  -6,  -1,
  180.    -4,  -1,  -3,  -1,  -2,  -1,  -1,  -1,   0,  -1,
  181.     1,  -1,   2,  -1,   3,  -1,   4,  -1,   6,  -1,
  182.     9,  -1, -31,   0, -23,   0, -18,   0, -14,   0,
  183.   -11,   0,  -7,   0,  -5,   0,  -4,   0,  -3,   0,
  184.    -2,   0,  -1,   0,   0, -31,   1,   0,   2,   0,
  185.     3,   0,   4,   0,   5,   0,   7,   0,  11,   0,
  186.    14,   0,  18,   0,  23,   0,  31,   0,  -9,   1,
  187.    -6,   1,  -4,   1,  -3,   1,  -2,   1,  -1,   1,
  188.     0,   1,   1,   1,   2,   1,   3,   1,   4,   1,
  189.     6,   1,   9,   1, -11,   2,  -7,   2,  -5,   2,
  190.    -3,   2,  -2,   2,  -1,   2,   0,   2,   1,   2,
  191.     2,   2,   3,   2,   5,   2,   7,   2,  11,   2,
  192.    -8,   3,  -6,   3,  -4,   3,  -2,   3,  -1,   3,
  193.     0,   3,   1,   3,   2,   3,   3,   3,   4,   3,
  194.     6,   3,   8,   3, -13,   4, -10,   4,  -5,   4,
  195.    -3,   4,  -1,   4,   0,   4,   1,   4,   3,   4,
  196.     5,   4,  10,   4,  13,   4, -17,   5,  -7,   5,
  197.    -4,   5,  -2,   5,   0,   5,   2,   5,   4,   5,
  198.     7,   5,  17,   5, -22,   6,  -9,   6,  -6,   6,
  199.    -3,   6,  -1,   6,   1,   6,   3,   6,   6,   6,
  200.     9,   6,  22,   6,  -5,   7,  -2,   7,   0,   7,
  201.     2,   7,   5,   7, -29,   8, -11,   8,  -8,   8,
  202.    -3,   8,   3,   8,   8,   8,  11,   8,  29,   8,
  203.    -6,   9,  -1,   9,   1,   9,   6,   9, -15,  10,
  204.    -4,  10,   4,  10,  15,  10,  -8,  11,  -2,  11,
  205.     0,  11,   2,  11,   8,  11,  19,  12, -19,  13,
  206.    -4,  13,   4,  13,   0,  14, -10,  15,  10,  15,
  207.    -5,  17,   5,  17,  25,  17, -25,  18,   0,  18,
  208.   -12,  19,  13,  19,  -6,  22,   6,  22,   0,  23,
  209.   -17,  25,  18,  25,  -8,  29,   8,  29,   0,  31,
  210.     0,   0,  -6, -22,   6, -22, -13, -19,  12, -19,
  211.     0, -18,  -5, -17,   5, -17, -10, -15,  10, -15,
  212.     0, -14,  -4, -13,   4, -13,  19, -13, -19, -12,
  213.    -8, -11,  -2, -11,   0, -11,   2, -11,   8, -11,
  214.   -15, -10,  -4, -10,   4, -10,  15, -10,  -6,  -9,
  215.    -1,  -9,   1,  -9,   6,  -9, -11,  -8,  -8,  -8,
  216.    -3,  -8,   0,  -8,   3,  -8,   8,  -8,  11,  -8,
  217.    -5,  -7,  -2,  -7,   0,  -7,   2,  -7,   5,  -7,
  218.   -22,  -6,  -9,  -6,  -6,  -6,  -3,  -6,  -1,  -6,
  219.     1,  -6,   3,  -6,   6,  -6,   9,  -6,  22,  -6,
  220.   -17,  -5,  -7,  -5,  -4,  -5,  -2,  -5,  -1,  -5,
  221.     0,  -5,   1,  -5,   2,  -5,   4,  -5,   7,  -5,
  222.    17,  -5, -13,  -4, -10,  -4,  -5,  -4,  -3,  -4,
  223.    -2,  -4,  -1,  -4,   0,  -4,   1,  -4,   2,  -4,
  224.     3,  -4,   5,  -4,  10,  -4,  13,  -4,  -8,  -3,
  225.    -6,  -3,  -4,  -3,  -3,  -3,  -2,  -3,  -1,  -3,
  226.     0,  -3,   1,  -3,   2,  -3,   3,  -3,   4,  -3,
  227.     6,  -3,   8,  -3, -11,  -2,  -7,  -2,  -5,  -2,
  228.    -4,  -2,  -3,  -2,  -2,  -2,  -1,  -2,   0,  -2,
  229.     1,  -2,   2,  -2,   3,  -2,   4,  -2,   5,  -2,
  230.     7,  -2,  11,  -2,  -9,  -1,  -6,  -1,  -5,  -1,
  231.    -4,  -1,  -3,  -1,  -2,  -1,  -1,  -1,   0,  -1,
  232.     1,  -1,   2,  -1,   3,  -1,   4,  -1,   5,  -1,
  233.     6,  -1,   9,  -1, -23,   0, -18,   0, -14,   0,
  234.   -11,   0,  -7,   0,  -5,   0,  -4,   0,  -3,   0,
  235.    -2,   0,  -1,   0,   0, -23,   1,   0,   2,   0,
  236.     3,   0,   4,   0,   5,   0,   7,   0,  11,   0,
  237.    14,   0,  18,   0,  23,   0,  -9,   1,  -6,   1,
  238.    -5,   1,  -4,   1,  -3,   1,  -2,   1,  -1,   1,
  239.     0,   1,   1,   1,   2,   1,   3,   1,   4,   1,
  240.     5,   1,   6,   1,   9,   1, -11,   2,  -7,   2,
  241.    -5,   2,  -4,   2,  -3,   2,  -2,   2,  -1,   2,
  242.     0,   2,   1,   2,   2,   2,   3,   2,   4,   2,
  243.     5,   2,   7,   2,  11,   2,  -8,   3,  -6,   3,
  244.    -4,   3,  -3,   3,  -2,   3,  -1,   3,   0,   3,
  245.     1,   3,   2,   3,   3,   3,   4,   3,   6,   3,
  246.     8,   3, -13,   4, -10,   4,  -5,   4,  -3,   4,
  247.    -2,   4,  -1,   4,   0,   4,   1,   4,   2,   4,
  248.     3,   4,   5,   4,  10,   4,  13,   4, -17,   5,
  249.    -7,   5,  -4,   5,  -2,   5,  -1,   5,   0,   5,
  250.     1,   5,   2,   5,   4,   5,   7,   5,  17,   5,
  251.   -22,   6,  -9,   6,  -6,   6,  -3,   6,  -1,   6,
  252.     1,   6,   3,   6,   6,   6,   9,   6,  22,   6,
  253.    -5,   7,  -2,   7,   0,   7,   2,   7,   5,   7,
  254.   -11,   8,  -8,   8,  -3,   8,   0,   8,   3,   8,
  255.     8,   8,  11,   8,  -6,   9,  -1,   9,   1,   9,
  256.     6,   9, -15,  10,  -4,  10,   4,  10,  15,  10,
  257.    -8,  11,  -2,  11,   0,  11,   2,  11,   8,  11,
  258.    19,  12, -19,  13,  -4,  13,   4,  13,   0,  14,
  259.   -10,  15,  10,  15,  -5,  17,   5,  17,   0,  18,
  260.   -12,  19,  13,  19,  -6,  22,   6,  22,   0,  23,
  261. };
  262.  
  263. typedef struct SANMVideoContext {
  264.     AVCodecContext *avctx;
  265.     GetByteContext gb;
  266.  
  267.     int version, subversion;
  268.     uint32_t pal[PALETTE_SIZE];
  269.     int16_t delta_pal[PALETTE_DELTA];
  270.  
  271.     int pitch;
  272.     int width, height;
  273.     int aligned_width, aligned_height;
  274.     int prev_seq;
  275.  
  276.     AVFrame *frame;
  277.     uint16_t *frm0, *frm1, *frm2;
  278.     uint8_t *stored_frame;
  279.     uint32_t frm0_size, frm1_size, frm2_size;
  280.     uint32_t stored_frame_size;
  281.  
  282.     uint8_t *rle_buf;
  283.     unsigned int rle_buf_size;
  284.  
  285.     int rotate_code;
  286.  
  287.     long npixels, buf_size;
  288.  
  289.     uint16_t codebook[256];
  290.     uint16_t small_codebook[4];
  291.  
  292.     int8_t p4x4glyphs[NGLYPHS][16];
  293.     int8_t p8x8glyphs[NGLYPHS][64];
  294. } SANMVideoContext;
  295.  
  296. typedef struct SANMFrameHeader {
  297.     int seq_num, codec, rotate_code, rle_output_size;
  298.  
  299.     uint16_t bg_color;
  300.     uint32_t width, height;
  301. } SANMFrameHeader;
  302.  
  303. enum GlyphEdge {
  304.     LEFT_EDGE,
  305.     TOP_EDGE,
  306.     RIGHT_EDGE,
  307.     BOTTOM_EDGE,
  308.     NO_EDGE
  309. };
  310.  
  311. enum GlyphDir {
  312.     DIR_LEFT,
  313.     DIR_UP,
  314.     DIR_RIGHT,
  315.     DIR_DOWN,
  316.     NO_DIR
  317. };
  318.  
  319. /**
  320.  * Return enum GlyphEdge of box where point (x, y) lies.
  321.  *
  322.  * @param x x point coordinate
  323.  * @param y y point coordinate
  324.  * @param edge_size box width/height.
  325.  */
  326. static enum GlyphEdge which_edge(int x, int y, int edge_size)
  327. {
  328.     const int edge_max = edge_size - 1;
  329.  
  330.     if (!y)
  331.         return BOTTOM_EDGE;
  332.     else if (y == edge_max)
  333.         return TOP_EDGE;
  334.     else if (!x)
  335.         return LEFT_EDGE;
  336.     else if (x == edge_max)
  337.         return RIGHT_EDGE;
  338.     else
  339.         return NO_EDGE;
  340. }
  341.  
  342. static enum GlyphDir which_direction(enum GlyphEdge edge0, enum GlyphEdge edge1)
  343. {
  344.     if ((edge0 == LEFT_EDGE && edge1 == RIGHT_EDGE) ||
  345.         (edge1 == LEFT_EDGE && edge0 == RIGHT_EDGE) ||
  346.         (edge0 == BOTTOM_EDGE && edge1 != TOP_EDGE) ||
  347.         (edge1 == BOTTOM_EDGE && edge0 != TOP_EDGE))
  348.         return DIR_UP;
  349.     else if ((edge0 == TOP_EDGE && edge1 != BOTTOM_EDGE) ||
  350.              (edge1 == TOP_EDGE && edge0 != BOTTOM_EDGE))
  351.         return DIR_DOWN;
  352.     else if ((edge0 == LEFT_EDGE && edge1 != RIGHT_EDGE) ||
  353.              (edge1 == LEFT_EDGE && edge0 != RIGHT_EDGE))
  354.         return DIR_LEFT;
  355.     else if ((edge0 == TOP_EDGE && edge1 == BOTTOM_EDGE) ||
  356.              (edge1 == TOP_EDGE && edge0 == BOTTOM_EDGE) ||
  357.              (edge0 == RIGHT_EDGE && edge1 != LEFT_EDGE) ||
  358.              (edge1 == RIGHT_EDGE && edge0 != LEFT_EDGE))
  359.         return DIR_RIGHT;
  360.  
  361.     return NO_DIR;
  362. }
  363.  
  364. /* Interpolate two points. */
  365. static void interp_point(int8_t *points, int x0, int y0, int x1, int y1,
  366.                          int pos, int npoints)
  367. {
  368.     if (npoints) {
  369.         points[0] = (x0 * pos + x1 * (npoints - pos) + (npoints >> 1)) / npoints;
  370.         points[1] = (y0 * pos + y1 * (npoints - pos) + (npoints >> 1)) / npoints;
  371.     } else {
  372.         points[0] = x0;
  373.         points[1] = y0;
  374.     }
  375. }
  376.  
  377. /**
  378.  * Construct glyphs by iterating through vector coordinates.
  379.  *
  380.  * @param pglyphs pointer to table where glyphs are stored
  381.  * @param xvec pointer to x component of vector coordinates
  382.  * @param yvec pointer to y component of vector coordinates
  383.  * @param side_length glyph width/height.
  384.  */
  385. static void make_glyphs(int8_t *pglyphs, const int8_t *xvec, const int8_t *yvec,
  386.                         const int side_length)
  387. {
  388.     const int glyph_size = side_length * side_length;
  389.     int8_t *pglyph = pglyphs;
  390.  
  391.     int i, j;
  392.     for (i = 0; i < GLYPH_COORD_VECT_SIZE; i++) {
  393.         int x0 = xvec[i];
  394.         int y0 = yvec[i];
  395.         enum GlyphEdge edge0 = which_edge(x0, y0, side_length);
  396.  
  397.         for (j = 0; j < GLYPH_COORD_VECT_SIZE; j++, pglyph += glyph_size) {
  398.             int x1 = xvec[j];
  399.             int y1 = yvec[j];
  400.             enum GlyphEdge edge1 = which_edge(x1, y1, side_length);
  401.             enum GlyphDir dir = which_direction(edge0, edge1);
  402.             int npoints = FFMAX(FFABS(x1 - x0), FFABS(y1 - y0));
  403.             int ipoint;
  404.  
  405.             for (ipoint = 0; ipoint <= npoints; ipoint++) {
  406.                 int8_t point[2];
  407.                 int irow, icol;
  408.  
  409.                 interp_point(point, x0, y0, x1, y1, ipoint, npoints);
  410.  
  411.                 switch (dir) {
  412.                 case DIR_UP:
  413.                     for (irow = point[1]; irow >= 0; irow--)
  414.                         pglyph[point[0] + irow * side_length] = 1;
  415.                     break;
  416.  
  417.                 case DIR_DOWN:
  418.                     for (irow = point[1]; irow < side_length; irow++)
  419.                         pglyph[point[0] + irow * side_length] = 1;
  420.                     break;
  421.  
  422.                 case DIR_LEFT:
  423.                     for (icol = point[0]; icol >= 0; icol--)
  424.                         pglyph[icol + point[1] * side_length] = 1;
  425.                     break;
  426.  
  427.                 case DIR_RIGHT:
  428.                     for (icol = point[0]; icol < side_length; icol++)
  429.                         pglyph[icol + point[1] * side_length] = 1;
  430.                     break;
  431.                 }
  432.             }
  433.         }
  434.     }
  435. }
  436.  
  437. static void init_sizes(SANMVideoContext *ctx, int width, int height)
  438. {
  439.     ctx->width   = width;
  440.     ctx->height  = height;
  441.     ctx->npixels = width * height;
  442.  
  443.     ctx->aligned_width  = FFALIGN(width, 8);
  444.     ctx->aligned_height = FFALIGN(height, 8);
  445.  
  446.     ctx->buf_size = ctx->aligned_width * ctx->aligned_height * sizeof(ctx->frm0[0]);
  447.     ctx->pitch    = width;
  448. }
  449.  
  450. static void destroy_buffers(SANMVideoContext *ctx)
  451. {
  452.     av_freep(&ctx->frm0);
  453.     av_freep(&ctx->frm1);
  454.     av_freep(&ctx->frm2);
  455.     av_freep(&ctx->stored_frame);
  456.     av_freep(&ctx->rle_buf);
  457.     ctx->frm0_size =
  458.     ctx->frm1_size =
  459.     ctx->frm2_size = 0;
  460.     init_sizes(ctx, 0, 0);
  461. }
  462.  
  463. static av_cold int init_buffers(SANMVideoContext *ctx)
  464. {
  465.     av_fast_padded_malloc(&ctx->frm0, &ctx->frm0_size, ctx->buf_size);
  466.     av_fast_padded_malloc(&ctx->frm1, &ctx->frm1_size, ctx->buf_size);
  467.     av_fast_padded_malloc(&ctx->frm2, &ctx->frm2_size, ctx->buf_size);
  468.     if (!ctx->version)
  469.         av_fast_padded_malloc(&ctx->stored_frame,
  470.                               &ctx->stored_frame_size, ctx->buf_size);
  471.  
  472.     if (!ctx->frm0 || !ctx->frm1 || !ctx->frm2 ||
  473.         (!ctx->stored_frame && !ctx->version)) {
  474.         destroy_buffers(ctx);
  475.         return AVERROR(ENOMEM);
  476.     }
  477.  
  478.     return 0;
  479. }
  480.  
  481. static void rotate_bufs(SANMVideoContext *ctx, int rotate_code)
  482. {
  483.     if (rotate_code == 2)
  484.         FFSWAP(uint16_t*, ctx->frm1, ctx->frm2);
  485.     FFSWAP(uint16_t*, ctx->frm2, ctx->frm0);
  486. }
  487.  
  488. static av_cold int decode_init(AVCodecContext *avctx)
  489. {
  490.     SANMVideoContext *ctx = avctx->priv_data;
  491.  
  492.     ctx->avctx   = avctx;
  493.     ctx->version = !avctx->extradata_size;
  494.  
  495.     avctx->pix_fmt = ctx->version ? AV_PIX_FMT_RGB565 : AV_PIX_FMT_PAL8;
  496.  
  497.     init_sizes(ctx, avctx->width, avctx->height);
  498.     if (init_buffers(ctx)) {
  499.         av_log(avctx, AV_LOG_ERROR, "Error allocating buffers.\n");
  500.         return AVERROR(ENOMEM);
  501.     }
  502.  
  503.     make_glyphs(ctx->p4x4glyphs[0], glyph4_x, glyph4_y, 4);
  504.     make_glyphs(ctx->p8x8glyphs[0], glyph8_x, glyph8_y, 8);
  505.  
  506.     if (!ctx->version) {
  507.         int i;
  508.  
  509.         if (avctx->extradata_size < 1026) {
  510.             av_log(avctx, AV_LOG_ERROR, "Not enough extradata.\n");
  511.             return AVERROR_INVALIDDATA;
  512.         }
  513.  
  514.         ctx->subversion = AV_RL16(avctx->extradata);
  515.         for (i = 0; i < PALETTE_SIZE; i++)
  516.             ctx->pal[i] = 0xFFU << 24 | AV_RL32(avctx->extradata + 2 + i * 4);
  517.     }
  518.  
  519.     return 0;
  520. }
  521.  
  522. static av_cold int decode_end(AVCodecContext *avctx)
  523. {
  524.     SANMVideoContext *ctx = avctx->priv_data;
  525.  
  526.     destroy_buffers(ctx);
  527.  
  528.     return 0;
  529. }
  530.  
  531. static int rle_decode(SANMVideoContext *ctx, uint8_t *dst, const int out_size)
  532. {
  533.     int opcode, color, run_len, left = out_size;
  534.  
  535.     while (left > 0) {
  536.         opcode = bytestream2_get_byte(&ctx->gb);
  537.         run_len = (opcode >> 1) + 1;
  538.         if (run_len > left || bytestream2_get_bytes_left(&ctx->gb) <= 0)
  539.             return AVERROR_INVALIDDATA;
  540.  
  541.         if (opcode & 1) {
  542.             color = bytestream2_get_byte(&ctx->gb);
  543.             memset(dst, color, run_len);
  544.         } else {
  545.             if (bytestream2_get_bytes_left(&ctx->gb) < run_len)
  546.                 return AVERROR_INVALIDDATA;
  547.             bytestream2_get_bufferu(&ctx->gb, dst, run_len);
  548.         }
  549.  
  550.         dst  += run_len;
  551.         left -= run_len;
  552.     }
  553.  
  554.     return 0;
  555. }
  556.  
  557. static int old_codec1(SANMVideoContext *ctx, int top,
  558.                       int left, int width, int height)
  559. {
  560.     uint8_t *dst = ((uint8_t *)ctx->frm0) + left + top * ctx->pitch;
  561.     int i, j, len, flag, code, val, pos, end;
  562.  
  563.     for (i = 0; i < height; i++) {
  564.         pos = 0;
  565.  
  566.         if (bytestream2_get_bytes_left(&ctx->gb) < 2)
  567.             return AVERROR_INVALIDDATA;
  568.  
  569.         len = bytestream2_get_le16u(&ctx->gb);
  570.         end = bytestream2_tell(&ctx->gb) + len;
  571.  
  572.         while (bytestream2_tell(&ctx->gb) < end) {
  573.             if (bytestream2_get_bytes_left(&ctx->gb) < 2)
  574.                 return AVERROR_INVALIDDATA;
  575.  
  576.             code = bytestream2_get_byteu(&ctx->gb);
  577.             flag = code & 1;
  578.             code = (code >> 1) + 1;
  579.             if (pos + code > width)
  580.                 return AVERROR_INVALIDDATA;
  581.             if (flag) {
  582.                 val = bytestream2_get_byteu(&ctx->gb);
  583.                 if (val)
  584.                     memset(dst + pos, val, code);
  585.                 pos += code;
  586.             } else {
  587.                 if (bytestream2_get_bytes_left(&ctx->gb) < code)
  588.                     return AVERROR_INVALIDDATA;
  589.                 for (j = 0; j < code; j++) {
  590.                     val = bytestream2_get_byteu(&ctx->gb);
  591.                     if (val)
  592.                         dst[pos] = val;
  593.                     pos++;
  594.                 }
  595.             }
  596.         }
  597.         dst += ctx->pitch;
  598.     }
  599.     ctx->rotate_code = 0;
  600.  
  601.     return 0;
  602. }
  603.  
  604. static inline void codec37_mv(uint8_t *dst, const uint8_t *src,
  605.                               int height, int stride, int x, int y)
  606. {
  607.     int pos, i, j;
  608.  
  609.     pos = x + y * stride;
  610.     for (j = 0; j < 4; j++) {
  611.         for (i = 0; i < 4; i++) {
  612.             if ((pos + i) < 0 || (pos + i) >= height * stride)
  613.                 dst[i] = 0;
  614.             else
  615.                 dst[i] = src[i];
  616.         }
  617.         dst += stride;
  618.         src += stride;
  619.         pos += stride;
  620.     }
  621. }
  622.  
  623. static int old_codec37(SANMVideoContext *ctx, int top,
  624.                        int left, int width, int height)
  625. {
  626.     int stride = ctx->pitch;
  627.     int i, j, k, t;
  628.     uint8_t *dst, *prev;
  629.     int skip_run = 0;
  630.     int compr = bytestream2_get_byte(&ctx->gb);
  631.     int mvoff = bytestream2_get_byte(&ctx->gb);
  632.     int seq   = bytestream2_get_le16(&ctx->gb);
  633.     uint32_t decoded_size = bytestream2_get_le32(&ctx->gb);
  634.     int flags;
  635.  
  636.     bytestream2_skip(&ctx->gb, 4);
  637.     flags = bytestream2_get_byte(&ctx->gb);
  638.     bytestream2_skip(&ctx->gb, 3);
  639.  
  640.     if (decoded_size > ctx->height * stride - left - top * stride) {
  641.         decoded_size = ctx->height * stride - left - top * stride;
  642.         av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
  643.     }
  644.  
  645.     ctx->rotate_code = 0;
  646.  
  647.     if (((seq & 1) || !(flags & 1)) && (compr && compr != 2))
  648.         rotate_bufs(ctx, 1);
  649.  
  650.     dst  = ((uint8_t*)ctx->frm0) + left + top * stride;
  651.     prev = ((uint8_t*)ctx->frm2) + left + top * stride;
  652.  
  653.     if (mvoff > 2) {
  654.         av_log(ctx->avctx, AV_LOG_ERROR, "Invalid motion base value %d.\n", mvoff);
  655.         return AVERROR_INVALIDDATA;
  656.     }
  657.  
  658.     switch (compr) {
  659.     case 0:
  660.         for (i = 0; i < height; i++) {
  661.             bytestream2_get_buffer(&ctx->gb, dst, width);
  662.             dst += stride;
  663.         }
  664.         memset(ctx->frm1, 0, ctx->height * stride);
  665.         memset(ctx->frm2, 0, ctx->height * stride);
  666.         break;
  667.     case 2:
  668.         if (rle_decode(ctx, dst, decoded_size))
  669.             return AVERROR_INVALIDDATA;
  670.         memset(ctx->frm1, 0, ctx->frm1_size);
  671.         memset(ctx->frm2, 0, ctx->frm2_size);
  672.         break;
  673.     case 3:
  674.     case 4:
  675.         if (flags & 4) {
  676.             for (j = 0; j < height; j += 4) {
  677.                 for (i = 0; i < width; i += 4) {
  678.                     int code;
  679.                     if (skip_run) {
  680.                         skip_run--;
  681.                         copy_block4(dst + i, prev + i, stride, stride, 4);
  682.                         continue;
  683.                     }
  684.                     if (bytestream2_get_bytes_left(&ctx->gb) < 1)
  685.                         return AVERROR_INVALIDDATA;
  686.                     code = bytestream2_get_byteu(&ctx->gb);
  687.                     switch (code) {
  688.                     case 0xFF:
  689.                         if (bytestream2_get_bytes_left(&ctx->gb) < 16)
  690.                             return AVERROR_INVALIDDATA;
  691.                         for (k = 0; k < 4; k++)
  692.                             bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4);
  693.                         break;
  694.                     case 0xFE:
  695.                         if (bytestream2_get_bytes_left(&ctx->gb) < 4)
  696.                             return AVERROR_INVALIDDATA;
  697.                         for (k = 0; k < 4; k++)
  698.                             memset(dst + i + k * stride, bytestream2_get_byteu(&ctx->gb), 4);
  699.                         break;
  700.                     case 0xFD:
  701.                         if (bytestream2_get_bytes_left(&ctx->gb) < 1)
  702.                             return AVERROR_INVALIDDATA;
  703.                         t = bytestream2_get_byteu(&ctx->gb);
  704.                         for (k = 0; k < 4; k++)
  705.                             memset(dst + i + k * stride, t, 4);
  706.                         break;
  707.                     default:
  708.                         if (compr == 4 && !code) {
  709.                             if (bytestream2_get_bytes_left(&ctx->gb) < 1)
  710.                                 return AVERROR_INVALIDDATA;
  711.                             skip_run = bytestream2_get_byteu(&ctx->gb) + 1;
  712.                             i -= 4;
  713.                         } else {
  714.                             int mx, my;
  715.  
  716.                             mx = c37_mv[(mvoff * 255 + code) * 2];
  717.                             my = c37_mv[(mvoff * 255 + code) * 2 + 1];
  718.                             codec37_mv(dst + i, prev + i + mx + my * stride,
  719.                                        ctx->height, stride, i + mx, j + my);
  720.                         }
  721.                     }
  722.                 }
  723.                 dst  += stride * 4;
  724.                 prev += stride * 4;
  725.             }
  726.         } else {
  727.             for (j = 0; j < height; j += 4) {
  728.                 for (i = 0; i < width; i += 4) {
  729.                     int code;
  730.                     if (skip_run) {
  731.                         skip_run--;
  732.                         copy_block4(dst + i, prev + i, stride, stride, 4);
  733.                         continue;
  734.                     }
  735.                     code = bytestream2_get_byte(&ctx->gb);
  736.                     if (code == 0xFF) {
  737.                         if (bytestream2_get_bytes_left(&ctx->gb) < 16)
  738.                             return AVERROR_INVALIDDATA;
  739.                         for (k = 0; k < 4; k++)
  740.                             bytestream2_get_bufferu(&ctx->gb, dst + i + k * stride, 4);
  741.                     } else if (compr == 4 && !code) {
  742.                         if (bytestream2_get_bytes_left(&ctx->gb) < 1)
  743.                             return AVERROR_INVALIDDATA;
  744.                         skip_run = bytestream2_get_byteu(&ctx->gb) + 1;
  745.                         i -= 4;
  746.                     } else {
  747.                         int mx, my;
  748.  
  749.                         mx = c37_mv[(mvoff * 255 + code) * 2];
  750.                         my = c37_mv[(mvoff * 255 + code) * 2 + 1];
  751.                         codec37_mv(dst + i, prev + i + mx + my * stride,
  752.                                    ctx->height, stride, i + mx, j + my);
  753.                     }
  754.                 }
  755.                 dst  += stride * 4;
  756.                 prev += stride * 4;
  757.             }
  758.         }
  759.         break;
  760.     default:
  761.         avpriv_report_missing_feature(ctx->avctx,
  762.                                       "Subcodec 37 compression %d", compr);
  763.         return AVERROR_PATCHWELCOME;
  764.     }
  765.  
  766.     return 0;
  767. }
  768.  
  769. static int process_block(SANMVideoContext *ctx, uint8_t *dst, uint8_t *prev1,
  770.                          uint8_t *prev2, int stride, int tbl, int size)
  771. {
  772.     int code, k, t;
  773.     uint8_t colors[2];
  774.     int8_t *pglyph;
  775.  
  776.     if (bytestream2_get_bytes_left(&ctx->gb) < 1)
  777.         return AVERROR_INVALIDDATA;
  778.  
  779.     code = bytestream2_get_byteu(&ctx->gb);
  780.     if (code >= 0xF8) {
  781.         switch (code) {
  782.         case 0xFF:
  783.             if (size == 2) {
  784.                 if (bytestream2_get_bytes_left(&ctx->gb) < 4)
  785.                     return AVERROR_INVALIDDATA;
  786.                 dst[0]          = bytestream2_get_byteu(&ctx->gb);
  787.                 dst[1]          = bytestream2_get_byteu(&ctx->gb);
  788.                 dst[0 + stride] = bytestream2_get_byteu(&ctx->gb);
  789.                 dst[1 + stride] = bytestream2_get_byteu(&ctx->gb);
  790.             } else {
  791.                 size >>= 1;
  792.                 if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
  793.                     return AVERROR_INVALIDDATA;
  794.                 if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
  795.                                   stride, tbl, size))
  796.                     return AVERROR_INVALIDDATA;
  797.                 dst   += size * stride;
  798.                 prev1 += size * stride;
  799.                 prev2 += size * stride;
  800.                 if (process_block(ctx, dst, prev1, prev2, stride, tbl, size))
  801.                     return AVERROR_INVALIDDATA;
  802.                 if (process_block(ctx, dst + size, prev1 + size, prev2 + size,
  803.                                   stride, tbl, size))
  804.                     return AVERROR_INVALIDDATA;
  805.             }
  806.             break;
  807.         case 0xFE:
  808.             if (bytestream2_get_bytes_left(&ctx->gb) < 1)
  809.                 return AVERROR_INVALIDDATA;
  810.  
  811.             t = bytestream2_get_byteu(&ctx->gb);
  812.             for (k = 0; k < size; k++)
  813.                 memset(dst + k * stride, t, size);
  814.             break;
  815.         case 0xFD:
  816.             if (bytestream2_get_bytes_left(&ctx->gb) < 3)
  817.                 return AVERROR_INVALIDDATA;
  818.  
  819.             code = bytestream2_get_byteu(&ctx->gb);
  820.             pglyph = (size == 8) ? ctx->p8x8glyphs[code] : ctx->p4x4glyphs[code];
  821.             bytestream2_get_bufferu(&ctx->gb, colors, 2);
  822.  
  823.             for (k = 0; k < size; k++)
  824.                 for (t = 0; t < size; t++)
  825.                     dst[t + k * stride] = colors[!*pglyph++];
  826.             break;
  827.         case 0xFC:
  828.             for (k = 0; k < size; k++)
  829.                 memcpy(dst + k * stride, prev1 + k * stride, size);
  830.             break;
  831.         default:
  832.             k = bytestream2_tell(&ctx->gb);
  833.             bytestream2_seek(&ctx->gb, tbl + (code & 7), SEEK_SET);
  834.             t = bytestream2_get_byte(&ctx->gb);
  835.             bytestream2_seek(&ctx->gb, k, SEEK_SET);
  836.             for (k = 0; k < size; k++)
  837.                 memset(dst + k * stride, t, size);
  838.         }
  839.     } else {
  840.         int mx = motion_vectors[code][0];
  841.         int my = motion_vectors[code][1];
  842.         int index = prev2 - (const uint8_t *)ctx->frm2;
  843.  
  844.         av_assert2(index >= 0 && index < (ctx->buf_size >> 1));
  845.  
  846.         if (index < -mx - my * stride ||
  847.             (ctx->buf_size >> 1) - index < mx + size + (my + size - 1) * stride) {
  848.             av_log(ctx->avctx, AV_LOG_ERROR, "MV is invalid.\n");
  849.             return AVERROR_INVALIDDATA;
  850.         }
  851.  
  852.         for (k = 0; k < size; k++)
  853.             memcpy(dst + k * stride, prev2 + mx + (my + k) * stride, size);
  854.     }
  855.  
  856.     return 0;
  857. }
  858.  
  859. static int old_codec47(SANMVideoContext *ctx, int top,
  860.                        int left, int width, int height)
  861. {
  862.     uint32_t decoded_size;
  863.     int i, j;
  864.     int stride     = ctx->pitch;
  865.     uint8_t *dst   = (uint8_t *)ctx->frm0 + left + top * stride;
  866.     uint8_t *prev1 = (uint8_t *)ctx->frm1;
  867.     uint8_t *prev2 = (uint8_t *)ctx->frm2;
  868.     int tbl_pos = bytestream2_tell(&ctx->gb);
  869.     int seq     = bytestream2_get_le16(&ctx->gb);
  870.     int compr   = bytestream2_get_byte(&ctx->gb);
  871.     int new_rot = bytestream2_get_byte(&ctx->gb);
  872.     int skip    = bytestream2_get_byte(&ctx->gb);
  873.  
  874.     bytestream2_skip(&ctx->gb, 9);
  875.     decoded_size = bytestream2_get_le32(&ctx->gb);
  876.     bytestream2_skip(&ctx->gb, 8);
  877.  
  878.     if (decoded_size > ctx->height * stride - left - top * stride) {
  879.         decoded_size = ctx->height * stride - left - top * stride;
  880.         av_log(ctx->avctx, AV_LOG_WARNING, "Decoded size is too large.\n");
  881.     }
  882.  
  883.     if (skip & 1)
  884.         bytestream2_skip(&ctx->gb, 0x8080);
  885.     if (!seq) {
  886.         ctx->prev_seq = -1;
  887.         memset(prev1, 0, ctx->height * stride);
  888.         memset(prev2, 0, ctx->height * stride);
  889.     }
  890.  
  891.     switch (compr) {
  892.     case 0:
  893.         if (bytestream2_get_bytes_left(&ctx->gb) < width * height)
  894.             return AVERROR_INVALIDDATA;
  895.         for (j = 0; j < height; j++) {
  896.             bytestream2_get_bufferu(&ctx->gb, dst, width);
  897.             dst += stride;
  898.         }
  899.         break;
  900.     case 1:
  901.         if (bytestream2_get_bytes_left(&ctx->gb) < ((width + 1) >> 1) * ((height + 1) >> 1))
  902.             return AVERROR_INVALIDDATA;
  903.         for (j = 0; j < height; j += 2) {
  904.             for (i = 0; i < width; i += 2) {
  905.                 dst[i] =
  906.                 dst[i + 1] =
  907.                 dst[stride + i] =
  908.                 dst[stride + i + 1] = bytestream2_get_byteu(&ctx->gb);
  909.             }
  910.             dst += stride * 2;
  911.         }
  912.         break;
  913.     case 2:
  914.         if (seq == ctx->prev_seq + 1) {
  915.             for (j = 0; j < height; j += 8) {
  916.                 for (i = 0; i < width; i += 8)
  917.                     if (process_block(ctx, dst + i, prev1 + i, prev2 + i, stride,
  918.                                       tbl_pos + 8, 8))
  919.                         return AVERROR_INVALIDDATA;
  920.                 dst   += stride * 8;
  921.                 prev1 += stride * 8;
  922.                 prev2 += stride * 8;
  923.             }
  924.         }
  925.         break;
  926.     case 3:
  927.         memcpy(ctx->frm0, ctx->frm2, ctx->pitch * ctx->height);
  928.         break;
  929.     case 4:
  930.         memcpy(ctx->frm0, ctx->frm1, ctx->pitch * ctx->height);
  931.         break;
  932.     case 5:
  933.         if (rle_decode(ctx, dst, decoded_size))
  934.             return AVERROR_INVALIDDATA;
  935.         break;
  936.     default:
  937.         avpriv_report_missing_feature(ctx->avctx,
  938.                                       "Subcodec 47 compression %d", compr);
  939.         return AVERROR_PATCHWELCOME;
  940.     }
  941.     if (seq == ctx->prev_seq + 1)
  942.         ctx->rotate_code = new_rot;
  943.     else
  944.         ctx->rotate_code = 0;
  945.     ctx->prev_seq = seq;
  946.  
  947.     return 0;
  948. }
  949.  
  950. static int process_frame_obj(SANMVideoContext *ctx)
  951. {
  952.     uint16_t codec = bytestream2_get_le16u(&ctx->gb);
  953.     uint16_t left  = bytestream2_get_le16u(&ctx->gb);
  954.     uint16_t top   = bytestream2_get_le16u(&ctx->gb);
  955.     uint16_t w     = bytestream2_get_le16u(&ctx->gb);
  956.     uint16_t h     = bytestream2_get_le16u(&ctx->gb);
  957.  
  958.     if (!w || !h) {
  959.         av_log(ctx->avctx, AV_LOG_ERROR, "Dimensions are invalid.\n");
  960.         return AVERROR_INVALIDDATA;
  961.     }
  962.  
  963.     if (ctx->width < left + w || ctx->height < top + h) {
  964.         int ret = ff_set_dimensions(ctx->avctx, FFMAX(left + w, ctx->width),
  965.                                     FFMAX(top + h, ctx->height));
  966.         if (ret < 0)
  967.             return ret;
  968.         init_sizes(ctx, FFMAX(left + w, ctx->width),
  969.                    FFMAX(top + h, ctx->height));
  970.         if (init_buffers(ctx)) {
  971.             av_log(ctx->avctx, AV_LOG_ERROR, "Error resizing buffers.\n");
  972.             return AVERROR(ENOMEM);
  973.         }
  974.     }
  975.     bytestream2_skip(&ctx->gb, 4);
  976.  
  977.     switch (codec) {
  978.     case 1:
  979.     case 3:
  980.         return old_codec1(ctx, top, left, w, h);
  981.         break;
  982.     case 37:
  983.         return old_codec37(ctx, top, left, w, h);
  984.         break;
  985.     case 47:
  986.         return old_codec47(ctx, top, left, w, h);
  987.         break;
  988.     default:
  989.         avpriv_request_sample(ctx->avctx, "Subcodec %d", codec);
  990.         return AVERROR_PATCHWELCOME;
  991.     }
  992. }
  993.  
  994. static int decode_0(SANMVideoContext *ctx)
  995. {
  996.     uint16_t *frm = ctx->frm0;
  997.     int x, y;
  998.  
  999.     if (bytestream2_get_bytes_left(&ctx->gb) < ctx->width * ctx->height * 2) {
  1000.         av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for raw frame.\n");
  1001.         return AVERROR_INVALIDDATA;
  1002.     }
  1003.     for (y = 0; y < ctx->height; y++) {
  1004.         for (x = 0; x < ctx->width; x++)
  1005.             frm[x] = bytestream2_get_le16u(&ctx->gb);
  1006.         frm += ctx->pitch;
  1007.     }
  1008.     return 0;
  1009. }
  1010.  
  1011. static int decode_nop(SANMVideoContext *ctx)
  1012. {
  1013.     avpriv_request_sample(ctx->avctx, "Unknown/unsupported compression type");
  1014.     return AVERROR_PATCHWELCOME;
  1015. }
  1016.  
  1017. static void copy_block(uint16_t *pdest, uint16_t *psrc, int block_size, int pitch)
  1018. {
  1019.     uint8_t *dst = (uint8_t *)pdest;
  1020.     uint8_t *src = (uint8_t *)psrc;
  1021.     int stride = pitch * 2;
  1022.  
  1023.     switch (block_size) {
  1024.     case 2:
  1025.         copy_block4(dst, src, stride, stride, 2);
  1026.         break;
  1027.     case 4:
  1028.         copy_block8(dst, src, stride, stride, 4);
  1029.         break;
  1030.     case 8:
  1031.         copy_block16(dst, src, stride, stride, 8);
  1032.         break;
  1033.     }
  1034. }
  1035.  
  1036. static void fill_block(uint16_t *pdest, uint16_t color, int block_size, int pitch)
  1037. {
  1038.     int x, y;
  1039.  
  1040.     pitch -= block_size;
  1041.     for (y = 0; y < block_size; y++, pdest += pitch)
  1042.         for (x = 0; x < block_size; x++)
  1043.             *pdest++ = color;
  1044. }
  1045.  
  1046. static int draw_glyph(SANMVideoContext *ctx, uint16_t *dst, int index,
  1047.                       uint16_t fg_color, uint16_t bg_color, int block_size,
  1048.                       int pitch)
  1049. {
  1050.     int8_t *pglyph;
  1051.     uint16_t colors[2] = { fg_color, bg_color };
  1052.     int x, y;
  1053.  
  1054.     if (index >= NGLYPHS) {
  1055.         av_log(ctx->avctx, AV_LOG_ERROR, "Ignoring nonexistent glyph #%u.\n", index);
  1056.         return AVERROR_INVALIDDATA;
  1057.     }
  1058.  
  1059.     pglyph = block_size == 8 ? ctx->p8x8glyphs[index] : ctx->p4x4glyphs[index];
  1060.     pitch -= block_size;
  1061.  
  1062.     for (y = 0; y < block_size; y++, dst += pitch)
  1063.         for (x = 0; x < block_size; x++)
  1064.             *dst++ = colors[*pglyph++];
  1065.     return 0;
  1066. }
  1067.  
  1068. static int opcode_0xf7(SANMVideoContext *ctx, int cx, int cy, int block_size, int pitch)
  1069. {
  1070.     uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
  1071.  
  1072.     if (block_size == 2) {
  1073.         uint32_t indices;
  1074.  
  1075.         if (bytestream2_get_bytes_left(&ctx->gb) < 4)
  1076.             return AVERROR_INVALIDDATA;
  1077.  
  1078.         indices        = bytestream2_get_le32u(&ctx->gb);
  1079.         dst[0]         = ctx->codebook[indices & 0xFF];
  1080.         indices      >>= 8;
  1081.         dst[1]         = ctx->codebook[indices & 0xFF];
  1082.         indices      >>= 8;
  1083.         dst[pitch]     = ctx->codebook[indices & 0xFF];
  1084.         indices      >>= 8;
  1085.         dst[pitch + 1] = ctx->codebook[indices & 0xFF];
  1086.     } else {
  1087.         uint16_t fgcolor, bgcolor;
  1088.         int glyph;
  1089.  
  1090.         if (bytestream2_get_bytes_left(&ctx->gb) < 3)
  1091.             return AVERROR_INVALIDDATA;
  1092.  
  1093.         glyph   = bytestream2_get_byteu(&ctx->gb);
  1094.         bgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
  1095.         fgcolor = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
  1096.  
  1097.         draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
  1098.     }
  1099.     return 0;
  1100. }
  1101.  
  1102. static int opcode_0xf8(SANMVideoContext *ctx, int cx, int cy, int block_size, int pitch)
  1103. {
  1104.     uint16_t *dst = ctx->frm0 + cx + cy * ctx->pitch;
  1105.  
  1106.     if (block_size == 2) {
  1107.         if (bytestream2_get_bytes_left(&ctx->gb) < 8)
  1108.             return AVERROR_INVALIDDATA;
  1109.  
  1110.         dst[0]         = bytestream2_get_le16u(&ctx->gb);
  1111.         dst[1]         = bytestream2_get_le16u(&ctx->gb);
  1112.         dst[pitch]     = bytestream2_get_le16u(&ctx->gb);
  1113.         dst[pitch + 1] = bytestream2_get_le16u(&ctx->gb);
  1114.     } else {
  1115.         uint16_t fgcolor, bgcolor;
  1116.         int glyph;
  1117.  
  1118.         if (bytestream2_get_bytes_left(&ctx->gb) < 5)
  1119.             return AVERROR_INVALIDDATA;
  1120.  
  1121.         glyph   = bytestream2_get_byteu(&ctx->gb);
  1122.         bgcolor = bytestream2_get_le16u(&ctx->gb);
  1123.         fgcolor = bytestream2_get_le16u(&ctx->gb);
  1124.  
  1125.         draw_glyph(ctx, dst, glyph, fgcolor, bgcolor, block_size, pitch);
  1126.     }
  1127.     return 0;
  1128. }
  1129.  
  1130. static int good_mvec(SANMVideoContext *ctx, int cx, int cy, int mx, int my,
  1131.                      int block_size)
  1132. {
  1133.     int start_pos = cx + mx + (cy + my) * ctx->pitch;
  1134.     int end_pos = start_pos + (block_size - 1) * (ctx->pitch + 1);
  1135.  
  1136.     int good = start_pos >= 0 && end_pos < (ctx->buf_size >> 1);
  1137.  
  1138.     if (!good)
  1139.         av_log(ctx->avctx, AV_LOG_ERROR,
  1140.                "Ignoring invalid motion vector (%i, %i)->(%u, %u), block size = %u\n",
  1141.                cx + mx, cy + my, cx, cy, block_size);
  1142.  
  1143.     return good;
  1144. }
  1145.  
  1146. static int codec2subblock(SANMVideoContext *ctx, int cx, int cy, int blk_size)
  1147. {
  1148.     int16_t mx, my, index;
  1149.     int opcode;
  1150.  
  1151.     if (bytestream2_get_bytes_left(&ctx->gb) < 1)
  1152.         return AVERROR_INVALIDDATA;
  1153.  
  1154.     opcode = bytestream2_get_byteu(&ctx->gb);
  1155.  
  1156.     switch (opcode) {
  1157.     default:
  1158.         mx = motion_vectors[opcode][0];
  1159.         my = motion_vectors[opcode][1];
  1160.  
  1161.         if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
  1162.             copy_block(ctx->frm0 + cx      + ctx->pitch *  cy,
  1163.                        ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
  1164.                        blk_size, ctx->pitch);
  1165.         }
  1166.         break;
  1167.     case 0xF5:
  1168.         if (bytestream2_get_bytes_left(&ctx->gb) < 2)
  1169.             return AVERROR_INVALIDDATA;
  1170.         index = bytestream2_get_le16u(&ctx->gb);
  1171.  
  1172.         mx = index % ctx->width;
  1173.         my = index / ctx->width;
  1174.  
  1175.         if (good_mvec(ctx, cx, cy, mx, my, blk_size)) {
  1176.             copy_block(ctx->frm0 + cx      + ctx->pitch *  cy,
  1177.                        ctx->frm2 + cx + mx + ctx->pitch * (cy + my),
  1178.                        blk_size, ctx->pitch);
  1179.         }
  1180.         break;
  1181.     case 0xF6:
  1182.         copy_block(ctx->frm0 + cx + ctx->pitch * cy,
  1183.                    ctx->frm1 + cx + ctx->pitch * cy,
  1184.                    blk_size, ctx->pitch);
  1185.         break;
  1186.     case 0xF7:
  1187.         opcode_0xf7(ctx, cx, cy, blk_size, ctx->pitch);
  1188.         break;
  1189.  
  1190.     case 0xF8:
  1191.         opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
  1192.         break;
  1193.     case 0xF9:
  1194.     case 0xFA:
  1195.     case 0xFB:
  1196.     case 0xFC:
  1197.         fill_block(ctx->frm0 + cx + cy * ctx->pitch,
  1198.                    ctx->small_codebook[opcode - 0xf9], blk_size, ctx->pitch);
  1199.         break;
  1200.     case 0xFD:
  1201.         if (bytestream2_get_bytes_left(&ctx->gb) < 1)
  1202.             return AVERROR_INVALIDDATA;
  1203.         fill_block(ctx->frm0 + cx + cy * ctx->pitch,
  1204.                    ctx->codebook[bytestream2_get_byteu(&ctx->gb)], blk_size, ctx->pitch);
  1205.         break;
  1206.     case 0xFE:
  1207.         if (bytestream2_get_bytes_left(&ctx->gb) < 2)
  1208.             return AVERROR_INVALIDDATA;
  1209.         fill_block(ctx->frm0 + cx + cy * ctx->pitch,
  1210.                    bytestream2_get_le16u(&ctx->gb), blk_size, ctx->pitch);
  1211.         break;
  1212.     case 0xFF:
  1213.         if (blk_size == 2) {
  1214.             opcode_0xf8(ctx, cx, cy, blk_size, ctx->pitch);
  1215.         } else {
  1216.             blk_size >>= 1;
  1217.             if (codec2subblock(ctx, cx, cy, blk_size))
  1218.                 return AVERROR_INVALIDDATA;
  1219.             if (codec2subblock(ctx, cx + blk_size, cy, blk_size))
  1220.                 return AVERROR_INVALIDDATA;
  1221.             if (codec2subblock(ctx, cx, cy + blk_size, blk_size))
  1222.                 return AVERROR_INVALIDDATA;
  1223.             if (codec2subblock(ctx, cx + blk_size, cy + blk_size, blk_size))
  1224.                 return AVERROR_INVALIDDATA;
  1225.         }
  1226.         break;
  1227.     }
  1228.     return 0;
  1229. }
  1230.  
  1231. static int decode_2(SANMVideoContext *ctx)
  1232. {
  1233.     int cx, cy, ret;
  1234.  
  1235.     for (cy = 0; cy < ctx->aligned_height; cy += 8)
  1236.         for (cx = 0; cx < ctx->aligned_width; cx += 8)
  1237.             if (ret = codec2subblock(ctx, cx, cy, 8))
  1238.                 return ret;
  1239.  
  1240.     return 0;
  1241. }
  1242.  
  1243. static int decode_3(SANMVideoContext *ctx)
  1244. {
  1245.     memcpy(ctx->frm0, ctx->frm2, ctx->frm2_size);
  1246.     return 0;
  1247. }
  1248.  
  1249. static int decode_4(SANMVideoContext *ctx)
  1250. {
  1251.     memcpy(ctx->frm0, ctx->frm1, ctx->frm1_size);
  1252.     return 0;
  1253. }
  1254.  
  1255. static int decode_5(SANMVideoContext *ctx)
  1256. {
  1257. #if HAVE_BIGENDIAN
  1258.     uint16_t *frm;
  1259.     int npixels;
  1260. #endif
  1261.     uint8_t *dst = (uint8_t*)ctx->frm0;
  1262.  
  1263.     if (rle_decode(ctx, dst, ctx->buf_size))
  1264.         return AVERROR_INVALIDDATA;
  1265.  
  1266. #if HAVE_BIGENDIAN
  1267.     npixels = ctx->npixels;
  1268.     frm = ctx->frm0;
  1269.     while (npixels--) {
  1270.         *frm = av_bswap16(*frm);
  1271.         frm++;
  1272.     }
  1273. #endif
  1274.  
  1275.     return 0;
  1276. }
  1277.  
  1278. static int decode_6(SANMVideoContext *ctx)
  1279. {
  1280.     int npixels = ctx->npixels;
  1281.     uint16_t *frm = ctx->frm0;
  1282.  
  1283.     if (bytestream2_get_bytes_left(&ctx->gb) < npixels) {
  1284.         av_log(ctx->avctx, AV_LOG_ERROR, "Insufficient data for frame.\n");
  1285.         return AVERROR_INVALIDDATA;
  1286.     }
  1287.     while (npixels--)
  1288.         *frm++ = ctx->codebook[bytestream2_get_byteu(&ctx->gb)];
  1289.  
  1290.     return 0;
  1291. }
  1292.  
  1293. static int decode_8(SANMVideoContext *ctx)
  1294. {
  1295.     uint16_t *pdest = ctx->frm0;
  1296.     uint8_t *rsrc;
  1297.     long npixels = ctx->npixels;
  1298.  
  1299.     av_fast_malloc(&ctx->rle_buf, &ctx->rle_buf_size, npixels);
  1300.     if (!ctx->rle_buf) {
  1301.         av_log(ctx->avctx, AV_LOG_ERROR, "RLE buffer allocation failed.\n");
  1302.         return AVERROR(ENOMEM);
  1303.     }
  1304.     rsrc = ctx->rle_buf;
  1305.  
  1306.     if (rle_decode(ctx, rsrc, npixels))
  1307.         return AVERROR_INVALIDDATA;
  1308.  
  1309.     while (npixels--)
  1310.         *pdest++ = ctx->codebook[*rsrc++];
  1311.  
  1312.     return 0;
  1313. }
  1314.  
  1315. typedef int (*frm_decoder)(SANMVideoContext *ctx);
  1316.  
  1317. static const frm_decoder v1_decoders[] = {
  1318.     decode_0, decode_nop, decode_2, decode_3, decode_4, decode_5,
  1319.     decode_6, decode_nop, decode_8
  1320. };
  1321.  
  1322. static int read_frame_header(SANMVideoContext *ctx, SANMFrameHeader *hdr)
  1323. {
  1324.     int i, ret;
  1325.  
  1326.     if ((ret = bytestream2_get_bytes_left(&ctx->gb)) < 560) {
  1327.         av_log(ctx->avctx, AV_LOG_ERROR, "Input frame too short (%d bytes).\n",
  1328.                ret);
  1329.         return AVERROR_INVALIDDATA;
  1330.     }
  1331.     bytestream2_skip(&ctx->gb, 8); // skip pad
  1332.  
  1333.     hdr->width  = bytestream2_get_le32u(&ctx->gb);
  1334.     hdr->height = bytestream2_get_le32u(&ctx->gb);
  1335.  
  1336.     if (hdr->width != ctx->width || hdr->height != ctx->height) {
  1337.         avpriv_report_missing_feature(ctx->avctx, "Variable size frames");
  1338.         return AVERROR_PATCHWELCOME;
  1339.     }
  1340.  
  1341.     hdr->seq_num     = bytestream2_get_le16u(&ctx->gb);
  1342.     hdr->codec       = bytestream2_get_byteu(&ctx->gb);
  1343.     hdr->rotate_code = bytestream2_get_byteu(&ctx->gb);
  1344.  
  1345.     bytestream2_skip(&ctx->gb, 4); // skip pad
  1346.  
  1347.     for (i = 0; i < 4; i++)
  1348.         ctx->small_codebook[i] = bytestream2_get_le16u(&ctx->gb);
  1349.     hdr->bg_color = bytestream2_get_le16u(&ctx->gb);
  1350.  
  1351.     bytestream2_skip(&ctx->gb, 2); // skip pad
  1352.  
  1353.     hdr->rle_output_size = bytestream2_get_le32u(&ctx->gb);
  1354.     for (i = 0; i < 256; i++)
  1355.         ctx->codebook[i] = bytestream2_get_le16u(&ctx->gb);
  1356.  
  1357.     bytestream2_skip(&ctx->gb, 8); // skip pad
  1358.  
  1359.     return 0;
  1360. }
  1361.  
  1362. static void fill_frame(uint16_t *pbuf, int buf_size, uint16_t color)
  1363. {
  1364.     while (buf_size--)
  1365.         *pbuf++ = color;
  1366. }
  1367.  
  1368. static int copy_output(SANMVideoContext *ctx, SANMFrameHeader *hdr)
  1369. {
  1370.     uint8_t *dst;
  1371.     const uint8_t *src = (uint8_t*) ctx->frm0;
  1372.     int ret, dstpitch, height = ctx->height;
  1373.     int srcpitch = ctx->pitch * (hdr ? sizeof(ctx->frm0[0]) : 1);
  1374.  
  1375.     if ((ret = ff_get_buffer(ctx->avctx, ctx->frame, 0)) < 0)
  1376.         return ret;
  1377.  
  1378.     dst      = ctx->frame->data[0];
  1379.     dstpitch = ctx->frame->linesize[0];
  1380.  
  1381.     while (height--) {
  1382.         memcpy(dst, src, srcpitch);
  1383.         src += srcpitch;
  1384.         dst += dstpitch;
  1385.     }
  1386.  
  1387.     return 0;
  1388. }
  1389.  
  1390. static int decode_frame(AVCodecContext *avctx, void *data,
  1391.                         int *got_frame_ptr, AVPacket *pkt)
  1392. {
  1393.     SANMVideoContext *ctx = avctx->priv_data;
  1394.     int i, ret;
  1395.  
  1396.     ctx->frame = data;
  1397.     bytestream2_init(&ctx->gb, pkt->data, pkt->size);
  1398.  
  1399.     if (!ctx->version) {
  1400.         int to_store = 0;
  1401.  
  1402.         while (bytestream2_get_bytes_left(&ctx->gb) >= 8) {
  1403.             uint32_t sig, size;
  1404.             int pos;
  1405.  
  1406.             sig  = bytestream2_get_be32u(&ctx->gb);
  1407.             size = bytestream2_get_be32u(&ctx->gb);
  1408.             pos  = bytestream2_tell(&ctx->gb);
  1409.  
  1410.             if (bytestream2_get_bytes_left(&ctx->gb) < size) {
  1411.                 av_log(avctx, AV_LOG_ERROR, "Incorrect chunk size %"PRIu32".\n", size);
  1412.                 break;
  1413.             }
  1414.             switch (sig) {
  1415.             case MKBETAG('N', 'P', 'A', 'L'):
  1416.                 if (size != PALETTE_SIZE * 3) {
  1417.                     av_log(avctx, AV_LOG_ERROR,
  1418.                            "Incorrect palette block size %"PRIu32".\n", size);
  1419.                     return AVERROR_INVALIDDATA;
  1420.                 }
  1421.                 for (i = 0; i < PALETTE_SIZE; i++)
  1422.                     ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
  1423.                 break;
  1424.             case MKBETAG('F', 'O', 'B', 'J'):
  1425.                 if (size < 16)
  1426.                     return AVERROR_INVALIDDATA;
  1427.                 if (ret = process_frame_obj(ctx))
  1428.                     return ret;
  1429.                 break;
  1430.             case MKBETAG('X', 'P', 'A', 'L'):
  1431.                 if (size == 6 || size == 4) {
  1432.                     uint8_t tmp[3];
  1433.                     int j;
  1434.  
  1435.                     for (i = 0; i < PALETTE_SIZE; i++) {
  1436.                         for (j = 0; j < 3; j++) {
  1437.                             int t = (ctx->pal[i] >> (16 - j * 8)) & 0xFF;
  1438.                             tmp[j] = av_clip_uint8((t * 129 + ctx->delta_pal[i * 3 + j]) >> 7);
  1439.                         }
  1440.                         ctx->pal[i] = 0xFFU << 24 | AV_RB24(tmp);
  1441.                     }
  1442.                 } else {
  1443.                     if (size < PALETTE_DELTA * 2 + 4) {
  1444.                         av_log(avctx, AV_LOG_ERROR,
  1445.                                "Incorrect palette change block size %"PRIu32".\n",
  1446.                                size);
  1447.                         return AVERROR_INVALIDDATA;
  1448.                     }
  1449.                     bytestream2_skipu(&ctx->gb, 4);
  1450.                     for (i = 0; i < PALETTE_DELTA; i++)
  1451.                         ctx->delta_pal[i] = bytestream2_get_le16u(&ctx->gb);
  1452.                     if (size >= PALETTE_DELTA * 5 + 4) {
  1453.                         for (i = 0; i < PALETTE_SIZE; i++)
  1454.                             ctx->pal[i] = 0xFFU << 24 | bytestream2_get_be24u(&ctx->gb);
  1455.                     } else {
  1456.                         memset(ctx->pal, 0, sizeof(ctx->pal));
  1457.                     }
  1458.                 }
  1459.                 break;
  1460.             case MKBETAG('S', 'T', 'O', 'R'):
  1461.                 to_store = 1;
  1462.                 break;
  1463.             case MKBETAG('F', 'T', 'C', 'H'):
  1464.                 memcpy(ctx->frm0, ctx->stored_frame, ctx->buf_size);
  1465.                 break;
  1466.             default:
  1467.                 bytestream2_skip(&ctx->gb, size);
  1468.                 av_log(avctx, AV_LOG_DEBUG,
  1469.                        "Unknown/unsupported chunk %"PRIx32".\n", sig);
  1470.                 break;
  1471.             }
  1472.  
  1473.             bytestream2_seek(&ctx->gb, pos + size, SEEK_SET);
  1474.             if (size & 1)
  1475.                 bytestream2_skip(&ctx->gb, 1);
  1476.         }
  1477.         if (to_store)
  1478.             memcpy(ctx->stored_frame, ctx->frm0, ctx->buf_size);
  1479.         if ((ret = copy_output(ctx, NULL)))
  1480.             return ret;
  1481.         memcpy(ctx->frame->data[1], ctx->pal, 1024);
  1482.     } else {
  1483.         SANMFrameHeader header;
  1484.  
  1485.         if ((ret = read_frame_header(ctx, &header)))
  1486.             return ret;
  1487.  
  1488.         ctx->rotate_code = header.rotate_code;
  1489.         if ((ctx->frame->key_frame = !header.seq_num)) {
  1490.             ctx->frame->pict_type = AV_PICTURE_TYPE_I;
  1491.             fill_frame(ctx->frm1, ctx->npixels, header.bg_color);
  1492.             fill_frame(ctx->frm2, ctx->npixels, header.bg_color);
  1493.         } else {
  1494.             ctx->frame->pict_type = AV_PICTURE_TYPE_P;
  1495.         }
  1496.  
  1497.         if (header.codec < FF_ARRAY_ELEMS(v1_decoders)) {
  1498.             if ((ret = v1_decoders[header.codec](ctx))) {
  1499.                 av_log(avctx, AV_LOG_ERROR,
  1500.                        "Subcodec %d: error decoding frame.\n", header.codec);
  1501.                 return ret;
  1502.             }
  1503.         } else {
  1504.             avpriv_request_sample(avctx, "Subcodec %d", header.codec);
  1505.             return AVERROR_PATCHWELCOME;
  1506.         }
  1507.  
  1508.         if ((ret = copy_output(ctx, &header)))
  1509.             return ret;
  1510.     }
  1511.     if (ctx->rotate_code)
  1512.         rotate_bufs(ctx, ctx->rotate_code);
  1513.  
  1514.     *got_frame_ptr = 1;
  1515.  
  1516.     return pkt->size;
  1517. }
  1518.  
  1519. AVCodec ff_sanm_decoder = {
  1520.     .name           = "sanm",
  1521.     .long_name      = NULL_IF_CONFIG_SMALL("LucasArts SANM/Smush video"),
  1522.     .type           = AVMEDIA_TYPE_VIDEO,
  1523.     .id             = AV_CODEC_ID_SANM,
  1524.     .priv_data_size = sizeof(SANMVideoContext),
  1525.     .init           = decode_init,
  1526.     .close          = decode_end,
  1527.     .decode         = decode_frame,
  1528.     .capabilities   = AV_CODEC_CAP_DR1,
  1529. };
  1530.