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

Commit 92fb9ab6 authored by Ram Mohan M's avatar Ram Mohan M Committed by Zhuoyao Zhang
Browse files

Omx vts tests.

Bug:32023356
Test: make vts.

bug fix : fix issues in port reconfiguration

soft and vendor omx components communicate differently. The existing
design doesnt cover this. This is now fixed

Change-Id: I898e60c93961f468e749ab5f13db996c5fd53967

add support for additional color formats

tested encoder for bgra & 420sp color format inputs.
added code to get/set encoder latency.
some more necessary code cleanup.

Change-Id: I05b79d0a7706e20afaf91c88caf3e523c98b4540

IOmxBufferSource callback tests

Change-Id: I2826597c6ab110a0bf52290e3c52ff3fb3c6ea23
parent 8c71c852
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@ Functionality of master is to enumerate all the omx components (and the roles it
usage: VtsHalMediaOmxV1\_0TargetMasterTest -I default

#### 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.
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 here are directed towards testing these (omx core). Every standard OMX compatible component is expected to pass these tests.

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

@@ -31,3 +31,4 @@ VtsHalMediaOmxV1\_0TargetVideoDecTest -I default -C <comp name> -R video_decoder

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

While tesing audio/video encoder, decoder components, test fixtures require input files. These input are files are present in the folder 'res'. Before running the tests all the files in 'res' have to be placed in '/media/sdcard/' or a path of your choice and this path needs to be provided as an argument to the test application
 No newline at end of file
+9 −2
Original line number Diff line number Diff line
@@ -425,8 +425,15 @@ void testEOS(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
        Message msg;
        status =
            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
        EXPECT_EQ(status,
                  android::hardware::media::omx::V1_0::Status::TIMED_OUT);
        if (status == android::hardware::media::omx::V1_0::Status::OK) {
            if (msg.data.eventData.event == OMX_EventBufferFlag) {
                // soft omx components donot send this, we will just ignore it
                // for now
            } else {
                // something unexpected happened
                EXPECT_TRUE(false);
            }
        }
        if (eosFlag == true) break;
    }
    // test for flag
+24 −6
Original line number Diff line number Diff line
@@ -214,7 +214,7 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                               strlen(gEnv->getComponent().c_str()) - suffixLen,
                           ".secure");
        if (isSecure) disableTest = true;
        if (disableTest) std::cerr << "[          ] Warning !  Test Disabled\n";
        if (disableTest) std::cout << "[          ] Warning !  Test Disabled\n";
    }

    virtual void TearDown() override {
@@ -257,7 +257,7 @@ class VideoDecHidlTest : public ::testing::VtsHalHidlTargetTestBase {
                            EXPECT_EQ(tsHit, true)
                                << "TimeStamp not recognized";
                        } else {
                            std::cerr
                            std::cout
                                << "[          ] Warning ! Received non-zero "
                                   "output / TimeStamp not recognized \n";
                        }
@@ -478,7 +478,8 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,

    if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
        ASSERT_EQ(msg.data.eventData.data1, kPortIndexOutput);
        if (msg.data.eventData.data2 == 0) {
        if (msg.data.eventData.data2 == OMX_IndexParamPortDefinition ||
            msg.data.eventData.data2 == 0) {
            status = omxNode->sendCommand(
                toRawCommandType(OMX_CommandPortDisable), kPortIndexOutput);
            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
@@ -532,6 +533,20 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,

                allocatePortBuffers(omxNode, oBuffer, kPortIndexOutput,
                                    oPortMode);
                if (oPortMode != PortMode::PRESET_BYTE_BUFFER) {
                    OMX_PARAM_PORTDEFINITIONTYPE portDef;

                    status = getPortParam(omxNode, OMX_IndexParamPortDefinition,
                                          kPortIndexOutput, &portDef);
                    ASSERT_EQ(
                        status,
                        ::android::hardware::media::omx::V1_0::Status::OK);
                    allocateGraphicBuffers(omxNode, kPortIndexOutput, oBuffer,
                                           portDef.format.video.nFrameWidth,
                                           portDef.format.video.nFrameHeight,
                                           &portDef.format.video.nStride,
                                           portDef.nBufferCountActual);
                }
                status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
                                                  iBuffer, oBuffer);
                ASSERT_EQ(status,
@@ -549,16 +564,19 @@ void portReconfiguration(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
            }
        } else if (msg.data.eventData.data2 ==
                   OMX_IndexConfigCommonOutputCrop) {
            std::cerr << "[          ] Warning ! OMX_EventPortSettingsChanged/ "
            std::cout << "[          ] Warning ! OMX_EventPortSettingsChanged/ "
                         "OMX_IndexConfigCommonOutputCrop not handled \n";
        } else if (msg.data.eventData.data2 == OMX_IndexVendorStartUnused + 3) {
            std::cerr << "[          ] Warning ! OMX_EventPortSettingsChanged/ "
            std::cout << "[          ] Warning ! OMX_EventPortSettingsChanged/ "
                         "kDescribeColorAspectsIndex not handled \n";
        }
    } else if (msg.data.eventData.event == OMX_EventError) {
        std::cerr << "[          ] Warning ! OMX_EventError/ "
        std::cout << "[          ] Warning ! OMX_EventError/ "
                     "Decode Frame Call might be failed \n";
        return;
    } else if (msg.data.eventData.event == OMX_EventBufferFlag) {
        // soft omx components donot send this, we will just ignore it
        // for now
    } else {
        // something unexpected happened
        ASSERT_TRUE(false);
+246 −42
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <android/hardware/graphics/mapper/2.0/types.h>
#include <android/hardware/media/omx/1.0/IGraphicBufferSource.h>
#include <android/hardware/media/omx/1.0/IOmx.h>
#include <android/hardware/media/omx/1.0/IOmxBufferSource.h>
#include <android/hardware/media/omx/1.0/IOmxNode.h>
#include <android/hardware/media/omx/1.0/IOmxObserver.h>
#include <android/hardware/media/omx/1.0/types.h>
@@ -39,6 +40,7 @@ using ::android::hardware::graphics::bufferqueue::V1_0::IProducerListener;
using ::android::hardware::graphics::common::V1_0::BufferUsage;
using ::android::hardware::graphics::common::V1_0::PixelFormat;
using ::android::hardware::media::omx::V1_0::IGraphicBufferSource;
using ::android::hardware::media::omx::V1_0::IOmxBufferSource;
using ::android::hardware::media::omx::V1_0::IOmx;
using ::android::hardware::media::omx::V1_0::IOmxObserver;
using ::android::hardware::media::omx::V1_0::IOmxNode;
@@ -345,6 +347,82 @@ struct CodecProducerListener : public IProducerListener {
    android::Mutex bufferLock;
};

// Mock IOmxBufferSource class. GraphicBufferSource.cpp in libstagefright/omx/
// implements this class. Below is dummy class introduced to test if callback
// functions are actually being called or not
struct DummyBufferSource : public IOmxBufferSource {
   public:
    DummyBufferSource(sp<IOmxNode> node) {
        callback = 0;
        executing = false;
        omxNode = node;
    }
    virtual Return<void> onOmxExecuting();
    virtual Return<void> onOmxIdle();
    virtual Return<void> onOmxLoaded();
    virtual Return<void> onInputBufferAdded(uint32_t buffer);
    virtual Return<void> onInputBufferEmptied(
        uint32_t buffer, const ::android::hardware::hidl_handle& fence);

    int callback;
    bool executing;
    sp<IOmxNode> omxNode;
    android::Vector<BufferInfo> iBuffer, oBuffer;
};

Return<void> DummyBufferSource::onOmxExecuting() {
    executing = true;
    callback |= 0x1;
    size_t index;
    // Fetch a client owned input buffer and send an EOS
    if ((index = getEmptyBufferID(&iBuffer)) < iBuffer.size()) {
        android::hardware::media::omx::V1_0::Status status;
        CodecBuffer t = iBuffer[index].omxBuffer;
        t.type = CodecBuffer::Type::ANW_BUFFER;
        native_handle_t* fenceNh = native_handle_create(0, 0);
        EXPECT_NE(fenceNh, nullptr);
        status = omxNode->emptyBuffer(iBuffer[index].id, t, OMX_BUFFERFLAG_EOS,
                                      0, fenceNh);
        native_handle_close(fenceNh);
        native_handle_delete(fenceNh);
        EXPECT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
        iBuffer.editItemAt(index).owner = component;
    }
    return Void();
};

Return<void> DummyBufferSource::onOmxIdle() {
    callback |= 0x2;
    executing = false;
    return Void();
};

Return<void> DummyBufferSource::onOmxLoaded() {
    callback |= 0x4;
    return Void();
};

Return<void> DummyBufferSource::onInputBufferAdded(uint32_t buffer) {
    (void)buffer;
    EXPECT_EQ(executing, false);
    callback |= 0x8;
    return Void();
};

Return<void> DummyBufferSource::onInputBufferEmptied(
    uint32_t buffer, const ::android::hardware::hidl_handle& fence) {
    (void)fence;
    callback |= 0x10;
    size_t i;
    for (i = 0; i < iBuffer.size(); i++) {
        if (iBuffer[i].id == buffer) {
            iBuffer.editItemAt(i).owner = client;
            break;
        }
    }
    return Void();
};

// request VOP refresh
void requestIDR(sp<IOmxNode> omxNode, OMX_U32 portIndex) {
    android::hardware::media::omx::V1_0::Status status;
@@ -419,6 +497,27 @@ void setRefreshPeriod(sp<IOmxNode> omxNode, OMX_U32 portIndex,
        std::cerr << "[          ] Warning ! unable to set Refresh Period \n";
}

void setLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t latency) {
    android::hardware::media::omx::V1_0::Status status;
    OMX_PARAM_U32TYPE param;
    param.nU32 = (OMX_U32)latency;
    status = setPortConfig(omxNode, (OMX_INDEXTYPE)OMX_IndexConfigLatency,
                           portIndex, &param);
    if (status != ::android::hardware::media::omx::V1_0::Status::OK)
        std::cerr << "[          ] Warning ! unable to set latency\n";
}

void getLatency(sp<IOmxNode> omxNode, OMX_U32 portIndex, uint32_t* latency) {
    android::hardware::media::omx::V1_0::Status status;
    OMX_PARAM_U32TYPE param;
    status = getPortConfig(omxNode, (OMX_INDEXTYPE)OMX_IndexConfigLatency,
                           portIndex, &param);
    if (status != ::android::hardware::media::omx::V1_0::Status::OK)
        std::cerr << "[          ] Warning ! unable to get latency\n";
    else
        *latency = param.nU32;
}

// Set Default port param.
void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
                         OMX_VIDEO_CODINGTYPE eCompressionFormat,
@@ -586,7 +685,7 @@ int colorFormatConversion(BufferInfo* buffer, void* buff, PixelFormat format,
                  android::hardware::graphics::mapper::V2_0::Error::NONE);
        if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
            return 1;
    } else if (format == PixelFormat::YCBCR_420_888) {
    } else {
        void* data;
        mapper->lock(buff, buffer->omxBuffer.attr.anwBuffer.usage, rect, fence,
                     [&](android::hardware::graphics::mapper::V2_0::Error _e,
@@ -599,6 +698,7 @@ int colorFormatConversion(BufferInfo* buffer, void* buff, PixelFormat format,
        if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
            return 1;

        if (format == PixelFormat::YCBCR_420_888) {
            ycbcrLayout.chromaStep = 1;
            ycbcrLayout.yStride = buffer->omxBuffer.attr.anwBuffer.stride;
            ycbcrLayout.cStride = ycbcrLayout.yStride >> 1;
@@ -626,6 +726,48 @@ int colorFormatConversion(BufferInfo* buffer, void* buff, PixelFormat format,
                if (eleStream.gcount() != rect.width >> 1) return 1;
                ipBuffer += ycbcrLayout.cStride;
            }
        } else if (format == PixelFormat::YCRCB_420_SP) {
            ycbcrLayout.chromaStep = 2;
            ycbcrLayout.yStride = buffer->omxBuffer.attr.anwBuffer.stride;
            ycbcrLayout.cStride = ycbcrLayout.yStride;
            ycbcrLayout.y = data;
            ycbcrLayout.cr = static_cast<char*>(ycbcrLayout.y) +
                             (ycbcrLayout.yStride * rect.height);
            ycbcrLayout.cb = static_cast<char*>(ycbcrLayout.cr) + 1;

            char* ipBuffer = static_cast<char*>(ycbcrLayout.y);
            for (size_t y = rect.height; y > 0; --y) {
                eleStream.read(ipBuffer, rect.width);
                if (eleStream.gcount() != rect.width) return 1;
                ipBuffer += ycbcrLayout.yStride;
            }
            ipBuffer = static_cast<char*>(ycbcrLayout.cb);
            for (size_t y = rect.height >> 1; y > 0; --y) {
                for (int32_t x = 0; x<rect.width>> 1; ++x) {
                    eleStream.read(&ipBuffer[2 * x], 1);
                    if (eleStream.gcount() != 1) return 1;
                }
                ipBuffer += ycbcrLayout.cStride;
            }
            ipBuffer = static_cast<char*>(ycbcrLayout.cr);
            for (size_t y = rect.height >> 1; y > 0; --y) {
                for (int32_t x = 0; x<rect.width>> 1; ++x) {
                    eleStream.read(&ipBuffer[2 * x], 1);
                    if (eleStream.gcount() != 1) return 1;
                }
                ipBuffer += ycbcrLayout.cStride;
            }
        } else if (format == PixelFormat::BGRA_8888) {
            char* ipBuffer = static_cast<char*>(data);
            for (size_t y = rect.height; y > 0; --y) {
                eleStream.read(ipBuffer, rect.width * 4);
                if (eleStream.gcount() != rect.width * 4) return 1;
                ipBuffer += buffer->omxBuffer.attr.anwBuffer.stride * 4;
            }
        } else {
            EXPECT_TRUE(false) << "un expected pixel format";
            return 1;
        }

        mapper->unlock(buff,
                       [&](android::hardware::graphics::mapper::V2_0::Error _e,
@@ -637,9 +779,6 @@ int colorFormatConversion(BufferInfo* buffer, void* buff, PixelFormat format,
                  android::hardware::graphics::mapper::V2_0::Error::NONE);
        if (error != android::hardware::graphics::mapper::V2_0::Error::NONE)
            return 1;
    } else {
        EXPECT_TRUE(false) << "un expected pixel format";
        return 1;
    }

    return 0;
@@ -959,6 +1098,63 @@ TEST_F(VideoEncHidlTest, EnumeratePortFormat) {
    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
}

// Test IOmxBufferSource CallBacks
TEST_F(VideoEncHidlTest, BufferSourceCallBacks) {
    description("Test IOmxBufferSource CallBacks");
    if (disableTest) return;
    android::hardware::media::omx::V1_0::Status status;
    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
    status = setRole(omxNode, gEnv->getRole().c_str());
    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
    OMX_PORT_PARAM_TYPE params;
    status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
        ASSERT_EQ(params.nPorts, 2U);
        kPortIndexInput = params.nStartPortNumber;
        kPortIndexOutput = kPortIndexInput + 1;
    }

    // Configure input port
    uint32_t nFrameWidth = 352;
    uint32_t nFrameHeight = 288;
    uint32_t xFramerate = (30U << 16);
    OMX_COLOR_FORMATTYPE eColorFormat = OMX_COLOR_FormatAndroidOpaque;
    setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
                 xFramerate, eColorFormat);

    sp<DummyBufferSource> buffersource = new DummyBufferSource(omxNode);
    EXPECT_NE(buffersource, nullptr);
    status = omxNode->setInputSurface(buffersource);
    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);

    // set port mode
    PortMode portMode[2];
    portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
    portMode[1] = PortMode::PRESET_BYTE_BUFFER;
    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);

    // set state to idle
    changeStateLoadedtoIdle(omxNode, observer, &buffersource->iBuffer,
                            &buffersource->oBuffer, kPortIndexInput,
                            kPortIndexOutput, portMode);
    // set state to executing
    changeStateIdletoExecute(omxNode, observer);
    testEOS(omxNode, observer, &buffersource->iBuffer, &buffersource->oBuffer,
            false, eosFlag);
    // set state to idle
    changeStateExecutetoIdle(omxNode, observer, &buffersource->iBuffer,
                             &buffersource->oBuffer);
    // set state to executing
    changeStateIdletoLoaded(omxNode, observer, &buffersource->iBuffer,
                            &buffersource->oBuffer, kPortIndexInput,
                            kPortIndexOutput);
    // test for callbacks
    EXPECT_EQ(buffersource->callback, 31);
}

// test raw stream encode (input is byte buffers)
TEST_F(VideoEncHidlTest, EncodeTest) {
    description("Test Encode");
@@ -1023,6 +1219,10 @@ TEST_F(VideoEncHidlTest, EncodeTest) {
    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);

    uint32_t latency = 0;
    setLatency(omxNode, kPortIndexInput, latency);
    getLatency(omxNode, kPortIndexInput, &latency);

    android::Vector<BufferInfo> iBuffer, oBuffer;

    // set state to idle
@@ -1086,12 +1286,6 @@ TEST_F(VideoEncHidlTest, EncodeTestBufferMetaModes) {
    ASSERT_NE(producer, nullptr);
    ASSERT_NE(source, nullptr);

    // Do setInputSurface()
    // enable MetaMode on input port
    status = source->configure(
        omxNode, android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN);
    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);

    // setMaxDequeuedBufferCount
    int32_t returnval;
    int32_t value;
@@ -1125,6 +1319,12 @@ TEST_F(VideoEncHidlTest, EncodeTestBufferMetaModes) {
                          kPortIndexInput, &portDef);
    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);

    // Do setInputSurface()
    // enable MetaMode on input port
    status = source->configure(
        omxNode, android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN);
    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);

    // set port mode
    PortMode portMode[2];
    portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;
@@ -1138,6 +1338,10 @@ TEST_F(VideoEncHidlTest, EncodeTestBufferMetaModes) {
    strcpy(mURL, gEnv->getRes().c_str());
    GetURLForComponent(mURL);

    uint32_t latency = 0;
    setLatency(omxNode, kPortIndexInput, latency);
    getLatency(omxNode, kPortIndexInput, &latency);

    std::ifstream eleStream;

    status = source->setSuspend(false, 0);
@@ -1232,12 +1436,6 @@ TEST_F(VideoEncHidlTest, EncodeTestEOS) {
    ASSERT_NE(producer, nullptr);
    ASSERT_NE(source, nullptr);

    // Do setInputSurface()
    // enable MetaMode on input port
    status = source->configure(
        omxNode, android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN);
    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);

    // setMaxDequeuedBufferCount
    int32_t returnval;
    int32_t value;
@@ -1271,6 +1469,12 @@ TEST_F(VideoEncHidlTest, EncodeTestEOS) {
                          kPortIndexInput, &portDef);
    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);

    // Do setInputSurface()
    // enable MetaMode on input port
    status = source->configure(
        omxNode, android::hardware::graphics::common::V1_0::Dataspace::UNKNOWN);
    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);

    // set port mode
    PortMode portMode[2];
    portMode[0] = PortMode::DYNAMIC_ANW_BUFFER;