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