xref: /aosp_15_r20/frameworks/av/media/ndk/NdkImage.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 }