?? cabac.c
字號:
/*****************************************************************************
*
* T264 AVC CODEC
*
* Copyright(C) 2004-2005 joylife <joylife_video@yahoo.com.cn>
* 2004-2005 tricro <tricro@hotmail.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-1307 USA
*
****************************************************************************/
/*****************************************************************************
* cabac.c: h264 encoder library
*****************************************************************************
* Copyright (C) 2003 Laurent Aimar
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* 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.
*****************************************************************************/
/*Note: the CABAC routine is currently referenced from x264 temporarily, with adaptation to
*the data structure of T264. It should be modified further in the near future.
*It's can support B slice, but only with MB mode P16x16, P16x8, P8x16, Direct16x16, B_SKIP
*ie., B8x8 is not support now
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "T264.h"
#include "cabac_engine.h"
#include "inter.h"
/* From ffmpeg
*/
#define T264_SCAN8_SIZE (6*8)
#define T264_SCAN8_0 (4+1*8)
static const int T264_scan8[16+2*4] =
{
/* Luma */
VEC_LUMA + 0, VEC_LUMA + 1, VEC_LUMA + 1*8 + 0, VEC_LUMA + 1*8 + 1,
VEC_LUMA + 2, VEC_LUMA + 3, VEC_LUMA + 1*8 + 2, VEC_LUMA + 1*8 + 3,
VEC_LUMA + 2*8 + 0, VEC_LUMA + 2*8 + 1, VEC_LUMA + 3*8 + 0, VEC_LUMA + 3*8 + 1,
VEC_LUMA + 2*8 + 2, VEC_LUMA + 2*8 + 3, VEC_LUMA + 3*8 + 2, VEC_LUMA + 3*8 + 3,
/* Cb */
NNZ_CHROMA0 + 0, NNZ_CHROMA0 + 1,
NNZ_CHROMA0 + 1*8 + 0, NNZ_CHROMA0 + 1*8 + 1,
/* Cr */
NNZ_CHROMA1 + 0, NNZ_CHROMA1 + 1,
NNZ_CHROMA1 + 1*8 + 0, NNZ_CHROMA1 + 1*8 + 1,
};
static const uint8_t block_idx_xy[4][4] =
{
{ 0, 2, 8, 10},
{ 1, 3, 9, 11},
{ 4, 6, 12, 14},
{ 5, 7, 13, 15}
};
#define IS_INTRA(mode) (mode == I_4x4 || mode == I_16x16)
#define IS_SKIP(type) ( (type) == P_SKIP || (type) == B_SKIP )
enum {
INTRA_4x4 = 0,
INTRA_16x16 = 1,
INTRA_PCM = 2,
P_L0 = 3,
P_8x81 = 4,
P_SKIP1 = 5,
B_DIRECT = 6,
B_L0_L0 = 7,
B_L0_L1 = 8,
B_L0_BI = 9,
B_L1_L0 = 10,
B_L1_L1 = 11,
B_L1_BI = 12,
B_BI_L0 = 13,
B_BI_L1 = 14,
B_BI_BI = 15,
B_8x81 = 16,
B_SKIP1 = 17,
};
static const int T264_mb_partition_listX_table[][2] =
{
{0, 0}, //B_DIRECT_8x8 = 100,
{1, 0}, //B_L0_8x8,
{0, 1}, //B_L1_8x8,
{1, 1}, //B_Bi_8x8,
{1, 0}, //B_L0_8x4,
{1, 0}, //B_L0_4x8,
{0, 1}, //B_L1_8x4,
{0, 1}, //B_L1_4x8,
{1, 1}, //B_Bi_8x4,
{1, 1}, //B_Bi_4x8,
{1, 0}, //B_L0_4x4,
{0, 1}, //B_L1_4x4,
{1, 1} //B_Bi_4x4
};
static const int T264_mb_type_list0_table[18][2] =
{
{0,0}, {0,0}, {0,0}, /* INTRA */
{1,1}, /* P_L0 */
{0,0}, /* P_8x8 */
{1,1}, /* P_SKIP */
{0,0}, /* B_DIRECT */
{1,1}, {1,0}, {1,1}, /* B_L0_* */
{0,1}, {0,0}, {0,1}, /* B_L1_* */
{1,1}, {1,0}, {1,1}, /* B_BI_* */
{0,0}, /* B_8x8 */
{0,0} /* B_SKIP */
};
static const int T264_mb_type_list1_table[18][2] =
{
{0,0}, {0,0}, {0,0}, /* INTRA */
{0,0}, /* P_L0 */
{0,0}, /* P_8x8 */
{0,0}, /* P_SKIP */
{0,0}, /* B_DIRECT */
{0,0}, {0,1}, {0,1}, /* B_L0_* */
{1,0}, {1,1}, {1,1}, /* B_L1_* */
{1,0}, {1,1}, {1,1}, /* B_BI_* */
{0,0}, /* B_8x8 */
{0,0} /* B_SKIP */
};
static void T264_cabac_mb_type( T264_t *t )
{
T264_mb_context_t *mb_ctxs = &(t->rec->mb[0]);
int32_t mb_mode = t->mb.mb_mode;
if( t->slice_type == SLICE_I )
{
int ctx = 0;
if( t->mb.mb_x > 0 && mb_ctxs[t->mb.mb_xy-1].mb_mode != I_4x4 )
{
ctx++;
}
if( t->mb.mb_y > 0 && mb_ctxs[t->mb.mb_xy - t->mb_stride].mb_mode != I_4x4 )
{
ctx++;
}
if( mb_mode == I_4x4 )
{
T264_cabac_encode_decision( &t->cabac, 3 + ctx, 0 );
}
else if(mb_mode == I_16x16) /* I_16x16 */
{
T264_cabac_encode_decision( &t->cabac, 3 + ctx, 1 );
T264_cabac_encode_terminal( &t->cabac, 0 );
T264_cabac_encode_decision( &t->cabac, 3 + 3, ( t->mb.cbp_y == 0 ? 0 : 1 ));
if( t->mb.cbp_c == 0 )
{
T264_cabac_encode_decision( &t->cabac, 3 + 4, 0 );
}
else
{
T264_cabac_encode_decision( &t->cabac, 3 + 4, 1 );
T264_cabac_encode_decision( &t->cabac, 3 + 5, ( t->mb.cbp_c == 1 ? 0 : 1 ) );
}
T264_cabac_encode_decision( &t->cabac, 3 + 6, ( (t->mb.mode_i16x16 / 2) ? 1 : 0 ));
T264_cabac_encode_decision( &t->cabac, 3 + 7, ( (t->mb.mode_i16x16 % 2) ? 1 : 0 ));
}
else /* I_PCM */
{
T264_cabac_encode_decision( &t->cabac, 3 + ctx, 1 );
T264_cabac_encode_terminal( &t->cabac, 1 );
}
}
else if( t->slice_type == SLICE_P )
{
/* prefix: 14, suffix: 17 */
if( mb_mode == P_MODE )
{
if( t->mb.mb_part == MB_16x16 )
{
T264_cabac_encode_decision( &t->cabac, 14, 0 );
T264_cabac_encode_decision( &t->cabac, 15, 0 );
T264_cabac_encode_decision( &t->cabac, 16, 0 );
}
else if( t->mb.mb_part == MB_16x8 )
{
T264_cabac_encode_decision( &t->cabac, 14, 0 );
T264_cabac_encode_decision( &t->cabac, 15, 1 );
T264_cabac_encode_decision( &t->cabac, 17, 1 );
}
else if( t->mb.mb_part == MB_8x16 )
{
T264_cabac_encode_decision( &t->cabac, 14, 0 );
T264_cabac_encode_decision( &t->cabac, 15, 1 );
T264_cabac_encode_decision( &t->cabac, 17, 0 );
}
else /* P8x8 mode */
{
T264_cabac_encode_decision( &t->cabac, 14, 0 );
T264_cabac_encode_decision( &t->cabac, 15, 0 );
T264_cabac_encode_decision( &t->cabac, 16, 1 );
}
}
else if( mb_mode == I_4x4 )
{
/* prefix */
T264_cabac_encode_decision( &t->cabac, 14, 1 );
T264_cabac_encode_decision( &t->cabac, 17, 0 );
}
else if(mb_mode == I_16x16) /* intra 16x16 */
{
/* prefix */
T264_cabac_encode_decision( &t->cabac, 14, 1 );
/* suffix */
T264_cabac_encode_decision( &t->cabac, 17, 1 );
T264_cabac_encode_terminal( &t->cabac, 0 ); /*ctxIdx == 276 */
T264_cabac_encode_decision( &t->cabac, 17+1, ( t->mb.cbp_y == 0 ? 0 : 1 ));
if( t->mb.cbp_c == 0 )
{
T264_cabac_encode_decision( &t->cabac, 17+2, 0 );
}
else
{
T264_cabac_encode_decision( &t->cabac, 17+2, 1 );
T264_cabac_encode_decision( &t->cabac, 17+2, ( t->mb.cbp_c == 1 ? 0 : 1 ) );
}
T264_cabac_encode_decision( &t->cabac, 17+3, ( (t->mb.mode_i16x16 / 2) ? 1 : 0 ));
T264_cabac_encode_decision( &t->cabac, 17+3, ( (t->mb.mode_i16x16 % 2) ? 1 : 0 ));
}
else /* I_PCM */
{
/* prefix */
T264_cabac_encode_decision( &t->cabac, 14, 1 );
T264_cabac_encode_decision( &t->cabac, 17, 1 );
T264_cabac_encode_terminal( &t->cabac, 1 ); /*ctxIdx == 276 */
}
}
else if( t->slice_type == SLICE_B )
{
int ctx = 0;
if( t->mb.mb_x > 0 && mb_ctxs[t->mb.mb_xy-1].mb_mode != B_SKIP && !mb_ctxs[t->mb.mb_xy-1].is_copy )
{
ctx++;
}
if( t->mb.mb_y > 0 && mb_ctxs[t->mb.mb_xy - t->mb_stride].mb_mode != B_SKIP && ! mb_ctxs[t->mb.mb_xy - t->mb_stride].is_copy)
{
ctx++;
}
if( t->mb.is_copy)
{
T264_cabac_encode_decision( &t->cabac, 27+ctx, 0 );
}
else if( t->mb.mb_part == MB_8x8 )
{
T264_cabac_encode_decision( &t->cabac, 27+ctx, 1 );
T264_cabac_encode_decision( &t->cabac, 27+3, 1 );
T264_cabac_encode_decision( &t->cabac, 27+4, 1 );
T264_cabac_encode_decision( &t->cabac, 27+5, 1 );
T264_cabac_encode_decision( &t->cabac, 27+5, 1 );
T264_cabac_encode_decision( &t->cabac, 27+5, 1 );
}
else if( IS_INTRA( mb_mode ) )
{
/* prefix */
T264_cabac_encode_decision( &t->cabac, 27+ctx, 1 );
T264_cabac_encode_decision( &t->cabac, 27+3, 1 );
T264_cabac_encode_decision( &t->cabac, 27+4, 1 );
T264_cabac_encode_decision( &t->cabac, 27+5, 1 );
T264_cabac_encode_decision( &t->cabac, 27+5, 0 );
T264_cabac_encode_decision( &t->cabac, 27+5, 1 );
/* Suffix */
if( mb_mode == I_4x4 )
{
T264_cabac_encode_decision( &t->cabac, 32, 0 );
}
else if(mb_mode == I_16x16)
{
T264_cabac_encode_decision( &t->cabac, 32, 1 );
T264_cabac_encode_terminal( &t->cabac, 0 );
/* TODO */
T264_cabac_encode_decision( &t->cabac, 32+1, ( t->mb.cbp_y == 0 ? 0 : 1 ));
if( t->mb.cbp_c == 0 )
{
T264_cabac_encode_decision( &t->cabac, 32+2, 0 );
}
else
{
T264_cabac_encode_decision( &t->cabac, 32+2, 1 );
T264_cabac_encode_decision( &t->cabac, 32+2, ( t->mb.cbp_c == 1 ? 0 : 1 ) );
}
T264_cabac_encode_decision( &t->cabac, 32+3, ( (t->mb.mode_i16x16 / 2) ? 1 : 0 ));
T264_cabac_encode_decision( &t->cabac, 32+3, ( (t->mb.mode_i16x16 % 2) ? 1 : 0 ));
}
else /* I_PCM */
{
T264_cabac_encode_decision( &t->cabac, 32, 1 );
T264_cabac_encode_terminal( &t->cabac, 1 );
}
}
else
{
static const int i_mb_len[21] =
{
3, 6, 6, /* L0 L0 */
3, 6, 6, /* L1 L1 */
6, 7, 7, /* BI BI */
6, 6, /* L0 L1 */
6, 6, /* L1 L0 */
7, 7, /* L0 BI */
7, 7, /* L1 BI */
7, 7, /* BI L0 */
7, 7, /* BI L1 */
};
static const int i_mb_bits[21][7] =
{
{ 1, 0, 0, }, { 1, 1, 0, 0, 0, 1, }, { 1, 1, 0, 0, 1, 0, }, /* L0 L0 */
{ 1, 0, 1, }, { 1, 1, 0, 0, 1, 1, }, { 1, 1, 0, 1, 0, 0, }, /* L1 L1 */
{ 1, 1, 0, 0, 0, 0 ,}, { 1, 1, 1, 1, 0, 0 , 0 }, { 1, 1, 1, 1, 0, 0 , 1 },/* BI BI */
{ 1, 1, 0, 1, 0, 1, }, { 1, 1, 0, 1, 1, 0, }, /* L0 L1 */
{ 1, 1, 0, 1, 1, 1, }, { 1, 1, 1, 1, 1, 0, }, /* L1 L0 */
{ 1, 1, 1, 0, 0, 0, 0 }, { 1, 1, 1, 0, 0, 0, 1 }, /* L0 BI */
{ 1, 1, 1, 0, 0, 1, 0 }, { 1, 1, 1, 0, 0, 1, 1 }, /* L1 BI */
{ 1, 1, 1, 0, 1, 0, 0 }, { 1, 1, 1, 0, 1, 0, 1 }, /* BI L0 */
{ 1, 1, 1, 0, 1, 1, 0 }, { 1, 1, 1, 0, 1, 1, 1 } /* BI L1 */
};
const int i_partition = t->mb.mb_part;
int idx = 0;
int i, b_part_mode, part_mode0, part_mode1;
static const int b_part_mode_map[3][3] = {
{ B_L0_L0, B_L0_L1, B_L0_BI },
{ B_L1_L0, B_L1_L1, B_L1_BI },
{ B_BI_L0, B_BI_L1, B_BI_BI }
};
switch(t->mb.mb_part)
{
case MB_16x16:
part_mode0 = t->mb.mb_part2[0] - B_L0_16x16;
b_part_mode = b_part_mode_map[part_mode0][part_mode0];
break;
case MB_16x8:
part_mode0 = t->mb.mb_part2[0] - B_L0_16x8;
part_mode1 = t->mb.mb_part2[1] - B_L0_16x8;
b_part_mode = b_part_mode_map[part_mode0][part_mode1];
break;
case MB_8x16:
part_mode0 = t->mb.mb_part2[0] - B_L0_8x16;
part_mode1 = t->mb.mb_part2[1] - B_L0_8x16;
b_part_mode = b_part_mode_map[part_mode0][part_mode1];
break;
}
switch( b_part_mode )
{
/* D_16x16, D_16x8, D_8x16 */
case B_BI_BI: idx += 3;
case B_L1_L1: idx += 3;
case B_L0_L0:
if( i_partition == MB_16x8 )
idx += 1;
else if( i_partition == MB_8x16 )
idx += 2;
break;
/* D_16x8, D_8x16 */
case B_BI_L1: idx += 2;
case B_BI_L0: idx += 2;
case B_L1_BI: idx += 2;
case B_L0_BI: idx += 2;
case B_L1_L0: idx += 2;
case B_L0_L1:
idx += 3*3;
if( i_partition == MB_8x16 )
idx++;
break;
default:
return;
}
T264_cabac_encode_decision( &t->cabac, 27+ctx, i_mb_bits[idx][0] );
T264_cabac_encode_decision( &t->cabac, 27+3, i_mb_bits[idx][1] );
T264_cabac_encode_decision( &t->cabac, 27+(i_mb_bits[idx][1] != 0 ? 4 : 5), i_mb_bits[idx][2] );
for( i = 3; i < i_mb_len[idx]; i++ )
{
T264_cabac_encode_decision( &t->cabac, 27+5, i_mb_bits[idx][i] );
}
}
}
else
{
//dummy here
}
}
static void T264_cabac_mb_intra4x4_pred_mode( T264_t *t, int i_pred, int i_mode )
{
if( i_pred == i_mode )
{
/* b_prev_intra4x4_pred_mode */
T264_cabac_encode_decision( &t->cabac, 68, 1 );
}
else
{
/* b_prev_intra4x4_pred_mode */
T264_cabac_encode_decision( &t->cabac, 68, 0 );
if( i_mode > i_pred )
{
i_mode--;
}
T264_cabac_encode_decision( &t->cabac, 69, (i_mode )&0x01 );
T264_cabac_encode_decision( &t->cabac, 69, (i_mode >> 1)&0x01 );
T264_cabac_encode_decision( &t->cabac, 69, (i_mode >> 2)&0x01 );
}
}
static void T264_cabac_mb_intra8x8_pred_mode( T264_t *t )
{
const int i_mode = t->mb.mb_mode_uv;
T264_mb_context_t *mb_ctxs = &(t->rec->mb[0]);
int ctx = 0;
if( t->mb.mb_x > 0 && mb_ctxs[t->mb.mb_xy-1].mb_mode_uv != Intra_8x8_DC)
{
ctx++;
}
if( t->mb.mb_y > 0 && mb_ctxs[t->mb.mb_xy - t->mb_stride].mb_mode_uv != Intra_8x8_DC )
{
ctx++;
}
if( i_mode == Intra_8x8_DC )
{
T264_cabac_encode_decision( &t->cabac, 64 + ctx, Intra_8x8_DC );
}
else
{
T264_cabac_encode_decision( &t->cabac, 64 + ctx, 1 );
T264_cabac_encode_decision( &t->cabac, 64 + 3, ( i_mode == 1 ? 0 : 1 ) );
if( i_mode > 1 )
{
T264_cabac_encode_decision( &t->cabac, 64 + 3, ( i_mode == 2 ? 0 : 1 ) );
}
}
}
static void T264_cabac_mb_cbp_luma( T264_t *t )
{
/* TODO: clean up and optimize */
T264_mb_context_t *mb_ctxs = &(t->rec->mb[0]);
int i8x8;
for( i8x8 = 0; i8x8 < 4; i8x8++ )
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -