[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