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_audio_dec_test"
18 #include <android-base/logging.h>
19 
20 #include <android/hardware/media/omx/1.0/IOmx.h>
21 #include <android/hardware/media/omx/1.0/IOmxNode.h>
22 #include <android/hardware/media/omx/1.0/IOmxObserver.h>
23 #include <android/hardware/media/omx/1.0/types.h>
24 #include <android/hidl/allocator/1.0/IAllocator.h>
25 #include <android/hidl/memory/1.0/IMapper.h>
26 #include <android/hidl/memory/1.0/IMemory.h>
27 
28 using ::android::hardware::media::omx::V1_0::IOmx;
29 using ::android::hardware::media::omx::V1_0::IOmxObserver;
30 using ::android::hardware::media::omx::V1_0::IOmxNode;
31 using ::android::hardware::media::omx::V1_0::Message;
32 using ::android::hardware::media::omx::V1_0::CodecBuffer;
33 using ::android::hardware::media::omx::V1_0::PortMode;
34 using ::android::hidl::allocator::V1_0::IAllocator;
35 using ::android::hidl::memory::V1_0::IMemory;
36 using ::android::hidl::memory::V1_0::IMapper;
37 using ::android::hardware::Return;
38 using ::android::hardware::Void;
39 using ::android::hardware::hidl_vec;
40 using ::android::hardware::hidl_string;
41 using ::android::sp;
42 
43 #include <VtsHalHidlTargetTestBase.h>
44 #include <getopt.h>
45 #include <media_audio_hidl_test_common.h>
46 #include <media_hidl_test_common.h>
47 #include <fstream>
48 
49 // A class for test environment setup
50 class ComponentTestEnvironment : public ::testing::Environment {
51    public:
SetUp()52     virtual void SetUp() {}
TearDown()53     virtual void TearDown() {}
54 
ComponentTestEnvironment()55     ComponentTestEnvironment() : instance("default"), res("/sdcard/media/") {}
56 
setInstance(const char * _instance)57     void setInstance(const char* _instance) { instance = _instance; }
58 
setComponent(const char * _component)59     void setComponent(const char* _component) { component = _component; }
60 
setRole(const char * _role)61     void setRole(const char* _role) { role = _role; }
62 
setRes(const char * _res)63     void setRes(const char* _res) { res = _res; }
64 
getInstance() const65     const hidl_string getInstance() const { return instance; }
66 
getComponent() const67     const hidl_string getComponent() const { return component; }
68 
getRole() const69     const hidl_string getRole() const { return role; }
70 
getRes() const71     const hidl_string getRes() const { return res; }
72 
initFromOptions(int argc,char ** argv)73     int initFromOptions(int argc, char** argv) {
74         static struct option options[] = {
75             {"instance", required_argument, 0, 'I'},
76             {"component", required_argument, 0, 'C'},
77             {"role", required_argument, 0, 'R'},
78             {"res", required_argument, 0, 'P'},
79             {0, 0, 0, 0}};
80 
81         while (true) {
82             int index = 0;
83             int c = getopt_long(argc, argv, "I:C:R:P:", options, &index);
84             if (c == -1) {
85                 break;
86             }
87 
88             switch (c) {
89                 case 'I':
90                     setInstance(optarg);
91                     break;
92                 case 'C':
93                     setComponent(optarg);
94                     break;
95                 case 'R':
96                     setRole(optarg);
97                     break;
98                 case 'P':
99                     setRes(optarg);
100                     break;
101                 case '?':
102                     break;
103             }
104         }
105 
106         if (optind < argc) {
107             fprintf(stderr,
108                     "unrecognized option: %s\n\n"
109                     "usage: %s <gtest options> <test options>\n\n"
110                     "test options are:\n\n"
111                     "-I, --instance: HAL instance to test\n"
112                     "-C, --component: OMX component to test\n"
113                     "-R, --role: OMX component Role\n"
114                     "-P, --res: Resource files directory location\n",
115                     argv[optind ?: 1], argv[0]);
116             return 2;
117         }
118         return 0;
119     }
120 
121    private:
122     hidl_string instance;
123     hidl_string component;
124     hidl_string role;
125     hidl_string res;
126 };
127 
128 static ComponentTestEnvironment* gEnv = nullptr;
129 
130 // audio decoder test fixture class
131 class AudioDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
132    public:
SetUp()133     virtual void SetUp() override {
134         disableTest = false;
135         android::hardware::media::omx::V1_0::Status status;
136         omx = ::testing::VtsHalHidlTargetTestBase::getService<IOmx>(
137             gEnv->getInstance());
138         ASSERT_NE(omx, nullptr);
139         observer =
140             new CodecObserver([this](Message msg, const BufferInfo* buffer) {
141                 handleMessage(msg, buffer);
142             });
143         ASSERT_NE(observer, nullptr);
144         if (strncmp(gEnv->getComponent().c_str(), "OMX.", 4) != 0)
145             disableTest = true;
146         EXPECT_TRUE(omx->allocateNode(
147                            gEnv->getComponent(), observer,
148                            [&](android::hardware::media::omx::V1_0::Status _s,
149                                sp<IOmxNode> const& _nl) {
150                                status = _s;
151                                this->omxNode = _nl;
152                            })
153                         .isOk());
154         ASSERT_NE(omxNode, nullptr);
155         ASSERT_NE(gEnv->getRole().empty(), true) << "Invalid Component Role";
156         struct StringToName {
157             const char* Name;
158             standardComp CompName;
159         };
160         const StringToName kStringToName[] = {
161             {"mp3", mp3}, {"amrnb", amrnb},       {"amrwb", amrwb},
162             {"aac", aac}, {"vorbis", vorbis},     {"opus", opus},
163             {"pcm", pcm}, {"g711alaw", g711alaw}, {"g711mlaw", g711mlaw},
164             {"gsm", gsm}, {"raw", raw},
165         };
166         const size_t kNumStringToName =
167             sizeof(kStringToName) / sizeof(kStringToName[0]);
168         const char* pch;
169         char substring[OMX_MAX_STRINGNAME_SIZE];
170         strcpy(substring, gEnv->getRole().c_str());
171         pch = strchr(substring, '.');
172         ASSERT_NE(pch, nullptr);
173         compName = unknown_comp;
174         for (size_t i = 0; i < kNumStringToName; ++i) {
175             if (!strcasecmp(pch + 1, kStringToName[i].Name)) {
176                 compName = kStringToName[i].CompName;
177                 break;
178             }
179         }
180         if (compName == unknown_comp) disableTest = true;
181         struct CompToCoding {
182             standardComp CompName;
183             OMX_AUDIO_CODINGTYPE eEncoding;
184         };
185         static const CompToCoding kCompToCoding[] = {
186             {mp3, OMX_AUDIO_CodingMP3},
187             {amrnb, OMX_AUDIO_CodingAMR},
188             {amrwb, OMX_AUDIO_CodingAMR},
189             {aac, OMX_AUDIO_CodingAAC},
190             {vorbis, OMX_AUDIO_CodingVORBIS},
191             {pcm, OMX_AUDIO_CodingPCM},
192             {opus, (OMX_AUDIO_CODINGTYPE)OMX_AUDIO_CodingAndroidOPUS},
193             {g711alaw, OMX_AUDIO_CodingG711},
194             {g711mlaw, OMX_AUDIO_CodingG711},
195             {gsm, OMX_AUDIO_CodingGSMFR},
196             {raw, OMX_AUDIO_CodingPCM},
197         };
198         static const size_t kNumCompToCoding =
199             sizeof(kCompToCoding) / sizeof(kCompToCoding[0]);
200         size_t i;
201         for (i = 0; i < kNumCompToCoding; ++i) {
202             if (kCompToCoding[i].CompName == compName) {
203                 eEncoding = kCompToCoding[i].eEncoding;
204                 break;
205             }
206         }
207         if (i == kNumCompToCoding) disableTest = true;
208         eosFlag = false;
209         framesReceived = 0;
210         timestampUs = 0;
211         timestampDevTest = false;
212         if (disableTest) std::cerr << "[          ] Warning !  Test Disabled\n";
213     }
214 
TearDown()215     virtual void TearDown() override {
216         if (omxNode != nullptr) {
217             EXPECT_TRUE((omxNode->freeNode()).isOk());
218             omxNode = nullptr;
219         }
220     }
221 
222     // callback function to process messages received by onMessages() from IL
223     // client.
handleMessage(Message msg,const BufferInfo * buffer)224     void handleMessage(Message msg, const BufferInfo* buffer) {
225         (void)buffer;
226         if (msg.type == Message::Type::FILL_BUFFER_DONE) {
227             if (msg.data.extendedBufferData.flags & OMX_BUFFERFLAG_EOS) {
228                 eosFlag = true;
229             }
230             if (msg.data.extendedBufferData.rangeLength != 0) {
231                 framesReceived += 1;
232                 // For decoder components current timestamp always exceeds
233                 // previous timestamp
234                 EXPECT_GE(msg.data.extendedBufferData.timestampUs, timestampUs);
235                 timestampUs = msg.data.extendedBufferData.timestampUs;
236                 // Test if current timestamp is among the list of queued
237                 // timestamps
238                 if (timestampDevTest) {
239                     bool tsHit = false;
240                     android::List<uint64_t>::iterator it =
241                         timestampUslist.begin();
242                     while (it != timestampUslist.end()) {
243                         if (*it == timestampUs) {
244                             timestampUslist.erase(it);
245                             tsHit = true;
246                             break;
247                         }
248                         it++;
249                     }
250                     if (tsHit == false) {
251                         if (timestampUslist.empty() == false) {
252                             EXPECT_EQ(tsHit, true)
253                                 << "TimeStamp not recognized";
254                         } else {
255                             std::cerr
256                                 << "[          ] Warning ! Received non-zero "
257                                    "output / TimeStamp not recognized \n";
258                         }
259                     }
260                 }
261 #define WRITE_OUTPUT 0
262 #if WRITE_OUTPUT
263                 static int count = 0;
264                 FILE* ofp = nullptr;
265                 if (count)
266                     ofp = fopen("out.bin", "ab");
267                 else
268                     ofp = fopen("out.bin", "wb");
269                 if (ofp != nullptr) {
270                     fwrite(static_cast<void*>(buffer->mMemory->getPointer()),
271                            sizeof(char),
272                            msg.data.extendedBufferData.rangeLength, ofp);
273                     fclose(ofp);
274                     count++;
275                 }
276 #endif
277             }
278         }
279     }
280 
281     enum standardComp {
282         mp3,
283         amrnb,
284         amrwb,
285         aac,
286         vorbis,
287         opus,
288         pcm,
289         g711alaw,
290         g711mlaw,
291         gsm,
292         raw,
293         unknown_comp,
294     };
295 
296     sp<IOmx> omx;
297     sp<CodecObserver> observer;
298     sp<IOmxNode> omxNode;
299     standardComp compName;
300     OMX_AUDIO_CODINGTYPE eEncoding;
301     bool disableTest;
302     bool eosFlag;
303     uint32_t framesReceived;
304     uint64_t timestampUs;
305     ::android::List<uint64_t> timestampUslist;
306     bool timestampDevTest;
307 
308    protected:
description(const std::string & description)309     static void description(const std::string& description) {
310         RecordProperty("description", description);
311     }
312 };
313 
314 // Set Default port param.
setDefaultPortParam(sp<IOmxNode> omxNode,OMX_U32 portIndex,OMX_AUDIO_CODINGTYPE eEncoding,int32_t nChannels=2,int32_t nSampleRate=44100,OMX_AUDIO_PCMMODETYPE ePCMMode=OMX_AUDIO_PCMModeLinear,OMX_NUMERICALDATATYPE eNumData=OMX_NumericalDataSigned,int32_t nBitPerSample=16)315 void setDefaultPortParam(
316     sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding,
317     int32_t nChannels = 2, int32_t nSampleRate = 44100,
318     OMX_AUDIO_PCMMODETYPE ePCMMode = OMX_AUDIO_PCMModeLinear,
319     OMX_NUMERICALDATATYPE eNumData = OMX_NumericalDataSigned,
320     int32_t nBitPerSample = 16) {
321     android::hardware::media::omx::V1_0::Status status;
322 
323     OMX_PARAM_PORTDEFINITIONTYPE portDef;
324     status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
325                           &portDef);
326     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
327 
328     portDef.format.audio.bFlagErrorConcealment = OMX_TRUE;
329     portDef.format.audio.eEncoding = eEncoding;
330     status = setPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
331                           &portDef);
332     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
333 
334     switch ((int)eEncoding) {
335         case OMX_AUDIO_CodingPCM:
336             setupPCMPort(omxNode, portIndex, nChannels, eNumData, nBitPerSample,
337                          nSampleRate, ePCMMode);
338             break;
339         case OMX_AUDIO_CodingAAC:
340             setupAACPort(omxNode, portIndex, OMX_AUDIO_AACObjectNull,
341                          OMX_AUDIO_AACStreamFormatMP4FF, nChannels, 0,
342                          nSampleRate);
343         default:
344             break;
345     }
346 }
347 
348 // In decoder components, often the input port parameters get updated upon
349 // parsing the header of elementary stream. Client needs to collect this
350 // information to reconfigure other ports that share data with this input
351 // port.
getInputChannelInfo(sp<IOmxNode> omxNode,OMX_U32 kPortIndexInput,OMX_AUDIO_CODINGTYPE eEncoding,int32_t * nChannels,int32_t * nSampleRate)352 void getInputChannelInfo(sp<IOmxNode> omxNode, OMX_U32 kPortIndexInput,
353                          OMX_AUDIO_CODINGTYPE eEncoding, int32_t* nChannels,
354                          int32_t* nSampleRate) {
355     android::hardware::media::omx::V1_0::Status status;
356     *nChannels = 0;
357     *nSampleRate = 0;
358 
359     switch ((int)eEncoding) {
360         case OMX_AUDIO_CodingGSMFR:
361         case OMX_AUDIO_CodingG711:
362         case OMX_AUDIO_CodingPCM: {
363             OMX_AUDIO_PARAM_PCMMODETYPE param;
364             status = getPortParam(omxNode, OMX_IndexParamAudioPcm,
365                                   kPortIndexInput, &param);
366             ASSERT_EQ(status,
367                       ::android::hardware::media::omx::V1_0::Status::OK);
368             *nChannels = param.nChannels;
369             *nSampleRate = param.nSamplingRate;
370             break;
371         }
372         case OMX_AUDIO_CodingMP3: {
373             OMX_AUDIO_PARAM_MP3TYPE param;
374             status = getPortParam(omxNode, OMX_IndexParamAudioMp3,
375                                   kPortIndexInput, &param);
376             ASSERT_EQ(status,
377                       ::android::hardware::media::omx::V1_0::Status::OK);
378             *nChannels = param.nChannels;
379             *nSampleRate = param.nSampleRate;
380             break;
381         }
382         case OMX_AUDIO_CodingAndroidOPUS: {
383             OMX_AUDIO_PARAM_ANDROID_OPUSTYPE param;
384             status = getPortParam(omxNode,
385                                   (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
386                                   kPortIndexInput, &param);
387             ASSERT_EQ(status,
388                       ::android::hardware::media::omx::V1_0::Status::OK);
389             *nChannels = param.nChannels;
390             *nSampleRate = param.nSampleRate;
391             break;
392         }
393         case OMX_AUDIO_CodingVORBIS: {
394             OMX_AUDIO_PARAM_VORBISTYPE param;
395             status = getPortParam(omxNode, OMX_IndexParamAudioVorbis,
396                                   kPortIndexInput, &param);
397             ASSERT_EQ(status,
398                       ::android::hardware::media::omx::V1_0::Status::OK);
399             *nChannels = param.nChannels;
400             *nSampleRate = param.nSampleRate;
401             break;
402         }
403         case OMX_AUDIO_CodingAMR: {
404             OMX_AUDIO_PARAM_AMRTYPE param;
405             status = getPortParam(omxNode, OMX_IndexParamAudioAmr,
406                                   kPortIndexInput, &param);
407             ASSERT_EQ(status,
408                       ::android::hardware::media::omx::V1_0::Status::OK);
409             *nChannels = param.nChannels;
410             *nSampleRate = 8000;
411             break;
412         }
413         case OMX_AUDIO_CodingAAC: {
414             OMX_AUDIO_PARAM_AACPROFILETYPE param;
415             status = getPortParam(omxNode, OMX_IndexParamAudioAac,
416                                   kPortIndexInput, &param);
417             ASSERT_EQ(status,
418                       ::android::hardware::media::omx::V1_0::Status::OK);
419             *nChannels = param.nChannels;
420             *nSampleRate = param.nSampleRate;
421             break;
422         }
423         default:
424             ASSERT_TRUE(false);
425             break;
426     }
427 }
428 
429 // LookUpTable of clips and metadata for component testing
GetURLForComponent(AudioDecHidlTest::standardComp comp,char * mURL,char * info)430 void GetURLForComponent(AudioDecHidlTest::standardComp comp, char* mURL,
431                         char* info) {
432     struct CompToURL {
433         AudioDecHidlTest::standardComp comp;
434         const char* mURL;
435         const char* info;
436     };
437     static const CompToURL kCompToURL[] = {
438         {AudioDecHidlTest::standardComp::mp3,
439          "bbb_mp3_stereo_192kbps_48000hz.mp3",
440          "bbb_mp3_stereo_192kbps_48000hz.info"},
441         {AudioDecHidlTest::standardComp::aac,
442          "bbb_aac_stereo_128kbps_48000hz.aac",
443          "bbb_aac_stereo_128kbps_48000hz.info"},
444         {AudioDecHidlTest::standardComp::amrnb,
445          "sine_amrnb_1ch_12kbps_8000hz.amrnb",
446          "sine_amrnb_1ch_12kbps_8000hz.info"},
447         {AudioDecHidlTest::standardComp::amrwb,
448          "bbb_amrwb_1ch_14kbps_16000hz.amrwb",
449          "bbb_amrwb_1ch_14kbps_16000hz.info"},
450         {AudioDecHidlTest::standardComp::vorbis,
451          "bbb_vorbis_stereo_128kbps_48000hz.vorbis",
452          "bbb_vorbis_stereo_128kbps_48000hz.info"},
453         {AudioDecHidlTest::standardComp::opus,
454          "bbb_opus_stereo_128kbps_48000hz.opus",
455          "bbb_opus_stereo_128kbps_48000hz.info"},
456         {AudioDecHidlTest::standardComp::g711alaw, "bbb_g711alaw_1ch_8khz.raw",
457          "bbb_g711alaw_1ch_8khz.info"},
458         {AudioDecHidlTest::standardComp::g711mlaw, "bbb_g711mulaw_1ch_8khz.raw",
459          "bbb_g711mulaw_1ch_8khz.info"},
460         {AudioDecHidlTest::standardComp::gsm, "bbb_gsm_1ch_8khz_13kbps.raw",
461          "bbb_gsm_1ch_8khz_13kbps.info"},
462         {AudioDecHidlTest::standardComp::raw, "bbb_raw_1ch_8khz_s32le.raw",
463          "bbb_raw_1ch_8khz_s32le.info"},
464     };
465 
466     for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
467         if (kCompToURL[i].comp == comp) {
468             strcat(mURL, kCompToURL[i].mURL);
469             strcat(info, kCompToURL[i].info);
470             return;
471         }
472     }
473 }
474 
475 // port settings reconfiguration during runtime. reconfigures sample rate and
476 // number
portReconfiguration(sp<IOmxNode> omxNode,sp<CodecObserver> observer,android::Vector<BufferInfo> * iBuffer,android::Vector<BufferInfo> * oBuffer,OMX_AUDIO_CODINGTYPE eEncoding,OMX_U32 kPortIndexInput,OMX_U32 kPortIndexOutput,Message msg,AudioDecHidlTest::standardComp comp=AudioDecHidlTest::standardComp::unknown_comp)477 void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
478                          android::Vector<BufferInfo>* iBuffer,
479                          android::Vector<BufferInfo>* oBuffer,
480                          OMX_AUDIO_CODINGTYPE eEncoding,
481                          OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput,
482                          Message msg,
483                          AudioDecHidlTest::standardComp comp =
484                              AudioDecHidlTest::standardComp::unknown_comp) {
485     android::hardware::media::omx::V1_0::Status status;
486 
487     if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
488         ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
489 
490         status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable),
491                                       kPortIndexOutput);
492         ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
493 
494         status =
495             observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
496         if (status == android::hardware::media::omx::V1_0::Status::TIMED_OUT) {
497             for (size_t i = 0; i < oBuffer->size(); ++i) {
498                 // test if client got all its buffers back
499                 EXPECT_EQ((*oBuffer)[i].owner, client);
500                 // free the buffers
501                 status =
502                     omxNode->freeBuffer(kPortIndexOutput, (*oBuffer)[i].id);
503                 ASSERT_EQ(status,
504                           android::hardware::media::omx::V1_0::Status::OK);
505             }
506             status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
507                                               oBuffer);
508             ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
509             ASSERT_EQ(msg.type, Message::Type::EVENT);
510             ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
511             ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortDisable);
512             ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
513 
514             // set Port Params
515             int32_t nChannels;
516             int32_t nSampleRate;
517             getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
518                                 &nSampleRate);
519             // Configure output port
520             // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way
521             // to
522             // configure output PCM port. The port undergoes auto configuration
523             // internally basing on parsed elementary stream information.
524             if (comp != AudioDecHidlTest::standardComp::vorbis &&
525                 comp != AudioDecHidlTest::standardComp::opus &&
526                 comp != AudioDecHidlTest::standardComp::raw) {
527                 setDefaultPortParam(omxNode, kPortIndexOutput,
528                                     OMX_AUDIO_CodingPCM, nChannels,
529                                     nSampleRate);
530             }
531 
532             // If you can disable a port, then you should be able to
533             // enable
534             // it as well
535             status = omxNode->sendCommand(
536                 toRawCommandType(OMX_CommandPortEnable), kPortIndexOutput);
537             ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
538 
539             // do not enable the port until all the buffers are supplied
540             status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
541                                               oBuffer);
542             ASSERT_EQ(status,
543                       android::hardware::media::omx::V1_0::Status::TIMED_OUT);
544 
545             allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput);
546             status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer,
547                                               oBuffer);
548             ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
549             ASSERT_EQ(msg.type, Message::Type::EVENT);
550             ASSERT_EQ(msg.data.eventData.data1, OMX_CommandPortEnable);
551             ASSERT_EQ(msg.data.eventData.data2, kPortIndexOutput);
552 
553             // dispatch output buffers
554             for (size_t i = 0; i < oBuffer->size(); i++) {
555                 dispatchOutputBuffer(omxNode, oBuffer, i);
556             }
557         } else {
558             ASSERT_TRUE(false);
559         }
560     } else {
561         EXPECT_TRUE(false);
562         return;
563     }
564 }
565 
566 // 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,OMX_AUDIO_CODINGTYPE eEncoding,OMX_U32 kPortIndexInput,OMX_U32 kPortIndexOutput)567 void waitOnInputConsumption(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
568                             android::Vector<BufferInfo>* iBuffer,
569                             android::Vector<BufferInfo>* oBuffer,
570                             OMX_AUDIO_CODINGTYPE eEncoding,
571                             OMX_U32 kPortIndexInput, OMX_U32 kPortIndexOutput) {
572     android::hardware::media::omx::V1_0::Status status;
573     Message msg;
574     int timeOut = TIMEOUT_COUNTER;
575 
576     while (timeOut--) {
577         size_t i = 0;
578         status =
579             observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
580         if (status == android::hardware::media::omx::V1_0::Status::OK) {
581             EXPECT_EQ(msg.type, Message::Type::EVENT);
582             portReconfiguration(omxNode, observer, iBuffer, oBuffer, eEncoding,
583                                 kPortIndexInput, kPortIndexOutput, msg);
584         }
585         // status == TIMED_OUT, it could be due to process time being large
586         // than DEFAULT_TIMEOUT or component needs output buffers to start
587         // processing.
588         for (; i < iBuffer->size(); i++) {
589             if ((*iBuffer)[i].owner != client) break;
590         }
591         if (i == iBuffer->size()) break;
592 
593         // Dispatch an output buffer assuming outQueue.empty() is true
594         size_t index;
595         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
596             dispatchOutputBuffer(omxNode, oBuffer, index);
597         }
598         timeOut--;
599     }
600 }
601 
602 // Decode N Frames
decodeNFrames(sp<IOmxNode> omxNode,sp<CodecObserver> observer,android::Vector<BufferInfo> * iBuffer,android::Vector<BufferInfo> * oBuffer,OMX_AUDIO_CODINGTYPE eEncoding,OMX_U32 kPortIndexInput,OMX_U32 kPortIndexOutput,std::ifstream & eleStream,android::Vector<FrameData> * Info,int offset,int range,AudioDecHidlTest::standardComp comp,bool signalEOS=true)603 void decodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
604                    android::Vector<BufferInfo>* iBuffer,
605                    android::Vector<BufferInfo>* oBuffer,
606                    OMX_AUDIO_CODINGTYPE eEncoding, OMX_U32 kPortIndexInput,
607                    OMX_U32 kPortIndexOutput, std::ifstream& eleStream,
608                    android::Vector<FrameData>* Info, int offset, int range,
609                    AudioDecHidlTest::standardComp comp, bool signalEOS = true) {
610     android::hardware::media::omx::V1_0::Status status;
611     Message msg;
612 
613     // dispatch output buffers
614     for (size_t i = 0; i < oBuffer->size(); i++) {
615         dispatchOutputBuffer(omxNode, oBuffer, i);
616     }
617     // dispatch input buffers
618     uint32_t flags = 0;
619     int frameID = offset;
620     for (size_t i = 0; (i < iBuffer->size()) && (frameID < (int)Info->size()) &&
621                        (frameID < (offset + range));
622          i++) {
623         char* ipBuffer = static_cast<char*>(
624             static_cast<void*>((*iBuffer)[i].mMemory->getPointer()));
625         ASSERT_LE((*Info)[frameID].bytesCount,
626                   static_cast<int>((*iBuffer)[i].mMemory->getSize()));
627         eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
628         ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
629         flags = (*Info)[frameID].flags;
630         if (signalEOS && ((frameID == (int)Info->size() - 1) ||
631                           (frameID == (offset + range - 1))))
632             flags |= OMX_BUFFERFLAG_EOS;
633         dispatchInputBuffer(omxNode, iBuffer, i, (*Info)[frameID].bytesCount,
634                             flags, (*Info)[frameID].timestamp);
635         frameID++;
636     }
637 
638     int timeOut = TIMEOUT_COUNTER;
639     bool stall = false;
640     while (1) {
641         status =
642             observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
643 
644         // Port Reconfiguration
645         if (status == android::hardware::media::omx::V1_0::Status::OK &&
646             msg.type == Message::Type::EVENT) {
647             portReconfiguration(omxNode, observer, iBuffer, oBuffer, eEncoding,
648                                 kPortIndexInput, kPortIndexOutput, msg, comp);
649         }
650 
651         if (frameID == (int)Info->size() || frameID == (offset + range)) break;
652 
653         // Dispatch input buffer
654         size_t index = 0;
655         if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
656             char* ipBuffer = static_cast<char*>(
657                 static_cast<void*>((*iBuffer)[index].mMemory->getPointer()));
658             ASSERT_LE((*Info)[frameID].bytesCount,
659                       static_cast<int>((*iBuffer)[index].mMemory->getSize()));
660             eleStream.read(ipBuffer, (*Info)[frameID].bytesCount);
661             ASSERT_EQ(eleStream.gcount(), (*Info)[frameID].bytesCount);
662             flags = (*Info)[frameID].flags;
663             if (signalEOS && ((frameID == (int)Info->size() - 1) ||
664                               (frameID == (offset + range - 1))))
665                 flags |= OMX_BUFFERFLAG_EOS;
666             dispatchInputBuffer(omxNode, iBuffer, index,
667                                 (*Info)[frameID].bytesCount, flags,
668                                 (*Info)[frameID].timestamp);
669             frameID++;
670             stall = false;
671         } else
672             stall = true;
673         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
674             dispatchOutputBuffer(omxNode, oBuffer, index);
675             stall = false;
676         } else
677             stall = true;
678         if (stall)
679             timeOut--;
680         else
681             timeOut = TIMEOUT_COUNTER;
682         if (timeOut == 0) {
683             EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
684             break;
685         }
686     }
687 }
688 
689 // set component role
TEST_F(AudioDecHidlTest,SetRole)690 TEST_F(AudioDecHidlTest, SetRole) {
691     description("Test Set Component Role");
692     if (disableTest) return;
693     android::hardware::media::omx::V1_0::Status status;
694     status = setRole(omxNode, gEnv->getRole().c_str());
695     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
696 }
697 
698 // port format enumeration
TEST_F(AudioDecHidlTest,DISABLED_EnumeratePortFormat)699 TEST_F(AudioDecHidlTest, DISABLED_EnumeratePortFormat) {
700     description("Test Component on Mandatory Port Parameters (Port Format)");
701     if (disableTest) return;
702     android::hardware::media::omx::V1_0::Status status;
703     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
704     status = setRole(omxNode, gEnv->getRole().c_str());
705     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
706     OMX_PORT_PARAM_TYPE params;
707     status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
708     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
709         ASSERT_EQ(params.nPorts, 2U);
710         kPortIndexInput = params.nStartPortNumber;
711         kPortIndexOutput = kPortIndexInput + 1;
712     }
713     status = setAudioPortFormat(omxNode, kPortIndexInput, eEncoding);
714     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
715     status = setAudioPortFormat(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM);
716     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
717 }
718 
719 // test port settings reconfiguration, elementary stream decode and timestamp
720 // deviation
TEST_F(AudioDecHidlTest,DecodeTest)721 TEST_F(AudioDecHidlTest, DecodeTest) {
722     description("Tests Port Reconfiguration, Decode and timestamp deviation");
723     if (disableTest) return;
724     android::hardware::media::omx::V1_0::Status status;
725     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
726     status = setRole(omxNode, gEnv->getRole().c_str());
727     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
728     OMX_PORT_PARAM_TYPE params;
729     status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
730     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
731         ASSERT_EQ(params.nPorts, 2U);
732         kPortIndexInput = params.nStartPortNumber;
733         kPortIndexOutput = kPortIndexInput + 1;
734     }
735     char mURL[512], info[512];
736     strcpy(mURL, gEnv->getRes().c_str());
737     strcpy(info, gEnv->getRes().c_str());
738     GetURLForComponent(compName, mURL, info);
739 
740     std::ifstream eleStream, eleInfo;
741 
742     eleInfo.open(info);
743     ASSERT_EQ(eleInfo.is_open(), true);
744     android::Vector<FrameData> Info;
745     int bytesCount = 0;
746     uint32_t flags = 0;
747     uint32_t timestamp = 0;
748     timestampDevTest = true;
749     while (1) {
750         if (!(eleInfo >> bytesCount)) break;
751         eleInfo >> flags;
752         eleInfo >> timestamp;
753         Info.push_back({bytesCount, flags, timestamp});
754         if (flags != OMX_BUFFERFLAG_CODECCONFIG)
755             timestampUslist.push_back(timestamp);
756     }
757     eleInfo.close();
758 
759     int32_t nChannels, nSampleRate;
760     // Configure input port
761     setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
762     if (compName == raw)
763         setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
764                             OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
765                             32);
766     getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
767                         &nSampleRate);
768     // Configure output port
769     // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
770     // configure output PCM port. The port undergoes auto configuration
771     // internally basing on parsed elementary stream information.
772     if (compName != vorbis && compName != opus && compName != raw) {
773         setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
774                             nChannels, nSampleRate);
775     }
776 
777     android::Vector<BufferInfo> iBuffer, oBuffer;
778 
779     // set state to idle
780     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
781                             kPortIndexInput, kPortIndexOutput);
782     // set state to executing
783     changeStateIdletoExecute(omxNode, observer);
784     // Port Reconfiguration
785     eleStream.open(mURL, std::ifstream::binary);
786     ASSERT_EQ(eleStream.is_open(), true);
787     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
788                   kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0,
789                   (int)Info.size(), compName);
790     eleStream.close();
791     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
792                            kPortIndexInput, kPortIndexOutput);
793     testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
794     EXPECT_EQ(timestampUslist.empty(), true);
795     // set state to idle
796     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
797     // set state to executing
798     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
799                             kPortIndexInput, kPortIndexOutput);
800 }
801 
802 // end of sequence test
803 // SPECIAL CASE; Sending Empty input EOS buffer is not supported across all
804 // components. For instance soft vorbis and soft opus expects CSD buffers at
805 // the start. Disabling this test for now. We shall revisit this at a later
806 // stage
TEST_F(AudioDecHidlTest,DISABLED_EOSTest_M)807 TEST_F(AudioDecHidlTest, DISABLED_EOSTest_M) {
808     description("Test end of stream monkeying");
809     if (disableTest) return;
810     android::hardware::media::omx::V1_0::Status status;
811     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
812     status = setRole(omxNode, gEnv->getRole().c_str());
813     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
814     OMX_PORT_PARAM_TYPE params;
815     status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
816     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
817         ASSERT_EQ(params.nPorts, 2U);
818         kPortIndexInput = params.nStartPortNumber;
819         kPortIndexOutput = kPortIndexInput + 1;
820     }
821 
822     int32_t nChannels, nSampleRate;
823     // Configure input port
824     setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
825     if (compName == raw)
826         setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
827                             OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
828                             32);
829     getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
830                         &nSampleRate);
831     // Configure output port
832     // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
833     // configure output PCM port. The port undergoes auto configuration
834     // internally basing on parsed elementary stream information.
835     if (compName != vorbis && compName != opus && compName != raw) {
836         setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
837                             nChannels, nSampleRate);
838     }
839 
840     android::Vector<BufferInfo> iBuffer, oBuffer;
841 
842     // set state to idle
843     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
844                             kPortIndexInput, kPortIndexOutput);
845     // set state to executing
846     changeStateIdletoExecute(omxNode, observer);
847 
848     // request EOS at the start
849     testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag);
850     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
851                kPortIndexOutput);
852     EXPECT_GE(framesReceived, 0U);
853     framesReceived = 0;
854     timestampUs = 0;
855 
856     // set state to idle
857     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
858     // set state to executing
859     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
860                             kPortIndexInput, kPortIndexOutput);
861 }
862 
863 // end of sequence test
TEST_F(AudioDecHidlTest,ThumbnailTest)864 TEST_F(AudioDecHidlTest, ThumbnailTest) {
865     description("Test Request for thumbnail");
866     if (disableTest) return;
867     android::hardware::media::omx::V1_0::Status status;
868     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
869     status = setRole(omxNode, gEnv->getRole().c_str());
870     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
871     OMX_PORT_PARAM_TYPE params;
872     status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
873     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
874         ASSERT_EQ(params.nPorts, 2U);
875         kPortIndexInput = params.nStartPortNumber;
876         kPortIndexOutput = kPortIndexInput + 1;
877     }
878     char mURL[512], info[512];
879     strcpy(mURL, gEnv->getRes().c_str());
880     strcpy(info, gEnv->getRes().c_str());
881     GetURLForComponent(compName, mURL, info);
882 
883     std::ifstream eleStream, eleInfo;
884 
885     eleInfo.open(info);
886     ASSERT_EQ(eleInfo.is_open(), true);
887     android::Vector<FrameData> Info;
888     int bytesCount = 0;
889     uint32_t flags = 0;
890     uint32_t timestamp = 0;
891     while (1) {
892         if (!(eleInfo >> bytesCount)) break;
893         eleInfo >> flags;
894         eleInfo >> timestamp;
895         Info.push_back({bytesCount, flags, timestamp});
896     }
897     eleInfo.close();
898 
899     int32_t nChannels, nSampleRate;
900     // Configure input port
901     setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
902     if (compName == raw)
903         setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
904                             OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
905                             32);
906     getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
907                         &nSampleRate);
908     // Configure output port
909     // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
910     // configure output PCM port. The port undergoes auto configuration
911     // internally basing on parsed elementary stream information.
912     if (compName != vorbis && compName != opus && compName != raw) {
913         setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
914                             nChannels, nSampleRate);
915     }
916 
917     android::Vector<BufferInfo> iBuffer, oBuffer;
918 
919     // set state to idle
920     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
921                             kPortIndexInput, kPortIndexOutput);
922     // set state to executing
923     changeStateIdletoExecute(omxNode, observer);
924 
925     // request EOS for thumbnail
926     // signal EOS flag with last frame
927     size_t i = 0;
928     while (!(Info[i].flags & OMX_BUFFERFLAG_SYNCFRAME)) i++;
929     eleStream.open(mURL, std::ifstream::binary);
930     ASSERT_EQ(eleStream.is_open(), true);
931     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
932                   kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0, i + 1,
933                   compName);
934     eleStream.close();
935     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
936                            kPortIndexInput, kPortIndexOutput);
937     testEOS(omxNode, observer, &iBuffer, &oBuffer, false, eosFlag);
938     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
939                kPortIndexOutput);
940     EXPECT_GE(framesReceived, 1U);
941     framesReceived = 0;
942     timestampUs = 0;
943 
944     // signal EOS flag after last frame
945     eleStream.open(mURL, std::ifstream::binary);
946     ASSERT_EQ(eleStream.is_open(), true);
947     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
948                   kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0, i + 1,
949                   compName, false);
950     eleStream.close();
951     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
952                            kPortIndexInput, kPortIndexOutput);
953     testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag);
954     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
955                kPortIndexOutput);
956     EXPECT_GE(framesReceived, 1U);
957     framesReceived = 0;
958     timestampUs = 0;
959 
960     // set state to idle
961     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
962     // set state to executing
963     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
964                             kPortIndexInput, kPortIndexOutput);
965 }
966 
967 // end of sequence test
TEST_F(AudioDecHidlTest,SimpleEOSTest)968 TEST_F(AudioDecHidlTest, SimpleEOSTest) {
969     description("Test end of stream");
970     if (disableTest) return;
971     android::hardware::media::omx::V1_0::Status status;
972     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
973     status = setRole(omxNode, gEnv->getRole().c_str());
974     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
975     OMX_PORT_PARAM_TYPE params;
976     status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
977     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
978         ASSERT_EQ(params.nPorts, 2U);
979         kPortIndexInput = params.nStartPortNumber;
980         kPortIndexOutput = kPortIndexInput + 1;
981     }
982     char mURL[512], info[512];
983     strcpy(mURL, gEnv->getRes().c_str());
984     strcpy(info, gEnv->getRes().c_str());
985     GetURLForComponent(compName, mURL, info);
986 
987     std::ifstream eleStream, eleInfo;
988 
989     eleInfo.open(info);
990     ASSERT_EQ(eleInfo.is_open(), true);
991     android::Vector<FrameData> Info;
992     int bytesCount = 0;
993     uint32_t flags = 0;
994     uint32_t timestamp = 0;
995     while (1) {
996         if (!(eleInfo >> bytesCount)) break;
997         eleInfo >> flags;
998         eleInfo >> timestamp;
999         Info.push_back({bytesCount, flags, timestamp});
1000     }
1001     eleInfo.close();
1002 
1003     int32_t nChannels, nSampleRate;
1004     // Configure input port
1005     setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
1006     if (compName == raw)
1007         setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
1008                             OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
1009                             32);
1010     getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
1011                         &nSampleRate);
1012     // Configure output port
1013     // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
1014     // configure output PCM port. The port undergoes auto configuration
1015     // internally basing on parsed elementary stream information.
1016     if (compName != vorbis && compName != opus && compName != raw) {
1017         setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
1018                             nChannels, nSampleRate);
1019     }
1020 
1021     android::Vector<BufferInfo> iBuffer, oBuffer;
1022 
1023     // set state to idle
1024     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1025                             kPortIndexInput, kPortIndexOutput);
1026     // set state to executing
1027     changeStateIdletoExecute(omxNode, observer);
1028 
1029     // request EOS at the end
1030     eleStream.open(mURL, std::ifstream::binary);
1031     ASSERT_EQ(eleStream.is_open(), true);
1032     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1033                   kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0,
1034                   (int)Info.size(), compName, false);
1035     eleStream.close();
1036     waitOnInputConsumption(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1037                            kPortIndexInput, kPortIndexOutput);
1038     testEOS(omxNode, observer, &iBuffer, &oBuffer, true, eosFlag);
1039     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1040                kPortIndexOutput);
1041     framesReceived = 0;
1042     timestampUs = 0;
1043 
1044     // set state to idle
1045     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1046     // set state to executing
1047     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1048                             kPortIndexInput, kPortIndexOutput);
1049 }
1050 
1051 // test input/output port flush
TEST_F(AudioDecHidlTest,FlushTest)1052 TEST_F(AudioDecHidlTest, FlushTest) {
1053     description("Test Flush");
1054     if (disableTest) return;
1055     android::hardware::media::omx::V1_0::Status status;
1056     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
1057     status = setRole(omxNode, gEnv->getRole().c_str());
1058     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
1059     OMX_PORT_PARAM_TYPE params;
1060     status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
1061     if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
1062         ASSERT_EQ(params.nPorts, 2U);
1063         kPortIndexInput = params.nStartPortNumber;
1064         kPortIndexOutput = kPortIndexInput + 1;
1065     }
1066     char mURL[512], info[512];
1067     strcpy(mURL, gEnv->getRes().c_str());
1068     strcpy(info, gEnv->getRes().c_str());
1069     GetURLForComponent(compName, mURL, info);
1070 
1071     std::ifstream eleStream, eleInfo;
1072 
1073     eleInfo.open(info);
1074     ASSERT_EQ(eleInfo.is_open(), true);
1075     android::Vector<FrameData> Info;
1076     int bytesCount = 0;
1077     uint32_t flags = 0;
1078     uint32_t timestamp = 0;
1079     while (1) {
1080         if (!(eleInfo >> bytesCount)) break;
1081         eleInfo >> flags;
1082         eleInfo >> timestamp;
1083         Info.push_back({bytesCount, flags, timestamp});
1084     }
1085     eleInfo.close();
1086 
1087     int32_t nChannels, nSampleRate;
1088     // Configure input port
1089     setDefaultPortParam(omxNode, kPortIndexInput, eEncoding);
1090     if (compName == raw)
1091         setDefaultPortParam(omxNode, kPortIndexInput, eEncoding, 1, 8000,
1092                             OMX_AUDIO_PCMModeLinear, OMX_NumericalDataSigned,
1093                             32);
1094     getInputChannelInfo(omxNode, kPortIndexInput, eEncoding, &nChannels,
1095                         &nSampleRate);
1096     // Configure output port
1097     // SPECIAL CASE: Soft Vorbis, Opus and Raw Decoders do not offer way to
1098     // configure output PCM port. The port undergoes auto configuration
1099     // internally basing on parsed elementary stream information.
1100     if (compName != vorbis && compName != opus && compName != raw) {
1101         setDefaultPortParam(omxNode, kPortIndexOutput, OMX_AUDIO_CodingPCM,
1102                             nChannels, nSampleRate);
1103     }
1104 
1105     android::Vector<BufferInfo> iBuffer, oBuffer;
1106 
1107     // set state to idle
1108     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
1109                             kPortIndexInput, kPortIndexOutput);
1110     // set state to executing
1111     changeStateIdletoExecute(omxNode, observer);
1112 
1113     // Decode 128 frames and flush. here 128 is chosen to ensure there is a key
1114     // frame after this so that the below section can be convered for all
1115     // components
1116     int nFrames = 128;
1117     eleStream.open(mURL, std::ifstream::binary);
1118     ASSERT_EQ(eleStream.is_open(), true);
1119     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1120                   kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0,
1121                   nFrames, compName, false);
1122     // Note: Assumes 200 ms is enough to end any decode call that started
1123     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1124                kPortIndexOutput, 200000);
1125     framesReceived = 0;
1126 
1127     // Seek to next key frame and start decoding till the end
1128     int index = nFrames;
1129     bool keyFrame = false;
1130     while (index < (int)Info.size()) {
1131         if ((Info[index].flags & OMX_BUFFERFLAG_SYNCFRAME) ==
1132             OMX_BUFFERFLAG_SYNCFRAME) {
1133             timestampUs = Info[index - 1].timestamp;
1134             keyFrame = true;
1135             break;
1136         }
1137         eleStream.ignore(Info[index].bytesCount);
1138         index++;
1139     }
1140     if (keyFrame) {
1141         decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
1142                       kPortIndexInput, kPortIndexOutput, eleStream, &Info,
1143                       index, Info.size() - index, compName, false);
1144     }
1145     // Note: Assumes 200 ms is enough to end any decode call that started
1146     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
1147                kPortIndexOutput, 200000);
1148     framesReceived = 0;
1149 
1150     // set state to idle
1151     changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
1152     // set state to executing
1153     changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
1154                             kPortIndexInput, kPortIndexOutput);
1155 }
1156 
main(int argc,char ** argv)1157 int main(int argc, char** argv) {
1158     gEnv = new ComponentTestEnvironment();
1159     ::testing::AddGlobalTestEnvironment(gEnv);
1160     ::testing::InitGoogleTest(&argc, argv);
1161     int status = gEnv->initFromOptions(argc, argv);
1162     if (status == 0) {
1163         status = RUN_ALL_TESTS();
1164         ALOGI("Test result = %d", status);
1165     }
1166     return status;
1167 }
1168