static int fill_filter_caches(const H264Context *h, H264SliceContext *sl, int mb_type) { const int mb_xy = sl->mb_xy; int top_xy, left_xy[LEFT_MBS]; int top_type, left_type[LEFT_MBS]; uint8_t *nnz; uint8_t *nnz_cache; top_xy = mb_xy - (h->mb_stride << MB_FIELD(sl)); /* Wow, what a mess, why didn't they simplify the interlacing & intra * stuff, I can't imagine that these complex rules are worth it. */ left_xy[LBOT] = left_xy[LTOP] = mb_xy - 1; if (FRAME_MBAFF(h)) { const int left_mb_field_flag = IS_INTERLACED(h->cur_pic.mb_type[mb_xy - 1]); const int curr_mb_field_flag = IS_INTERLACED(mb_type); if (sl->mb_y & 1) { if (left_mb_field_flag != curr_mb_field_flag) left_xy[LTOP] -= h->mb_stride; } else { if (curr_mb_field_flag) top_xy += h->mb_stride & (((h->cur_pic.mb_type[top_xy] >> 7) & 1) - 1); if (left_mb_field_flag != curr_mb_field_flag) left_xy[LBOT] += h->mb_stride; } } sl->top_mb_xy = top_xy; sl->left_mb_xy[LTOP] = left_xy[LTOP]; sl->left_mb_xy[LBOT] = left_xy[LBOT]; { /* For sufficiently low qp, filtering wouldn't do anything. * This is a conservative estimate: could also check beta_offset * and more accurate chroma_qp. */ int qp_thresh = sl->qp_thresh; // FIXME strictly we should store qp_thresh for each mb of a slice int qp = h->cur_pic.qscale_table[mb_xy]; if (qp <= qp_thresh && (left_xy[LTOP] < 0 || ((qp + h->cur_pic.qscale_table[left_xy[LTOP]] + 1) >> 1) <= qp_thresh) && (top_xy < 0 || ((qp + h->cur_pic.qscale_table[top_xy] + 1) >> 1) <= qp_thresh)) { if (!FRAME_MBAFF(h)) return 1; if ((left_xy[LTOP] < 0 || ((qp + h->cur_pic.qscale_table[left_xy[LBOT]] + 1) >> 1) <= qp_thresh) && (top_xy < h->mb_stride || ((qp + h->cur_pic.qscale_table[top_xy - h->mb_stride] + 1) >> 1) <= qp_thresh)) return 1; } } top_type = h->cur_pic.mb_type[top_xy]; left_type[LTOP] = h->cur_pic.mb_type[left_xy[LTOP]]; left_type[LBOT] = h->cur_pic.mb_type[left_xy[LBOT]]; if (sl->deblocking_filter == 2) { if (h->slice_table[top_xy] != sl->slice_num) top_type = 0; if (h->slice_table[left_xy[LBOT]] != sl->slice_num) left_type[LTOP] = left_type[LBOT] = 0; } else { if (h->slice_table[top_xy] == 0xFFFF) top_type = 0; if (h->slice_table[left_xy[LBOT]] == 0xFFFF) left_type[LTOP] = left_type[LBOT] = 0; } sl->top_type = top_type; sl->left_type[LTOP] = left_type[LTOP]; sl->left_type[LBOT] = left_type[LBOT]; if (IS_INTRA(mb_type)) return 0; fill_filter_caches_inter(h, sl, mb_type, top_xy, left_xy, top_type, left_type, mb_xy, 0); if (sl->list_count == 2) fill_filter_caches_inter(h, sl, mb_type, top_xy, left_xy, top_type, left_type, mb_xy, 1); nnz = h->non_zero_count[mb_xy]; nnz_cache = sl->non_zero_count_cache; AV_COPY32(&nnz_cache[4 + 8 * 1], &nnz[0]); AV_COPY32(&nnz_cache[4 + 8 * 2], &nnz[4]); AV_COPY32(&nnz_cache[4 + 8 * 3], &nnz[8]); AV_COPY32(&nnz_cache[4 + 8 * 4], &nnz[12]); sl->cbp = h->cbp_table[mb_xy]; if (top_type) { nnz = h->non_zero_count[top_xy]; AV_COPY32(&nnz_cache[4 + 8 * 0], &nnz[3 * 4]); } if (left_type[LTOP]) { nnz = h->non_zero_count[left_xy[LTOP]]; nnz_cache[3 + 8 * 1] = nnz[3 + 0 * 4]; nnz_cache[3 + 8 * 2] = nnz[3 + 1 * 4]; nnz_cache[3 + 8 * 3] = nnz[3 + 2 * 4]; nnz_cache[3 + 8 * 4] = nnz[3 + 3 * 4]; } /* CAVLC 8x8dct requires NNZ values for residual decoding that differ * from what the loop filter needs */ if (!CABAC(h) && h->pps.transform_8x8_mode) { if (IS_8x8DCT(top_type)) { nnz_cache[4 + 8 * 0] = nnz_cache[5 + 8 * 0] = (h->cbp_table[top_xy] & 0x4000) >> 12; nnz_cache[6 + 8 * 0] = nnz_cache[7 + 8 * 0] = (h->cbp_table[top_xy] & 0x8000) >> 12; } if (IS_8x8DCT(left_type[LTOP])) { nnz_cache[3 + 8 * 1] = nnz_cache[3 + 8 * 2] = (h->cbp_table[left_xy[LTOP]] & 0x2000) >> 12; // FIXME check MBAFF } if (IS_8x8DCT(left_type[LBOT])) { nnz_cache[3 + 8 * 3] = nnz_cache[3 + 8 * 4] = (h->cbp_table[left_xy[LBOT]] & 0x8000) >> 12; // FIXME check MBAFF } if (IS_8x8DCT(mb_type)) { nnz_cache[scan8[0]] = nnz_cache[scan8[1]] = nnz_cache[scan8[2]] = nnz_cache[scan8[3]] = (sl->cbp & 0x1000) >> 12; nnz_cache[scan8[0 + 4]] = nnz_cache[scan8[1 + 4]] = nnz_cache[scan8[2 + 4]] = nnz_cache[scan8[3 + 4]] = (sl->cbp & 0x2000) >> 12; nnz_cache[scan8[0 + 8]] = nnz_cache[scan8[1 + 8]] = nnz_cache[scan8[2 + 8]] = nnz_cache[scan8[3 + 8]] = (sl->cbp & 0x4000) >> 12; nnz_cache[scan8[0 + 12]] = nnz_cache[scan8[1 + 12]] = nnz_cache[scan8[2 + 12]] = nnz_cache[scan8[3 + 12]] = (sl->cbp & 0x8000) >> 12; } } return 0; }