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