1 /*
2  * Copyright 2018 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 
18 #define LOG_TAG "ImageReaderTestHelpers"
19 
20 #include "ImageReaderTestHelpers.h"
21 
22 #include <android/log.h>
23 
24 #define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
25 #define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
26 #define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
27 
ImageReaderHelper(int32_t width,int32_t height,int32_t format,uint64_t usage,int32_t maxImages)28 ImageReaderHelper::ImageReaderHelper(int32_t width, int32_t height,
29                                      int32_t format, uint64_t usage,
30                                      int32_t maxImages)
31     : mWidth(width), mHeight(height), mFormat(format), mUsage(usage),
32       mMaxImages(maxImages) {}
33 
~ImageReaderHelper()34 ImageReaderHelper::~ImageReaderHelper() {
35   mAcquiredImage.reset();
36   if (mImgReaderAnw) {
37     AImageReader_delete(mImgReader);
38     // No need to call ANativeWindow_release on imageReaderAnw
39   }
40 }
41 
initImageReader()42 int ImageReaderHelper::initImageReader() {
43   if (mImgReader != nullptr || mImgReaderAnw != nullptr) {
44     ALOGE("Cannot re-initalize image reader, mImgReader=%p, mImgReaderAnw=%p",
45           mImgReader, mImgReaderAnw);
46     return -1;
47   }
48 
49   int ret = AImageReader_newWithUsage(mWidth, mHeight, mFormat, mUsage,
50                                       mMaxImages, &mImgReader);
51   if (ret != AMEDIA_OK || mImgReader == nullptr) {
52     ALOGE("Failed to create new AImageReader, ret=%d, mImgReader=%p", ret,
53           mImgReader);
54     return -1;
55   }
56 
57   ret = AImageReader_setImageListener(mImgReader, &mReaderAvailableCb);
58   if (ret != AMEDIA_OK) {
59     ALOGE("Failed to set image available listener, ret=%d.", ret);
60     return ret;
61   }
62 
63   ret = AImageReader_getWindow(mImgReader, &mImgReaderAnw);
64   if (ret != AMEDIA_OK || mImgReaderAnw == nullptr) {
65     ALOGE("Failed to get ANativeWindow from AImageReader, ret=%d, "
66           "mImgReaderAnw=%p.",
67           ret, mImgReaderAnw);
68     return -1;
69   }
70 
71   return 0;
72 }
73 
getBufferFromCurrentImage(AHardwareBuffer ** outBuffer)74 int ImageReaderHelper::getBufferFromCurrentImage(AHardwareBuffer **outBuffer) {
75   std::lock_guard<std::mutex> lock(mMutex);
76 
77   int ret = 0;
78   if (mAvailableImages > 0) {
79     AImage *outImage = nullptr;
80 
81     mAvailableImages -= 1;
82 
83     ret = AImageReader_acquireNextImage(mImgReader, &outImage);
84     if (ret != AMEDIA_OK || outImage == nullptr) {
85       // When the BufferQueue is in async mode, it is still possible that
86       // AImageReader_acquireNextImage returns nothing after onFrameAvailable.
87       ALOGW("Failed to acquire image, ret=%d, outIamge=%p.", ret, outImage);
88     } else {
89       // Any exisitng in mAcquiredImage will be deleted and released
90       // automatically.
91       mAcquiredImage.reset(outImage);
92     }
93   }
94 
95   if (mAcquiredImage == nullptr) {
96     return -EAGAIN;
97   }
98 
99   // Note that AImage_getHardwareBuffer is not acquiring additional reference to
100   // the buffer, so we can return it here any times we want without worrying
101   // about releasing.
102   AHardwareBuffer *buffer = nullptr;
103   ret = AImage_getHardwareBuffer(mAcquiredImage.get(), &buffer);
104   if (ret != AMEDIA_OK || buffer == nullptr) {
105     ALOGE("Faild to get hardware buffer, ret=%d, outBuffer=%p.", ret, buffer);
106     return -ENOMEM;
107   }
108 
109   *outBuffer = buffer;
110   return 0;
111 }
112 
handleImageAvailable()113 void ImageReaderHelper::handleImageAvailable() {
114   std::lock_guard<std::mutex> lock(mMutex);
115 
116   mAvailableImages += 1;
117 }
118 
onImageAvailable(void * obj,AImageReader *)119 void ImageReaderHelper::onImageAvailable(void *obj, AImageReader *) {
120   ImageReaderHelper *thiz = reinterpret_cast<ImageReaderHelper *>(obj);
121   thiz->handleImageAvailable();
122 }
123