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, &param);
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, &param);
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                            &param);
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, &param);
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                           &param);
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, &param);
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, &param);
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, &params);
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, &params);
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, &params);
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), &param);
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, &timestampUslist));
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, &params);
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, &params);
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