Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright 2011, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // #define LOG_NDEBUG 0
     18 #define LOG_TAG "AndroidMediaUtils"
     19 
     20 #include <hardware/camera3.h>
     21 #include <utils/Log.h>
     22 #include "android_media_Utils.h"
     23 
     24 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
     25 
     26 // Must be in sync with the value in HeicCompositeStream.cpp
     27 #define CAMERA3_HEIC_BLOB_ID 0x00FE
     28 
     29 namespace android {
     30 
     31 // -----------Utility functions used by ImageReader/Writer JNI-----------------
     32 
     33 enum {
     34     IMAGE_MAX_NUM_PLANES = 3,
     35 };
     36 
     37 bool usingRGBAToJpegOverride(int32_t imageFormat,
     38         int32_t containerFormat) {
     39     return containerFormat == HAL_PIXEL_FORMAT_BLOB && imageFormat == HAL_PIXEL_FORMAT_RGBA_8888;
     40 }
     41 
     42 int32_t applyFormatOverrides(int32_t imageFormat, int32_t containerFormat) {
     43     // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
     44     // write limitations for some platforms (b/17379185).
     45     if (usingRGBAToJpegOverride(imageFormat, containerFormat)) {
     46         return HAL_PIXEL_FORMAT_BLOB;
     47     }
     48     return containerFormat;
     49 }
     50 
     51 bool isFormatOpaque(int format) {
     52     // This is the only opaque format exposed in the ImageFormat public API.
     53     // Note that we do support CPU access for HAL_PIXEL_FORMAT_RAW_OPAQUE
     54     // (ImageFormat#RAW_PRIVATE) so it doesn't count as opaque here.
     55     return format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
     56 }
     57 
     58 bool isPossiblyYUV(PixelFormat format) {
     59     switch (static_cast<int>(format)) {
     60         case HAL_PIXEL_FORMAT_RGBA_8888:
     61         case HAL_PIXEL_FORMAT_RGBX_8888:
     62         case HAL_PIXEL_FORMAT_RGB_888:
     63         case HAL_PIXEL_FORMAT_RGB_565:
     64         case HAL_PIXEL_FORMAT_BGRA_8888:
     65         case HAL_PIXEL_FORMAT_Y8:
     66         case HAL_PIXEL_FORMAT_Y16:
     67         case HAL_PIXEL_FORMAT_RAW16:
     68         case HAL_PIXEL_FORMAT_RAW10:
     69         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
     70         case HAL_PIXEL_FORMAT_BLOB:
     71         case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
     72             return false;
     73 
     74         case HAL_PIXEL_FORMAT_YV12:
     75         case HAL_PIXEL_FORMAT_YCbCr_420_888:
     76         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
     77         default:
     78             return true;
     79     }
     80 }
     81 
     82 uint32_t Image_getBlobSize(LockedImage* buffer, bool usingRGBAOverride) {
     83     ALOGV("%s", __FUNCTION__);
     84     LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
     85     uint32_t size = 0;
     86     uint32_t width = buffer->width;
     87     uint8_t* blobBuffer = buffer->data;
     88 
     89     if (usingRGBAOverride) {
     90         width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4;
     91     }
     92 
     93     // First check for BLOB transport header at the end of the buffer
     94     uint8_t* header = blobBuffer + (width - sizeof(struct camera3_jpeg_blob));
     95     struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header);
     96     if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID ||
     97             blob->jpeg_blob_id == CAMERA3_HEIC_BLOB_ID) {
     98         size = blob->jpeg_size;
     99         ALOGV("%s: Jpeg/Heic size = %d", __FUNCTION__, size);
    100     }
    101 
    102     // failed to find size, default to whole buffer
    103     if (size == 0) {
    104         /*
    105          * This is a problem because not including the JPEG/BLOB header
    106          * means that in certain rare situations a regular JPEG/HEIC blob
    107          * will be mis-identified as having a header, in which case
    108          * we will get a garbage size value.
    109          */
    110         ALOGW("%s: No JPEG/HEIC header detected, defaulting to size=width=%d",
    111                 __FUNCTION__, width);
    112         size = width;
    113     }
    114 
    115     return size;
    116 }
    117 
    118 status_t getLockedImageInfo(LockedImage* buffer, int idx,
    119         int32_t containerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) {
    120     ALOGV("%s", __FUNCTION__);
    121     LOG_ALWAYS_FATAL_IF(buffer == NULL, "Input buffer is NULL!!!");
    122     LOG_ALWAYS_FATAL_IF(base == NULL, "base is NULL!!!");
    123     LOG_ALWAYS_FATAL_IF(size == NULL, "size is NULL!!!");
    124     LOG_ALWAYS_FATAL_IF(pixelStride == NULL, "pixelStride is NULL!!!");
    125     LOG_ALWAYS_FATAL_IF(rowStride == NULL, "rowStride is NULL!!!");
    126     LOG_ALWAYS_FATAL_IF((idx >= IMAGE_MAX_NUM_PLANES) || (idx < 0), "idx (%d) is illegal", idx);
    127 
    128     ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
    129 
    130     uint32_t dataSize, ySize, cSize, cStride;
    131     uint32_t pStride = 0, rStride = 0;
    132     uint8_t *cb, *cr;
    133     uint8_t *pData = NULL;
    134     int bytesPerPixel = 0;
    135 
    136     dataSize = ySize = cSize = cStride = 0;
    137     int32_t fmt = buffer->flexFormat;
    138 
    139     bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, containerFormat);
    140     fmt = applyFormatOverrides(fmt, containerFormat);
    141     switch (fmt) {
    142         case HAL_PIXEL_FORMAT_YCbCr_420_888:
    143             pData =
    144                 (idx == 0) ?
    145                     buffer->data :
    146                 (idx == 1) ?
    147                     buffer->dataCb :
    148                 buffer->dataCr;
    149             // only map until last pixel
    150             if (idx == 0) {
    151                 pStride = 1;
    152                 rStride = buffer->stride;
    153                 dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
    154             } else {
    155                 pStride = buffer->chromaStep;
    156                 rStride = buffer->chromaStride;
    157                 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
    158                         buffer->chromaStep * (buffer->width / 2 - 1) + 1;
    159             }
    160             break;
    161         // NV21
    162         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
    163             cr = buffer->data + (buffer->stride * buffer->height);
    164             cb = cr + 1;
    165             // only map until last pixel
    166             ySize = buffer->width * (buffer->height - 1) + buffer->width;
    167             cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
    168 
    169             pData =
    170                 (idx == 0) ?
    171                     buffer->data :
    172                 (idx == 1) ?
    173                     cb:
    174                 cr;
    175 
    176             dataSize = (idx == 0) ? ySize : cSize;
    177             pStride = (idx == 0) ? 1 : 2;
    178             rStride = buffer->width;
    179             break;
    180         case HAL_PIXEL_FORMAT_YV12:
    181             // Y and C stride need to be 16 pixel aligned.
    182             LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
    183                                 "Stride is not 16 pixel aligned %d", buffer->stride);
    184 
    185             ySize = buffer->stride * buffer->height;
    186             cStride = ALIGN(buffer->stride / 2, 16);
    187             cr = buffer->data + ySize;
    188             cSize = cStride * buffer->height / 2;
    189             cb = cr + cSize;
    190 
    191             pData =
    192                 (idx == 0) ?
    193                     buffer->data :
    194                 (idx == 1) ?
    195                     cb :
    196                 cr;
    197             dataSize = (idx == 0) ? ySize : cSize;
    198             pStride = 1;
    199             rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
    200             break;
    201         case HAL_PIXEL_FORMAT_Y8:
    202             // Single plane, 8bpp.
    203             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
    204 
    205             pData = buffer->data;
    206             dataSize = buffer->stride * buffer->height;
    207             pStride = 1;
    208             rStride = buffer->stride;
    209             break;
    210         case HAL_PIXEL_FORMAT_Y16:
    211             bytesPerPixel = 2;
    212             // Single plane, 16bpp, strides are specified in pixels, not in bytes
    213             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
    214 
    215             pData = buffer->data;
    216             dataSize = buffer->stride * buffer->height * bytesPerPixel;
    217             pStride = bytesPerPixel;
    218             rStride = buffer->stride * 2;
    219             break;
    220         case HAL_PIXEL_FORMAT_BLOB:
    221             // Used for JPEG data, height must be 1, width == size, single plane.
    222             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
    223             // When RGBA override is being used, buffer height will be equal to width
    224             if (usingRGBAOverride) {
    225                 LOG_ALWAYS_FATAL_IF(buffer->height != buffer->width,
    226                         "RGBA override BLOB format buffer should have height == width");
    227             } else {
    228                 LOG_ALWAYS_FATAL_IF(buffer->height != 1,
    229                         "BLOB format buffer should have height value 1");
    230             }
    231 
    232 
    233             pData = buffer->data;
    234             dataSize = Image_getBlobSize(buffer, usingRGBAOverride);
    235             pStride = 0;
    236             rStride = 0;
    237             break;
    238         case HAL_PIXEL_FORMAT_RAW16:
    239             // Single plane 16bpp bayer data.
    240             bytesPerPixel = 2;
    241             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
    242             pData = buffer->data;
    243             dataSize = buffer->stride * buffer->height * bytesPerPixel;
    244             pStride = bytesPerPixel;
    245             rStride = buffer->stride * 2;
    246             break;
    247         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
    248             // Used for RAW_OPAQUE data, height must be 1, width == size, single plane.
    249             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
    250             LOG_ALWAYS_FATAL_IF(buffer->height != 1,
    251                     "RAW_PRIVATE should has height value one but got %d", buffer->height);
    252             pData = buffer->data;
    253             dataSize = buffer->width;
    254             pStride = 0; // RAW OPAQUE doesn't have pixel stride
    255             rStride = 0; // RAW OPAQUE doesn't have row stride
    256             break;
    257         case HAL_PIXEL_FORMAT_RAW10:
    258             // Single plane 10bpp bayer data.
    259             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
    260             LOG_ALWAYS_FATAL_IF(buffer->width % 4,
    261                                 "Width is not multiple of 4 %d", buffer->width);
    262             LOG_ALWAYS_FATAL_IF(buffer->height % 2,
    263                                 "Height is not even %d", buffer->height);
    264             LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8),
    265                                 "stride (%d) should be at least %d",
    266                                 buffer->stride, buffer->width * 10 / 8);
    267             pData = buffer->data;
    268             dataSize = buffer->stride * buffer->height;
    269             pStride = 0;
    270             rStride = buffer->stride;
    271             break;
    272         case HAL_PIXEL_FORMAT_RAW12:
    273             // Single plane 10bpp bayer data.
    274             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
    275             LOG_ALWAYS_FATAL_IF(buffer->width % 4,
    276                                 "Width is not multiple of 4 %d", buffer->width);
    277             LOG_ALWAYS_FATAL_IF(buffer->height % 2,
    278                                 "Height is not even %d", buffer->height);
    279             LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8),
    280                                 "stride (%d) should be at least %d",
    281                                 buffer->stride, buffer->width * 12 / 8);
    282             pData = buffer->data;
    283             dataSize = buffer->stride * buffer->height;
    284             pStride = 0;
    285             rStride = buffer->stride;
    286             break;
    287         case HAL_PIXEL_FORMAT_RGBA_8888:
    288         case HAL_PIXEL_FORMAT_RGBX_8888:
    289             // Single plane, 32bpp.
    290             bytesPerPixel = 4;
    291             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
    292             pData = buffer->data;
    293             dataSize = buffer->stride * buffer->height * bytesPerPixel;
    294             pStride = bytesPerPixel;
    295             rStride = buffer->stride * 4;
    296             break;
    297         case HAL_PIXEL_FORMAT_RGB_565:
    298             // Single plane, 16bpp.
    299             bytesPerPixel = 2;
    300             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
    301             pData = buffer->data;
    302             dataSize = buffer->stride * buffer->height * bytesPerPixel;
    303             pStride = bytesPerPixel;
    304             rStride = buffer->stride * 2;
    305             break;
    306         case HAL_PIXEL_FORMAT_RGB_888:
    307             // Single plane, 24bpp.
    308             bytesPerPixel = 3;
    309             LOG_ALWAYS_FATAL_IF(idx != 0, "Wrong index: %d", idx);
    310             pData = buffer->data;
    311             dataSize = buffer->stride * buffer->height * bytesPerPixel;
    312             pStride = bytesPerPixel;
    313             rStride = buffer->stride * 3;
    314             break;
    315         default:
    316             return BAD_VALUE;
    317     }
    318 
    319     *base = pData;
    320     *size = dataSize;
    321     *pixelStride = pStride;
    322     *rowStride = rStride;
    323 
    324     return OK;
    325 }
    326 
    327 status_t lockImageFromBuffer(sp<GraphicBuffer> buffer, uint32_t inUsage,
    328         const Rect& rect, int fenceFd, LockedImage* outputImage) {
    329     ALOGV("%s: Try to lock the GraphicBuffer", __FUNCTION__);
    330 
    331     if (buffer == nullptr || outputImage == nullptr) {
    332         ALOGE("Input BufferItem or output LockedImage is NULL!");
    333         return BAD_VALUE;
    334     }
    335     if (isFormatOpaque(buffer->getPixelFormat())) {
    336         ALOGE("Opaque format buffer is not lockable!");
    337         return BAD_VALUE;
    338     }
    339 
    340     void* pData = NULL;
    341     android_ycbcr ycbcr = android_ycbcr();
    342     status_t res;
    343     int format = buffer->getPixelFormat();
    344     int flexFormat = format;
    345     if (isPossiblyYUV(format)) {
    346         res = buffer->lockAsyncYCbCr(inUsage, rect, &ycbcr, fenceFd);
    347         pData = ycbcr.y;
    348         flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888;
    349     }
    350 
    351     // lockAsyncYCbCr for YUV is unsuccessful.
    352     if (pData == NULL) {
    353         res = buffer->lockAsync(inUsage, rect, &pData, fenceFd);
    354         if (res != OK) {
    355             ALOGE("Lock buffer failed!");
    356             return res;
    357         }
    358     }
    359 
    360     outputImage->data = reinterpret_cast<uint8_t*>(pData);
    361     outputImage->width = buffer->getWidth();
    362     outputImage->height = buffer->getHeight();
    363     outputImage->format = format;
    364     outputImage->flexFormat = flexFormat;
    365     outputImage->stride =
    366             (ycbcr.y != NULL) ? static_cast<uint32_t>(ycbcr.ystride) : buffer->getStride();
    367 
    368     outputImage->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb);
    369     outputImage->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr);
    370     outputImage->chromaStride = static_cast<uint32_t>(ycbcr.cstride);
    371     outputImage->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step);
    372     ALOGV("%s: Successfully locked the image from the GraphicBuffer", __FUNCTION__);
    373     // Crop, transform, scalingMode, timestamp, and frameNumber should be set by caller,
    374     // and cann't be set them here.
    375     return OK;
    376 }
    377 
    378 status_t lockImageFromBuffer(BufferItem* bufferItem, uint32_t inUsage,
    379         int fenceFd, LockedImage* outputImage) {
    380     ALOGV("%s: Try to lock the BufferItem", __FUNCTION__);
    381     if (bufferItem == nullptr || outputImage == nullptr) {
    382         ALOGE("Input BufferItem or output LockedImage is NULL!");
    383         return BAD_VALUE;
    384     }
    385 
    386     status_t res = lockImageFromBuffer(bufferItem->mGraphicBuffer, inUsage, bufferItem->mCrop,
    387             fenceFd, outputImage);
    388     if (res != OK) {
    389         ALOGE("%s: lock graphic buffer failed", __FUNCTION__);
    390         return res;
    391     }
    392 
    393     outputImage->crop        = bufferItem->mCrop;
    394     outputImage->transform   = bufferItem->mTransform;
    395     outputImage->scalingMode = bufferItem->mScalingMode;
    396     outputImage->timestamp   = bufferItem->mTimestamp;
    397     outputImage->dataSpace   = bufferItem->mDataSpace;
    398     outputImage->frameNumber = bufferItem->mFrameNumber;
    399     ALOGV("%s: Successfully locked the image from the BufferItem", __FUNCTION__);
    400     return OK;
    401 }
    402 
    403 int getBufferWidth(BufferItem* buffer) {
    404     if (buffer == NULL) return -1;
    405 
    406     if (!buffer->mCrop.isEmpty()) {
    407         return buffer->mCrop.getWidth();
    408     }
    409 
    410     ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
    411     return buffer->mGraphicBuffer->getWidth();
    412 }
    413 
    414 int getBufferHeight(BufferItem* buffer) {
    415     if (buffer == NULL) return -1;
    416 
    417     if (!buffer->mCrop.isEmpty()) {
    418         return buffer->mCrop.getHeight();
    419     }
    420 
    421     ALOGV("%s: buffer->mGraphicBuffer: %p", __FUNCTION__, buffer->mGraphicBuffer.get());
    422     return buffer->mGraphicBuffer->getHeight();
    423 }
    424 
    425 }  // namespace android
    426 
    427