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

mmsfb_blit_rgb24_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_RGB24__
00036 #ifdef __HAVE_PF_YV12__
00037 
00038 #include "mmstools/mmstools.h"
00039 
00040 void mmsfb_blit_rgb24_to_yv12(MMSFBExternalSurfaceBuffer *extbuf, int src_height, int sx, int sy, int sw, int sh,
00041                               unsigned char *dst, int dst_pitch, int dst_height, int dx, int dy) {
00042     // first time?
00043     static bool firsttime = true;
00044     if (firsttime) {
00045         printf("DISKO: Using accelerated conversion RGB24 to YV12.\n");
00046         firsttime = false;
00047     }
00048 
00049     // get the first source ptr/pitch
00050     unsigned char *src = (unsigned char *)extbuf->ptr;
00051     int src_pitch = extbuf->pitch;
00052 
00053     // prepare...
00054     int  src_pitch_pix      = src_pitch / 3;
00055     int dst_pitch_pix       = dst_pitch;
00056     int dst_pitch_pix_half  = dst_pitch_pix >> 1;
00057 
00058     src+= (sx + sy * src_pitch_pix) * 3;
00059 
00060     // check the surface range
00061     if (dst_pitch_pix - dx < sw - sx)
00062         sw = dst_pitch_pix - dx - sx;
00063     if (dst_height - dy < sh - sy)
00064         sh = dst_height - dy - sy;
00065     if ((sw <= 0)||(sh <= 0))
00066         return;
00067 
00068     int  src_pixels = src_pitch_pix * sh;
00069 
00070     // check odd/even
00071     bool odd_left   = (dx & 0x01);
00072     bool odd_top    = (dy & 0x01);
00073     bool odd_right  = ((dx + sw) & 0x01);
00074     bool odd_bottom = ((dy + sh) & 0x01);
00075 
00076     // pointer to the pixel components of the first pixel
00077     unsigned char *dst_y = dst + dx + dy * dst_pitch_pix;
00078     unsigned char *dst_u = dst + dst_pitch_pix * dst_height + dst_pitch_pix_half * (dst_height >> 1) + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00079     unsigned char *dst_v = dst + dst_pitch_pix * dst_height                                          + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00080 
00081     // offsets to the other three pixels
00082     unsigned int dst_y2_offs = 1;
00083     unsigned int dst_y3_offs = dst_pitch;
00084     unsigned int dst_y4_offs = dst_y3_offs + 1;
00085     unsigned int src2_offs = 3;
00086     unsigned int src3_offs = src_pitch;
00087     unsigned int src4_offs = src3_offs + 3;
00088 
00089     // arithmetic mean
00090     register unsigned int d_u;
00091     register unsigned int d_v;
00092 
00093     // draw odd pixels around the even rectangle
00094     if (odd_top && odd_left) {
00095         // odd top-left pixel
00096         // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00097         d_u = (*dst_u) * 3;
00098         d_v = (*dst_v) * 3;
00099 
00100         // calculate my pixel...
00101         MMSFB_CONV_RGB24_TO_YV12_PIXEL(src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00102 
00103         // calulate the arithmetic mean
00104         *dst_u = d_u >> 2;
00105         *dst_v = d_v >> 2;
00106     }
00107 
00108     if (odd_top && odd_right) {
00109         // odd top-right pixel
00110         MMSFB_CONV_RGB24_TO_YV12_PUSHPTR;
00111 
00112         // go to the pixel in the current line
00113         src   += (sw - 1) * 3;
00114         dst_y += sw - 1;
00115         if (odd_left) {
00116             dst_u += sw >> 1;
00117             dst_v += sw >> 1;
00118         }
00119         else {
00120             dst_u += (sw - 1) >> 1;
00121             dst_v += (sw - 1) >> 1;
00122         }
00123 
00124         // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00125         d_u = (*dst_u) * 3;
00126         d_v = (*dst_v) * 3;
00127 
00128         // calculate my pixel...
00129         MMSFB_CONV_RGB24_TO_YV12_PIXEL(src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00130 
00131         // calulate the arithmetic mean
00132         *dst_u = d_u >> 2;
00133         *dst_v = d_v >> 2;
00134 
00135         // restore the pointers
00136         MMSFB_CONV_RGB24_TO_YV12_POPPTR;
00137     }
00138 
00139     if (odd_bottom && odd_left) {
00140         // odd bottom-left pixel
00141         MMSFB_CONV_RGB24_TO_YV12_PUSHPTR;
00142 
00143         // go to the line
00144         src   += (src_pitch_pix * (sh-1)) * 3;
00145         dst_y += dst_pitch_pix * (sh-1);
00146         if (odd_top) {
00147             dst_u += dst_pitch_pix_half * (sh >> 1);
00148             dst_v += dst_pitch_pix_half * (sh >> 1);
00149         }
00150         else {
00151             dst_u += dst_pitch_pix_half * ((sh-1) >> 1);
00152             dst_v += dst_pitch_pix_half * ((sh-1) >> 1);
00153         }
00154 
00155         // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00156         d_u = (*dst_u) * 3;
00157         d_v = (*dst_v) * 3;
00158 
00159         // calculate my pixel...
00160         MMSFB_CONV_RGB24_TO_YV12_PIXEL(src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00161 
00162         // calulate the arithmetic mean
00163         *dst_u = d_u >> 2;
00164         *dst_v = d_v >> 2;
00165 
00166         // restore the pointers
00167         MMSFB_CONV_RGB24_TO_YV12_POPPTR;
00168     }
00169 
00170     if (odd_bottom && odd_right) {
00171         // odd bottom-right pixel
00172         MMSFB_CONV_RGB24_TO_YV12_PUSHPTR;
00173 
00174         // go to the line
00175         src   += (src_pitch_pix * (sh-1)) * 3;
00176         dst_y += dst_pitch_pix * (sh-1);
00177         if (odd_top) {
00178             dst_u += dst_pitch_pix_half * (sh >> 1);
00179             dst_v += dst_pitch_pix_half * (sh >> 1);
00180         }
00181         else {
00182             dst_u += dst_pitch_pix_half * ((sh-1) >> 1);
00183             dst_v += dst_pitch_pix_half * ((sh-1) >> 1);
00184         }
00185 
00186         // go to the pixel in the current line
00187         src   += (sw - 1) * 3;
00188         dst_y += sw - 1;
00189         if (odd_left) {
00190             dst_u += sw >> 1;
00191             dst_v += sw >> 1;
00192         }
00193         else {
00194             dst_u += (sw - 1) >> 1;
00195             dst_v += (sw - 1) >> 1;
00196         }
00197 
00198         // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00199         d_u = (*dst_u) * 3;
00200         d_v = (*dst_v) * 3;
00201 
00202         // calculate my pixel...
00203         MMSFB_CONV_RGB24_TO_YV12_PIXEL(src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00204 
00205         // calulate the arithmetic mean
00206         *dst_u = d_u >> 2;
00207         *dst_v = d_v >> 2;
00208 
00209         // restore the pointers
00210         MMSFB_CONV_RGB24_TO_YV12_POPPTR;
00211     }
00212 
00213     if (odd_top) {
00214         // odd top line
00215         MMSFB_CONV_RGB24_TO_YV12_PUSHPTR;
00216 
00217         // calculate start and end
00218         unsigned char *line_end = src + sw * 3;
00219         if (odd_left) {
00220             src+=3;
00221             dst_y++;
00222             dst_u++;
00223             dst_v++;
00224             line_end-=3;
00225         }
00226         if (odd_right)
00227             line_end-=3;
00228 
00229         // through the line
00230         while (src < line_end) {
00231             // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00232             d_u = (*dst_u) << 1;
00233             d_v = (*dst_v) << 1;
00234 
00235             // calculate my two pixels...
00236             MMSFB_CONV_RGB24_TO_YV12_PIXEL(src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00237             MMSFB_CONV_RGB24_TO_YV12_PIXEL(src+src2_offs, dst_y[dst_y2_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00238 
00239             // calulate the arithmetic mean
00240             *dst_u = d_u >> 2;
00241             *dst_v = d_v >> 2;
00242 
00243             // go to the next two pixels
00244             src+=2*3;
00245             dst_y+=2;
00246             dst_u++;
00247             dst_v++;
00248         }
00249 
00250         // restore the pointers
00251         MMSFB_CONV_RGB24_TO_YV12_POPPTR;
00252     }
00253 
00254     if (odd_bottom) {
00255         // odd bottom line
00256         MMSFB_CONV_RGB24_TO_YV12_PUSHPTR;
00257 
00258         // calculate start and end
00259         src   += (src_pitch_pix * (sh-1)) * 3;
00260         dst_y += dst_pitch_pix * (sh-1);
00261         if (odd_top) {
00262             dst_u += dst_pitch_pix_half * (sh >> 1);
00263             dst_v += dst_pitch_pix_half * (sh >> 1);
00264         }
00265         else {
00266             dst_u += dst_pitch_pix_half * ((sh-1) >> 1);
00267             dst_v += dst_pitch_pix_half * ((sh-1) >> 1);
00268         }
00269 
00270         unsigned char *line_end = src + sw * 3;
00271         if (odd_left) {
00272             src+=3;
00273             dst_y++;
00274             dst_u++;
00275             dst_v++;
00276             line_end-=3;
00277         }
00278         if (odd_right)
00279             line_end-=3;
00280 
00281         // through the line
00282         while (src < line_end) {
00283             // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00284             d_u = (*dst_u) << 1;
00285             d_v = (*dst_v) << 1;
00286 
00287             // calculate my two pixels...
00288             MMSFB_CONV_RGB24_TO_YV12_PIXEL(src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00289             MMSFB_CONV_RGB24_TO_YV12_PIXEL(src+src2_offs, dst_y[dst_y2_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00290 
00291             // calulate the arithmetic mean
00292             *dst_u = d_u >> 2;
00293             *dst_v = d_v >> 2;
00294 
00295             // go to the next two pixels
00296             src+=2*3;
00297             dst_y+=2;
00298             dst_u++;
00299             dst_v++;
00300         }
00301 
00302         // restore the pointers
00303         MMSFB_CONV_RGB24_TO_YV12_POPPTR;
00304     }
00305 
00306     if (odd_left) {
00307         // odd left line
00308         MMSFB_CONV_RGB24_TO_YV12_PUSHPTR;
00309 
00310         // calculate start and end
00311         unsigned char *src_end = src + src_pixels * 3;
00312         int src_pitch_diff    = (src_pitch_pix << 1) * 3;
00313         int dst_pitch_diff    = dst_pitch_pix << 1;
00314         int dst_pitch_uvdiff  = dst_pitch_pix_half;
00315         if (odd_top) {
00316             src     += src_pitch_pix * 3;
00317             src_end -= src_pitch_pix * 3;
00318             dst_y   += dst_pitch_pix;
00319             dst_u   += dst_pitch_pix_half;
00320             dst_v   += dst_pitch_pix_half;
00321         }
00322         if (odd_bottom)
00323             src_end -= src_pitch_pix * 3;
00324 
00325         // through all lines
00326         while (src < src_end) {
00327             // for the first pixel in the line
00328             // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00329             d_u = (*dst_u) << 1;
00330             d_v = (*dst_v) << 1;
00331 
00332             // calculate my two pixels...
00333             MMSFB_CONV_RGB24_TO_YV12_PIXEL(src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00334             MMSFB_CONV_RGB24_TO_YV12_PIXEL(src+src3_offs, dst_y[dst_y3_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00335 
00336             // calulate the arithmetic mean
00337             *dst_u = d_u >> 2;
00338             *dst_v = d_v >> 2;
00339 
00340             // go to the next two lines
00341             src   += src_pitch_diff;
00342             dst_y += dst_pitch_diff;
00343             dst_u += dst_pitch_uvdiff;
00344             dst_v += dst_pitch_uvdiff;
00345         }
00346 
00347         // restore the pointers
00348         MMSFB_CONV_RGB24_TO_YV12_POPPTR;
00349     }
00350 
00351     if (odd_right) {
00352         // odd right line
00353         MMSFB_CONV_RGB24_TO_YV12_PUSHPTR;
00354 
00355         // calculate start and end
00356         unsigned char *src_end = src + src_pixels * 3;
00357         int src_pitch_diff    = (src_pitch_pix << 1) * 3;
00358         int dst_pitch_diff    = dst_pitch_pix << 1;
00359         int dst_pitch_uvdiff  = dst_pitch_pix_half;
00360         src   += (sw - 1) * 3;
00361         dst_y += sw - 1;
00362         if (odd_left) {
00363             dst_u += sw >> 1;
00364             dst_v += sw >> 1;
00365         }
00366         else {
00367             dst_u += (sw - 1) >> 1;
00368             dst_v += (sw - 1) >> 1;
00369         }
00370         if (odd_top) {
00371             src     += src_pitch_pix * 3;
00372             src_end -= src_pitch_pix * 3;
00373             dst_y   += dst_pitch_pix;
00374             dst_u   += dst_pitch_pix_half;
00375             dst_v   += dst_pitch_pix_half;
00376         }
00377         if (odd_bottom)
00378             src_end -= src_pitch_pix * 3;
00379 
00380         // through all lines
00381         while (src < src_end) {
00382             // for the first pixel in the line
00383             // for arithmetic mean we have to set U and V from pixels outside the current rectangle
00384             d_u = (*dst_u) << 1;
00385             d_v = (*dst_v) << 1;
00386 
00387             // calculate my two pixels...
00388             MMSFB_CONV_RGB24_TO_YV12_PIXEL(src, *dst_y, *dst_u, *dst_v, d_u+=, d_v+=);
00389             MMSFB_CONV_RGB24_TO_YV12_PIXEL(src+src3_offs, dst_y[dst_y3_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00390 
00391             // calulate the arithmetic mean
00392             *dst_u = d_u >> 2;
00393             *dst_v = d_v >> 2;
00394 
00395             // go to the next two lines
00396             src   += src_pitch_diff;
00397             dst_y += dst_pitch_diff;
00398             dst_u += dst_pitch_uvdiff;
00399             dst_v += dst_pitch_uvdiff;
00400         }
00401 
00402         // restore the pointers
00403         MMSFB_CONV_RGB24_TO_YV12_POPPTR;
00404     }
00405 
00406     // calc even positions...
00407     if (odd_top) {
00408         // odd top
00409         dy++;
00410         sh--;
00411         src+=src_pitch_pix * 3;
00412         src_pixels-=src_pitch_pix;
00413         dst_y+=dst_pitch;
00414         dst_u+=dst_pitch >> 1;
00415         dst_v+=dst_pitch >> 1;
00416     }
00417 
00418     if (odd_bottom) {
00419         // odd bottom
00420         src_height--;
00421         src_pixels-=src_pitch_pix;
00422     }
00423 
00424     if (odd_left) {
00425         // odd left
00426         dx++;
00427         sw--;
00428         src+=3;
00429         dst_y++;
00430         dst_u++;
00431         dst_v++;
00432     }
00433 
00434     if (odd_right) {
00435         // odd right
00436         sw--;
00437     }
00438 
00439     // now we are even aligned and can go through a optimized loop
00440     ////////////////////////////////////////////////////////////////////////
00441     unsigned char *src_end = src + src_pixels * 3;
00442     int src_pitch_diff = ((src_pitch_pix << 1) - sw) * 3;
00443     int dst_pitch_diff = (dst_pitch_pix << 1) - sw;
00444     int dst_pitch_uvdiff = (dst_pitch_pix - sw) >> 1;
00445     int swb = sw * 3;
00446 
00447     // for all lines
00448     while (src < src_end) {
00449         // for all pixels in the line
00450         unsigned char *line_end = src + swb;
00451 
00452         // go through two lines in parallel (square 2x2 pixel)
00453         while (src < line_end) {
00454             // calculate the four pixels...
00455             MMSFB_CONV_RGB24_TO_YV12_PIXEL(src, *dst_y, *dst_u, *dst_v, d_u=, d_v=);
00456             MMSFB_CONV_RGB24_TO_YV12_PIXEL(src+src2_offs, dst_y[dst_y2_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00457             MMSFB_CONV_RGB24_TO_YV12_PIXEL(src+src3_offs, dst_y[dst_y3_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00458             MMSFB_CONV_RGB24_TO_YV12_PIXEL(src+src4_offs, dst_y[dst_y4_offs], *dst_u, *dst_v, d_u+=, d_v+=);
00459 
00460             // calulate the arithmetic mean
00461             *dst_u = d_u >> 2;
00462             *dst_v = d_v >> 2;
00463 
00464             // go to the next two pixels
00465             src  +=2*3;
00466             dst_y+=2;
00467             dst_u++;
00468             dst_v++;
00469         }
00470 
00471         // go to the next two lines
00472         src   += src_pitch_diff;
00473         dst_y += dst_pitch_diff;
00474         dst_u += dst_pitch_uvdiff;
00475         dst_v += dst_pitch_uvdiff;
00476     }
00477 }
00478 
00479 #endif
00480 #endif

Generated by doxygen