• 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 <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 
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 
40 // Can only be called by free() with mLock hold
~AImage()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
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     Mutex::Autolock _l(mLock);
82     delete this;
83 }
84 
85 void
lockReader() const86 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
unlockReader() const96 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
getWidth(int32_t * width) const106 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
getHeight(int32_t * height) const120 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
getFormat(int32_t * format) const134 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
getNumPlanes(int32_t * numPlanes) const148 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
getTimestamp(int64_t * timestamp) const162 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 
lockImage()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 
unlockImageIfLocked(int * fenceFd)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
getPlanePixelStride(int planeIdx,int32_t * pixelStride) const240 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
getPlaneRowStride(int planeIdx,int32_t * rowStride) const300 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
getJpegSize() const383 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
getPlaneData(int planeIdx,uint8_t ** data,int * dataLength) const417 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
getHardwareBuffer(AHardwareBuffer ** buffer) const601 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
AImage_delete(AImage * image)613 void AImage_delete(AImage* image) {
614     ALOGV("%s", __FUNCTION__);
615     AImage_deleteAsync(image, -1);
616     return;
617 }
618 
619 EXPORT
AImage_deleteAsync(AImage * image,int releaseFenceFd)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
AImage_getWidth(const AImage * image,int32_t * width)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
AImage_getHeight(const AImage * image,int32_t * height)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
AImage_getFormat(const AImage * image,int32_t * format)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
AImage_getCropRect(const AImage * image,AImageCropRect * rect)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
AImage_getTimestamp(const AImage * image,int64_t * timestampNs)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
AImage_getNumberOfPlanes(const AImage * image,int32_t * numPlanes)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
AImage_getPlanePixelStride(const AImage * image,int planeIdx,int32_t * pixelStride)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
AImage_getPlaneRowStride(const AImage * image,int planeIdx,int32_t * rowStride)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
AImage_getPlaneData(const AImage * image,int planeIdx,uint8_t ** data,int * dataLength)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
AImage_getHardwareBuffer(const AImage * image,AHardwareBuffer ** buffer)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