1 /*
2 * Copyright (C) 2017 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 #define LOG_TAG "media_omx_hidl_video_enc_test"
18 #ifdef __LP64__
19 #define OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
20 #endif
21
22 #include <android-base/logging.h>
23
24 #include <android/hardware/graphics/bufferqueue/1.0/IGraphicBufferProducer.h>
25 #include <android/hardware/graphics/bufferqueue/1.0/IProducerListener.h>
26 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
27 #include <android/hardware/graphics/mapper/2.0/types.h>
28 #include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
29 #include <android/hardware/media/omx/1.0/IOmx.h>
30 #include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
31 #include <android/hardware/media/omx/1.0/IOmxNode.h>
32 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
33 #include <android/hardware/media/omx/1.0/types.h>
34 #include <android/hidl/allocator/1.0/IAllocator.h>
35 #include <android/hidl/memory/1.0/IMapper.h>
36 #include <android/hidl/memory/1.0/IMemory.h>
37 #include <gtest/gtest.h>
38 #include <hidl/GtestPrinter.h>
39
40 using ::android::hardware::graphics::bufferqueue::V1_0::IGraphicBufferProducer;
41 using ::android::hardware::graphics::bufferqueue::V1_0::IProducerListener;
42 using ::android::hardware::graphics::common::V1_0::BufferUsage;
43 using ::android::hardware::graphics::common::V1_0::PixelFormat;
44 using ::android::hardware::media::omx::V1_0::IGraphicBufferSource;
45 using ::android::hardware::media::omx::V1_0::IOmxBufferSource;
46 using ::android::hardware::media::omx::V1_0::IOmx;
47 using ::android::hardware::media::omx::V1_0::IOmxObserver;
48 using ::android::hardware::media::omx::V1_0::IOmxNode;
49 using ::android::hardware::media::omx::V1_0::Message;
50 using ::android::hardware::media::omx::V1_0::CodecBuffer;
51 using ::android::hardware::media::omx::V1_0::PortMode;
52 using ::android::hidl::allocator::V1_0::IAllocator;
53 using ::android::hidl::memory::V1_0::IMemory;
54 using ::android::hidl::memory::V1_0::IMapper;
55 using ::android::hardware::Return;
56 using ::android::hardware::Void;
57 using ::android::hardware::hidl_vec;
58 using ::android::hardware::hidl_string;
59 using ::android::sp;
60
61 #include <getopt.h>
62 #include <media/hardware/HardwareAPI.h>
63 #include <media_video_hidl_test_common.h>
64 #include <system/window.h>
65 #include <fstream>
66 #include <variant>
67
68 // Resource directory
69 std::string sResourceDir = "";
70
71 // video encoder test fixture class
72 class VideoEncHidlTest
73 : public ::testing::TestWithParam<std::tuple<std::string, std::string, std::string>> {
74 public:
getTestCaseInfo() const75 ::std::string getTestCaseInfo() const {
76 return ::std::string() + "Component: " + component_ + " | " + "Role: " + role_ + " | " +
77 "Instance: " + instance_ + " | " + "Res: " + sResourceDir;
78 }
79
SetUp()80 virtual void SetUp() override {
81 instance_ = std::get<0>(GetParam());
82 component_ = std::get<1>(GetParam());
83 role_ = std::get<2>(GetParam());
84 ASSERT_NE(sResourceDir.empty(), true);
85
86 disableTest = false;
87 android::hardware::media::omx::V1_0::Status status;
88 omx = IOmx::getService(instance_);
89 ASSERT_NE(omx, nullptr);
90 observer =
91 new CodecObserver([this](Message msg, const BufferInfo* buffer) {
92 handleMessage(msg, buffer);
93 });
94 ASSERT_NE(observer, nullptr);
95 if (component_.find("OMX.") != 0) disableTest = true;
96 EXPECT_TRUE(omx->allocateNode(component_, observer,
97 [&](android::hardware::media::omx::V1_0::Status _s,
98 sp<IOmxNode> const& _nl) {
99 status = _s;
100 this->omxNode = _nl;
101 })
102 .isOk());
103 if (status == android::hardware::media::omx::V1_0::Status::NAME_NOT_FOUND) {
104 disableTest = true;
105 std::cout << "[ WARN ] Test Disabled, component not present\n";
106 return;
107 }
108 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
109 ASSERT_NE(omxNode, nullptr);
110 ASSERT_NE(role_.empty(), true) << "Invalid Component Role";
111 struct StringToName {
112 const char* Name;
113 standardComp CompName;
114 };
115 const StringToName kStringToName[] = {
116 {"h263", h263}, {"avc", avc}, {"mpeg4", mpeg4},
117 {"hevc", hevc}, {"vp8", vp8}, {"vp9", vp9},
118 };
119 const size_t kNumStringToName =
120 sizeof(kStringToName) / sizeof(kStringToName[0]);
121 const char* pch;
122 char substring[OMX_MAX_STRINGNAME_SIZE];
123 strcpy(substring, role_.c_str());
124 pch = strchr(substring, '.');
125 ASSERT_NE(pch, nullptr);
126 compName = unknown_comp;
127 for (size_t i = 0; i < kNumStringToName; ++i) {
128 if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
129 compName = kStringToName[i].CompName;
130 break;
131 }
132 }
133 if (compName == unknown_comp) disableTest = true;
134 struct CompToCompression {
135 standardComp CompName;
136 OMX_VIDEO_CODINGTYPE eCompressionFormat;
137 };
138 static const CompToCompression kCompToCompression[] = {
139 {h263, OMX_VIDEO_CodingH263}, {avc, OMX_VIDEO_CodingAVC},
140 {mpeg4, OMX_VIDEO_CodingMPEG4}, {hevc, OMX_VIDEO_CodingHEVC},
141 {vp8, OMX_VIDEO_CodingVP8}, {vp9, OMX_VIDEO_CodingVP9},
142 };
143 static const size_t kNumCompToCompression =
144 sizeof(kCompToCompression) / sizeof(kCompToCompression[0]);
145 size_t i;
146 for (i = 0; i < kNumCompToCompression; ++i) {
147 if (kCompToCompression[i].CompName == compName) {
148 eCompressionFormat = kCompToCompression[i].eCompressionFormat;
149 break;
150 }
151 }
152 if (i == kNumCompToCompression) disableTest = true;
153 eosFlag = false;
154 prependSPSPPS = false;
155 timestampDevTest = false;
156 producer = nullptr;
157 source = nullptr;
158 isSecure = false;
159 size_t suffixLen = strlen(".secure");
160 if (component_.rfind(".secure") == component_.length() - suffixLen) {
161 isSecure = true;
162 }
163 if (isSecure) disableTest = true;
164 if (disableTest) std::cout << "[ WARN ] Test Disabled \n";
165 }
166
TearDown()167 virtual void TearDown() override {
168 if (omxNode != nullptr) {
169 // If you have encountered a fatal failure, it is possible that
170 // freeNode() will not go through. Instead of hanging the app.
171 // let it pass through and report errors
172 if (::testing::Test::HasFatalFailure()) return;
173 EXPECT_TRUE((omxNode->freeNode()).isOk());
174 omxNode = nullptr;
175 }
176 }
177
178 // callback function to process messages received by onMessages() from IL
179 // client.
handleMessage(Message msg,const BufferInfo * buffer)180 void handleMessage(Message msg, const BufferInfo* buffer) {
181 (void)buffer;
182
183 if (msg.type == Message::Type::FILL_BUFFER_DONE) {
184 if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
185 eosFlag = true;
186 }
187 if (msg.data.extendedBufferData.rangeLength != 0) {
188 // Test if current timestamp is among the list of queued
189 // timestamps
190 if (timestampDevTest && ((msg.data.extendedBufferData.flags &
191 OMX_BUFFERFLAG_CODECCONFIG) == 0)) {
192 bool tsHit = false;
193 android::List<uint64_t>::iterator it =
194 timestampUslist.begin();
195 while (it != timestampUslist.end()) {
196 if (*it == msg.data.extendedBufferData.timestampUs) {
197 timestampUslist.erase(it);
198 tsHit = true;
199 break;
200 }
201 it++;
202 }
203 if (tsHit == false) {
204 if (timestampUslist.empty() == false) {
205 EXPECT_EQ(tsHit, true)
206 << "TimeStamp not recognized";
207 } else {
208 std::cout << "[ INFO ] Received non-zero "
209 "output / TimeStamp not recognized \n";
210 }
211 }
212 }
213 #define WRITE_OUTPUT 0
214 #if WRITE_OUTPUT
215 static int count = 0;
216 FILE* ofp = nullptr;
217 if (count)
218 ofp = fopen("out.bin", "ab");
219 else
220 ofp = fopen("out.bin", "wb");
221 if (ofp != nullptr) {
222 fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
223 sizeof(char),
224 msg.data.extendedBufferData.rangeLength, ofp);
225 fclose(ofp);
226 count++;
227 }
228 #endif
229 }
230 }
231 }
232
233 enum standardComp {
234 h263,
235 avc,
236 mpeg4,
237 hevc,
238 vp8,
239 vp9,
240 unknown_comp,
241 };
242
243 std::string component_;
244 std::string role_;
245 std::string instance_;
246
247 sp<IOmx> omx;
248 sp<CodecObserver> observer;
249 sp<IOmxNode> omxNode;
250 standardComp compName;
251 OMX_VIDEO_CODINGTYPE eCompressionFormat;
252 bool disableTest;
253 bool eosFlag;
254 bool prependSPSPPS;
255 ::android::List<uint64_t> timestampUslist;
256 bool timestampDevTest;
257 bool isSecure;
258 sp<IGraphicBufferProducer> producer;
259 sp<IGraphicBufferSource> source;
260
261 protected:
description(const std::string & description)262 static void description(const std::string& description) {
263 RecordProperty("description", description);
264 }
265 };
266
267 // CodecProducerListener class
268 struct CodecProducerListener : public IProducerListener {
269 public:
CodecProducerListenerCodecProducerListener270 CodecProducerListener(int a, int b)
271 : freeBuffers(a), minUnDequeuedCount(b) {}
onBufferReleasedCodecProducerListener272 virtual ::android::hardware::Return<void> onBufferReleased() override {
273 android::Mutex::Autolock autoLock(bufferLock);
274 freeBuffers += 1;
275 return Void();
276 }
needsReleaseNotifyCodecProducerListener277 virtual ::android::hardware::Return<bool> needsReleaseNotify() override {
278 return true;
279 }
reduceCountCodecProducerListener280 void reduceCount() {
281 android::Mutex::Autolock autoLock(bufferLock);
282 freeBuffers -= 1;
283 EXPECT_GE(freeBuffers, minUnDequeuedCount);
284 }
285
286 size_t freeBuffers;
287 size_t minUnDequeuedCount;
288 android::Mutex bufferLock;
289 };
290
291 // Mock IOmxBufferSource class. GraphicBufferSource.cpp in libstagefright/omx/
292 // implements this class. Below class is introduced to test if callback
293 // functions are actually being called or not
294 struct MockBufferSource : public IOmxBufferSource {
295 public:
MockBufferSourceMockBufferSource296 MockBufferSource(sp<IOmxNode> node) {
297 callback = 0;
298 executing = false;
299 omxNode = node;
300 }
301 virtual Return<void> onOmxExecuting();
302 virtual Return<void> onOmxIdle();
303 virtual Return<void> onOmxLoaded();
304 virtual Return<void> onInputBufferAdded(uint32_t buffer);
305 virtual Return<void> onInputBufferEmptied(
306 uint32_t buffer, const ::android::hardware::hidl_handle& fence);
307
308 int callback;
309 bool executing;
310 sp<IOmxNode> omxNode;
311 android::Vector<BufferInfo> iBuffer, oBuffer;
312 };
313
onOmxExecuting()314 Return<void> MockBufferSource::onOmxExecuting() {
315 executing = true;
316 callback |= 0x1;
317 size_t index;
318 // Fetch a client owned input buffer and send an EOS
319 if ((index = getEmptyBufferID(&iBuffer)) < iBuffer.size()) {
320 android::hardware::media::omx::V1_0::Status status;
321 CodecBuffer t = iBuffer[index].omxBuffer;
322 t.type = CodecBuffer::Type::ANW_BUFFER;
323 native_handle_t* fenceNh = native_handle_create(0, 0);
324 EXPECT_NE(fenceNh, nullptr);
325 status = omxNode->emptyBuffer(iBuffer[index].id, t, OMX_BUFFERFLAG_EOS,
326 0, fenceNh);
327 native_handle_close(fenceNh);
328 native_handle_delete(fenceNh);
329 EXPECT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
330 iBuffer.editItemAt(index).owner = component;
331 }
332 return Void();
333 };
334
onOmxIdle()335 Return<void> MockBufferSource::onOmxIdle() {
336 callback |= 0x2;
337 executing = false;
338 return Void();
339 };
340
onOmxLoaded()341 Return<void> MockBufferSource::onOmxLoaded() {
342 callback |= 0x4;
343 return Void();
344 };
345
onInputBufferAdded(uint32_t buffer)346 Return<void> MockBufferSource::onInputBufferAdded(uint32_t buffer) {
347 (void)buffer;
348 EXPECT_EQ(executing, false);
349 callback |= 0x8;
350 return Void();
351 };
352
onInputBufferEmptied(uint32_t buffer,const::android::hardware::hidl_handle & fence)353 Return<void> MockBufferSource::onInputBufferEmptied(
354 uint32_t buffer, const ::android::hardware::hidl_handle& fence) {
355 (void)fence;
356 callback |= 0x10;
357 size_t i;
358 for (i = 0; i < iBuffer.size(); i++) {
359 if (iBuffer[i].id == buffer) {
360 iBuffer.editItemAt(i).owner = client;
361 break;
362 }
363 }
364 return Void();
365 };
366
367 // Variant of mappers
368 struct MapperV2 : public GrallocV2 {
369 sp<IMapper> mMapper;
MapperV2MapperV2370 MapperV2(sp<IMapper>&& mapper): mMapper{std::move(mapper)} {}
371 MapperV2() = default;
lockMapperV2372 android::hardware::Return<void> lock(
373 void* buffer,
374 Usage usage,
375 const Rect& rect,
376 const android::hardware::hidl_handle& handle,
377 Error* error,
378 void** data) {
379 return mMapper->lock(buffer, usage, rect, handle,
380 [error, data](Error e, void* d) {
381 *error = e;
382 *data = d;
383 });
384 }
385 };
386 struct MapperV3 : public GrallocV3 {
387 sp<IMapper> mMapper;
MapperV3MapperV3388 MapperV3(sp<IMapper>&& mapper): mMapper{std::move(mapper)} {}
389 MapperV3() = default;
lockMapperV3390 android::hardware::Return<void> lock(
391 void* buffer,
392 Usage usage,
393 const Rect& rect,
394 const android::hardware::hidl_handle& handle,
395 Error* error,
396 void** data) {
397 return mMapper->lock(buffer, usage, rect, handle,
398 [error, data](Error e, void* d, int32_t, int32_t) {
399 *error = e;
400 *data = d;
401 });
402 }
403 };
404 using MapperVar = std::variant<MapperV2, MapperV3>;
405 // Initializes the MapperVar by trying services of different versions.
initialize(MapperVar & mapperVar)406 bool initialize(MapperVar& mapperVar) {
407 sp<android::hardware::graphics::mapper::V3_0::IMapper> mapper3 =
408 android::hardware::graphics::mapper::V3_0::IMapper::getService();
409 if (mapper3) {
410 mapperVar.emplace<MapperV3>(std::move(mapper3));
411 return true;
412 }
413 sp<android::hardware::graphics::mapper::V2_0::IMapper> mapper2 =
414 android::hardware::graphics::mapper::V2_0::IMapper::getService();
415 if (mapper2) {
416 mapperVar.emplace<MapperV2>(std::move(mapper2));
417 return true;
418 }
419 return false;
420 }
421
422 // request VOP refresh
requestIDR(sp<IOmxNode> omxNode,OMX_U32 portIndex)423 void requestIDR(sp<IOmxNode> omxNode, OMX_U32 portIndex) {
424 android::hardware::media::omx::V1_0::Status status;
425 OMX_CONFIG_INTRAREFRESHVOPTYPE param;
426 param.IntraRefreshVOP = OMX_TRUE;
427 status = setPortConfig(omxNode, OMX_IndexConfigVideoIntraVOPRefresh,
428 portIndex, ¶m);
429 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
430 std::cout << "[ INFO ] unable to request IDR \n";
431 }
432
433 // modify bitrate
changeBitrate(sp<IOmxNode> omxNode,OMX_U32 portIndex,uint32_t nBitrate)434 void changeBitrate(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t nBitrate) {
435 android::hardware::media::omx::V1_0::Status status;
436 OMX_VIDEO_CONFIG_BITRATETYPE param;
437 param.nEncodeBitrate = nBitrate;
438 status =
439 setPortConfig(omxNode, OMX_IndexConfigVideoBitrate, portIndex, ¶m);
440 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
441 std::cout << "[ INFO ] unable to change Bitrate \n";
442 }
443
444 // modify framerate
changeFrameRate(sp<IOmxNode> omxNode,OMX_U32 portIndex,uint32_t xFramerate)445 Return<android::hardware::media::omx::V1_0::Status> changeFrameRate(
446 sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t xFramerate) {
447 android::hardware::media::omx::V1_0::Status status;
448 OMX_CONFIG_FRAMERATETYPE param;
449 param.xEncodeFramerate = xFramerate;
450 status = setPortConfig(omxNode, OMX_IndexConfigVideoFramerate, portIndex,
451 ¶m);
452 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
453 std::cout << "[ INFO ] unable to change Framerate \n";
454 return status;
455 }
456
457 // modify intra refresh interval
changeRefreshPeriod(sp<IOmxNode> omxNode,OMX_U32 portIndex,uint32_t nRefreshPeriod)458 void changeRefreshPeriod(sp<IOmxNode> omxNode, OMX_U32 portIndex,
459 uint32_t nRefreshPeriod) {
460 android::hardware::media::omx::V1_0::Status status;
461 OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE param;
462 param.nRefreshPeriod = nRefreshPeriod;
463 status = setPortConfig(omxNode,
464 (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh,
465 portIndex, ¶m);
466 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
467 std::cout << "[ INFO ] unable to change Refresh Period\n";
468 }
469
470 // set intra refresh interval
setRefreshPeriod(sp<IOmxNode> omxNode,OMX_U32 portIndex,uint32_t nRefreshPeriod)471 void setRefreshPeriod(sp<IOmxNode> omxNode, OMX_U32 portIndex,
472 uint32_t nRefreshPeriod) {
473 android::hardware::media::omx::V1_0::Status status;
474 OMX_VIDEO_PARAM_INTRAREFRESHTYPE param;
475 param.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
476 param.nCirMBs = 0;
477 if (nRefreshPeriod == 0)
478 param.nCirMBs = 0;
479 else {
480 OMX_PARAM_PORTDEFINITIONTYPE portDef;
481 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
482 &portDef);
483 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
484 param.nCirMBs =
485 ((portDef.format.video.nFrameWidth + 15) >>
486 4 * (portDef.format.video.nFrameHeight + 15) >> 4) /
487 nRefreshPeriod;
488 }
489 }
490 status = setPortParam(omxNode, OMX_IndexParamVideoIntraRefresh, portIndex,
491 ¶m);
492 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
493 std::cout << "[ INFO ] unable to set Refresh Period \n";
494 }
495
setLatency(sp<IOmxNode> omxNode,OMX_U32 portIndex,uint32_t latency)496 void setLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t latency) {
497 android::hardware::media::omx::V1_0::Status status;
498 OMX_PARAM_U32TYPE param;
499 param.nU32 = (OMX_U32)latency;
500 status = setPortConfig(omxNode, (OMX_INDEXTYPE)OMX_IndexConfigLatency,
501 portIndex, ¶m);
502 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
503 std::cout << "[ INFO ] unable to set latency\n";
504 }
505
getLatency(sp<IOmxNode> omxNode,OMX_U32 portIndex,uint32_t * latency)506 void getLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t* latency) {
507 android::hardware::media::omx::V1_0::Status status;
508 OMX_PARAM_U32TYPE param;
509 status = getPortConfig(omxNode, (OMX_INDEXTYPE)OMX_IndexConfigLatency,
510 portIndex, ¶m);
511 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
512 std::cout << "[ INFO ] unable to get latency\n";
513 else
514 *latency = param.nU32;
515 }
516
517 // Set Default port param.
setDefaultPortParam(sp<IOmxNode> omxNode,OMX_U32 portIndex,OMX_VIDEO_CODINGTYPE eCompressionFormat,OMX_U32 nFrameWidth,OMX_U32 nFrameHeight,OMX_U32 nBitrate,OMX_U32 xFramerate)518 void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
519 OMX_VIDEO_CODINGTYPE eCompressionFormat,
520 OMX_U32 nFrameWidth, OMX_U32 nFrameHeight,
521 OMX_U32 nBitrate, OMX_U32 xFramerate) {
522 android::hardware::media::omx::V1_0::Status status;
523 OMX_PARAM_PORTDEFINITIONTYPE portDef;
524 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
525 &portDef);
526 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
527 portDef.format.video.nFrameWidth = nFrameWidth;
528 portDef.format.video.nFrameHeight = nFrameHeight;
529 portDef.format.video.nBitrate = nBitrate;
530 portDef.format.video.xFramerate = xFramerate;
531 portDef.format.video.bFlagErrorConcealment = OMX_TRUE;
532 portDef.format.video.eCompressionFormat = eCompressionFormat;
533 portDef.format.video.eColorFormat = OMX_COLOR_FormatUnused;
534 status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
535 &portDef);
536 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
537
538 std::vector<int32_t> arrProfile;
539 std::vector<int32_t> arrLevel;
540 enumerateProfileAndLevel(omxNode, portIndex, &arrProfile, &arrLevel);
541 if (arrProfile.empty() == true || arrLevel.empty() == true)
542 ASSERT_TRUE(false);
543 int32_t profile = arrProfile[0];
544 int32_t level = arrLevel[0];
545
546 switch ((int)eCompressionFormat) {
547 case OMX_VIDEO_CodingAVC:
548 setupAVCPort(omxNode, portIndex,
549 static_cast<OMX_VIDEO_AVCPROFILETYPE>(profile),
550 static_cast<OMX_VIDEO_AVCLEVELTYPE>(level),
551 xFramerate);
552 break;
553 case OMX_VIDEO_CodingHEVC:
554 setupHEVCPort(omxNode, portIndex,
555 static_cast<OMX_VIDEO_HEVCPROFILETYPE>(profile),
556 static_cast<OMX_VIDEO_HEVCLEVELTYPE>(level));
557 break;
558 case OMX_VIDEO_CodingH263:
559 setupH263Port(omxNode, portIndex,
560 static_cast<OMX_VIDEO_H263PROFILETYPE>(profile),
561 static_cast<OMX_VIDEO_H263LEVELTYPE>(level),
562 xFramerate);
563 break;
564 case OMX_VIDEO_CodingMPEG4:
565 setupMPEG4Port(omxNode, portIndex,
566 static_cast<OMX_VIDEO_MPEG4PROFILETYPE>(profile),
567 static_cast<OMX_VIDEO_MPEG4LEVELTYPE>(level),
568 xFramerate);
569 break;
570 case OMX_VIDEO_CodingVP8:
571 setupVPXPort(omxNode, portIndex, xFramerate);
572 setupVP8Port(omxNode, portIndex,
573 static_cast<OMX_VIDEO_VP8PROFILETYPE>(profile),
574 static_cast<OMX_VIDEO_VP8LEVELTYPE>(level));
575 break;
576 case OMX_VIDEO_CodingVP9:
577 setupVPXPort(omxNode, portIndex, xFramerate);
578 setupVP9Port(omxNode, portIndex,
579 static_cast<OMX_VIDEO_VP9PROFILETYPE>(profile),
580 static_cast<OMX_VIDEO_VP9LEVELTYPE>(level));
581 break;
582 default:
583 break;
584 }
585 }
586
587 // LookUpTable of clips and metadata for component testing
GetURLForComponent(char * URL)588 void GetURLForComponent(char* URL) {
589 strcat(URL, "bbb_352x288_420p_30fps_32frames.yuv");
590 }
591
592 // blocking call to ensures application to Wait till all the inputs are consumed
waitOnInputConsumption(sp<IOmxNode> omxNode,sp<CodecObserver> observer,android::Vector<BufferInfo> * iBuffer,android::Vector<BufferInfo> * oBuffer,bool inputDataIsMeta=false,sp<CodecProducerListener> listener=nullptr)593 void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
594 android::Vector<BufferInfo>* iBuffer,
595 android::Vector<BufferInfo>* oBuffer,
596 bool inputDataIsMeta = false,
597 sp<CodecProducerListener> listener = nullptr) {
598 android::hardware::media::omx::V1_0::Status status;
599 Message msg;
600 int timeOut = TIMEOUT_COUNTER_Q;
601
602 while (timeOut--) {
603 size_t i = 0;
604 status =
605 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
606 ASSERT_EQ(status,
607 android::hardware::media::omx::V1_0::Status::TIMED_OUT);
608 // status == TIMED_OUT, it could be due to process time being large
609 // than DEFAULT_TIMEOUT or component needs output buffers to start
610 // processing.
611 if (inputDataIsMeta) {
612 if (listener->freeBuffers == iBuffer->size()) break;
613 } else {
614 for (; i < iBuffer->size(); i++) {
615 if ((*iBuffer)[i].owner != client) break;
616 }
617 if (i == iBuffer->size()) break;
618 }
619
620 // Dispatch an output buffer assuming outQueue.empty() is true
621 size_t index;
622 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
623 ASSERT_NO_FATAL_FAILURE(
624 dispatchOutputBuffer(omxNode, oBuffer, index));
625 timeOut = TIMEOUT_COUNTER_Q;
626 }
627 }
628 }
629
colorFormatConversion(BufferInfo * buffer,void * buff,PixelFormat format,std::ifstream & eleStream)630 int colorFormatConversion(BufferInfo* buffer, void* buff, PixelFormat format,
631 std::ifstream& eleStream) {
632 MapperVar mapperVar;
633 if (!initialize(mapperVar)) {
634 EXPECT_TRUE(false) << "failed to obtain mapper service";
635 return 1;
636 }
637
638 return std::visit([buffer, buff, format, &eleStream](auto&& mapper) -> int {
639 using Gralloc = std::remove_reference_t<decltype(mapper)>;
640 using Error = typename Gralloc::Error;
641 using Rect = typename Gralloc::Rect;
642 using Usage = typename Gralloc::Usage;
643 using YCbCrLayout = typename Gralloc::YCbCrLayout;
644
645 android::hardware::hidl_handle fence;
646 Rect rect;
647 YCbCrLayout ycbcrLayout;
648 Error error;
649 rect.left = 0;
650 rect.top = 0;
651 rect.width = buffer->omxBuffer.attr.anwBuffer.width;
652 rect.height = buffer->omxBuffer.attr.anwBuffer.height;
653
654 if (format == PixelFormat::YV12 || format == PixelFormat::YCRCB_420_SP ||
655 format == PixelFormat::YCBCR_420_888) {
656 mapper.mMapper->lockYCbCr(
657 buff,
658 static_cast<Usage>(
659 buffer->omxBuffer.attr.anwBuffer.usage),
660 rect,
661 fence,
662 [&](Error _e,
663 const YCbCrLayout& _n1) {
664 error = _e;
665 ycbcrLayout = _n1;
666 });
667 EXPECT_EQ(error, Error::NONE);
668 if (error != Error::NONE)
669 return 1;
670
671 int size = ((rect.width * rect.height * 3) >> 1);
672 char* img = new char[size];
673 if (img == nullptr) return 1;
674 eleStream.read(img, size);
675 if (eleStream.gcount() != size) {
676 delete[] img;
677 return 1;
678 }
679
680 char* imgTmp = img;
681 char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
682 for (size_t y = rect.height; y > 0; --y) {
683 memcpy(ipBuffer, imgTmp, rect.width);
684 ipBuffer += ycbcrLayout.yStride;
685 imgTmp += rect.width;
686 }
687
688 if (format == PixelFormat::YV12)
689 EXPECT_EQ(ycbcrLayout.chromaStep, 1U);
690 else if (format == PixelFormat::YCRCB_420_SP)
691 EXPECT_EQ(ycbcrLayout.chromaStep, 2U);
692
693 ipBuffer = static_cast<char*>(ycbcrLayout.cb);
694 for (size_t y = rect.height >> 1; y > 0; --y) {
695 for (int32_t x = 0; x < (rect.width >> 1); ++x) {
696 ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
697 }
698 ipBuffer += ycbcrLayout.cStride;
699 }
700 ipBuffer = static_cast<char*>(ycbcrLayout.cr);
701 for (size_t y = rect.height >> 1; y > 0; --y) {
702 for (int32_t x = 0; x < (rect.width >> 1); ++x) {
703 ipBuffer[ycbcrLayout.chromaStep * x] = *imgTmp++;
704 }
705 ipBuffer += ycbcrLayout.cStride;
706 }
707
708 delete[] img;
709
710 mapper.mMapper->unlock(buff,
711 [&](Error _e,
712 const android::hardware::hidl_handle& _n1) {
713 error = _e;
714 fence = _n1;
715 });
716 EXPECT_EQ(error, Error::NONE);
717 if (error != Error::NONE)
718 return 1;
719 } else {
720 void* data;
721 mapper.lock(
722 buff,
723 buffer->omxBuffer.attr.anwBuffer.usage,
724 rect,
725 fence,
726 &error,
727 &data);
728 EXPECT_EQ(error, Error::NONE);
729 if (error != Error::NONE)
730 return 1;
731
732 if (format == PixelFormat::BGRA_8888) {
733 char* ipBuffer = static_cast<char*>(data);
734 for (size_t y = rect.height; y > 0; --y) {
735 eleStream.read(ipBuffer, rect.width * 4);
736 if (eleStream.gcount() != rect.width * 4) return 1;
737 ipBuffer += buffer->omxBuffer.attr.anwBuffer.stride * 4;
738 }
739 } else {
740 EXPECT_TRUE(false) << "un expected pixel format";
741 return 1;
742 }
743
744 mapper.mMapper->unlock(
745 buff,
746 [&](Error _e, const android::hardware::hidl_handle& _n1) {
747 error = _e;
748 fence = _n1;
749 });
750 EXPECT_EQ(error, Error::NONE);
751 if (error != Error::NONE)
752 return 1;
753 }
754
755 return 0;
756 }, mapperVar);
757 }
758
fillGraphicBuffer(BufferInfo * buffer,PixelFormat format,std::ifstream & eleStream)759 int fillGraphicBuffer(BufferInfo* buffer, PixelFormat format,
760 std::ifstream& eleStream) {
761 MapperVar mapperVar;
762 if (!initialize(mapperVar)) {
763 EXPECT_TRUE(false) << "failed to obtain mapper service";
764 return 1;
765 }
766
767 return std::visit([buffer, format, &eleStream](auto&& mapper) -> int {
768 using Gralloc = std::remove_reference_t<decltype(mapper)>;
769 using Error = typename Gralloc::Error;
770
771 void* buff = nullptr;
772 Error error;
773 mapper.mMapper->importBuffer(
774 buffer->omxBuffer.nativeHandle,
775 [&](Error _e, void* _n1) {
776 error = _e;
777 buff = _n1;
778 });
779 EXPECT_EQ(error, Error::NONE);
780 if (error != Error::NONE)
781 return 1;
782
783 if (colorFormatConversion(buffer, buff, format, eleStream)) return 1;
784
785 error = mapper.mMapper->freeBuffer(buff);
786 EXPECT_EQ(error, Error::NONE);
787 if (error != Error::NONE)
788 return 1;
789
790 return 0;
791 }, mapperVar);
792 }
793
dispatchGraphicBuffer(sp<IOmxNode> omxNode,sp<IGraphicBufferProducer> producer,sp<CodecProducerListener> listener,android::Vector<BufferInfo> * buffArray,OMX_U32 portIndex,std::ifstream & eleStream,uint64_t timestamp)794 int dispatchGraphicBuffer(sp<IOmxNode> omxNode,
795 sp<IGraphicBufferProducer> producer,
796 sp<CodecProducerListener> listener,
797 android::Vector<BufferInfo>* buffArray,
798 OMX_U32 portIndex, std::ifstream& eleStream,
799 uint64_t timestamp) {
800 android::hardware::media::omx::V1_0::Status status;
801 OMX_PARAM_PORTDEFINITIONTYPE portDef;
802
803 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
804 &portDef);
805 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
806 if (status != ::android::hardware::media::omx::V1_0::Status::OK) return 1;
807
808 enum {
809 // A flag returned by dequeueBuffer when the client needs to call
810 // requestBuffer immediately thereafter.
811 BUFFER_NEEDS_REALLOCATION = 0x1,
812 // A flag returned by dequeueBuffer when all mirrored slots should be
813 // released by the client. This flag should always be processed first.
814 RELEASE_ALL_BUFFERS = 0x2,
815 };
816
817 int32_t slot;
818 int32_t result;
819 ::android::hardware::hidl_handle fence;
820 IGraphicBufferProducer::FrameEventHistoryDelta outTimestamps;
821 ::android::hardware::media::V1_0::AnwBuffer AnwBuffer;
822 PixelFormat format = PixelFormat::YCBCR_420_888;
823 producer->dequeueBuffer(
824 portDef.format.video.nFrameWidth, portDef.format.video.nFrameHeight,
825 format, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN,
826 true, [&](int32_t _s, int32_t const& _n1,
827 ::android::hardware::hidl_handle const& _n2,
828 IGraphicBufferProducer::FrameEventHistoryDelta const& _n3) {
829 result = _s;
830 slot = _n1;
831 fence = _n2;
832 outTimestamps = _n3;
833 });
834 if (result & BUFFER_NEEDS_REALLOCATION) {
835 producer->requestBuffer(
836 slot, [&](int32_t _s,
837 ::android::hardware::media::V1_0::AnwBuffer const& _n1) {
838 result = _s;
839 AnwBuffer = _n1;
840 });
841 EXPECT_EQ(result, 0);
842 if (result != 0) return 1;
843 size_t i;
844 for (i = 0; i < buffArray->size(); i++) {
845 if ((*buffArray)[i].slot == -1) {
846 buffArray->editItemAt(i).slot = slot;
847 buffArray->editItemAt(i).omxBuffer.nativeHandle =
848 AnwBuffer.nativeHandle;
849 buffArray->editItemAt(i).omxBuffer.attr.anwBuffer =
850 AnwBuffer.attr;
851 break;
852 }
853 }
854 EXPECT_NE(i, buffArray->size());
855 if (i == buffArray->size()) return 1;
856 }
857 EXPECT_EQ(result, 0);
858 if (result != 0) return 1;
859
860 // fill Buffer
861 BufferInfo buffer;
862 size_t i;
863 for (i = 0; i < buffArray->size(); i++) {
864 if ((*buffArray)[i].slot == slot) {
865 buffer = (*buffArray)[i];
866 break;
867 }
868 }
869 EXPECT_NE(i, buffArray->size());
870 if (i == buffArray->size()) return 1;
871 if (fillGraphicBuffer(&buffer, format, eleStream)) return 1;
872
873 // queue Buffer
874 IGraphicBufferProducer::QueueBufferOutput output;
875 IGraphicBufferProducer::QueueBufferInput input;
876 android::hardware::media::V1_0::Rect rect;
877 rect.left = 0;
878 rect.top = 0;
879 rect.right = buffer.omxBuffer.attr.anwBuffer.width;
880 rect.bottom = buffer.omxBuffer.attr.anwBuffer.height;
881 input.timestamp = timestamp;
882 input.isAutoTimestamp = false;
883 input.dataSpace =
884 android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN;
885 input.crop = rect;
886 input.scalingMode = 0;
887 input.transform = 0;
888 input.stickyTransform = 0;
889 input.fence = android::hardware::hidl_handle();
890 input.surfaceDamage =
891 android::hardware::hidl_vec<android::hardware::media::V1_0::Rect>{rect};
892 input.getFrameTimestamps = false;
893 producer->queueBuffer(
894 buffer.slot, input,
895 [&](int32_t _s, const IGraphicBufferProducer::QueueBufferOutput& _n1) {
896 result = _s;
897 output = _n1;
898 });
899 EXPECT_EQ(result, 0);
900 if (result != 0) return 1;
901
902 listener->reduceCount();
903
904 return 0;
905 }
906
fillByteBuffer(sp<IOmxNode> omxNode,char * ipBuffer,OMX_U32 portIndexInput,std::ifstream & eleStream)907 int fillByteBuffer(sp<IOmxNode> omxNode, char* ipBuffer, OMX_U32 portIndexInput,
908 std::ifstream& eleStream) {
909 android::hardware::media::omx::V1_0::Status status;
910 OMX_PARAM_PORTDEFINITIONTYPE portDef;
911 uint32_t i, j;
912
913 status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndexInput,
914 &portDef);
915 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
916
917 int size = ((portDef.format.video.nFrameWidth *
918 portDef.format.video.nFrameHeight * 3) >>
919 1);
920 char* img = new char[size];
921 if (img == nullptr) return 1;
922 eleStream.read(img, size);
923 if (eleStream.gcount() != size) {
924 delete[] img;
925 return 1;
926 }
927
928 char* Y = ipBuffer;
929 char* imgTmp = img;
930 for (j = 0; j < portDef.format.video.nFrameHeight; ++j) {
931 memcpy(Y, imgTmp, portDef.format.video.nFrameWidth);
932 Y += portDef.format.video.nStride;
933 imgTmp += portDef.format.video.nFrameWidth;
934 }
935
936 if (portDef.format.video.eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
937 char* Cb = ipBuffer + (portDef.format.video.nFrameHeight *
938 portDef.format.video.nStride);
939 char* Cr = Cb + 1;
940 for (j = 0; j<portDef.format.video.nFrameHeight>> 1; ++j) {
941 for (i = 0; i < (portDef.format.video.nFrameWidth >> 1); ++i) {
942 Cb[2 * i] = *imgTmp++;
943 }
944 Cb += portDef.format.video.nStride;
945 }
946 for (j = 0; j<portDef.format.video.nFrameHeight>> 1; ++j) {
947 for (i = 0; i < (portDef.format.video.nFrameWidth >> 1); ++i) {
948 Cr[2 * i] = *imgTmp++;
949 }
950 Cr += portDef.format.video.nStride;
951 }
952 } else if (portDef.format.video.eColorFormat ==
953 OMX_COLOR_FormatYUV420Planar) {
954 char* Cb = ipBuffer + (portDef.format.video.nFrameHeight *
955 portDef.format.video.nStride);
956 char* Cr = Cb + ((portDef.format.video.nFrameHeight *
957 portDef.format.video.nStride) >>
958 2);
959 for (j = 0; j<portDef.format.video.nFrameHeight>> 1; ++j) {
960 memcpy(Cb, imgTmp, (portDef.format.video.nFrameWidth >> 1));
961 Cb += (portDef.format.video.nStride >> 1);
962 imgTmp += (portDef.format.video.nFrameWidth >> 1);
963 }
964 for (j = 0; j<portDef.format.video.nFrameHeight>> 1; ++j) {
965 memcpy(Cr, imgTmp, (portDef.format.video.nFrameWidth >> 1));
966 Cr += (portDef.format.video.nStride >> 1);
967 imgTmp += (portDef.format.video.nFrameWidth >> 1);
968 }
969 }
970
971 delete[] img;
972 return 0;
973 }
974
975 // Encode N Frames
encodeNFrames(sp<IOmxNode> omxNode,sp<CodecObserver> observer,OMX_U32 portIndexInput,OMX_U32 portIndexOutput,android::Vector<BufferInfo> * iBuffer,android::Vector<BufferInfo> * oBuffer,uint32_t nFrames,uint32_t xFramerate,int bytesCount,std::ifstream & eleStream,::android::List<uint64_t> * timestampUslist=nullptr,bool signalEOS=true,bool inputDataIsMeta=false,sp<IGraphicBufferProducer> producer=nullptr,sp<CodecProducerListener> listener=nullptr)976 void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
977 OMX_U32 portIndexInput, OMX_U32 portIndexOutput,
978 android::Vector<BufferInfo>* iBuffer,
979 android::Vector<BufferInfo>* oBuffer, uint32_t nFrames,
980 uint32_t xFramerate, int bytesCount,
981 std::ifstream& eleStream,
982 ::android::List<uint64_t>* timestampUslist = nullptr,
983 bool signalEOS = true, bool inputDataIsMeta = false,
984 sp<IGraphicBufferProducer> producer = nullptr,
985 sp<CodecProducerListener> listener = nullptr) {
986 android::hardware::media::omx::V1_0::Status status;
987 Message msg;
988 uint64_t timestamp = 0;
989 uint32_t flags = 0;
990 int timeOut = TIMEOUT_COUNTER_Q;
991 bool iQueued, oQueued;
992
993 uint32_t ipCount = 0;
994 if (ipCount == 0) {
995 status = changeFrameRate(omxNode, portIndexOutput, (24U << 16));
996 if (status == ::android::hardware::media::omx::V1_0::Status::OK)
997 xFramerate = (24U << 16);
998 }
999 int32_t timestampIncr = (int)((float)1000000 / (xFramerate >> 16));
1000 if (inputDataIsMeta) timestampIncr *= 1000; // timestamp scale: Nano sec
1001
1002 while (1) {
1003 iQueued = oQueued = false;
1004 status =
1005 observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
1006 // Port Reconfiguration
1007 if (status == android::hardware::media::omx::V1_0::Status::OK) {
1008 ASSERT_EQ(msg.type, Message::Type::EVENT);
1009 if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
1010 ASSERT_EQ(msg.data.eventData.data1, portIndexOutput);
1011 ASSERT_EQ(msg.data.eventData.data2,
1012 OMX_IndexConfigAndroidIntraRefresh);
1013 } else if (msg.data.eventData.event == OMX_EventError) {
1014 ASSERT_TRUE(false) << "Received OMX_EventError, not sure why";
1015 } else if (msg.data.eventData.event == OMX_EventDataSpaceChanged) {
1016 // TODO: how am i supposed to respond now?
1017 std::cout << "[ INFO ] OMX_EventDataSpaceChanged \n";
1018 } else {
1019 ASSERT_TRUE(false);
1020 }
1021 }
1022
1023 if (nFrames == 0) break;
1024
1025 // Dispatch input buffer
1026 size_t index = 0;
1027 if (inputDataIsMeta) {
1028 if (listener->freeBuffers > listener->minUnDequeuedCount) {
1029 if (dispatchGraphicBuffer(omxNode, producer, listener, iBuffer,
1030 portIndexInput, eleStream,
1031 timestamp)) {
1032 if (::testing::Test::HasFailure())
1033 ASSERT_TRUE(false);
1034 else
1035 break;
1036 }
1037 timestamp += timestampIncr;
1038 nFrames--;
1039 ipCount++;
1040 iQueued = true;
1041 }
1042 } else {
1043 if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
1044 char* ipBuffer = static_cast<char*>(static_cast<void*>(
1045 (*iBuffer)[index].mMemory->getPointer()));
1046 ASSERT_LE(
1047 bytesCount,
1048 static_cast<int>((*iBuffer)[index].mMemory->getSize()));
1049 if (fillByteBuffer(omxNode, ipBuffer, portIndexInput,
1050 eleStream))
1051 break;
1052 flags = OMX_BUFFERFLAG_ENDOFFRAME;
1053 if (signalEOS && (nFrames == 1)) flags |= OMX_BUFFERFLAG_EOS;
1054 ASSERT_NO_FATAL_FAILURE(dispatchInputBuffer(
1055 omxNode, iBuffer, index, bytesCount, flags, timestamp));
1056 if (timestampUslist) timestampUslist->push_back(timestamp);
1057 timestamp += timestampIncr;
1058 nFrames--;
1059 ipCount++;
1060 iQueued = true;
1061 }
1062 }
1063 // Dispatch output buffer
1064 if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
1065 ASSERT_NO_FATAL_FAILURE(
1066 dispatchOutputBuffer(omxNode, oBuffer, index));
1067 oQueued = true;
1068 }
1069 // Reset Counters when either input or output buffer is dispatched
1070 if (iQueued || oQueued)
1071 timeOut = TIMEOUT_COUNTER_Q;
1072 else
1073 timeOut--;
1074 if (timeOut == 0) {
1075 ASSERT_TRUE(false) << "Wait on Input/Output is found indefinite";
1076 }
1077 // Runtime Param Configuration
1078 if (ipCount == 15) {
1079 changeBitrate(omxNode, portIndexOutput, 768000);
1080 requestIDR(omxNode, portIndexOutput);
1081 changeRefreshPeriod(omxNode, portIndexOutput, 15);
1082 }
1083 }
1084 }
1085
1086 // set component role
TEST_P(VideoEncHidlTest,SetRole)1087 TEST_P(VideoEncHidlTest, SetRole) {
1088 description("Test Set Component Role");
1089 if (disableTest) return;
1090 android::hardware::media::omx::V1_0::Status status;
1091 status = setRole(omxNode, role_);
1092 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1093 }
1094
1095 // port format enumeration
TEST_P(VideoEncHidlTest,EnumeratePortFormat)1096 TEST_P(VideoEncHidlTest, EnumeratePortFormat) {
1097 description("Test Component on Mandatory Port Parameters (Port Format)");
1098 if (disableTest) return;
1099 android::hardware::media::omx::V1_0::Status status;
1100 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1101 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatYUV420Planar;
1102 OMX_U32 xFramerate = (30U << 16);
1103 status = setRole(omxNode, role_);
1104 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1105 OMX_PORT_PARAM_TYPE params;
1106 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1107 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1108 ASSERT_EQ(params.nPorts, 2U);
1109 kPortIndexInput = params.nStartPortNumber;
1110 kPortIndexOutput = kPortIndexInput + 1;
1111 }
1112 status =
1113 setVideoPortFormat(omxNode, kPortIndexInput, OMX_VIDEO_CodingUnused,
1114 eColorFormat, xFramerate);
1115 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1116
1117 status = setVideoPortFormat(omxNode, kPortIndexOutput, eCompressionFormat,
1118 OMX_COLOR_FormatUnused, 0U);
1119 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1120 }
1121
1122 // Test IOmxBufferSource CallBacks
TEST_P(VideoEncHidlTest,BufferSourceCallBacks)1123 TEST_P(VideoEncHidlTest, BufferSourceCallBacks) {
1124 description("Test IOmxBufferSource CallBacks");
1125 if (disableTest) return;
1126 android::hardware::media::omx::V1_0::Status status;
1127 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1128 status = setRole(omxNode, role_);
1129 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1130 OMX_PORT_PARAM_TYPE params;
1131 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1132 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1133 ASSERT_EQ(params.nPorts, 2U);
1134 kPortIndexInput = params.nStartPortNumber;
1135 kPortIndexOutput = kPortIndexInput + 1;
1136 }
1137
1138 // Configure input port
1139 uint32_t nFrameWidth = 352;
1140 uint32_t nFrameHeight = 288;
1141 uint32_t xFramerate = (30U << 16);
1142 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatAndroidOpaque;
1143 setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
1144 xFramerate, eColorFormat);
1145
1146 sp<MockBufferSource> buffersource = new MockBufferSource(omxNode);
1147 ASSERT_NE(buffersource, nullptr);
1148 status = omxNode->setInputSurface(buffersource);
1149 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1150
1151 // set port mode
1152 PortMode portMode[2];
1153 portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
1154 portMode[1] = PortMode::PRESET_BYTE_BUFFER;
1155 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1156 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1157 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1158 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1159
1160 // set state to idle
1161 ASSERT_NO_FATAL_FAILURE(changeStateLoadedtoIdle(
1162 omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer,
1163 kPortIndexInput, kPortIndexOutput, portMode));
1164 // set state to executing
1165 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1166 ASSERT_NO_FATAL_FAILURE(testEOS(omxNode, observer, &buffersource->iBuffer,
1167 &buffersource->oBuffer, false, eosFlag));
1168 // set state to idle
1169 ASSERT_NO_FATAL_FAILURE(changeStateExecutetoIdle(
1170 omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer));
1171 // set state to executing
1172 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(
1173 omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer,
1174 kPortIndexInput, kPortIndexOutput));
1175 // test for callbacks
1176 EXPECT_EQ(buffersource->callback, 31);
1177 }
1178
1179 // test raw stream encode (input is byte buffers)
TEST_P(VideoEncHidlTest,EncodeTest)1180 TEST_P(VideoEncHidlTest, EncodeTest) {
1181 description("Test Encode");
1182 if (disableTest) return;
1183 android::hardware::media::omx::V1_0::Status status;
1184 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1185 status = setRole(omxNode, role_);
1186 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1187 OMX_PORT_PARAM_TYPE params;
1188 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1189 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1190 ASSERT_EQ(params.nPorts, 2U);
1191 kPortIndexInput = params.nStartPortNumber;
1192 kPortIndexOutput = kPortIndexInput + 1;
1193 }
1194 char mURL[512];
1195 strcpy(mURL, sResourceDir.c_str());
1196 GetURLForComponent(mURL);
1197
1198 std::ifstream eleStream;
1199
1200 timestampDevTest = true;
1201
1202 // Configure input port
1203 uint32_t nFrameWidth = 352;
1204 uint32_t nFrameHeight = 288;
1205 uint32_t xFramerate = (30U << 16);
1206 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatUnused;
1207 OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
1208 portFormat.nIndex = 0;
1209 while (1) {
1210 status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat,
1211 kPortIndexInput, &portFormat);
1212 if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
1213 EXPECT_EQ(portFormat.eCompressionFormat, OMX_VIDEO_CodingUnused);
1214 if (OMX_COLOR_FormatYUV420SemiPlanar == portFormat.eColorFormat ||
1215 OMX_COLOR_FormatYUV420Planar == portFormat.eColorFormat) {
1216 eColorFormat = portFormat.eColorFormat;
1217 break;
1218 }
1219 portFormat.nIndex++;
1220 if (portFormat.nIndex == 512) break;
1221 }
1222 ASSERT_NE(eColorFormat, OMX_COLOR_FormatUnused);
1223 setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
1224 xFramerate, eColorFormat);
1225
1226 // Configure output port
1227 uint32_t nBitRate = 512000;
1228 ASSERT_NO_FATAL_FAILURE(
1229 setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat,
1230 nFrameWidth, nFrameHeight, nBitRate, xFramerate));
1231 setRefreshPeriod(omxNode, kPortIndexOutput, 0);
1232
1233 unsigned int index;
1234 omxNode->getExtensionIndex(
1235 "OMX.google.android.index.prependSPSPPSToIDRFrames",
1236 [&status, &index](android::hardware::media::omx::V1_0::Status _s,
1237 unsigned int _nl) {
1238 status = _s;
1239 index = _nl;
1240 });
1241 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1242 android::PrependSPSPPSToIDRFramesParams param;
1243 param.bEnable = OMX_TRUE;
1244 status = setParam(omxNode, static_cast<OMX_INDEXTYPE>(index), ¶m);
1245 }
1246 if (status != ::android::hardware::media::omx::V1_0::Status::OK)
1247 std::cout << "[ INFO ] unable to prependSPSPPSToIDRFrames\n";
1248 else
1249 prependSPSPPS = true;
1250
1251 // set port mode
1252 PortMode portMode[2];
1253 portMode[0] = portMode[1] = PortMode::PRESET_BYTE_BUFFER;
1254 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1255 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1256 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1257 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1258
1259 uint32_t latency = 0;
1260 setLatency(omxNode, kPortIndexInput, latency);
1261 getLatency(omxNode, kPortIndexInput, &latency);
1262
1263 android::Vector<BufferInfo> iBuffer, oBuffer;
1264
1265 // set state to idle
1266 ASSERT_NO_FATAL_FAILURE(
1267 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1268 kPortIndexInput, kPortIndexOutput, portMode));
1269 // set state to executing
1270 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1271
1272 eleStream.open(mURL, std::ifstream::binary);
1273 ASSERT_EQ(eleStream.is_open(), true);
1274 ASSERT_NO_FATAL_FAILURE(encodeNFrames(
1275 omxNode, observer, kPortIndexInput, kPortIndexOutput, &iBuffer,
1276 &oBuffer, 32, xFramerate, (nFrameWidth * nFrameHeight * 3) >> 1,
1277 eleStream, ×tampUslist));
1278 eleStream.close();
1279 ASSERT_NO_FATAL_FAILURE(
1280 waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer));
1281 ASSERT_NO_FATAL_FAILURE(
1282 testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
1283 if (timestampDevTest) EXPECT_EQ(timestampUslist.empty(), true);
1284
1285 // set state to idle
1286 ASSERT_NO_FATAL_FAILURE(
1287 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1288 // set state to executing
1289 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1290 &oBuffer, kPortIndexInput,
1291 kPortIndexOutput));
1292 }
1293
1294 // test raw stream encode (input is ANW buffers)
TEST_P(VideoEncHidlTest,EncodeTestBufferMetaModes)1295 TEST_P(VideoEncHidlTest, EncodeTestBufferMetaModes) {
1296 description("Test Encode Input buffer metamodes");
1297 if (disableTest) return;
1298 android::hardware::media::omx::V1_0::Status status;
1299 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1300 status = setRole(omxNode, role_);
1301 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1302 OMX_PORT_PARAM_TYPE params;
1303 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1304 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1305 ASSERT_EQ(params.nPorts, 2U);
1306 kPortIndexInput = params.nStartPortNumber;
1307 kPortIndexOutput = kPortIndexInput + 1;
1308 }
1309
1310 // Configure input port
1311 uint32_t nFrameWidth = 352;
1312 uint32_t nFrameHeight = 288;
1313 uint32_t xFramerate = (30U << 16);
1314 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatAndroidOpaque;
1315 setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
1316 xFramerate, eColorFormat);
1317
1318 // Configure output port
1319 uint32_t nBitRate = 512000;
1320 ASSERT_NO_FATAL_FAILURE(
1321 setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat,
1322 nFrameWidth, nFrameHeight, nBitRate, xFramerate));
1323 // CreateInputSurface
1324 EXPECT_TRUE(omx->createInputSurface(
1325 [&](android::hardware::media::omx::V1_0::Status _s,
1326 sp<IGraphicBufferProducer> const& _nl,
1327 sp<IGraphicBufferSource> const& _n2) {
1328 status = _s;
1329 producer = _nl;
1330 source = _n2;
1331 })
1332 .isOk());
1333 ASSERT_NE(producer, nullptr);
1334 ASSERT_NE(source, nullptr);
1335
1336 // setMaxDequeuedBufferCount
1337 int32_t returnval;
1338 int32_t value;
1339 producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
1340 [&returnval, &value](int32_t _s, int32_t _n1) {
1341 returnval = _s;
1342 value = _n1;
1343 });
1344 ASSERT_EQ(returnval, 0);
1345 OMX_PARAM_PORTDEFINITIONTYPE portDef;
1346 status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
1347 kPortIndexInput, &portDef);
1348 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1349 ASSERT_EQ(::android::OK,
1350 producer->setMaxDequeuedBufferCount(portDef.nBufferCountActual));
1351
1352 // Connect :: Mock Producer Listener
1353 IGraphicBufferProducer::QueueBufferOutput qbo;
1354 sp<CodecProducerListener> listener =
1355 new CodecProducerListener(portDef.nBufferCountActual + value, value);
1356 producer->connect(
1357 listener, NATIVE_WINDOW_API_CPU, false,
1358 [&](int32_t _s, IGraphicBufferProducer::QueueBufferOutput const& _n1) {
1359 returnval = _s;
1360 qbo = _n1;
1361 });
1362 ASSERT_EQ(returnval, 0);
1363
1364 portDef.nBufferCountActual = portDef.nBufferCountActual + value;
1365 status = setPortParam(omxNode, OMX_IndexParamPortDefinition,
1366 kPortIndexInput, &portDef);
1367 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1368
1369 // Do setInputSurface()
1370 // enable MetaMode on input port
1371 status = source->configure(
1372 omxNode, android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN);
1373 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1374
1375 // set port mode
1376 PortMode portMode[2];
1377 portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
1378 portMode[1] = PortMode::PRESET_BYTE_BUFFER;
1379 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1380 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1381 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1382 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1383
1384 char mURL[512];
1385 strcpy(mURL, sResourceDir.c_str());
1386 GetURLForComponent(mURL);
1387
1388 uint32_t latency = 0;
1389 setLatency(omxNode, kPortIndexInput, latency);
1390 getLatency(omxNode, kPortIndexInput, &latency);
1391
1392 std::ifstream eleStream;
1393
1394 status = source->setSuspend(false, 0);
1395 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1396 status = source->setRepeatPreviousFrameDelayUs(100000);
1397 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1398 status = source->setMaxFps(24.0f);
1399 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1400 status = source->setTimeLapseConfig(24.0, 24.0);
1401 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1402 status = source->setTimeOffsetUs(-100);
1403 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1404 status = source->setStartTimeUs(10);
1405 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1406 status = source->setStopTimeUs(1000000);
1407 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1408 ::android::hardware::media::omx::V1_0::ColorAspects aspects;
1409 aspects.range =
1410 ::android::hardware::media::omx::V1_0::ColorAspects::Range::UNSPECIFIED;
1411 aspects.primaries = ::android::hardware::media::omx::V1_0::ColorAspects::
1412 Primaries::UNSPECIFIED;
1413 aspects.transfer = ::android::hardware::media::omx::V1_0::ColorAspects::
1414 Transfer::UNSPECIFIED;
1415 aspects.matrixCoeffs = ::android::hardware::media::omx::V1_0::ColorAspects::
1416 MatrixCoeffs::UNSPECIFIED;
1417 status = source->setColorAspects(aspects);
1418 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1419 int64_t stopTimeOffsetUs;
1420 source->getStopTimeOffsetUs(
1421 [&](android::hardware::media::omx::V1_0::Status _s, int64_t _n1) {
1422 status = _s;
1423 stopTimeOffsetUs = _n1;
1424 });
1425 EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1426
1427 android::Vector<BufferInfo> iBuffer, oBuffer;
1428 // set state to idle
1429 ASSERT_NO_FATAL_FAILURE(
1430 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1431 kPortIndexInput, kPortIndexOutput, portMode));
1432 // set state to executing
1433 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1434
1435 eleStream.open(mURL, std::ifstream::binary);
1436 ASSERT_EQ(eleStream.is_open(), true);
1437 ASSERT_NO_FATAL_FAILURE(encodeNFrames(
1438 omxNode, observer, kPortIndexInput, kPortIndexOutput, &iBuffer,
1439 &oBuffer, 1024, xFramerate, (nFrameWidth * nFrameHeight * 3) >> 1,
1440 eleStream, nullptr, false, true, producer, listener));
1441 eleStream.close();
1442 ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(omxNode, observer, &iBuffer,
1443 &oBuffer, true, listener));
1444 ASSERT_NO_FATAL_FAILURE(
1445 testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
1446
1447 // set state to idle
1448 ASSERT_NO_FATAL_FAILURE(
1449 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1450 EXPECT_EQ(portDef.nBufferCountActual, listener->freeBuffers);
1451 // set state to executing
1452 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1453 &oBuffer, kPortIndexInput,
1454 kPortIndexOutput));
1455
1456 returnval = producer->disconnect(
1457 NATIVE_WINDOW_API_CPU, IGraphicBufferProducer::DisconnectMode::API);
1458 ASSERT_EQ(returnval, 0);
1459 }
1460
1461 // Test end of stream
TEST_P(VideoEncHidlTest,EncodeTestEOS)1462 TEST_P(VideoEncHidlTest, EncodeTestEOS) {
1463 description("Test EOS");
1464 if (disableTest) return;
1465 android::hardware::media::omx::V1_0::Status status;
1466 uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1467 status = setRole(omxNode, role_);
1468 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1469 OMX_PORT_PARAM_TYPE params;
1470 status = getParam(omxNode, OMX_IndexParamVideoInit, ¶ms);
1471 if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1472 ASSERT_EQ(params.nPorts, 2U);
1473 kPortIndexInput = params.nStartPortNumber;
1474 kPortIndexOutput = kPortIndexInput + 1;
1475 }
1476
1477 // Configure input port
1478 uint32_t nFrameWidth = 352;
1479 uint32_t nFrameHeight = 288;
1480 uint32_t xFramerate = (30U << 16);
1481 OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatAndroidOpaque;
1482 setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
1483 xFramerate, eColorFormat);
1484
1485 // CreateInputSurface
1486 EXPECT_TRUE(omx->createInputSurface(
1487 [&](android::hardware::media::omx::V1_0::Status _s,
1488 sp<IGraphicBufferProducer> const& _nl,
1489 sp<IGraphicBufferSource> const& _n2) {
1490 status = _s;
1491 producer = _nl;
1492 source = _n2;
1493 })
1494 .isOk());
1495 ASSERT_NE(producer, nullptr);
1496 ASSERT_NE(source, nullptr);
1497
1498 // setMaxDequeuedBufferCount
1499 int32_t returnval;
1500 int32_t value;
1501 producer->query(NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS,
1502 [&returnval, &value](int32_t _s, int32_t _n1) {
1503 returnval = _s;
1504 value = _n1;
1505 });
1506 ASSERT_EQ(returnval, 0);
1507 OMX_PARAM_PORTDEFINITIONTYPE portDef;
1508 status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
1509 kPortIndexInput, &portDef);
1510 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1511 ASSERT_EQ(::android::OK,
1512 producer->setMaxDequeuedBufferCount(portDef.nBufferCountActual));
1513
1514 // Connect :: Mock Producer Listener
1515 IGraphicBufferProducer::QueueBufferOutput qbo;
1516 sp<CodecProducerListener> listener =
1517 new CodecProducerListener(portDef.nBufferCountActual + value, value);
1518 producer->connect(
1519 listener, NATIVE_WINDOW_API_CPU, false,
1520 [&](int32_t _s, IGraphicBufferProducer::QueueBufferOutput const& _n1) {
1521 returnval = _s;
1522 qbo = _n1;
1523 });
1524 ASSERT_EQ(returnval, 0);
1525
1526 portDef.nBufferCountActual = portDef.nBufferCountActual + value;
1527 status = setPortParam(omxNode, OMX_IndexParamPortDefinition,
1528 kPortIndexInput, &portDef);
1529 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1530
1531 // Do setInputSurface()
1532 // enable MetaMode on input port
1533 status = source->configure(
1534 omxNode, android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN);
1535 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1536
1537 // set port mode
1538 PortMode portMode[2];
1539 portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
1540 portMode[1] = PortMode::PRESET_BYTE_BUFFER;
1541 status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
1542 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1543 status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
1544 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1545
1546 android::Vector<BufferInfo> iBuffer, oBuffer;
1547 // set state to idle
1548 ASSERT_NO_FATAL_FAILURE(
1549 changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1550 kPortIndexInput, kPortIndexOutput, portMode));
1551 // set state to executing
1552 ASSERT_NO_FATAL_FAILURE(changeStateIdletoExecute(omxNode, observer));
1553
1554 // send EOS
1555 status = source->signalEndOfInputStream();
1556 ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1557 ASSERT_NO_FATAL_FAILURE(waitOnInputConsumption(omxNode, observer, &iBuffer,
1558 &oBuffer, true, listener));
1559 ASSERT_NO_FATAL_FAILURE(
1560 testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag));
1561
1562 // set state to idle
1563 ASSERT_NO_FATAL_FAILURE(
1564 changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
1565 EXPECT_EQ(portDef.nBufferCountActual, listener->freeBuffers);
1566 // set state to executing
1567 ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
1568 &oBuffer, kPortIndexInput,
1569 kPortIndexOutput));
1570
1571 returnval = producer->disconnect(
1572 NATIVE_WINDOW_API_CPU, IGraphicBufferProducer::DisconnectMode::API);
1573 ASSERT_EQ(returnval, 0);
1574 }
1575
1576 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VideoEncHidlTest);
1577 INSTANTIATE_TEST_SUITE_P(PerInstance, VideoEncHidlTest, testing::ValuesIn(kTestParameters),
1578 android::hardware::PrintInstanceTupleNameToString<>);
1579
main(int argc,char ** argv)1580 int main(int argc, char** argv) {
1581 kTestParameters = getTestParameters("video_encoder");
1582 ::testing::InitGoogleTest(&argc, argv);
1583
1584 // Set the resource directory based on command line args.
1585 // Test will fail to set up if the argument is not set.
1586 for (int i = 1; i < argc; i++) {
1587 if (strcmp(argv[i], "-P") == 0 && i < argc - 1) {
1588 sResourceDir = argv[i + 1];
1589 break;
1590 }
1591 }
1592
1593 return RUN_ALL_TESTS();
1594 }