Home | History | Annotate | Download | only in libcopybit
      1 /*
      2  * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *     * Redistributions of source code must retain the above copyright
      8  *       notice, this list of conditions and the following disclaimer.
      9  *     * Redistributions in binary form must reproduce the above
     10  *       copyright notice, this list of conditions and the following
     11  *       disclaimer in the documentation and/or other materials provided
     12  *       with the distribution.
     13  *     * Neither the name of The Linux Foundation nor the names of its
     14  *       contributors may be used to endorse or promote products derived
     15  *       from this software without specific prior written permission.
     16  *
     17  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
     18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
     21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     24  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     25  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     26  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
     27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #include <cutils/log.h>
     31 #include <string.h>
     32 #include <stdlib.h>
     33 #include <errno.h>
     34 #include "software_converter.h"
     35 
     36 /** Convert YV12 to YCrCb_420_SP */
     37 int convertYV12toYCrCb420SP(const copybit_image_t *src, private_handle_t *yv12_handle)
     38 {
     39     private_handle_t* hnd = (private_handle_t*)src->handle;
     40 
     41     if(hnd == NULL || yv12_handle == NULL){
     42         ALOGE("Invalid handle");
     43         return -1;
     44     }
     45 
     46     // Please refer to the description of YV12 in hardware.h
     47     // for the formulae used to calculate buffer sizes and offsets
     48 
     49     // In a copybit_image_t, w is the stride and
     50     // stride - horiz_padding is the actual width
     51     // vertical stride is the same as height, so not considered
     52     unsigned int   stride  = src->w;
     53     unsigned int   width   = src->w - src->horiz_padding;
     54     unsigned int   height  = src->h;
     55     unsigned int   y_size  = stride * src->h;
     56     unsigned int   c_width = ALIGN(stride/2, (unsigned int)16);
     57     unsigned int   c_size  = c_width * src->h/2;
     58     unsigned int   chromaPadding = c_width - width/2;
     59     unsigned int   chromaSize = c_size * 2;
     60     unsigned char* newChroma = (unsigned char *)(yv12_handle->base + y_size);
     61     unsigned char* oldChroma = (unsigned char*)(hnd->base + y_size);
     62     memcpy((char *)yv12_handle->base,(char *)hnd->base,y_size);
     63 
     64 #if defined(__ARM_HAVE_NEON) && !defined(__aarch64__)
     65    /* interleave */
     66     if(!chromaPadding) {
     67         unsigned char * t1 = newChroma;
     68         unsigned char * t2 = oldChroma;
     69         unsigned char * t3 = t2 + chromaSize/2;
     70         for(unsigned int i=0; i < (chromaSize/2)>>3; i++) {
     71             __asm__ __volatile__ (
     72                                     "vld1.u8 d0, [%0]! \n"
     73                                     "vld1.u8 d1, [%1]! \n"
     74                                     "vst2.u8 {d0, d1}, [%2]! \n"
     75                                     :"+r"(t2), "+r"(t3), "+r"(t1)
     76                                     :
     77                                     :"memory","d0","d1"
     78                                  );
     79 
     80         }
     81     }
     82 #else  //__ARM_HAVE_NEON
     83     if(!chromaPadding) {
     84         for(unsigned int i = 0; i< chromaSize/2; i++) {
     85             newChroma[i*2]   = oldChroma[i];
     86             newChroma[i*2+1] = oldChroma[i+chromaSize/2];
     87         }
     88 
     89     }
     90 #endif
     91     // If the image is not aligned to 16 pixels,
     92     // convert using the C routine below
     93     // r1 tracks the row of the source buffer
     94     // r2 tracks the row of the destination buffer
     95     // The width/2 checks are to avoid copying
     96     // from the padding
     97 
     98     if(chromaPadding) {
     99         unsigned int r1 = 0, r2 = 0, i = 0, j = 0;
    100         while(r1 < height/2) {
    101             if(j == width) {
    102                 j = 0;
    103                 r2++;
    104                 continue;
    105             }
    106             if (j+1 == width) {
    107                 newChroma[r2*width + j] = oldChroma[r1*c_width+i];
    108                 r2++;
    109                 newChroma[r2*width] = oldChroma[r1*c_width+i+c_size];
    110                 j = 1;
    111             } else {
    112                 newChroma[r2*width + j] = oldChroma[r1*c_width+i];
    113                 newChroma[r2*width + j + 1] = oldChroma[r1*c_width+i+c_size];
    114                 j+=2;
    115             }
    116             i++;
    117             if (i == width/2 ) {
    118                 i = 0;
    119                 r1++;
    120             }
    121         }
    122     }
    123 
    124   return 0;
    125 }
    126 
    127 struct copyInfo{
    128     int width;
    129     int height;
    130     int src_stride;
    131     int dst_stride;
    132     size_t src_plane1_offset;
    133     size_t src_plane2_offset;
    134     size_t dst_plane1_offset;
    135     size_t dst_plane2_offset;
    136 };
    137 
    138 /* Internal function to do the actual copy of source to destination */
    139 static int copy_source_to_destination(const uintptr_t src_base,
    140                                       const uintptr_t dst_base,
    141                                       copyInfo& info)
    142 {
    143     if (!src_base || !dst_base) {
    144         ALOGE("%s: invalid memory src_base = 0x%p dst_base=0x%p",
    145              __FUNCTION__, (void*)src_base, (void*)dst_base);
    146          return COPYBIT_FAILURE;
    147     }
    148 
    149     int width = info.width;
    150     int height = info.height;
    151     unsigned char *src = (unsigned char*)src_base;
    152     unsigned char *dst = (unsigned char*)dst_base;
    153 
    154     // Copy the luma
    155     for (int i = 0; i < height; i++) {
    156         memcpy(dst, src, width);
    157         src += info.src_stride;
    158         dst += info.dst_stride;
    159     }
    160 
    161     // Copy plane 1
    162     src = (unsigned char*)(src_base + info.src_plane1_offset);
    163     dst = (unsigned char*)(dst_base + info.dst_plane1_offset);
    164     width = width/2;
    165     height = height/2;
    166     for (int i = 0; i < height; i++) {
    167         memcpy(dst, src, info.src_stride);
    168         src += info.src_stride;
    169         dst += info.dst_stride;
    170     }
    171     return 0;
    172 }
    173 
    174 
    175 /*
    176  * Function to convert the c2d format into an equivalent Android format
    177  *
    178  * @param: source buffer handle
    179  * @param: destination image
    180  *
    181  * @return: return status
    182  */
    183 int convert_yuv_c2d_to_yuv_android(private_handle_t *hnd,
    184                                    struct copybit_image_t const *rhs)
    185 {
    186     ALOGD("Enter %s", __FUNCTION__);
    187     if (!hnd || !rhs) {
    188         ALOGE("%s: invalid inputs hnd=%p rhs=%p", __FUNCTION__, hnd, rhs);
    189         return COPYBIT_FAILURE;
    190     }
    191 
    192     int ret = COPYBIT_SUCCESS;
    193     private_handle_t *dst_hnd = (private_handle_t *)rhs->handle;
    194 
    195     copyInfo info;
    196     info.width = rhs->w;
    197     info.height = rhs->h;
    198     info.src_stride = ALIGN(info.width, 32);
    199     info.dst_stride = ALIGN(info.width, 16);
    200     switch(rhs->format) {
    201         case HAL_PIXEL_FORMAT_YCbCr_420_SP:
    202         case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
    203             info.src_plane1_offset = info.src_stride*info.height;
    204             info.dst_plane1_offset = info.dst_stride*info.height;
    205         } break;
    206         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: {
    207             // Chroma is 2K aligned for the NV12 encodeable format.
    208             info.src_plane1_offset = ALIGN(info.src_stride*info.height, 2048);
    209             info.dst_plane1_offset = ALIGN(info.dst_stride*info.height, 2048);
    210         } break;
    211         default:
    212             ALOGE("%s: unsupported format (format=0x%x)", __FUNCTION__,
    213                  rhs->format);
    214             return COPYBIT_FAILURE;
    215     }
    216 
    217     ret = copy_source_to_destination((uintptr_t) hnd->base, (uintptr_t) dst_hnd->base, info);
    218     return ret;
    219 }
    220 
    221 /*
    222  * Function to convert the Android format into an equivalent C2D format
    223  *
    224  * @param: source buffer handle
    225  * @param: destination image
    226  *
    227  * @return: return status
    228  */
    229 int convert_yuv_android_to_yuv_c2d(private_handle_t *hnd,
    230                                    struct copybit_image_t const *rhs)
    231 {
    232     if (!hnd || !rhs) {
    233         ALOGE("%s: invalid inputs hnd=%p rhs=%p", __FUNCTION__, hnd, rhs);
    234         return COPYBIT_FAILURE;
    235     }
    236 
    237     int ret = COPYBIT_SUCCESS;
    238     private_handle_t *dst_hnd = (private_handle_t *)rhs->handle;
    239 
    240     copyInfo info;
    241     info.width = rhs->w;
    242     info.height = rhs->h;
    243     info.src_stride = ALIGN(hnd->width, 16);
    244     info.dst_stride = ALIGN(info.width, 32);
    245     switch(rhs->format) {
    246         case HAL_PIXEL_FORMAT_YCbCr_420_SP:
    247         case HAL_PIXEL_FORMAT_YCrCb_420_SP: {
    248             info.src_plane1_offset = info.src_stride*info.height;
    249             info.dst_plane1_offset = info.dst_stride*info.height;
    250         } break;
    251         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: {
    252             // Chroma is 2K aligned for the NV12 encodeable format.
    253             info.src_plane1_offset = ALIGN(info.src_stride*info.height, 2048);
    254             info.dst_plane1_offset = ALIGN(info.dst_stride*info.height, 2048);
    255         } break;
    256         default:
    257             ALOGE("%s: unsupported format (format=0x%x)", __FUNCTION__,
    258                  rhs->format);
    259             return -1;
    260     }
    261 
    262     ret = copy_source_to_destination((uintptr_t) hnd->base, (uintptr_t) dst_hnd->base, info);
    263     return ret;
    264 }
    265