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