/* * Tests the 4 H.264 Intra_8x8 chroma prediction modes against * spec-derived expected patterns. Same buffer layout idea as the * other intra tests: a buffer that holds the 8x8 output + 1-pixel * top/left context + 1-pixel top-left corner. * * row 0: [tl][t0..t7] * row 1: [l0][output row 0] * ... * row 8: [l7][output row 7] * * Dimensions: 9 rows × 9 cols. dst (passed to pred fns) = &buf[1][1]. */ #include #include #include #include extern void daedalus_h264_pred_chroma8x8_dc_ref(uint8_t *dst, ptrdiff_t stride); extern void daedalus_h264_pred_chroma8x8_horizontal_ref(uint8_t *dst, ptrdiff_t stride); extern void daedalus_h264_pred_chroma8x8_vertical_ref(uint8_t *dst, ptrdiff_t stride); extern void daedalus_h264_pred_chroma8x8_plane_ref(uint8_t *dst, ptrdiff_t stride); #define STRIDE 9 #define ROWS 9 static void set_ctx(uint8_t buf[ROWS][STRIDE], int tl, const int t[8], const int l[8]) { for (int r = 0; r < ROWS; r++) for (int c = 0; c < STRIDE; c++) buf[r][c] = 0xff; buf[0][0] = (uint8_t) tl; for (int c = 0; c < 8; c++) buf[0][1 + c] = (uint8_t) t[c]; for (int r = 0; r < 8; r++) buf[1 + r][0] = (uint8_t) l[r]; } static int check_per_cell(const uint8_t buf[ROWS][STRIDE], const char *name, const uint8_t expect[8][8]) { int diff = 0; int first_r = 0, first_c = 0, first_got = 0, first_exp = 0; for (int r = 0; r < 8; r++) { for (int c = 0; c < 8; c++) { uint8_t got = buf[1 + r][1 + c]; uint8_t exp = expect[r][c]; if (got != exp) { if (diff == 0) { first_r = r; first_c = c; first_got = got; first_exp = exp; } diff++; } } } if (diff == 0) printf(" %-30s PASS\n", name); else printf(" %-30s FAIL (%d/64 wrong, first r=%d c=%d got=%u exp=%u)\n", name, diff, first_r, first_c, first_got, first_exp); return diff == 0 ? 0 : 1; } int main(void) { int fail = 0; /* --- Mode 1 Horizontal --- */ { uint8_t buf[ROWS][STRIDE]; int t[8] = {0}, l[8] = {10, 20, 30, 40, 50, 60, 70, 80}; set_ctx(buf, 0, t, l); daedalus_h264_pred_chroma8x8_horizontal_ref(&buf[1][1], STRIDE); uint8_t exp[8][8]; for (int r = 0; r < 8; r++) for (int c = 0; c < 8; c++) exp[r][c] = (uint8_t) l[r]; fail |= check_per_cell(buf, "Horizontal (mode 1)", exp); } /* --- Mode 2 Vertical --- */ { uint8_t buf[ROWS][STRIDE]; int t[8] = {15, 25, 35, 45, 55, 65, 75, 85}, l[8] = {0}; set_ctx(buf, 0, t, l); daedalus_h264_pred_chroma8x8_vertical_ref(&buf[1][1], STRIDE); uint8_t exp[8][8]; for (int r = 0; r < 8; r++) for (int c = 0; c < 8; c++) exp[r][c] = (uint8_t) t[c]; fail |= check_per_cell(buf, "Vertical (mode 2)", exp); } /* --- Mode 0 DC: per-quadrant. Test with distinct halves so any * quadrant mix-up surfaces immediately. * * top[0..3] = 4 × 8 → sum_top_lo = 32 * top[4..7] = 4 × 16 → sum_top_hi = 64 * left[0..3] = 4 × 24 → sum_left_lo = 96 * left[4..7] = 4 × 40 → sum_left_hi = 160 * * dc00 = (32 + 96 + 4) >> 3 = 132/8 = 16 * dc01 = (64 + 2) >> 2 = 66/4 = 16 * dc10 = ( 160 + 2) >> 2 = 162/4 = 40 * dc11 = (64 + 160 + 4) >> 3 = 228/8 = 28 */ { uint8_t buf[ROWS][STRIDE]; int t[8] = { 8, 8, 8, 8, 16, 16, 16, 16 }; int l[8] = { 24, 24, 24, 24, 40, 40, 40, 40 }; set_ctx(buf, 99, t, l); daedalus_h264_pred_chroma8x8_dc_ref(&buf[1][1], STRIDE); uint8_t exp[8][8] = { {16,16,16,16, 16,16,16,16}, {16,16,16,16, 16,16,16,16}, {16,16,16,16, 16,16,16,16}, {16,16,16,16, 16,16,16,16}, {40,40,40,40, 28,28,28,28}, {40,40,40,40, 28,28,28,28}, {40,40,40,40, 28,28,28,28}, {40,40,40,40, 28,28,28,28}, }; fail |= check_per_cell(buf, "DC quadrants (mode 0)", exp); } /* --- Mode 3 Plane (uniform): H = V = 0; a = 16 * (100 + 100) = 3200. * pred[y][x] = (3200 + 0 + 0 + 16) >> 5 = 3216 >> 5 = 100. */ { uint8_t buf[ROWS][STRIDE]; int t[8], l[8]; for (int i = 0; i < 8; i++) { t[i] = 100; l[i] = 100; } set_ctx(buf, 100, t, l); daedalus_h264_pred_chroma8x8_plane_ref(&buf[1][1], STRIDE); uint8_t exp[8][8]; for (int r = 0; r < 8; r++) for (int c = 0; c < 8; c++) exp[r][c] = 100; fail |= check_per_cell(buf, "Plane uniform (mode 3)", exp); } /* --- Mode 3 Plane gradient sanity --- * t = 0..7, l = 0..7, tl = 0. * H = 1*(t[4]-t[2]) + 2*(t[5]-t[1]) + 3*(t[6]-t[0]) + 4*(t[7]-tl) * = 1*(4-2) + 2*(5-1) + 3*(6-0) + 4*(7-0) * = 2 + 8 + 18 + 28 = 56 * V = same shape on left = 56 * b = (34*56 + 32) >> 6 = 1936 >> 6 = 30 * c = 30 * a = 16 * (l[7] + t[7]) = 16 * (7 + 7) = 224 * * pred[0][0] = (224 + 30*(-3) + 30*(-3) + 16) >> 5 * = (224 - 90 - 90 + 16) >> 5 * = 60 >> 5 = 1 * pred[7][7] = (224 + 30*4 + 30*4 + 16) >> 5 * = (224 + 120 + 120 + 16) >> 5 * = 480 >> 5 = 15 * Spot-check those two corners. */ { uint8_t buf[ROWS][STRIDE]; int t[8], l[8]; for (int i = 0; i < 8; i++) { t[i] = i; l[i] = i; } set_ctx(buf, 0, t, l); daedalus_h264_pred_chroma8x8_plane_ref(&buf[1][1], STRIDE); uint8_t tl_actual = buf[1 + 0][1 + 0]; uint8_t br_actual = buf[1 + 7][1 + 7]; int spot_fail = 0; if (tl_actual != 1) { fprintf(stderr, "Plane gradient pred[0][0] = %u, expected 1\n", tl_actual); spot_fail = 1; } if (br_actual != 15) { fprintf(stderr, "Plane gradient pred[7][7] = %u, expected 15\n", br_actual); spot_fail = 1; } if (!spot_fail) printf(" %-30s PASS (corners 1, 15)\n", "Plane gradient (mode 3)"); else printf(" %-30s FAIL\n", "Plane gradient (mode 3)"); fail |= spot_fail; } if (fail == 0) printf("\nALL Intra_8x8 chroma mode references PASS\n"); else fprintf(stderr, "\n%d test(s) FAILED\n", fail); return fail ? 1 : 0; }