[FFmpeg-devel] [PATCH i/N] RV30 loop filter

Kostya kostya.shishkov
Sat Mar 8 18:15:18 CET 2008


On Sun, Feb 24, 2008 at 12:37:24AM +0100, Michael Niedermayer wrote:
> On Sat, Feb 23, 2008 at 12:57:29PM +0200, Kostya wrote:
> > $subj
> > 
> > Probably correct.
> 
[...]
> > +static void rv30_loop_filter(RV34DecContext *r)
> > +{
> > +    MpegEncContext *s = &r->s;
> > +    int mb_pos;
> > +    int i, j;
> 
> > +    int strength = 0;//FIXME how to determine correct value?
> > +    const uint8_t* lim = rv30_loop_filt_lim[strength];
> 
> This does not look correct.

I believe it is - rv30_loop_filt_lim is an array of 32-element mapping
tables between quantizer and limit values.

> > +    int cbp1, cbp2, q;
> > +
> > +    s->mb_x = 0;
> > +    for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++){
> > +        ff_init_block_index(s);
> > +        mb_pos = s->mb_y * s->mb_stride;
> > +        for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++, mb_pos++){
> > +            ff_update_block_index(s);
> > +            if(!IS_INTRA(s->current_picture_ptr->mb_type[mb_pos])) continue;
> > +            if(s->mb_x && IS_INTRA(s->current_picture_ptr->mb_type[mb_pos - 1])){
> > +                cbp1 = r->cbp_luma[mb_pos - 1];
> > +                cbp2 = r->cbp_luma[mb_pos];
> > +                q = s->current_picture_ptr->qscale_table[mb_pos - 1];
> 
> > +                for(i = 0; i < 16; i += 4, cbp1 >>= 4, cbp2 >>= 4)
> 
> Please dont put so much stuff in the for() this makes the code hard to read.

moved to the end of loop 
 
> > +                    if((cbp1 & 8) && (cbp2 & 1))
> > +                        rv30_weak_loop_filter(s->dest[0] + i * s->linesize, 1, s->linesize, lim[q]);
> 
> cbp2 &= cbp1>>3;

simplified

> > +                cbp1 = r->cbp_chroma[mb_pos - 1];
> > +                cbp2 = r->cbp_chroma[mb_pos];
> > +                for(i = 0; i < 8; i += 4, cbp1 >>= 2, cbp2 >>= 2){
> > +                    if((cbp1 & 0x02) && (cbp2 & 0x01))
> > +                        rv30_weak_loop_filter(s->dest[1] + i * s->uvlinesize, 1, s->uvlinesize, lim[q]);
> > +                    if((cbp1 & 0x20) && (cbp2 & 0x10))
> > +                        rv30_weak_loop_filter(s->dest[2] + i * s->uvlinesize, 1, s->uvlinesize, lim[q]);
> > +                }
> > +            }
> > +            q = s->current_picture_ptr->qscale_table[mb_pos];
> > +            for(j = 4; j < 16; j += 4){
> > +                cbp1 = r->cbp_luma[mb_pos] >> ((j >> 2) - 1);
> > +                for(i = 0; i < 16; i += 4, cbp1 >>= 4)
> > +                    if(cbp1 & 3)
> > +                        rv30_weak_loop_filter(s->dest[0] + j + i * s->linesize, 1, s->linesize, lim[q]);
> > +            }
> > +            cbp1 = r->cbp_chroma[mb_pos];
> > +            for(i = 0; i < 8; i += 4, cbp1 >>= 2){
> > +                if(cbp1 & 0x03)
> > +                    rv30_weak_loop_filter(s->dest[1] + 4 + i * s->uvlinesize, 1, s->uvlinesize, lim[q]);
> > +                if(cbp1 & 0x30)
> > +                    rv30_weak_loop_filter(s->dest[2] + 4 + i * s->uvlinesize, 1, s->uvlinesize, lim[q]);
> > +            }
> 
> This code does cbpA || cbpB the one above does cbpA && cbpB, this is strange.

before it was luma, here it is chroma and I just merged U and V filter calls together

New version below.
 
> [...]
> -- 
> Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
-------------- next part --------------
Index: libavcodec/rv30data.h
===================================================================
--- libavcodec/rv30data.h	(revision 12129)
+++ libavcodec/rv30data.h	(working copy)
@@ -171,4 +171,17 @@
     2, 7, 8, 4, 0, 6, 1, 5, 3,
     2, 8, 3, 0, 7, 4, 1, 6, 5,
 };
+
+/**
+ * Loop filter limits are taken from this table.
+ */
+static const uint8_t rv30_loop_filt_lim[7][32] = {
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5 },
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4 },
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5 },
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6 },
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7 },
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8 },
+    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9 }
+};
 #endif /* FFMPEG_RV30DATA_H */
Index: libavcodec/rv30.c
===================================================================
--- libavcodec/rv30.c	(revision 12129)
+++ libavcodec/rv30.c	(working copy)
@@ -111,6 +111,111 @@
         return rv30_b_types[code];
 }
 
