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