Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 23c658f1 authored by Ram Mohan M's avatar Ram Mohan M Committed by Zhuoyao Zhang
Browse files

Omx VTS tests

Bug: 32023356
Test: make vts.

preload elementary stream information during decoding

instead of using extractor to get the frame boundaries, frame
flags and timestamp information, they are read from a metadata
file in the resources directory on demand. Instead of doing it
on demand, we load the entire file information and use it. This
modification comes in handy for future test fixtures

Change-Id: I3a434018111eb66008f17c24b4c2c16d0db22ed1

bug fix: wait on input consumption

after queuing all the frames that need to be processed by
the component, the application continues its job of deinitializing
the component before ensuring all the inputs were decoded.
This is corrected.

Change-Id: I09a11fd5badabe2889ba243383145be07be51953

add end of stream test for audio decoder

component is provided an input with nFlags field set OMX_BUFFERFLAG_EOS.
the application expects this flag to be returned via one of its output
buffers. this flag is passed to the component at different timings to test
the robustness.

Change-Id: I00e3fdd5ef50d93f2620d8b0e9fc3c358de428d7

add timestamp deviation test for decoder components

the list of timestamps received from the component is
compared with the list provided to the component for any
differences

Change-Id: Ifcc16b7a00f58e1c1dfdba9f538d307ddcbfcc71

add option to configure resource files path

default location of resource files is /sdcard/media/. client can provide
choice of this location via the option -P.

example: VtsHalMediaOmxV1_0TargetVideoDecTest -C <component> -R <role> -P /sdcard/res/

Change-Id: Ib8d3af03c19a171e3bbb9839f7e331cbe576b24b

add flush test for audio & video dec components

while decoding a group of frames, flush call is made and it is
checked if all the i/o buffers are sent back to client. we then
seek to the next keyframe and test for decoding. monotonous
increase of timestamps is ensured.

Change-Id: Id48c76c157ebdfdefd3003e57519da3bd9715973
parent 76061d78
Loading
Loading
Loading
Loading
+19 −35
Original line number Diff line number Diff line
## Codec OMX Tests
## Omx Hal @ 1.0 tests ##
---
## Overview :
The scope of the tests presented here is not restricted solely to testing omx hal @ 1.0 API but also test to omx core functionality and to an extent omx components as well. The current directory contains the following folders: audio, common, component, master and video. Besides common all other folders contain test fixtures for testing AV decoder, encoder components. Common constitutes files that are used across by these test applications.

The current directory contains the following folders: audio, common, component, master
and video.
#### master :
Functionality of master is to enumerate all the omx components (and the roles it supports) available in android media framework.

Besides common, all other folders contain basic OMX unit tests for testing audio and video decoder-encoder
components. common constitutes files that are used across test applications.
usage: VtsHalMediaOmxV1\_0TargetMasterTest -I default

## master
Enumerates all the omx components (and their roles) available in android media framework.
#### component :
This folder includes test fixtures that tests aspects common to all omx compatible components. For instance, port enabling/disabling, enumerating port formats, state transitions, flush, ..., stay common to all components irrespective of the service they offer. Test fixtures are directed towards testing the omx core. Every standard OMX compatible component is expected to pass these tests.

Usage:
usage: VtsHalMediaOmxV1\_0TargetComponentTest -I default -C <comp name> -R <comp role>

VtsHalMediaOmxV1\_0TargetMasterTest -I default
#### audio :
This folder includes test fixtures associated with testing audio encoder and decoder components such as simple encoding of a raw clip or decoding of an elementary stream, end of stream test, timestamp deviations test, flush test and so on. These tests are aimed towards testing the plugin that connects the component to the omx core.

## component
This folder includes test fixtures that tests aspects common to all OMX compatible components. For instance, port enabling/disabling, enumerating port formats, state transitions, flush etc. stay common to all components irrespective of the service they offer. In a way this tests the OMX Core. Every standard OMX compatible component is expected to pass these tests.
usage:

