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