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