VtsHalMediaOmxV1\_0TargetAudioDecTest -I default -C <comp name> -R audio_decoder.<comp class> -P /sdcard/media/

Usage:
VtsHalMediaOmxV1\_0TargetAudioEncTest -I default -C <comp name> -R audio_encoder.<comp class> -P /sdcard/media/

VtsHalMediaOmxV1\_0TargetComponentTest -I default -C <component name> -R <component role>
#### video :
This folder includes test fixtures associated with testing video encoder and decoder components such as simple encoding of a raw clip or decoding of an elementary stream, end of stream test, timestamp deviations test, flush test and so on. These tests are aimed towards testing the plugin that connects the component to the omx core.

## audio
This folder includes test fixtures associated with audio encoder/decoder components such as encoding/decoding, EOS test, timestamp test etc. These tests are aimed towards testing the component specific aspects.
usage:

Usage:
VtsHalMediaOmxV1\_0TargetVideoDecTest -I default -C <comp name> -R video_decoder.<comp class> -P /sdcard/media/

VtsHalMediaOmxV1\_0TargetAudioDecTest -I default -C <component name> -R audio_decoder.<class>

VtsHalMediaOmxV1\_0TargetAudioEncTest -I default -C <component name> -R audio_encoder.<class>

## video
This folder includes test fixtures associated with video encoder/decoder components like encoding/decoding, EOS test, timestamp test etc. These tests are aimed towards testing the component specific aspects.

Usage:

VtsHalMediaOmxV1\_0TargetVideoDecTest -I default -C <component name> -R video_decoder.<class>

VtsHalMediaOmxV1\_0TargetVideoEncTest -I default -C <component name> -R video_encoder.<class>

## notes
Every component shall be tested by two applications,

* ComponentTest.

* AudioDecTest/AudioEncTest/VideoDecTest/VideoEncTest depending on the component class.
VtsHalMediaOmxV1\_0TargetVideoEncTest -I default -C <comp name> -R video_encoder.<comp class> -P /sdcard/media/
+509 −137

File changed.

Preview size limit exceeded, changes collapsed.

