summaryrefslogtreecommitdiff
path: root/libavcodec/vc1dsp.c
diff options
context:
space:
mode:
authorDavid Conrad <lessen42@gmail.com>2009-04-15 06:20:22 +0000
committerDavid Conrad <lessen42@gmail.com>2009-04-15 06:20:22 +0000
commit0e58865d6e86bbb664d92311c0f81c65e0213c35 (patch)
treef685d4f29bfcf3a4b6fd5ac205bc009f43824a95 /libavcodec/vc1dsp.c
parent9bf0fdf378cd8d93a105e7b26d143b4718656e87 (diff)
Move VC1 loop filter to DSPContext
Originally committed as revision 18520 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/vc1dsp.c')
-rw-r--r--libavcodec/vc1dsp.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/libavcodec/vc1dsp.c b/libavcodec/vc1dsp.c
index 3effbb7743..5420e7e260 100644
--- a/libavcodec/vc1dsp.c
+++ b/libavcodec/vc1dsp.c
@@ -78,6 +78,73 @@ static void vc1_h_overlap_c(uint8_t* src, int stride)
}
}
+/**
+ * VC-1 in-loop deblocking filter for one line
+ * @param src source block type
+ * @param stride block stride
+ * @param pq block quantizer
+ * @return whether other 3 pairs should be filtered or not
+ * @see 8.6
+ */
+static av_always_inline int vc1_filter_line(uint8_t* src, int stride, int pq){
+ uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
+
+ int a0 = (2*(src[-2*stride] - src[ 1*stride]) - 5*(src[-1*stride] - src[ 0*stride]) + 4) >> 3;
+ int a0_sign = a0 >> 31; /* Store sign */
+ a0 = (a0 ^ a0_sign) - a0_sign; /* a0 = FFABS(a0); */
+ if(a0 < pq){
+ int a1 = FFABS((2*(src[-4*stride] - src[-1*stride]) - 5*(src[-3*stride] - src[-2*stride]) + 4) >> 3);
+ int a2 = FFABS((2*(src[ 0*stride] - src[ 3*stride]) - 5*(src[ 1*stride] - src[ 2*stride]) + 4) >> 3);
+ if(a1 < a0 || a2 < a0){
+ int clip = src[-1*stride] - src[ 0*stride];
+ int clip_sign = clip >> 31;
+ clip = ((clip ^ clip_sign) - clip_sign)>>1;
+ if(clip){
+ int a3 = FFMIN(a1, a2);
+ int d = 5 * (a3 - a0);
+ int d_sign = (d >> 31);
+ d = ((d ^ d_sign) - d_sign) >> 3;
+ d_sign ^= a0_sign;
+
+ if( d_sign ^ clip_sign )
+ d = 0;
+ else{
+ d = FFMIN(d, clip);
+ d = (d ^ d_sign) - d_sign; /* Restore sign */
+ src[-1*stride] = cm[src[-1*stride] - d];
+ src[ 0*stride] = cm[src[ 0*stride] + d];
+ }
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+/**
+ * VC-1 in-loop deblocking filter
+ * @param src source block type
+ * @param step distance between horizontally adjacent elements
+ * @param stride distance between vertically adjacent elements
+ * @param len edge length to filter (4 or 8 pixels)
+ * @param pq block quantizer
+ * @see 8.6
+ */
+static void vc1_loop_filter(uint8_t* src, int step, int stride, int len, int pq)
+{
+ int i;
+ int filt3;
+
+ for(i = 0; i < len; i += 4){
+ filt3 = vc1_filter_line(src + 2*step, stride, pq);
+ if(filt3){
+ vc1_filter_line(src + 0*step, stride, pq);
+ vc1_filter_line(src + 1*step, stride, pq);
+ vc1_filter_line(src + 3*step, stride, pq);
+ }
+ src += step * 4;
+ }
+}
/** Do inverse transform on 8x8 block
*/
@@ -450,6 +517,7 @@ void ff_vc1dsp_init(DSPContext* dsp, AVCodecContext *avctx) {
dsp->vc1_inv_trans_4x4 = vc1_inv_trans_4x4_c;
dsp->vc1_h_overlap = vc1_h_overlap_c;
dsp->vc1_v_overlap = vc1_v_overlap_c;
+ dsp->vc1_loop_filter = vc1_loop_filter;
dsp->put_vc1_mspel_pixels_tab[ 0] = ff_put_vc1_mspel_mc00_c;
dsp->put_vc1_mspel_pixels_tab[ 1] = put_vc1_mspel_mc10_c;