Home | History | Annotate | Download | only in ndk
      1 /*
      2  * Copyright (C) 2016 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 #include <inttypes.h>
     18 
     19 //#define LOG_NDEBUG 0
     20 #define LOG_TAG "NdkImage"
     21 
     22 #include "NdkImagePriv.h"
     23 #include "NdkImageReaderPriv.h"
     24 
     25 #include <android_media_Utils.h>
     26 #include <android_runtime/android_hardware_HardwareBuffer.h>
     27 #include <utils/Log.h>
     28 #include "hardware/camera3.h"
     29 
     30 using namespace android;
     31 
     32 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
     33 
     34 AImage::AImage(AImageReader* reader, int32_t format, uint64_t usage, BufferItem* buffer,
     35         int64_t timestamp, int32_t width, int32_t height, int32_t numPlanes) :
     36         mReader(reader), mFormat(format), mUsage(usage), mBuffer(buffer), mLockedBuffer(nullptr),
     37         mTimestamp(timestamp), mWidth(width), mHeight(height), mNumPlanes(numPlanes) {
     38 }
     39 
     40 AImage::~AImage() {
     41     Mutex::Autolock _l(mLock);
     42     if (!mIsClosed) {
     43         LOG_ALWAYS_FATAL(
     44                 "Error: AImage %p is deleted before returning buffer to AImageReader!", this);
     45     }
     46 }
     47 
     48 bool
     49 AImage::isClosed() const {
     50     Mutex::Autolock _l(mLock);
     51     return mIsClosed;
     52 }
     53 
     54 void
     55 AImage::close(int releaseFenceFd) {
     56     Mutex::Autolock _l(mLock);
     57     if (mIsClosed) {
     58         return;
     59     }
     60     sp<AImageReader> reader = mReader.promote();
     61     if (reader != nullptr) {
     62         reader->releaseImageLocked(this, releaseFenceFd);
     63     } else if (mBuffer != nullptr) {
     64         LOG_ALWAYS_FATAL("%s: parent AImageReader closed without releasing image %p",
     65                 __FUNCTION__, this);
     66     }
     67 
     68     // Should have been set to nullptr in releaseImageLocked
     69     // Set to nullptr here for extra safety only
     70     mBuffer = nullptr;
     71     mLockedBuffer = nullptr;
     72     mIsClosed = true;
     73 }
     74 
     75 void
     76 AImage::free() {
     77     if (!isClosed()) {
     78         ALOGE("Cannot free AImage before close!");
     79         return;
     80     }
     81     delete this;
     82 }
     83 
     84 void
     85 AImage::lockReader() const {
     86     sp<AImageReader> reader = mReader.promote();
     87     if (reader == nullptr) {
     88         // Reader has been closed
     89         return;
     90     }
     91     reader->mLock.lock();
     92 }
     93 
     94 void
     95 AImage::unlockReader() const {
     96     sp<AImageReader> reader = mReader.promote();
     97     if (reader == nullptr) {
     98         // Reader has been closed
     99         return;
    100     }
    101     reader->mLock.unlock();
    102 }
    103 
    104 media_status_t
    105 AImage::getWidth(int32_t* width) const {
    106     if (width == nullptr) {
    107         return AMEDIA_ERROR_INVALID_PARAMETER;
    108     }
    109     *width = -1;
    110     if (isClosed()) {
    111         ALOGE("%s: image %p has been closed!", __FUNCTION__, this);
    112         return AMEDIA_ERROR_INVALID_OBJECT;
    113     }
    114     *width = mWidth;
    115     return AMEDIA_OK;
    116 }
    117 
    118 media_status_t
    119 AImage::getHeight(int32_t* height) const {
    120     if (height == nullptr) {
    121         return AMEDIA_ERROR_INVALID_PARAMETER;
    122     }
    123     *height = -1;
    124     if (isClosed()) {
    125         ALOGE("%s: image %p has been closed!", __FUNCTION__, this);
    126         return AMEDIA_ERROR_INVALID_OBJECT;
    127     }
    128     *height = mHeight;
    129     return AMEDIA_OK;
    130 }
    131 
    132 media_status_t
    133 AImage::getFormat(int32_t* format) const {
    134     if (format == nullptr) {
    135         return AMEDIA_ERROR_INVALID_PARAMETER;
    136     }
    137     *format = -1;
    138     if (isClosed()) {
    139         ALOGE("%s: image %p has been closed!", __FUNCTION__, this);
    140         return AMEDIA_ERROR_INVALID_OBJECT;
    141     }
    142     *format = mFormat;
    143     return AMEDIA_OK;
    144 }
    145 
    146 media_status_t
    147 AImage::getNumPlanes(int32_t* numPlanes) const {
    148     if (numPlanes == nullptr) {
    149         return AMEDIA_ERROR_INVALID_PARAMETER;
    150     }
    151     *numPlanes = -1;
    152     if (isClosed()) {
    153         ALOGE("%s: image %p has been closed!", __FUNCTION__, this);
    154         return AMEDIA_ERROR_INVALID_OBJECT;
    155     }
    156     *numPlanes = mNumPlanes;
    157     return AMEDIA_OK;
    158 }
    159 
    160 media_status_t
    161 AImage::getTimestamp(int64_t* timestamp) const {
    162     if (timestamp == nullptr) {
    163         return AMEDIA_ERROR_INVALID_PARAMETER;
    164     }
    165     *timestamp = -1;
    166     if (isClosed()) {
    167         ALOGE("%s: image %p has been closed!", __FUNCTION__, this);
    168         return AMEDIA_ERROR_INVALID_OBJECT;
    169     }
    170     *timestamp = mTimestamp;
    171     return AMEDIA_OK;
    172 }
    173 
    174 media_status_t AImage::lockImage() {
    175     if (mBuffer == nullptr || mBuffer->mGraphicBuffer == nullptr) {
    176         LOG_ALWAYS_FATAL("%s: AImage %p has no buffer.", __FUNCTION__, this);
    177         return AMEDIA_ERROR_INVALID_OBJECT;
    178     }
    179 
    180     if ((mUsage & AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN) == 0) {
    181         ALOGE("%s: AImage %p does not have any software read usage bits set, usage=%" PRIu64 "",
    182               __FUNCTION__, this, mUsage);
    183         return AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE;
    184     }
    185 
    186     if (mLockedBuffer != nullptr) {
    187         // Return immediately if the image has already been locked.
    188         return AMEDIA_OK;
    189     }
    190 
    191     auto lockedBuffer = std::make_unique<CpuConsumer::LockedBuffer>();
    192 
    193     uint64_t grallocUsage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(mUsage);
    194 
    195     status_t ret =
    196             lockImageFromBuffer(mBuffer, grallocUsage, mBuffer->mFence->dup(), lockedBuffer.get());
    197     if (ret != OK) {
    198         ALOGE("%s: AImage %p failed to lock, error=%d", __FUNCTION__, this, ret);
    199         return AMEDIA_IMGREADER_CANNOT_LOCK_IMAGE;
    200     }
    201 
    202     ALOGV("%s: Successfully locked the image %p.", __FUNCTION__, this);
    203     mLockedBuffer = std::move(lockedBuffer);
    204 
    205     return AMEDIA_OK;
    206 }
    207 
    208 media_status_t AImage::unlockImageIfLocked(int* fenceFd) {
    209     if (fenceFd == nullptr) {
    210         LOG_ALWAYS_FATAL("%s: fenceFd cannot be null.", __FUNCTION__);
    211         return AMEDIA_ERROR_INVALID_PARAMETER;
    212     }
    213 
    214     if (mBuffer == nullptr || mBuffer->mGraphicBuffer == nullptr) {
    215         LOG_ALWAYS_FATAL("%s: AImage %p has no buffer.", __FUNCTION__, this);
    216         return AMEDIA_ERROR_INVALID_OBJECT;
    217     }
    218 
    219     if (mLockedBuffer == nullptr) {
    220         // This image hasn't been locked yet, no need to unlock.
    221         *fenceFd = -1;
    222         return AMEDIA_OK;
    223     }
    224 
    225     // No fence by default.
    226     int releaseFenceFd = -1;
    227     status_t res = mBuffer->mGraphicBuffer->unlockAsync(&releaseFenceFd);
    228     if (res != OK) {
    229         ALOGE("%s unlock buffer failed on iamge %p.", __FUNCTION__, this);
    230         *fenceFd = -1;
    231         return AMEDIA_IMGREADER_CANNOT_UNLOCK_IMAGE;
    232     }
    233 
    234     *fenceFd = releaseFenceFd;
    235     return AMEDIA_OK;
    236 }
    237 
    238 media_status_t
    239 AImage::getPlanePixelStride(int planeIdx, /*out*/int32_t* pixelStride) const {
    240     if (mLockedBuffer == nullptr) {
    241         ALOGE("%s: buffer not locked.", __FUNCTION__);
    242         return AMEDIA_IMGREADER_IMAGE_NOT_LOCKED;
    243     }
    244 
    245     if (planeIdx < 0 || planeIdx >= mNumPlanes) {
    246         ALOGE("Error: planeIdx %d out of bound [0,%d]",
    247                 planeIdx, mNumPlanes - 1);
    248         return AMEDIA_ERROR_INVALID_PARAMETER;
    249     }
    250     if (pixelStride == nullptr) {
    251         return AMEDIA_ERROR_INVALID_PARAMETER;
    252     }
    253     if (isClosed()) {
    254         ALOGE("%s: image %p has been closed!", __FUNCTION__, this);
    255         return AMEDIA_ERROR_INVALID_OBJECT;
    256     }
    257     int32_t fmt = mLockedBuffer->flexFormat;
    258     switch (fmt) {
    259         case HAL_PIXEL_FORMAT_YCbCr_420_888:
    260             *pixelStride = (planeIdx == 0) ? 1 : mLockedBuffer->chromaStep;
    261             return AMEDIA_OK;
    262         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
    263             *pixelStride = (planeIdx == 0) ? 1 : 2;
    264             return AMEDIA_OK;
    265         case HAL_PIXEL_FORMAT_Y8:
    266             *pixelStride = 1;
    267             return AMEDIA_OK;
    268         case HAL_PIXEL_FORMAT_YV12:
    269             *pixelStride = 1;
    270             return AMEDIA_OK;
    271         case HAL_PIXEL_FORMAT_Y16:
    272         case HAL_PIXEL_FORMAT_RAW16:
    273         case HAL_PIXEL_FORMAT_RGB_565:
    274             // Single plane 16bpp data.
    275             *pixelStride = 2;
    276             return AMEDIA_OK;
    277         case HAL_PIXEL_FORMAT_RGBA_8888:
    278         case HAL_PIXEL_FORMAT_RGBX_8888:
    279             *pixelStride = 4;
    280             return AMEDIA_OK;
    281         case HAL_PIXEL_FORMAT_RGB_888:
    282             // Single plane, 24bpp.
    283             *pixelStride = 3;
    284             return AMEDIA_OK;
    285         case HAL_PIXEL_FORMAT_BLOB:
    286         case HAL_PIXEL_FORMAT_RAW10:
    287         case HAL_PIXEL_FORMAT_RAW12:
    288         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
    289             // Blob is used for JPEG data, RAW10 and RAW12 is used for 10-bit and 12-bit raw data,
    290             // those are single plane data without pixel stride defined
    291             return AMEDIA_ERROR_UNSUPPORTED;
    292         default:
    293             ALOGE("Pixel format: 0x%x is unsupported", fmt);
    294             return AMEDIA_ERROR_UNSUPPORTED;
    295     }
    296 }
    297 
    298 media_status_t
    299 AImage::getPlaneRowStride(int planeIdx, /*out*/int32_t* rowStride) const {
    300     if (mLockedBuffer == nullptr) {
    301         ALOGE("%s: buffer not locked.", __FUNCTION__);
    302         return AMEDIA_IMGREADER_IMAGE_NOT_LOCKED;
    303     }
    304 
    305     if (planeIdx < 0 || planeIdx >= mNumPlanes) {
    306         ALOGE("Error: planeIdx %d out of bound [0,%d]",
    307                 planeIdx, mNumPlanes - 1);
    308         return AMEDIA_ERROR_INVALID_PARAMETER;
    309     }
    310     if (rowStride == nullptr) {
    311         return AMEDIA_ERROR_INVALID_PARAMETER;
    312     }
    313     if (isClosed()) {
    314         ALOGE("%s: image %p has been closed!", __FUNCTION__, this);
    315         return AMEDIA_ERROR_INVALID_OBJECT;
    316     }
    317     int32_t fmt = mLockedBuffer->flexFormat;
    318     switch (fmt) {
    319         case HAL_PIXEL_FORMAT_YCbCr_420_888:
    320             *rowStride = (planeIdx == 0) ? mLockedBuffer->stride
    321                                          : mLockedBuffer->chromaStride;
    322             return AMEDIA_OK;
    323         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
    324             *rowStride = mLockedBuffer->width;
    325             return AMEDIA_OK;
    326         case HAL_PIXEL_FORMAT_YV12:
    327             if (mLockedBuffer->stride % 16) {
    328                 ALOGE("Stride %d is not 16 pixel aligned!", mLockedBuffer->stride);
    329                 return AMEDIA_ERROR_UNKNOWN;
    330             }
    331             *rowStride = (planeIdx == 0) ? mLockedBuffer->stride
    332                                          : ALIGN(mLockedBuffer->stride / 2, 16);
    333             return AMEDIA_OK;
    334         case HAL_PIXEL_FORMAT_RAW10:
    335         case HAL_PIXEL_FORMAT_RAW12:
    336             // RAW10 and RAW12 are used for 10-bit and 12-bit raw data, they are single plane
    337             *rowStride = mLockedBuffer->stride;
    338             return AMEDIA_OK;
    339         case HAL_PIXEL_FORMAT_Y8:
    340             if (mLockedBuffer->stride % 16) {
    341                 ALOGE("Stride %d is not 16 pixel aligned!",
    342                       mLockedBuffer->stride);
    343                 return AMEDIA_ERROR_UNKNOWN;
    344             }
    345             *rowStride = mLockedBuffer->stride;
    346             return AMEDIA_OK;
    347         case HAL_PIXEL_FORMAT_Y16:
    348         case HAL_PIXEL_FORMAT_RAW16:
    349             // In native side, strides are specified in pixels, not in bytes.
    350             // Single plane 16bpp bayer data. even width/height,
    351             // row stride multiple of 16 pixels (32 bytes)
    352             if (mLockedBuffer->stride % 16) {
    353                 ALOGE("Stride %d is not 16 pixel aligned!",
    354                       mLockedBuffer->stride);
    355                 return AMEDIA_ERROR_UNKNOWN;
    356             }
    357             *rowStride = mLockedBuffer->stride * 2;
    358             return AMEDIA_OK;
    359         case HAL_PIXEL_FORMAT_RGB_565:
    360             *rowStride = mLockedBuffer->stride * 2;
    361             return AMEDIA_OK;
    362         case HAL_PIXEL_FORMAT_RGBA_8888:
    363         case HAL_PIXEL_FORMAT_RGBX_8888:
    364             *rowStride = mLockedBuffer->stride * 4;
    365             return AMEDIA_OK;
    366         case HAL_PIXEL_FORMAT_RGB_888:
    367             // Single plane, 24bpp.
    368             *rowStride = mLockedBuffer->stride * 3;
    369             return AMEDIA_OK;
    370         case HAL_PIXEL_FORMAT_BLOB:
    371         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
    372             // Blob is used for JPEG/Raw opaque data. It is single plane and has 0 row stride and
    373             // no row stride defined
    374             return AMEDIA_ERROR_UNSUPPORTED;
    375         default:
    376             ALOGE("%s Pixel format: 0x%x is unsupported", __FUNCTION__, fmt);
    377           return AMEDIA_ERROR_UNSUPPORTED;
    378     }
    379 }
    380 
    381 uint32_t
    382 AImage::getJpegSize() const {
    383     if (mLockedBuffer == nullptr) {
    384         LOG_ALWAYS_FATAL("Error: buffer is null");
    385     }
    386 
    387     uint32_t size = 0;
    388     uint32_t width = mLockedBuffer->width;
    389     uint8_t* jpegBuffer = mLockedBuffer->data;
    390 
    391     // First check for JPEG transport header at the end of the buffer
    392     uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob));
    393     struct camera3_jpeg_blob* blob = (struct camera3_jpeg_blob*)(header);
    394     if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) {
    395         size = blob->jpeg_size;
    396         ALOGV("%s: Jpeg size = %d", __FUNCTION__, size);
    397     }
    398 
    399     // failed to find size, default to whole buffer
    400     if (size == 0) {
    401         /*
    402          * This is a problem because not including the JPEG header
    403          * means that in certain rare situations a regular JPEG blob
    404          * will be misidentified as having a header, in which case
    405          * we will get a garbage size value.
    406          */
    407         ALOGW("%s: No JPEG header detected, defaulting to size=width=%d",
    408                 __FUNCTION__, width);
    409         size = width;
    410     }
    411 
    412     return size;
    413 }
    414 
    415 media_status_t
    416 AImage::getPlaneData(int planeIdx,/*out*/uint8_t** data, /*out*/int* dataLength) const {
    417     if (mLockedBuffer == nullptr) {
    418         ALOGE("%s: buffer not locked.", __FUNCTION__);
    419         return AMEDIA_IMGREADER_IMAGE_NOT_LOCKED;
    420     }
    421 
    422     if (planeIdx < 0 || planeIdx >= mNumPlanes) {
    423         ALOGE("Error: planeIdx %d out of bound [0,%d]",
    424                 planeIdx, mNumPlanes - 1);
    425         return AMEDIA_ERROR_INVALID_PARAMETER;
    426     }
    427     if (data == nullptr || dataLength == nullptr) {
    428         return AMEDIA_ERROR_INVALID_PARAMETER;
    429     }
    430     if (isClosed()) {
    431         ALOGE("%s: image %p has been closed!", __FUNCTION__, this);
    432         return AMEDIA_ERROR_INVALID_OBJECT;
    433     }
    434 
    435     uint32_t dataSize, ySize, cSize, cStride;
    436     uint8_t* cb = nullptr;
    437     uint8_t* cr = nullptr;
    438     uint8_t* pData = nullptr;
    439     int bytesPerPixel = 0;
    440     int32_t fmt = mLockedBuffer->flexFormat;
    441 
    442     switch (fmt) {
    443         case HAL_PIXEL_FORMAT_YCbCr_420_888:
    444             pData = (planeIdx == 0) ? mLockedBuffer->data
    445                                     : (planeIdx == 1) ? mLockedBuffer->dataCb
    446                                                       : mLockedBuffer->dataCr;
    447             // only map until last pixel
    448             if (planeIdx == 0) {
    449                 dataSize = mLockedBuffer->stride * (mLockedBuffer->height - 1) +
    450                            mLockedBuffer->width;
    451             } else {
    452                 dataSize =
    453                     mLockedBuffer->chromaStride *
    454                         (mLockedBuffer->height / 2 - 1) +
    455                     mLockedBuffer->chromaStep * (mLockedBuffer->width / 2 - 1) +
    456                     1;
    457             }
    458             break;
    459         // NV21
    460         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
    461             cr = mLockedBuffer->data +
    462                  (mLockedBuffer->stride * mLockedBuffer->height);
    463             cb = cr + 1;
    464             // only map until last pixel
    465             ySize = mLockedBuffer->width * (mLockedBuffer->height - 1) +
    466                     mLockedBuffer->width;
    467             cSize = mLockedBuffer->width * (mLockedBuffer->height / 2 - 1) +
    468                     mLockedBuffer->width - 1;
    469             pData = (planeIdx == 0) ? mLockedBuffer->data
    470                                     : (planeIdx == 1) ? cb : cr;
    471             dataSize = (planeIdx == 0) ? ySize : cSize;
    472             break;
    473         case HAL_PIXEL_FORMAT_YV12:
    474             // Y and C stride need to be 16 pixel aligned.
    475             if (mLockedBuffer->stride % 16) {
    476                 ALOGE("Stride %d is not 16 pixel aligned!",
    477                       mLockedBuffer->stride);
    478                 return AMEDIA_ERROR_UNKNOWN;
    479             }
    480 
    481             ySize = mLockedBuffer->stride * mLockedBuffer->height;
    482             cStride = ALIGN(mLockedBuffer->stride / 2, 16);
    483             cr = mLockedBuffer->data + ySize;
    484             cSize = cStride * mLockedBuffer->height / 2;
    485             cb = cr + cSize;
    486 
    487             pData = (planeIdx == 0) ? mLockedBuffer->data
    488                                     : (planeIdx == 1) ? cb : cr;
    489             dataSize = (planeIdx == 0) ? ySize : cSize;
    490             break;
    491         case HAL_PIXEL_FORMAT_Y8:
    492             // Single plane, 8bpp.
    493 
    494             pData = mLockedBuffer->data;
    495             dataSize = mLockedBuffer->stride * mLockedBuffer->height;
    496             break;
    497         case HAL_PIXEL_FORMAT_Y16:
    498             bytesPerPixel = 2;
    499 
    500             pData = mLockedBuffer->data;
    501             dataSize =
    502                 mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel;
    503             break;
    504         case HAL_PIXEL_FORMAT_BLOB:
    505             // Used for JPEG data, height must be 1, width == size, single plane.
    506             if (mLockedBuffer->height != 1) {
    507                 ALOGE("Jpeg should have height value one but got %d",
    508                       mLockedBuffer->height);
    509                 return AMEDIA_ERROR_UNKNOWN;
    510             }
    511 
    512             pData = mLockedBuffer->data;
    513             dataSize = getJpegSize();
    514             break;
    515         case HAL_PIXEL_FORMAT_RAW16:
    516             // Single plane 16bpp bayer data.
    517             bytesPerPixel = 2;
    518             pData = mLockedBuffer->data;
    519             dataSize =
    520                 mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel;
    521             break;
    522         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
    523             // Used for RAW_OPAQUE data, height must be 1, width == size, single plane.
    524             if (mLockedBuffer->height != 1) {
    525                 ALOGE("RAW_OPAQUE should have height value one but got %d",
    526                       mLockedBuffer->height);
    527                 return AMEDIA_ERROR_UNKNOWN;
    528             }
    529             pData = mLockedBuffer->data;
    530             dataSize = mLockedBuffer->width;
    531             break;
    532         case HAL_PIXEL_FORMAT_RAW10:
    533             // Single plane 10bpp bayer data.
    534             if (mLockedBuffer->width % 4) {
    535                 ALOGE("Width is not multiple of 4 %d", mLockedBuffer->width);
    536                 return AMEDIA_ERROR_UNKNOWN;
    537             }
    538             if (mLockedBuffer->height % 2) {
    539                 ALOGE("Height is not multiple of 2 %d", mLockedBuffer->height);
    540                 return AMEDIA_ERROR_UNKNOWN;
    541             }
    542             if (mLockedBuffer->stride < (mLockedBuffer->width * 10 / 8)) {
    543                 ALOGE("stride (%d) should be at least %d",
    544                         mLockedBuffer->stride, mLockedBuffer->width * 10 / 8);
    545                 return AMEDIA_ERROR_UNKNOWN;
    546             }
    547             pData = mLockedBuffer->data;
    548             dataSize = mLockedBuffer->stride * mLockedBuffer->height;
    549             break;
    550         case HAL_PIXEL_FORMAT_RAW12:
    551             // Single plane 10bpp bayer data.
    552             if (mLockedBuffer->width % 4) {
    553                 ALOGE("Width is not multiple of 4 %d", mLockedBuffer->width);
    554                 return AMEDIA_ERROR_UNKNOWN;
    555             }
    556             if (mLockedBuffer->height % 2) {
    557                 ALOGE("Height is not multiple of 2 %d", mLockedBuffer->height);
    558                 return AMEDIA_ERROR_UNKNOWN;
    559             }
    560             if (mLockedBuffer->stride < (mLockedBuffer->width * 12 / 8)) {
    561                 ALOGE("stride (%d) should be at least %d",
    562                         mLockedBuffer->stride, mLockedBuffer->width * 12 / 8);
    563                 return AMEDIA_ERROR_UNKNOWN;
    564             }
    565             pData = mLockedBuffer->data;
    566             dataSize = mLockedBuffer->stride * mLockedBuffer->height;
    567             break;
    568         case HAL_PIXEL_FORMAT_RGBA_8888:
    569         case HAL_PIXEL_FORMAT_RGBX_8888:
    570             // Single plane, 32bpp.
    571             bytesPerPixel = 4;
    572             pData = mLockedBuffer->data;
    573             dataSize =
    574                 mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel;
    575             break;
    576         case HAL_PIXEL_FORMAT_RGB_565:
    577             // Single plane, 16bpp.
    578             bytesPerPixel = 2;
    579             pData = mLockedBuffer->data;
    580             dataSize =
    581                 mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel;
    582             break;
    583         case HAL_PIXEL_FORMAT_RGB_888:
    584             // Single plane, 24bpp.
    585             bytesPerPixel = 3;
    586             pData = mLockedBuffer->data;
    587             dataSize = mLockedBuffer->stride * mLockedBuffer->height * bytesPerPixel;
    588             break;
    589         default:
    590             ALOGE("Pixel format: 0x%x is unsupported", fmt);
    591             return AMEDIA_ERROR_UNSUPPORTED;
    592     }
    593 
    594     *data = pData;
    595     *dataLength = dataSize;
    596     return AMEDIA_OK;
    597 }
    598 
    599 media_status_t
    600 AImage::getHardwareBuffer(/*out*/AHardwareBuffer** buffer) const {
    601     if (mBuffer == nullptr || mBuffer->mGraphicBuffer == nullptr) {
    602         ALOGE("%s: AImage %p has no buffer.", __FUNCTION__, this);
    603         return AMEDIA_ERROR_INVALID_OBJECT;
    604     }
    605 
    606     // TODO(jwcai) Someone from Android graphics team stating this should just be a static_cast.
    607     *buffer = reinterpret_cast<AHardwareBuffer*>(mBuffer->mGraphicBuffer.get());
    608     return AMEDIA_OK;
    609 }
    610 
    611 EXPORT
    612 void AImage_delete(AImage* image) {
    613     ALOGV("%s", __FUNCTION__);
    614     AImage_deleteAsync(image, -1);
    615     return;
    616 }
    617 
    618 EXPORT
    619 void AImage_deleteAsync(AImage* image, int releaseFenceFd) {
    620     ALOGV("%s", __FUNCTION__);
    621     if (image != nullptr) {
    622         image->lockReader();
    623         image->close(releaseFenceFd);
    624         image->unlockReader();
    625         if (!image->isClosed()) {
    626             LOG_ALWAYS_FATAL("Image close failed!");
    627         }
    628         image->free();
    629     }
    630     return;
    631 }
    632 
    633 EXPORT
    634 media_status_t AImage_getWidth(const AImage* image, /*out*/int32_t* width) {
    635     ALOGV("%s", __FUNCTION__);
    636     if (image == nullptr || width == nullptr) {
    637         ALOGE("%s: bad argument. image %p width %p",
    638                 __FUNCTION__, image, width);
    639         return AMEDIA_ERROR_INVALID_PARAMETER;
    640     }
    641     return image->getWidth(width);
    642 }
    643 
    644 EXPORT
    645 media_status_t AImage_getHeight(const AImage* image, /*out*/int32_t* height) {
    646     ALOGV("%s", __FUNCTION__);
    647     if (image == nullptr || height == nullptr) {
    648         ALOGE("%s: bad argument. image %p height %p",
    649                 __FUNCTION__, image, height);
    650         return AMEDIA_ERROR_INVALID_PARAMETER;
    651     }
    652     return image->getHeight(height);
    653 }
    654 
    655 EXPORT
    656 media_status_t AImage_getFormat(const AImage* image, /*out*/int32_t* format) {
    657     ALOGV("%s", __FUNCTION__);
    658     if (image == nullptr || format == nullptr) {
    659         ALOGE("%s: bad argument. image %p format %p",
    660                 __FUNCTION__, image, format);
    661         return AMEDIA_ERROR_INVALID_PARAMETER;
    662     }
    663     return image->getFormat(format);
    664 }
    665 
    666 EXPORT
    667 media_status_t AImage_getCropRect(const AImage* image, /*out*/AImageCropRect* rect) {
    668     ALOGV("%s", __FUNCTION__);
    669     if (image == nullptr || rect == nullptr) {
    670         ALOGE("%s: bad argument. image %p rect %p",
    671                 __FUNCTION__, image, rect);
    672         return AMEDIA_ERROR_INVALID_PARAMETER;
    673     }
    674     // For now AImage only supports camera outputs where cropRect is always full window
    675     int32_t width = -1;
    676     media_status_t ret = image->getWidth(&width);
    677     if (ret != AMEDIA_OK) {
    678         return ret;
    679     }
    680     int32_t height = -1;
    681     ret = image->getHeight(&height);
    682     if (ret != AMEDIA_OK) {
    683         return ret;
    684     }
    685     rect->left = 0;
    686     rect->top = 0;
    687     rect->right = width;
    688     rect->bottom = height;
    689     return AMEDIA_OK;
    690 }
    691 
    692 EXPORT
    693 media_status_t AImage_getTimestamp(const AImage* image, /*out*/int64_t* timestampNs) {
    694     ALOGV("%s", __FUNCTION__);
    695     if (image == nullptr || timestampNs == nullptr) {
    696         ALOGE("%s: bad argument. image %p timestampNs %p",
    697                 __FUNCTION__, image, timestampNs);
    698         return AMEDIA_ERROR_INVALID_PARAMETER;
    699     }
    700     return image->getTimestamp(timestampNs);
    701 }
    702 
    703 EXPORT
    704 media_status_t AImage_getNumberOfPlanes(const AImage* image, /*out*/int32_t* numPlanes) {
    705     ALOGV("%s", __FUNCTION__);
    706     if (image == nullptr || numPlanes == nullptr) {
    707         ALOGE("%s: bad argument. image %p numPlanes %p",
    708                 __FUNCTION__, image, numPlanes);
    709         return AMEDIA_ERROR_INVALID_PARAMETER;
    710     }
    711     return image->getNumPlanes(numPlanes);
    712 }
    713 
    714 EXPORT
    715 media_status_t AImage_getPlanePixelStride(
    716         const AImage* image, int planeIdx, /*out*/int32_t* pixelStride) {
    717     ALOGV("%s", __FUNCTION__);
    718     if (image == nullptr || pixelStride == nullptr) {
    719         ALOGE("%s: bad argument. image %p pixelStride %p",
    720                 __FUNCTION__, image, pixelStride);
    721         return AMEDIA_ERROR_INVALID_PARAMETER;
    722     }
    723     media_status_t ret = const_cast<AImage*>(image)->lockImage();
    724     if (ret != AMEDIA_OK) {
    725         ALOGE("%s: failed to lock buffer for CPU access. image %p, error=%d.",
    726               __FUNCTION__, image, ret);
    727         return ret;
    728     }
    729     return image->getPlanePixelStride(planeIdx, pixelStride);
    730 }
    731 
    732 EXPORT
    733 media_status_t AImage_getPlaneRowStride(
    734         const AImage* image, int planeIdx, /*out*/int32_t* rowStride) {
    735     ALOGV("%s", __FUNCTION__);
    736     if (image == nullptr || rowStride == nullptr) {
    737         ALOGE("%s: bad argument. image %p rowStride %p",
    738                 __FUNCTION__, image, rowStride);
    739         return AMEDIA_ERROR_INVALID_PARAMETER;
    740     }
    741     media_status_t ret = const_cast<AImage*>(image)->lockImage();
    742     if (ret != AMEDIA_OK) {
    743         ALOGE("%s: failed to lock buffer for CPU access. image %p, error=%d.",
    744               __FUNCTION__, image, ret);
    745         return ret;
    746     }
    747     return image->getPlaneRowStride(planeIdx, rowStride);
    748 }
    749 
    750 EXPORT
    751 media_status_t AImage_getPlaneData(
    752         const AImage* image, int planeIdx,
    753         /*out*/uint8_t** data, /*out*/int* dataLength) {
    754     ALOGV("%s", __FUNCTION__);
    755     if (image == nullptr || data == nullptr || dataLength == nullptr) {
    756         ALOGE("%s: bad argument. image %p data %p dataLength %p",
    757                 __FUNCTION__, image, data, dataLength);
    758         return AMEDIA_ERROR_INVALID_PARAMETER;
    759     }
    760     media_status_t ret = const_cast<AImage*>(image)->lockImage();
    761     if (ret != AMEDIA_OK) {
    762         ALOGE("%s: failed to lock buffer for CPU access. image %p, error=%d.",
    763               __FUNCTION__, image, ret);
    764         return ret;
    765     }
    766     return image->getPlaneData(planeIdx, data, dataLength);
    767 }
    768 
    769 EXPORT
    770 media_status_t AImage_getHardwareBuffer(
    771     const AImage* image, /*out*/AHardwareBuffer** buffer) {
    772     ALOGV("%s", __FUNCTION__);
    773 
    774     if (image == nullptr || buffer == nullptr) {
    775         ALOGE("%s: bad argument. image %p buffer %p", __FUNCTION__, image, buffer);
    776         return AMEDIA_ERROR_INVALID_PARAMETER;
    777     }
    778     return image->getHardwareBuffer(buffer);
    779 }
    780