+static inline void rv30_weak_loop_filter(uint8_t *src, const int step,
+                                         const int stride, const int lim)
+{
+    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+    int i, diff;
+
+    if(!lim) return;
+    for(i = 0; i < 4; i++){
+        diff = ((src[-2*step] - src[1*step]) - (src[-1*step] - src[0*step])*4) >> 3;
+        diff = av_clip(diff, -lim, lim);
+        src[-1*step] = cm[src[-1*step] + diff];
+        src[ 0*step] = cm[src[ 0*step] - diff];
+        src += stride;
+    }
+}
+
+static void rv30_loop_filter(RV34DecContext *r)
+{
+    MpegEncContext *s = &r->s;
+    int mb_pos;
+    int i, j;
+    int strength = 0;//FIXME how to determine correct value?
+    const uint8_t* lim = rv30_loop_filt_lim[strength];
+    int cbp, q;
+
+    s->mb_x = 0;
+    for(s->mb_y = 0; s->mb_y < s->mb_height; s->mb_y++){
+        ff_init_block_index(s);
+        mb_pos = s->mb_y * s->mb_stride;
+        for(s->mb_x = 0; s->mb_x < s->mb_width; s->mb_x++, mb_pos++){
+            ff_update_block_index(s);
+            if(!IS_INTRA(s->current_picture_ptr->mb_type[mb_pos])) continue;
+            if(s->mb_x && IS_INTRA(s->current_picture_ptr->mb_type[mb_pos - 1])){
+                cbp = r->cbp_luma[mb_pos] & (r->cbp_luma[mb_pos - 1] >> 3);
+                q = s->current_picture_ptr->qscale_table[mb_pos - 1];
+                for(i = 0; i < 16; i += 4){
+                    if(cbp & 1)
+                        rv30_weak_loop_filter(s->dest[0] + i * s->linesize, 1, s->linesize, lim[q]);
+                    cbp >>= 4;
+                }
+                cbp = (r->cbp_chroma[mb_pos] >> 1) & r->cbp_chroma[mb_pos - 1];
+                for(i = 0; i < 8; i += 4){
+                    if(cbp & 0x01)
+                        rv30_weak_loop_filter(s->dest[1] + i * s->uvlinesize, 1, s->uvlinesize, lim[q]);
+                    if(cbp & 0x10)
+                        rv30_weak_loop_filter(s->dest[2] + i * s->uvlinesize, 1, s->uvlinesize, lim[q]);
+                    cbp >>= 2;
+                }
+            }
+            q = s->current_picture_ptr->qscale_table[mb_pos];
+            for(j = 4; j < 16; j += 4){
+                cbp = r->cbp_luma[mb_pos] >> ((j >> 2) - 1);
+                for(i = 0; i < 16; i += 4){
+                    if(cbp & 3)
+                        rv30_weak_loop_filter(s->dest[0] + j + i * s->linesize, 1, s->linesize, lim[q]);
+                    cbp >>= 4;
+                }
+            }
+            cbp = r->cbp_chroma[mb_pos];
+            for(i = 0; i < 8; i += 4){
+                if(cbp & 0x03)
+                    rv30_weak_loop_filter(s->dest[1] + 4 + i * s->uvlinesize, 1, s->uvlinesize, lim[q]);
+                if(cbp & 0x30)
+                    rv30_weak_loop_filter(s->dest[2] + 4 + i * s->uvlinesize, 1, s->uvlinesize, lim[q]);
+                cbp >>= 2;
+            }
+
+            if(s->mb_y && IS_INTRA(s->current_picture_ptr->mb_type[mb_pos - s->mb_stride])){
+                cbp = r->cbp_luma[mb_pos] & (r->cbp_luma[mb_pos - s->mb_stride] >> 12);
+                q = s->current_picture_ptr->qscale_table[mb_pos - s->mb_stride];
+                for(i = 0; i < 16; i += 4){
+                    if(cbp & 1)
+                        rv30_weak_loop_filter(s->dest[0] + i, s->linesize, 1, lim[q]);
+                    cbp >>= 1;
+                }
+                cbp = r->cbp_chroma[mb_pos] & (r->cbp_chroma[mb_pos - s->mb_stride] >> 2);
+                for(i = 0; i < 8; i += 4){
+                    if(cbp & 0x01)
+                        rv30_weak_loop_filter(s->dest[1] + i * s->uvlinesize, s->uvlinesize, 1, lim[q]);
+                    if(cbp & 0x10)
+                        rv30_weak_loop_filter(s->dest[2] + i * s->uvlinesize, s->uvlinesize, 1, lim[q]);
+                    cbp >>= 1;
+                }
+            }
+            q = s->current_picture_ptr->qscale_table[mb_pos];
+            for(j = 4; j < 16; j += 4){
+                cbp = r->cbp_luma[mb_pos] >> (j - 4);
+                for(i = 0; i < 16; i += 4){
+                    if(cbp & 0x11)
+                        rv30_weak_loop_filter(s->dest[0] + i + j * s->linesize, s->linesize, 1, lim[q]);
+                    cbp >>= 4;
+                }
+            }
+            cbp = r->cbp_chroma[mb_pos];
+            for(i = 0; i < 8; i += 4){
+                if(cbp & 0x05)
+                    rv30_weak_loop_filter(s->dest[1] + i + 4 * s->uvlinesize, s->uvlinesize, 1, lim[q]);
+                if(cbp & 0x50)
+                    rv30_weak_loop_filter(s->dest[2] + i + 4 * s->uvlinesize, s->uvlinesize, 1, lim[q]);
+                cbp >>= 2;
+            }
+        }
+    }
+}
+
 /**
  * Initialize decoder.
  */
@@ -129,6 +234,7 @@
     r->parse_slice_header = rv30_parse_slice_header;
     r->decode_intra_types = rv30_decode_intra_types;
     r->decode_mb_info     = rv30_decode_mb_info;
+    r->loop_filter        = rv30_loop_filter;
     r->luma_dc_quant_i = rv30_luma_dc_quant;
     r->luma_dc_quant_p = rv30_luma_dc_quant;
     return 0;



More information about the ffmpeg-devel mailing list