Ticket #113: altivec_lum.6.diff

File altivec_lum.6.diff, 18.7 kB (added by gbooker, 2 years ago)

Took gpoirier's changes, and added a few more. The deblock_p0_q0 has been reworked (I never trusted the math in the MMX version) into what makes more sense to me and fixed a glaring mistake with the if statement on the four bytes of the tc array. The * in there should have been an &.

  • libavcodec/ppc/h264_altivec.c

    old new  
    524524    ALTIVEC_STORE_SUM_CLIP(&dst[7*stride], idct7, perm_ldv, perm_stv, sel); 
    525525} 
    526526 
     527/* A routine to read an unaligned vector.  Thanks for the example code Apple */ 
     528static inline vector unsigned char read_unaligned(int offset, uint8_t *src) 
     529{ 
     530    register vector unsigned char first = vec_ld(offset, src); 
     531    register vector unsigned char second = vec_ld(offset+15, src); 
     532    register vector unsigned char mask = vec_lvsl(offset, src); 
     533    return vec_perm(first, second, mask); 
     534} 
     535 
     536#define transpose4x16(r0, r1, r2, r3) {      \ 
     537    register vector unsigned char r4;        \ 
     538    register vector unsigned char r5;        \ 
     539    register vector unsigned char r6;        \ 
     540    register vector unsigned char r7;        \ 
     541                                             \ 
     542    r4 = vec_mergeh(r0, r2);  /*0, 2 set 0*/ \ 
     543    r5 = vec_mergel(r0, r2);  /*0, 2 set 1*/ \ 
     544    r6 = vec_mergeh(r1, r3);  /*1, 3 set 0*/ \ 
     545    r7 = vec_mergel(r1, r3);  /*1, 3 set 1*/ \ 
     546                                             \ 
     547    r0 = vec_mergeh(r4, r6);  /*all set 0*/  \ 
     548    r1 = vec_mergel(r4, r6);  /*all set 1*/  \ 
     549    r2 = vec_mergeh(r5, r7);  /*all set 2*/  \ 
     550    r3 = vec_mergel(r5, r7);  /*all set 3*/  \ 
     551} 
     552 
     553static inline void write16x4(uint8_t *dst, int dst_stride,     register vector unsigned char r0, 
     554                             register vector unsigned char r1, register vector unsigned char r2, 
     555                             register vector unsigned char r3) { 
     556    DECLARE_ALIGNED_16(unsigned char, result[64]); 
     557    uint32_t *src_int = (uint32_t *)result, *dst_int = (uint32_t *)dst; 
     558    int int_dst_stride = dst_stride/4; 
     559     
     560    vec_st(r0, 0, result); 
     561    vec_st(r1, 16, result); 
     562    vec_st(r2, 32, result); 
     563    vec_st(r3, 48, result); 
     564    /* there has to be a better way!!!! */ 
     565    *dst_int = *src_int; 
     566    *(dst_int+   int_dst_stride) = *(src_int + 1); 
     567    *(dst_int+ 2*int_dst_stride) = *(src_int + 2); 
     568    *(dst_int+ 3*int_dst_stride) = *(src_int + 3); 
     569    *(dst_int+ 4*int_dst_stride) = *(src_int + 4); 
     570    *(dst_int+ 5*int_dst_stride) = *(src_int + 5); 
     571    *(dst_int+ 6*int_dst_stride) = *(src_int + 6); 
     572    *(dst_int+ 7*int_dst_stride) = *(src_int + 7); 
     573    *(dst_int+ 8*int_dst_stride) = *(src_int + 8); 
     574    *(dst_int+ 9*int_dst_stride) = *(src_int + 9); 
     575    *(dst_int+10*int_dst_stride) = *(src_int + 10); 
     576    *(dst_int+11*int_dst_stride) = *(src_int + 11); 
     577    *(dst_int+12*int_dst_stride) = *(src_int + 12); 
     578    *(dst_int+13*int_dst_stride) = *(src_int + 13); 
     579    *(dst_int+14*int_dst_stride) = *(src_int + 14); 
     580    *(dst_int+15*int_dst_stride) = *(src_int + 15); 
     581} 
     582 
     583/* This function does an 6x16 transpose on data in src, and stores it in dst */ 
     584#define readAndTranspose16x6(src, src_stride, r8, r9, r10, r11, r12, r13) {\ 
     585    register vector unsigned char r0  = read_unaligned(0,             src);\ 
     586    register vector unsigned char r1  = read_unaligned(   src_stride, src);\ 
     587    register vector unsigned char r2  = read_unaligned(2* src_stride, src);\ 
     588    register vector unsigned char r3  = read_unaligned(3* src_stride, src);\ 
     589    register vector unsigned char r4  = read_unaligned(4* src_stride, src);\ 
     590    register vector unsigned char r5  = read_unaligned(5* src_stride, src);\ 
     591    register vector unsigned char r6  = read_unaligned(6* src_stride, src);\ 
     592    register vector unsigned char r7  = read_unaligned(7* src_stride, src);\ 
     593    register vector unsigned char r14 = read_unaligned(14*src_stride, src);\ 
     594    register vector unsigned char r15 = read_unaligned(15*src_stride, src);\ 
     595                                                                           \ 
     596    r8  = read_unaligned( 8*src_stride, src);                              \ 
     597    r9  = read_unaligned( 9*src_stride, src);                              \ 
     598    r10 = read_unaligned(10*src_stride, src);                              \ 
     599    r11 = read_unaligned(11*src_stride, src);                              \ 
     600    r12 = read_unaligned(12*src_stride, src);                              \ 
     601    r13 = read_unaligned(13*src_stride, src);                              \ 
     602                                                                           \ 
     603    /*Merge first pairs*/                                                  \ 
     604    r0 = vec_mergeh(r0, r8);    /*0, 8*/                                   \ 
     605    r1 = vec_mergeh(r1, r9);    /*1, 9*/                                   \ 
     606    r2 = vec_mergeh(r2, r10);   /*2,10*/                                   \ 
     607    r3 = vec_mergeh(r3, r11);   /*3,11*/                                   \ 
     608    r4 = vec_mergeh(r4, r12);   /*4,12*/                                   \ 
     609    r5 = vec_mergeh(r5, r13);   /*5,13*/                                   \ 
     610    r6 = vec_mergeh(r6, r14);   /*6,14*/                                   \ 
     611    r7 = vec_mergeh(r7, r15);   /*7,15*/                                   \ 
     612                                                                           \ 
     613    /*Merge second pairs*/                                                 \ 
     614    r8  = vec_mergeh(r0, r4);   /*0,4, 8,12 set 0*/                        \ 
     615    r9  = vec_mergel(r0, r4);   /*0,4, 8,12 set 1*/                        \ 
     616    r10 = vec_mergeh(r1, r5);   /*1,5, 9,13 set 0*/                        \ 
     617    r11 = vec_mergel(r1, r5);   /*1,5, 9,13 set 1*/                        \ 
     618    r12 = vec_mergeh(r2, r6);   /*2,6,10,14 set 0*/                        \ 
     619    r13 = vec_mergel(r2, r6);   /*2,6,10,14 set 1*/                        \ 
     620    r14 = vec_mergeh(r3, r7);   /*3,7,11,15 set 0*/                        \ 
     621    r15 = vec_mergel(r3, r7);   /*3,7,11,15 set 1*/                        \ 
     622                                                                           \ 
     623    /*Third merge*/                                                        \ 
     624    r0 = vec_mergeh(r8, r12);   /*0,2,4,6,8,10,12,14 set 0*/               \ 
     625    r1 = vec_mergel(r8, r12);   /*0,2,4,6,8,10,12,14 set 1*/               \ 
     626    r2 = vec_mergeh(r9, r13);   /*0,2,4,6,8,10,12,14 set 2*/               \ 
     627    r4 = vec_mergeh(r10, r14);  /*1,3,5,7,9,11,13,15 set 0*/               \ 
     628    r5 = vec_mergel(r10, r14);  /*1,3,5,7,9,11,13,15 set 1*/               \ 
     629    r6 = vec_mergeh(r11, r15);  /*1,3,5,7,9,11,13,15 set 2*/               \ 
     630    /* Don't need to compute 3 and 7*/                                     \ 
     631                                                                           \ 
     632    /*Final merge*/                                                        \ 
     633    r8  = vec_mergeh(r0, r4);   /*all set 0*/                              \ 
     634    r9  = vec_mergel(r0, r4);   /*all set 1*/                              \ 
     635    r10 = vec_mergeh(r1, r5);   /*all set 2*/                              \ 
     636    r11 = vec_mergel(r1, r5);   /*all set 3*/                              \ 
     637    r12 = vec_mergeh(r2, r6);   /*all set 4*/                              \ 
     638    r13 = vec_mergel(r2, r6);   /*all set 5*/                              \ 
     639    /* Don't need to compute 14 and 15*/                                   \ 
     640                                                                           \ 
     641} 
     642 
     643// out: o = |x-y| < a 
     644static inline vector unsigned char diff_lt_altivec ( register vector unsigned char x, 
     645                                                     register vector unsigned char y, 
     646                                                     register vector unsigned char a) { 
     647 
     648    register vector unsigned char diff = vec_subs(x, y); 
     649    register vector unsigned char diffneg = vec_subs(y, x); 
     650    register vector unsigned char o = vec_or(diff, diffneg); /* |x-y| */ 
     651    o = vec_cmplt(o, a); 
     652    return o; 
     653} 
     654 
     655static inline vector unsigned char h264_deblock_mask ( register vector unsigned char p0, 
     656                                                       register vector unsigned char p1, 
     657                                                       register vector unsigned char q0, 
     658                                                       register vector unsigned char q1, 
     659                                                       register vector unsigned char alpha, 
     660                                                       register vector unsigned char beta) { 
     661 
     662    register vector unsigned char mask; 
     663    register vector unsigned char tempmask; 
     664 
     665    mask = diff_lt_altivec(p0, q0, alpha); 
     666    tempmask = diff_lt_altivec(p1, p0, beta); 
     667    mask = vec_and(mask, tempmask); 
     668    tempmask = diff_lt_altivec(q1, q0, beta); 
     669    mask = vec_and(mask, tempmask); 
     670     
     671    return mask; 
     672} 
     673 
     674// out: p1 = clip((p2 + ((p0 + q0 + 1) >> 1)) >> 1, p1-tc0, p1+tc0) 
     675#define h264_deblock_q1(p0, p1, p2, q0, tc0) {                     \ 
     676                                                                   \ 
     677    register vector unsigned char average = vec_avg(p0, q0);       \ 
     678    register vector unsigned char temp;                            \ 
     679    register vector unsigned char uncliped;                        \ 
     680    register vector unsigned char ones;                            \ 
     681    register vector unsigned char max;                             \ 
     682    register vector unsigned char min;                             \ 
     683                                                                   \ 
     684    temp = vec_xor(average, p2);                                   \ 
     685    average = vec_avg(average, p2);     /*avg(p2, avg(p0, q0)) */  \ 
     686    ones = vec_splat_u8(1);                                        \ 
     687    temp = vec_and(temp, ones);         /*(p2^avg(p0, q0)) & 1 */  \ 
     688    uncliped = vec_subs(average, temp); /*(p2+((p0+q0+1)>>1))>>1 */\ 
     689    max = vec_adds(p1, tc0);                                       \ 
     690    min = vec_subs(p1, tc0);                                       \ 
     691    p1 = vec_max(min, uncliped);                                   \ 
     692    p1 = vec_min(max, p1);                                         \ 
     693} 
     694 
     695#define h264_deblock_p0_q0(p0, p1, q0, q1, tc0masked) {                                           \ 
     696                                                                                                  \ 
     697    const vec_u8_t A0v = (vec_u8_t) AVV(0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,                  \ 
     698                                        0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0);                 \ 
     699                                                                                                  \ 
     700    register vector unsigned char pq0bit = vec_xor(p0,q0);                                        \ 
     701    register vector unsigned char temp;                                                           \ 
     702    register vector unsigned char q1minus;                                                        \ 
     703    register vector unsigned char p0minus;                                                        \ 
     704    register vector unsigned char stage1;                                                         \ 
     705    register vector unsigned char stage2;                                                         \ 
     706    register vector unsigned char vec160;                                                         \ 
     707    register vector unsigned char delta;                                                          \ 
     708    register vector unsigned char deltaneg;                                                       \ 
     709                                                                                                  \ 
     710    temp = vec_cmpeq(p0, p0);                                                                     \ 
     711    q1minus = vec_xor(temp, q1);               /* 255 - q1 */                                     \ 
     712    stage1 = vec_avg(p1, q1minus);             /* (p1 - q1 + 256)>>1 */                           \ 
     713    stage2 = vec_sr(stage1, vec_splat_u8(1));  /* (p1 - q1 + 256)>>2 = 64 + (p1 - q1) >> 2 */     \ 
     714    p0minus = vec_xor(temp, p0);               /* 255 - p0 */                                     \ 
     715    stage1 = vec_avg(q0, p0minus);             /* (q0 - p0 + 256)>>1 */                           \ 
     716    pq0bit = vec_and(pq0bit, vec_splat_u8(1));                                                    \ 
     717    stage2 = vec_avg(stage2, pq0bit);          /* 32 + ((q0 - p0)&1 + (p1 - q1) >> 2 + 1) >> 1 */ \ 
     718    stage2 = vec_adds(stage2, stage1);         /* 160 + ((p0 - q0) + (p1 - q1) >> 2 + 1) >> 1 */  \ 
     719    vec160 = vec_ld(0, &A0v);                                                                     \ 
     720    deltaneg = vec_subs(vec160, stage2);       /* -d */                                           \ 
     721    delta = vec_subs(stage2, vec160);          /* d */                                            \ 
     722    deltaneg = vec_min(tc0masked, deltaneg);                                                      \ 
     723    delta = vec_min(tc0masked, delta);                                                            \ 
     724    p0 = vec_subs(p0, deltaneg);                                                                  \ 
     725    q0 = vec_subs(q0, delta);                                                                     \ 
     726    p0 = vec_adds(p0, delta);                                                                     \ 
     727    q0 = vec_adds(q0, deltaneg);                                                                  \ 
     728} 
     729 
     730#define h264_loop_filter_luma_altivec(p2, p1, p0, q0, q1, q2, alpha, beta, tc0) {            \ 
     731    DECLARE_ALIGNED_16(unsigned char, temp[16]);                                             \ 
     732    register vector unsigned char alphavec;                                                  \ 
     733    register vector unsigned char betavec;                                                   \ 
     734    register vector unsigned char mask;                                                      \ 
     735    register vector unsigned char p1mask;                                                    \ 
     736    register vector unsigned char q1mask;                                                    \ 
     737    register vector char tc0vec;                                                             \ 
     738    register vector unsigned char finaltc0;                                                  \ 
     739    register vector unsigned char tc0masked;                                                 \ 
     740                                                                                             \ 
     741    temp[0] = alpha;                                                                         \ 
     742    temp[1] = beta;                                                                          \ 
     743    alphavec = vec_ld(0, temp);                                                              \ 
     744    betavec = vec_splat(alphavec, 0x1);                                                      \ 
     745    alphavec = vec_splat(alphavec, 0x0);                                                     \ 
     746    mask = h264_deblock_mask(p0, p1, q0, q1, alphavec, betavec); /*if in block */            \ 
     747                                                                                             \ 
     748    *((int *)temp) = *((int *)tc0);                                                          \ 
     749    tc0vec = vec_ld(0, temp);                                                                \ 
     750    tc0vec = vec_mergeh(tc0vec, tc0vec);                                                     \ 
     751    tc0vec = vec_mergeh(tc0vec, tc0vec);                                                     \ 
     752    mask = vec_and(mask, vec_cmpgt(tc0vec, vec_splat_u8(-1)));  /* if tc0[i] >= 0 */         \ 
     753    finaltc0 = vec_and(tc0vec, mask);                           /*tc = tc0[i]*/              \ 
     754                                                                                             \ 
     755    p1mask = diff_lt_altivec(p2, p0, betavec);                                               \ 
     756    p1mask = vec_and(p1mask, mask);                             /* if( |p2 - p0| < beta) */  \ 
     757    tc0masked = vec_and(p1mask, tc0vec);                                                     \ 
     758    finaltc0 = vec_sub(finaltc0, p1mask);                       /* tc++ */                   \ 
     759    h264_deblock_q1(p0, p1, p2, q0, tc0masked);                                              \ 
     760    /*end if*/                                                                               \ 
     761                                                                                             \ 
     762    q1mask = diff_lt_altivec(q2, q0, betavec);                                               \ 
     763    q1mask = vec_and(q1mask, mask);                             /* if ( |q2 - q0| < beta ) */\ 
     764    tc0masked = vec_and(q1mask, tc0vec);                                                     \ 
     765    finaltc0 = vec_sub(finaltc0, q1mask);                       /* tc++ */                   \ 
     766    h264_deblock_q1(p0, q1, q2, q0, tc0masked);                                              \ 
     767    /*end if*/                                                                               \ 
     768                                                                                             \ 
     769    h264_deblock_p0_q0(p0, p1, q0, q1, finaltc0);                                            \ 
     770} 
     771 
     772static void h264_v_loop_filter_luma_altivec(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) { 
     773 
     774    if((tc0[0] & tc0[1] & tc0[2] & tc0[3]) >= 0) { 
     775        register vector unsigned char p2 = vec_ld(-3*stride, pix); 
     776        register vector unsigned char p1 = vec_ld(-2*stride, pix); 
     777        register vector unsigned char p0 = vec_ld(-1*stride, pix); 
     778        register vector unsigned char q0 = vec_ld(0, pix); 
     779        register vector unsigned char q1 = vec_ld(stride, pix); 
     780        register vector unsigned char q2 = vec_ld(2*stride, pix); 
     781        h264_loop_filter_luma_altivec(p2, p1, p0, q0, q1, q2, alpha, beta, tc0); 
     782        vec_st(p1, -2*stride, pix); 
     783        vec_st(p0, -1*stride, pix); 
     784        vec_st(q0, 0, pix); 
     785        vec_st(q1, stride, pix); 
     786    } 
     787} 
     788 
     789static void h264_h_loop_filter_luma_altivec(uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0) { 
     790 
     791    register vector unsigned char line0, line1, line2, line3, line4, line5; 
     792    if((tc0[0] & tc0[1] & tc0[2] & tc0[3]) < 0) 
     793        return; 
     794    readAndTranspose16x6(pix-3, stride, line0, line1, line2, line3, line4, line5); 
     795    h264_loop_filter_luma_altivec(line0, line1, line2, line3, line4, line5, alpha, beta, tc0); 
     796    transpose4x16(line1, line2, line3, line4); 
     797    write16x4(pix-2, stride, line1, line2, line3, line4); 
     798} 
     799 
    527800void dsputil_h264_init_ppc(DSPContext* c, AVCodecContext *avctx) { 
    528801 
    529802#ifdef HAVE_ALTIVEC 
     
    532805    c->put_no_rnd_h264_chroma_pixels_tab[0] = put_no_rnd_h264_chroma_mc8_altivec; 
    533806    c->avg_h264_chroma_pixels_tab[0] = avg_h264_chroma_mc8_altivec; 
    534807    c->h264_idct8_add = ff_h264_idct8_add_altivec; 
     808    c->h264_v_loop_filter_luma= h264_v_loop_filter_luma_altivec; 
     809    c->h264_h_loop_filter_luma= h264_h_loop_filter_luma_altivec; 
    535810 
    536811#define dspfunc(PFX, IDX, NUM) \ 
    537812    c->PFX ## _pixels_tab[IDX][ 0] = PFX ## NUM ## _mc00_altivec; \