mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
4243da4ff4
This is possible, because every given FFCodec has to implement exactly one of these. Doing so decreases sizeof(FFCodec) and therefore decreases the size of the binary. Notice that in case of position-independent code the decrease is in .data.rel.ro, so that this translates to decreased memory consumption. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
1326 lines
58 KiB
C
1326 lines
58 KiB
C
/*
|
|
* Chinese AVS video (AVS1-P2, JiZhun profile) decoder.
|
|
* Copyright (c) 2006 Stefan Gehrer <stefan.gehrer@gmx.de>
|
|
*
|
|
* This file is part of FFmpeg.
|
|
*
|
|
* FFmpeg is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* FFmpeg is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with FFmpeg; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* Chinese AVS video (AVS1-P2, JiZhun profile) decoder
|
|
* @author Stefan Gehrer <stefan.gehrer@gmx.de>
|
|
*/
|
|
|
|
#include "libavutil/avassert.h"
|
|
#include "avcodec.h"
|
|
#include "get_bits.h"
|
|
#include "golomb.h"
|
|
#include "cavs.h"
|
|
#include "codec_internal.h"
|
|
#include "internal.h"
|
|
#include "mathops.h"
|
|
#include "mpeg12data.h"
|
|
#include "startcode.h"
|
|
|
|
static const uint8_t mv_scan[4] = {
|
|
MV_FWD_X0, MV_FWD_X1,
|
|
MV_FWD_X2, MV_FWD_X3
|
|
};
|
|
|
|
static const uint8_t cbp_tab[64][2] = {
|
|
{ 63, 0 }, { 15, 15 }, { 31, 63 }, { 47, 31 }, { 0, 16 }, { 14, 32 }, { 13, 47 }, { 11, 13 },
|
|
{ 7, 14 }, { 5, 11 }, { 10, 12 }, { 8, 5 }, { 12, 10 }, { 61, 7 }, { 4, 48 }, { 55, 3 },
|
|
{ 1, 2 }, { 2, 8 }, { 59, 4 }, { 3, 1 }, { 62, 61 }, { 9, 55 }, { 6, 59 }, { 29, 62 },
|
|
{ 45, 29 }, { 51, 27 }, { 23, 23 }, { 39, 19 }, { 27, 30 }, { 46, 28 }, { 53, 9 }, { 30, 6 },
|
|
{ 43, 60 }, { 37, 21 }, { 60, 44 }, { 16, 26 }, { 21, 51 }, { 28, 35 }, { 19, 18 }, { 35, 20 },
|
|
{ 42, 24 }, { 26, 53 }, { 44, 17 }, { 32, 37 }, { 58, 39 }, { 24, 45 }, { 20, 58 }, { 17, 43 },
|
|
{ 18, 42 }, { 48, 46 }, { 22, 36 }, { 33, 33 }, { 25, 34 }, { 49, 40 }, { 40, 52 }, { 36, 49 },
|
|
{ 34, 50 }, { 50, 56 }, { 52, 25 }, { 54, 22 }, { 41, 54 }, { 56, 57 }, { 38, 41 }, { 57, 38 }
|
|
};
|
|
|
|
static const uint8_t scan3x3[4] = { 4, 5, 7, 8 };
|
|
|
|
static const uint8_t dequant_shift[64] = {
|
|
14, 14, 14, 14, 14, 14, 14, 14,
|
|
13, 13, 13, 13, 13, 13, 13, 13,
|
|
13, 12, 12, 12, 12, 12, 12, 12,
|
|
11, 11, 11, 11, 11, 11, 11, 11,
|
|
11, 10, 10, 10, 10, 10, 10, 10,
|
|
10, 9, 9, 9, 9, 9, 9, 9,
|
|
9, 8, 8, 8, 8, 8, 8, 8,
|
|
7, 7, 7, 7, 7, 7, 7, 7
|
|
};
|
|
|
|
static const uint16_t dequant_mul[64] = {
|
|
32768, 36061, 38968, 42495, 46341, 50535, 55437, 60424,
|
|
32932, 35734, 38968, 42495, 46177, 50535, 55109, 59933,
|
|
65535, 35734, 38968, 42577, 46341, 50617, 55027, 60097,
|
|
32809, 35734, 38968, 42454, 46382, 50576, 55109, 60056,
|
|
65535, 35734, 38968, 42495, 46320, 50515, 55109, 60076,
|
|
65535, 35744, 38968, 42495, 46341, 50535, 55099, 60087,
|
|
65535, 35734, 38973, 42500, 46341, 50535, 55109, 60097,
|
|
32771, 35734, 38965, 42497, 46341, 50535, 55109, 60099
|
|
};
|
|
|
|
#define EOB 0, 0, 0
|
|
|
|
static const struct dec_2dvlc intra_dec[7] = {
|
|
{
|
|
{ //level / run / table_inc
|
|
{ 1, 1, 1 }, { -1, 1, 1 }, { 1, 2, 1 }, { -1, 2, 1 }, { 1, 3, 1 }, { -1, 3, 1 },
|
|
{ 1, 4, 1 }, { -1, 4, 1 }, { 1, 5, 1 }, { -1, 5, 1 }, { 1, 6, 1 }, { -1, 6, 1 },
|
|
{ 1, 7, 1 }, { -1, 7, 1 }, { 1, 8, 1 }, { -1, 8, 1 }, { 1, 9, 1 }, { -1, 9, 1 },
|
|
{ 1, 10, 1 }, { -1, 10, 1 }, { 1, 11, 1 }, { -1, 11, 1 }, { 2, 1, 2 }, { -2, 1, 2 },
|
|
{ 1, 12, 1 }, { -1, 12, 1 }, { 1, 13, 1 }, { -1, 13, 1 }, { 1, 14, 1 }, { -1, 14, 1 },
|
|
{ 1, 15, 1 }, { -1, 15, 1 }, { 2, 2, 2 }, { -2, 2, 2 }, { 1, 16, 1 }, { -1, 16, 1 },
|
|
{ 1, 17, 1 }, { -1, 17, 1 }, { 3, 1, 3 }, { -3, 1, 3 }, { 1, 18, 1 }, { -1, 18, 1 },
|
|
{ 1, 19, 1 }, { -1, 19, 1 }, { 2, 3, 2 }, { -2, 3, 2 }, { 1, 20, 1 }, { -1, 20, 1 },
|
|
{ 1, 21, 1 }, { -1, 21, 1 }, { 2, 4, 2 }, { -2, 4, 2 }, { 1, 22, 1 }, { -1, 22, 1 },
|
|
{ 2, 5, 2 }, { -2, 5, 2 }, { 1, 23, 1 }, { -1, 23, 1 }, { EOB }
|
|
},
|
|
//level_add
|
|
{ 0, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1 },
|
|
2, //golomb_order
|
|
0, //inc_limit
|
|
23, //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ 1, 1, 0 }, { -1, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 2, 1, 1 }, { -2, 1, 1 },
|
|
{ 1, 3, 0 }, { -1, 3, 0 }, { EOB }, { 1, 4, 0 }, { -1, 4, 0 }, { 1, 5, 0 },
|
|
{ -1, 5, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 3, 1, 2 }, { -3, 1, 2 }, { 2, 2, 1 },
|
|
{ -2, 2, 1 }, { 1, 7, 0 }, { -1, 7, 0 }, { 1, 8, 0 }, { -1, 8, 0 }, { 1, 9, 0 },
|
|
{ -1, 9, 0 }, { 2, 3, 1 }, { -2, 3, 1 }, { 4, 1, 2 }, { -4, 1, 2 }, { 1, 10, 0 },
|
|
{ -1, 10, 0 }, { 1, 11, 0 }, { -1, 11, 0 }, { 2, 4, 1 }, { -2, 4, 1 }, { 3, 2, 2 },
|
|
{ -3, 2, 2 }, { 1, 12, 0 }, { -1, 12, 0 }, { 2, 5, 1 }, { -2, 5, 1 }, { 5, 1, 3 },
|
|
{ -5, 1, 3 }, { 1, 13, 0 }, { -1, 13, 0 }, { 2, 6, 1 }, { -2, 6, 1 }, { 1, 14, 0 },
|
|
{ -1, 14, 0 }, { 2, 7, 1 }, { -2, 7, 1 }, { 2, 8, 1 }, { -2, 8, 1 }, { 3, 3, 2 },
|
|
{ -3, 3, 2 }, { 6, 1, 3 }, { -6, 1, 3 }, { 1, 15, 0 }, { -1, 15, 0 }
|
|
},
|
|
//level_add
|
|
{ 0, 7, 4, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
2, //golomb_order
|
|
1, //inc_limit
|
|
15, //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 },
|
|
{ 3, 1, 1 }, { -3, 1, 1 }, { EOB }, { 1, 3, 0 }, { -1, 3, 0 }, { 2, 2, 0 },
|
|
{ -2, 2, 0 }, { 4, 1, 1 }, { -4, 1, 1 }, { 1, 4, 0 }, { -1, 4, 0 }, { 5, 1, 2 },
|
|
{ -5, 1, 2 }, { 1, 5, 0 }, { -1, 5, 0 }, { 3, 2, 1 }, { -3, 2, 1 }, { 2, 3, 0 },
|
|
{ -2, 3, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 6, 1, 2 }, { -6, 1, 2 }, { 2, 4, 0 },
|
|
{ -2, 4, 0 }, { 1, 7, 0 }, { -1, 7, 0 }, { 4, 2, 1 }, { -4, 2, 1 }, { 7, 1, 2 },
|
|
{ -7, 1, 2 }, { 3, 3, 1 }, { -3, 3, 1 }, { 2, 5, 0 }, { -2, 5, 0 }, { 1, 8, 0 },
|
|
{ -1, 8, 0 }, { 2, 6, 0 }, { -2, 6, 0 }, { 8, 1, 3 }, { -8, 1, 3 }, { 1, 9, 0 },
|
|
{ -1, 9, 0 }, { 5, 2, 2 }, { -5, 2, 2 }, { 3, 4, 1 }, { -3, 4, 1 }, { 2, 7, 0 },
|
|
{ -2, 7, 0 }, { 9, 1, 3 }, { -9, 1, 3 }, { 1, 10, 0 }, { -1, 10, 0 }
|
|
},
|
|
//level_add
|
|
{ 0, 10, 6, 4, 4, 3, 3, 3, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
2, //golomb_order
|
|
2, //inc_limit
|
|
10, //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 }, { -3, 1, 0 },
|
|
{ 1, 2, 0 }, { -1, 2, 0 }, { EOB }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 1 },
|
|
{ -5, 1, 1 }, { 2, 2, 0 }, { -2, 2, 0 }, { 1, 3, 0 }, { -1, 3, 0 }, { 6, 1, 1 },
|
|
{ -6, 1, 1 }, { 3, 2, 0 }, { -3, 2, 0 }, { 7, 1, 1 }, { -7, 1, 1 }, { 1, 4, 0 },
|
|
{ -1, 4, 0 }, { 8, 1, 2 }, { -8, 1, 2 }, { 2, 3, 0 }, { -2, 3, 0 }, { 4, 2, 0 },
|
|
{ -4, 2, 0 }, { 1, 5, 0 }, { -1, 5, 0 }, { 9, 1, 2 }, { -9, 1, 2 }, { 5, 2, 1 },
|
|
{ -5, 2, 1 }, { 2, 4, 0 }, { -2, 4, 0 }, { 10, 1, 2 }, {-10, 1, 2 }, { 3, 3, 0 },
|
|
{ -3, 3, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 11, 1, 3 }, {-11, 1, 3 }, { 6, 2, 1 },
|
|
{ -6, 2, 1 }, { 1, 7, 0 }, { -1, 7, 0 }, { 2, 5, 0 }, { -2, 5, 0 }, { 3, 4, 0 },
|
|
{ -3, 4, 0 }, { 12, 1, 3 }, {-12, 1, 3 }, { 4, 3, 0 }, { -4, 3, 0 }
|
|
},
|
|
//level_add
|
|
{ 0, 13, 7, 5, 4, 3, 2, 2, -1, -1, -1 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
2, //golomb_order
|
|
4, //inc_limit
|
|
7, //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 }, { -3, 1, 0 },
|
|
{ EOB }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, { -5, 1, 0 }, { 6, 1, 0 },
|
|
{ -6, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 7, 1, 0 }, { -7, 1, 0 }, { 8, 1, 1 },
|
|
{ -8, 1, 1 }, { 2, 2, 0 }, { -2, 2, 0 }, { 9, 1, 1 }, { -9, 1, 1 }, { 10, 1, 1 },
|
|
{-10, 1, 1 }, { 1, 3, 0 }, { -1, 3, 0 }, { 3, 2, 0 }, { -3, 2, 0 }, { 11, 1, 2 },
|
|
{-11, 1, 2 }, { 4, 2, 0 }, { -4, 2, 0 }, { 12, 1, 2 }, {-12, 1, 2 }, { 13, 1, 2 },
|
|
{-13, 1, 2 }, { 5, 2, 0 }, { -5, 2, 0 }, { 1, 4, 0 }, { -1, 4, 0 }, { 2, 3, 0 },
|
|
{ -2, 3, 0 }, { 14, 1, 2 }, {-14, 1, 2 }, { 6, 2, 0 }, { -6, 2, 0 }, { 15, 1, 2 },
|
|
{-15, 1, 2 }, { 16, 1, 2 }, {-16, 1, 2 }, { 3, 3, 0 }, { -3, 3, 0 }, { 1, 5, 0 },
|
|
{ -1, 5, 0 }, { 7, 2, 0 }, { -7, 2, 0 }, { 17, 1, 2 }, {-17, 1, 2 }
|
|
},
|
|
//level_add
|
|
{ 0,18, 8, 4, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
2, //golomb_order
|
|
7, //inc_limit
|
|
5, //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 },
|
|
{ -3, 1, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, { -5, 1, 0 }, { 6, 1, 0 },
|
|
{ -6, 1, 0 }, { 7, 1, 0 }, { -7, 1, 0 }, { 8, 1, 0 }, { -8, 1, 0 }, { 9, 1, 0 },
|
|
{ -9, 1, 0 }, { 10, 1, 0 }, {-10, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 11, 1, 1 },
|
|
{-11, 1, 1 }, { 12, 1, 1 }, {-12, 1, 1 }, { 13, 1, 1 }, {-13, 1, 1 }, { 2, 2, 0 },
|
|
{ -2, 2, 0 }, { 14, 1, 1 }, {-14, 1, 1 }, { 15, 1, 1 }, {-15, 1, 1 }, { 3, 2, 0 },
|
|
{ -3, 2, 0 }, { 16, 1, 1 }, {-16, 1, 1 }, { 1, 3, 0 }, { -1, 3, 0 }, { 17, 1, 1 },
|
|
{-17, 1, 1 }, { 4, 2, 0 }, { -4, 2, 0 }, { 18, 1, 1 }, {-18, 1, 1 }, { 5, 2, 0 },
|
|
{ -5, 2, 0 }, { 19, 1, 1 }, {-19, 1, 1 }, { 20, 1, 1 }, {-20, 1, 1 }, { 6, 2, 0 },
|
|
{ -6, 2, 0 }, { 21, 1, 1 }, {-21, 1, 1 }, { 2, 3, 0 }, { -2, 3, 0 }
|
|
},
|
|
//level_add
|
|
{ 0, 22, 7, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
2, //golomb_order
|
|
10, //inc_limit
|
|
3, //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 },
|
|
{ -3, 1, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, { -5, 1, 0 }, { 6, 1, 0 },
|
|
{ -6, 1, 0 }, { 7, 1, 0 }, { -7, 1, 0 }, { 8, 1, 0 }, { -8, 1, 0 }, { 9, 1, 0 },
|
|
{ -9, 1, 0 }, { 10, 1, 0 }, {-10, 1, 0 }, { 11, 1, 0 }, {-11, 1, 0 }, { 12, 1, 0 },
|
|
{-12, 1, 0 }, { 13, 1, 0 }, {-13, 1, 0 }, { 14, 1, 0 }, {-14, 1, 0 }, { 15, 1, 0 },
|
|
{-15, 1, 0 }, { 16, 1, 0 }, {-16, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 17, 1, 0 },
|
|
{-17, 1, 0 }, { 18, 1, 0 }, {-18, 1, 0 }, { 19, 1, 0 }, {-19, 1, 0 }, { 20, 1, 0 },
|
|
{-20, 1, 0 }, { 21, 1, 0 }, {-21, 1, 0 }, { 2, 2, 0 }, { -2, 2, 0 }, { 22, 1, 0 },
|
|
{-22, 1, 0 }, { 23, 1, 0 }, {-23, 1, 0 }, { 24, 1, 0 }, {-24, 1, 0 }, { 25, 1, 0 },
|
|
{-25, 1, 0 }, { 3, 2, 0 }, { -3, 2, 0 }, { 26, 1, 0 }, {-26, 1, 0 }
|
|
},
|
|
//level_add
|
|
{ 0, 27, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
2, //golomb_order
|
|
INT_MAX, //inc_limit
|
|
2, //max_run
|
|
}
|
|
};
|
|
|
|
static const struct dec_2dvlc inter_dec[7] = {
|
|
{
|
|
{ //level / run
|
|
{ 1, 1, 1 }, { -1, 1, 1 }, { 1, 2, 1 }, { -1, 2, 1 }, { 1, 3, 1 }, { -1, 3, 1 },
|
|
{ 1, 4, 1 }, { -1, 4, 1 }, { 1, 5, 1 }, { -1, 5, 1 }, { 1, 6, 1 }, { -1, 6, 1 },
|
|
{ 1, 7, 1 }, { -1, 7, 1 }, { 1, 8, 1 }, { -1, 8, 1 }, { 1, 9, 1 }, { -1, 9, 1 },
|
|
{ 1, 10, 1 }, { -1, 10, 1 }, { 1, 11, 1 }, { -1, 11, 1 }, { 1, 12, 1 }, { -1, 12, 1 },
|
|
{ 1, 13, 1 }, { -1, 13, 1 }, { 2, 1, 2 }, { -2, 1, 2 }, { 1, 14, 1 }, { -1, 14, 1 },
|
|
{ 1, 15, 1 }, { -1, 15, 1 }, { 1, 16, 1 }, { -1, 16, 1 }, { 1, 17, 1 }, { -1, 17, 1 },
|
|
{ 1, 18, 1 }, { -1, 18, 1 }, { 1, 19, 1 }, { -1, 19, 1 }, { 3, 1, 3 }, { -3, 1, 3 },
|
|
{ 1, 20, 1 }, { -1, 20, 1 }, { 1, 21, 1 }, { -1, 21, 1 }, { 2, 2, 2 }, { -2, 2, 2 },
|
|
{ 1, 22, 1 }, { -1, 22, 1 }, { 1, 23, 1 }, { -1, 23, 1 }, { 1, 24, 1 }, { -1, 24, 1 },
|
|
{ 1, 25, 1 }, { -1, 25, 1 }, { 1, 26, 1 }, { -1, 26, 1 }, { EOB }
|
|
},
|
|
//level_add
|
|
{ 0, 4, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
|
|
3, //golomb_order
|
|
0, //inc_limit
|
|
26 //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ 1, 1, 0 }, { -1, 1, 0 }, { EOB }, { 1, 2, 0 }, { -1, 2, 0 }, { 1, 3, 0 },
|
|
{ -1, 3, 0 }, { 1, 4, 0 }, { -1, 4, 0 }, { 1, 5, 0 }, { -1, 5, 0 }, { 1, 6, 0 },
|
|
{ -1, 6, 0 }, { 2, 1, 1 }, { -2, 1, 1 }, { 1, 7, 0 }, { -1, 7, 0 }, { 1, 8, 0 },
|
|
{ -1, 8, 0 }, { 1, 9, 0 }, { -1, 9, 0 }, { 1, 10, 0 }, { -1, 10, 0 }, { 2, 2, 1 },
|
|
{ -2, 2, 1 }, { 1, 11, 0 }, { -1, 11, 0 }, { 1, 12, 0 }, { -1, 12, 0 }, { 3, 1, 2 },
|
|
{ -3, 1, 2 }, { 1, 13, 0 }, { -1, 13, 0 }, { 1, 14, 0 }, { -1, 14, 0 }, { 2, 3, 1 },
|
|
{ -2, 3, 1 }, { 1, 15, 0 }, { -1, 15, 0 }, { 2, 4, 1 }, { -2, 4, 1 }, { 1, 16, 0 },
|
|
{ -1, 16, 0 }, { 2, 5, 1 }, { -2, 5, 1 }, { 1, 17, 0 }, { -1, 17, 0 }, { 4, 1, 3 },
|
|
{ -4, 1, 3 }, { 2, 6, 1 }, { -2, 6, 1 }, { 1, 18, 0 }, { -1, 18, 0 }, { 1, 19, 0 },
|
|
{ -1, 19, 0 }, { 2, 7, 1 }, { -2, 7, 1 }, { 3, 2, 2 }, { -3, 2, 2 }
|
|
},
|
|
//level_add
|
|
{ 0, 5, 4, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1 },
|
|
2, //golomb_order
|
|
1, //inc_limit
|
|
19 //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ 1, 1, 0 }, { -1, 1, 0 }, { EOB }, { 1, 2, 0 }, { -1, 2, 0 }, { 2, 1, 0 },
|
|
{ -2, 1, 0 }, { 1, 3, 0 }, { -1, 3, 0 }, { 1, 4, 0 }, { -1, 4, 0 }, { 3, 1, 1 },
|
|
{ -3, 1, 1 }, { 2, 2, 0 }, { -2, 2, 0 }, { 1, 5, 0 }, { -1, 5, 0 }, { 1, 6, 0 },
|
|
{ -1, 6, 0 }, { 1, 7, 0 }, { -1, 7, 0 }, { 2, 3, 0 }, { -2, 3, 0 }, { 4, 1, 2 },
|
|
{ -4, 1, 2 }, { 1, 8, 0 }, { -1, 8, 0 }, { 3, 2, 1 }, { -3, 2, 1 }, { 2, 4, 0 },
|
|
{ -2, 4, 0 }, { 1, 9, 0 }, { -1, 9, 0 }, { 1, 10, 0 }, { -1, 10, 0 }, { 5, 1, 2 },
|
|
{ -5, 1, 2 }, { 2, 5, 0 }, { -2, 5, 0 }, { 1, 11, 0 }, { -1, 11, 0 }, { 2, 6, 0 },
|
|
{ -2, 6, 0 }, { 1, 12, 0 }, { -1, 12, 0 }, { 3, 3, 1 }, { -3, 3, 1 }, { 6, 1, 2 },
|
|
{ -6, 1, 2 }, { 4, 2, 2 }, { -4, 2, 2 }, { 1, 13, 0 }, { -1, 13, 0 }, { 2, 7, 0 },
|
|
{ -2, 7, 0 }, { 3, 4, 1 }, { -3, 4, 1 }, { 1, 14, 0 }, { -1, 14, 0 }
|
|
},
|
|
//level_add
|
|
{ 0, 7, 5, 4, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
2, //golomb_order
|
|
2, //inc_limit
|
|
14 //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ 1, 1, 0 }, { -1, 1, 0 }, { EOB }, { 2, 1, 0 }, { -2, 1, 0 }, { 1, 2, 0 },
|
|
{ -1, 2, 0 }, { 3, 1, 0 }, { -3, 1, 0 }, { 1, 3, 0 }, { -1, 3, 0 }, { 2, 2, 0 },
|
|
{ -2, 2, 0 }, { 4, 1, 1 }, { -4, 1, 1 }, { 1, 4, 0 }, { -1, 4, 0 }, { 5, 1, 1 },
|
|
{ -5, 1, 1 }, { 1, 5, 0 }, { -1, 5, 0 }, { 3, 2, 0 }, { -3, 2, 0 }, { 2, 3, 0 },
|
|
{ -2, 3, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 6, 1, 1 }, { -6, 1, 1 }, { 2, 4, 0 },
|
|
{ -2, 4, 0 }, { 1, 7, 0 }, { -1, 7, 0 }, { 4, 2, 1 }, { -4, 2, 1 }, { 7, 1, 2 },
|
|
{ -7, 1, 2 }, { 3, 3, 0 }, { -3, 3, 0 }, { 1, 8, 0 }, { -1, 8, 0 }, { 2, 5, 0 },
|
|
{ -2, 5, 0 }, { 8, 1, 2 }, { -8, 1, 2 }, { 1, 9, 0 }, { -1, 9, 0 }, { 3, 4, 0 },
|
|
{ -3, 4, 0 }, { 2, 6, 0 }, { -2, 6, 0 }, { 5, 2, 1 }, { -5, 2, 1 }, { 1, 10, 0 },
|
|
{ -1, 10, 0 }, { 9, 1, 2 }, { -9, 1, 2 }, { 4, 3, 1 }, { -4, 3, 1 }
|
|
},
|
|
//level_add
|
|
{ 0,10, 6, 5, 4, 3, 3, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
2, //golomb_order
|
|
3, //inc_limit
|
|
10 //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ 1, 1, 0 }, { -1, 1, 0 }, { EOB }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 },
|
|
{ -3, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 },
|
|
{ -5, 1, 0 }, { 2, 2, 0 }, { -2, 2, 0 }, { 1, 3, 0 }, { -1, 3, 0 }, { 6, 1, 0 },
|
|
{ -6, 1, 0 }, { 3, 2, 0 }, { -3, 2, 0 }, { 7, 1, 1 }, { -7, 1, 1 }, { 1, 4, 0 },
|
|
{ -1, 4, 0 }, { 8, 1, 1 }, { -8, 1, 1 }, { 2, 3, 0 }, { -2, 3, 0 }, { 4, 2, 0 },
|
|
{ -4, 2, 0 }, { 1, 5, 0 }, { -1, 5, 0 }, { 9, 1, 1 }, { -9, 1, 1 }, { 5, 2, 0 },
|
|
{ -5, 2, 0 }, { 2, 4, 0 }, { -2, 4, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 10, 1, 2 },
|
|
{-10, 1, 2 }, { 3, 3, 0 }, { -3, 3, 0 }, { 11, 1, 2 }, {-11, 1, 2 }, { 1, 7, 0 },
|
|
{ -1, 7, 0 }, { 6, 2, 0 }, { -6, 2, 0 }, { 3, 4, 0 }, { -3, 4, 0 }, { 2, 5, 0 },
|
|
{ -2, 5, 0 }, { 12, 1, 2 }, {-12, 1, 2 }, { 4, 3, 0 }, { -4, 3, 0 }
|
|
},
|
|
//level_add
|
|
{ 0, 13, 7, 5, 4, 3, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
2, //golomb_order
|
|
6, //inc_limit
|
|
7 //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 },
|
|
{ -3, 1, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, { -5, 1, 0 }, { 1, 2, 0 },
|
|
{ -1, 2, 0 }, { 6, 1, 0 }, { -6, 1, 0 }, { 7, 1, 0 }, { -7, 1, 0 }, { 8, 1, 0 },
|
|
{ -8, 1, 0 }, { 2, 2, 0 }, { -2, 2, 0 }, { 9, 1, 0 }, { -9, 1, 0 }, { 1, 3, 0 },
|
|
{ -1, 3, 0 }, { 10, 1, 1 }, { -10, 1, 1 }, { 3, 2, 0 }, { -3, 2, 0 }, { 11, 1, 1 },
|
|
{ -11, 1, 1 }, { 4, 2, 0 }, { -4, 2, 0 }, { 12, 1, 1 }, { -12, 1, 1 }, { 1, 4, 0 },
|
|
{ -1, 4, 0 }, { 2, 3, 0 }, { -2, 3, 0 }, { 13, 1, 1 }, { -13, 1, 1 }, { 5, 2, 0 },
|
|
{ -5, 2, 0 }, { 14, 1, 1 }, { -14, 1, 1 }, { 6, 2, 0 }, { -6, 2, 0 }, { 1, 5, 0 },
|
|
{ -1, 5, 0 }, { 15, 1, 1 }, { -15, 1, 1 }, { 3, 3, 0 }, { -3, 3, 0 }, { 16, 1, 1 },
|
|
{ -16, 1, 1 }, { 2, 4, 0 }, { -2, 4, 0 }, { 7, 2, 0 }, { -7, 2, 0 }
|
|
},
|
|
//level_add
|
|
{ 0, 17, 8, 4, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
2, //golomb_order
|
|
9, //inc_limit
|
|
5 //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 },
|
|
{ -3, 1, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, { -5, 1, 0 }, { 6, 1, 0 },
|
|
{ -6, 1, 0 }, { 7, 1, 0 }, { -7, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 8, 1, 0 },
|
|
{ -8, 1, 0 }, { 9, 1, 0 }, { -9, 1, 0 }, { 10, 1, 0 }, { -10, 1, 0 }, { 11, 1, 0 },
|
|
{ -11, 1, 0 }, { 12, 1, 0 }, { -12, 1, 0 }, { 2, 2, 0 }, { -2, 2, 0 }, { 13, 1, 0 },
|
|
{ -13, 1, 0 }, { 1, 3, 0 }, { -1, 3, 0 }, { 14, 1, 0 }, { -14, 1, 0 }, { 15, 1, 0 },
|
|
{ -15, 1, 0 }, { 3, 2, 0 }, { -3, 2, 0 }, { 16, 1, 0 }, { -16, 1, 0 }, { 17, 1, 0 },
|
|
{ -17, 1, 0 }, { 18, 1, 0 }, { -18, 1, 0 }, { 4, 2, 0 }, { -4, 2, 0 }, { 19, 1, 0 },
|
|
{ -19, 1, 0 }, { 20, 1, 0 }, { -20, 1, 0 }, { 2, 3, 0 }, { -2, 3, 0 }, { 1, 4, 0 },
|
|
{ -1, 4, 0 }, { 5, 2, 0 }, { -5, 2, 0 }, { 21, 1, 0 }, { -21, 1, 0 }
|
|
},
|
|
//level_add
|
|
{ 0, 22, 6, 3, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
2, //golomb_order
|
|
INT_MAX, //inc_limit
|
|
4 //max_run
|
|
}
|
|
};
|
|
|
|
static const struct dec_2dvlc chroma_dec[5] = {
|
|
{
|
|
{ //level / run
|
|
{ 1, 1, 1 }, { -1, 1, 1 }, { 1, 2, 1 }, { -1, 2, 1 }, { 1, 3, 1 }, { -1, 3, 1 },
|
|
{ 1, 4, 1 }, { -1, 4, 1 }, { 1, 5, 1 }, { -1, 5, 1 }, { 1, 6, 1 }, { -1, 6, 1 },
|
|
{ 1, 7, 1 }, { -1, 7, 1 }, { 2, 1, 2 }, { -2, 1, 2 }, { 1, 8, 1 }, { -1, 8, 1 },
|
|
{ 1, 9, 1 }, { -1, 9, 1 }, { 1, 10, 1 }, { -1, 10, 1 }, { 1, 11, 1 }, { -1, 11, 1 },
|
|
{ 1, 12, 1 }, { -1, 12, 1 }, { 1, 13, 1 }, { -1, 13, 1 }, { 1, 14, 1 }, { -1, 14, 1 },
|
|
{ 1, 15, 1 }, { -1, 15, 1 }, { 3, 1, 3 }, { -3, 1, 3 }, { 1, 16, 1 }, { -1, 16, 1 },
|
|
{ 1, 17, 1 }, { -1, 17, 1 }, { 1, 18, 1 }, { -1, 18, 1 }, { 1, 19, 1 }, { -1, 19, 1 },
|
|
{ 1, 20, 1 }, { -1, 20, 1 }, { 1, 21, 1 }, { -1, 21, 1 }, { 1, 22, 1 }, { -1, 22, 1 },
|
|
{ 2, 2, 2 }, { -2, 2, 2 }, { 1, 23, 1 }, { -1, 23, 1 }, { 1, 24, 1 }, { -1, 24, 1 },
|
|
{ 1, 25, 1 }, { -1, 25, 1 }, { 4, 1, 3 }, { -4, 1, 3 }, { EOB }
|
|
},
|
|
//level_add
|
|
{ 0, 5, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1 },
|
|
2, //golomb_order
|
|
0, //inc_limit
|
|
25 //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 2, 1, 1 },
|
|
{ -2, 1, 1 }, { 1, 3, 0 }, { -1, 3, 0 }, { 1, 4, 0 }, { -1, 4, 0 }, { 1, 5, 0 },
|
|
{ -1, 5, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 3, 1, 2 }, { -3, 1, 2 }, { 1, 7, 0 },
|
|
{ -1, 7, 0 }, { 1, 8, 0 }, { -1, 8, 0 }, { 2, 2, 1 }, { -2, 2, 1 }, { 1, 9, 0 },
|
|
{ -1, 9, 0 }, { 1, 10, 0 }, { -1, 10, 0 }, { 1, 11, 0 }, { -1, 11, 0 }, { 4, 1, 2 },
|
|
{ -4, 1, 2 }, { 1, 12, 0 }, { -1, 12, 0 }, { 1, 13, 0 }, { -1, 13, 0 }, { 1, 14, 0 },
|
|
{ -1, 14, 0 }, { 2, 3, 1 }, { -2, 3, 1 }, { 1, 15, 0 }, { -1, 15, 0 }, { 2, 4, 1 },
|
|
{ -2, 4, 1 }, { 5, 1, 3 }, { -5, 1, 3 }, { 3, 2, 2 }, { -3, 2, 2 }, { 1, 16, 0 },
|
|
{ -1, 16, 0 }, { 1, 17, 0 }, { -1, 17, 0 }, { 1, 18, 0 }, { -1, 18, 0 }, { 2, 5, 1 },
|
|
{ -2, 5, 1 }, { 1, 19, 0 }, { -1, 19, 0 }, { 1, 20, 0 }, { -1, 20, 0 }
|
|
},
|
|
//level_add
|
|
{ 0, 6, 4, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1 },
|
|
0, //golomb_order
|
|
1, //inc_limit
|
|
20 //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ 1, 1, 0 }, { -1, 1, 0 }, { EOB }, { 2, 1, 0 }, { -2, 1, 0 }, { 1, 2, 0 },
|
|
{ -1, 2, 0 }, { 3, 1, 1 }, { -3, 1, 1 }, { 1, 3, 0 }, { -1, 3, 0 }, { 4, 1, 1 },
|
|
{ -4, 1, 1 }, { 2, 2, 0 }, { -2, 2, 0 }, { 1, 4, 0 }, { -1, 4, 0 }, { 5, 1, 2 },
|
|
{ -5, 1, 2 }, { 1, 5, 0 }, { -1, 5, 0 }, { 3, 2, 1 }, { -3, 2, 1 }, { 2, 3, 0 },
|
|
{ -2, 3, 0 }, { 1, 6, 0 }, { -1, 6, 0 }, { 6, 1, 2 }, { -6, 1, 2 }, { 1, 7, 0 },
|
|
{ -1, 7, 0 }, { 2, 4, 0 }, { -2, 4, 0 }, { 7, 1, 2 }, { -7, 1, 2 }, { 1, 8, 0 },
|
|
{ -1, 8, 0 }, { 4, 2, 1 }, { -4, 2, 1 }, { 1, 9, 0 }, { -1, 9, 0 }, { 3, 3, 1 },
|
|
{ -3, 3, 1 }, { 2, 5, 0 }, { -2, 5, 0 }, { 2, 6, 0 }, { -2, 6, 0 }, { 8, 1, 2 },
|
|
{ -8, 1, 2 }, { 1, 10, 0 }, { -1, 10, 0 }, { 1, 11, 0 }, { -1, 11, 0 }, { 9, 1, 2 },
|
|
{ -9, 1, 2 }, { 5, 2, 2 }, { -5, 2, 2 }, { 3, 4, 1 }, { -3, 4, 1 },
|
|
},
|
|
//level_add
|
|
{ 0,10, 6, 4, 4, 3, 3, 2, 2, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
1, //golomb_order
|
|
2, //inc_limit
|
|
11 //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 },
|
|
{ -3, 1, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 1, 2, 0 }, { -1, 2, 0 }, { 5, 1, 1 },
|
|
{ -5, 1, 1 }, { 2, 2, 0 }, { -2, 2, 0 }, { 6, 1, 1 }, { -6, 1, 1 }, { 1, 3, 0 },
|
|
{ -1, 3, 0 }, { 7, 1, 1 }, { -7, 1, 1 }, { 3, 2, 0 }, { -3, 2, 0 }, { 8, 1, 1 },
|
|
{ -8, 1, 1 }, { 1, 4, 0 }, { -1, 4, 0 }, { 2, 3, 0 }, { -2, 3, 0 }, { 9, 1, 1 },
|
|
{ -9, 1, 1 }, { 4, 2, 0 }, { -4, 2, 0 }, { 1, 5, 0 }, { -1, 5, 0 }, { 10, 1, 1 },
|
|
{-10, 1, 1 }, { 3, 3, 0 }, { -3, 3, 0 }, { 5, 2, 1 }, { -5, 2, 1 }, { 2, 4, 0 },
|
|
{ -2, 4, 0 }, { 11, 1, 1 }, {-11, 1, 1 }, { 1, 6, 0 }, { -1, 6, 0 }, { 12, 1, 1 },
|
|
{-12, 1, 1 }, { 1, 7, 0 }, { -1, 7, 0 }, { 6, 2, 1 }, { -6, 2, 1 }, { 13, 1, 1 },
|
|
{-13, 1, 1 }, { 2, 5, 0 }, { -2, 5, 0 }, { 1, 8, 0 }, { -1, 8, 0 },
|
|
},
|
|
//level_add
|
|
{ 0, 14, 7, 4, 3, 3, 2, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
1, //golomb_order
|
|
4, //inc_limit
|
|
8 //max_run
|
|
},
|
|
{
|
|
{ //level / run
|
|
{ EOB }, { 1, 1, 0 }, { -1, 1, 0 }, { 2, 1, 0 }, { -2, 1, 0 }, { 3, 1, 0 },
|
|
{ -3, 1, 0 }, { 4, 1, 0 }, { -4, 1, 0 }, { 5, 1, 0 }, { -5, 1, 0 }, { 6, 1, 0 },
|
|
{ -6, 1, 0 }, { 7, 1, 0 }, { -7, 1, 0 }, { 8, 1, 0 }, { -8, 1, 0 }, { 1, 2, 0 },
|
|
{ -1, 2, 0 }, { 9, 1, 0 }, { -9, 1, 0 }, { 10, 1, 0 }, { -10, 1, 0 }, { 11, 1, 0 },
|
|
{ -11, 1, 0 }, { 2, 2, 0 }, { -2, 2, 0 }, { 12, 1, 0 }, { -12, 1, 0 }, { 13, 1, 0 },
|
|
{ -13, 1, 0 }, { 3, 2, 0 }, { -3, 2, 0 }, { 14, 1, 0 }, { -14, 1, 0 }, { 1, 3, 0 },
|
|
{ -1, 3, 0 }, { 15, 1, 0 }, { -15, 1, 0 }, { 4, 2, 0 }, { -4, 2, 0 }, { 16, 1, 0 },
|
|
{ -16, 1, 0 }, { 17, 1, 0 }, { -17, 1, 0 }, { 5, 2, 0 }, { -5, 2, 0 }, { 1, 4, 0 },
|
|
{ -1, 4, 0 }, { 2, 3, 0 }, { -2, 3, 0 }, { 18, 1, 0 }, { -18, 1, 0 }, { 6, 2, 0 },
|
|
{ -6, 2, 0 }, { 19, 1, 0 }, { -19, 1, 0 }, { 1, 5, 0 }, { -1, 5, 0 },
|
|
},
|
|
//level_add
|
|
{ 0, 20, 7, 3, 2, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
|
|
0, //golomb_order
|
|
INT_MAX, //inc_limit
|
|
5, //max_run
|
|
}
|
|
};
|
|
|
|
#undef EOB
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* motion vector prediction
|
|
*
|
|
****************************************************************************/
|
|
|
|
static inline void store_mvs(AVSContext *h)
|
|
{
|
|
h->col_mv[h->mbidx * 4 + 0] = h->mv[MV_FWD_X0];
|
|
h->col_mv[h->mbidx * 4 + 1] = h->mv[MV_FWD_X1];
|
|
h->col_mv[h->mbidx * 4 + 2] = h->mv[MV_FWD_X2];
|
|
h->col_mv[h->mbidx * 4 + 3] = h->mv[MV_FWD_X3];
|
|
}
|
|
|
|
static inline void mv_pred_direct(AVSContext *h, cavs_vector *pmv_fw,
|
|
cavs_vector *col_mv)
|
|
{
|
|
cavs_vector *pmv_bw = pmv_fw + MV_BWD_OFFS;
|
|
unsigned den = h->direct_den[col_mv->ref];
|
|
int m = FF_SIGNBIT(col_mv->x);
|
|
|
|
pmv_fw->dist = h->dist[1];
|
|
pmv_bw->dist = h->dist[0];
|
|
pmv_fw->ref = 1;
|
|
pmv_bw->ref = 0;
|
|
/* scale the co-located motion vector according to its temporal span */
|
|
pmv_fw->x = (((den + (den * col_mv->x * pmv_fw->dist ^ m) - m - 1) >> 14) ^ m) - m;
|
|
pmv_bw->x = m - (((den + (den * col_mv->x * pmv_bw->dist ^ m) - m - 1) >> 14) ^ m);
|
|
m = FF_SIGNBIT(col_mv->y);
|
|
pmv_fw->y = (((den + (den * col_mv->y * pmv_fw->dist ^ m) - m - 1) >> 14) ^ m) - m;
|
|
pmv_bw->y = m - (((den + (den * col_mv->y * pmv_bw->dist ^ m) - m - 1) >> 14) ^ m);
|
|
}
|
|
|
|
static inline void mv_pred_sym(AVSContext *h, cavs_vector *src,
|
|
enum cavs_block size)
|
|
{
|
|
cavs_vector *dst = src + MV_BWD_OFFS;
|
|
|
|
/* backward mv is the scaled and negated forward mv */
|
|
dst->x = -((src->x * h->sym_factor + 256) >> 9);
|
|
dst->y = -((src->y * h->sym_factor + 256) >> 9);
|
|
dst->ref = 0;
|
|
dst->dist = h->dist[0];
|
|
set_mvs(dst, size);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* residual data decoding
|
|
*
|
|
****************************************************************************/
|
|
|
|
/** kth-order exponential golomb code */
|
|
static inline int get_ue_code(GetBitContext *gb, int order)
|
|
{
|
|
unsigned ret = get_ue_golomb(gb);
|
|
if (ret >= ((1U<<31)>>order)) {
|
|
av_log(NULL, AV_LOG_ERROR, "get_ue_code: value too large\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
if (order) {
|
|
return (ret<<order) + get_bits(gb, order);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static inline int dequant(AVSContext *h, int16_t *level_buf, uint8_t *run_buf,
|
|
int16_t *dst, int mul, int shift, int coeff_num)
|
|
{
|
|
int round = 1 << (shift - 1);
|
|
int pos = -1;
|
|
const uint8_t *scantab = h->scantable.permutated;
|
|
|
|
/* inverse scan and dequantization */
|
|
while (--coeff_num >= 0) {
|
|
pos += run_buf[coeff_num];
|
|
if (pos > 63) {
|
|
av_log(h->avctx, AV_LOG_ERROR,
|
|
"position out of block bounds at pic %d MB(%d,%d)\n",
|
|
h->cur.poc, h->mbx, h->mby);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
dst[scantab[pos]] = (level_buf[coeff_num] * mul + round) >> shift;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* decode coefficients from one 8x8 block, dequantize, inverse transform
|
|
* and add them to sample block
|
|
* @param r pointer to 2D VLC table
|
|
* @param esc_golomb_order escape codes are k-golomb with this order k
|
|
* @param qp quantizer
|
|
* @param dst location of sample block
|
|
* @param stride line stride in frame buffer
|
|
*/
|
|
static int decode_residual_block(AVSContext *h, GetBitContext *gb,
|
|
const struct dec_2dvlc *r, int esc_golomb_order,
|
|
int qp, uint8_t *dst, ptrdiff_t stride)
|
|
{
|
|
int i, esc_code, level, mask, ret;
|
|
unsigned int level_code, run;
|
|
int16_t level_buf[65];
|
|
uint8_t run_buf[65];
|
|
int16_t *block = h->block;
|
|
|
|
for (i = 0; i < 65; i++) {
|
|
level_code = get_ue_code(gb, r->golomb_order);
|
|
if (level_code >= ESCAPE_CODE) {
|
|
run = ((level_code - ESCAPE_CODE) >> 1) + 1;
|
|
if(run > 64) {
|
|
av_log(h->avctx, AV_LOG_ERROR, "run %d is too large\n", run);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
esc_code = get_ue_code(gb, esc_golomb_order);
|
|
if (esc_code < 0 || esc_code > 32767) {
|
|
av_log(h->avctx, AV_LOG_ERROR, "esc_code invalid\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
level = esc_code + (run > r->max_run ? 1 : r->level_add[run]);
|
|
while (level > r->inc_limit)
|
|
r++;
|
|
mask = -(level_code & 1);
|
|
level = (level ^ mask) - mask;
|
|
} else {
|
|
level = r->rltab[level_code][0];
|
|
if (!level) //end of block signal
|
|
break;
|
|
run = r->rltab[level_code][1];
|
|
r += r->rltab[level_code][2];
|
|
}
|
|
level_buf[i] = level;
|
|
run_buf[i] = run;
|
|
}
|
|
if ((ret = dequant(h, level_buf, run_buf, block, dequant_mul[qp],
|
|
dequant_shift[qp], i)) < 0)
|
|
return ret;
|
|
h->cdsp.cavs_idct8_add(dst, block, stride);
|
|
h->bdsp.clear_block(block);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static inline int decode_residual_chroma(AVSContext *h)
|
|
{
|
|
if (h->cbp & (1 << 4)) {
|
|
int ret = decode_residual_block(h, &h->gb, chroma_dec, 0,
|
|
ff_cavs_chroma_qp[h->qp], h->cu, h->c_stride);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
if (h->cbp & (1 << 5)) {
|
|
int ret = decode_residual_block(h, &h->gb, chroma_dec, 0,
|
|
ff_cavs_chroma_qp[h->qp], h->cv, h->c_stride);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static inline int decode_residual_inter(AVSContext *h)
|
|
{
|
|
int block;
|
|
|
|
/* get coded block pattern */
|
|
int cbp = get_ue_golomb(&h->gb);
|
|
if (cbp > 63U) {
|
|
av_log(h->avctx, AV_LOG_ERROR, "illegal inter cbp %d\n", cbp);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
h->cbp = cbp_tab[cbp][1];
|
|
|
|
/* get quantizer */
|
|
if (h->cbp && !h->qp_fixed)
|
|
h->qp = (h->qp + (unsigned)get_se_golomb(&h->gb)) & 63;
|
|
for (block = 0; block < 4; block++)
|
|
if (h->cbp & (1 << block))
|
|
decode_residual_block(h, &h->gb, inter_dec, 0, h->qp,
|
|
h->cy + h->luma_scan[block], h->l_stride);
|
|
decode_residual_chroma(h);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* macroblock level
|
|
*
|
|
****************************************************************************/
|
|
|
|
static inline void set_mv_intra(AVSContext *h)
|
|
{
|
|
h->mv[MV_FWD_X0] = ff_cavs_intra_mv;
|
|
set_mvs(&h->mv[MV_FWD_X0], BLK_16X16);
|
|
h->mv[MV_BWD_X0] = ff_cavs_intra_mv;
|
|
set_mvs(&h->mv[MV_BWD_X0], BLK_16X16);
|
|
if (h->cur.f->pict_type != AV_PICTURE_TYPE_B)
|
|
h->col_type_base[h->mbidx] = I_8X8;
|
|
}
|
|
|
|
static int decode_mb_i(AVSContext *h, int cbp_code)
|
|
{
|
|
GetBitContext *gb = &h->gb;
|
|
unsigned pred_mode_uv;
|
|
int block;
|
|
uint8_t top[18];
|
|
uint8_t *left = NULL;
|
|
uint8_t *d;
|
|
int ret;
|
|
|
|
ff_cavs_init_mb(h);
|
|
|
|
/* get intra prediction modes from stream */
|
|
for (block = 0; block < 4; block++) {
|
|
int nA, nB, predpred;
|
|
int pos = scan3x3[block];
|
|
|
|
nA = h->pred_mode_Y[pos - 1];
|
|
nB = h->pred_mode_Y[pos - 3];
|
|
predpred = FFMIN(nA, nB);
|
|
if (predpred == NOT_AVAIL) // if either is not available
|
|
predpred = INTRA_L_LP;
|
|
if (!get_bits1(gb)) {
|
|
int rem_mode = get_bits(gb, 2);
|
|
predpred = rem_mode + (rem_mode >= predpred);
|
|
}
|
|
h->pred_mode_Y[pos] = predpred;
|
|
}
|
|
pred_mode_uv = get_ue_golomb_31(gb);
|
|
if (pred_mode_uv > 6) {
|
|
av_log(h->avctx, AV_LOG_ERROR, "illegal intra chroma pred mode\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
ff_cavs_modify_mb_i(h, &pred_mode_uv);
|
|
|
|
/* get coded block pattern */
|
|
if (h->cur.f->pict_type == AV_PICTURE_TYPE_I)
|
|
cbp_code = get_ue_golomb(gb);
|
|
if (cbp_code > 63U) {
|
|
av_log(h->avctx, AV_LOG_ERROR, "illegal intra cbp\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
h->cbp = cbp_tab[cbp_code][0];
|
|
if (h->cbp && !h->qp_fixed)
|
|
h->qp = (h->qp + (unsigned)get_se_golomb(gb)) & 63; //qp_delta
|
|
|
|
/* luma intra prediction interleaved with residual decode/transform/add */
|
|
for (block = 0; block < 4; block++) {
|
|
d = h->cy + h->luma_scan[block];
|
|
ff_cavs_load_intra_pred_luma(h, top, &left, block);
|
|
h->intra_pred_l[h->pred_mode_Y[scan3x3[block]]]
|
|
(d, top, left, h->l_stride);
|
|
if (h->cbp & (1<<block)) {
|
|
ret = decode_residual_block(h, gb, intra_dec, 1, h->qp, d, h->l_stride);
|
|
if (ret < 0)
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
/* chroma intra prediction */
|
|
ff_cavs_load_intra_pred_chroma(h);
|
|
h->intra_pred_c[pred_mode_uv](h->cu, &h->top_border_u[h->mbx * 10],
|
|
h->left_border_u, h->c_stride);
|
|
h->intra_pred_c[pred_mode_uv](h->cv, &h->top_border_v[h->mbx * 10],
|
|
h->left_border_v, h->c_stride);
|
|
|
|
ret = decode_residual_chroma(h);
|
|
if (ret < 0)
|
|
return ret;
|
|
ff_cavs_filter(h, I_8X8);
|
|
set_mv_intra(h);
|
|
return 0;
|
|
}
|
|
|
|
static inline void set_intra_mode_default(AVSContext *h)
|
|
{
|
|
if (h->stream_revision > 0) {
|
|
h->pred_mode_Y[3] = h->pred_mode_Y[6] = NOT_AVAIL;
|
|
h->top_pred_Y[h->mbx * 2 + 0] = h->top_pred_Y[h->mbx * 2 + 1] = NOT_AVAIL;
|
|
} else {
|
|
h->pred_mode_Y[3] = h->pred_mode_Y[6] = INTRA_L_LP;
|
|
h->top_pred_Y[h->mbx * 2 + 0] = h->top_pred_Y[h->mbx * 2 + 1] = INTRA_L_LP;
|
|
}
|
|
}
|
|
|
|
static void decode_mb_p(AVSContext *h, enum cavs_mb mb_type)
|
|
{
|
|
GetBitContext *gb = &h->gb;
|
|
int ref[4];
|
|
|
|
ff_cavs_init_mb(h);
|
|
switch (mb_type) {
|
|
case P_SKIP:
|
|
ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_PSKIP, BLK_16X16, 0);
|
|
break;
|
|
case P_16X16:
|
|
ref[0] = h->ref_flag ? 0 : get_bits1(gb);
|
|
ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, ref[0]);
|
|
break;
|
|
case P_16X8:
|
|
ref[0] = h->ref_flag ? 0 : get_bits1(gb);
|
|
ref[2] = h->ref_flag ? 0 : get_bits1(gb);
|
|
ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_TOP, BLK_16X8, ref[0]);
|
|
ff_cavs_mv(h, MV_FWD_X2, MV_FWD_A1, MV_PRED_LEFT, BLK_16X8, ref[2]);
|
|
break;
|
|
case P_8X16:
|
|
ref[0] = h->ref_flag ? 0 : get_bits1(gb);
|
|
ref[1] = h->ref_flag ? 0 : get_bits1(gb);
|
|
ff_cavs_mv(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_LEFT, BLK_8X16, ref[0]);
|
|
ff_cavs_mv(h, MV_FWD_X1, MV_FWD_C2, MV_PRED_TOPRIGHT, BLK_8X16, ref[1]);
|
|
break;
|
|
case P_8X8:
|
|
ref[0] = h->ref_flag ? 0 : get_bits1(gb);
|
|
ref[1] = h->ref_flag ? 0 : get_bits1(gb);
|
|
ref[2] = h->ref_flag ? 0 : get_bits1(gb);
|
|
ref[3] = h->ref_flag ? 0 : get_bits1(gb);
|
|
ff_cavs_mv(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_MEDIAN, BLK_8X8, ref[0]);
|
|
ff_cavs_mv(h, MV_FWD_X1, MV_FWD_C2, MV_PRED_MEDIAN, BLK_8X8, ref[1]);
|
|
ff_cavs_mv(h, MV_FWD_X2, MV_FWD_X1, MV_PRED_MEDIAN, BLK_8X8, ref[2]);
|
|
ff_cavs_mv(h, MV_FWD_X3, MV_FWD_X0, MV_PRED_MEDIAN, BLK_8X8, ref[3]);
|
|
}
|
|
ff_cavs_inter(h, mb_type);
|
|
set_intra_mode_default(h);
|
|
store_mvs(h);
|
|
if (mb_type != P_SKIP)
|
|
decode_residual_inter(h);
|
|
ff_cavs_filter(h, mb_type);
|
|
h->col_type_base[h->mbidx] = mb_type;
|
|
}
|
|
|
|
static int decode_mb_b(AVSContext *h, enum cavs_mb mb_type)
|
|
{
|
|
int block;
|
|
enum cavs_sub_mb sub_type[4];
|
|
int flags;
|
|
|
|
ff_cavs_init_mb(h);
|
|
|
|
/* reset all MVs */
|
|
h->mv[MV_FWD_X0] = ff_cavs_dir_mv;
|
|
set_mvs(&h->mv[MV_FWD_X0], BLK_16X16);
|
|
h->mv[MV_BWD_X0] = ff_cavs_dir_mv;
|
|
set_mvs(&h->mv[MV_BWD_X0], BLK_16X16);
|
|
switch (mb_type) {
|
|
case B_SKIP:
|
|
case B_DIRECT:
|
|
if (!h->col_type_base[h->mbidx]) {
|
|
/* intra MB at co-location, do in-plane prediction */
|
|
ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_BSKIP, BLK_16X16, 1);
|
|
ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_BSKIP, BLK_16X16, 0);
|
|
} else
|
|
/* direct prediction from co-located P MB, block-wise */
|
|
for (block = 0; block < 4; block++)
|
|
mv_pred_direct(h, &h->mv[mv_scan[block]],
|
|
&h->col_mv[h->mbidx * 4 + block]);
|
|
break;
|
|
case B_FWD_16X16:
|
|
ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, 1);
|
|
break;
|
|
case B_SYM_16X16:
|
|
ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_MEDIAN, BLK_16X16, 1);
|
|
mv_pred_sym(h, &h->mv[MV_FWD_X0], BLK_16X16);
|
|
break;
|
|
case B_BWD_16X16:
|
|
ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_MEDIAN, BLK_16X16, 0);
|
|
break;
|
|
case B_8X8:
|
|
#define TMP_UNUSED_INX 7
|
|
flags = 0;
|
|
for (block = 0; block < 4; block++)
|
|
sub_type[block] = get_bits(&h->gb, 2);
|
|
for (block = 0; block < 4; block++) {
|
|
switch (sub_type[block]) {
|
|
case B_SUB_DIRECT:
|
|
if (!h->col_type_base[h->mbidx]) {
|
|
/* intra MB at co-location, do in-plane prediction */
|
|
if(flags==0) {
|
|
// if col-MB is a Intra MB, current Block size is 16x16.
|
|
// AVS standard section 9.9.1
|
|
if(block>0){
|
|
h->mv[TMP_UNUSED_INX ] = h->mv[MV_FWD_X0 ];
|
|
h->mv[TMP_UNUSED_INX + MV_BWD_OFFS] = h->mv[MV_FWD_X0 + MV_BWD_OFFS];
|
|
}
|
|
ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2,
|
|
MV_PRED_BSKIP, BLK_8X8, 1);
|
|
ff_cavs_mv(h, MV_FWD_X0+MV_BWD_OFFS,
|
|
MV_FWD_C2+MV_BWD_OFFS,
|
|
MV_PRED_BSKIP, BLK_8X8, 0);
|
|
if(block>0) {
|
|
flags = mv_scan[block];
|
|
h->mv[flags ] = h->mv[MV_FWD_X0 ];
|
|
h->mv[flags + MV_BWD_OFFS] = h->mv[MV_FWD_X0 + MV_BWD_OFFS];
|
|
h->mv[MV_FWD_X0 ] = h->mv[TMP_UNUSED_INX ];
|
|
h->mv[MV_FWD_X0 + MV_BWD_OFFS] = h->mv[TMP_UNUSED_INX + MV_BWD_OFFS];
|
|
} else
|
|
flags = MV_FWD_X0;
|
|
} else {
|
|
h->mv[mv_scan[block] ] = h->mv[flags ];
|
|
h->mv[mv_scan[block] + MV_BWD_OFFS] = h->mv[flags + MV_BWD_OFFS];
|
|
}
|
|
} else
|
|
mv_pred_direct(h, &h->mv[mv_scan[block]],
|
|
&h->col_mv[h->mbidx * 4 + block]);
|
|
break;
|
|
case B_SUB_FWD:
|
|
ff_cavs_mv(h, mv_scan[block], mv_scan[block] - 3,
|
|
MV_PRED_MEDIAN, BLK_8X8, 1);
|
|
break;
|
|
case B_SUB_SYM:
|
|
ff_cavs_mv(h, mv_scan[block], mv_scan[block] - 3,
|
|
MV_PRED_MEDIAN, BLK_8X8, 1);
|
|
mv_pred_sym(h, &h->mv[mv_scan[block]], BLK_8X8);
|
|
break;
|
|
}
|
|
}
|
|
#undef TMP_UNUSED_INX
|
|
for (block = 0; block < 4; block++) {
|
|
if (sub_type[block] == B_SUB_BWD)
|
|
ff_cavs_mv(h, mv_scan[block] + MV_BWD_OFFS,
|
|
mv_scan[block] + MV_BWD_OFFS - 3,
|
|
MV_PRED_MEDIAN, BLK_8X8, 0);
|
|
}
|
|
break;
|
|
default:
|
|
if (mb_type <= B_SYM_16X16) {
|
|
av_log(h->avctx, AV_LOG_ERROR, "Invalid mb_type %d in B frame\n", mb_type);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
av_assert2(mb_type < B_8X8);
|
|
flags = ff_cavs_partition_flags[mb_type];
|
|
if (mb_type & 1) { /* 16x8 macroblock types */
|
|
if (flags & FWD0)
|
|
ff_cavs_mv(h, MV_FWD_X0, MV_FWD_C2, MV_PRED_TOP, BLK_16X8, 1);
|
|
if (flags & SYM0)
|
|
mv_pred_sym(h, &h->mv[MV_FWD_X0], BLK_16X8);
|
|
if (flags & FWD1)
|
|
ff_cavs_mv(h, MV_FWD_X2, MV_FWD_A1, MV_PRED_LEFT, BLK_16X8, 1);
|
|
if (flags & SYM1)
|
|
mv_pred_sym(h, &h->mv[MV_FWD_X2], BLK_16X8);
|
|
if (flags & BWD0)
|
|
ff_cavs_mv(h, MV_BWD_X0, MV_BWD_C2, MV_PRED_TOP, BLK_16X8, 0);
|
|
if (flags & BWD1)
|
|
ff_cavs_mv(h, MV_BWD_X2, MV_BWD_A1, MV_PRED_LEFT, BLK_16X8, 0);
|
|
} else { /* 8x16 macroblock types */
|
|
if (flags & FWD0)
|
|
ff_cavs_mv(h, MV_FWD_X0, MV_FWD_B3, MV_PRED_LEFT, BLK_8X16, 1);
|
|
if (flags & SYM0)
|
|
mv_pred_sym(h, &h->mv[MV_FWD_X0], BLK_8X16);
|
|
if (flags & FWD1)
|
|
ff_cavs_mv(h, MV_FWD_X1, MV_FWD_C2, MV_PRED_TOPRIGHT, BLK_8X16, 1);
|
|
if (flags & SYM1)
|
|
mv_pred_sym(h, &h->mv[MV_FWD_X1], BLK_8X16);
|
|
if (flags & BWD0)
|
|
ff_cavs_mv(h, MV_BWD_X0, MV_BWD_B3, MV_PRED_LEFT, BLK_8X16, 0);
|
|
if (flags & BWD1)
|
|
ff_cavs_mv(h, MV_BWD_X1, MV_BWD_C2, MV_PRED_TOPRIGHT, BLK_8X16, 0);
|
|
}
|
|
}
|
|
ff_cavs_inter(h, mb_type);
|
|
set_intra_mode_default(h);
|
|
if (mb_type != B_SKIP)
|
|
decode_residual_inter(h);
|
|
ff_cavs_filter(h, mb_type);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* slice level
|
|
*
|
|
****************************************************************************/
|
|
|
|
static inline int decode_slice_header(AVSContext *h, GetBitContext *gb)
|
|
{
|
|
if (h->stc > 0xAF)
|
|
av_log(h->avctx, AV_LOG_ERROR, "unexpected start code 0x%02x\n", h->stc);
|
|
|
|
if (h->stc >= h->mb_height) {
|
|
av_log(h->avctx, AV_LOG_ERROR, "stc 0x%02x is too large\n", h->stc);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
h->mby = h->stc;
|
|
h->mbidx = h->mby * h->mb_width;
|
|
|
|
/* mark top macroblocks as unavailable */
|
|
h->flags &= ~(B_AVAIL | C_AVAIL);
|
|
if (!h->pic_qp_fixed) {
|
|
h->qp_fixed = get_bits1(gb);
|
|
h->qp = get_bits(gb, 6);
|
|
}
|
|
/* inter frame or second slice can have weighting params */
|
|
if ((h->cur.f->pict_type != AV_PICTURE_TYPE_I) ||
|
|
(!h->pic_structure && h->mby >= h->mb_width / 2))
|
|
if (get_bits1(gb)) { //slice_weighting_flag
|
|
av_log(h->avctx, AV_LOG_ERROR,
|
|
"weighted prediction not yet supported\n");
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static inline int check_for_slice(AVSContext *h)
|
|
{
|
|
GetBitContext *gb = &h->gb;
|
|
int align;
|
|
|
|
if (h->mbx)
|
|
return 0;
|
|
align = (-get_bits_count(gb)) & 7;
|
|
/* check for stuffing byte */
|
|
if (!align && (show_bits(gb, 8) == 0x80))
|
|
align = 8;
|
|
if ((show_bits_long(gb, 24 + align) & 0xFFFFFF) == 0x000001) {
|
|
skip_bits_long(gb, 24 + align);
|
|
h->stc = get_bits(gb, 8);
|
|
if (h->stc >= h->mb_height)
|
|
return 0;
|
|
decode_slice_header(h, gb);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* frame level
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int decode_pic(AVSContext *h)
|
|
{
|
|
int ret;
|
|
int skip_count = -1;
|
|
enum cavs_mb mb_type;
|
|
|
|
if (!h->top_qp) {
|
|
av_log(h->avctx, AV_LOG_ERROR, "No sequence header decoded yet\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
|
|
av_frame_unref(h->cur.f);
|
|
|
|
skip_bits(&h->gb, 16);//bbv_dwlay
|
|
if (h->stc == PIC_PB_START_CODE) {
|
|
h->cur.f->pict_type = get_bits(&h->gb, 2) + AV_PICTURE_TYPE_I;
|
|
if (h->cur.f->pict_type > AV_PICTURE_TYPE_B) {
|
|
av_log(h->avctx, AV_LOG_ERROR, "illegal picture type\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
/* make sure we have the reference frames we need */
|
|
if (!h->DPB[0].f->data[0] ||
|
|
(!h->DPB[1].f->data[0] && h->cur.f->pict_type == AV_PICTURE_TYPE_B))
|
|
return AVERROR_INVALIDDATA;
|
|
} else {
|
|
h->cur.f->pict_type = AV_PICTURE_TYPE_I;
|
|
if (get_bits1(&h->gb))
|
|
skip_bits(&h->gb, 24);//time_code
|
|
/* old sample clips were all progressive and no low_delay,
|
|
bump stream revision if detected otherwise */
|
|
if (h->low_delay || !(show_bits(&h->gb, 9) & 1))
|
|
h->stream_revision = 1;
|
|
/* similarly test top_field_first and repeat_first_field */
|
|
else if (show_bits(&h->gb, 11) & 3)
|
|
h->stream_revision = 1;
|
|
if (h->stream_revision > 0)
|
|
skip_bits(&h->gb, 1); //marker_bit
|
|
}
|
|
|
|
ret = ff_get_buffer(h->avctx, h->cur.f, h->cur.f->pict_type == AV_PICTURE_TYPE_B ?
|
|
0 : AV_GET_BUFFER_FLAG_REF);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
if (!h->edge_emu_buffer) {
|
|
int alloc_size = FFALIGN(FFABS(h->cur.f->linesize[0]) + 32, 32);
|
|
h->edge_emu_buffer = av_mallocz(alloc_size * 2 * 24);
|
|
if (!h->edge_emu_buffer)
|
|
return AVERROR(ENOMEM);
|
|
}
|
|
|
|
if ((ret = ff_cavs_init_pic(h)) < 0)
|
|
return ret;
|
|
h->cur.poc = get_bits(&h->gb, 8) * 2;
|
|
|
|
/* get temporal distances and MV scaling factors */
|
|
if (h->cur.f->pict_type != AV_PICTURE_TYPE_B) {
|
|
h->dist[0] = (h->cur.poc - h->DPB[0].poc) & 511;
|
|
} else {
|
|
h->dist[0] = (h->DPB[0].poc - h->cur.poc) & 511;
|
|
}
|
|
h->dist[1] = (h->cur.poc - h->DPB[1].poc) & 511;
|
|
h->scale_den[0] = h->dist[0] ? 512/h->dist[0] : 0;
|
|
h->scale_den[1] = h->dist[1] ? 512/h->dist[1] : 0;
|
|
if (h->cur.f->pict_type == AV_PICTURE_TYPE_B) {
|
|
h->sym_factor = h->dist[0] * h->scale_den[1];
|
|
if (FFABS(h->sym_factor) > 32768) {
|
|
av_log(h->avctx, AV_LOG_ERROR, "sym_factor %d too large\n", h->sym_factor);
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
} else {
|
|
h->direct_den[0] = h->dist[0] ? 16384 / h->dist[0] : 0;
|
|
h->direct_den[1] = h->dist[1] ? 16384 / h->dist[1] : 0;
|
|
}
|
|
|
|
if (h->low_delay)
|
|
get_ue_golomb(&h->gb); //bbv_check_times
|
|
h->progressive = get_bits1(&h->gb);
|
|
h->pic_structure = 1;
|
|
if (!h->progressive)
|
|
h->pic_structure = get_bits1(&h->gb);
|
|
if (!h->pic_structure && h->stc == PIC_PB_START_CODE)
|
|
skip_bits1(&h->gb); //advanced_pred_mode_disable
|
|
skip_bits1(&h->gb); //top_field_first
|
|
skip_bits1(&h->gb); //repeat_first_field
|
|
h->pic_qp_fixed =
|
|
h->qp_fixed = get_bits1(&h->gb);
|
|
h->qp = get_bits(&h->gb, 6);
|
|
if (h->cur.f->pict_type == AV_PICTURE_TYPE_I) {
|
|
if (!h->progressive && !h->pic_structure)
|
|
skip_bits1(&h->gb);//what is this?
|
|
skip_bits(&h->gb, 4); //reserved bits
|
|
} else {
|
|
if (!(h->cur.f->pict_type == AV_PICTURE_TYPE_B && h->pic_structure == 1))
|
|
h->ref_flag = get_bits1(&h->gb);
|
|
skip_bits(&h->gb, 4); //reserved bits
|
|
h->skip_mode_flag = get_bits1(&h->gb);
|
|
}
|
|
h->loop_filter_disable = get_bits1(&h->gb);
|
|
if (!h->loop_filter_disable && get_bits1(&h->gb)) {
|
|
h->alpha_offset = get_se_golomb(&h->gb);
|
|
h->beta_offset = get_se_golomb(&h->gb);
|
|
if ( h->alpha_offset < -64 || h->alpha_offset > 64
|
|
|| h-> beta_offset < -64 || h-> beta_offset > 64) {
|
|
h->alpha_offset = h->beta_offset = 0;
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
} else {
|
|
h->alpha_offset = h->beta_offset = 0;
|
|
}
|
|
|
|
ret = 0;
|
|
if (h->cur.f->pict_type == AV_PICTURE_TYPE_I) {
|
|
do {
|
|
check_for_slice(h);
|
|
ret = decode_mb_i(h, 0);
|
|
if (ret < 0)
|
|
break;
|
|
} while (ff_cavs_next_mb(h));
|
|
} else if (h->cur.f->pict_type == AV_PICTURE_TYPE_P) {
|
|
do {
|
|
if (check_for_slice(h))
|
|
skip_count = -1;
|
|
if (h->skip_mode_flag && (skip_count < 0)) {
|
|
if (get_bits_left(&h->gb) < 1) {
|
|
ret = AVERROR_INVALIDDATA;
|
|
break;
|
|
}
|
|
skip_count = get_ue_golomb(&h->gb);
|
|
}
|
|
if (h->skip_mode_flag && skip_count--) {
|
|
decode_mb_p(h, P_SKIP);
|
|
} else {
|
|
if (get_bits_left(&h->gb) < 1) {
|
|
ret = AVERROR_INVALIDDATA;
|
|
break;
|
|
}
|
|
mb_type = get_ue_golomb(&h->gb) + P_SKIP + h->skip_mode_flag;
|
|
if (mb_type > P_8X8)
|
|
ret = decode_mb_i(h, mb_type - P_8X8 - 1);
|
|
else
|
|
decode_mb_p(h, mb_type);
|
|
}
|
|
if (ret < 0)
|
|
break;
|
|
} while (ff_cavs_next_mb(h));
|
|
} else { /* AV_PICTURE_TYPE_B */
|
|
do {
|
|
if (check_for_slice(h))
|
|
skip_count = -1;
|
|
if (h->skip_mode_flag && (skip_count < 0)) {
|
|
if (get_bits_left(&h->gb) < 1) {
|
|
ret = AVERROR_INVALIDDATA;
|
|
break;
|
|
}
|
|
skip_count = get_ue_golomb(&h->gb);
|
|
}
|
|
if (h->skip_mode_flag && skip_count--) {
|
|
ret = decode_mb_b(h, B_SKIP);
|
|
} else {
|
|
if (get_bits_left(&h->gb) < 1) {
|
|
ret = AVERROR_INVALIDDATA;
|
|
break;
|
|
}
|
|
mb_type = get_ue_golomb(&h->gb) + B_SKIP + h->skip_mode_flag;
|
|
if (mb_type > B_8X8)
|
|
ret = decode_mb_i(h, mb_type - B_8X8 - 1);
|
|
else
|
|
ret = decode_mb_b(h, mb_type);
|
|
}
|
|
if (ret < 0)
|
|
break;
|
|
} while (ff_cavs_next_mb(h));
|
|
}
|
|
emms_c();
|
|
if (ret >= 0 && h->cur.f->pict_type != AV_PICTURE_TYPE_B) {
|
|
av_frame_unref(h->DPB[1].f);
|
|
FFSWAP(AVSFrame, h->cur, h->DPB[1]);
|
|
FFSWAP(AVSFrame, h->DPB[0], h->DPB[1]);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* headers and interface
|
|
*
|
|
****************************************************************************/
|
|
|
|
static int decode_seq_header(AVSContext *h)
|
|
{
|
|
int frame_rate_code;
|
|
int width, height;
|
|
int ret;
|
|
|
|
h->profile = get_bits(&h->gb, 8);
|
|
h->level = get_bits(&h->gb, 8);
|
|
skip_bits1(&h->gb); //progressive sequence
|
|
|
|
width = get_bits(&h->gb, 14);
|
|
height = get_bits(&h->gb, 14);
|
|
if ((h->width || h->height) && (h->width != width || h->height != height)) {
|
|
avpriv_report_missing_feature(h->avctx,
|
|
"Width/height changing in CAVS");
|
|
return AVERROR_PATCHWELCOME;
|
|
}
|
|
if (width <= 0 || height <= 0) {
|
|
av_log(h->avctx, AV_LOG_ERROR, "Dimensions invalid\n");
|
|
return AVERROR_INVALIDDATA;
|
|
}
|
|
skip_bits(&h->gb, 2); //chroma format
|
|
skip_bits(&h->gb, 3); //sample_precision
|
|
h->aspect_ratio = get_bits(&h->gb, 4);
|
|
frame_rate_code = get_bits(&h->gb, 4);
|
|
if (frame_rate_code == 0 || frame_rate_code > 13) {
|
|
av_log(h->avctx, AV_LOG_WARNING,
|
|
"frame_rate_code %d is invalid\n", frame_rate_code);
|
|
frame_rate_code = 1;
|
|
}
|
|
|
|
skip_bits(&h->gb, 18); //bit_rate_lower
|
|
skip_bits1(&h->gb); //marker_bit
|
|
skip_bits(&h->gb, 12); //bit_rate_upper
|
|
h->low_delay = get_bits1(&h->gb);
|
|
|
|
ret = ff_set_dimensions(h->avctx, width, height);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
h->width = width;
|
|
h->height = height;
|
|
h->mb_width = (h->width + 15) >> 4;
|
|
h->mb_height = (h->height + 15) >> 4;
|
|
h->avctx->framerate = ff_mpeg12_frame_rate_tab[frame_rate_code];
|
|
if (!h->top_qp)
|
|
return ff_cavs_init_top_lines(h);
|
|
return 0;
|
|
}
|
|
|
|
static void cavs_flush(AVCodecContext * avctx)
|
|
{
|
|
AVSContext *h = avctx->priv_data;
|
|
h->got_keyframe = 0;
|
|
}
|
|
|
|
static int cavs_decode_frame(AVCodecContext *avctx, AVFrame *rframe,
|
|
int *got_frame, AVPacket *avpkt)
|
|
{
|
|
AVSContext *h = avctx->priv_data;
|
|
const uint8_t *buf = avpkt->data;
|
|
int buf_size = avpkt->size;
|
|
uint32_t stc = -1;
|
|
int input_size, ret;
|
|
const uint8_t *buf_end;
|
|
const uint8_t *buf_ptr;
|
|
int frame_start = 0;
|
|
|
|
if (buf_size == 0) {
|
|
if (!h->low_delay && h->DPB[0].f->data[0]) {
|
|
*got_frame = 1;
|
|
av_frame_move_ref(rframe, h->DPB[0].f);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
h->stc = 0;
|
|
|
|
buf_ptr = buf;
|
|
buf_end = buf + buf_size;
|
|
for(;;) {
|
|
buf_ptr = avpriv_find_start_code(buf_ptr, buf_end, &stc);
|
|
if ((stc & 0xFFFFFE00) || buf_ptr == buf_end) {
|
|
if (!h->stc)
|
|
av_log(h->avctx, AV_LOG_WARNING, "no frame decoded\n");
|
|
return FFMAX(0, buf_ptr - buf);
|
|
}
|
|
input_size = (buf_end - buf_ptr) * 8;
|
|
switch (stc) {
|
|
case CAVS_START_CODE:
|
|
init_get_bits(&h->gb, buf_ptr, input_size);
|
|
decode_seq_header(h);
|
|
break;
|
|
case PIC_I_START_CODE:
|
|
if (!h->got_keyframe) {
|
|
av_frame_unref(h->DPB[0].f);
|
|
av_frame_unref(h->DPB[1].f);
|
|
h->got_keyframe = 1;
|
|
}
|
|
case PIC_PB_START_CODE:
|
|
if (frame_start > 1)
|
|
return AVERROR_INVALIDDATA;
|
|
frame_start ++;
|
|
if (*got_frame)
|
|
av_frame_unref(rframe);
|
|
*got_frame = 0;
|
|
if (!h->got_keyframe)
|
|
break;
|
|
init_get_bits(&h->gb, buf_ptr, input_size);
|
|
h->stc = stc;
|
|
if (decode_pic(h))
|
|
break;
|
|
*got_frame = 1;
|
|
if (h->cur.f->pict_type != AV_PICTURE_TYPE_B) {
|
|
if (h->DPB[!h->low_delay].f->data[0]) {
|
|
if ((ret = av_frame_ref(rframe, h->DPB[!h->low_delay].f)) < 0)
|
|
return ret;
|
|
} else {
|
|
*got_frame = 0;
|
|
}
|
|
} else {
|
|
av_frame_move_ref(rframe, h->cur.f);
|
|
}
|
|
break;
|
|
case EXT_START_CODE:
|
|
//mpeg_decode_extension(avctx, buf_ptr, input_size);
|
|
break;
|
|
case USER_START_CODE:
|
|
//mpeg_decode_user_data(avctx, buf_ptr, input_size);
|
|
break;
|
|
default:
|
|
if (stc <= SLICE_MAX_START_CODE) {
|
|
init_get_bits(&h->gb, buf_ptr, input_size);
|
|
decode_slice_header(h, &h->gb);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
const FFCodec ff_cavs_decoder = {
|
|
.p.name = "cavs",
|
|
.p.long_name = NULL_IF_CONFIG_SMALL("Chinese AVS (Audio Video Standard) (AVS1-P2, JiZhun profile)"),
|
|
.p.type = AVMEDIA_TYPE_VIDEO,
|
|
.p.id = AV_CODEC_ID_CAVS,
|
|
.priv_data_size = sizeof(AVSContext),
|
|
.init = ff_cavs_init,
|
|
.close = ff_cavs_end,
|
|
FF_CODEC_DECODE_CB(cavs_decode_frame),
|
|
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
|
|
.flush = cavs_flush,
|
|
.caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_INIT_CLEANUP,
|
|
};
|