blob: ef0ff675a5409d86f0c364243d6a1ec3fcee26c2 [file] [log] [blame]
Jayant Chowdhary249e1f22018-09-24 15:07:45 -07001/*
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#include <gtest/gtest.h>
18#include <media/NdkImageReader.h>
19#include <media/NdkImage.h>
Jayant Chowdhary32b4f492018-11-14 18:38:21 -080020#include <mediautils/AImageReaderUtils.h>
Jayant Chowdhary249e1f22018-09-24 15:07:45 -070021#include <gui/IGraphicBufferProducer.h>
22#include <gui/bufferqueue/1.0/H2BGraphicBufferProducer.h>
23#include <NdkImageReaderPriv.h>
24#include <vndk/hardware_buffer.h>
25#include <memory>
26
27namespace android {
28
29using hardware::graphics::bufferqueue::V1_0::utils::H2BGraphicBufferProducer;
Jayant Chowdhary32b4f492018-11-14 18:38:21 -080030using aimg::AImageReader_getHGBPFromHandle;
31
Jayant Chowdhary249e1f22018-09-24 15:07:45 -070032typedef IGraphicBufferProducer::QueueBufferInput QueueBufferInput;
33typedef IGraphicBufferProducer::QueueBufferOutput QueueBufferOutput;
34
35static constexpr uint64_t kImageBufferUsage =
36 AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
37static constexpr int kImageWidth = 640;
38static constexpr int kImageHeight = 480;
39static constexpr int kImageFormat = AIMAGE_FORMAT_RGBA_8888;
40static constexpr int kMaxImages = 1;
41
42static constexpr int64_t kQueueBufferInputTimeStamp = 1384888611;
43static constexpr bool kQueueBufferInputIsAutoTimeStamp = false;
44static constexpr android_dataspace kQueueBufferInputDataspace = HAL_DATASPACE_UNKNOWN;
45static const Rect kQueueBufferInputRect = Rect(kImageWidth, kImageHeight);
46static constexpr int kQueueBufferInputScalingMode = 0;
47static constexpr int kQueueBufferInputTransform = 0;
48static const sp<Fence> kQueueBufferInputFence = Fence::NO_FENCE;
49
50static constexpr int kOnImageAvailableWaitUs = 100 * 1000;
51
52class AImageReaderWindowHandleTest : public ::testing::Test {
53 public:
54 void SetUp() override {
55 AImageReader_newWithUsage(kImageWidth, kImageHeight, kImageFormat,
56 kImageBufferUsage , kMaxImages, &imageReader_);
57 media_status_t ret = AMEDIA_ERROR_UNKNOWN;
58 ASSERT_NE(imageReader_, nullptr);
59 ret = AImageReader_setImageListener(imageReader_,
60 &imageReaderAvailableCb_);
61 ASSERT_EQ(ret, AMEDIA_OK);
62 ret = AImageReader_setBufferRemovedListener(imageReader_,
63 &imageReaderDetachedCb_);
64 ASSERT_EQ(ret, AMEDIA_OK);
65 }
66 void TearDown() override {
67 if (imageReader_) {
68 AImageReader_delete(imageReader_);
69 }
70 }
71
72 void HandleImageAvailable() {
73 AImage *outImage = nullptr;
74 media_status_t ret = AMEDIA_OK;
75 auto imageDeleter = [](AImage *img) { AImage_delete(img); };
76 std::unique_ptr<AImage, decltype(imageDeleter)> img(nullptr, imageDeleter);
77
78 // Test that the image can be acquired.
79 ret = AImageReader_acquireNextImage(imageReader_, &outImage);
80 ASSERT_EQ(ret, AMEDIA_OK);
81 img.reset(outImage);
82 ASSERT_NE(img, nullptr);
83
84 // Test that we can get a handle to the image's hardware buffer and a
85 // native handle to it.
86 AHardwareBuffer *hardwareBuffer = nullptr;
87 ret = AImage_getHardwareBuffer(img.get(), &hardwareBuffer);
88 ASSERT_EQ(ret, AMEDIA_OK);
89 ASSERT_NE(hardwareBuffer, nullptr);
90 const native_handle_t *nh = AHardwareBuffer_getNativeHandle(hardwareBuffer);
91 ASSERT_NE(nh, nullptr);
92 std::unique_lock<std::mutex> lock(imageAvailableMutex_);
93 imageAvailable_ = true;
94 imageCondVar_.notify_one();
95 }
96
97 static void onImageAvailable(void *context, AImageReader *reader) {
98 (void)reader;
99 AImageReaderWindowHandleTest *thisContext =
100 reinterpret_cast<AImageReaderWindowHandleTest *>(context);
101 thisContext->HandleImageAvailable();
102 }
103
104 static void onBufferRemoved(void *, AImageReader *, AHardwareBuffer *) {
105 }
106
107 AImageReader *imageReader_ = nullptr;
108 AImageReader_ImageListener imageReaderAvailableCb_{this, onImageAvailable};
109 AImageReader_BufferRemovedListener imageReaderDetachedCb_{this, onBufferRemoved};
110 std::mutex imageAvailableMutex_;
111 std::condition_variable imageCondVar_;
112 bool imageAvailable_ = false;
113};
114
115static void fillRGBA8Buffer(uint8_t* buf, int w, int h, int stride) {
116 const size_t PIXEL_SIZE = 4;
117 for (int x = 0; x < w; x++) {
118 for (int y = 0; y < h; y++) {
119 off_t offset = (y * stride + x) * PIXEL_SIZE;
120 for (int c = 0; c < 4; c++) {
121 int parityX = (x / (1 << (c+2))) & 1;
122 int parityY = (y / (1 << (c+2))) & 1;
123 buf[offset + c] = (parityX ^ parityY) ? 231 : 35;
124 }
125 }
126 }
127}
128
129TEST_F(AImageReaderWindowHandleTest, CreateWindowNativeHandle) {
130 // Check that we can create a native_handle_t corresponding to the
131 // AImageReader.
132 native_handle_t *nh = nullptr;
133 AImageReader_getWindowNativeHandle(imageReader_, &nh);
134 ASSERT_NE(nh, nullptr);
135
136 // Check that there are only ints in the handle.
137 ASSERT_EQ(nh->numFds, 0);
138 ASSERT_NE(nh->numInts, 0);
139
140 // Check that the HGBP can be retrieved from the handle.
141 sp<HGraphicBufferProducer> hgbp = AImageReader_getHGBPFromHandle(nh);
142 ASSERT_NE(hgbp, nullptr);
143 sp<IGraphicBufferProducer> igbp = new H2BGraphicBufferProducer(hgbp);
144 int dequeuedSlot = -1;
145 sp<Fence> dequeuedFence;
146 IGraphicBufferProducer::QueueBufferOutput output;
147 ASSERT_EQ(OK, igbp->connect(nullptr, NATIVE_WINDOW_API_CPU, false, &output));
148
149 // Test that we can dequeue a buffer.
150 ASSERT_EQ(OK,
151 ~IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION &
152 (igbp->dequeueBuffer(&dequeuedSlot, &dequeuedFence,
153 kImageWidth, kImageHeight,
154 kImageFormat, kImageBufferUsage,
155 nullptr, nullptr)));
156 EXPECT_LE(0, dequeuedSlot);
157 EXPECT_GT(BufferQueue::NUM_BUFFER_SLOTS, dequeuedSlot);
158
159 sp<GraphicBuffer> dequeuedBuffer;
160 igbp->requestBuffer(dequeuedSlot, &dequeuedBuffer);
161 uint8_t* img = nullptr;
162 ASSERT_EQ(NO_ERROR, dequeuedBuffer->lock(kImageBufferUsage, (void**)(&img)));
163
164 // Write in some dummy image data.
165 fillRGBA8Buffer(img, dequeuedBuffer->getWidth(), dequeuedBuffer->getHeight(),
166 dequeuedBuffer->getStride());
167 ASSERT_EQ(NO_ERROR, dequeuedBuffer->unlock());
168 QueueBufferInput queueBufferInput(kQueueBufferInputTimeStamp,
169 kQueueBufferInputIsAutoTimeStamp,
170 kQueueBufferInputDataspace,
171 kQueueBufferInputRect,
172 kQueueBufferInputScalingMode,
173 kQueueBufferInputTransform,
174 kQueueBufferInputFence);
175 QueueBufferOutput queueBufferOutput;
176 ASSERT_EQ(OK, igbp->queueBuffer(dequeuedSlot, queueBufferInput,
177 &queueBufferOutput));
178 // wait until the onImageAvailable callback is called, or timeout completes.
179 std::unique_lock<std::mutex> lock(imageAvailableMutex_);
180 imageCondVar_.wait_for(lock, std::chrono::microseconds(kOnImageAvailableWaitUs),
181 [this]{ return this->imageAvailable_;});
182 EXPECT_TRUE(imageAvailable_) << "Timed out waiting for image data to be handled!\n";
183}
184
185} // namespace android