1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "rsAllocation.h" 18 #include "rsContext.h" 19 #include "rsGrallocConsumer.h" 20 #include "rs_hal.h" 21 22 namespace android { 23 namespace renderscript { 24 25 GrallocConsumer::GrallocConsumer (const Context *rsc, Allocation *a, uint32_t numAlloc) 26 { 27 mCtx = rsc; 28 mAlloc = new Allocation *[numAlloc]; 29 mAcquiredBuffer = new AcquiredBuffer[numAlloc]; 30 isIdxUsed = new bool[numAlloc]; 31 32 mAlloc[0] = a; 33 isIdxUsed[0] = true; 34 mNumAlloc = numAlloc; 35 36 uint32_t width = a->mHal.drvState.lod[0].dimX; 37 uint32_t height = a->mHal.drvState.lod[0].dimY; 38 if (height < 1) height = 1; 39 40 int32_t format = AIMAGE_FORMAT_RGBA_8888; 41 if (a->mHal.state.yuv) { 42 format = AIMAGE_FORMAT_YUV_420_888; 43 } 44 45 media_status_t ret = AImageReader_new( 46 width, height, format, 47 mNumAlloc, &mImgReader); 48 if (ret != AMEDIA_OK || mImgReader == nullptr) { 49 ALOGE("Error creating image reader. ret %d", ret); 50 } 51 52 ret = AImageReader_getWindow(mImgReader, &mNativeWindow); 53 if (ret != AMEDIA_OK || mNativeWindow == nullptr) { 54 ALOGE("Error creating native window. ret %d", ret); 55 } 56 57 mReaderCb = {this, GrallocConsumer::onFrameAvailable}; 58 ret = AImageReader_setImageListener(mImgReader, &mReaderCb); 59 60 for (uint32_t i = 1; i < numAlloc; i++) { 61 isIdxUsed[i] = false; 62 } 63 } 64 65 GrallocConsumer::~GrallocConsumer() { 66 AImageReader_delete(mImgReader); 67 delete[] mAlloc; 68 delete[] mAcquiredBuffer; 69 delete[] isIdxUsed; 70 } 71 72 void GrallocConsumer::onFrameAvailable(void* obj, AImageReader* reader) { 73 GrallocConsumer* consumer = (GrallocConsumer *) obj; 74 for (uint32_t i = 0; i < consumer->mNumAlloc; i++) { 75 if (consumer->mAlloc[i] != nullptr) { 76 intptr_t ip = (intptr_t)(consumer->mAlloc[i]); 77 consumer->mCtx->sendMessageToClient(&ip, 78 RS_MESSAGE_TO_CLIENT_NEW_BUFFER, 0, sizeof(ip), true); 79 } 80 } 81 } 82 83 ANativeWindow* GrallocConsumer::getNativeWindow() { 84 return mNativeWindow; 85 } 86 87 media_status_t GrallocConsumer::lockNextBuffer(uint32_t idx) { 88 media_status_t ret; 89 90 if (idx >= mNumAlloc) { 91 ALOGE("Invalid buffer index: %d", idx); 92 return AMEDIA_ERROR_INVALID_PARAMETER; 93 } 94 95 if (mAcquiredBuffer[idx].mImg != nullptr) { 96 ret = unlockBuffer(idx); 97 if (ret != AMEDIA_OK) { 98 return ret; 99 } 100 } 101 102 ret = AImageReader_acquireNextImage(mImgReader, &(mAcquiredBuffer[idx].mImg)); 103 if (ret != AMEDIA_OK || mAcquiredBuffer[idx].mImg == nullptr) { 104 ALOGE("%s: acquire image from reader %p failed! ret: %d, img %p", 105 __FUNCTION__, mImgReader, ret, mAcquiredBuffer[idx].mImg); 106 return ret; 107 } 108 109 AImage *img = mAcquiredBuffer[idx].mImg; 110 int32_t format = -1; 111 ret = AImage_getFormat(img, &format); 112 if (ret != AMEDIA_OK || format == -1) { 113 ALOGE("%s: get format for image %p failed! ret: %d, format %d", 114 __FUNCTION__, img, ret, format); 115 return ret; 116 } 117 118 if (format != AIMAGE_FORMAT_YUV_420_888 && format != AIMAGE_FORMAT_RGBA_8888) { 119 ALOGE("Format %d not supported", format); 120 return AMEDIA_ERROR_INVALID_OBJECT; 121 } 122 123 uint8_t *data = nullptr; 124 int dataLength = 0; 125 ret = AImage_getPlaneData(img, 0, &data, &dataLength); 126 if (ret != AMEDIA_OK || data == nullptr || dataLength <= 0) { 127 ALOGE("%s: get data for image %p failed! ret: %d, data %p, len %d", 128 __FUNCTION__, img, ret, data, dataLength); 129 return ret; 130 } 131 132 int64_t timestamp = -1; 133 ret = AImage_getTimestamp(img, ×tamp); 134 if (ret != AMEDIA_OK || timestamp == -1) { 135 ALOGE("%s: get timestamp for image %p failed! ret: %d", 136 __FUNCTION__, img, ret); 137 return ret; 138 } 139 140 int32_t rowstride = -1; 141 ret = AImage_getPlaneRowStride(img, 0, &rowstride); 142 if (ret != AMEDIA_OK || rowstride == -1) { 143 ALOGE("%s: get row stride for image %p failed! ret: %d, rowstride %d", 144 __FUNCTION__, img, ret, rowstride); 145 return ret; 146 } 147 148 AHardwareBuffer *hardwareBuffer = nullptr; 149 ret = AImage_getHardwareBuffer(img, &hardwareBuffer); 150 if (ret != AMEDIA_OK || hardwareBuffer == nullptr) { 151 ALOGE("%s: get hardware buffer for image %p failed! ret: %d", 152 __FUNCTION__, img, ret); 153 return ret; 154 } 155 156 mAcquiredBuffer[idx].mBufferPointer = data; 157 158 mAlloc[idx]->mHal.drvState.lod[0].mallocPtr = data; 159 mAlloc[idx]->mHal.drvState.lod[0].stride = rowstride; 160 mAlloc[idx]->mHal.state.nativeBuffer = hardwareBuffer; 161 mAlloc[idx]->mHal.state.timestamp = timestamp; 162 163 if (format == AIMAGE_FORMAT_YUV_420_888) { 164 const int yWidth = mAlloc[idx]->mHal.drvState.lod[0].dimX; 165 const int yHeight = mAlloc[idx]->mHal.drvState.lod[0].dimY; 166 167 const int cWidth = yWidth / 2; 168 const int cHeight = yHeight / 2; 169 170 uint8_t *uData = nullptr; 171 int uDataLength = 0; 172 ret = AImage_getPlaneData(img, 1, &uData, &uDataLength); 173 if (ret != AMEDIA_OK || uData == nullptr || uDataLength <= 0) { 174 ALOGE("%s: get U data for image %p failed! ret: %d, data %p, len %d", 175 __FUNCTION__, img, ret, uData, uDataLength); 176 return ret; 177 } 178 179 uint8_t *vData = nullptr; 180 int vDataLength = 0; 181 ret = AImage_getPlaneData(img, 2, &vData, &vDataLength); 182 if (ret != AMEDIA_OK || vData == nullptr || vDataLength <= 0) { 183 ALOGE("%s: get V data for image %p failed! ret: %d, data %p, len %d", 184 __FUNCTION__, img, ret, vData, vDataLength); 185 return ret; 186 } 187 188 int32_t uRowStride = -1; 189 ret = AImage_getPlaneRowStride(img, 1, &uRowStride); 190 if (ret != AMEDIA_OK || uRowStride == -1) { 191 ALOGE("%s: get U row stride for image %p failed! ret: %d, uRowStride %d", 192 __FUNCTION__, img, ret, uRowStride); 193 return ret; 194 } 195 196 int32_t vRowStride = -1; 197 ret = AImage_getPlaneRowStride(img, 2, &vRowStride); 198 if (ret != AMEDIA_OK || vRowStride == -1) { 199 ALOGE("%s: get V row stride for image %p failed! ret: %d, vRowStride %d", 200 __FUNCTION__, img, ret, vRowStride); 201 return ret; 202 } 203 204 int32_t uPixStride = -1; 205 ret = AImage_getPlanePixelStride(img, 1, &uPixStride); 206 if (ret != AMEDIA_OK || uPixStride == -1) { 207 ALOGE("%s: get U pixel stride for image %p failed! ret: %d, uPixStride %d", 208 __FUNCTION__, img, ret, uPixStride); 209 return ret; 210 } 211 212 mAlloc[idx]->mHal.drvState.lod[1].dimX = cWidth; 213 mAlloc[idx]->mHal.drvState.lod[1].dimY = cHeight; 214 mAlloc[idx]->mHal.drvState.lod[2].dimX = cWidth; 215 mAlloc[idx]->mHal.drvState.lod[2].dimY = cHeight; 216 217 mAlloc[idx]->mHal.drvState.lod[1].mallocPtr = uData; 218 mAlloc[idx]->mHal.drvState.lod[2].mallocPtr = vData; 219 220 mAlloc[idx]->mHal.drvState.lod[1].stride = uRowStride; 221 mAlloc[idx]->mHal.drvState.lod[2].stride = vRowStride; 222 223 mAlloc[idx]->mHal.drvState.yuv.shift = 1; 224 mAlloc[idx]->mHal.drvState.yuv.step = uPixStride; 225 mAlloc[idx]->mHal.drvState.lodCount = 3; 226 } 227 228 return AMEDIA_OK; 229 } 230 231 media_status_t GrallocConsumer::unlockBuffer(uint32_t idx) { 232 media_status_t ret; 233 234 if (idx >= mNumAlloc) { 235 ALOGE("Invalid buffer index: %d", idx); 236 return AMEDIA_ERROR_INVALID_PARAMETER; 237 } 238 if (mAcquiredBuffer[idx].mImg == nullptr) { 239 return AMEDIA_OK; 240 } 241 242 AImage_delete(mAcquiredBuffer[idx].mImg); 243 mAcquiredBuffer[idx].mImg = nullptr; 244 return AMEDIA_OK; 245 } 246 247 uint32_t GrallocConsumer::getNextAvailableIdx(Allocation *a) { 248 for (uint32_t i = 0; i < mNumAlloc; i++) { 249 if (isIdxUsed[i] == false) { 250 mAlloc[i] = a; 251 isIdxUsed[i] = true; 252 return i; 253 } 254 } 255 return mNumAlloc; 256 } 257 258 bool GrallocConsumer::releaseIdx(uint32_t idx) { 259 if (idx >= mNumAlloc) { 260 ALOGE("Invalid buffer index: %d", idx); 261 return false; 262 } 263 if (isIdxUsed[idx] == false) { 264 ALOGV("Buffer index already released: %d", idx); 265 return true; 266 } 267 media_status_t ret; 268 ret = unlockBuffer(idx); 269 if (ret != OK) { 270 ALOGE("Unable to unlock graphic buffer"); 271 return false; 272 } 273 mAlloc[idx] = nullptr; 274 isIdxUsed[idx] = false; 275 return true; 276 } 277 278 bool GrallocConsumer::isActive() { 279 for (uint32_t i = 0; i < mNumAlloc; i++) { 280 if (isIdxUsed[i]) { 281 return true; 282 } 283 } 284 return false; 285 } 286 287 } // namespace renderscript 288 } // namespace android 289