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

Commit 3cc7fe17 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 6535363 from 66ca5761 to mainline-release

Change-Id: I1169bd941529476f70f06d052e64acf2e03a2a34
parents 9b2e60e3 66ca5761
Loading
Loading
Loading
Loading
+114 −0
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ using android::C2AllocatorIon;
static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
        kDecodeTestParameters;

static std::vector<std::tuple<std::string, std::string, std::string>> kCsdFlushTestParameters;

// Resource directory
static std::string sResourceDir = "";

@@ -831,6 +833,109 @@ TEST_P(Codec2AudioDecHidlTest, DecodeTestEmptyBuffersInserted) {
    ASSERT_EQ(mComponent->stop(), C2_OK);
}

class Codec2AudioDecCsdInputTests
    : public Codec2AudioDecHidlTestBase,
      public ::testing::WithParamInterface<std::tuple<std::string, std::string, std::string>> {
    void getParams() {
        mInstanceName = std::get<0>(GetParam());
        mComponentName = std::get<1>(GetParam());
    }
};

// Test the codecs for the following
// start - csd - data… - (with/without)flush - data… - flush - data…
TEST_P(Codec2AudioDecCsdInputTests, CSDFlushTest) {
    description("Tests codecs for flush at different states");
    if (mDisableTest) GTEST_SKIP() << "Test is disabled";

    char mURL[512], info[512];
    android::Vector<FrameInfo> Info;

    strcpy(mURL, sResourceDir.c_str());
    strcpy(info, sResourceDir.c_str());
    GetURLForComponent(mCompName, mURL, info);
    if (!strcmp(mURL, sResourceDir.c_str())) {
        ALOGV("EMPTY INPUT sResourceDir.c_str() %s mURL  %s ", sResourceDir.c_str(), mURL);
        return;
    }
    ALOGV("mURL : %s", mURL);

    int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
    ASSERT_GE(numCsds, 0) << "Error in parsing input info file";

    int32_t bitStreamInfo[2] = {0};
    if (mCompName == raw) {
        bitStreamInfo[0] = 8000;
        bitStreamInfo[1] = 1;
    } else {
        ASSERT_NO_FATAL_FAILURE(getInputChannelInfo(mComponent, mCompName, bitStreamInfo));
    }
    if (!setupConfigParam(mComponent, bitStreamInfo)) {
        std::cout << "[   WARN   ] Test Skipped \n";
        return;
    }

    ASSERT_EQ(mComponent->start(), C2_OK);
    std::ifstream eleStream;
    eleStream.open(mURL, std::ifstream::binary);
    ASSERT_EQ(eleStream.is_open(), true);

    bool signalEOS = false;
    bool flushCsd = !std::get<2>(GetParam()).compare("true");
    ALOGV("sending %d csd data ", numCsds);
    int framesToDecode = numCsds;
    ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
                                          mFlushedIndices, mLinearPool, eleStream, &Info, 0,
                                          framesToDecode, false));

    c2_status_t err = C2_OK;
    std::list<std::unique_ptr<C2Work>> flushedWork;
    if (numCsds && flushCsd) {
        // We wait for all the CSD buffers to get consumed.
        // Once we have received all CSD work back, we call flush
        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);

        err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
        ASSERT_EQ(err, C2_OK);
        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
                               MAX_INPUT_BUFFERS - flushedWork.size());
        ASSERT_NO_FATAL_FAILURE(
                verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
        ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
        oBufferMetaData.clear();
    }

    int offset = framesToDecode;
    while (1) {
        framesToDecode = c2_min(FLUSH_INTERVAL, (int)Info.size() - offset);
        if (framesToDecode < FLUSH_INTERVAL) signalEOS = true;
        ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
                                              mFlushedIndices, mLinearPool, eleStream, &Info,
                                              offset, framesToDecode, signalEOS));
        offset += framesToDecode;
        err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
        ASSERT_EQ(err, C2_OK);
        // blocking call to ensures application to Wait till remaining
        // 'non-flushed' inputs are consumed
        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
                               MAX_INPUT_BUFFERS - flushedWork.size());
        ASSERT_NO_FATAL_FAILURE(
                verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
        ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
        if (signalEOS || offset >= (int)Info.size()) {
            break;
        }
    }
    if (!signalEOS) {
        ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
                                                C2FrameData::FLAG_END_OF_STREAM, false));
        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
    }
    eleStream.close();
    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
    ASSERT_EQ(mComponent->stop(), C2_OK);
}

INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioDecHidlTest, testing::ValuesIn(kTestParameters),
                         android::hardware::PrintInstanceTupleNameToString<>);

@@ -839,6 +944,10 @@ INSTANTIATE_TEST_SUITE_P(StreamIndexAndEOS, Codec2AudioDecDecodeTest,
                         testing::ValuesIn(kDecodeTestParameters),
                         android::hardware::PrintInstanceTupleNameToString<>);

INSTANTIATE_TEST_SUITE_P(CsdInputs, Codec2AudioDecCsdInputTests,
                         testing::ValuesIn(kCsdFlushTestParameters),
                         android::hardware::PrintInstanceTupleNameToString<>);

}  // anonymous namespace

int main(int argc, char** argv) {
@@ -852,6 +961,11 @@ int main(int argc, char** argv) {
                std::make_tuple(std::get<0>(params), std::get<1>(params), "1", "false"));
        kDecodeTestParameters.push_back(
                std::make_tuple(std::get<0>(params), std::get<1>(params), "1", "true"));

        kCsdFlushTestParameters.push_back(
                std::make_tuple(std::get<0>(params), std::get<1>(params), "true"));
        kCsdFlushTestParameters.push_back(
                std::make_tuple(std::get<0>(params), std::get<1>(params), "false"));
    }

    // Set the resource directory based on command line args.
+216 −0
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ class Codec2AudioEncHidlTestBase : public ::testing::Test {
        mCsd = false;
        mFramesReceived = 0;
        mWorkResult = C2_OK;
        mOutputSize = 0u;
        if (mCompName == unknown_comp) mDisableTest = true;
        if (mDisableTest) std::cout << "[   WARN   ] Test Disabled \n";
        getInputMaxBufSize();
@@ -117,6 +118,16 @@ class Codec2AudioEncHidlTestBase : public ::testing::Test {
        for (std::unique_ptr<C2Work>& work : workItems) {
            if (!work->worklets.empty()) {
                mWorkResult |= work->result;
                if (!work->worklets.front()->output.buffers.empty()) {
                    mOutputSize += work->worklets.front()
                                           ->output.buffers[0]
                                           ->data()
                                           .linearBlocks()
                                           .front()
                                           .map()
                                           .get()
                                           .capacity();
                }
                workDone(mComponent, work, mFlushedIndices, mQueueLock, mQueueCondition, mWorkQueue,
                         mEos, mCsd, mFramesReceived);
            }
@@ -141,6 +152,7 @@ class Codec2AudioEncHidlTestBase : public ::testing::Test {
    int32_t mWorkResult;
    uint32_t mFramesReceived;
    int32_t mInputMaxBufSize;
    uint64_t mOutputSize;
    std::list<uint64_t> mFlushedIndices;

    C2BlockPool::local_id_t mBlockPoolId;
@@ -569,6 +581,210 @@ TEST_P(Codec2AudioEncHidlTest, FlushTest) {
    ASSERT_EQ(mComponent->stop(), C2_OK);
}

TEST_P(Codec2AudioEncHidlTest, MultiChannelCountTest) {
    description("Encodes input file for different channel count");
    if (mDisableTest) GTEST_SKIP() << "Test is disabled";

    char mURL[512];
    strcpy(mURL, sResourceDir.c_str());
    GetURLForComponent(mCompName, mURL);

    std::ifstream eleStream;
    eleStream.open(mURL, std::ifstream::binary);
    ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
    ALOGV("mURL : %s", mURL);

    int32_t nSampleRate;
    int32_t samplesPerFrame;
    int32_t nChannels;
    int32_t numFrames = 16;
    int32_t maxChannelCount = 8;

    if (!getConfigParams(mCompName, &nChannels, &nSampleRate, &samplesPerFrame)) {
        std::cout << "Failed to get the config params for " << mCompName << " component\n";
        std::cout << "[   WARN   ] Test Skipped \n";
        return;
    }

    uint64_t prevOutputSize = 0u;
    uint32_t prevChannelCount = 0u;

    // Looping through the maximum number of channel count supported by encoder
    for (nChannels = 1; nChannels < maxChannelCount; nChannels++) {
        ALOGV("Configuring %u encoder for channel count = %d", mCompName, nChannels);
        if (!setupConfigParam(mComponent, nChannels, nSampleRate)) {
            std::cout << "[   WARN   ] Test Skipped \n";
            return;
        }

        std::vector<std::unique_ptr<C2Param>> inParams;
        c2_status_t c2_status = mComponent->query({}, {C2StreamChannelCountInfo::input::PARAM_TYPE},
                                                  C2_DONT_BLOCK, &inParams);
        ASSERT_TRUE(!c2_status && inParams.size())
                << "Query configured channelCount failed => %d" << c2_status;

        size_t offset = sizeof(C2Param);
        C2Param* param = inParams[0].get();
        int32_t channelCount = *(int32_t*)((uint8_t*)param + offset);
        if (channelCount != nChannels) {
            std::cout << "[   WARN   ] Test Skipped for ChannelCount " << nChannels << "\n";
            continue;
        }

        // To check if the input stream is sufficient to encode for the higher channel count
        int32_t bytesCount = (samplesPerFrame * nChannels * 2) * numFrames;
        if (eleStream.gcount() < bytesCount) {
            std::cout << "[   WARN   ] Test Skipped for ChannelCount " << nChannels
                      << " because of insufficient input data\n";
            continue;
        }

        ASSERT_EQ(mComponent->start(), C2_OK);

        ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
                                              mFlushedIndices, mLinearPool, eleStream, numFrames,
                                              samplesPerFrame, nChannels, nSampleRate));

        // mDisableTest will be set if buffer was not fetched properly.
        // This may happen when config params is not proper but config succeeded
        // In this cases, we skip encoding the input stream
        if (mDisableTest) {
            std::cout << "[   WARN   ] Test Disabled for ChannelCount " << nChannels << "\n";
            ASSERT_EQ(mComponent->stop(), C2_OK);
            return;
        }

        // blocking call to ensures application to Wait till all the inputs are consumed
        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);

        // Validate output size based on chosen ChannelCount
        EXPECT_GE(mOutputSize, prevOutputSize);

        prevChannelCount = nChannels;
        prevOutputSize = mOutputSize;

        if (mFramesReceived != numFrames) {
            ALOGE("Input buffer count and Output buffer count mismatch");
            ALOGE("framesReceived : %d inputFrames : %u", mFramesReceived, numFrames);
            ASSERT_TRUE(false);
        }
        if ((mCompName == flac || mCompName == opus || mCompName == aac)) {
            ASSERT_TRUE(mCsd) << "CSD buffer missing";
        }
        ASSERT_TRUE(mEos);
        ASSERT_EQ(mComponent->stop(), C2_OK);
        mFramesReceived = 0;
        mOutputSize = 0;
        mEos = false;
        mCsd = false;
        eleStream.seekg(0, eleStream.beg);
    }
}

TEST_P(Codec2AudioEncHidlTest, MultiSampleRateTest) {
    description("Encodes input file for different SampleRate");
    if (mDisableTest) GTEST_SKIP() << "Test is disabled";

    char mURL[512];
    strcpy(mURL, sResourceDir.c_str());
    GetURLForComponent(mCompName, mURL);

    std::ifstream eleStream;
    eleStream.open(mURL, std::ifstream::binary);
    ASSERT_EQ(eleStream.is_open(), true) << mURL << " file not found";
    ALOGV("mURL : %s", mURL);

    int32_t nSampleRate;
    int32_t samplesPerFrame;
    int32_t nChannels;
    int32_t numFrames = 16;

    if (!getConfigParams(mCompName, &nChannels, &nSampleRate, &samplesPerFrame)) {
        std::cout << "Failed to get the config params for " << mCompName << " component\n";
        std::cout << "[   WARN   ] Test Skipped \n";
        return;
    }

    int32_t sampleRateValues[] = {1000, 8000, 16000, 24000, 48000, 96000, 192000};

    uint64_t prevOutputSize = 0u;
    uint32_t prevSampleRate = 0u;

    for (int32_t nSampleRate : sampleRateValues) {
        ALOGV("Configuring %u encoder for SampleRate = %d", mCompName, nSampleRate);
        if (!setupConfigParam(mComponent, nChannels, nSampleRate)) {
            std::cout << "[   WARN   ] Test Skipped \n";
            return;
        }

        std::vector<std::unique_ptr<C2Param>> inParams;
        c2_status_t c2_status = mComponent->query({}, {C2StreamSampleRateInfo::input::PARAM_TYPE},
                                                  C2_DONT_BLOCK, &inParams);

        ASSERT_TRUE(!c2_status && inParams.size())
                << "Query configured SampleRate failed => %d" << c2_status;
        size_t offset = sizeof(C2Param);
        C2Param* param = inParams[0].get();
        int32_t configuredSampleRate = *(int32_t*)((uint8_t*)param + offset);

        if (configuredSampleRate != nSampleRate) {
            std::cout << "[   WARN   ] Test Skipped for SampleRate " << nSampleRate << "\n";
            continue;
        }

        // To check if the input stream is sufficient to encode for the higher SampleRate
        int32_t bytesCount = (samplesPerFrame * nChannels * 2) * numFrames;
        if (eleStream.gcount() < bytesCount) {
            std::cout << "[   WARN   ] Test Skipped for SampleRate " << nSampleRate
                      << " because of insufficient input data\n";
            continue;
        }

        ASSERT_EQ(mComponent->start(), C2_OK);

        ASSERT_NO_FATAL_FAILURE(encodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
                                              mFlushedIndices, mLinearPool, eleStream, numFrames,
                                              samplesPerFrame, nChannels, nSampleRate));

        // mDisableTest will be set if buffer was not fetched properly.
        // This may happen when config params is not proper but config succeeded
        // In this case, we skip encoding the input stream
        if (mDisableTest) {
            std::cout << "[   WARN   ] Test Disabled for SampleRate" << nSampleRate << "\n";
            ASSERT_EQ(mComponent->stop(), C2_OK);
            return;
        }

        // blocking call to ensures application to Wait till all the inputs are consumed
        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);

        // Validate output size based on chosen samplerate
        if (prevSampleRate >= nSampleRate) {
            EXPECT_LE(mOutputSize, prevOutputSize);
        } else {
            EXPECT_GT(mOutputSize, prevOutputSize);
        }
        prevSampleRate = nSampleRate;
        prevOutputSize = mOutputSize;

        if (mFramesReceived != numFrames) {
            ALOGE("Input buffer count and Output buffer count mismatch");
            ALOGE("framesReceived : %d inputFrames : %u", mFramesReceived, numFrames);
            ASSERT_TRUE(false);
        }
        if ((mCompName == flac || mCompName == opus || mCompName == aac)) {
            ASSERT_TRUE(mCsd) << "CSD buffer missing";
        }
        ASSERT_TRUE(mEos);
        ASSERT_EQ(mComponent->stop(), C2_OK);
        mFramesReceived = 0;
        mOutputSize = 0;
        mEos = false;
        mCsd = false;
        eleStream.seekg(0, eleStream.beg);
    }
}

INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2AudioEncHidlTest, testing::ValuesIn(kTestParameters),
                         android::hardware::PrintInstanceTupleNameToString<>);

+115 −0
Original line number Diff line number Diff line
@@ -43,6 +43,8 @@ using android::C2AllocatorIon;
static std::vector<std::tuple<std::string, std::string, std::string, std::string>>
        kDecodeTestParameters;

static std::vector<std::tuple<std::string, std::string, std::string>> kCsdFlushTestParameters;

// Resource directory
static std::string sResourceDir = "";

@@ -1001,6 +1003,110 @@ TEST_P(Codec2VideoDecHidlTest, DecodeTestEmptyBuffersInserted) {
    }
}

class Codec2VideoDecCsdInputTests
    : public Codec2VideoDecHidlTestBase,
      public ::testing::WithParamInterface<std::tuple<std::string, std::string, std::string>> {
    void getParams() {
        mInstanceName = std::get<0>(GetParam());
        mComponentName = std::get<1>(GetParam());
    }
};

// Test the codecs for the following
// start - csd - data… - (with/without)flush - data… - flush - data…
TEST_P(Codec2VideoDecCsdInputTests, CSDFlushTest) {
    description("Tests codecs for flush at different states");
    if (mDisableTest) GTEST_SKIP() << "Test is disabled";

    char mURL[512], info[512];

    android::Vector<FrameInfo> Info;

    strcpy(mURL, sResourceDir.c_str());
    strcpy(info, sResourceDir.c_str());
    GetURLForComponent(mCompName, mURL, info);

    int32_t numCsds = populateInfoVector(info, &Info, mTimestampDevTest, &mTimestampUslist);
    ASSERT_GE(numCsds, 0) << "Error in parsing input info file";

    ASSERT_EQ(mComponent->start(), C2_OK);

    ALOGV("mURL : %s", mURL);
    std::ifstream eleStream;
    eleStream.open(mURL, std::ifstream::binary);
    ASSERT_EQ(eleStream.is_open(), true);
    bool flushedDecoder = false;
    bool signalEOS = false;
    bool keyFrame = false;
    bool flushCsd = !std::get<2>(GetParam()).compare("true");

    ALOGV("sending %d csd data ", numCsds);
    int framesToDecode = numCsds;
    ASSERT_NO_FATAL_FAILURE(decodeNFrames(mComponent, mQueueLock, mQueueCondition, mWorkQueue,
                                          mFlushedIndices, mLinearPool, eleStream, &Info, 0,
                                          framesToDecode, false));
    c2_status_t err = C2_OK;
    std::list<std::unique_ptr<C2Work>> flushedWork;
    if (numCsds && flushCsd) {
        // We wait for all the CSD buffers to get consumed.
        // Once we have received all CSD work back, we call flush
        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);

        err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
        ASSERT_EQ(err, C2_OK);
        flushedDecoder = true;
        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
                               MAX_INPUT_BUFFERS - flushedWork.size());
        ASSERT_NO_FATAL_FAILURE(
                verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
        ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
    }

    int offset = framesToDecode;
    uint32_t flags = 0;
    while (1) {
        while (offset < (int)Info.size()) {
            flags = 0;
            if (Info[offset].flags) flags = 1u << (Info[offset].flags - 1);
            if (flags & SYNC_FRAME) {
                keyFrame = true;
                break;
            }
            eleStream.ignore(Info[offset].bytesCount);
            offset++;
        }
        if (keyFrame) {
            framesToDecode = c2_min(FLUSH_INTERVAL, (int)Info.size() - offset);
            if (framesToDecode < FLUSH_INTERVAL) signalEOS = true;
            ASSERT_NO_FATAL_FAILURE(decodeNFrames(
                    mComponent, mQueueLock, mQueueCondition, mWorkQueue, mFlushedIndices,
                    mLinearPool, eleStream, &Info, offset, framesToDecode, signalEOS));
            offset += framesToDecode;
        }
        err = mComponent->flush(C2Component::FLUSH_COMPONENT, &flushedWork);
        ASSERT_EQ(err, C2_OK);
        keyFrame = false;
        // blocking call to ensures application to Wait till remaining
        // 'non-flushed' inputs are consumed
        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue,
                               MAX_INPUT_BUFFERS - flushedWork.size());
        ASSERT_NO_FATAL_FAILURE(
                verifyFlushOutput(flushedWork, mWorkQueue, mFlushedIndices, mQueueLock));
        ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
        if (signalEOS || offset >= (int)Info.size()) {
            break;
        }
    }
    if (!signalEOS) {
        ASSERT_NO_FATAL_FAILURE(testInputBuffer(mComponent, mQueueLock, mWorkQueue,
                                                C2FrameData::FLAG_END_OF_STREAM, false));
        waitOnInputConsumption(mQueueLock, mQueueCondition, mWorkQueue);
    }
    eleStream.close();
    ASSERT_EQ(mWorkQueue.size(), MAX_INPUT_BUFFERS);
    ASSERT_EQ(mComponent->stop(), C2_OK);
}

INSTANTIATE_TEST_SUITE_P(PerInstance, Codec2VideoDecHidlTest, testing::ValuesIn(kTestParameters),
                         android::hardware::PrintInstanceTupleNameToString<>);

@@ -1009,6 +1115,10 @@ INSTANTIATE_TEST_SUITE_P(StreamIndexAndEOS, Codec2VideoDecDecodeTest,
                         testing::ValuesIn(kDecodeTestParameters),
                         android::hardware::PrintInstanceTupleNameToString<>);

INSTANTIATE_TEST_SUITE_P(CsdInputs, Codec2VideoDecCsdInputTests,
                         testing::ValuesIn(kCsdFlushTestParameters),
                         android::hardware::PrintInstanceTupleNameToString<>);

}  // anonymous namespace

// TODO : Video specific configuration Test
@@ -1027,6 +1137,11 @@ int main(int argc, char** argv) {
                std::make_tuple(std::get<0>(params), std::get<1>(params), "2", "false"));
        kDecodeTestParameters.push_back(
                std::make_tuple(std::get<0>(params), std::get<1>(params), "2", "true"));

        kCsdFlushTestParameters.push_back(
                std::make_tuple(std::get<0>(params), std::get<1>(params), "true"));
        kCsdFlushTestParameters.push_back(
                std::make_tuple(std::get<0>(params), std::get<1>(params), "false"));
    }

    // Set the resource directory based on command line args.
+101 −193

File changed.

Preview size limit exceeded, changes collapsed.

+0 −42
Original line number Diff line number Diff line
@@ -306,48 +306,6 @@ private:

    Mutexed<PipelineWatcher> mPipelineWatcher;

    class ReorderStash {
    public:
        struct Entry {
            inline Entry() : buffer(nullptr), timestamp(0), flags(0), ordinal({0, 0, 0}) {}
            inline Entry(
                    const std::shared_ptr<C2Buffer> &b,
                    int64_t t,
                    int32_t f,
                    const C2WorkOrdinalStruct &o)
                : buffer(b), timestamp(t), flags(f), ordinal(o) {}
            std::shared_ptr<C2Buffer> buffer;
            int64_t timestamp;
            int32_t flags;
            C2WorkOrdinalStruct ordinal;
        };

        ReorderStash();

        void clear();
        void flush();
        void setDepth(uint32_t depth);
        void setKey(C2Config::ordinal_key_t key);
        bool pop(Entry *entry);
        void emplace(
                const std::shared_ptr<C2Buffer> &buffer,
                int64_t timestamp,
                int32_t flags,
                const C2WorkOrdinalStruct &ordinal);
        void defer(const Entry &entry);
        bool hasPending() const;
        uint32_t depth() const { return mDepth; }

    private:
        std::list<Entry> mPending;
        std::list<Entry> mStash;
        uint32_t mDepth;
        C2Config::ordinal_key_t mKey;

        bool less(const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2);
    };
    Mutexed<ReorderStash> mReorderStash;

    std::atomic_bool mInputMetEos;
    std::once_flag mRenderWarningFlag;

Loading