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

Commit 464d4ff7 authored by Wonsik Kim's avatar Wonsik Kim Committed by Android (Google) Code Review
Browse files

Merge changes Id9b40acc,I6ddff3f8 into qt-dev

* changes:
  codec2: Add support for B frames in C2SoftAvcEnc plugin
  codec2: add support for B Frames in C2SoftHevcEnc
parents 00ffd9e0 26b946de
Loading
Loading
Loading
Loading
+170 −47
Original line number Diff line number Diff line
@@ -55,7 +55,6 @@ public:
        noPrivateBuffers(); // TODO: account for our buffers here
        noInputReferences();
        noOutputReferences();
        noInputLatency();
        noTimeStretch();
        setDerivedInstance(this);

@@ -81,6 +80,13 @@ public:
                .withSetter(SizeSetter)
                .build());

        addParameter(
                DefineParam(mActualInputDelay, C2_PARAMKEY_INPUT_DELAY)
                .withDefault(new C2PortActualDelayTuning::input(DEFAULT_B_FRAMES))
                .withFields({C2F(mActualInputDelay, value).inRange(0, MAX_B_FRAMES)})
                .withSetter(Setter<decltype(*mActualInputDelay)>::StrictValueWithNoDeps)
                .build());

        addParameter(
                DefineParam(mFrameRate, C2_PARAMKEY_FRAME_RATE)
                .withDefault(new C2StreamFrameRateInfo::output(0u, 30.))
@@ -365,9 +371,9 @@ C2SoftAvcEnc::C2SoftAvcEnc(
      mAVCEncLevel(41),
      mStarted(false),
      mSawInputEOS(false),
      mSawOutputEOS(false),
      mSignalledError(false),
      mCodecCtx(nullptr),
      mOutBlock(nullptr),
      // TODO: output buffer size
      mOutBufferSize(524288) {

@@ -380,7 +386,7 @@ C2SoftAvcEnc::C2SoftAvcEnc(
}

C2SoftAvcEnc::~C2SoftAvcEnc() {
    releaseEncoder();
    onRelease();
}

c2_status_t C2SoftAvcEnc::onInit() {
@@ -394,11 +400,17 @@ c2_status_t C2SoftAvcEnc::onStop() {
void C2SoftAvcEnc::onReset() {
    // TODO: use IVE_CMD_CTL_RESET?
    releaseEncoder();
    if (mOutBlock) {
        mOutBlock.reset();
    }
    initEncParams();
}

void C2SoftAvcEnc::onRelease() {
    releaseEncoder();
    if (mOutBlock) {
        mOutBlock.reset();
    }
}

c2_status_t C2SoftAvcEnc::onFlush_sm() {
@@ -1106,8 +1118,10 @@ c2_status_t C2SoftAvcEnc::setEncodeArgs(
        const C2GraphicView *const input,
        uint8_t *base,
        uint32_t capacity,
        uint64_t timestamp) {
        uint64_t workIndex) {
    iv_raw_buf_t *ps_inp_raw_buf;
    memset(ps_encode_ip, 0, sizeof(*ps_encode_ip));
    memset(ps_encode_op, 0, sizeof(*ps_encode_op));

    ps_inp_raw_buf = &ps_encode_ip->s_inp_buf;
    ps_encode_ip->s_out_buf.pv_buf = base;
@@ -1123,8 +1137,8 @@ c2_status_t C2SoftAvcEnc::setEncodeArgs(
    ps_encode_ip->u4_mb_info_type = 0;
    ps_encode_ip->u4_pic_info_type = 0;
    ps_encode_ip->u4_is_last = 0;
    ps_encode_ip->u4_timestamp_high = timestamp >> 32;
    ps_encode_ip->u4_timestamp_low = timestamp & 0xFFFFFFFF;
    ps_encode_ip->u4_timestamp_high = workIndex >> 32;
    ps_encode_ip->u4_timestamp_low = workIndex & 0xFFFFFFFF;
    ps_encode_op->s_out_buf.pv_buf = nullptr;

    /* Initialize color formats */
@@ -1271,17 +1285,46 @@ c2_status_t C2SoftAvcEnc::setEncodeArgs(
    return C2_OK;
}

void C2SoftAvcEnc::finishWork(uint64_t workIndex, const std::unique_ptr<C2Work> &work,
                              ive_video_encode_op_t *ps_encode_op) {
    std::shared_ptr<C2Buffer> buffer =
            createLinearBuffer(mOutBlock, 0, ps_encode_op->s_out_buf.u4_bytes);
    if (IV_IDR_FRAME == ps_encode_op->u4_encoded_frame_type) {
        ALOGV("IDR frame produced");
        buffer->setInfo(std::make_shared<C2StreamPictureTypeMaskInfo::output>(
                0u /* stream id */, C2Config::SYNC_FRAME));
    }
    mOutBlock = nullptr;

    auto fillWork = [buffer](const std::unique_ptr<C2Work> &work) {
        work->worklets.front()->output.flags = (C2FrameData::flags_t)0;
        work->worklets.front()->output.buffers.clear();
        work->worklets.front()->output.buffers.push_back(buffer);
        work->worklets.front()->output.ordinal = work->input.ordinal;
        work->workletsProcessed = 1u;
    };
    if (work && c2_cntr64_t(workIndex) == work->input.ordinal.frameIndex) {
        fillWork(work);
        if (mSawInputEOS) {
            work->worklets.front()->output.flags = C2FrameData::FLAG_END_OF_STREAM;
        }
    } else {
        finish(workIndex, fillWork);
    }
}

void C2SoftAvcEnc::process(
        const std::unique_ptr<C2Work> &work,
        const std::shared_ptr<C2BlockPool> &pool) {
    // Initialize output work
    work->result = C2_OK;
    work->workletsProcessed = 1u;
    work->workletsProcessed = 0u;
    work->worklets.front()->output.flags = work->input.flags;

    IV_STATUS_T status;
    WORD32 timeDelay, timeTaken;
    uint64_t timestamp = work->input.ordinal.timestamp.peekull();
    WORD32 timeDelay = 0;
    WORD32 timeTaken = 0;
    uint64_t workIndex = work->input.ordinal.frameIndex.peekull();

    // Initialize encoder if not already initialized
    if (mCodecCtx == nullptr) {
@@ -1289,27 +1332,29 @@ void C2SoftAvcEnc::process(
            ALOGE("Failed to initialize encoder");
            mSignalledError = true;
            work->result = C2_CORRUPTED;
            work->workletsProcessed = 1u;
            return;
        }
    }
    if (mSignalledError) {
        return;
    }

    // while (!mSawOutputEOS && !outQueue.empty()) {
    c2_status_t error;
    ive_video_encode_ip_t s_encode_ip;
    ive_video_encode_op_t s_encode_op;
    memset(&s_encode_op, 0, sizeof(s_encode_op));

    if (!mSpsPpsHeaderReceived) {
        constexpr uint32_t kHeaderLength = MIN_STREAM_SIZE;
        uint8_t header[kHeaderLength];
        error = setEncodeArgs(
                &s_encode_ip, &s_encode_op, nullptr, header, kHeaderLength, timestamp);
                &s_encode_ip, &s_encode_op, nullptr, header, kHeaderLength, workIndex);
        if (error != C2_OK) {
            ALOGE("setEncodeArgs failed: %d", error);
            mSignalledError = true;
            work->result = C2_CORRUPTED;
            work->workletsProcessed = 1u;
            return;
        }
        status = ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);
@@ -1317,6 +1362,7 @@ void C2SoftAvcEnc::process(
        if (IV_SUCCESS != status) {
            ALOGE("Encode header failed = 0x%x\n",
                    s_encode_op.u4_error_code);
            work->workletsProcessed = 1u;
            return;
        } else {
            ALOGV("Bytes Generated in header %d\n",
@@ -1331,6 +1377,7 @@ void C2SoftAvcEnc::process(
            ALOGE("CSD allocation failed");
            mSignalledError = true;
            work->result = C2_NO_MEMORY;
            work->workletsProcessed = 1u;
            return;
        }
        memcpy(csd->m.value, header, s_encode_op.s_out_buf.u4_bytes);
@@ -1338,6 +1385,10 @@ void C2SoftAvcEnc::process(

        DUMP_TO_FILE(
                mOutFile, csd->m.value, csd->flexCount());
        if (work->input.buffers.empty()) {
            work->workletsProcessed = 1u;
            return;
        }
    }

    // handle dynamic config parameters
@@ -1394,34 +1445,41 @@ void C2SoftAvcEnc::process(
                inputBuffer->data().graphicBlocks().front().map().get());
        if (view->error() != C2_OK) {
            ALOGE("graphic view map err = %d", view->error());
            work->workletsProcessed = 1u;
            return;
        }
    }

    std::shared_ptr<C2LinearBlock> block;

    do {
        C2MemoryUsage usage = { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE };
        if (mSawInputEOS && work->input.buffers.empty()) break;
        if (!mOutBlock) {
            C2MemoryUsage usage = {C2MemoryUsage::CPU_READ,
                                   C2MemoryUsage::CPU_WRITE};
            // TODO: error handling, proper usage, etc.
        c2_status_t err = pool->fetchLinearBlock(mOutBufferSize, usage, &block);
            c2_status_t err =
                pool->fetchLinearBlock(mOutBufferSize, usage, &mOutBlock);
            if (err != C2_OK) {
                ALOGE("fetch linear block err = %d", err);
                work->result = err;
                work->workletsProcessed = 1u;
                return;
            }
        C2WriteView wView = block->map().get();
        }
        C2WriteView wView = mOutBlock->map().get();
        if (wView.error() != C2_OK) {
            ALOGE("write view map err = %d", wView.error());
            work->result = wView.error();
            work->workletsProcessed = 1u;
            return;
        }

        error = setEncodeArgs(
                &s_encode_ip, &s_encode_op, view.get(), wView.base(), wView.capacity(), timestamp);
                &s_encode_ip, &s_encode_op, view.get(), wView.base(), wView.capacity(), workIndex);
        if (error != C2_OK) {
            ALOGE("setEncodeArgs failed : %d", error);
            mSignalledError = true;
            work->result = error;
            work->workletsProcessed = 1u;
            return;
        }

@@ -1439,12 +1497,14 @@ void C2SoftAvcEnc::process(
            if ((s_encode_op.u4_error_code & 0xFF) == IH264E_BITSTREAM_BUFFER_OVERFLOW) {
                // TODO: use IVE_CMD_CTL_GETBUFINFO for proper max input size?
                mOutBufferSize *= 2;
                mOutBlock.reset();
                continue;
            }
            ALOGE("Encode Frame failed = 0x%x\n",
                    s_encode_op.u4_error_code);
            mSignalledError = true;
            work->result = C2_CORRUPTED;
            work->workletsProcessed = 1u;
            return;
        }
    } while (IV_SUCCESS != status);
@@ -1473,41 +1533,104 @@ void C2SoftAvcEnc::process(
        }
    }

    work->worklets.front()->output.flags = work->input.flags;
    work->worklets.front()->output.ordinal = work->input.ordinal;
    work->worklets.front()->output.ordinal.timestamp =
        ((uint64_t)s_encode_op.u4_timestamp_high << 32) | s_encode_op.u4_timestamp_low;
    work->worklets.front()->output.buffers.clear();
    if (s_encode_op.output_present) {
        if (!s_encode_op.s_out_buf.u4_bytes) {
            ALOGE("Error: Output present but bytes generated is zero");
            mSignalledError = true;
            work->result = C2_CORRUPTED;
            work->workletsProcessed = 1u;
            return;
        }
        uint64_t workId = ((uint64_t)s_encode_op.u4_timestamp_high << 32) |
                      s_encode_op.u4_timestamp_low;
        finishWork(workId, work, &s_encode_op);
    }
    if (mSawInputEOS) {
        drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
    }
}

    if (s_encode_op.s_out_buf.u4_bytes) {
        std::shared_ptr<C2Buffer> buffer =
            createLinearBuffer(block, 0, s_encode_op.s_out_buf.u4_bytes);
        if (IV_IDR_FRAME == s_encode_op.u4_encoded_frame_type) {
            ALOGV("IDR frame produced");
            buffer->setInfo(std::make_shared<C2StreamPictureTypeMaskInfo::output>(
                    0u /* stream id */, C2Config::SYNC_FRAME));
c2_status_t C2SoftAvcEnc::drainInternal(
        uint32_t drainMode,
        const std::shared_ptr<C2BlockPool> &pool,
        const std::unique_ptr<C2Work> &work) {

    if (drainMode == NO_DRAIN) {
        ALOGW("drain with NO_DRAIN: no-op");
        return C2_OK;
    }
        work->worklets.front()->output.buffers.push_back(buffer);
    if (drainMode == DRAIN_CHAIN) {
        ALOGW("DRAIN_CHAIN not supported");
        return C2_OMITTED;
    }

    while (true) {
        if (!mOutBlock) {
            C2MemoryUsage usage = {C2MemoryUsage::CPU_READ,
                                   C2MemoryUsage::CPU_WRITE};
            // TODO: error handling, proper usage, etc.
            c2_status_t err =
                pool->fetchLinearBlock(mOutBufferSize, usage, &mOutBlock);
            if (err != C2_OK) {
                ALOGE("fetch linear block err = %d", err);
                work->result = err;
                work->workletsProcessed = 1u;
                return err;
            }
        }
        C2WriteView wView = mOutBlock->map().get();
        if (wView.error()) {
            ALOGE("graphic view map failed %d", wView.error());
            return C2_CORRUPTED;
        }
        ive_video_encode_ip_t s_encode_ip;
        ive_video_encode_op_t s_encode_op;
        if (C2_OK != setEncodeArgs(&s_encode_ip, &s_encode_op, nullptr,
                                   wView.base(), wView.capacity(), 0)) {
            ALOGE("setEncodeArgs failed for drainInternal");
            mSignalledError = true;
            work->result = C2_CORRUPTED;
            work->workletsProcessed = 1u;
            return C2_CORRUPTED;
        }
        (void)ive_api_function(mCodecCtx, &s_encode_ip, &s_encode_op);

    if (s_encode_op.u4_is_last) {
        // outputBufferHeader->nFlags |= OMX_BUFFERFLAG_EOS;
        mSawOutputEOS = true;
        void *freed = s_encode_op.s_inp_buf.apv_bufs[0];
        /* If encoder frees up an input buffer, mark it as free */
        if (freed != nullptr) {
            if (mBuffers.count(freed) == 0u) {
                ALOGD("buffer not tracked");
            } else {
        // outputBufferHeader->nFlags &= ~OMX_BUFFERFLAG_EOS;
                // Release input buffer reference
                mBuffers.erase(freed);
                mConversionBuffersInUse.erase(freed);
            }
        }

        if (s_encode_op.output_present) {
            uint64_t workId = ((uint64_t)s_encode_op.u4_timestamp_high << 32) |
                          s_encode_op.u4_timestamp_low;
            finishWork(workId, work, &s_encode_op);
        } else {
            if (work->workletsProcessed != 1u) {
                work->worklets.front()->output.flags = work->input.flags;
                work->worklets.front()->output.ordinal = work->input.ordinal;
                work->worklets.front()->output.buffers.clear();
                work->workletsProcessed = 1u;
            }
            break;
        }
    }

    return C2_OK;
}

c2_status_t C2SoftAvcEnc::drain(
        uint32_t drainMode,
        const std::shared_ptr<C2BlockPool> &pool) {
    // TODO: use IVE_CMD_CTL_FLUSH?
    (void)drainMode;
    (void)pool;
    return C2_OK;
    return drainInternal(drainMode, pool, nullptr);
}


class C2SoftAvcEncFactory : public C2ComponentFactory {
public:
    C2SoftAvcEncFactory() : mHelper(std::static_pointer_cast<C2ReflectorHelper>(
+10 −2
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ namespace android {
#define LEN_STATUS_BUFFER        (10  * 1024)
#define MAX_VBV_BUFF_SIZE        (120 * 16384)
#define MAX_NUM_IO_BUFS           3
#define MAX_B_FRAMES              1

#define DEFAULT_MAX_REF_FRM         2
#define DEFAULT_MAX_REORDER_FRM     0
@@ -167,7 +168,6 @@ private:
    bool     mSpsPpsHeaderReceived;

    bool     mSawInputEOS;
    bool     mSawOutputEOS;
    bool     mSignalledError;
    bool     mIntra4x4;
    bool     mEnableFastSad;
@@ -183,6 +183,8 @@ private:
    size_t mNumMemRecords;       // Number of memory records requested by codec
    size_t mNumCores;            // Number of cores used by the codec

    std::shared_ptr<C2LinearBlock> mOutBlock;

    // configurations used by component in process
    // (TODO: keep this in intf but make them internal only)
    std::shared_ptr<C2StreamPictureSizeInfo::input> mSize;
@@ -230,7 +232,13 @@ private:
            const C2GraphicView *const input,
            uint8_t *base,
            uint32_t capacity,
            uint64_t timestamp);
            uint64_t workIndex);
    void finishWork(uint64_t workIndex,
            const std::unique_ptr<C2Work> &work,
            ive_video_encode_op_t *ps_encode_op);
    c2_status_t drainInternal(uint32_t drainMode,
            const std::shared_ptr<C2BlockPool> &pool,
            const std::unique_ptr<C2Work> &work);

    C2_DO_NOT_COPY(C2SoftAvcEnc);
};
+126 −54
Original line number Diff line number Diff line
@@ -56,10 +56,19 @@ class C2SoftHevcEnc::IntfImpl : public SimpleInterface<void>::BaseParams {
        noPrivateBuffers(); // TODO: account for our buffers here
        noInputReferences();
        noOutputReferences();
        noInputLatency();
        noTimeStretch();
        setDerivedInstance(this);

        addParameter(
                DefineParam(mActualInputDelay, C2_PARAMKEY_INPUT_DELAY)
                .withDefault(new C2PortActualDelayTuning::input(
                    DEFAULT_B_FRAMES + DEFAULT_RC_LOOKAHEAD))
                .withFields({C2F(mActualInputDelay, value).inRange(
                    0, MAX_B_FRAMES + MAX_RC_LOOKAHEAD)})
                .withSetter(
                    Setter<decltype(*mActualInputDelay)>::StrictValueWithNoDeps)
                .build());

        addParameter(
                DefineParam(mAttrib, C2_PARAMKEY_COMPONENT_ATTRIBUTES)
                .withConstValue(new C2ComponentAttributesSetting(
@@ -462,7 +471,8 @@ c2_status_t C2SoftHevcEnc::initEncParams() {
    mIvVideoColorFormat = IV_YUV_420P;
    mEncParams.s_multi_thrd_prms.i4_max_num_cores = mNumCores;
    mEncParams.s_out_strm_prms.i4_codec_profile = mHevcEncProfile;
    mEncParams.s_lap_prms.i4_rc_look_ahead_pics = 0;
    mEncParams.s_lap_prms.i4_rc_look_ahead_pics = DEFAULT_RC_LOOKAHEAD;
    mEncParams.s_coding_tools_prms.i4_max_temporal_layers = DEFAULT_B_FRAMES;

    switch (mBitrateMode->value) {
        case C2Config::BITRATE_IGNORE:
@@ -512,10 +522,9 @@ c2_status_t C2SoftHevcEnc::releaseEncoder() {

c2_status_t C2SoftHevcEnc::drain(uint32_t drainMode,
                                 const std::shared_ptr<C2BlockPool>& pool) {
    (void)drainMode;
    (void)pool;
    return C2_OK;
    return drainInternal(drainMode, pool, nullptr);
}

c2_status_t C2SoftHevcEnc::initEncoder() {
    CHECK(!mCodecCtx);
    {
@@ -552,7 +561,7 @@ c2_status_t C2SoftHevcEnc::initEncoder() {

c2_status_t C2SoftHevcEnc::setEncodeArgs(ihevce_inp_buf_t* ps_encode_ip,
                                         const C2GraphicView* const input,
                                         uint64_t timestamp) {
                                         uint64_t workIndex) {
    ihevce_static_cfg_params_t* params = &mEncParams;
    memset(ps_encode_ip, 0, sizeof(*ps_encode_ip));

@@ -696,7 +705,92 @@ c2_status_t C2SoftHevcEnc::setEncodeArgs(ihevce_inp_buf_t* ps_encode_ip,
    ps_encode_ip->i4_curr_peak_bitrate =
        params->s_tgt_lyr_prms.as_tgt_params[0].ai4_peak_bitrate[0];
    ps_encode_ip->i4_curr_rate_factor = params->s_config_prms.i4_rate_factor;
    ps_encode_ip->u8_pts = timestamp;
    ps_encode_ip->u8_pts = workIndex;
    return C2_OK;
}

void C2SoftHevcEnc::finishWork(uint64_t index,
                               const std::unique_ptr<C2Work>& work,
                               const std::shared_ptr<C2BlockPool>& pool,
                               ihevce_out_buf_t* ps_encode_op) {
    std::shared_ptr<C2LinearBlock> block;
    C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
    c2_status_t status =
        pool->fetchLinearBlock(ps_encode_op->i4_bytes_generated, usage, &block);
    if (C2_OK != status) {
        ALOGE("fetchLinearBlock for Output failed with status 0x%x", status);
        mSignalledError = true;
        work->result = status;
        work->workletsProcessed = 1u;
        return;
    }
    C2WriteView wView = block->map().get();
    if (C2_OK != wView.error()) {
        ALOGE("write view map failed with status 0x%x", wView.error());
        mSignalledError = true;
        work->result = wView.error();
        work->workletsProcessed = 1u;
        return;
    }
    memcpy(wView.data(), ps_encode_op->pu1_output_buf,
           ps_encode_op->i4_bytes_generated);

    std::shared_ptr<C2Buffer> buffer =
        createLinearBuffer(block, 0, ps_encode_op->i4_bytes_generated);

    DUMP_TO_FILE(mOutFile, ps_encode_op->pu1_output_buf,
                 ps_encode_op->i4_bytes_generated);

    if (ps_encode_op->i4_is_key_frame) {
        ALOGV("IDR frame produced");
        buffer->setInfo(std::make_shared<C2StreamPictureTypeMaskInfo::output>(
            0u /* stream id */, C2Config::SYNC_FRAME));
    }

    auto fillWork = [buffer](const std::unique_ptr<C2Work>& work) {
        work->worklets.front()->output.flags = (C2FrameData::flags_t)0;
        work->worklets.front()->output.buffers.clear();
        work->worklets.front()->output.buffers.push_back(buffer);
        work->worklets.front()->output.ordinal = work->input.ordinal;
        work->workletsProcessed = 1u;
    };
    if (work && c2_cntr64_t(index) == work->input.ordinal.frameIndex) {
        fillWork(work);
        if (mSignalledEos) {
            work->worklets.front()->output.flags =
                C2FrameData::FLAG_END_OF_STREAM;
        }
    } else {
        finish(index, fillWork);
    }
}

c2_status_t C2SoftHevcEnc::drainInternal(
        uint32_t drainMode,
        const std::shared_ptr<C2BlockPool> &pool,
        const std::unique_ptr<C2Work> &work) {

    if (drainMode == NO_DRAIN) {
        ALOGW("drain with NO_DRAIN: no-op");
        return C2_OK;
    }
    if (drainMode == DRAIN_CHAIN) {
        ALOGW("DRAIN_CHAIN not supported");
        return C2_OMITTED;
    }

    while (true) {
        ihevce_out_buf_t s_encode_op{};
        memset(&s_encode_op, 0, sizeof(s_encode_op));

        ihevce_encode(mCodecCtx, nullptr, &s_encode_op);
        if (s_encode_op.i4_bytes_generated) {
            finishWork(s_encode_op.u8_pts, work, pool, &s_encode_op);
        } else {
            if (work->workletsProcessed != 1u) fillEmptyWork(work);
            break;
        }
    }
    return C2_OK;
}

@@ -704,7 +798,7 @@ void C2SoftHevcEnc::process(const std::unique_ptr<C2Work>& work,
                            const std::shared_ptr<C2BlockPool>& pool) {
    // Initialize output work
    work->result = C2_OK;
    work->workletsProcessed = 1u;
    work->workletsProcessed = 0u;
    work->worklets.front()->output.flags = work->input.flags;

    if (mSignalledError || mSignalledEos) {
@@ -721,6 +815,7 @@ void C2SoftHevcEnc::process(const std::unique_ptr<C2Work>& work,
            ALOGE("Failed to initialize encoder : 0x%x", status);
            mSignalledError = true;
            work->result = status;
            work->workletsProcessed = 1u;
            return;
        }
    }
@@ -728,6 +823,8 @@ void C2SoftHevcEnc::process(const std::unique_ptr<C2Work>& work,
    std::shared_ptr<const C2GraphicView> view;
    std::shared_ptr<C2Buffer> inputBuffer = nullptr;
    bool eos = ((work->input.flags & C2FrameData::FLAG_END_OF_STREAM) != 0);
    if (eos) mSignalledEos = true;

    if (!work->input.buffers.empty()) {
        inputBuffer = work->input.buffers[0];
        view = std::make_shared<const C2GraphicView>(
@@ -736,13 +833,12 @@ void C2SoftHevcEnc::process(const std::unique_ptr<C2Work>& work,
            ALOGE("graphic view map err = %d", view->error());
            mSignalledError = true;
            work->result = C2_CORRUPTED;
            work->workletsProcessed = 1u;
            return;
        }
    }

    IHEVCE_PLUGIN_STATUS_T err = IHEVCE_EOK;

    fillEmptyWork(work);
    if (!mSpsPpsHeaderReceived) {
        ihevce_out_buf_t s_header_op{};
        err = ihevce_encode_header(mCodecCtx, &s_header_op);
@@ -754,6 +850,7 @@ void C2SoftHevcEnc::process(const std::unique_ptr<C2Work>& work,
                ALOGE("CSD allocation failed");
                mSignalledError = true;
                work->result = C2_NO_MEMORY;
                work->workletsProcessed = 1u;
                return;
            }
            memcpy(csd->m.value, s_header_op.pu1_output_buf,
@@ -764,35 +861,41 @@ void C2SoftHevcEnc::process(const std::unique_ptr<C2Work>& work,
            mSpsPpsHeaderReceived = true;
        }
        if (!inputBuffer) {
            work->workletsProcessed = 1u;
            return;
        }
    }
    ihevce_inp_buf_t s_encode_ip{};
    ihevce_out_buf_t s_encode_op{};
    uint64_t timestamp = work->input.ordinal.timestamp.peekull();
    uint64_t workIndex = work->input.ordinal.frameIndex.peekull();

    status = setEncodeArgs(&s_encode_ip, view.get(), timestamp);
    status = setEncodeArgs(&s_encode_ip, view.get(), workIndex);
    if (C2_OK != status) {
        ALOGE("setEncodeArgs failed : 0x%x", status);
        mSignalledError = true;
        work->result = status;
        work->workletsProcessed = 1u;
        return;
    }

    uint64_t timeDelay = 0;
    uint64_t timeTaken = 0;
    memset(&s_encode_op, 0, sizeof(s_encode_op));
    GETTIME(&mTimeStart, nullptr);
    TIME_DIFF(mTimeEnd, mTimeStart, timeDelay);

    ihevce_inp_buf_t* ps_encode_ip = (inputBuffer) ? &s_encode_ip : nullptr;

    err = ihevce_encode(mCodecCtx, ps_encode_ip, &s_encode_op);
    if (inputBuffer) {
        err = ihevce_encode(mCodecCtx, &s_encode_ip, &s_encode_op);
        if (IHEVCE_EOK != err) {
            ALOGE("Encode Frame failed : 0x%x", err);
            mSignalledError = true;
            work->result = C2_CORRUPTED;
            work->workletsProcessed = 1u;
            return;
        }
    } else if (!eos) {
        fillEmptyWork(work);
    }

    GETTIME(&mTimeEnd, nullptr);
    /* Compute time taken for decode() */
@@ -802,42 +905,11 @@ void C2SoftHevcEnc::process(const std::unique_ptr<C2Work>& work,
          (int)timeDelay, s_encode_op.i4_bytes_generated);

    if (s_encode_op.i4_bytes_generated) {
        std::shared_ptr<C2LinearBlock> block;
        C2MemoryUsage usage = {C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE};
        status = pool->fetchLinearBlock(s_encode_op.i4_bytes_generated, usage, &block);
        if (C2_OK != status) {
            ALOGE("fetchLinearBlock for Output failed with status 0x%x", status);
            work->result = C2_NO_MEMORY;
            mSignalledError = true;
            return;
        }
        C2WriteView wView = block->map().get();
        if (C2_OK != wView.error()) {
            ALOGE("write view map failed with status 0x%x", wView.error());
            work->result = wView.error();
            mSignalledError = true;
            return;
        finishWork(s_encode_op.u8_pts, work, pool, &s_encode_op);
    }
        memcpy(wView.data(), s_encode_op.pu1_output_buf,
               s_encode_op.i4_bytes_generated);

        std::shared_ptr<C2Buffer> buffer =
            createLinearBuffer(block, 0, s_encode_op.i4_bytes_generated);

        DUMP_TO_FILE(mOutFile, s_encode_op.pu1_output_buf,
                     s_encode_op.i4_bytes_generated);

        work->worklets.front()->output.ordinal.timestamp = s_encode_op.u8_pts;
        if (s_encode_op.i4_is_key_frame) {
            ALOGV("IDR frame produced");
            buffer->setInfo(
                std::make_shared<C2StreamPictureTypeMaskInfo::output>(
                    0u /* stream id */, C2Config::SYNC_FRAME));
        }
        work->worklets.front()->output.buffers.push_back(buffer);
    }
    if (eos) {
        mSignalledEos = true;
        drainInternal(DRAIN_COMPONENT_WITH_EOS, pool, work);
    }
}

+13 −3

File changed.

Preview size limit exceeded, changes collapsed.