@@ -987,6 +987,134 @@ static void vp8_pred4x4(uint8_t *d, int s, int m,
987987 }
988988}
989989
990+
991+ /* VP8 Simple Loop Filter (RFC 6386 §15.2) */
992+ static INLINE int vp8_sc (int v ) { return v < -128 ? -128 : v > 127 ? 127 : v ; }
993+
994+ static void vp8_simple_filter (uint8_t * p , int stride , int count , int flimit )
995+ {
996+ int i ;
997+ for (i = 0 ; i < count ; i ++ )
998+ {
999+ int p1 = p [-2 * stride ], p0 = p [-1 * stride ], q0 = p [0 ], q1 = p [stride ];
1000+ int a = vp8_sc (vp8_sc (3 * (q0 - p0 ) + vp8_sc (p1 - q1 )) + 4 ) >> 3 ;
1001+ p [-1 * stride ] = vp8_cl (p0 + a );
1002+ p [0 ] = vp8_cl (q0 - a );
1003+ p ++ ;
1004+ }
1005+ }
1006+
1007+ static void vp8_loop_filter_simple (uint8_t * y , int ys , uint8_t * u , int uvs , uint8_t * v_plane ,
1008+ int mbw , int mbh , int lf_level , int sharpness ,
1009+ int seg_enabled , int seg_abs , const int * seg_lf , const uint8_t * seg_map )
1010+ {
1011+ int mx , my , bx , by ;
1012+ for (my = 0 ; my < mbh ; my ++ )
1013+ {
1014+ for (mx = 0 ; mx < mbw ; mx ++ )
1015+ {
1016+ int mb_lf = lf_level ;
1017+ int seg_id = seg_map ? seg_map [my * mbw + mx ] : 0 ;
1018+ int flimit , ilimit ;
1019+ if (seg_enabled && seg_abs )
1020+ mb_lf = seg_lf [seg_id ];
1021+ else if (seg_enabled )
1022+ mb_lf = lf_level + seg_lf [seg_id ];
1023+ if (mb_lf < 0 ) mb_lf = 0 ;
1024+ if (mb_lf > 63 ) mb_lf = 63 ;
1025+ /* Compute filter limit */
1026+ flimit = 2 * mb_lf + (sharpness > 0 ? (sharpness > 4 ? 2 : 1 ) : 0 );
1027+ if (flimit > 63 ) flimit = 63 ;
1028+ ilimit = mb_lf ;
1029+ if (sharpness > 0 ) {
1030+ ilimit >>= (sharpness > 4 ? 2 : 1 );
1031+ if (ilimit > 9 - sharpness ) ilimit = 9 - sharpness ;
1032+ }
1033+ if (ilimit < 1 ) ilimit = 1 ;
1034+
1035+ if (mb_lf == 0 ) continue ;
1036+
1037+ /* Y plane: filter vertical edges (between columns of 4x4 blocks) */
1038+ for (by = 0 ; by < 16 ; by ++ )
1039+ {
1040+ uint8_t * row = y + (my * 16 + by )* ys + mx * 16 ;
1041+ /* MB left edge (stronger filter at MB boundary) */
1042+ if (mx > 0 )
1043+ {
1044+ int p1 = row [-2 ], p0 = row [-1 ], q0 = row [0 ], q1 = row [1 ];
1045+ int a = vp8_sc (3 * (q0 - p0 ) + vp8_sc (p1 - q1 ));
1046+ if (a < 0 ? - a : a <= flimit ) {
1047+ int f = vp8_sc (a + 4 ) >> 3 ;
1048+ row [-1 ] = vp8_cl (p0 + f );
1049+ row [0 ] = vp8_cl (q0 - f );
1050+ }
1051+ }
1052+ /* Sub-block edges at columns 4, 8, 12 */
1053+ for (bx = 4 ; bx < 16 ; bx += 4 )
1054+ {
1055+ int p1 = row [bx - 2 ], p0 = row [bx - 1 ], q0 = row [bx ], q1 = row [bx + 1 ];
1056+ int a = vp8_sc (3 * (q0 - p0 ) + vp8_sc (p1 - q1 ));
1057+ if (a < 0 ? - a : a <= ilimit ) {
1058+ int f = vp8_sc (a + 4 ) >> 3 ;
1059+ row [bx - 1 ] = vp8_cl (p0 + f );
1060+ row [bx ] = vp8_cl (q0 - f );
1061+ }
1062+ }
1063+ }
1064+ /* Y plane: filter horizontal edges */
1065+ for (bx = 0 ; bx < 16 ; bx ++ )
1066+ {
1067+ /* MB top edge */
1068+ if (my > 0 )
1069+ {
1070+ uint8_t * col = y + (my * 16 )* ys + mx * 16 + bx ;
1071+ int p1 = col [-2 * ys ], p0 = col [- ys ], q0 = col [0 ], q1 = col [ys ];
1072+ int a = vp8_sc (3 * (q0 - p0 ) + vp8_sc (p1 - q1 ));
1073+ if (a < 0 ? - a : a <= flimit ) {
1074+ int f = vp8_sc (a + 4 ) >> 3 ;
1075+ col [- ys ] = vp8_cl (p0 + f );
1076+ col [0 ] = vp8_cl (q0 - f );
1077+ }
1078+ }
1079+ /* Sub-block edges at rows 4, 8, 12 */
1080+ for (by = 4 ; by < 16 ; by += 4 )
1081+ {
1082+ uint8_t * col = y + (my * 16 + by )* ys + mx * 16 + bx ;
1083+ int p1 = col [-2 * ys ], p0 = col [- ys ], q0 = col [0 ], q1 = col [ys ];
1084+ int a = vp8_sc (3 * (q0 - p0 ) + vp8_sc (p1 - q1 ));
1085+ if (a < 0 ? - a : a <= ilimit ) {
1086+ int f = vp8_sc (a + 4 ) >> 3 ;
1087+ col [- ys ] = vp8_cl (p0 + f );
1088+ col [0 ] = vp8_cl (q0 - f );
1089+ }
1090+ }
1091+ }
1092+ /* UV planes: filter at MB edges and 8x8 sub-block edges */
1093+ /* (simplified: only MB edges for UV) */
1094+ if (mx > 0 ) {
1095+ for (by = 0 ; by < 8 ; by ++ ) {
1096+ uint8_t * ur = u + (my * 8 + by )* uvs + mx * 8 ;
1097+ uint8_t * vr = v_plane + (my * 8 + by )* uvs + mx * 8 ;
1098+ { int p1 = ur [-2 ],p0 = ur [-1 ],q0 = ur [0 ],q1 = ur [1 ]; int a = vp8_sc (3 * (q0 - p0 )+ vp8_sc (p1 - q1 ));
1099+ if ((a < 0 ?- a :a )<=flimit ){int f = vp8_sc (a + 4 )>>3 ; ur [-1 ]= vp8_cl (p0 + f ); ur [0 ]= vp8_cl (q0 - f );} }
1100+ { int p1 = vr [-2 ],p0 = vr [-1 ],q0 = vr [0 ],q1 = vr [1 ]; int a = vp8_sc (3 * (q0 - p0 )+ vp8_sc (p1 - q1 ));
1101+ if ((a < 0 ?- a :a )<=flimit ){int f = vp8_sc (a + 4 )>>3 ; vr [-1 ]= vp8_cl (p0 + f ); vr [0 ]= vp8_cl (q0 - f );} }
1102+ }
1103+ }
1104+ if (my > 0 ) {
1105+ for (bx = 0 ; bx < 8 ; bx ++ ) {
1106+ uint8_t * uc = u + my * 8 * uvs + mx * 8 + bx ;
1107+ uint8_t * vc = v_plane + my * 8 * uvs + mx * 8 + bx ;
1108+ { int p1 = uc [-2 * uvs ],p0 = uc [- uvs ],q0 = uc [0 ],q1 = uc [uvs ]; int a = vp8_sc (3 * (q0 - p0 )+ vp8_sc (p1 - q1 ));
1109+ if ((a < 0 ?- a :a )<=flimit ){int f = vp8_sc (a + 4 )>>3 ; uc [- uvs ]= vp8_cl (p0 + f ); uc [0 ]= vp8_cl (q0 - f );} }
1110+ { int p1 = vc [-2 * uvs ],p0 = vc [- uvs ],q0 = vc [0 ],q1 = vc [uvs ]; int a = vp8_sc (3 * (q0 - p0 )+ vp8_sc (p1 - q1 ));
1111+ if ((a < 0 ?- a :a )<=flimit ){int f = vp8_sc (a + 4 )>>3 ; vc [- uvs ]= vp8_cl (p0 + f ); vc [0 ]= vp8_cl (q0 - f );} }
1112+ }
1113+ }
1114+ }
1115+ }
1116+ }
1117+
9901118static void vp8_pred16 (uint8_t * d , int s , int m , const uint8_t * a , const uint8_t * l , uint8_t tl )
9911119{
9921120 int i , j ;
@@ -1020,7 +1148,8 @@ static uint32_t *vp8_decode(const uint8_t *data, size_t len,
10201148 int base_qp , y1dc_dq , y2dc_dq , y2ac_dq , uvdc_dq , uvac_dq ;
10211149 int qp , y1_dc_q , y1_ac_q , y2_dc_q , y2_ac_q , uv_dc_q , uv_ac_q ;
10221150 int skip_enabled , prob_skip , log2parts , num_parts ;
1023- int seg_enabled , seg_abs , seg_qp [4 ], seg_prob [3 ];
1151+ int filter_type , lf_level , sharpness ;
1152+ int seg_enabled , seg_abs , seg_qp [4 ], seg_lf [4 ], seg_prob [3 ];
10241153 vp8b br ;
10251154 vp8b tbr [8 ]; /* up to 8 token partitions */
10261155 const uint8_t * p0 ;
@@ -1048,18 +1177,19 @@ static uint32_t *vp8_decode(const uint8_t *data, size_t len,
10481177 seg_abs = 0 ;
10491178 seg_qp [0 ] = seg_qp [1 ] = seg_qp [2 ] = seg_qp [3 ] = 0 ;
10501179 seg_prob [0 ] = seg_prob [1 ] = seg_prob [2 ] = 255 ;
1180+ seg_lf [0 ] = seg_lf [1 ] = seg_lf [2 ] = seg_lf [3 ] = 0 ;
10511181 if (seg_enabled )
10521182 {
10531183 int um = vp8b_bit (& br ), ud = vp8b_bit (& br );
10541184 if (ud ) {
10551185 seg_abs = vp8b_bit (& br );
10561186 for (i = 0 ;i < 4 ;i ++ ) seg_qp [i ] = vp8b_bit (& br ) ? vp8b_sig (& br ,7 ) : 0 ;
1057- for (i = 0 ;i < 4 ;i ++ ) if ( vp8b_bit (& br )) vp8b_sig (& br ,6 ); /* lf deltas - discard */
1187+ for (i = 0 ;i < 4 ;i ++ ) seg_lf [ i ] = vp8b_bit (& br ) ? vp8b_sig (& br ,6 ) : 0 ;
10581188 }
10591189 if (um ) for (i = 0 ;i < 3 ;i ++ ) { if (vp8b_bit (& br )) seg_prob [i ] = (int )vp8b_lit (& br ,8 ); }
10601190 }
10611191
1062- vp8b_bit (& br ); vp8b_lit (& br ,6 ); vp8b_lit (& br ,3 ); /* filter */
1192+ filter_type = vp8b_bit (& br ); lf_level = ( int ) vp8b_lit (& br ,6 ); sharpness = ( int ) vp8b_lit (& br ,3 );
10631193 { int mrd = vp8b_bit (& br );
10641194 if (mrd && vp8b_bit (& br ))
10651195 { for (i = 0 ;i < 4 ;i ++ ) if (vp8b_bit (& br )) vp8b_sig (& br ,6 );
@@ -1174,7 +1304,9 @@ static uint32_t *vp8_decode(const uint8_t *data, size_t len,
11741304 }
11751305 }
11761306
1307+ uint8_t * seg_map_buf = NULL ;
11771308 ys = mbw * 16 ; uvs = mbw * 8 ;
1309+ seg_map_buf = (uint8_t * )calloc (mbw * mbh , 1 );
11781310 yb = (uint8_t * )calloc (ys * mbh * 16 , 1 );
11791311 ub = (uint8_t * )calloc (uvs * mbh * 8 , 1 );
11801312 vb = (uint8_t * )calloc (uvs * mbh * 8 , 1 );
@@ -1228,6 +1360,7 @@ static uint32_t *vp8_decode(const uint8_t *data, size_t len,
12281360 seg_id = vp8b_get (& br , seg_prob [1 ]);
12291361 }
12301362
1363+ if (seg_map_buf ) seg_map_buf [my * mbw + mx ] = (uint8_t )seg_id ;
12311364 /* Compute per-MB quantizer based on segment */
12321365 if (seg_enabled && seg_abs )
12331366 mb_qp = seg_qp [seg_id ];
@@ -1454,6 +1587,30 @@ static uint32_t *vp8_decode(const uint8_t *data, size_t len,
14541587 memset (left_nz_v , 0 , sizeof (left_nz_v ));
14551588 left_nz_dc = 0 ;
14561589 }
1590+
1591+ /* Per-MB simple loop filter */
1592+ if (filter_type == 1 ) {
1593+ int mb_lf_val = lf_level ;
1594+ if (seg_enabled && seg_abs ) mb_lf_val = seg_lf [seg_id ];
1595+ else if (seg_enabled ) mb_lf_val = lf_level + seg_lf [seg_id ];
1596+ if (mb_lf_val < 0 ) mb_lf_val = 0 ; if (mb_lf_val > 63 ) mb_lf_val = 63 ;
1597+ if (mb_lf_val > 0 ) {
1598+ int fl = 2 * mb_lf_val , il = mb_lf_val ;
1599+ if (sharpness > 0 ) { fl += (sharpness > 4 ) ? 2 : 1 ; }
1600+ if (fl > 63 ) fl = 63 ;
1601+ if (sharpness > 0 ) { il >>= (sharpness > 4 ) ? 2 : 1 ; if (il > 9 - sharpness ) il = 9 - sharpness ; }
1602+ if (il < 1 ) il = 1 ;
1603+ for (by = 0 ; by < 16 ; by ++ ) {
1604+ uint8_t * row = yb + (my * 16 + by )* ys + mx * 16 ;
1605+ if (mx > 0 ) { int p1 = row [-2 ],p0 = row [-1 ],q0 = row [0 ],q1 = row [1 ], a = vp8_sc (3 * (q0 - p0 )+ vp8_sc (p1 - q1 )); if ((a < 0 ?- a :a )<=fl ){int f = vp8_sc (a + 4 )>>3 ;row [-1 ]= vp8_cl (p0 + f );row [0 ]= vp8_cl (q0 - f );} }
1606+ for (bx = 4 ; bx < 16 ; bx += 4 ) { int p1 = row [bx - 2 ],p0 = row [bx - 1 ],q0 = row [bx ],q1 = row [bx + 1 ], a = vp8_sc (3 * (q0 - p0 )+ vp8_sc (p1 - q1 )); if ((a < 0 ?- a :a )<=il ){int f = vp8_sc (a + 4 )>>3 ;row [bx - 1 ]= vp8_cl (p0 + f );row [bx ]= vp8_cl (q0 - f );} }
1607+ }
1608+ for (bx = 0 ; bx < 16 ; bx ++ ) {
1609+ if (my > 0 ) { uint8_t * c2 = yb + my * 16 * ys + mx * 16 + bx ; int p1 = c2 [-2 * ys ],p0 = c2 [- ys ],q0 = c2 [0 ],q1 = c2 [ys ], a = vp8_sc (3 * (q0 - p0 )+ vp8_sc (p1 - q1 )); if ((a < 0 ?- a :a )<=fl ){int f = vp8_sc (a + 4 )>>3 ;c2 [- ys ]= vp8_cl (p0 + f );c2 [0 ]= vp8_cl (q0 - f );} }
1610+ for (by = 4 ; by < 16 ; by += 4 ) { uint8_t * c2 = yb + (my * 16 + by )* ys + mx * 16 + bx ; int p1 = c2 [-2 * ys ],p0 = c2 [- ys ],q0 = c2 [0 ],q1 = c2 [ys ], a = vp8_sc (3 * (q0 - p0 )+ vp8_sc (p1 - q1 )); if ((a < 0 ?- a :a )<=il ){int f = vp8_sc (a + 4 )>>3 ;c2 [- ys ]= vp8_cl (p0 + f );c2 [0 ]= vp8_cl (q0 - f );} }
1611+ }
1612+ }
1613+ }
14571614 }
14581615 }
14591616
@@ -1470,11 +1627,11 @@ static uint32_t *vp8_decode(const uint8_t *data, size_t len,
14701627 vp8_yuv2rgb (yb [j * ys + i ], ub [(j >>1 )* uvs + (i >>1 )], vb [(j >>1 )* uvs + (i >>1 )], & r , & g , & b2 );
14711628 pix [j * w + i ] = 0xFF000000u | ((uint32_t )r <<16 ) | ((uint32_t )g <<8 ) | (uint32_t )b2 ;
14721629 }
1473- free (yb ); free (ub ); free (vb );
1630+ free (yb ); free (ub ); free (vb ); free ( seg_map_buf );
14741631 * ow = (unsigned )w ; * oh = (unsigned )h ;
14751632 return pix ;
14761633lfail :
1477- free (yb ); free (ub ); free (vb ); free (pix );
1634+ free (yb ); free (ub ); free (vb ); free (seg_map_buf ); free ( pix );
14781635 return NULL ;
14791636}
14801637
0 commit comments