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