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