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