Commit 6ba71fc4 authored by Loïc Le Loarer's avatar Loïc Le Loarer Committed by Michael Niedermayer

This is the second patch for MBAFF support, this adds the deblocking

filter code for the I slice.

With this patch, 4 more frames are decoded correctly from the
conformance streams.
patch by (Loïc Le Loarer <lll+ffmpeg m4x org>)

Originally committed as revision 4088 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 3bf3d666
...@@ -168,6 +168,9 @@ typedef struct H264Context{ ...@@ -168,6 +168,9 @@ typedef struct H264Context{
int chroma_pred_mode; int chroma_pred_mode;
int intra16x16_pred_mode; int intra16x16_pred_mode;
int top_mb_xy;
int left_mb_xy[2];
int8_t intra4x4_pred_mode_cache[5*8]; int8_t intra4x4_pred_mode_cache[5*8];
int8_t (*intra4x4_pred_mode)[8]; int8_t (*intra4x4_pred_mode)[8];
void (*pred4x4 [9+3])(uint8_t *src, uint8_t *topright, int stride);//FIXME move to dsp? void (*pred4x4 [9+3])(uint8_t *src, uint8_t *topright, int stride);//FIXME move to dsp?
...@@ -177,8 +180,8 @@ typedef struct H264Context{ ...@@ -177,8 +180,8 @@ typedef struct H264Context{
unsigned int top_samples_available; unsigned int top_samples_available;
unsigned int topright_samples_available; unsigned int topright_samples_available;
unsigned int left_samples_available; unsigned int left_samples_available;
uint8_t (*top_border)[16+2*8]; uint8_t (*top_borders[2])[16+2*8];
uint8_t left_border[17+2*9]; uint8_t left_border[2*(17+2*9)];
/** /**
* non zero coeff count cache. * non zero coeff count cache.
...@@ -233,6 +236,7 @@ typedef struct H264Context{ ...@@ -233,6 +236,7 @@ typedef struct H264Context{
int slice_type_fixed; int slice_type_fixed;
//interlacing specific flags //interlacing specific flags
int mb_aff_frame;
int mb_field_decoding_flag; int mb_field_decoding_flag;
int sub_mb_type[4]; int sub_mb_type[4];
...@@ -342,7 +346,7 @@ static VLC run7_vlc; ...@@ -342,7 +346,7 @@ static VLC run7_vlc;
static void svq3_luma_dc_dequant_idct_c(DCTELEM *block, int qp); static void svq3_luma_dc_dequant_idct_c(DCTELEM *block, int qp);
static void svq3_add_idct_c(uint8_t *dst, DCTELEM *block, int stride, int qp, int dc); static void svq3_add_idct_c(uint8_t *dst, DCTELEM *block, int stride, int qp, int dc);
static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr); static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize);
static inline uint32_t pack16to32(int a, int b){ static inline uint32_t pack16to32(int a, int b){
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
...@@ -438,7 +442,7 @@ static inline void fill_caches(H264Context *h, int mb_type, int for_deblock){ ...@@ -438,7 +442,7 @@ static inline void fill_caches(H264Context *h, int mb_type, int for_deblock){
left_block[5]= 10; left_block[5]= 10;
left_block[6]= 8; left_block[6]= 8;
left_block[7]= 11; left_block[7]= 11;
if(h->sps.mb_aff){ if(h->mb_aff_frame){
const int pair_xy = s->mb_x + (s->mb_y & ~1)*s->mb_stride; const int pair_xy = s->mb_x + (s->mb_y & ~1)*s->mb_stride;
const int top_pair_xy = pair_xy - s->mb_stride; const int top_pair_xy = pair_xy - s->mb_stride;
const int topleft_pair_xy = top_pair_xy - 1; const int topleft_pair_xy = top_pair_xy - 1;
...@@ -504,6 +508,11 @@ static inline void fill_caches(H264Context *h, int mb_type, int for_deblock){ ...@@ -504,6 +508,11 @@ static inline void fill_caches(H264Context *h, int mb_type, int for_deblock){
} }
} }
if(for_deblock){
h->top_mb_xy = top_xy;
h->left_mb_xy[0] = left_xy[0];
h->left_mb_xy[1] = left_xy[1];
}
if(for_deblock){ if(for_deblock){
topleft_type = h->slice_table[topleft_xy ] < 255 ? s->current_picture.mb_type[topleft_xy] : 0; topleft_type = h->slice_table[topleft_xy ] < 255 ? s->current_picture.mb_type[topleft_xy] : 0;
top_type = h->slice_table[top_xy ] < 255 ? s->current_picture.mb_type[top_xy] : 0; top_type = h->slice_table[top_xy ] < 255 ? s->current_picture.mb_type[top_xy] : 0;
...@@ -1663,9 +1672,9 @@ static void chroma_dc_dct_c(DCTELEM *block){ ...@@ -1663,9 +1672,9 @@ static void chroma_dc_dct_c(DCTELEM *block){
/** /**
* gets the chroma qp. * gets the chroma qp.
*/ */
static inline int get_chroma_qp(H264Context *h, int qscale){ static inline int get_chroma_qp(int chroma_qp_index_offset, int qscale){
return chroma_qp[clip(qscale + h->pps.chroma_qp_index_offset, 0, 51)]; return chroma_qp[clip(qscale + chroma_qp_index_offset, 0, 51)];
} }
...@@ -2598,7 +2607,8 @@ static void free_tables(H264Context *h){ ...@@ -2598,7 +2607,8 @@ static void free_tables(H264Context *h){
av_freep(&h->direct_table); av_freep(&h->direct_table);
av_freep(&h->non_zero_count); av_freep(&h->non_zero_count);
av_freep(&h->slice_table_base); av_freep(&h->slice_table_base);
av_freep(&h->top_border); av_freep(&h->top_borders[1]);
av_freep(&h->top_borders[0]);
h->slice_table= NULL; h->slice_table= NULL;
av_freep(&h->mb2b_xy); av_freep(&h->mb2b_xy);
...@@ -2620,7 +2630,8 @@ static int alloc_tables(H264Context *h){ ...@@ -2620,7 +2630,8 @@ static int alloc_tables(H264Context *h){
CHECKED_ALLOCZ(h->non_zero_count , big_mb_num * 16 * sizeof(uint8_t)) CHECKED_ALLOCZ(h->non_zero_count , big_mb_num * 16 * sizeof(uint8_t))
CHECKED_ALLOCZ(h->slice_table_base , big_mb_num * sizeof(uint8_t)) CHECKED_ALLOCZ(h->slice_table_base , big_mb_num * sizeof(uint8_t))
CHECKED_ALLOCZ(h->top_border , s->mb_width * (16+8+8) * sizeof(uint8_t)) CHECKED_ALLOCZ(h->top_borders[0] , s->mb_width * (16+8+8) * sizeof(uint8_t))
CHECKED_ALLOCZ(h->top_borders[1] , s->mb_width * (16+8+8) * sizeof(uint8_t))
CHECKED_ALLOCZ(h->cbp_table, big_mb_num * sizeof(uint16_t)) CHECKED_ALLOCZ(h->cbp_table, big_mb_num * sizeof(uint16_t))
if( h->pps.cabac ) { if( h->pps.cabac ) {
...@@ -2735,23 +2746,23 @@ static inline void backup_mb_border(H264Context *h, uint8_t *src_y, uint8_t *src ...@@ -2735,23 +2746,23 @@ static inline void backup_mb_border(H264Context *h, uint8_t *src_y, uint8_t *src
// There is two lines saved, the line above the the top macroblock of a pair, // There is two lines saved, the line above the the top macroblock of a pair,
// and the line above the bottom macroblock // and the line above the bottom macroblock
h->left_border[0]= h->top_border[s->mb_x][15]; h->left_border[0]= h->top_borders[0][s->mb_x][15];
for(i=1; i<17; i++){ for(i=1; i<17; i++){
h->left_border[i]= src_y[15+i* linesize]; h->left_border[i]= src_y[15+i* linesize];
} }
*(uint64_t*)(h->top_border[s->mb_x]+0)= *(uint64_t*)(src_y + 16*linesize); *(uint64_t*)(h->top_borders[0][s->mb_x]+0)= *(uint64_t*)(src_y + 16*linesize);
*(uint64_t*)(h->top_border[s->mb_x]+8)= *(uint64_t*)(src_y +8+16*linesize); *(uint64_t*)(h->top_borders[0][s->mb_x]+8)= *(uint64_t*)(src_y +8+16*linesize);
if(!(s->flags&CODEC_FLAG_GRAY)){ if(!(s->flags&CODEC_FLAG_GRAY)){
h->left_border[17 ]= h->top_border[s->mb_x][16+7]; h->left_border[17 ]= h->top_borders[0][s->mb_x][16+7];
h->left_border[17+9]= h->top_border[s->mb_x][24+7]; h->left_border[17+9]= h->top_borders[0][s->mb_x][24+7];
for(i=1; i<9; i++){ for(i=1; i<9; i++){
h->left_border[i+17 ]= src_cb[7+i*uvlinesize]; h->left_border[i+17 ]= src_cb[7+i*uvlinesize];
h->left_border[i+17+9]= src_cr[7+i*uvlinesize]; h->left_border[i+17+9]= src_cr[7+i*uvlinesize];
} }
*(uint64_t*)(h->top_border[s->mb_x]+16)= *(uint64_t*)(src_cb+8*uvlinesize); *(uint64_t*)(h->top_borders[0][s->mb_x]+16)= *(uint64_t*)(src_cb+8*uvlinesize);
*(uint64_t*)(h->top_border[s->mb_x]+24)= *(uint64_t*)(src_cr+8*uvlinesize); *(uint64_t*)(h->top_borders[0][s->mb_x]+24)= *(uint64_t*)(src_cr+8*uvlinesize);
} }
} }
...@@ -2779,8 +2790,8 @@ b= t; ...@@ -2779,8 +2790,8 @@ b= t;
} }
if(deblock_top){ if(deblock_top){
XCHG(*(uint64_t*)(h->top_border[s->mb_x]+0), *(uint64_t*)(src_y +1), temp64, xchg); XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+0), *(uint64_t*)(src_y +1), temp64, xchg);
XCHG(*(uint64_t*)(h->top_border[s->mb_x]+8), *(uint64_t*)(src_y +9), temp64, 1); XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+8), *(uint64_t*)(src_y +9), temp64, 1);
} }
if(!(s->flags&CODEC_FLAG_GRAY)){ if(!(s->flags&CODEC_FLAG_GRAY)){
...@@ -2791,8 +2802,93 @@ b= t; ...@@ -2791,8 +2802,93 @@ b= t;
} }
} }
if(deblock_top){ if(deblock_top){
XCHG(*(uint64_t*)(h->top_border[s->mb_x]+16), *(uint64_t*)(src_cb+1), temp64, 1); XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+16), *(uint64_t*)(src_cb+1), temp64, 1);
XCHG(*(uint64_t*)(h->top_border[s->mb_x]+24), *(uint64_t*)(src_cr+1), temp64, 1); XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+24), *(uint64_t*)(src_cr+1), temp64, 1);
}
}
}
static inline void backup_pair_border(H264Context *h, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, int linesize, int uvlinesize){
MpegEncContext * const s = &h->s;
int i;
src_y -= 2 * linesize;
src_cb -= 2 * uvlinesize;
src_cr -= 2 * uvlinesize;
// There is two lines saved, the line above the the top macroblock of a pair,
// and the line above the bottom macroblock
h->left_border[0]= h->top_borders[0][s->mb_x][15];
h->left_border[1]= h->top_borders[1][s->mb_x][15];
for(i=2; i<34; i++){
h->left_border[i]= src_y[15+i* linesize];
}
*(uint64_t*)(h->top_borders[0][s->mb_x]+0)= *(uint64_t*)(src_y + 32*linesize);
*(uint64_t*)(h->top_borders[0][s->mb_x]+8)= *(uint64_t*)(src_y +8+32*linesize);
*(uint64_t*)(h->top_borders[1][s->mb_x]+0)= *(uint64_t*)(src_y + 33*linesize);
*(uint64_t*)(h->top_borders[1][s->mb_x]+8)= *(uint64_t*)(src_y +8+33*linesize);
if(!(s->flags&CODEC_FLAG_GRAY)){
h->left_border[34 ]= h->top_borders[0][s->mb_x][16+7];
h->left_border[34+ 1]= h->top_borders[1][s->mb_x][16+7];
h->left_border[34+18 ]= h->top_borders[0][s->mb_x][24+7];
h->left_border[34+18+1]= h->top_borders[1][s->mb_x][24+7];
for(i=2; i<18; i++){
h->left_border[i+34 ]= src_cb[7+i*uvlinesize];
h->left_border[i+34+18]= src_cr[7+i*uvlinesize];
}
*(uint64_t*)(h->top_borders[0][s->mb_x]+16)= *(uint64_t*)(src_cb+16*uvlinesize);
*(uint64_t*)(h->top_borders[0][s->mb_x]+24)= *(uint64_t*)(src_cr+16*uvlinesize);
*(uint64_t*)(h->top_borders[1][s->mb_x]+16)= *(uint64_t*)(src_cb+17*uvlinesize);
*(uint64_t*)(h->top_borders[1][s->mb_x]+24)= *(uint64_t*)(src_cr+17*uvlinesize);
}
}
static inline void xchg_pair_border(H264Context *h, uint8_t *src_y, uint8_t *src_cb, uint8_t *src_cr, int linesize, int uvlinesize, int xchg){
MpegEncContext * const s = &h->s;
int temp8, i;
uint64_t temp64;
int deblock_left = (s->mb_x > 0);
int deblock_top = (s->mb_y > 0);
tprintf("xchg_pair_border: src_y:%p src_cb:%p src_cr:%p ls:%d uvls:%d\n", src_y, src_cb, src_cr, linesize, uvlinesize);
src_y -= 2 * linesize + 1;
src_cb -= 2 * uvlinesize + 1;
src_cr -= 2 * uvlinesize + 1;
#define XCHG(a,b,t,xchg)\
t= a;\
if(xchg)\
a= b;\
b= t;
if(deblock_left){
for(i = (!deblock_top)<<1; i<34; i++){
XCHG(h->left_border[i ], src_y [i* linesize], temp8, xchg);
}
}
if(deblock_top){
XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+0), *(uint64_t*)(src_y +1), temp64, xchg);
XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+8), *(uint64_t*)(src_y +9), temp64, 1);
XCHG(*(uint64_t*)(h->top_borders[1][s->mb_x]+0), *(uint64_t*)(src_y +1 +linesize), temp64, xchg);
XCHG(*(uint64_t*)(h->top_borders[1][s->mb_x]+8), *(uint64_t*)(src_y +9 +linesize), temp64, 1);
}
if(!(s->flags&CODEC_FLAG_GRAY)){
if(deblock_left){
for(i = (!deblock_top) << 1; i<18; i++){
XCHG(h->left_border[i+34 ], src_cb[i*uvlinesize], temp8, xchg);
XCHG(h->left_border[i+34+18], src_cr[i*uvlinesize], temp8, xchg);
}
}
if(deblock_top){
XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+16), *(uint64_t*)(src_cb+1), temp64, 1);
XCHG(*(uint64_t*)(h->top_borders[0][s->mb_x]+24), *(uint64_t*)(src_cr+1), temp64, 1);
XCHG(*(uint64_t*)(h->top_borders[1][s->mb_x]+16), *(uint64_t*)(src_cb+1 +uvlinesize), temp64, 1);
XCHG(*(uint64_t*)(h->top_borders[1][s->mb_x]+24), *(uint64_t*)(src_cr+1 +uvlinesize), temp64, 1);
} }
} }
} }
...@@ -2807,6 +2903,7 @@ static void hl_decode_mb(H264Context *h){ ...@@ -2807,6 +2903,7 @@ static void hl_decode_mb(H264Context *h){
int linesize, uvlinesize /*dct_offset*/; int linesize, uvlinesize /*dct_offset*/;
int i; int i;
int *block_offset = &h->block_offset[0]; int *block_offset = &h->block_offset[0];
const unsigned int bottom = mb_y & 1;
if(!s->decode) if(!s->decode)
return; return;
...@@ -2858,8 +2955,14 @@ static void hl_decode_mb(H264Context *h){ ...@@ -2858,8 +2955,14 @@ static void hl_decode_mb(H264Context *h){
} }
} else { } else {
if(IS_INTRA(mb_type)){ if(IS_INTRA(mb_type)){
if(h->deblocking_filter) if(h->deblocking_filter) {
if (h->mb_aff_frame) {
if (!bottom)
xchg_pair_border(h, dest_y, dest_cb, dest_cr, s->linesize, s->uvlinesize, 1);
} else {
xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 1); xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 1);
}
}
if(!(s->flags&CODEC_FLAG_GRAY)){ if(!(s->flags&CODEC_FLAG_GRAY)){
h->pred8x8[ h->chroma_pred_mode ](dest_cb, uvlinesize); h->pred8x8[ h->chroma_pred_mode ](dest_cb, uvlinesize);
...@@ -2881,7 +2984,7 @@ static void hl_decode_mb(H264Context *h){ ...@@ -2881,7 +2984,7 @@ static void hl_decode_mb(H264Context *h){
tr= ptr[3 - linesize]*0x01010101; tr= ptr[3 - linesize]*0x01010101;
topright= (uint8_t*) &tr; topright= (uint8_t*) &tr;
}else if(i==5 && h->deblocking_filter){ }else if(i==5 && h->deblocking_filter){
tr= *(uint32_t*)h->top_border[mb_x+1]; tr= *(uint32_t*)h->top_borders[h->mb_aff_frame ? IS_INTERLACED(mb_type) ? bottom : 1 : 0][mb_x+1];
topright= (uint8_t*) &tr; topright= (uint8_t*) &tr;
}else }else
topright= ptr + 4 - linesize; topright= ptr + 4 - linesize;
...@@ -2904,8 +3007,20 @@ static void hl_decode_mb(H264Context *h){ ...@@ -2904,8 +3007,20 @@ static void hl_decode_mb(H264Context *h){
else else
svq3_luma_dc_dequant_idct_c(h->mb, s->qscale); svq3_luma_dc_dequant_idct_c(h->mb, s->qscale);
} }
if(h->deblocking_filter) if(h->deblocking_filter) {
if (h->mb_aff_frame) {
if (bottom) {
uint8_t *pair_dest_y = s->current_picture.data[0] + ((mb_y-1) * 16* s->linesize ) + mb_x * 16;
uint8_t *pair_dest_cb = s->current_picture.data[1] + ((mb_y-1) * 8 * s->uvlinesize) + mb_x * 8;
uint8_t *pair_dest_cr = s->current_picture.data[2] + ((mb_y-1) * 8 * s->uvlinesize) + mb_x * 8;
s->mb_y--;
xchg_pair_border(h, pair_dest_y, pair_dest_cb, pair_dest_cr, s->linesize, s->uvlinesize, 0);
s->mb_y++;
}
} else {
xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 0); xchg_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize, 0);
}
}
}else if(s->codec_id == CODEC_ID_H264){ }else if(s->codec_id == CODEC_ID_H264){
hl_motion(h, dest_y, dest_cb, dest_cr, hl_motion(h, dest_y, dest_cb, dest_cr,
s->dsp.put_h264_qpel_pixels_tab, s->dsp.put_h264_chroma_pixels_tab, s->dsp.put_h264_qpel_pixels_tab, s->dsp.put_h264_chroma_pixels_tab,
...@@ -2965,9 +3080,42 @@ static void hl_decode_mb(H264Context *h){ ...@@ -2965,9 +3080,42 @@ static void hl_decode_mb(H264Context *h){
} }
} }
if(h->deblocking_filter) { if(h->deblocking_filter) {
if (h->mb_aff_frame) {
const int mb_y = s->mb_y - 1;
uint8_t *pair_dest_y, *pair_dest_cb, *pair_dest_cr;
const int mb_xy= mb_x + mb_y*s->mb_stride;
const int mb_type_top = s->current_picture.mb_type[mb_xy];
const int mb_type_bottom= s->current_picture.mb_type[mb_xy+s->mb_stride];
uint8_t tmp = s->current_picture.data[1][384];
if (!bottom) return;
pair_dest_y = s->current_picture.data[0] + (mb_y * 16* s->linesize ) + mb_x * 16;
pair_dest_cb = s->current_picture.data[1] + (mb_y * 8 * s->uvlinesize) + mb_x * 8;
pair_dest_cr = s->current_picture.data[2] + (mb_y * 8 * s->uvlinesize) + mb_x * 8;
backup_pair_border(h, pair_dest_y, pair_dest_cb, pair_dest_cr, s->linesize, s->uvlinesize);
// TODO deblock a pair
// top
s->mb_y--;
tprintf("call mbaff filter_mb mb_x:%d mb_y:%d pair_dest_y = %p, dest_y = %p\n", mb_x, mb_y, pair_dest_y, dest_y);
fill_caches(h, mb_type_top, 1); //FIXME dont fill stuff which isnt used by filter_mb
filter_mb(h, mb_x, mb_y, pair_dest_y, pair_dest_cb, pair_dest_cr, linesize, uvlinesize);
if (tmp != s->current_picture.data[1][384]) {
tprintf("modified pixel 8,1 (1)\n");
}
// bottom
s->mb_y++;
tprintf("call mbaff filter_mb\n");
fill_caches(h, mb_type_bottom, 1); //FIXME dont fill stuff which isnt used by filter_mb
filter_mb(h, mb_x, mb_y+1, dest_y, dest_cb, dest_cr, linesize, uvlinesize);
if (tmp != s->current_picture.data[1][384]) {
tprintf("modified pixel 8,1 (2)\n");
}
} else {
tprintf("call filter_mb\n");
backup_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize); backup_mb_border(h, dest_y, dest_cb, dest_cr, linesize, uvlinesize);
fill_caches(h, mb_type, 1); //FIXME dont fill stuff which isnt used by filter_mb fill_caches(h, mb_type, 1); //FIXME dont fill stuff which isnt used by filter_mb
filter_mb(h, mb_x, mb_y, dest_y, dest_cb, dest_cr); filter_mb(h, mb_x, mb_y, dest_y, dest_cb, dest_cr, linesize, uvlinesize);
}
} }
} }
...@@ -3679,19 +3827,21 @@ static int decode_slice_header(H264Context *h){ ...@@ -3679,19 +3827,21 @@ static int decode_slice_header(H264Context *h){
s->current_picture_ptr->frame_num= //FIXME frame_num cleanup s->current_picture_ptr->frame_num= //FIXME frame_num cleanup
h->frame_num= get_bits(&s->gb, h->sps.log2_max_frame_num); h->frame_num= get_bits(&s->gb, h->sps.log2_max_frame_num);
h->mb_aff_frame = 0;
if(h->sps.frame_mbs_only_flag){ if(h->sps.frame_mbs_only_flag){
s->picture_structure= PICT_FRAME; s->picture_structure= PICT_FRAME;
}else{ }else{
if(get_bits1(&s->gb)) //field_pic_flag if(get_bits1(&s->gb)) { //field_pic_flag
s->picture_structure= PICT_TOP_FIELD + get_bits1(&s->gb); //bottom_field_flag s->picture_structure= PICT_TOP_FIELD + get_bits1(&s->gb); //bottom_field_flag
else { } else {
s->picture_structure= PICT_FRAME; s->picture_structure= PICT_FRAME;
first_mb_in_slice <<= 1; first_mb_in_slice <<= 1;
h->mb_aff_frame = h->sps.mb_aff;
} }
} }
s->resync_mb_x = s->mb_x = first_mb_in_slice % s->mb_width; s->resync_mb_x = s->mb_x = first_mb_in_slice % s->mb_width;
s->resync_mb_y = s->mb_y = first_mb_in_slice / s->mb_width; //FIXME AFFW s->resync_mb_y = s->mb_y = first_mb_in_slice / s->mb_width;
if(s->picture_structure==PICT_FRAME){ if(s->picture_structure==PICT_FRAME){
h->curr_pic_num= h->frame_num; h->curr_pic_num= h->frame_num;
...@@ -3774,7 +3924,7 @@ static int decode_slice_header(H264Context *h){ ...@@ -3774,7 +3924,7 @@ static int decode_slice_header(H264Context *h){
av_log(s->avctx, AV_LOG_ERROR, "QP %d out of range\n", s->qscale); av_log(s->avctx, AV_LOG_ERROR, "QP %d out of range\n", s->qscale);
return -1; return -1;
} }
h->chroma_qp = get_chroma_qp(h, s->qscale); h->chroma_qp = get_chroma_qp(h->pps.chroma_qp_index_offset, s->qscale);
//FIXME qscale / qp ... stuff //FIXME qscale / qp ... stuff
if(h->slice_type == SP_TYPE){ if(h->slice_type == SP_TYPE){
get_bits1(&s->gb); /* sp_for_switch_flag */ get_bits1(&s->gb); /* sp_for_switch_flag */
...@@ -3997,11 +4147,16 @@ static void decode_mb_skip(H264Context *h){ ...@@ -3997,11 +4147,16 @@ static void decode_mb_skip(H264Context *h){
memset(h->non_zero_count[mb_xy], 0, 16); memset(h->non_zero_count[mb_xy], 0, 16);
memset(h->non_zero_count_cache + 8, 0, 8*5); //FIXME ugly, remove pfui memset(h->non_zero_count_cache + 8, 0, 8*5); //FIXME ugly, remove pfui
if(h->mb_aff_frame && 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;
if( h->slice_type == B_TYPE ) if( h->slice_type == B_TYPE )
{ {
// just for fill_caches. pred_direct_motion will set the real mb_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; mb_type= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P0L1|MB_TYPE_DIRECT2|MB_TYPE_SKIP;
//FIXME mbaff
fill_caches(h, mb_type, 0); //FIXME check what is needed and what not ... fill_caches(h, mb_type, 0); //FIXME check what is needed and what not ...
pred_direct_motion(h, &mb_type); pred_direct_motion(h, &mb_type);
...@@ -4015,12 +4170,6 @@ static void decode_mb_skip(H264Context *h){ ...@@ -4015,12 +4170,6 @@ static void decode_mb_skip(H264Context *h){
int mx, my; int mx, my;
mb_type= MB_TYPE_16x16|MB_TYPE_P0L0|MB_TYPE_P1L0|MB_TYPE_SKIP; 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, 0); //FIXME check what is needed and what not ... fill_caches(h, mb_type, 0); //FIXME check what is needed and what not ...
pred_pskip_motion(h, &mx, &my); pred_pskip_motion(h, &mx, &my);
fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1); fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1);
...@@ -4059,7 +4208,7 @@ static int decode_mb_cavlc(H264Context *h){ ...@@ -4059,7 +4208,7 @@ static int decode_mb_cavlc(H264Context *h){
return 0; return 0;
} }
} }
if(h->sps.mb_aff && s->picture_structure==PICT_FRAME ){ if(h->mb_aff_frame){
if ( ((s->mb_y&1) == 0) || h->prev_mb_skiped) if ( ((s->mb_y&1) == 0) || h->prev_mb_skiped)
h->mb_field_decoding_flag = get_bits1(&s->gb); h->mb_field_decoding_flag = get_bits1(&s->gb);
}else }else
...@@ -4134,7 +4283,7 @@ decode_intra_mb: ...@@ -4134,7 +4283,7 @@ decode_intra_mb:
// In deblocking, the quantiser is 0 // In deblocking, the quantiser is 0
s->current_picture.qscale_table[mb_xy]= 0; s->current_picture.qscale_table[mb_xy]= 0;
h->chroma_qp = get_chroma_qp(h, 0); h->chroma_qp = get_chroma_qp(h->pps.chroma_qp_index_offset, 0);
// All coeffs are presents // All coeffs are presents
memset(h->non_zero_count[mb_xy], 16, 16); memset(h->non_zero_count[mb_xy], 16, 16);
...@@ -4395,7 +4544,7 @@ decode_intra_mb: ...@@ -4395,7 +4544,7 @@ decode_intra_mb:
else s->qscale-= 52; else s->qscale-= 52;
} }
h->chroma_qp= chroma_qp= get_chroma_qp(h, s->qscale); h->chroma_qp= chroma_qp= get_chroma_qp(h->pps.chroma_qp_index_offset, s->qscale);
if(IS_INTRA16x16(mb_type)){ if(IS_INTRA16x16(mb_type)){
if( decode_residual(h, h->intra_gb_ptr, h->mb, LUMA_DC_BLOCK_INDEX, dc_scan, s->qscale, 16) < 0){ if( decode_residual(h, h->intra_gb_ptr, h->mb, LUMA_DC_BLOCK_INDEX, dc_scan, s->qscale, 16) < 0){
return -1; //FIXME continue if partotioned and other retirn -1 too return -1; //FIXME continue if partotioned and other retirn -1 too
...@@ -5082,7 +5231,7 @@ decode_intra_mb: ...@@ -5082,7 +5231,7 @@ decode_intra_mb:
h->chroma_pred_mode_table[mb_xy] = 0; h->chroma_pred_mode_table[mb_xy] = 0;
// In deblocking, the quantiser is 0 // In deblocking, the quantiser is 0
s->current_picture.qscale_table[mb_xy]= 0; s->current_picture.qscale_table[mb_xy]= 0;
h->chroma_qp = get_chroma_qp(h, 0); h->chroma_qp = get_chroma_qp(h->pps.chroma_qp_index_offset, 0);
// All coeffs are presents // All coeffs are presents
memset(h->non_zero_count[mb_xy], 16, 16); memset(h->non_zero_count[mb_xy], 16, 16);
return 0; return 0;
...@@ -5337,7 +5486,7 @@ decode_intra_mb: ...@@ -5337,7 +5486,7 @@ decode_intra_mb:
if(s->qscale<0) s->qscale+= 52; if(s->qscale<0) s->qscale+= 52;
else s->qscale-= 52; else s->qscale-= 52;
} }
h->chroma_qp = get_chroma_qp(h, s->qscale); h->chroma_qp = get_chroma_qp(h->pps.chroma_qp_index_offset, s->qscale);
if( IS_INTRA16x16( mb_type ) ) { if( IS_INTRA16x16( mb_type ) ) {
int i; int i;
...@@ -5449,6 +5598,7 @@ static void filter_mb_edgev( H264Context *h, uint8_t *pix, int stride, int bS[4] ...@@ -5449,6 +5598,7 @@ static void filter_mb_edgev( H264Context *h, uint8_t *pix, int stride, int bS[4]
i_delta = clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc ); i_delta = clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
pix[-1] = clip_uint8( p0 + i_delta ); /* p0' */ pix[-1] = clip_uint8( p0 + i_delta ); /* p0' */
pix[0] = clip_uint8( q0 - i_delta ); /* q0' */ pix[0] = clip_uint8( q0 - i_delta ); /* q0' */
tprintf("filter_mb_edgev i:%d d:%d, qp:%d, indexA:%d, alpha:%d, beta:%d, tc:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, qp, index_a, alpha, beta, tc, bS[i], pix[-3], p1, p0, q0, q1, pix[2], pix[-2], pix[-1], pix[0], pix[1]);
} }
pix += stride; pix += stride;
} }
...@@ -5495,6 +5645,7 @@ static void filter_mb_edgev( H264Context *h, uint8_t *pix, int stride, int bS[4] ...@@ -5495,6 +5645,7 @@ static void filter_mb_edgev( H264Context *h, uint8_t *pix, int stride, int bS[4]
pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2; pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
pix[ 0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; pix[ 0] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
} }
tprintf("filter_mb_edgev i:%d d:%d\n# bS:4 -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, p2, p1, p0, q0, q1, q2, pix[-2], pix[-1], pix[0], pix[1]);
} }
pix += stride; pix += stride;
} }
...@@ -5529,7 +5680,7 @@ static void filter_mb_edgecv( H264Context *h, uint8_t *pix, int stride, int bS[4 ...@@ -5529,7 +5680,7 @@ static void filter_mb_edgecv( H264Context *h, uint8_t *pix, int stride, int bS[4
pix[-1] = clip_uint8( p0 + i_delta ); /* p0' */ pix[-1] = clip_uint8( p0 + i_delta ); /* p0' */
pix[0] = clip_uint8( q0 - i_delta ); /* q0' */ pix[0] = clip_uint8( q0 - i_delta ); /* q0' */
//tprintf("filter_mb_edgecv i:%d d:%d, qp:%d, indexA:%d, alpha:%d, beta:%d, tc:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, qp, index_a, alpha, beta, tc, bS[i], pix[-3], p1, p0, q0, q1, pix[2], p1, pix[-1], pix[0], q1); tprintf("filter_mb_edgecv i:%d d:%d, qp:%d, indexA:%d, alpha:%d, beta:%d, tc:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, qp, index_a, alpha, beta, tc, bS[i], pix[-3], p1, p0, q0, q1, pix[2], p1, pix[-1], pix[0], q1);
} }
pix += stride; pix += stride;
} }
...@@ -5547,7 +5698,7 @@ static void filter_mb_edgecv( H264Context *h, uint8_t *pix, int stride, int bS[4 ...@@ -5547,7 +5698,7 @@ static void filter_mb_edgecv( H264Context *h, uint8_t *pix, int stride, int bS[4
pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2; /* p0' */ pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2; /* p0' */
pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; /* q0' */ pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; /* q0' */
//tprintf("filter_mb_edgecv i:%d d:%d\n# bS:4 -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, pix[-3], p1, p0, q0, q1, pix[2], p1, pix[-1], pix[0], q1); tprintf("filter_mb_edgecv i:%d d:%d\n# bS:4 -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, pix[-3], p1, p0, q0, q1, pix[2], p1, pix[-1], pix[0], q1);
} }
pix += stride; pix += stride;
} }
...@@ -5555,6 +5706,160 @@ static void filter_mb_edgecv( H264Context *h, uint8_t *pix, int stride, int bS[4 ...@@ -5555,6 +5706,160 @@ static void filter_mb_edgecv( H264Context *h, uint8_t *pix, int stride, int bS[4
} }
} }
static void filter_mb_mbaff_edgev( H264Context *h, uint8_t *pix, int stride, int bS[8], int qp[2] ) {
int i;
for( i = 0; i < 16; i++, pix += stride) {
int index_a;
int alpha;
int beta;
int qp_index;
int bS_index = (i >> 1);
if (h->mb_field_decoding_flag) {
bS_index &= ~1;
bS_index |= (i & 1);
}
if( bS[bS_index] == 0 ) {
continue;
}
qp_index = h->mb_field_decoding_flag ? (i & 1) : (i >> 3);
index_a = clip( qp[qp_index] + h->slice_alpha_c0_offset, 0, 51 );
alpha = alpha_table[index_a];
beta = beta_table[clip( qp[qp_index] + h->slice_beta_offset, 0, 51 )];
if( bS[bS_index] < 4 ) {
const int tc0 = tc0_table[index_a][bS[bS_index] - 1];
/* 4px edge length */
const int p0 = pix[-1];
const int p1 = pix[-2];
const int p2 = pix[-3];
const int q0 = pix[0];
const int q1 = pix[1];
const int q2 = pix[2];
if( ABS( p0 - q0 ) < alpha &&
ABS( p1 - p0 ) < beta &&
ABS( q1 - q0 ) < beta ) {
int tc = tc0;
int i_delta;
if( ABS( p2 - p0 ) < beta ) {
pix[-2] = p1 + clip( ( p2 + ( ( p0 + q0 + 1 ) >> 1 ) - ( p1 << 1 ) ) >> 1, -tc0, tc0 );
tc++;
}
if( ABS( q2 - q0 ) < beta ) {
pix[1] = q1 + clip( ( q2 + ( ( p0 + q0 + 1 ) >> 1 ) - ( q1 << 1 ) ) >> 1, -tc0, tc0 );
tc++;
}
i_delta = clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
pix[-1] = clip_uint8( p0 + i_delta ); /* p0' */
pix[0] = clip_uint8( q0 - i_delta ); /* q0' */
tprintf("filter_mb_mbaff_edgev i:%d, qp:%d, indexA:%d, alpha:%d, beta:%d, tc:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, qp[qp_index], index_a, alpha, beta, tc, bS[bS_index], pix[-3], p1, p0, q0, q1, pix[2], p1, pix[-1], pix[0], q1);
}
}else{
/* 4px edge length */
const int p0 = pix[-1];
const int p1 = pix[-2];
const int p2 = pix[-3];
const int q0 = pix[0];
const int q1 = pix[1];
const int q2 = pix[2];
if( ABS( p0 - q0 ) < alpha &&
ABS( p1 - p0 ) < beta &&
ABS( q1 - q0 ) < beta ) {
if(ABS( p0 - q0 ) < (( alpha >> 2 ) + 2 )){
if( ABS( p2 - p0 ) < beta)
{
const int p3 = pix[-4];
/* p0', p1', p2' */
pix[-1] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3;
pix[-2] = ( p2 + p1 + p0 + q0 + 2 ) >> 2;
pix[-3] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3;
} else {
/* p0' */
pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
}
if( ABS( q2 - q0 ) < beta)
{
const int q3 = pix[3];
/* q0', q1', q2' */
pix[0] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3;
pix[1] = ( p0 + q0 + q1 + q2 + 2 ) >> 2;
pix[2] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3;
} else {
/* q0' */
pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
}
}else{
/* p0', q0' */
pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
pix[ 0] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
}
tprintf("filter_mb_mbaff_edgev i:%d, qp:%d, indexA:%d, alpha:%d, beta:%d\n# bS:4 -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x, %02x, %02x]\n", i, qp[qp_index], index_a, alpha, beta, p2, p1, p0, q0, q1, q2, pix[-3], pix[-2], pix[-1], pix[0], pix[1], pix[2]);
}
}
}
}
static void filter_mb_mbaff_edgecv( H264Context *h, uint8_t *pix, int stride, int bS[4], int qp[2] ) {
int i;
for( i = 0; i < 8; i++, pix += stride) {
int index_a;
int alpha;
int beta;
int qp_index;
int bS_index = i;
if( bS[bS_index] == 0 ) {
continue;
}
qp_index = h->mb_field_decoding_flag ? (i & 1) : (i >> 3);
index_a = clip( qp[qp_index] + h->slice_alpha_c0_offset, 0, 51 );
alpha = alpha_table[index_a];
beta = beta_table[clip( qp[qp_index] + h->slice_beta_offset, 0, 51 )];
if( bS[bS_index] < 4 ) {
const int tc = tc0_table[index_a][bS[bS_index] - 1] + 1;
/* 2px edge length (because we use same bS than the one for luma) */
const int p0 = pix[-1];
const int p1 = pix[-2];
const int q0 = pix[0];
const int q1 = pix[1];
if( ABS( p0 - q0 ) < alpha &&
ABS( p1 - p0 ) < beta &&
ABS( q1 - q0 ) < beta ) {
const int i_delta = clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
pix[-1] = clip_uint8( p0 + i_delta ); /* p0' */
pix[0] = clip_uint8( q0 - i_delta ); /* q0' */
tprintf("filter_mb_mbaff_edgecv i:%d, qp:%d, indexA:%d, alpha:%d, beta:%d, tc:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, qp[qp_index], index_a, alpha, beta, tc, bS[bS_index], pix[-3], p1, p0, q0, q1, pix[2], p1, pix[-1], pix[0], q1);
}
}else{
const int p0 = pix[-1];
const int p1 = pix[-2];
const int q0 = pix[0];
const int q1 = pix[1];
if( ABS( p0 - q0 ) < alpha &&
ABS( p1 - p0 ) < beta &&
ABS( q1 - q0 ) < beta ) {
pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2; /* p0' */
pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; /* q0' */
tprintf("filter_mb_mbaff_edgecv i:%d\n# bS:4 -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x, %02x, %02x]\n", i, pix[-3], p1, p0, q0, q1, pix[2], pix[-3], pix[-2], pix[-1], pix[0], pix[1], pix[2]);
}
}
}
}
static void filter_mb_edgeh( H264Context *h, uint8_t *pix, int stride, int bS[4], int qp ) { static void filter_mb_edgeh( H264Context *h, uint8_t *pix, int stride, int bS[4], int qp ) {
int i, d; int i, d;
const int index_a = clip( qp + h->slice_alpha_c0_offset, 0, 51 ); const int index_a = clip( qp + h->slice_alpha_c0_offset, 0, 51 );
...@@ -5598,6 +5903,7 @@ static void filter_mb_edgeh( H264Context *h, uint8_t *pix, int stride, int bS[4] ...@@ -5598,6 +5903,7 @@ static void filter_mb_edgeh( H264Context *h, uint8_t *pix, int stride, int bS[4]
i_delta = clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc ); i_delta = clip( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
pix[-pix_next] = clip_uint8( p0 + i_delta ); /* p0' */ pix[-pix_next] = clip_uint8( p0 + i_delta ); /* p0' */
pix[0] = clip_uint8( q0 - i_delta ); /* q0' */ pix[0] = clip_uint8( q0 - i_delta ); /* q0' */
tprintf("filter_mb_edgeh i:%d d:%d, qp:%d, indexA:%d, alpha:%d, beta:%d, tc:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, qp, index_a, alpha, beta, tc, bS[i], p2, p1, p0, q0, q1, q2, pix[-2*pix_next], pix[-pix_next], pix[0], pix[pix_next]);
} }
pix++; pix++;
} }
...@@ -5642,6 +5948,7 @@ static void filter_mb_edgeh( H264Context *h, uint8_t *pix, int stride, int bS[4] ...@@ -5642,6 +5948,7 @@ static void filter_mb_edgeh( H264Context *h, uint8_t *pix, int stride, int bS[4]
pix[-1*pix_next] = ( 2*p1 + p0 + q1 + 2 ) >> 2; pix[-1*pix_next] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
pix[ 0*pix_next] = ( 2*q1 + q0 + p1 + 2 ) >> 2; pix[ 0*pix_next] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
} }
tprintf("filter_mb_edgeh i:%d d:%d, qp:%d, indexA:%d, alpha:%d, beta:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, qp, index_a, alpha, beta, bS[i], p2, p1, p0, q0, q1, q2, pix[-2*pix_next], pix[-pix_next], pix[0], pix[pix_next]);
} }
pix++; pix++;
} }
...@@ -5680,6 +5987,7 @@ static void filter_mb_edgech( H264Context *h, uint8_t *pix, int stride, int bS[4 ...@@ -5680,6 +5987,7 @@ static void filter_mb_edgech( H264Context *h, uint8_t *pix, int stride, int bS[4
pix[-pix_next] = clip_uint8( p0 + i_delta ); /* p0' */ pix[-pix_next] = clip_uint8( p0 + i_delta ); /* p0' */
pix[0] = clip_uint8( q0 - i_delta ); /* q0' */ pix[0] = clip_uint8( q0 - i_delta ); /* q0' */
tprintf("filter_mb_edgech i:%d d:%d, qp:%d, indexA:%d, alpha:%d, beta:%d, tc:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, qp, index_a, alpha, beta, tc, bS[i], pix[-3*pix_next], p1, p0, q0, q1, pix[2*pix_next], pix[-2*pix_next], pix[-pix_next], pix[0], pix[pix_next]);
} }
pix++; pix++;
} }
...@@ -5697,6 +6005,7 @@ static void filter_mb_edgech( H264Context *h, uint8_t *pix, int stride, int bS[4 ...@@ -5697,6 +6005,7 @@ static void filter_mb_edgech( H264Context *h, uint8_t *pix, int stride, int bS[4
pix[-pix_next] = ( 2*p1 + p0 + q1 + 2 ) >> 2; /* p0' */ pix[-pix_next] = ( 2*p1 + p0 + q1 + 2 ) >> 2; /* p0' */
pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; /* q0' */ pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; /* q0' */
tprintf("filter_mb_edgech i:%d d:%d, qp:%d, indexA:%d, alpha:%d, beta:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, qp, index_a, alpha, beta, bS[i], pix[-3*pix_next], p1, p0, q0, q1, pix[2*pix_next], pix[-2*pix_next], pix[-pix_next], pix[0], pix[pix_next]);
} }
pix++; pix++;
} }
...@@ -5704,39 +6013,167 @@ static void filter_mb_edgech( H264Context *h, uint8_t *pix, int stride, int bS[4 ...@@ -5704,39 +6013,167 @@ static void filter_mb_edgech( H264Context *h, uint8_t *pix, int stride, int bS[4
} }
} }
static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr) { static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize) {
MpegEncContext * const s = &h->s; MpegEncContext * const s = &h->s;
const int mb_xy= mb_x + mb_y*s->mb_stride; const int mb_xy= mb_x + mb_y*s->mb_stride;
int linesize, uvlinesize; int first_vertical_edge_done = 0;
int dir; int dir;
/* FIXME Implement deblocking filter for field MB */ if (h->mb_aff_frame
if( h->sps.mb_aff ) { // left mb is in picture
return; && h->slice_table[mb_xy-1] != 255
// and current and left pair do not have the same interlaced type
&& (IS_INTERLACED(s->current_picture.mb_type[mb_xy]) != IS_INTERLACED(s->current_picture.mb_type[mb_xy-1]))
// and left mb is in the same slice if deblocking_filter == 2
&& (h->deblocking_filter!=2 || h->slice_table[mb_xy-1] == h->slice_table[mb_xy])) {
/* First vertical edge is different in MBAFF frames
* There are 8 differents bS to compute and 2 differents Qp
*/
int bS[8];
int qp[2];
int chroma_qp[2];
int i;
first_vertical_edge_done = 1;
for( i = 0; i < 8; i++ ) {
int y = i>>1;
int b_idx= 8 + 4 + 8*y;
int bn_idx= b_idx - 1;
int mbn_xy = h->mb_field_decoding_flag ? h->left_mb_xy[i>>2] : h->left_mb_xy[i&1];
if( IS_INTRA( s->current_picture.mb_type[mb_xy] ) ||
IS_INTRA( s->current_picture.mb_type[mbn_xy] ) ) {
bS[i] = 4;
} else if( h->non_zero_count_cache[b_idx] != 0 ||
h->non_zero_count_cache[bn_idx] != 0 ) {
bS[i] = 2;
} else {
/* FIXME: A given frame may occupy more than one position in
* the reference list. So we should compare the frame numbers,
* not the indices in the ref list. */
int l;
bS[i] = 0;
for( l = 0; l < 1 + (h->slice_type == B_TYPE); l++ ) {
if( h->ref_cache[l][b_idx] != h->ref_cache[l][bn_idx] ||
ABS( h->mv_cache[l][b_idx][0] - h->mv_cache[l][bn_idx][0] ) >= 4 ||
ABS( h->mv_cache[l][b_idx][1] - h->mv_cache[l][bn_idx][1] ) >= 4 ) {
bS[i] = 1;
break;
} }
linesize = s->linesize; }
uvlinesize = s->uvlinesize; }
}
if(bS[0]+bS[1]+bS[2]+bS[3] != 0) {
// Do not use s->qscale as luma quantiser because it has not the same
// value in IPCM macroblocks.
qp[0] = ( s->current_picture.qscale_table[mb_xy] + s->current_picture.qscale_table[h->left_mb_xy[0]] + 1 ) >> 1;
chroma_qp[0] = ( get_chroma_qp( h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[mb_xy] ) +
get_chroma_qp( h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[h->left_mb_xy[0]] ) + 1 ) >> 1;
qp[1] = ( s->current_picture.qscale_table[mb_xy] + s->current_picture.qscale_table[h->left_mb_xy[1]] + 1 ) >> 1;
chroma_qp[1] = ( get_chroma_qp( h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[mb_xy] ) +
get_chroma_qp( h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[h->left_mb_xy[1]] ) + 1 ) >> 1;
/* Filter edge */
tprintf("filter mb:%d/%d MBAFF, QPy:%d/%d, QPc:%d/%d ls:%d uvls:%d", mb_x, mb_y, qp[0], qp[1], chroma_qp[0], chroma_qp[1], linesize, uvlinesize);
{ int i; for (i = 0; i < 8; i++) tprintf(" bS[%d]:%d", i, bS[i]); tprintf("\n"); }
filter_mb_mbaff_edgev ( h, &img_y [0], linesize, bS, qp );
filter_mb_mbaff_edgecv( h, &img_cb[0], uvlinesize, bS, chroma_qp );
filter_mb_mbaff_edgecv( h, &img_cr[0], uvlinesize, bS, chroma_qp );
}
}
/* dir : 0 -> vertical edge, 1 -> horizontal edge */ /* dir : 0 -> vertical edge, 1 -> horizontal edge */
for( dir = 0; dir < 2; dir++ ) for( dir = 0; dir < 2; dir++ )
{ {
int edge; int edge;
const int mbm_xy = dir == 0 ? mb_xy -1 : mb_xy - s->mb_stride; const int mbm_xy = dir == 0 ? mb_xy -1 : h->top_mb_xy;
int start = h->slice_table[mbm_xy] == 255 ? 1 : 0; int start = h->slice_table[mbm_xy] == 255 ? 1 : 0;
if (first_vertical_edge_done) {
start = 1;
first_vertical_edge_done = 0;
}
if (h->deblocking_filter==2 && h->slice_table[mbm_xy] != h->slice_table[mb_xy]) if (h->deblocking_filter==2 && h->slice_table[mbm_xy] != h->slice_table[mb_xy])
start = 1; start = 1;
/* Calculate bS */ /* Calculate bS */
for( edge = start; edge < 4; edge++ ) { for( edge = start; edge < 4; edge++ ) {
/* mbn_xy: neighbour macroblock (how that works for field ?) */ /* mbn_xy: neighbour macroblock */
int mbn_xy = edge > 0 ? mb_xy : mbm_xy; int mbn_xy = edge > 0 ? mb_xy : mbm_xy;
int bS[4]; int bS[4];
int qp; int qp;
if (h->mb_aff_frame && (dir == 1) && (edge == 0) && ((mb_y & 1) == 0)
&& !IS_INTERLACED(s->current_picture.mb_type[mb_xy])
&& IS_INTERLACED(s->current_picture.mb_type[mbn_xy])
) {
// This is a special case in the norm where the filtering must
// be done twice (one each of the field) even if we are in a
// frame macroblock.
//
unsigned int tmp_linesize = 2 * linesize;
unsigned int tmp_uvlinesize = 2 * uvlinesize;
int mbn_xy = mb_xy - 2 * s->mb_stride;
int qp, chroma_qp;
// first filtering
if( IS_INTRA( s->current_picture.mb_type[mb_xy] ) || if( IS_INTRA( s->current_picture.mb_type[mb_xy] ) ||
IS_INTRA( s->current_picture.mb_type[mbn_xy] ) ) { IS_INTRA( s->current_picture.mb_type[mbn_xy] ) ) {
bS[0] = bS[1] = bS[2] = bS[3] = ( edge == 0 ? 4 : 3 ); bS[0] = bS[1] = bS[2] = bS[3] = 3;
} else {
// TODO
assert(0);
}
/* Filter edge */
// Do not use s->qscale as luma quantiser because it has not the same
// value in IPCM macroblocks.
qp = ( s->current_picture.qscale_table[mb_xy] + s->current_picture.qscale_table[mbn_xy] + 1 ) >> 1;
tprintf("filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, tmp_linesize, tmp_uvlinesize);
{ int i; for (i = 0; i < 4; i++) tprintf(" bS[%d]:%d", i, bS[i]); tprintf("\n"); }
filter_mb_edgeh( h, &img_y[0], tmp_linesize, bS, qp );
chroma_qp = ( h->chroma_qp +
get_chroma_qp( h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1;
filter_mb_edgech( h, &img_cb[0], tmp_uvlinesize, bS, chroma_qp );
filter_mb_edgech( h, &img_cr[0], tmp_uvlinesize, bS, chroma_qp );
// second filtering
mbn_xy += s->mb_stride;
if( IS_INTRA( s->current_picture.mb_type[mb_xy] ) ||
IS_INTRA( s->current_picture.mb_type[mbn_xy] ) ) {
bS[0] = bS[1] = bS[2] = bS[3] = 3;
} else {
// TODO
assert(0);
}
/* Filter edge */
// Do not use s->qscale as luma quantiser because it has not the same
// value in IPCM macroblocks.
qp = ( s->current_picture.qscale_table[mb_xy] + s->current_picture.qscale_table[mbn_xy] + 1 ) >> 1;
tprintf("filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, tmp_linesize, tmp_uvlinesize);
{ int i; for (i = 0; i < 4; i++) tprintf(" bS[%d]:%d", i, bS[i]); tprintf("\n"); }
filter_mb_edgeh( h, &img_y[linesize], tmp_linesize, bS, qp );
chroma_qp = ( h->chroma_qp +
get_chroma_qp( h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1;
filter_mb_edgech( h, &img_cb[uvlinesize], tmp_uvlinesize, bS, chroma_qp );
filter_mb_edgech( h, &img_cr[uvlinesize], tmp_uvlinesize, bS, chroma_qp );
continue;
}
if( IS_INTRA( s->current_picture.mb_type[mb_xy] ) ||
IS_INTRA( s->current_picture.mb_type[mbn_xy] ) ) {
int value;
if (edge == 0) {
if ( (!IS_INTERLACED(s->current_picture.mb_type[mb_xy]) && !IS_INTERLACED(s->current_picture.mb_type[mbm_xy]))
|| ((h->mb_aff_frame || (s->picture_structure != PICT_FRAME)) && (dir == 0))
) {
value = 4;
} else {
value = 3;
}
} else {
value = 3;
}
bS[0] = bS[1] = bS[2] = bS[3] = value;
} else { } else {
int i; int i;
for( i = 0; i < 4; i++ ) { for( i = 0; i < 4; i++ ) {
...@@ -5776,11 +6213,13 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8 ...@@ -5776,11 +6213,13 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8
// value in IPCM macroblocks. // value in IPCM macroblocks.
qp = ( s->current_picture.qscale_table[mb_xy] + s->current_picture.qscale_table[mbn_xy] + 1 ) >> 1; qp = ( s->current_picture.qscale_table[mb_xy] + s->current_picture.qscale_table[mbn_xy] + 1 ) >> 1;
//tprintf("filter mb:%d/%d dir:%d edge:%d, QPy:%d, QPc:%d, QPcn:%d\n", mb_x, mb_y, dir, edge, qp, h->chroma_qp, s->current_picture.qscale_table[mbn_xy]); //tprintf("filter mb:%d/%d dir:%d edge:%d, QPy:%d, QPc:%d, QPcn:%d\n", mb_x, mb_y, dir, edge, qp, h->chroma_qp, s->current_picture.qscale_table[mbn_xy]);
tprintf("filter mb:%d/%d dir:%d edge:%d, QPy:%d ls:%d uvls:%d", mb_x, mb_y, dir, edge, qp, linesize, uvlinesize);
{ int i; for (i = 0; i < 4; i++) tprintf(" bS[%d]:%d", i, bS[i]); tprintf("\n"); }
if( dir == 0 ) { if( dir == 0 ) {
filter_mb_edgev( h, &img_y[4*edge], linesize, bS, qp ); filter_mb_edgev( h, &img_y[4*edge], linesize, bS, qp );
if( (edge&1) == 0 ) { if( (edge&1) == 0 ) {
int chroma_qp = ( h->chroma_qp + int chroma_qp = ( h->chroma_qp +
get_chroma_qp( h, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1; get_chroma_qp( h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1;
filter_mb_edgecv( h, &img_cb[2*edge], uvlinesize, bS, chroma_qp ); filter_mb_edgecv( h, &img_cb[2*edge], uvlinesize, bS, chroma_qp );
filter_mb_edgecv( h, &img_cr[2*edge], uvlinesize, bS, chroma_qp ); filter_mb_edgecv( h, &img_cr[2*edge], uvlinesize, bS, chroma_qp );
} }
...@@ -5788,7 +6227,7 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8 ...@@ -5788,7 +6227,7 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8
filter_mb_edgeh( h, &img_y[4*edge*linesize], linesize, bS, qp ); filter_mb_edgeh( h, &img_y[4*edge*linesize], linesize, bS, qp );
if( (edge&1) == 0 ) { if( (edge&1) == 0 ) {
int chroma_qp = ( h->chroma_qp + int chroma_qp = ( h->chroma_qp +
get_chroma_qp( h, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1; get_chroma_qp( h->pps.chroma_qp_index_offset, s->current_picture.qscale_table[mbn_xy] ) + 1 ) >> 1;
filter_mb_edgech( h, &img_cb[2*edge*uvlinesize], uvlinesize, bS, chroma_qp ); filter_mb_edgech( h, &img_cb[2*edge*uvlinesize], uvlinesize, bS, chroma_qp );
filter_mb_edgech( h, &img_cr[2*edge*uvlinesize], uvlinesize, bS, chroma_qp ); filter_mb_edgech( h, &img_cr[2*edge*uvlinesize], uvlinesize, bS, chroma_qp );
} }
...@@ -5835,7 +6274,7 @@ static int decode_slice(H264Context *h){ ...@@ -5835,7 +6274,7 @@ static int decode_slice(H264Context *h){
if(ret>=0) hl_decode_mb(h); if(ret>=0) hl_decode_mb(h);
/* XXX: useless as decode_mb_cabac it doesn't support that ... */ /* XXX: useless as decode_mb_cabac it doesn't support that ... */
if( ret >= 0 && h->sps.mb_aff ) { //FIXME optimal? or let mb_decode decode 16x32 ? if( ret >= 0 && h->mb_aff_frame ) { //FIXME optimal? or let mb_decode decode 16x32 ?
s->mb_y++; s->mb_y++;
if(ret>=0) ret = decode_mb_cabac(h); if(ret>=0) ret = decode_mb_cabac(h);
...@@ -5855,7 +6294,7 @@ static int decode_slice(H264Context *h){ ...@@ -5855,7 +6294,7 @@ static int decode_slice(H264Context *h){
s->mb_x = 0; s->mb_x = 0;
ff_draw_horiz_band(s, 16*s->mb_y, 16); ff_draw_horiz_band(s, 16*s->mb_y, 16);
++s->mb_y; ++s->mb_y;
if(h->sps.mb_aff && s->picture_structure==PICT_FRAME ) { if(h->mb_aff_frame) {
++s->mb_y; ++s->mb_y;
} }
} }
...@@ -5865,13 +6304,6 @@ static int decode_slice(H264Context *h){ ...@@ -5865,13 +6304,6 @@ static int decode_slice(H264Context *h){
ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, (AC_END|DC_END|MV_END)&part_mask); ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
return 0; return 0;
} }
#if 0
/* TODO test over-reading in cabac code */
else if( read too much in h->cabac ) {
ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_ERROR|DC_ERROR|MV_ERROR)&part_mask);
return -1;
}
#endif
} }
} else { } else {
...@@ -5880,7 +6312,7 @@ static int decode_slice(H264Context *h){ ...@@ -5880,7 +6312,7 @@ static int decode_slice(H264Context *h){
if(ret>=0) hl_decode_mb(h); if(ret>=0) hl_decode_mb(h);
if(ret>=0 && h->sps.mb_aff){ //FIXME optimal? or let mb_decode decode 16x32 ? if(ret>=0 && h->mb_aff_frame){ //FIXME optimal? or let mb_decode decode 16x32 ?
s->mb_y++; s->mb_y++;
ret = decode_mb_cavlc(h); ret = decode_mb_cavlc(h);
...@@ -5899,7 +6331,7 @@ static int decode_slice(H264Context *h){ ...@@ -5899,7 +6331,7 @@ static int decode_slice(H264Context *h){
s->mb_x=0; s->mb_x=0;
ff_draw_horiz_band(s, 16*s->mb_y, 16); ff_draw_horiz_band(s, 16*s->mb_y, 16);
++s->mb_y; ++s->mb_y;
if(h->sps.mb_aff && s->picture_structure==PICT_FRAME ) { if(h->mb_aff_frame) {
++s->mb_y; ++s->mb_y;
} }
if(s->mb_y >= s->mb_height){ if(s->mb_y >= s->mb_height){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment