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

Commit f57a2e0f authored by Fyodor Kyslov's avatar Fyodor Kyslov Committed by Gerrit Code Review
Browse files

Merge "C2SoftDav1dDec: Fix performance issues in frame parallel multi-threading" into main

parents 8c291efc 98d9a240
Loading
Loading
Loading
Loading
+28 −78
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ constexpr char COMPONENT_NAME[] = CODECNAME;

constexpr size_t kMinInputBufferSize = 2 * 1024 * 1024;

constexpr uint32_t kOutputDelay = 4;

class C2SoftDav1dDec::IntfImpl : public SimpleInterface<void>::BaseParams {
  public:
    explicit IntfImpl(const std::shared_ptr<C2ReflectorHelper>& helper)
@@ -239,6 +241,13 @@ class C2SoftDav1dDec::IntfImpl : public SimpleInterface<void>::BaseParams {
                             .withFields({C2F(mPixelFormat, value).oneOf(pixelFormats)})
                             .withSetter((Setter<decltype(*mPixelFormat)>::StrictValueWithNoDeps))
                             .build());

        addParameter(
                DefineParam(mActualOutputDelay, C2_PARAMKEY_OUTPUT_DELAY)
                .withDefault(new C2PortActualDelayTuning::output(kOutputDelay))
                .withFields({C2F(mActualOutputDelay, value).inRange(0, kOutputDelay)})
                .withSetter(Setter<decltype(*mActualOutputDelay)>::StrictValueWithNoDeps)
                .build());
    }

    static C2R SizeSetter(bool mayBlock, const C2P<C2StreamPictureSizeInfo::output>& oldMe,
@@ -450,13 +459,6 @@ void C2SoftDav1dDec::flushDav1d() {
    if (mDav1dCtx) {
        Dav1dPicture p;

        while (mDecodedPictures.size() > 0) {
            p = mDecodedPictures.front();
            mDecodedPictures.pop_front();

            dav1d_picture_unref(&p);
        }

        int res = 0;
        while (true) {
            memset(&p, 0, sizeof(p));
@@ -527,6 +529,8 @@ bool C2SoftDav1dDec::initDecoder() {
            android::base::GetIntProperty(NUM_THREADS_DAV1D_PROPERTY, NUM_THREADS_DAV1D_DEFAULT);
    if (numThreads > 0) lib_settings.n_threads = numThreads;

    lib_settings.max_frame_delay = kOutputDelay;

    int res = 0;
    if ((res = dav1d_open(&mDav1dCtx, &lib_settings))) {
        ALOGE("dav1d_open failed. status: %d.", res);
@@ -540,15 +544,6 @@ bool C2SoftDav1dDec::initDecoder() {

void C2SoftDav1dDec::destroyDecoder() {
    if (mDav1dCtx) {
        Dav1dPicture p;
        while (mDecodedPictures.size() > 0) {
            memset(&p, 0, sizeof(p));
            p = mDecodedPictures.front();
            mDecodedPictures.pop_front();

            dav1d_picture_unref(&p);
        }

        dav1d_close(&mDav1dCtx);
        mDav1dCtx = nullptr;
        mOutputBufferIndex = 0;
@@ -572,19 +567,24 @@ void fillEmptyWork(const std::unique_ptr<C2Work>& work) {
}

void C2SoftDav1dDec::finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
                                const std::shared_ptr<C2GraphicBlock>& block) {
                                const std::shared_ptr<C2GraphicBlock>& block,
                                const Dav1dPicture &img) {
    std::shared_ptr<C2Buffer> buffer = createGraphicBuffer(block, C2Rect(mWidth, mHeight));
    {
        IntfImpl::Lock lock = mIntf->lock();
        buffer->setInfo(mIntf->getColorAspects_l());
    }
    auto fillWork = [buffer, index](const std::unique_ptr<C2Work>& work) {

    auto fillWork = [buffer, index, img, this](const std::unique_ptr<C2Work>& work) {
        uint32_t flags = 0;
        if ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) &&
            (c2_cntr64_t(index) == work->input.ordinal.frameIndex)) {
            flags |= C2FrameData::FLAG_END_OF_STREAM;
            ALOGV("signalling end_of_stream.");
        }
        getHDRStaticParams(&img, work);
        getHDR10PlusInfoData(&img, work);

        work->worklets.front()->output.flags = (C2FrameData::flags_t)flags;
        work->worklets.front()->output.buffers.clear();
        work->worklets.front()->output.buffers.push_back(buffer);
@@ -705,39 +705,9 @@ void C2SoftDav1dDec::process(const std::unique_ptr<C2Work>& work,
                        break;
                    }

                    bool b_output_error = false;

                    do {
                        Dav1dPicture img;
                        memset(&img, 0, sizeof(img));

                        res = dav1d_get_picture(mDav1dCtx, &img);
                        if (res == 0) {
                            mDecodedPictures.push_back(img);

                            if (!end_of_stream) break;
                        } else if (res == DAV1D_ERR(EAGAIN)) {
                            /* the decoder needs more data to be able to output something.
                             * if there is more data pending, continue the loop below or
                             * otherwise break */
                            if (data.sz != 0) res = 0;
                            break;
                        } else {
                            ALOGE("warning! Decoder error %d!", res);
                            b_output_error = true;
                            break;
                        }
                    } while (res == 0);

                    if (b_output_error) break;
                    outputBuffer(pool, work);

                    /* on drain, we must ignore the 1st EAGAIN */
                    if (!b_draining && (res == DAV1D_ERR(EAGAIN) || res == 0) &&
                        (end_of_stream)) {
                        b_draining = true;
                        res = 0;
                    }
                } while (res == 0 && ((data.sz != 0) || b_draining));
                } while (res == DAV1D_ERR(EAGAIN));

                if (data.sz > 0) {
                    ALOGE("unexpected data.sz=%zu after dav1d_send_data", data.sz);
@@ -759,8 +729,6 @@ void C2SoftDav1dDec::process(const std::unique_ptr<C2Work>& work,
        }
    }

    (void)outputBuffer(pool, work);

    if (end_of_stream) {
        drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
        mSignalledOutputEos = true;
@@ -769,7 +737,7 @@ void C2SoftDav1dDec::process(const std::unique_ptr<C2Work>& work,
    }
}

void C2SoftDav1dDec::getHDRStaticParams(Dav1dPicture* picture,
void C2SoftDav1dDec::getHDRStaticParams(const Dav1dPicture* picture,
                                        const std::unique_ptr<C2Work>& work) {
    C2StreamHdrStaticMetadataInfo::output hdrStaticMetadataInfo{};
    bool infoPresent = false;
@@ -833,7 +801,7 @@ void C2SoftDav1dDec::getHDRStaticParams(Dav1dPicture* picture,
    }
}

void C2SoftDav1dDec::getHDR10PlusInfoData(Dav1dPicture* picture,
void C2SoftDav1dDec::getHDR10PlusInfoData(const Dav1dPicture* picture,
                                          const std::unique_ptr<C2Work>& work) {
    if (picture != nullptr) {
        if (picture->itut_t35 != nullptr) {
@@ -873,7 +841,7 @@ void C2SoftDav1dDec::getHDR10PlusInfoData(Dav1dPicture* picture,
    }
}

void C2SoftDav1dDec::getVuiParams(Dav1dPicture* picture) {
void C2SoftDav1dDec::getVuiParams(const Dav1dPicture* picture) {
    VuiColorAspects vuiColorAspects;

    if (picture) {
@@ -944,26 +912,11 @@ bool C2SoftDav1dDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
    memset(&img, 0, sizeof(img));

    int res = 0;
    if (mDecodedPictures.size() > 0) {
        img = mDecodedPictures.front();
        mDecodedPictures.pop_front();
        // ALOGD("Got a picture(out_frameIndex=%ld,timestamp=%ld) from the deque for
        // outputBuffer.",img.m.timestamp,img.m.timestamp);
    } else {
    res = dav1d_get_picture(mDav1dCtx, &img);
        if (res == 0) {
            // ALOGD("Got a picture(out_frameIndex=%ld,timestamp=%ld) from dav1d for
            // outputBuffer.",img.m.timestamp,img.m.timestamp);
        } else {
            ALOGE("failed to get a picture from dav1d for outputBuffer.");
        }
    }

    if (res == DAV1D_ERR(EAGAIN)) {
        ALOGD("Not enough data to output a picture.");
        ALOGV("Not enough data to output a picture.");
        return false;
    }
    if (res != 0) {
    } else if (res != 0) {
        ALOGE("The AV1 decoder failed to get a picture (res=%s).", strerror(DAV1D_ERR(res)));
        return false;
    }
@@ -989,8 +942,6 @@ bool C2SoftDav1dDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
    }

    getVuiParams(&img);
    getHDRStaticParams(&img, work);
    getHDR10PlusInfoData(&img, work);

    // out_frameIndex that the decoded picture returns from dav1d.
    int64_t out_frameIndex = img.m.timestamp;
@@ -1176,9 +1127,8 @@ bool C2SoftDav1dDec::outputBuffer(const std::shared_ptr<C2BlockPool>& pool,
                             convFormat);
    }

    finishWork(out_frameIndex, work, std::move(block), img);
    dav1d_picture_unref(&img);

    finishWork(out_frameIndex, work, std::move(block));
    block = nullptr;
    return true;
}
+5 −5
Original line number Diff line number Diff line
@@ -58,7 +58,6 @@ struct C2SoftDav1dDec : public SimpleC2Component {
    int mOutputBufferIndex = 0;

    Dav1dContext* mDav1dCtx = nullptr;
    std::deque<Dav1dPicture> mDecodedPictures;

    // configurations used by component in process
    // (TODO: keep this in intf but make them internal only)
@@ -101,12 +100,13 @@ struct C2SoftDav1dDec : public SimpleC2Component {
    nsecs_t mTimeEnd = 0;    // Time at the end of decode()

    bool initDecoder();
    void getHDRStaticParams(Dav1dPicture* picture, const std::unique_ptr<C2Work>& work);
    void getHDR10PlusInfoData(Dav1dPicture* picture, const std::unique_ptr<C2Work>& work);
    void getVuiParams(Dav1dPicture* picture);
    void getHDRStaticParams(const Dav1dPicture* picture, const std::unique_ptr<C2Work>& work);
    void getHDR10PlusInfoData(const Dav1dPicture* picture, const std::unique_ptr<C2Work>& work);
    void getVuiParams(const Dav1dPicture* picture);
    void destroyDecoder();
    void finishWork(uint64_t index, const std::unique_ptr<C2Work>& work,
                    const std::shared_ptr<C2GraphicBlock>& block);
                    const std::shared_ptr<C2GraphicBlock>& block,
                    const Dav1dPicture &img);
    // Sets |work->result| and mSignalledError. Returns false.
    void setError(const std::unique_ptr<C2Work>& work, c2_status_t error);
    bool allocTmpFrameBuffer(size_t size);