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
32using ::android::hardware::media::omx::V1_0::IOmx;
33using ::android::hardware::media::omx::V1_0::IOmxObserver;
34using ::android::hardware::media::omx::V1_0::IOmxNode;
35using ::android::hardware::media::omx::V1_0::Message;
36using ::android::hardware::media::omx::V1_0::CodecBuffer;
37using ::android::hardware::media::omx::V1_0::PortMode;
38using ::android::hidl::allocator::V1_0::IAllocator;
39using ::android::hidl::memory::V1_0::IMemory;
40using ::android::hidl::memory::V1_0::IMapper;
41using ::android::hardware::Return;
42using ::android::hardware::Void;
43using ::android::hardware::hidl_vec;
44using ::android::hardware::hidl_string;
45using ::android::sp;
46
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>
52
53// A class for test environment setup
54class ComponentTestEnvironment : public ::testing::Environment {
55   public:
56    virtual void SetUp() {}
57    virtual void TearDown() {}
58
59    ComponentTestEnvironment() : instance("default"), res("/sdcard/media/") {}
60
61    void setInstance(const char* _instance) { instance = _instance; }
62
63    void setComponent(const char* _component) { component = _component; }
64
65    void setRole(const char* _role) { role = _role; }
66
67    void setRes(const char* _res) { res = _res; }
68
69    const hidl_string getInstance() const { return instance; }
70
71    const hidl_string getComponent() const { return component; }
72
73    const hidl_string getRole() const { return role; }
74
75    const hidl_string getRes() const { return res; }
76
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}};
84
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            }
91
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        }
109
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    }
124
125   private:
126    hidl_string instance;
127    hidl_string component;
128    hidl_string role;
129    hidl_string res;
130};
131
132static ComponentTestEnvironment* gEnv = nullptr;
133
134// audio decoder test fixture class
135class 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    }
146
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    }
230
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    }
242
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    }
300
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    };
316
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;
328
329   protected:
330    static void description(const std::string& description) {
331        RecordProperty("description", description);
332    }
333};
334
335// Set Default port param.
336void 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;
343
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);
348
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);
354
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    }
367}
368
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.
373void 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;
379
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    }
461}
462
463// LookUpTable of clips and metadata for component testing
464void 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    };
502
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    }
510}
511
512// port settings reconfiguration during runtime. reconfigures sample rate and
513// number
514typedef struct {
515    OMX_AUDIO_CODINGTYPE eEncoding;
516    AudioDecHidlTest::standardComp comp;
517} packedArgs;
518void 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;
528
529    if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
530        ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
531
532        status = omxNode->sendCommand(toRawCommandType(OMX_CommandPortDisable),
533                                      kPortIndexOutput);
534        ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
535
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);
555
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            }
573
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);
579
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);
585
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);
594
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    }
606}
607
608// blocking call to ensures application to Wait till all the inputs are consumed
609void 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;
618
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;
638
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    }
647}
648
649// Decode N Frames
650void 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;
664
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        }
678
679        if (frameID == (int)Info->size() || frameID == (offset + range)) break;
680
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    }
719}
720
721// set component role
722TEST_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);
728}
729
730// port format enumeration
731TEST_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);
749}
750
751// test port settings reconfiguration, elementary stream decode and timestamp
752// deviation
753TEST_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);
771
772    std::ifstream eleStream, eleInfo;
773
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();
790
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    }
808
809    android::Vector<BufferInfo> iBuffer, oBuffer;
810
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));
839}
840
841// end of sequence test
842TEST_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    }
856
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    }
874
875    android::Vector<BufferInfo> iBuffer, oBuffer;
876
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));
883
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;
894
895    // set state to idle
896    ASSERT_NO_FATAL_FAILURE(
897        changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer));
898
899    // set state to executing
900    ASSERT_NO_FATAL_FAILURE(changeStateIdletoLoaded(omxNode, observer, &iBuffer,
901                                                    &oBuffer, kPortIndexInput,
902                                                    kPortIndexOutput));
903}
904
905// end of sequence test
906TEST_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);
924
925    std::ifstream eleStream, eleInfo;
926
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();
940
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    }
958
959    android::Vector<BufferInfo> iBuffer, oBuffer;
960
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));
967
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;
990
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;
1009
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));
1017}
1018
1019// end of sequence test
1020TEST_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);
1038
1039    std::ifstream eleStream, eleInfo;
1040
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();
1054
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    }
1072
1073    android::Vector<BufferInfo> iBuffer, oBuffer;
1074
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));
1081
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;
1101
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));
1109}
1110
1111// test input/output port flush
1112TEST_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);
1130
1131    std::ifstream eleStream, eleInfo;
1132
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();
1146
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    }
1164
1165    android::Vector<BufferInfo> iBuffer, oBuffer;
1166
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));
1173
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;
1186
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;
1209
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));
1217}
1218
1219int 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;
1229}
1230