]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/imgresample.c
move h264 idct to its own file and call via function pointer in DspContext
[ffmpeg] / libavcodec / imgresample.c
index 2e67fecb3d093133d43bf39b1f123e3ca8add4ec..35aff28aea65861a7f7c9a5343b16bff5f2b1d94 100644 (file)
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+/**
+ * @file imgresample.c
+ * High quality image resampling with polyphase filters .
+ */
 #include "avcodec.h"
 #include "dsputil.h"
 
 #define LINE_BUF_HEIGHT (NB_TAPS * 4)
 
 struct ImgReSampleContext {
-    int iwidth, iheight, owidth, oheight, topBand, bottomBand, leftBand, rightBand;
+    int iwidth, iheight, owidth, oheight;
+    int topBand, bottomBand, leftBand, rightBand;
+    int padtop, padbottom, padleft, padright;
+    int pad_owidth, pad_oheight;
     int h_incr, v_incr;
     int16_t h_filters[NB_PHASES][NB_TAPS] __align8; /* horizontal filters */
     int16_t v_filters[NB_PHASES][NB_TAPS] __align8; /* vertical filters */
     uint8_t *line_buf;
 };
 
+void av_build_filter(int16_t *filter, double factor, int tap_count, int phase_count, int scale, int type);
+
 static inline int get_phase(int pos)
 {
     return ((pos) >> (POS_FRAC_BITS - PHASE_BITS)) & ((1 << PHASE_BITS) - 1);
 }
 
 /* This function must be optimized */
