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