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