+25 −28
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@ class ComponentTestEnvironment : public ::testing::Environment {
    virtual void SetUp() {}
    virtual void TearDown() {}

    ComponentTestEnvironment() : instance("default") {}
    ComponentTestEnvironment() : instance("default"), res("/sdcard/media/") {}

    void setInstance(const char* _instance) { instance = _instance; }

@@ -59,7 +59,7 @@ class ComponentTestEnvironment : public ::testing::Environment {

    void setRole(const char* _role) { role = _role; }

    void setQuirks(int _quirks) { quirks = _quirks; }
    void setRes(const char* _res) { res = _res; }

    const hidl_string getInstance() const { return instance; }

@@ -67,19 +67,19 @@ class ComponentTestEnvironment : public ::testing::Environment {

    const hidl_string getRole() const { return role; }

    int getQuirks() const { return quirks; }
    const hidl_string getRes() const { return res; }

    int initFromOptions(int argc, char** argv) {
        static struct option options[] = {
            {"instance", required_argument, 0, 'I'},
            {"component", required_argument, 0, 'C'},
            {"role", required_argument, 0, 'R'},
            {"quirks", required_argument, 0, 'Q'},
            {"res", required_argument, 0, 'P'},
            {0, 0, 0, 0}};

        while (true) {
            int index = 0;
            int c = getopt_long(argc, argv, "I:C:Q:R:", options, &index);
            int c = getopt_long(argc, argv, "I:C:R:P:", options, &index);
            if (c == -1) {
                break;
            }
@@ -91,12 +91,12 @@ class ComponentTestEnvironment : public ::testing::Environment {
                case 'C':
                    setComponent(optarg);
                    break;
                case 'Q':
                    setQuirks(atoi(optarg));
                    break;
                case 'R':
                    setRole(optarg);
                    break;
                case 'P':
                    setRes(optarg);
                    break;
                case '?':
                    break;
            }
@@ -109,8 +109,8 @@ class ComponentTestEnvironment : public ::testing::Environment {
                    "test options are:\n\n"
                    "-I, --instance: HAL instance to test\n"
                    "-C, --component: OMX component to test\n"
                    "-R, --Role: OMX component Role\n"
                    "-Q, --quirks: Component quirks\n",
                    "-R, --role: OMX component Role\n"
                    "-P, --res: Resource files directory location\n",
                    argv[optind ?: 1], argv[0]);
            return 2;
        }
@@ -121,12 +121,12 @@ class ComponentTestEnvironment : public ::testing::Environment {
    hidl_string instance;
    hidl_string component;
    hidl_string role;
    // to be removed when IOmxNode::setQuirks is removed
    int quirks;
    hidl_string res;
};

static ComponentTestEnvironment* gEnv = nullptr;

// audio encoder test fixture class
class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
   public:
    virtual void SetUp() override {
@@ -134,7 +134,7 @@ class AudioEncHidlTest : public ::testing::VtsHalHidlTargetTestBase {
        omx = ::testing::VtsHalHidlTargetTestBase::getService<IOmx>(
            gEnv->getInstance());
        ASSERT_NE(omx, nullptr);
        observer = new CodecObserver();
        observer = new CodecObserver([this](Message msg) { (void)msg; });
        ASSERT_NE(observer, nullptr);
        ASSERT_EQ(strncmp(gEnv->getComponent().c_str(), "OMX.", 4), 0)
            << "Invalid Component Name";
@@ -257,27 +257,21 @@ void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
}

// LookUpTable of clips and metadata for component testing
void GetURLForComponent(AudioEncHidlTest::standardComp comp,
                        const char** mURL) {
void GetURLForComponent(AudioEncHidlTest::standardComp comp, char* mURL) {
    struct CompToURL {
        AudioEncHidlTest::standardComp comp;
        const char* mURL;
    };
    static const CompToURL kCompToURL[] = {
        {AudioEncHidlTest::standardComp::aac,
         "/sdcard/media/bbb_raw_2ch_48khz_s16le.raw"},
        {AudioEncHidlTest::standardComp::amrnb,
         "/sdcard/media/bbb_raw_1ch_8khz_s16le.raw"},
        {AudioEncHidlTest::standardComp::amrwb,
         "/sdcard/media/bbb_raw_1ch_16khz_s16le.raw"},
        {AudioEncHidlTest::standardComp::flac,
         "/sdcard/media/bbb_raw_2ch_48khz_s16le.raw"},
        {AudioEncHidlTest::standardComp::aac, "bbb_raw_2ch_48khz_s16le.raw"},
        {AudioEncHidlTest::standardComp::amrnb, "bbb_raw_1ch_8khz_s16le.raw"},
        {AudioEncHidlTest::standardComp::amrwb, "bbb_raw_1ch_16khz_s16le.raw"},
        {AudioEncHidlTest::standardComp::flac, "bbb_raw_2ch_48khz_s16le.raw"},
    };

    *mURL = nullptr;
    for (size_t i = 0; i < sizeof(kCompToURL) / sizeof(kCompToURL[0]); ++i) {
        if (kCompToURL[i].comp == comp) {
            *mURL = kCompToURL[i].mURL;
            strcat(mURL, kCompToURL[i].mURL);
            return;
        }
    }
@@ -343,6 +337,7 @@ void encodeNFrames(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    }
}

// set component role
TEST_F(AudioEncHidlTest, SetRole) {
    description("Test Set Component Role");
    android::hardware::media::omx::V1_0::Status status;
@@ -350,6 +345,7 @@ TEST_F(AudioEncHidlTest, SetRole) {
    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}

// port format enumeration
TEST_F(AudioEncHidlTest, EnumeratePortFormat) {
    description("Test Component on Mandatory Port Parameters (Port Format)");
    android::hardware::media::omx::V1_0::Status status;
@@ -369,6 +365,7 @@ TEST_F(AudioEncHidlTest, EnumeratePortFormat) {
    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}

// test raw stream encode
TEST_F(AudioEncHidlTest, EncodeTest) {
    description("Tests Encode");
    android::hardware::media::omx::V1_0::Status status;
@@ -382,9 +379,9 @@ TEST_F(AudioEncHidlTest, EncodeTest) {
        kPortIndexInput = params.nStartPortNumber;
        kPortIndexOutput = kPortIndexInput + 1;
    }
    const char* mURL = nullptr;
    GetURLForComponent(compName, &mURL);
    EXPECT_NE(mURL, nullptr);
    char mURL[512];
    strcpy(mURL, gEnv->getRes().c_str());
    GetURLForComponent(compName, mURL);

    std::ifstream eleStream;
    eleStream.open(mURL, std::ifstream::binary);
+27 −25
Original line number Diff line number Diff line
@@ -235,42 +235,42 @@ size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray) {
    return buffArray->size();
}

// dispatch buffer to input port
void dispatchInputBuffer(sp<IOmxNode> omxNode,
// dispatch buffer to output port
void dispatchOutputBuffer(sp<IOmxNode> omxNode,
                          android::Vector<BufferInfo>* buffArray,
                         size_t bufferIndex, int bytesCount, uint32_t flags,
                         uint64_t timestamp) {
                          size_t bufferIndex) {
    android::hardware::media::omx::V1_0::Status status;
    CodecBuffer t;
    t.sharedMemory = android::hardware::hidl_memory();
    t.nativeHandle = android::hardware::hidl_handle();
    t.type = CodecBuffer::Type::PRESET;
    t.attr.preset.rangeOffset = 0;
    t.attr.preset.rangeLength = bytesCount;
    t.attr.preset.rangeLength = 0;
    native_handle_t* fenceNh = native_handle_create(0, 0);
    ASSERT_NE(fenceNh, nullptr);
    status = omxNode->emptyBuffer((*buffArray)[bufferIndex].id, t, flags,
                                  timestamp, fenceNh);
    status = omxNode->fillBuffer((*buffArray)[bufferIndex].id, t, fenceNh);
    native_handle_close(fenceNh);
    native_handle_delete(fenceNh);
    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
    buffArray->editItemAt(bufferIndex).owner = component;
}

// dispatch buffer to output port
void dispatchOutputBuffer(sp<IOmxNode> omxNode,
// dispatch buffer to input port
void dispatchInputBuffer(sp<IOmxNode> omxNode,
                         android::Vector<BufferInfo>* buffArray,
                          size_t bufferIndex) {
                         size_t bufferIndex, int bytesCount, uint32_t flags,
                         uint64_t timestamp) {
    android::hardware::media::omx::V1_0::Status status;
    CodecBuffer t;
    t.sharedMemory = android::hardware::hidl_memory();
    t.nativeHandle = android::hardware::hidl_handle();
    t.type = CodecBuffer::Type::PRESET;
    t.attr.preset.rangeOffset = 0;
    t.attr.preset.rangeLength = 0;
    t.attr.preset.rangeLength = bytesCount;
    native_handle_t* fenceNh = native_handle_create(0, 0);
    ASSERT_NE(fenceNh, nullptr);
    status = omxNode->fillBuffer((*buffArray)[bufferIndex].id, t, fenceNh);
    status = omxNode->emptyBuffer((*buffArray)[bufferIndex].id, t, flags,
                                  timestamp, fenceNh);
    native_handle_close(fenceNh);
    native_handle_delete(fenceNh);
    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
@@ -281,7 +281,7 @@ void dispatchOutputBuffer(sp<IOmxNode> omxNode,
void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                android::Vector<BufferInfo>* iBuffer,
                android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
                OMX_U32 kPortIndexOutput) {
                OMX_U32 kPortIndexOutput, int64_t timeoutUs) {
    android::hardware::media::omx::V1_0::Status status;
    Message msg;

@@ -289,7 +289,7 @@ void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
                                  kPortIndexInput);
    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
    status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
    status = observer->dequeueMessage(&msg, timeoutUs, iBuffer, oBuffer);
    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
    ASSERT_EQ(msg.type, Message::Type::EVENT);
    ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
@@ -304,7 +304,7 @@ void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
    status = omxNode->sendCommand(toRawCommandType(OMX_CommandFlush),
                                  kPortIndexOutput);
    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
    status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
    status = observer->dequeueMessage(&msg, timeoutUs, iBuffer, oBuffer);
    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
    ASSERT_EQ(msg.type, Message::Type::EVENT);
    ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
@@ -317,10 +317,10 @@ void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
}

Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
    sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE encoding) {
    sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding) {
    OMX_U32 index = 0;
    OMX_AUDIO_PARAM_PORTFORMATTYPE portFormat;
    std::vector<OMX_AUDIO_CODINGTYPE> eEncoding;
    std::vector<OMX_AUDIO_CODINGTYPE> arrEncoding;
    android::hardware::media::omx::V1_0::Status status;

    while (1) {
@@ -328,24 +328,26 @@ Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
        status = getPortParam(omxNode, OMX_IndexParamAudioPortFormat, portIndex,
                              &portFormat);
        if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
        eEncoding.push_back(portFormat.eEncoding);
        arrEncoding.push_back(portFormat.eEncoding);
        index++;
        if (index == 512) {
            // enumerated way too many formats, highly unusual for this to
            // happen.
            EXPECT_LE(index, 512U)
                << "Expecting OMX_ErrorNoMore but not received";
            break;
        }
    }
    if (!index) return status;
    for (index = 0; index < eEncoding.size(); index++) {
        if (eEncoding[index] == encoding) {
            portFormat.eEncoding = eEncoding[index];
    for (index = 0; index < arrEncoding.size(); index++) {
        if (arrEncoding[index] == eEncoding) {
            portFormat.eEncoding = arrEncoding[index];
            break;
        }
    }
    if (index == eEncoding.size()) {
    if (index == arrEncoding.size()) {
        ALOGI("setting default Port format");
        portFormat.eEncoding = eEncoding[0];
        portFormat.eEncoding = arrEncoding[0];
    }
    // In setParam call nIndex shall be ignored as per omx-il specification.
    // see how this holds up by corrupting nIndex
+6 −6
Original line number Diff line number Diff line
@@ -48,22 +48,22 @@ void changeStateExecutetoIdle(sp<IOmxNode> omxNode, sp<CodecObserver> observer,

size_t getEmptyBufferID(android::Vector<BufferInfo>* buffArray);

void dispatchOutputBuffer(sp<IOmxNode> omxNode,
                          android::Vector<BufferInfo>* buffArray,
                          size_t bufferIndex);

void dispatchInputBuffer(sp<IOmxNode> omxNode,
                         android::Vector<BufferInfo>* buffArray,
                         size_t bufferIndex, int bytesCount, uint32_t flags,
                         uint64_t timestamp);

void dispatchOutputBuffer(sp<IOmxNode> omxNode,
                          android::Vector<BufferInfo>* buffArray,
                          size_t bufferIndex);

void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                android::Vector<BufferInfo>* iBuffer,
                android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
                OMX_U32 kPortIndexOutput);
                OMX_U32 kPortIndexOutput, int64_t timeoutUs = DEFAULT_TIMEOUT);

Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
    sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE encoding);
    sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding);

Return<android::hardware::media::omx::V1_0::Status> setRole(
    sp<IOmxNode> omxNode, const char* role);
Loading