-static void h_resample_fast(uint8_t *dst, int dst_width, uint8_t *src, int src_width,
-                            int src_start, int src_incr, int16_t *filters)
+static void h_resample_fast(uint8_t *dst, int dst_width, const uint8_t *src,
+                           int src_width, int src_start, int src_incr,
+                           int16_t *filters)
 {
     int src_pos, phase, sum, i;
-    uint8_t *s;
+    const uint8_t *s;
     int16_t *filter;
 
     src_pos = src_start;
@@ -95,11 +107,11 @@ static void h_resample_fast(uint8_t *dst, int dst_width, uint8_t *src, int src_w
 }
 
 /* This function must be optimized */
-static void v_resample(uint8_t *dst, int dst_width, uint8_t *src, int wrap, 
-                       int16_t *filter)
+static void v_resample(uint8_t *dst, int dst_width, const uint8_t *src,
+                      int wrap, int16_t *filter)
 {
     int sum, i;
-    uint8_t *s;
+    const uint8_t *s;
 
     s = src;
     for(i=0;i<dst_width;i++) {
@@ -154,11 +166,12 @@ static void v_resample(uint8_t *dst, int dst_width, uint8_t *src, int wrap,
 #define DUMP(reg) movq_r2m(reg, tmp); printf(#reg "=%016Lx\n", tmp.uq);
 
 /* XXX: do four pixels at a time */
-static void h_resample_fast4_mmx(uint8_t *dst, int dst_width, uint8_t *src, int src_width,
+static void h_resample_fast4_mmx(uint8_t *dst, int dst_width,
+                                const uint8_t *src, int src_width,
                                  int src_start, int src_incr, int16_t *filters)
 {
     int src_pos, phase;
-    uint8_t *s;
+    const uint8_t *s;
     int16_t *filter;
     mmx_t tmp;
     
@@ -198,11 +211,11 @@ static void h_resample_fast4_mmx(uint8_t *dst, int dst_width, uint8_t *src, int
     emms();
 }
 
-static void v_resample4_mmx(uint8_t *dst, int dst_width, uint8_t *src, int wrap, 
-                            int16_t *filter)
+static void v_resample4_mmx(uint8_t *dst, int dst_width, const uint8_t *src,
+                           int wrap, int16_t *filter)
 {
     int sum, i, v;
-    uint8_t *s;
+    const uint8_t *s;
     mmx_t tmp;
     mmx_t coefs[4];
     
@@ -274,11 +287,11 @@ typedef   union {
     signed short s[8];
 } vec_ss_t;
 
-void v_resample16_altivec(uint8_t *dst, int dst_width, uint8_t *src, int wrap,
-                            int16_t *filter)
+void v_resample16_altivec(uint8_t *dst, int dst_width, const uint8_t *src,
+                         int wrap, int16_t *filter)
 {
     int sum, i;
-    uint8_t *s;
+    const uint8_t *s;
     vector unsigned char *tv, tmp, dstv, zero;
     vec_ss_t srchv[4], srclv[4], fv[4];
     vector signed short zeros, sumhv, sumlv;    
@@ -391,11 +404,12 @@ void v_resample16_altivec(uint8_t *dst, int dst_width, uint8_t *src, int wrap,
 #endif
 
 /* slow version to handle limit cases. Does not need optimisation */
-static void h_resample_slow(uint8_t *dst, int dst_width, uint8_t *src, int src_width,
+static void h_resample_slow(uint8_t *dst, int dst_width,
+                           const uint8_t *src, int src_width,
                             int src_start, int src_incr, int16_t *filters)
 {
     int src_pos, phase, sum, j, v, i;
-    uint8_t *s, *src_end;
+    const uint8_t *s, *src_end;
     int16_t *filter;
 
     src_end = src + src_width;
@@ -426,8 +440,9 @@ static void h_resample_slow(uint8_t *dst, int dst_width, uint8_t *src, int src_w
     }
 }
 
-static void h_resample(uint8_t *dst, int dst_width, uint8_t *src, int src_width,
-                       int src_start, int src_incr, int16_t *filters)
+static void h_resample(uint8_t *dst, int dst_width, const uint8_t *src,
+                      int src_width, int src_start, int src_incr,
+                      int16_t *filters)
 {
     int n, src_end;
 
@@ -522,53 +537,24 @@ static void component_resample(ImgReSampleContext *s,
                        &s->v_filters[phase_y][0]);
             
         src_y += s->v_incr;
+        
         output += owrap;
     }
 }
 
-/* XXX: the following filter is quite naive, but it seems to suffice
-   for 4 taps */
-static void build_filter(int16_t *filter, float factor)
-{
-    int ph, i, v;
-    float x, y, tab[NB_TAPS], norm, mult;
-
-    /* if upsampling, only need to interpolate, no filter */
-    if (factor > 1.0)
-        factor = 1.0;
-
-    for(ph=0;ph<NB_PHASES;ph++) {
-        norm = 0;
-        for(i=0;i<NB_TAPS;i++) {
-            
-            x = M_PI * ((float)(i - FCENTER) - (float)ph / NB_PHASES) * factor;
-            if (x == 0)
-                y = 1.0;
-            else
-                y = sin(x) / x;
-            tab[i] = y;
-            norm += y;
-        }
-
-        /* normalize so that an uniform color remains the same */
-        mult = (float)(1 << FILTER_BITS) / norm;
-        for(i=0;i<NB_TAPS;i++) {
-            v = (int)(tab[i] * mult);
-            filter[ph * NB_TAPS + i] = v;
-        }
-    }
-}
-
 ImgReSampleContext *img_resample_init(int owidth, int oheight,
                                       int iwidth, int iheight)
 {
-       return img_resample_full_init(owidth, oheight, iwidth, iheight, 0, 0, 0, 0);
+    return img_resample_full_init(owidth, oheight, iwidth, iheight, 
+            0, 0, 0, 0, 0, 0, 0, 0);
 }
 
 ImgReSampleContext *img_resample_full_init(int owidth, int oheight,
                                       int iwidth, int iheight,
                                       int topBand, int bottomBand,
-                                      int leftBand, int rightBand)
+        int leftBand, int rightBand,
+        int padtop, int padbottom,
+        int padleft, int padright)
 {
     ImgReSampleContext *s;
 
@@ -583,34 +569,52 @@ ImgReSampleContext *img_resample_full_init(int owidth, int oheight,
     s->oheight = oheight;
     s->iwidth = iwidth;
     s->iheight = iheight;
+  
     s->topBand = topBand;
     s->bottomBand = bottomBand;
     s->leftBand = leftBand;
     s->rightBand = rightBand;
     
-    s->h_incr = ((iwidth - leftBand - rightBand) * POS_FRAC) / owidth;
-    s->v_incr = ((iheight - topBand - bottomBand) * POS_FRAC) / oheight;
-    
-    build_filter(&s->h_filters[0][0], (float) owidth  / (float) (iwidth - leftBand - rightBand));
-    build_filter(&s->v_filters[0][0], (float) oheight / (float) (iheight - topBand - bottomBand));
+    s->padtop = padtop;
+    s->padbottom = padbottom;
+    s->padleft = padleft;
+    s->padright = padright;
+
+    s->pad_owidth = owidth - (padleft + padright);
+    s->pad_oheight = oheight - (padtop + padbottom);
+
+    s->h_incr = ((iwidth - leftBand - rightBand) * POS_FRAC) / s->pad_owidth;
+    s->v_incr = ((iheight - topBand - bottomBand) * POS_FRAC) / s->pad_oheight; 
+
+    av_build_filter(&s->h_filters[0][0], (float) s->pad_owidth  / 
+            (float) (iwidth - leftBand - rightBand), NB_TAPS, NB_PHASES, 1<<FILTER_BITS, 0);
+    av_build_filter(&s->v_filters[0][0], (float) s->pad_oheight / 
+            (float) (iheight - topBand - bottomBand), NB_TAPS, NB_PHASES, 1<<FILTER_BITS, 0);
 
     return s;
- fail:
+fail:
     av_free(s);
     return NULL;
 }
 
 void img_resample(ImgReSampleContext *s, 
-                  AVPicture *output, AVPicture *input)
+                  AVPicture *output, const AVPicture *input)
 {
     int i, shift;
+    uint8_t* optr;
 
-    for(i=0;i<3;i++) {
+    for (i=0;i<3;i++) {
         shift = (i == 0) ? 0 : 1;
-        component_resample(s, output->data[i], output->linesize[i], 
-                           s->owidth >> shift, s->oheight >> shift,
-                           input->data[i] + (input->linesize[i] * (s->topBand >> shift)) + (s->leftBand >> shift),
-                           input->linesize[i], ((s->iwidth - s->leftBand - s->rightBand) >> shift),
+
+        optr = output->data[i] + (((output->linesize[i] * 
+                        s->padtop) + s->padleft) >> shift);
+
+        component_resample(s, optr, output->linesize[i], 
+                s->pad_owidth >> shift, s->pad_oheight >> shift,
+                input->data[i] + (input->linesize[i] * 
+                    (s->topBand >> shift)) + (s->leftBand >> shift),
+                input->linesize[i], ((s->iwidth - s->leftBand - 
+                        s->rightBand) >> shift),
                            (s->iheight - s->topBand - s->bottomBand) >> shift);
     }
 }