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