mirror of https://git.ffmpeg.org/ffmpeg.git
implement B_DIRECT and B_SKIP macroblock types.
fix reference list sorting for B-frames. fix mv caching for mixed list B-blocks. Originally committed as revision 3775 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
6feb1de50f
commit
5ad984c997
|
@ -270,6 +270,7 @@ typedef struct H264Context{
|
|||
int redundant_pic_count;
|
||||
|
||||
int direct_spatial_mv_pred;
|
||||
int dist_scale_factor[16];
|
||||
|
||||
/**
|
||||
* num_ref_idx_l0/1_active_minus1 + 1
|
||||
|
@ -314,6 +315,8 @@ typedef struct H264Context{
|
|||
int last_qscale_diff;
|
||||
int16_t (*mvd_table[2])[2];
|
||||
int16_t mvd_cache[2][5*8][2];
|
||||
uint8_t *direct_table;
|
||||
uint8_t direct_cache[5*8];
|
||||
|
||||
}H264Context;
|
||||
|
||||
|
@ -562,16 +565,17 @@ static inline void fill_caches(H264Context *h, int mb_type){
|
|||
}
|
||||
|
||||
#if 1
|
||||
if(IS_INTER(mb_type)){
|
||||
//FIXME direct mb can skip much of this
|
||||
if(IS_INTER(mb_type) || (IS_DIRECT(mb_type) && h->direct_spatial_mv_pred)){
|
||||
int list;
|
||||
for(list=0; list<2; list++){
|
||||
if((!IS_8X8(mb_type)) && !USES_LIST(mb_type, list)){
|
||||
if((!IS_8X8(mb_type)) && !USES_LIST(mb_type, list) && !IS_DIRECT(mb_type)){
|
||||
/*if(!h->mv_cache_clean[list]){
|
||||
memset(h->mv_cache [list], 0, 8*5*2*sizeof(int16_t)); //FIXME clean only input? clean at all?
|
||||
memset(h->ref_cache[list], PART_NOT_AVAILABLE, 8*5*sizeof(int8_t));
|
||||
h->mv_cache_clean[list]= 1;
|
||||
}*/
|
||||
continue; //FIXME direct mode ...
|
||||
continue;
|
||||
}
|
||||
h->mv_cache_clean[list]= 0;
|
||||
|
||||
|
@ -696,9 +700,35 @@ static inline void fill_caches(H264Context *h, int mb_type){
|
|||
*(uint32_t*)h->mvd_cache [list][scan8[13]+1]= //FIXME remove past 3 (init somewher else)
|
||||
*(uint32_t*)h->mvd_cache [list][scan8[4 ]]=
|
||||
*(uint32_t*)h->mvd_cache [list][scan8[12]]= 0;
|
||||
|
||||
if(h->slice_type == B_TYPE){
|
||||
fill_rectangle(&h->direct_cache[scan8[0]], 4, 4, 8, 0, 1);
|
||||
|
||||
if(IS_DIRECT(top_type)){
|
||||
*(uint32_t*)&h->direct_cache[scan8[0] - 1*8]= 0x01010101;
|
||||
}else if(IS_8X8(top_type)){
|
||||
int b8_xy = h->mb2b8_xy[top_xy] + h->b8_stride;
|
||||
h->direct_cache[scan8[0] + 0 - 1*8]= h->direct_table[b8_xy];
|
||||
h->direct_cache[scan8[0] + 2 - 1*8]= h->direct_table[b8_xy + 1];
|
||||
}else{
|
||||
*(uint32_t*)&h->direct_cache[scan8[0] - 1*8]= 0;
|
||||
}
|
||||
|
||||
//FIXME interlacing
|
||||
if(IS_DIRECT(left_type[0])){
|
||||
h->direct_cache[scan8[0] - 1 + 0*8]=
|
||||
h->direct_cache[scan8[0] - 1 + 2*8]= 1;
|
||||
}else if(IS_8X8(left_type[0])){
|
||||
int b8_xy = h->mb2b8_xy[left_xy[0]] + 1;
|
||||
h->direct_cache[scan8[0] - 1 + 0*8]= h->direct_table[b8_xy];
|
||||
h->direct_cache[scan8[0] - 1 + 2*8]= h->direct_table[b8_xy + h->b8_stride];
|
||||
}else{
|
||||
h->direct_cache[scan8[0] - 1 + 0*8]=
|
||||
h->direct_cache[scan8[0] - 1 + 2*8]= 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//FIXME
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -997,6 +1027,191 @@ static inline void pred_pskip_motion(H264Context * const h, int * const mx, int
|
|||
return;
|
||||
}
|
||||
|
||||
static inline void direct_dist_scale_factor(H264Context * const h){
|
||||
const int poc = h->s.current_picture_ptr->poc;
|
||||
const int poc1 = h->ref_list[1][0].poc;
|
||||
int i;
|
||||
for(i=0; i<h->ref_count[0]; i++){
|
||||
int poc0 = h->ref_list[0][i].poc;
|
||||
int td = clip(poc1 - poc0, -128, 127);
|
||||
if(td == 0 /* FIXME || pic0 is a long-term ref */){
|
||||
h->dist_scale_factor[i] = 256;
|
||||
}else{
|
||||
int tb = clip(poc - poc0, -128, 127);
|
||||
int tx = (16384 + (ABS(td) >> 1)) / td;
|
||||
h->dist_scale_factor[i] = clip((tb*tx + 32) >> 6, -1024, 1023);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void pred_direct_motion(H264Context * const h, int *mb_type){
|
||||
MpegEncContext * const s = &h->s;
|
||||
const int mb_xy = s->mb_x + s->mb_y*s->mb_stride;
|
||||
const int b8_xy = 2*s->mb_x + 2*s->mb_y*h->b8_stride;
|
||||
const int b4_xy = 4*s->mb_x + 4*s->mb_y*h->b_stride;
|
||||
const int mb_type_col = h->ref_list[1][0].mb_type[mb_xy];
|
||||
const int16_t (*l1mv0)[2] = (const int16_t (*)[2]) &h->ref_list[1][0].motion_val[0][b4_xy];
|
||||
const int8_t *l1ref0 = &h->ref_list[1][0].ref_index[0][b8_xy];
|
||||
const int is_b8x8 = IS_8X8(*mb_type);
|
||||
int sub_mb_type;
|
||||
int i8, i4;
|
||||
|
||||
if(IS_8X8(mb_type_col) && !h->sps.direct_8x8_inference_flag){
|
||||
/* FIXME save sub mb types from previous frames (or derive from MVs)
|
||||
* so we know exactly what block size to use */
|
||||
sub_mb_type = MB_TYPE_8x8|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_4x4 */
|
||||
*mb_type = MB_TYPE_8x8;
|
||||
}else if(!is_b8x8 && (IS_16X16(mb_type_col) || IS_INTRA(mb_type_col))){
|
||||
sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */
|
||||
*mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_16x16 */
|
||||
}else{
|
||||
sub_mb_type = MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2; /* B_SUB_8x8 */
|
||||
*mb_type = MB_TYPE_8x8;
|
||||
}
|
||||
if(!is_b8x8)
|
||||
*mb_type |= MB_TYPE_DIRECT2;
|
||||
|
||||
if(h->direct_spatial_mv_pred){
|
||||
int ref[2];
|
||||
int mv[2][2];
|
||||
int list;
|
||||
|
||||
/* ref = min(neighbors) */
|
||||
for(list=0; list<2; list++){
|
||||
int refa = h->ref_cache[list][scan8[0] - 1];
|
||||
int refb = h->ref_cache[list][scan8[0] - 8];
|
||||
int refc = h->ref_cache[list][scan8[0] - 8 + 4];
|
||||
if(refc == -2)
|
||||
refc = h->ref_cache[list][scan8[0] - 8 - 1];
|
||||
ref[list] = refa;
|
||||
if(ref[list] < 0 || (refb < ref[list] && refb >= 0))
|
||||
ref[list] = refb;
|
||||
if(ref[list] < 0 || (refc < ref[list] && refc >= 0))
|
||||
ref[list] = refc;
|
||||
if(ref[list] < 0)
|
||||
ref[list] = -1;
|
||||
}
|
||||
|
||||
if(ref[0] < 0 && ref[1] < 0){
|
||||
ref[0] = ref[1] = 0;
|
||||
mv[0][0] = mv[0][1] =
|
||||
mv[1][0] = mv[1][1] = 0;
|
||||
}else{
|
||||
for(list=0; list<2; list++){
|
||||
if(ref[list] >= 0)
|
||||
pred_motion(h, 0, 4, list, ref[list], &mv[list][0], &mv[list][1]);
|
||||
else
|
||||
mv[list][0] = mv[list][1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(ref[1] < 0){
|
||||
*mb_type &= ~MB_TYPE_P0L1;
|
||||
sub_mb_type &= ~MB_TYPE_P0L1;
|
||||
}else if(ref[0] < 0){
|
||||
*mb_type &= ~MB_TYPE_P0L0;
|
||||
sub_mb_type &= ~MB_TYPE_P0L0;
|
||||
}
|
||||
|
||||
if(IS_16X16(*mb_type)){
|
||||
fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref[0], 1);
|
||||
fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, ref[1], 1);
|
||||
if(!IS_INTRA(mb_type_col) && l1ref0[0] == 0 &&
|
||||
ABS(l1mv0[0][0]) <= 1 && ABS(l1mv0[0][1]) <= 1){
|
||||
if(ref[0] > 0)
|
||||
fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mv[0][0],mv[0][1]), 4);
|
||||
else
|
||||
fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4);
|
||||
if(ref[1] > 0)
|
||||
fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, pack16to32(mv[1][0],mv[1][1]), 4);
|
||||
else
|
||||
fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, 0, 4);
|
||||
}else{
|
||||
fill_rectangle(&h->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mv[0][0],mv[0][1]), 4);
|
||||
fill_rectangle(&h->mv_cache[1][scan8[0]], 4, 4, 8, pack16to32(mv[1][0],mv[1][1]), 4);
|
||||
}
|
||||
}else{
|
||||
for(i8=0; i8<4; i8++){
|
||||
const int x8 = i8&1;
|
||||
const int y8 = i8>>1;
|
||||
|
||||
if(is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8]))
|
||||
continue;
|
||||
h->sub_mb_type[i8] = sub_mb_type;
|
||||
|
||||
fill_rectangle(&h->mv_cache[0][scan8[i8*4]], 2, 2, 8, pack16to32(mv[0][0],mv[0][1]), 4);
|
||||
fill_rectangle(&h->mv_cache[1][scan8[i8*4]], 2, 2, 8, pack16to32(mv[1][0],mv[1][1]), 4);
|
||||
fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, ref[0], 1);
|
||||
fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, ref[1], 1);
|
||||
|
||||
/* col_zero_flag */
|
||||
if(!IS_INTRA(mb_type_col) && l1ref0[x8 + y8*h->b8_stride] == 0){
|
||||
for(i4=0; i4<4; i4++){
|
||||
const int16_t *mv_col = l1mv0[x8*2 + (i4&1) + (y8*2 + (i4>>1))*h->b_stride];
|
||||
if(ABS(mv_col[0]) <= 1 && ABS(mv_col[1]) <= 1){
|
||||
if(ref[0] == 0)
|
||||
*(uint32_t*)h->mv_cache[0][scan8[i8*4+i4]] = 0;
|
||||
if(ref[1] == 0)
|
||||
*(uint32_t*)h->mv_cache[1][scan8[i8*4+i4]] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{ /* direct temporal mv pred */
|
||||
/* FIXME assumes that L1ref0 used the same ref lists as current frame */
|
||||
if(IS_16X16(*mb_type)){
|
||||
fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, 0, 1);
|
||||
if(IS_INTRA(mb_type_col)){
|
||||
fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1);
|
||||
fill_rectangle(&h-> mv_cache[0][scan8[0]], 4, 4, 8, 0, 4);
|
||||
fill_rectangle(&h-> mv_cache[1][scan8[0]], 4, 4, 8, 0, 4);
|
||||
}else{
|
||||
const int ref0 = l1ref0[0];
|
||||
const int dist_scale_factor = h->dist_scale_factor[ref0];
|
||||
const int16_t *mv_col = l1mv0[0];
|
||||
int mv_l0[2];
|
||||
mv_l0[0] = (dist_scale_factor * mv_col[0] + 128) >> 8;
|
||||
mv_l0[1] = (dist_scale_factor * mv_col[1] + 128) >> 8;
|
||||
fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref0, 1);
|
||||
fill_rectangle(&h-> mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mv_l0[0],mv_l0[1]), 4);
|
||||
fill_rectangle(&h-> mv_cache[1][scan8[0]], 4, 4, 8, pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]), 4);
|
||||
}
|
||||
}else{
|
||||
for(i8=0; i8<4; i8++){
|
||||
const int x8 = i8&1;
|
||||
const int y8 = i8>>1;
|
||||
int ref0, dist_scale_factor;
|
||||
|
||||
if(is_b8x8 && !IS_DIRECT(h->sub_mb_type[i8]))
|
||||
continue;
|
||||
h->sub_mb_type[i8] = sub_mb_type;
|
||||
if(IS_INTRA(mb_type_col)){
|
||||
fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, 0, 1);
|
||||
fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, 0, 1);
|
||||
fill_rectangle(&h-> mv_cache[0][scan8[i8*4]], 2, 2, 8, 0, 4);
|
||||
fill_rectangle(&h-> mv_cache[1][scan8[i8*4]], 2, 2, 8, 0, 4);
|
||||
continue;
|
||||
}
|
||||
|
||||
ref0 = l1ref0[x8 + y8*h->b8_stride];
|
||||
dist_scale_factor = h->dist_scale_factor[ref0];
|
||||
|
||||
fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, ref0, 1);
|
||||
fill_rectangle(&h->ref_cache[1][scan8[i8*4]], 2, 2, 8, 0, 1);
|
||||
for(i4=0; i4<4; i4++){
|
||||
const int16_t *mv_col = l1mv0[x8*2 + (i4&1) + (y8*2 + (i4>>1))*h->b_stride];
|
||||
int16_t *mv_l0 = h->mv_cache[0][scan8[i8*4+i4]];
|
||||
mv_l0[0] = (dist_scale_factor * mv_col[0] + 128) >> 8;
|
||||
mv_l0[1] = (dist_scale_factor * mv_col[1] + 128) >> 8;
|
||||
*(uint32_t*)h->mv_cache[1][scan8[i8*4+i4]] =
|
||||
pack16to32(mv_l0[0]-mv_col[0],mv_l0[1]-mv_col[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void write_back_motion(H264Context *h, int mb_type){
|
||||
MpegEncContext * const s = &h->s;
|
||||
const int b_xy = 4*s->mb_x + 4*s->mb_y*h->b_stride;
|
||||
|
@ -1022,7 +1237,7 @@ static inline void write_back_motion(H264Context *h, int mb_type){
|
|||
*(uint16_t*)&s->current_picture.ref_index[list][b8_xy + y*h->b8_stride]= (LIST_NOT_USED&0xFF)*0x0101;
|
||||
}
|
||||
}
|
||||
continue; //FIXME direct mode ...
|
||||
continue;
|
||||
}
|
||||
|
||||
for(y=0; y<4; y++){
|
||||
|
@ -1040,6 +1255,14 @@ static inline void write_back_motion(H264Context *h, int mb_type){
|
|||
s->current_picture.ref_index[list][b8_xy + 1 + y*h->b8_stride]= h->ref_cache[list][scan8[0]+2 + 16*y];
|
||||
}
|
||||
}
|
||||
|
||||
if(h->slice_type == B_TYPE && h->pps.cabac){
|
||||
if(IS_8X8(mb_type)){
|
||||
h->direct_table[b8_xy+1+0*h->b8_stride] = IS_DIRECT(h->sub_mb_type[1]) ? 1 : 0;
|
||||
h->direct_table[b8_xy+0+1*h->b8_stride] = IS_DIRECT(h->sub_mb_type[2]) ? 1 : 0;
|
||||
h->direct_table[b8_xy+1+1*h->b8_stride] = IS_DIRECT(h->sub_mb_type[3]) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2165,6 +2388,7 @@ static void free_tables(H264Context *h){
|
|||
av_freep(&h->cbp_table);
|
||||
av_freep(&h->mvd_table[0]);
|
||||
av_freep(&h->mvd_table[1]);
|
||||
av_freep(&h->direct_table);
|
||||
av_freep(&h->non_zero_count);
|
||||
av_freep(&h->slice_table_base);
|
||||
av_freep(&h->top_border);
|
||||
|
@ -2194,6 +2418,7 @@ static int alloc_tables(H264Context *h){
|
|||
CHECKED_ALLOCZ(h->chroma_pred_mode_table, big_mb_num * sizeof(uint8_t))
|
||||
CHECKED_ALLOCZ(h->mvd_table[0], 32*big_mb_num * sizeof(uint16_t));
|
||||
CHECKED_ALLOCZ(h->mvd_table[1], 32*big_mb_num * sizeof(uint16_t));
|
||||
CHECKED_ALLOCZ(h->direct_table, 32*big_mb_num * sizeof(uint8_t));
|
||||
}
|
||||
|
||||
memset(h->slice_table_base, -1, big_mb_num * sizeof(uint8_t));
|
||||
|
@ -2541,7 +2766,7 @@ static int fill_default_ref_list(H264Context *h){
|
|||
int index=0;
|
||||
|
||||
for(i=0; i<h->short_ref_count && index < h->ref_count[list]; i++){
|
||||
const int i2= list ? h->short_ref_count - i - 1 : i;
|
||||
const int i2= list ? i : h->short_ref_count - i - 1;
|
||||
const int poc= sorted_short_ref[i2].poc;
|
||||
|
||||
if(sorted_short_ref[i2].reference != 3) continue; //FIXME refernce field shit
|
||||
|
@ -2663,6 +2888,9 @@ static int decode_ref_pic_list_reordering(H264Context *h){
|
|||
|
||||
if(h->slice_type!=B_TYPE) break;
|
||||
}
|
||||
|
||||
if(h->slice_type==B_TYPE && !h->direct_spatial_mv_pred)
|
||||
direct_dist_scale_factor(h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3368,6 +3596,56 @@ static int decode_residual(H264Context *h, GetBitContext *gb, DCTELEM *block, in
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* decodes a P_SKIP or B_SKIP macroblock
|
||||
*/
|
||||
static void decode_mb_skip(H264Context *h){
|
||||
MpegEncContext * const s = &h->s;
|
||||
const int mb_xy= s->mb_x + s->mb_y*s->mb_stride;
|
||||
int mb_type;
|
||||
|
||||
memset(h->non_zero_count[mb_xy], 0, 16);
|
||||
memset(h->non_zero_count_cache + 8, 0, 8*5); //FIXME ugly, remove pfui
|
||||
|
||||
if( h->slice_type == B_TYPE )
|
||||
{
|
||||
// just for fill_caches. pred_direct_motion will set the real mb_type
|
||||
mb_type= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2|MB_TYPE_SKIP;
|
||||
//FIXME mbaff
|
||||
|
||||
fill_caches(h, mb_type); //FIXME check what is needed and what not ...
|
||||
pred_direct_motion(h, &mb_type);
|
||||
if(h->pps.cabac){
|
||||
fill_rectangle(h->mvd_cache[0][scan8[0]], 4, 4, 8, 0, 4);
|
||||
fill_rectangle(h->mvd_cache[1][scan8[0]], 4, 4, 8, 0, 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int mx, my;
|
||||
mb_type= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P1L0|MB_TYPE_SKIP;
|
||||
|
||||
if(h->sps.mb_aff && s->mb_skip_run==0 && (s->mb_y&1)==0){
|
||||
h->mb_field_decoding_flag= get_bits1(&s->gb);
|
||||
}
|
||||
if(h->mb_field_decoding_flag)
|
||||
mb_type|= MB_TYPE_INTERLACED;
|
||||
|
||||
fill_caches(h, mb_type); //FIXME check what is needed and what not ...
|
||||
pred_pskip_motion(h, &mx, &my);
|
||||
fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1);
|
||||
fill_rectangle( h->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mx,my), 4);
|
||||
if(h->pps.cabac)
|
||||
fill_rectangle(h->mvd_cache[0][scan8[0]], 4, 4, 8, 0, 4);
|
||||
}
|
||||
|
||||
write_back_motion(h, mb_type);
|
||||
s->current_picture.mb_type[mb_xy]= mb_type|MB_TYPE_SKIP;
|
||||
s->current_picture.qscale_table[mb_xy]= s->qscale;
|
||||
h->slice_table[ mb_xy ]= h->slice_num;
|
||||
h->prev_mb_skiped= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* decodes a macroblock
|
||||
* @returns 0 if ok, AC_ERROR / DC_ERROR / MV_ERROR if an error is noticed
|
||||
|
@ -3387,32 +3665,7 @@ static int decode_mb_cavlc(H264Context *h){
|
|||
s->mb_skip_run= get_ue_golomb(&s->gb);
|
||||
|
||||
if (s->mb_skip_run--) {
|
||||
int mx, my;
|
||||
/* skip mb */
|
||||
//FIXME b frame
|
||||
mb_type= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P1L0;
|
||||
|
||||
memset(h->non_zero_count[mb_xy], 0, 16);
|
||||
memset(h->non_zero_count_cache + 8, 0, 8*5); //FIXME ugly, remove pfui
|
||||
|
||||
if(h->sps.mb_aff && s->mb_skip_run==0 && (s->mb_y&1)==0){
|
||||
h->mb_field_decoding_flag= get_bits1(&s->gb);
|
||||
}
|
||||
|
||||
if(h->mb_field_decoding_flag)
|
||||
mb_type|= MB_TYPE_INTERLACED;
|
||||
|
||||
fill_caches(h, mb_type); //FIXME check what is needed and what not ...
|
||||
pred_pskip_motion(h, &mx, &my);
|
||||
fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1);
|
||||
fill_rectangle( h->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mx,my), 4);
|
||||
write_back_motion(h, mb_type);
|
||||
|
||||
s->current_picture.mb_type[mb_xy]= mb_type; //FIXME SKIP type
|
||||
s->current_picture.qscale_table[mb_xy]= s->qscale;
|
||||
h->slice_table[ mb_xy ]= h->slice_num;
|
||||
|
||||
h->prev_mb_skiped= 1;
|
||||
decode_mb_skip(h);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -3549,6 +3802,9 @@ decode_intra_mb:
|
|||
sub_partition_count[i]= b_sub_mb_type_info[ h->sub_mb_type[i] ].partition_count;
|
||||
h->sub_mb_type[i]= b_sub_mb_type_info[ h->sub_mb_type[i] ].type;
|
||||
}
|
||||
if( IS_DIRECT(h->sub_mb_type[0]) || IS_DIRECT(h->sub_mb_type[1])
|
||||
|| IS_DIRECT(h->sub_mb_type[2]) || IS_DIRECT(h->sub_mb_type[3]))
|
||||
pred_direct_motion(h, &mb_type);
|
||||
}else{
|
||||
assert(h->slice_type == P_TYPE || h->slice_type == SP_TYPE); //FIXME SP correct ?
|
||||
for(i=0; i<4; i++){
|
||||
|
@ -3566,7 +3822,8 @@ decode_intra_mb:
|
|||
const int ref_count= IS_REF0(mb_type) ? 1 : h->ref_count[list];
|
||||
if(ref_count == 0) continue;
|
||||
for(i=0; i<4; i++){
|
||||
if(IS_DIR(h->sub_mb_type[i], 0, list) && !IS_DIRECT(h->sub_mb_type[i])){
|
||||
if(IS_DIRECT(h->sub_mb_type[i])) continue;
|
||||
if(IS_DIR(h->sub_mb_type[i], 0, list)){
|
||||
ref[list][i] = get_te0_golomb(&s->gb, ref_count); //FIXME init to 0 before and skip?
|
||||
}else{
|
||||
//FIXME
|
||||
|
@ -3580,10 +3837,11 @@ decode_intra_mb:
|
|||
if(ref_count == 0) continue;
|
||||
|
||||
for(i=0; i<4; i++){
|
||||
if(IS_DIRECT(h->sub_mb_type[i])) continue;
|
||||
h->ref_cache[list][ scan8[4*i] ]=h->ref_cache[list][ scan8[4*i]+1 ]=
|
||||
h->ref_cache[list][ scan8[4*i]+8 ]=h->ref_cache[list][ scan8[4*i]+9 ]= ref[list][i];
|
||||
|
||||
if(IS_DIR(h->sub_mb_type[i], 0, list) && !IS_DIRECT(h->sub_mb_type[i])){
|
||||
if(IS_DIR(h->sub_mb_type[i], 0, list)){
|
||||
const int sub_mb_type= h->sub_mb_type[i];
|
||||
const int block_width= (sub_mb_type & (MB_TYPE_16x16|MB_TYPE_16x8)) ? 2 : 1;
|
||||
for(j=0; j<sub_partition_count[i]; j++){
|
||||
|
@ -3619,7 +3877,10 @@ decode_intra_mb:
|
|||
}
|
||||
}
|
||||
}
|
||||
}else if(!IS_DIRECT(mb_type)){
|
||||
}else if(IS_DIRECT(mb_type)){
|
||||
pred_direct_motion(h, &mb_type);
|
||||
s->current_picture.mb_type[mb_xy]= mb_type;
|
||||
}else{
|
||||
int list, mx, my, i;
|
||||
//FIXME we should set ref_idx_l? to 0 if we use that later ...
|
||||
if(IS_16X16(mb_type)){
|
||||
|
@ -3649,7 +3910,8 @@ decode_intra_mb:
|
|||
if(IS_DIR(mb_type, i, list)){
|
||||
const int val= get_te0_golomb(&s->gb, h->ref_count[list]);
|
||||
fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, val, 1);
|
||||
}
|
||||
}else // needed only for mixed refs (e.g. B_L0_L1_16x8)
|
||||
fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, (LIST_NOT_USED&0xFF), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3662,7 +3924,8 @@ decode_intra_mb:
|
|||
tprintf("final mv:%d %d\n", mx, my);
|
||||
|
||||
fill_rectangle(h->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack16to32(mx,my), 4);
|
||||
}
|
||||
}else
|
||||
fill_rectangle(h->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 4);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
@ -3673,7 +3936,8 @@ decode_intra_mb:
|
|||
if(IS_DIR(mb_type, i, list)){ //FIXME optimize
|
||||
const int val= get_te0_golomb(&s->gb, h->ref_count[list]);
|
||||
fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, val, 1);
|
||||
}
|
||||
}else // needed only for mixed refs
|
||||
fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, (LIST_NOT_USED&0xFF), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3686,7 +3950,8 @@ decode_intra_mb:
|
|||
tprintf("final mv:%d %d\n", mx, my);
|
||||
|
||||
fill_rectangle(h->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack16to32(mx,my), 4);
|
||||
}
|
||||
}else
|
||||
fill_rectangle(h->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4109,10 +4374,17 @@ static int decode_cabac_mb_ref( H264Context *h, int list, int n ) {
|
|||
int ref = 0;
|
||||
int ctx = 0;
|
||||
|
||||
if( refa > 0 )
|
||||
ctx++;
|
||||
if( refb > 0 )
|
||||
ctx += 2;
|
||||
if( h->slice_type == B_TYPE) {
|
||||
if( refa > 0 && !h->direct_cache[scan8[n] - 1] )
|
||||
ctx++;
|
||||
if( refb > 0 && !h->direct_cache[scan8[n] - 8] )
|
||||
ctx += 2;
|
||||
} else {
|
||||
if( refa > 0 )
|
||||
ctx++;
|
||||
if( refb > 0 )
|
||||
ctx += 2;
|
||||
}
|
||||
|
||||
while( get_cabac( &h->cabac, &h->cabac_state[54+ctx] ) ) {
|
||||
ref++;
|
||||
|
@ -4314,38 +4586,12 @@ static int decode_mb_cabac(H264Context *h) {
|
|||
if( h->slice_type != I_TYPE && h->slice_type != SI_TYPE ) {
|
||||
/* read skip flags */
|
||||
if( decode_cabac_mb_skip( h ) ) {
|
||||
int mx, my;
|
||||
decode_mb_skip(h);
|
||||
|
||||
//FIXME b frame
|
||||
/* skip mb */
|
||||
mb_type= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P1L0|MB_TYPE_SKIP;
|
||||
|
||||
memset(h->non_zero_count[mb_xy], 0, 16);
|
||||
memset(h->non_zero_count_cache + 8, 0, 8*5); //FIXME ugly, remove pfui
|
||||
#if 0
|
||||
if(h->sps.mb_aff && s->mb_skip_run==0 && (s->mb_y&1)==0){
|
||||
h->mb_field_decoding_flag= get_bits1(&s->gb);
|
||||
}
|
||||
if(h->mb_field_decoding_flag)
|
||||
mb_type|= MB_TYPE_INTERLACED;
|
||||
#endif
|
||||
|
||||
fill_caches(h, mb_type); //FIXME check what is needed and what not ...
|
||||
pred_pskip_motion(h, &mx, &my);
|
||||
fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1);
|
||||
fill_rectangle( h->mvd_cache[0][scan8[0]], 4, 4, 8, pack16to32(0,0), 4);
|
||||
fill_rectangle( h->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mx,my), 4);
|
||||
write_back_motion(h, mb_type);
|
||||
|
||||
s->current_picture.mb_type[mb_xy]= mb_type; //FIXME SKIP type
|
||||
s->current_picture.qscale_table[mb_xy]= s->qscale;
|
||||
h->slice_table[ mb_xy ]= h->slice_num;
|
||||
h->cbp_table[mb_xy] = 0;
|
||||
h->chroma_pred_mode_table[mb_xy] = 0;
|
||||
h->last_qscale_diff = 0;
|
||||
|
||||
h->prev_mb_skiped= 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -4430,6 +4676,15 @@ decode_intra_mb:
|
|||
sub_partition_count[i]= b_sub_mb_type_info[ h->sub_mb_type[i] ].partition_count;
|
||||
h->sub_mb_type[i]= b_sub_mb_type_info[ h->sub_mb_type[i] ].type;
|
||||
}
|
||||
if( IS_DIRECT(h->sub_mb_type[0]) || IS_DIRECT(h->sub_mb_type[1])
|
||||
|| IS_DIRECT(h->sub_mb_type[2]) || IS_DIRECT(h->sub_mb_type[3])) {
|
||||
pred_direct_motion(h, &mb_type);
|
||||
if( h->ref_count[0] > 1 || h->ref_count[1] > 1 ) {
|
||||
for( i = 0; i < 4; i++ )
|
||||
if( IS_DIRECT(h->sub_mb_type[i]) )
|
||||
fill_rectangle( &h->direct_cache[scan8[4*i]], 2, 2, 8, 1, 1 );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for( i = 0; i < 4; i++ ) {
|
||||
h->sub_mb_type[i] = decode_cabac_p_mb_sub_type( h );
|
||||
|
@ -4441,7 +4696,8 @@ decode_intra_mb:
|
|||
for( list = 0; list < 2; list++ ) {
|
||||
if( h->ref_count[list] > 0 ) {
|
||||
for( i = 0; i < 4; i++ ) {
|
||||
if(IS_DIR(h->sub_mb_type[i], 0, list) && !IS_DIRECT(h->sub_mb_type[i])){
|
||||
if(IS_DIRECT(h->sub_mb_type[i])) continue;
|
||||
if(IS_DIR(h->sub_mb_type[i], 0, list)){
|
||||
if( h->ref_count[list] > 1 )
|
||||
ref[list][i] = decode_cabac_mb_ref( h, list, 4*i );
|
||||
else
|
||||
|
@ -4457,6 +4713,10 @@ decode_intra_mb:
|
|||
|
||||
for(list=0; list<2; list++){
|
||||
for(i=0; i<4; i++){
|
||||
if(IS_DIRECT(h->sub_mb_type[i])){
|
||||
fill_rectangle(h->mvd_cache[list][scan8[4*i]], 2, 2, 8, 0, 4);
|
||||
continue;
|
||||
}
|
||||
h->ref_cache[list][ scan8[4*i] ]=h->ref_cache[list][ scan8[4*i]+1 ];
|
||||
|
||||
if(IS_DIR(h->sub_mb_type[i], 0, list) && !IS_DIRECT(h->sub_mb_type[i])){
|
||||
|
@ -4513,7 +4773,12 @@ decode_intra_mb:
|
|||
}
|
||||
}
|
||||
}
|
||||
} else if( !IS_DIRECT(mb_type) ) {
|
||||
} else if( IS_DIRECT(mb_type) ) {
|
||||
pred_direct_motion(h, &mb_type);
|
||||
s->current_picture.mb_type[mb_xy]= mb_type;
|
||||
fill_rectangle(h->mvd_cache[0][scan8[0]], 4, 4, 8, 0, 4);
|
||||
fill_rectangle(h->mvd_cache[1][scan8[0]], 4, 4, 8, 0, 4);
|
||||
} else {
|
||||
int list, mx, my, i, mpx, mpy;
|
||||
if(IS_16X16(mb_type)){
|
||||
for(list=0; list<2; list++){
|
||||
|
@ -4544,7 +4809,8 @@ decode_intra_mb:
|
|||
if(IS_DIR(mb_type, i, list)){
|
||||
const int ref= h->ref_count[list] > 1 ? decode_cabac_mb_ref( h, list, 8*i ) : 0;
|
||||
fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, ref, 1);
|
||||
}
|
||||
}else
|
||||
fill_rectangle(&h->ref_cache[list][ scan8[0] + 16*i ], 4, 2, 8, (LIST_NOT_USED&0xFF), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4558,6 +4824,9 @@ decode_intra_mb:
|
|||
|
||||
fill_rectangle(h->mvd_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack16to32(mx-mpx,my-mpy), 4);
|
||||
fill_rectangle(h->mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, pack16to32(mx,my), 4);
|
||||
}else{ // needed only for mixed refs
|
||||
fill_rectangle(h->mvd_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 4);
|
||||
fill_rectangle(h-> mv_cache[list][ scan8[0] + 16*i ], 4, 2, 8, 0, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4569,7 +4838,8 @@ decode_intra_mb:
|
|||
if(IS_DIR(mb_type, i, list)){ //FIXME optimize
|
||||
const int ref= h->ref_count[list] > 1 ? decode_cabac_mb_ref( h, list, 4*i ) : 0;
|
||||
fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, ref, 1);
|
||||
}
|
||||
}else
|
||||
fill_rectangle(&h->ref_cache[list][ scan8[0] + 2*i ], 2, 4, 8, (LIST_NOT_USED&0xFF), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4583,6 +4853,9 @@ decode_intra_mb:
|
|||
tprintf("final mv:%d %d\n", mx, my);
|
||||
fill_rectangle(h->mvd_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack16to32(mx-mpx,my-mpy), 4);
|
||||
fill_rectangle(h->mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, pack16to32(mx,my), 4);
|
||||
}else{ // needed only for mixed refs
|
||||
fill_rectangle(h->mvd_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 4);
|
||||
fill_rectangle(h-> mv_cache[list][ scan8[0] + 2*i ], 2, 4, 8, 0, 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue