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