www.pudn.com > p264decoder.zip > dec_cavlc.c
/***************************************************************************** * dec_cavlc.c: h264 decoder library ***************************************************************************** * Copyright (C) 2005 p264 project * $Id: $ * * Authors: Peter Lee (lspbeyond@126.com) * 2005-2006 at icas of Ningbo university, China * p264 Decoder site: http://p264decoder.zj.com * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/ #include#include #include #include "core/core.h" #include "dec_cavlc.h" typedef struct { uint8_t len; uint8_t trailing_ones; uint8_t total_coeff; } vlc_coeff_token_t; #define VLC(a, b, c) {a, b, c} #define VLC2(a, b, c) VLC(a, b, c), VLC(a, b, c) #define VLC4(a, b, c) VLC2(a, b, c), VLC2(a, b, c) /* ++ cavlc tables ++ */ static const vlc_coeff_token_t coeff4_0[] = { VLC(6, 0, 2), /* 0001 00 */ VLC(6, 3, 3), /* 0001 01 */ VLC(6, 1, 2), /* 0001 10 */ VLC(6, 0, 1), /* 0001 11 */ }; static const vlc_coeff_token_t coeff4_1[] = { VLC2(7, 3, 4), /* 0000 000(0) */ VLC(8, 2, 4), /* 0000 0010 */ VLC(8, 1, 4), /* 0000 0011 */ VLC2(7, 2, 3), /* 0000 010(0) */ VLC2(7, 1, 3), /* 0000 011(0) */ VLC4(6, 0, 4), /* 0000 10(00) */ VLC4(6, 0, 3), /* 0000 11(00) */ }; static const vlc_coeff_token_t coeff3_0[] = { VLC(6, 0, 1), /* 0000 00 */ VLC(6, 1, 1), /* 0000 01 */ VLC(-1, -1, -1), /* 0000 10 */ VLC(6, 0, 0), /* 0000 11 */ VLC(6, 0, 2), /* 0001 00 */ VLC(6, 1, 2), /* 0001 01 */ VLC(6, 2, 2), /* 0001 10 */ VLC(-1, -1, -1), /* 0001 11 */ VLC(6, 0, 3), /* 0010 00 */ VLC(6, 1, 3), /* 0010 01 */ VLC(6, 2, 3), /* 0010 10 */ VLC(6, 3, 3), /* 0010 11 */ VLC(6, 0, 4), /* 0011 00 */ VLC(6, 1, 4), /* 0011 01 */ VLC(6, 2, 4), /* 0011 10 */ VLC(6, 3, 4), /* 0011 11 */ VLC(6, 0, 5), /* 0100 00 */ VLC(6, 1, 5), /* 0100 01 */ VLC(6, 2, 5), /* 0100 10 */ VLC(6, 3, 5), /* 0100 11 */ VLC(6, 0, 6), /* 0101 00 */ VLC(6, 1, 6), /* 0101 01 */ VLC(6, 2, 6), /* 0101 10 */ VLC(6, 3, 6), /* 0101 11 */ VLC(6, 0, 7), /* 0110 00 */ VLC(6, 1, 7), /* 0110 01 */ VLC(6, 2, 7), /* 0110 10 */ VLC(6, 3, 7), /* 0110 11 */ VLC(6, 0, 8), VLC(6, 1, 8), VLC(6, 2, 8), VLC(6, 3, 8), VLC(6, 0, 9), VLC(6, 1, 9), VLC(6, 2, 9), VLC(6, 3, 9), VLC(6, 0, 10), VLC(6, 1, 10), VLC(6, 2, 10), VLC(6, 3, 10), VLC(6, 0, 11), VLC(6, 1, 11), VLC(6, 2, 11), VLC(6, 3, 11), VLC(6, 0, 12), VLC(6, 1, 12), VLC(6, 2, 12), VLC(6, 3, 12), VLC(6, 0, 13), VLC(6, 1, 13), VLC(6, 2, 13), VLC(6, 3, 13), VLC(6, 0, 14), VLC(6, 1, 14), VLC(6, 2, 14), VLC(6, 3, 14), VLC(6, 0, 15), VLC(6, 1, 15), VLC(6, 2, 15), VLC(6, 3, 15), VLC(6, 0, 16), VLC(6, 1, 16), VLC(6, 2, 16), VLC(6, 3, 16) }; static const vlc_coeff_token_t coeff2_0[] = { VLC(4, 3, 7), /* 1000 */ VLC(4, 3, 6), /* 1001 */ VLC(4, 3, 5), /* 1010 */ VLC(4, 3, 4), /* 1011 */ VLC(4, 3, 3), /* 1100 */ VLC(4, 2, 2), /* 1101 */ VLC(4, 1, 1), /* 1110 */ VLC(4, 0, 0), /* 1111 */ }; static const vlc_coeff_token_t coeff2_1[] = { VLC(5, 1, 5), /* 0100 0 */ VLC(5, 2, 5), VLC(5, 1, 4), VLC(5, 2, 4), VLC(5, 1, 3), VLC(5, 3, 8), VLC(5, 2, 3), VLC(5, 1, 2), }; static const vlc_coeff_token_t coeff2_2[] = { VLC(6, 0, 3), /* 0010 00 */ VLC(6, 2, 7), VLC(6, 1, 7), VLC(6, 0, 2), VLC(6, 3, 9), VLC(6, 2, 6), VLC(6, 1, 6), VLC(6, 0, 1), }; static const vlc_coeff_token_t coeff2_3[] = { VLC(7, 0, 7), /* 0001 000 */ VLC(7, 0, 6), VLC(7, 2, 9), VLC(7, 0, 5), VLC(7, 3, 10), VLC(7, 2, 8), VLC(7, 1, 8), VLC(7, 0, 4), }; static const vlc_coeff_token_t coeff2_4[] = { VLC(8, 3, 12), /* 0000 1000 */ VLC(8, 2, 11), VLC(8, 1, 10), VLC(8, 0, 9), VLC(8, 3, 11), VLC(8, 2, 10), VLC(8, 1, 9), VLC(8, 0, 8), }; static const vlc_coeff_token_t coeff2_5[] = { VLC(9, 0, 12), /* 0000 0100 0 */ VLC(9, 2, 13), VLC(9, 1, 12), VLC(9, 0, 11), VLC(9, 3, 13), VLC(9, 2, 12), VLC(9, 1, 11), VLC(9, 0, 10), }; static const vlc_coeff_token_t coeff2_6[] = { VLC(-1, -1, -1), /* 0000 0000 00 */ VLC(10, 0, 16), /* 0000 0000 01 */ VLC(10, 3, 16), /* 0000 0000 10 */ VLC(10, 2, 16), /* 0000 0000 11 */ VLC(10, 1, 16), /* 0000 0001 00 */ VLC(10, 0, 15), /* 0000 0001 01 */ VLC(10, 3, 15), /* 0000 0001 10 */ VLC(10, 2, 15), /* 0000 0001 11 */ VLC(10, 1, 15), /* 0000 0010 00 */ VLC(10, 0, 14), VLC(10, 3, 14), VLC(10, 2, 14), VLC(10, 1, 14), VLC(10, 0, 13), VLC2(9, 1, 13), /* 0000 0011 1(0) */ }; static const vlc_coeff_token_t coeff1_0[] = { VLC(4, 3, 4), /* 0100 */ VLC(4, 3, 3), /* 0101 */ VLC2(3, 2, 2), /* 011(0) */ VLC4(2, 1, 1), /* 10 */ VLC4(2, 0, 0), /* 11 */ }; static const vlc_coeff_token_t coeff1_1[] = { VLC(6, 3, 7), /* 0001 00 */ VLC(6, 2, 4), /* 0001 01 */ VLC(6, 1, 4), /* 0001 10 */ VLC(6, 0, 2), /* 0001 11 */ VLC(6, 3, 6), /* 0010 00 */ VLC(6, 2, 3), /* 0010 01 */ VLC(6, 1, 3), /* 0010 10 */ VLC(6, 0, 1), /* 0010 11*/ VLC2(5, 3, 5), /* 0011 0(0)*/ VLC2(5, 1, 2), /* 0011 1(0)*/ }; static const vlc_coeff_token_t coeff1_2[] = { VLC(9, 3, 9), /* 0000 0010 0 */ VLC(9, 2, 7), /* 0000 0010 1 */ VLC(9, 1, 7), /* 0000 0011 0 */ VLC(9, 0, 6), /* 0000 0011 1 */ VLC2(8, 0, 5), /* 0000 0100 */ VLC2(8, 2, 6), /* 0000 0101 */ VLC2(8, 1, 6), /* 0000 0110 */ VLC2(8, 0, 4), /* 0000 0111 */ VLC4(7, 3, 8), /* 0000 100 */ VLC4(7, 2, 5), /* 0000 101 */ VLC4(7, 1, 5), /* 0000 110 */ VLC4(7, 0, 3), /* 0000 111 */ }; static const vlc_coeff_token_t coeff1_3[] = { VLC(11, 3, 11), /* 0000 0001 000 */ VLC(11, 2, 9), /* 0000 0001 001 */ VLC(11, 1, 9), /* 0000 0001 010 */ VLC(11, 0, 8), /* 0000 0001 011 */ VLC(11, 3, 10), /* 0000 0001 100 */ VLC(11, 2, 8), /* 0000 0001 101 */ VLC(11, 1, 8), /* 0000 0001 110 */ VLC(11, 0, 7), /* 0000 0001 111 */ }; static const vlc_coeff_token_t coeff1_4[] = { VLC(12, 0, 11), /* 0000 0000 1000 */ VLC(12, 2, 11), /* 0000 0000 1001 */ VLC(12, 1, 11), /* 0000 0000 1010 */ VLC(12, 0, 10), /* 0000 0000 1011 */ VLC(12, 3, 12), /* 0000 0000 1100 */ VLC(12, 2, 10), /* 0000 0000 1101 */ VLC(12, 1, 10), /* 0000 0000 1110 */ VLC(12, 0, 9), /* 0000 0000 1111 */ }; static const vlc_coeff_token_t coeff1_5[] = { VLC(13, 3, 14), /* 0000 0000 0100 0 */ VLC(13, 2, 13), /* 0000 0000 0100 1 */ VLC(13, 1, 13), /* 0000 0000 0101 0 */ VLC(13, 0, 13), /* 0000 0000 0101 1 */ VLC(13, 3, 13), /* 0000 0000 0110 0 */ VLC(13, 2, 12), /* 0000 0000 0110 1 */ VLC(13, 1, 12), /* 0000 0000 0111 0 */ VLC(13, 0, 12), /* 0000 0000 0111 1 */ }; static const vlc_coeff_token_t coeff1_6[] = { VLC2(-1, -1, -1), /* 0000 0000 0000 00 */ VLC2(13, 3, 15), /* 0000 0000 0000 1(0) */ VLC(14, 3, 16), /* 0000 0000 0001 00 */ VLC(14, 2, 16), /* 0000 0000 0001 01 */ VLC(14, 1, 16), /* 0000 0000 0001 10 */ VLC(14, 0, 16), /* 0000 0000 0001 11 */ VLC(14, 1, 15), /* 0000 0000 0010 00 */ VLC(14, 0, 15), /* 0000 0000 0010 01 */ VLC(14, 2, 15), /* 0000 0000 0010 10 */ VLC(14, 1, 14), /* 0000 0000 0010 11 */ VLC2(13, 2, 14), /* 0000 0000 0011 0(0) */ VLC2(13, 0, 14), /* 0000 0000 0011 1(0) */ }; static const vlc_coeff_token_t coeff0_0[] = { VLC2(-1, -1, -1), /* 0000 0000 0000 000(0) */ VLC2(15, 1, 13), /* 0000 0000 0000 001(0) */ VLC(16, 0, 16), /* 0000 0000 0000 0100 */ VLC(16, 2, 16), VLC(16, 1, 16), VLC(16, 0, 15), VLC(16, 3, 16), VLC(16, 2, 15), VLC(16, 1, 15), VLC(16, 0, 14), VLC(16, 3, 15), VLC(16, 2, 14), VLC(16, 1, 14), VLC(16, 0, 13), /* 0000 0000 0000 1111 */ VLC2(15, 3, 14), /* 0000 0000 0001 000(0) */ VLC2(15, 2, 13), VLC2(15, 1, 12), VLC2(15, 0, 12), VLC2(15, 3, 13), VLC2(15, 2, 12), VLC2(15, 1, 11), VLC2(15, 0, 11), /* 0000 0000 0001 111(0) */ VLC4(14, 3, 12), /* 0000 0000 0010 00(00) */ VLC4(14, 2, 11), VLC4(14, 1, 10), VLC4(14, 0, 10), VLC4(14, 3, 11), VLC4(14, 2, 10), VLC4(14, 1, 9), VLC4(14, 0, 9), /* 0000 0000 0011 11(00) */ }; static const vlc_coeff_token_t coeff0_1[] = { VLC(13, 0, 8), /* 0000 0000 0100 0 */ VLC(13, 2, 9), VLC(13, 1, 8), VLC(13, 0, 7), VLC(13, 3, 10), VLC(13, 2, 8), VLC(13, 1, 7), VLC(13, 0, 6), /* 0000 0000 0111 1 */ }; static const vlc_coeff_token_t coeff0_2[] = { VLC(11, 3, 9), /* 0000 0000 100 */ VLC(11, 2, 7), VLC(11, 1, 6), VLC(11, 0, 5), /* 0000 0000 111 */ VLC2(10, 3, 8), /* 0000 0001 00(0) */ VLC2(10, 2, 6), VLC2(10, 1, 5), VLC2(10, 0, 4), /* 0000 0001 11(0) */ VLC4(9, 3, 7), /* 0000 0010 0(0) */ VLC4(9, 2, 5), VLC4(9, 1, 4), VLC4(9, 0, 3), /* 0000 0011 1(0) */ }; static const vlc_coeff_token_t coeff0_3[] = { VLC(8, 3, 6), /* 0000 0100 */ VLC(8, 2, 4), VLC(8, 1, 3), VLC(8, 0, 2), VLC2(7, 3, 5), /* 0000 100 */ VLC2(7, 2, 3), VLC4(6, 3, 4), /* 0000 11 */ }; static const vlc_coeff_token_t coeff0_4[] = { VLC(6, 1, 2), /* 0001 00 */ VLC(6, 0, 1), /* 0001 01 */ VLC2(5, 3, 3) /* 0001 1 */ }; static const vlc_coeff_token_t coeff0_5[] = { VLC(-1, -1, -1), /* 000 */ VLC(3, 2, 2), /* 001 */ VLC2(2, 1, 1), /* 01 */ VLC4(1, 0, 0) /* 1 */ }; static const uint8_t prefix_table0[] = { -1, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; static const uint8_t prefix_table1[] = { -1, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4 }; static const uint8_t prefix_table2[] = { -1, 11, 10, 10, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8 }; static const uint8_t prefix_table3[] = { -1, 15, 14, 14, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12 }; #undef VLC #undef VLC2 #undef VLC4 #define VLC(a, b) {a, b} #define VLC2(a, b) VLC(a, b), VLC(a, b) #define VLC4(a, b) VLC2(a, b), VLC2(a, b) #define VLC8(a, b) VLC4(a, b), VLC4(a, b) typedef struct { uint8_t num; uint8_t len; } zero_count_t; static const zero_count_t total_zero_table1_0[] = { VLC(-1, -1), VLC(15, 9), /* 0000 0000 1 */ VLC(14, 9), VLC(13, 9), /* 0000 0001 1 */ VLC2(12, 8),/* 0000 0010 */ VLC2(11, 8),/* 0000 0011 */ VLC4(10, 7),/* 0000 010 */ VLC4(9, 7), /* 0000 011 */ VLC8(8, 6), /* 0000 10 */ VLC8(7, 6), /* 0000 11 */ }; static const zero_count_t total_zero_table1_1[] = { VLC2(-1, -1), VLC(6, 5), /* 0001 0 */ VLC(5, 5), /* 0001 1 */ VLC2(4, 4),/* 0010 */ VLC2(3, 4),/* 0011 */ VLC4(2, 3),/* 010 */ VLC4(1, 3),/* 011 */ VLC8(0, 1), /*1 */ VLC8(0, 1), /*1 */ }; static const zero_count_t total_zero_table2_0[] = { VLC(14, 6), /* 0000 00 */ VLC(13, 6), VLC(12, 6), VLC(11, 6), VLC2(10, 5),/* 0001 0 */ VLC2(9, 5), }; static const zero_count_t total_zero_table2_1[] = { VLC2(-1, -1), VLC(8, 4), /* 0010 */ VLC(7, 4), /* 0011 */ VLC(6, 4), VLC(5, 4), VLC2(4, 3),/* 011 */ VLC2(3, 3),/* 100 */ VLC2(2, 3), /*101 */ VLC2(1, 3), /*110 */ VLC2(0, 3), /*111 */ }; static const zero_count_t total_zero_table3_0[] = { VLC(13, 6), /* 0000 00 */ VLC(11, 6), VLC2(12, 5),/* 0000 1 */ VLC2(10, 5),/* 0001 0 */ VLC2(9, 5), /* 0001 1 */ }; static const zero_count_t total_zero_table3_1[] = { VLC2(-1, -1), VLC(8, 4), /* 0010 */ VLC(5, 4), /* 0011 */ VLC(4, 4), VLC(0, 4), VLC2(7, 3),/* 011 */ VLC2(6, 3),/* 100 */ VLC2(3, 3), /*101 */ VLC2(2, 3), /*110 */ VLC2(1, 3), /*111 */ }; static const zero_count_t total_zero_table6_0[] = { VLC(10, 6), /* 0000 00 */ VLC(0, 6), VLC2(1, 5),/* 0000 1 */ VLC4(8, 4),/* 0000 1 */ }; static const zero_count_t total_zero_table6_1[] = { VLC(-1, -1), VLC(9, 3), /* 001 */ VLC(7, 3), /* 010 */ VLC(6, 3), VLC(5, 3), VLC(4, 3), VLC(3, 3), VLC(2, 3) }; static const zero_count_t total_zero_table7_0[] = { VLC(9, 6), /* 0000 00 */ VLC(0, 6), VLC2(1, 5),/* 0000 1 */ VLC4(7, 4),/* 0001 */ }; static const zero_count_t total_zero_table7_1[] = { VLC(-1, -1), VLC(8, 3), /* 001 */ VLC(6, 3), /* 010 */ VLC(4, 3), VLC(3, 3), VLC(2, 3), VLC2(5, 2) }; static const zero_count_t total_zero_table8_0[] = { VLC(8, 6), /* 0000 00 */ VLC(0, 6), VLC2(2, 5),/* 0000 1 */ VLC4(1, 4),/* 0001 */ }; static const zero_count_t total_zero_table8_1[] = { VLC(-1, -1), VLC(7, 3), /* 001 */ VLC(6, 3), /* 010 */ VLC(3, 3), VLC2(5, 2), VLC2(4, 2) }; static const zero_count_t total_zero_table9_0[] = { VLC(1, 6), /* 0000 00 */ VLC(0, 6), VLC2(7, 5),/* 0000 1 */ VLC4(2, 4),/* 0001 */ }; static const zero_count_t total_zero_table9_1[] = { VLC(-1, -1), VLC(5, 3), /* 001 */ VLC2(6, 2), /* 01 */ VLC2(4, 2), VLC2(3, 2), }; static const zero_count_t total_zero_table4_0[] = { VLC(12, 5), /* 0000 0 */ VLC(11, 5), VLC(10, 5), /* 0000 1 */ VLC(0, 5), /* 0001 1 */ VLC2(9, 4), /* 0010 */ VLC2(7, 4), VLC2(3, 4), VLC2(2, 4), /* 0101 */ VLC4(8, 3), /* 011 */ }; static const zero_count_t total_zero_table4_1[] = { VLC(6, 3), /* 100 */ VLC(5, 3), /* 101 */ VLC(4, 3), /* 110 */ VLC(1, 3) /* 111 */ }; static const zero_count_t total_zero_table5_0[] = { VLC(11, 5), /* 0000 0 */ VLC(9, 5), VLC2(10, 4), /* 0000 1 */ VLC2(8, 4), /* 0010 */ VLC2(2, 4), VLC2(1, 4), VLC2(0, 4), VLC4(7, 3) }; static const zero_count_t total_zero_table5_1[] = { VLC(6, 3), /* 100 */ VLC(5, 3), VLC(4, 3), VLC(3, 3) }; static const zero_count_t total_zero_table10_0[] = { VLC(1, 5), /* 0000 0 */ VLC(0, 5), VLC2(6, 4), /* 0000 1 */ }; static const zero_count_t total_zero_table10_1[] = { VLC(-1, -1), VLC(2, 3), /* 001 */ VLC2(5, 2), /* 01 */ VLC2(4, 2), VLC2(3, 2), }; static const zero_count_t total_zero_table11_0[] = { VLC(0, 4), /* 0000 */ VLC(1, 4), VLC2(2, 3), /* 010 */ VLC2(3, 3), VLC2(5, 3), VLC8(4, 1) }; static const zero_count_t total_zero_table12_0[] = { VLC(0, 4), /* 0000 */ VLC(1, 4), VLC2(4, 3), /* 010 */ VLC4(2, 2), VLC8(3, 1) }; static const zero_count_t total_zero_table13_0[] = { VLC(0, 3), /* 000 */ VLC(1, 3), VLC2(3, 2), /* 01 */ VLC4(2, 1), }; static const zero_count_t total_zero_table14_0[] = { VLC(0, 2), VLC(1, 2), VLC2(2, 1), }; static const zero_count_t total_zero_table_chroma[3][8] = { { VLC(3, 3), VLC(2, 3), VLC2(1, 2), VLC4(0, 1) }, { VLC2(2, 2), VLC2(1, 2), VLC4(0, 1) }, { VLC4(1, 1), VLC4(0, 1) } }; static const zero_count_t run_before_table_0[7][8] = { { VLC4(1, 1), VLC4(0, 1) }, { VLC2(2, 2), VLC2(1, 2), VLC4(0, 1) }, { VLC2(3, 2), VLC2(2, 2), VLC2(1, 2), VLC2(0, 2) }, { VLC(4, 3), VLC(3, 3), VLC2(2, 2), VLC2(1, 2), VLC2(0, 2) }, { VLC(5, 3), VLC(4, 3), VLC(3, 3), VLC(2, 3), VLC2(1, 2), VLC2(0, 2), }, { VLC(1, 3), VLC(2, 3), VLC(4, 3), VLC(3, 3), VLC(6, 3), VLC(5, 3), VLC2(0, 2) }, { VLC(-1, -1), VLC(6, 3), VLC(5, 3), VLC(4, 3), VLC(3, 3), VLC(2, 3), VLC(1, 3), VLC(0, 3) } }; static const uint8_t run_before_table_1[] = { -1, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7 }; static const uint8_t run_before_table_2[] = { -1, 14, 13, 13, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 11 }; /* -- cavlc tables -- */ /* nC == -1 */ void read_coff_token_t4(bs_t *s, uint8_t* trailing_ones, uint8_t* total_coff) { int32_t code; code = bs_show(s, 8); if (code >= 16) { if (code >= 128) { /* 1 */ *trailing_ones = 1; *total_coff = 1; bs_skip(s, 1); } else if (code >= 64) { /* 01 */ *trailing_ones = 0; *total_coff = 0; bs_skip(s, 2); } else if (code >= 32) { /* 001 */ *trailing_ones = 2; *total_coff = 2; bs_skip(s, 3); } else { code = (code >> 2) - 4; *trailing_ones = coeff4_0[code].trailing_ones; *total_coff = coeff4_0[code].total_coeff; bs_skip(s, 6); } } else { *trailing_ones = coeff4_1[code].trailing_ones; *total_coff = coeff4_1[code].total_coeff; bs_skip(s, coeff4_1[code].len); } } /* nC >= 8 */ void read_coff_token_t3(bs_t *s, uint8_t* trailing_ones, uint8_t* total_coff) { int32_t code; code = bs_read(s, 6); *trailing_ones = coeff3_0[code].trailing_ones; *total_coff = coeff3_0[code].total_coeff; } /* 8 > nC >= 4 */ void read_coff_token_t2(bs_t *s, uint8_t* trailing_ones, uint8_t* total_coff) { int32_t code; const vlc_coeff_token_t* table; code = bs_show(s, 10); if (code >= 512) { table = coeff2_0; code = (code >> 6) - 8; } else if (code >= 256) { table = coeff2_1; code = (code >> 5) - 8; } else if (code >= 128) { table = coeff2_2; code = (code >> 4) - 8; } else if (code >= 64) { table = coeff2_3; code = (code >> 3) - 8; } else if (code >= 32) { table = coeff2_4; code = (code >> 2) - 8; } else if (code >= 16) { table = coeff2_5; code = (code >> 1) - 8; } else { table = coeff2_6; } *trailing_ones = table[code].trailing_ones; *total_coff = table[code].total_coeff; bs_skip(s, table[code].len); } /* 4 > nC >= 2 */ void read_coff_token_t1(bs_t *s, uint8_t* trailing_ones, uint8_t* total_coff) { int32_t code; const vlc_coeff_token_t* table; code = bs_show(s, 14); if (code >= 4096) { table = coeff1_0; code = (code >> 10) - 4; } else if (code >= 1024) { table = coeff1_1; code = (code >> 8) - 4; } else if (code >= 128) { table = coeff1_2; code = (code >> 5) - 4; } else if (code >= 64) { table = coeff1_3; code = (code >> 3) - 8; } else if (code >= 32) { table = coeff1_4; code = (code >> 2) - 8; } else if (code >= 16) { table = coeff1_5; code = (code >> 1) - 8; } else { table = coeff1_6; } *trailing_ones = table[code].trailing_ones; *total_coff = table[code].total_coeff; bs_skip(s, table[code].len); } /* 2 > nC >= 0 */ void read_coff_token_t0(bs_t *s, uint8_t* trailing_ones, uint8_t* total_coff) { int32_t code; const vlc_coeff_token_t* table; code = bs_show(s, 16); if (code >= 8192) { table = coeff0_5; code >>= 13; } else if (code >= 4096) { table = coeff0_4; code = (code >> 10) - 4; } else if (code >= 1024) { table = coeff0_3; code = (code >> 8) - 4; } else if (code >= 128) { table = coeff0_2; code = (code >> 5) - 4; } else if (code >= 64) { table = coeff0_1; code = (code >> 3) - 8; } else { table = coeff0_0; } *trailing_ones = table[code].trailing_ones; *total_coff = table[code].total_coeff; bs_skip(s, table[code].len); } uint8_t read_level_prefix(bs_t *s) { uint8_t prefix; int32_t code; code = bs_show(s, 16); if (code >= 4096) { prefix = prefix_table0[code >> 12]; } else if (code >= 256) { prefix = prefix_table1[code >> 8]; } else if (code >= 16) { prefix = prefix_table2[code >> 4]; } else { prefix = prefix_table3[code]; } bs_skip(s, prefix + 1); return prefix; } uint8_t read_total_zero1(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 9); if (code >= 32) { code >>= 4; total_zero = total_zero_table1_1[code].num; bs_skip(s, total_zero_table1_1[code].len); } else { total_zero = total_zero_table1_0[code].num; bs_skip(s, total_zero_table1_0[code].len); } assert(total_zero != 255); return total_zero; } uint8_t read_total_zero2(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 6); if (code >= 8) { code >>= 2; total_zero = total_zero_table2_1[code].num; bs_skip(s, total_zero_table2_1[code].len); } else { total_zero = total_zero_table2_0[code].num; bs_skip(s, total_zero_table2_0[code].len); } assert(total_zero != 255); return total_zero; } uint8_t read_total_zero3(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 6); if (code >= 8) { code >>= 2; total_zero = total_zero_table3_1[code].num; bs_skip(s, total_zero_table3_1[code].len); } else { total_zero = total_zero_table3_0[code].num; bs_skip(s, total_zero_table3_0[code].len); } assert(total_zero != 255); return total_zero; } uint8_t read_total_zero6(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 6); if (code >= 8) { code >>= 3; total_zero = total_zero_table6_1[code].num; bs_skip(s, total_zero_table6_1[code].len); } else { total_zero = total_zero_table6_0[code].num; bs_skip(s, total_zero_table6_0[code].len); } assert(total_zero != 255); return total_zero; } uint8_t read_total_zero7(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 6); if (code >= 8) { code >>= 3; total_zero = total_zero_table7_1[code].num; bs_skip(s, total_zero_table7_1[code].len); } else { total_zero = total_zero_table7_0[code].num; bs_skip(s, total_zero_table7_0[code].len); } assert(total_zero != 255); return total_zero; } uint8_t read_total_zero8(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 6); if (code >= 8) { code >>= 3; total_zero = total_zero_table8_1[code].num; bs_skip(s, total_zero_table8_1[code].len); } else { total_zero = total_zero_table8_0[code].num; bs_skip(s, total_zero_table8_0[code].len); } assert(total_zero != 255); return total_zero; } uint8_t read_total_zero9(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 6); if (code >= 8) { code >>= 3; total_zero = total_zero_table9_1[code].num; bs_skip(s, total_zero_table9_1[code].len); } else { total_zero = total_zero_table9_0[code].num; bs_skip(s, total_zero_table9_0[code].len); } assert(total_zero != 255); return total_zero; } uint8_t read_total_zero4(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 5); if (code >= 16) { code = (code >> 2) - 4; total_zero = total_zero_table4_1[code].num; bs_skip(s, total_zero_table4_1[code].len); } else { total_zero = total_zero_table4_0[code].num; bs_skip(s, total_zero_table4_0[code].len); } assert(total_zero != 255); return total_zero; } uint8_t read_total_zero5(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 5); if (code >= 16) { code = (code >> 2) - 4; total_zero = total_zero_table5_1[code].num; bs_skip(s, total_zero_table5_1[code].len); } else { total_zero = total_zero_table5_0[code].num; bs_skip(s, total_zero_table5_0[code].len); } assert(total_zero != 255); return total_zero; } uint8_t read_total_zero10(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 5); if (code >= 4) { code >>= 2; total_zero = total_zero_table10_1[code].num; bs_skip(s, total_zero_table10_1[code].len); } else { total_zero = total_zero_table10_0[code].num; bs_skip(s, total_zero_table10_0[code].len); } assert(total_zero != 255); return total_zero; } uint8_t read_total_zero11(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 4); total_zero = total_zero_table11_0[code].num; bs_skip(s, total_zero_table11_0[code].len); assert(total_zero != 255); return total_zero; } uint8_t read_total_zero12(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 4); total_zero = total_zero_table12_0[code].num; bs_skip(s, total_zero_table12_0[code].len); return total_zero; } uint8_t read_total_zero13(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 3); total_zero = total_zero_table13_0[code].num; bs_skip(s, total_zero_table13_0[code].len); return total_zero; } uint8_t read_total_zero14(bs_t *s) { uint8_t total_zero; int32_t code; code = bs_show(s, 2); total_zero = total_zero_table14_0[code].num; bs_skip(s, total_zero_table14_0[code].len); return total_zero; } uint8_t read_total_zero15(bs_t *s) { return bs_read1(s); } uint8_t read_total_zero_chroma(bs_t *s, uint8_t total_coeff) { uint8_t total_zero; int32_t code; code = bs_show(s, 3); total_zero = total_zero_table_chroma[total_coeff - 1][code].num; bs_skip(s, total_zero_table_chroma[total_coeff - 1][code].len); assert(total_zero != 255); return total_zero; } uint8_t read_run_before(bs_t *s, uint8_t zero_left) { int32_t code; uint8_t run_before; assert(zero_left != 255); code = bs_show(s, 3); if (zero_left <= 6) { run_before = run_before_table_0[zero_left - 1][code].num; bs_skip(s, run_before_table_0[zero_left - 1][code].len); } else { bs_skip(s, 3); if (code > 0) { run_before = run_before_table_0[6][code].num; } else { code = bs_show(s, 4); if (code > 0) { run_before = run_before_table_1[code]; bs_skip(s, run_before - 6); } else { bs_skip(s, 4); code = bs_show(s, 4); run_before = run_before_table_2[code]; bs_skip(s, run_before - 10); } } } assert(run_before >= 0 && run_before <= 14); return run_before; } int p264dec_read_residual_block_cavlc( p264_t *h, bs_t *s, int idx, int *l, int i_count ) { uint8_t trailing_ones, total_coeff; int32_t i, j; int32_t zero_left = 0; int16_t level[16]; //order: is from high frequency to low frequency uint8_t run[16]; if(idx == BLOCK_INDEX_CHROMA_DC) { read_coff_token_t4(s, &trailing_ones, &total_coeff); } else { //[1] NC-> total coeff and trailing ones /* P264_mb_predict_non_zero_code return 0 <-> (16+16+1)>>1 = 16 */ int32_t nC = 0; typedef void (*read_coff_token_t)(bs_t *s, uint8_t* trailing_ones, uint8_t* total_coff); static const read_coff_token_t read_coeff[17] = { read_coff_token_t0, read_coff_token_t0, read_coff_token_t1, read_coff_token_t1, read_coff_token_t2, read_coff_token_t2, read_coff_token_t2, read_coff_token_t2, read_coff_token_t3, read_coff_token_t3, read_coff_token_t3, read_coff_token_t3, read_coff_token_t3, read_coff_token_t3, read_coff_token_t3, read_coff_token_t3, read_coff_token_t3 }; if(idx == BLOCK_INDEX_LUMA_DC) { // predict nC = (nA + nB) / 2; nC = p264_mb_predict_non_zero_code( h, 0 ); read_coeff[nC](s, &trailing_ones, &total_coeff); } else { // predict nC = (nA + nB) / 2; nC = p264_mb_predict_non_zero_code( h, idx ); read_coeff[nC](s, &trailing_ones, &total_coeff); assert(total_coeff != 255); assert(trailing_ones != 255); h->mb.cache.non_zero_count[p264_scan8[idx]]=total_coeff; //lsp } }//end of if(idx == BLOCK_INDEX_CHROMA_DC) else if (total_coeff > 0) { int suffix_length = 0; int level_code; if (total_coeff > 10 && trailing_ones < 3) suffix_length = 1; //[3] read the trailing ones sign, then set the according level for(i = 0 ; i < trailing_ones ; i ++) { level[i] = 1 - 2 * bs_read( s, 1 ); } //[4] read the other non zero coeff for( ; i < total_coeff ; i ++) { int level_suffixsize; int level_suffix; int level_prefix = read_level_prefix(s); level_suffixsize = suffix_length; if (suffix_length == 0 && level_prefix == 14) level_suffixsize = 4; else if (level_prefix == 15) level_suffixsize = 12; if (level_suffixsize > 0) level_suffix = bs_read(s, level_suffixsize); else level_suffix = 0; level_code = (level_prefix << suffix_length) + level_suffix; if (level_prefix == 15 && suffix_length == 0) { level_code += 15; } if (i == trailing_ones && trailing_ones < 3) { level_code += 2; } if (level_code % 2 == 0) { level[i] = (level_code + 2) >> 1; } else { level[i] = (-level_code - 1) >> 1; } if (suffix_length == 0) suffix_length = 1; if (abs(level[i]) > (3 << (suffix_length - 1)) && suffix_length < 6) { suffix_length ++; } }//end of for( ; i < total_coeff ; i ++) //[5] total_zero if (total_coeff < i_count) { typedef uint8_t (*read_total_zero_t)(bs_t *s); static read_total_zero_t total_zero_f[] = { read_total_zero1, read_total_zero2, read_total_zero3, read_total_zero4, read_total_zero5, read_total_zero6, read_total_zero7, read_total_zero8, read_total_zero9, read_total_zero10, read_total_zero11, read_total_zero12, read_total_zero13, read_total_zero14, read_total_zero15 }; if(idx != BLOCK_INDEX_CHROMA_DC) zero_left = total_zero_f[total_coeff - 1](s); else zero_left = read_total_zero_chroma(s, total_coeff); } //[6] run before for(i = 0 ; i < total_coeff - 1 ; i ++) { if (zero_left > 0) { run[i] = read_run_before(s, zero_left); } else { run[i] = 0; } zero_left -= run[i]; } run[total_coeff - 1] = zero_left; //[annex] save into l[] j = -1; for(i = total_coeff - 1 ; i >= 0 ; i --) { j +=run[i] + 1; l[j] = level[i]; } }//end of if (total_coeff > 0) return 0; }