• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GrallocConsumer(const Context * rsc,Allocation * a,uint32_t numAlloc)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 
~GrallocConsumer()65 GrallocConsumer::~GrallocConsumer() {
66     AImageReader_delete(mImgReader);
67     delete[] mAlloc;
68     delete[] mAcquiredBuffer;
69     delete[] isIdxUsed;
70 }
71 
onFrameAvailable(void * obj,AImageReader * reader)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 
getNativeWindow()83 ANativeWindow* GrallocConsumer::getNativeWindow() {
84     return mNativeWindow;
85 }
86 
lockNextBuffer(uint32_t idx)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, &timestamp);
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 
unlockBuffer(uint32_t idx)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 
getNextAvailableIdx(Allocation * a)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 
releaseIdx(uint32_t idx)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 
isActive()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