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