Logo
  • Main Page
  • Related Pages
  • Modules
  • Classes
  • Files

mmsfb_stretchblit_yv12_to_yv12.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2005-2007 Stefan Schwarzer, Jens Schneider,             *
00003  *                           Matthias Hardt, Guido Madaus                  *
00004  *                                                                         *
00005  *   Copyright (C) 2007-2008 BerLinux Solutions GbR                        *
00006  *                           Stefan Schwarzer & Guido Madaus               *
00007  *                                                                         *
00008  *   Copyright (C) 2009-2013 BerLinux Solutions GmbH                       *
00009  *                                                                         *
00010  *   Authors:                                                              *
00011  *      Stefan Schwarzer   <stefan.schwarzer@diskohq.org>,                 *
00012  *      Matthias Hardt     <matthias.hardt@diskohq.org>,                   *
00013  *      Jens Schneider     <jens.schneider@diskohq.org>,                   *
00014  *      Guido Madaus       <guido.madaus@diskohq.org>,                     *
00015  *      Patrick Helterhoff <patrick.helterhoff@diskohq.org>,               *
00016  *      René Bählkow       <rene.baehlkow@diskohq.org>                     *
00017  *                                                                         *
00018  *   This library is free software; you can redistribute it and/or         *
00019  *   modify it under the terms of the GNU Lesser General Public            *
00020  *   License version 2.1 as published by the Free Software Foundation.     *
00021  *                                                                         *
00022  *   This library is distributed in the hope that it will be useful,       *
00023  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00024  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00025  *   Lesser General Public License for more details.                       *
00026  *                                                                         *
00027  *   You should have received a copy of the GNU Lesser General Public      *
00028  *   License along with this library; if not, write to the                 *
00029  *   Free Software Foundation, Inc.,                                       *
00030  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
00031  **************************************************************************/
00032 
00033 #include "mmsgui/fb/mmsfbconv.h"
00034 
00035 #ifdef __HAVE_PF_YV12__
00036 
00037 #include "mmstools/mmstools.h"
00038 
00039 #ifdef __HAVE_SWSCALE__
00040 extern "C" {
00041 #include <libswscale/swscale.h>
00042 }
00043 #endif
00044 
00045 void mmsfb_stretchblit_yv12_to_yv12(MMSFBSurfacePlanes *src_planes, int src_height, int sx, int sy, int sw, int sh,
00046                                     MMSFBSurfacePlanes *dst_planes, int dst_height, int dx, int dy, int dw, int dh,
00047                                     bool antialiasing) {
00048     // first time?
00049     static bool firsttime = true;
00050     if (firsttime) {
00051         printf("DISKO: Using accelerated stretch YV12 to YV12.\n");
00052         firsttime = false;
00053     }
00054 
00055 //dy = 200;
00056 //dh-= 400;
00057 
00058 
00059 //////TESTONLY//////
00060 #ifdef __HAVE_SWSCALE__
00061     static int fff = 0;
00062 #endif
00063     static int testswitchtime = 0;
00064     static int testswitch = 0;
00065     if (!testswitchtime) {
00066         testswitchtime=time(NULL)+30;
00067 #ifdef __HAVE_SWSCALE__
00068         printf(">>> using disko stretchblit YV12\n");
00069 #endif
00070     }
00071     else
00072     if (testswitchtime < time(NULL)) {
00073         testswitchtime=time(NULL)+30;
00074         testswitch++;
00075         if (testswitch > 11)
00076             testswitch = 0;
00077 #ifdef __HAVE_SWSCALE__
00078         switch (testswitch) {
00079         case 0:
00080             printf(">>> using disko stretchblit YV12\n");
00081             break;
00082         case 1:
00083             fff = SWS_POINT;
00084             printf(">>> using SWSCALE stretchblit flag=SWS_POINT\n");
00085             break;
00086         case 2:
00087             fff = SWS_AREA;
00088             printf(">>> using SWSCALE stretchblit flag=SWS_AREA\n");
00089             break;
00090         case 3:
00091             fff = SWS_BILINEAR;
00092             printf(">>> using SWSCALE stretchblit flag=SWS_BILINEAR\n");
00093             break;
00094         case 4:
00095             fff = SWS_FAST_BILINEAR;
00096             printf(">>> using SWSCALE stretchblit flag=SWS_FAST_BILINEAR\n");
00097             break;
00098         case 5:
00099             fff = SWS_BICUBIC;
00100             printf(">>> using SWSCALE stretchblit flag=SWS_BICUBIC\n");
00101             break;
00102         case 6:
00103             fff = SWS_X;
00104             printf(">>> using SWSCALE stretchblit flag=SWS_X\n");
00105             break;
00106         case 7:
00107             fff = SWS_GAUSS;
00108             printf(">>> using SWSCALE stretchblit flag=SWS_GAUSS\n");
00109             break;
00110         case 8:
00111             fff = SWS_LANCZOS;
00112             printf(">>> using SWSCALE stretchblit flag=SWS_LANCZOS\n");
00113             break;
00114         case 9:
00115             fff = SWS_SINC;
00116             printf(">>> using SWSCALE stretchblit flag=SWS_SINC\n");
00117             break;
00118         case 10:
00119             fff = SWS_SPLINE;
00120             printf(">>> using SWSCALE stretchblit flag=SWS_SPLINE\n");
00121             break;
00122         case 11:
00123             fff = SWS_BICUBLIN;
00124             printf(">>> using SWSCALE stretchblit flag=SWS_BICUBLIN\n");
00125             break;
00126         }
00127 
00128         /*
00129         02585     i= flags & ( SWS_POINT
00130         02586                 |SWS_AREA
00131         02587                 |SWS_BILINEAR
00132         02588                 |SWS_FAST_BILINEAR
00133         02589                 |SWS_BICUBIC
00134         02590                 |SWS_X
00135         02591                 |SWS_GAUSS
00136         02592                 |SWS_LANCZOS
00137         02593                 |SWS_SINC
00138         02594                 |SWS_SPLINE
00139         02595                 |SWS_BICUBLIN);
00140 */
00141 
00142 
00143 
00144 
00145 #endif
00146     }
00147     if (testswitch > 0) {
00148 /////TESTONLY///////
00149 #ifdef __HAVE_SWSCALE__
00150     // this code is for libswscale support...
00151     if   ((sx == 0 && dx == 0)
00152         &&(src_planes->pitch == sw && src_height >= (sy + sh))
00153         &&(dst_planes->pitch == dw && dst_height >= (dy + dh))) {
00154         // stretchblit with libswscale
00155         // note: the width of the source and destination rectangle MUST
00156         //       fit the width of the surfaces!!!
00157         // note: the position and the height of the source and destination rectangle
00158         //       should be multiple of two
00159         static SwsContext *sws_context = NULL;
00160         if (!sws_context) {
00161             const char *license = swscale_license();
00162             printf("DISKO: Using libswscale with license %s\n", license);
00163         }
00164 
00165         // multiple of two check
00166         if (sy & 0x01) {
00167             sy++;
00168             sh--;
00169         }
00170         if (dy & 0x01) {
00171             dy++;
00172             dh--;
00173         }
00174         sh = sh & ~0x01;
00175         dh = dh & ~0x01;
00176 
00177         // pixel width & height of source and destination
00178         int pix_src_width = src_planes->pitch;
00179         int pix_src_height = sh;
00180         int pix_dst_width = dst_planes->pitch;
00181         int pix_dst_height = dh;
00182         int src_yoffs = sy * src_planes->pitch;
00183         int dst_yoffs = dy * dst_planes->pitch;
00184         int flags = fff;
00185 
00186         // get an sws context with pixelformat PIX_FMT_YUV420P
00187         // which is equal to MMSFB_PF_I420 (reverse UV planes as against MMSFB_PF_YV12)
00188         // note: if the parameters are changed, a new context will be created
00189         //       else the previous context will be used
00190         sws_context = sws_getCachedContext( sws_context,
00191                                             pix_src_width, pix_src_height, PIX_FMT_YUV420P,
00192                                             pix_dst_width, pix_dst_height, PIX_FMT_YUV420P,
00193                                             flags, NULL, NULL, NULL);
00194         if (!sws_context) {
00195             // error, using disko YV12 stretch blit fall back
00196             printf("DISKO: Failed to get SwsContext, using YV12 stretch blit fall back\n");
00197         }
00198         else {
00199             // set source pitches
00200             int sws_src_stride[3];
00201             sws_src_stride[0] = src_planes->pitch;
00202             sws_src_stride[1] = sws_src_stride[2] = src_planes->pitch/2;
00203 
00204             // set destination pitches
00205             int sws_dst_stride[3];
00206             sws_dst_stride[0] = dst_planes->pitch;
00207             sws_dst_stride[1] = sws_dst_stride[2] = dst_planes->pitch/2;
00208 
00209             // set source planes (reverse order, because source is YV12)
00210             uint8_t* sws_src[3];
00211             sws_src[0] = (uint8_t*)src_planes->ptr;
00212             if (!src_planes->ptr2) {
00213                 // no plane pointers given, calculate it
00214                 sws_src[2] = sws_src[0] + src_planes->pitch * src_height;
00215                 sws_src[1] = sws_src[2] + src_planes->pitch * src_height / 4;
00216             }
00217             else {
00218                 // set plane pointers
00219                 sws_src[2] = (uint8_t*)src_planes->ptr2;
00220                 sws_src[1] = (uint8_t*)src_planes->ptr3;
00221             }
00222 
00223             // add source offset
00224             sws_src[0] = sws_src[0] + src_yoffs;
00225             sws_src[1] = sws_src[1] + (src_yoffs >> 2);
00226             sws_src[2] = sws_src[2] + (src_yoffs >> 2);
00227 
00228             // set destination planes (reverse order, because destination is YV12)
00229             uint8_t* sws_dst[3];
00230             sws_dst[0] = (uint8_t*)dst_planes->ptr;
00231             if (!dst_planes->ptr2) {
00232                 // no plane pointers given, calculate it
00233                 sws_dst[2] = sws_dst[0] + dst_planes->pitch * dst_height;
00234                 sws_dst[1] = sws_dst[2] + dst_planes->pitch * dst_height / 4;
00235             }
00236             else {
00237                 // set plane pointers
00238                 sws_dst[2] = (uint8_t*)dst_planes->ptr2;
00239                 sws_dst[1] = (uint8_t*)dst_planes->ptr3;
00240             }
00241 
00242             // add destination offset
00243             sws_dst[0] = sws_dst[0] + dst_yoffs;
00244             sws_dst[1] = sws_dst[1] + (dst_yoffs >> 2);
00245             sws_dst[2] = sws_dst[2] + (dst_yoffs >> 2);
00246 
00247             // scale the buffer
00248             sws_scale(  sws_context,
00249                         sws_src, sws_src_stride, 0, pix_src_height,
00250                         sws_dst, sws_dst_stride);
00251 
00252             // finished :)
00253             return;
00254         }
00255     }
00256 #endif
00257 
00258     }
00259 
00260 
00261     // here starts the disko YV12 stretch blit...
00262 
00263     // get the first source ptr/pitch
00264     unsigned char *src = (unsigned char *)src_planes->ptr;
00265     int src_pitch = src_planes->pitch;
00266 
00267     // get the first destination ptr/pitch
00268     unsigned char *dst = (unsigned char *)dst_planes->ptr;
00269     int dst_pitch = dst_planes->pitch;
00270 
00271     // prepare...
00272     int src_pitch_pix       = src_pitch;
00273     int src_pitch_pix_half  = src_pitch_pix >> 1;
00274     int dst_pitch_pix       = dst_pitch;
00275     int dst_pitch_pix_half  = dst_pitch_pix >> 1;
00276 
00277     // check the surface range
00278     if ((sw <= 0)||(sh <= 0))
00279         return;
00280 
00281     // check odd/even
00282     bool src_odd_left   = (sx & 0x01);
00283     bool src_odd_top    = (sy & 0x01);
00284     bool src_odd_right  = ((sx + sw) & 0x01);
00285     bool src_odd_bottom = ((sy + sh) & 0x01);
00286     bool dst_odd_left   = (dx & 0x01);
00287     bool dst_odd_top    = (dy & 0x01);
00288     bool dst_odd_right  = ((dx + dw) & 0x01);
00289     bool dst_odd_bottom = ((dy + dh) & 0x01);
00290 
00291     // pointer to the pixel components of the first source pixel
00292     unsigned char *src_y = src + sx + sy * src_pitch_pix;
00293     unsigned char *src_u;
00294     unsigned char *src_v;
00295     if ((src_planes->ptr2)&&(src_planes->ptr3)) {
00296         src_u = (unsigned char *)src_planes->ptr3 + (sx >> 1) + (sy >> 1) * src_pitch_pix_half;
00297         src_v = (unsigned char *)src_planes->ptr2 + (sx >> 1) + (sy >> 1) * src_pitch_pix_half;
00298     }
00299     else {
00300         src_u = src + src_pitch_pix * src_height + src_pitch_pix_half * (src_height >> 1) + (sx >> 1) + (sy >> 1) * src_pitch_pix_half;
00301         src_v = src + src_pitch_pix * src_height                                          + (sx >> 1) + (sy >> 1) * src_pitch_pix_half;
00302     }
00303 
00304     // pointer to the pixel components of the first destination pixel
00305     unsigned char *dst_y = dst + dx + dy * dst_pitch_pix;
00306     unsigned char *dst_u;
00307     unsigned char *dst_v;
00308     if ((dst_planes->ptr2)&&(dst_planes->ptr3)) {
00309         dst_u = (unsigned char *)dst_planes->ptr2 + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00310         dst_v = (unsigned char *)dst_planes->ptr3 + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00311     }
00312     else {
00313         dst_u = dst + dst_pitch_pix * dst_height + dst_pitch_pix_half * (dst_height >> 1) + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00314         dst_v = dst + dst_pitch_pix * dst_height                                          + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00315     }
00316 
00317     // antialiasing horizontal/vertical/both
00318     bool h_antialiasing = false;
00319     bool v_antialiasing = false;
00320     if (antialiasing) {
00321         if (sw != dw)
00322             h_antialiasing = true;
00323         if (sh != dh)
00324             v_antialiasing = true;
00325     }
00326 
00327     // calc even positions for src...
00328     if (src_odd_top) {
00329         // odd top
00330         sy++;
00331         sh--;
00332         src_y+=src_pitch;
00333         src_u+=src_pitch >> 1;
00334         src_v+=src_pitch >> 1;
00335     }
00336     if (src_odd_bottom) {
00337         // odd bottom
00338         src_height--;
00339     }
00340     if (src_odd_left) {
00341         // odd left
00342         sx++;
00343         sw--;
00344         src_y++;
00345         src_u++;
00346         src_v++;
00347     }
00348     if (src_odd_right) {
00349         // odd right
00350         sw--;
00351     }
00352 
00353     // calc even positions for dst...
00354     if (dst_odd_top) {
00355         // odd top
00356         dy++;
00357         dh--;
00358         dst_y+=dst_pitch;
00359         dst_u+=dst_pitch >> 1;
00360         dst_v+=dst_pitch >> 1;
00361     }
00362     if (dst_odd_bottom) {
00363         // odd bottom
00364         dst_height--;
00365     }
00366     if (dst_odd_left) {
00367         // odd left
00368         dx++;
00369         dw--;
00370         dst_y++;
00371         dst_u++;
00372         dst_v++;
00373     }
00374     if (dst_odd_right) {
00375         // odd right
00376         dw--;
00377     }
00378 
00379     // check if something to do :)
00380     if ((sw < 2)||(sh < 2)||(dw < 2)||(dh < 2))
00381         return;
00382 
00383     // now we are even aligned and can go through a optimized loop
00384     ////////////////////////////////////////////////////////////////////////
00385 
00386 //printf("sw=%d,dw=%d,sh=%d,dh=%d\n", sw,dw, sh,dh);
00387 
00388     // calc U plane (use Y plane as temp buffer)
00389     // note: concerning performance we use vertical antialiasing only in combination with horizontal antialiasing
00390     // note: the stretch and the subsequent 2x2 matrix conversion is needed to calculate the correct arithmetic mean
00391     stretch_byte_buffer(h_antialiasing, h_antialiasing,
00392                         src_u, src_pitch >> 1, src_pitch_pix >> 1, src_height >> 1, sw >> 1, sh >> 1,
00393                         dst_y, dst_pitch, dst_pitch_pix, dst_height, dw, dh);
00394     compress_2x2_matrix(dst_y, dst_pitch, dst_pitch_pix, dst_height, dw, dh,
00395                         dst_u, dst_pitch >> 1, dst_pitch_pix >> 1, dst_height >> 1, dw >> 1, dh >> 1);
00396 
00397     // calc V plane (use Y plane as temp buffer)
00398     // note: concerning performance we use vertical antialiasing only in combination with horizontal antialiasing
00399     // note: the stretch and the subsequent 2x2 matrix conversion is needed to calculate the correct arithmetic mean
00400     stretch_byte_buffer(h_antialiasing, h_antialiasing,
00401                         src_v, src_pitch >> 1, src_pitch_pix >> 1, src_height >> 1, sw >> 1, sh >> 1,
00402                         dst_y, dst_pitch, dst_pitch_pix, dst_height, dw, dh);
00403     compress_2x2_matrix(dst_y, dst_pitch, dst_pitch_pix, dst_height, dw, dh,
00404                         dst_v, dst_pitch >> 1, dst_pitch_pix >> 1, dst_height >> 1, dw >> 1, dh >> 1);
00405 
00406     // calc Y plane
00407     stretch_byte_buffer(h_antialiasing, v_antialiasing,
00408                         src_y, src_pitch, src_pitch_pix, src_height, sw, sh,
00409                         dst_y, dst_pitch, dst_pitch_pix, dst_height, dw, dh);
00410 }
00411 
00412 #endif

Generated by doxygen