Loading media/codec2/components/avc/C2SoftAvcEnc.cpp +170 −47 Original line number Diff line number Diff line Loading @@ -55,7 +55,6 @@ public: noPrivateBuffers(); // TODO: account for our buffers here noInputReferences(); noOutputReferences(); noInputLatency(); noTimeStretch(); setDerivedInstance(this); Loading @@ -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.)) Loading Loading @@ -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) { Loading @@ -380,7 +386,7 @@ C2SoftAvcEnc::C2SoftAvcEnc( } C2SoftAvcEnc::~C2SoftAvcEnc() { releaseEncoder(); onRelease(); } c2_status_t C2SoftAvcEnc::onInit() { Loading @@ -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() { Loading Loading @@ -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; Loading @@ -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 */ Loading Loading @@ -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) { Loading @@ -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); Loading @@ -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", Loading @@ -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); Loading @@ -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 Loading Loading @@ -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; } Loading @@ -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); Loading Loading @@ -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>( Loading media/codec2/components/avc/C2SoftAvcEnc.h +10 −2 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -167,7 +168,6 @@ private: bool mSpsPpsHeaderReceived; bool mSawInputEOS; bool mSawOutputEOS; bool mSignalledError; bool mIntra4x4; bool mEnableFastSad; Loading @@ -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; Loading Loading @@ -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); }; Loading media/codec2/components/hevc/C2SoftHevcEnc.cpp +126 −54 Original line number Diff line number Diff line Loading @@ -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( Loading Loading @@ -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: Loading Loading @@ -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); { Loading Loading @@ -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)); Loading Loading @@ -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; } Loading @@ -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) { Loading @@ -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; } } Loading @@ -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>( Loading @@ -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); Loading @@ -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, Loading @@ -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() */ Loading @@ -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); } } Loading media/codec2/components/hevc/C2SoftHevcEnc.h +13 −3 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
media/codec2/components/avc/C2SoftAvcEnc.cpp +170 −47 Original line number Diff line number Diff line Loading @@ -55,7 +55,6 @@ public: noPrivateBuffers(); // TODO: account for our buffers here noInputReferences(); noOutputReferences(); noInputLatency(); noTimeStretch(); setDerivedInstance(this); Loading @@ -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.)) Loading Loading @@ -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) { Loading @@ -380,7 +386,7 @@ C2SoftAvcEnc::C2SoftAvcEnc( } C2SoftAvcEnc::~C2SoftAvcEnc() { releaseEncoder(); onRelease(); } c2_status_t C2SoftAvcEnc::onInit() { Loading @@ -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() { Loading Loading @@ -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; Loading @@ -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 */ Loading Loading @@ -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) { Loading @@ -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); Loading @@ -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", Loading @@ -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); Loading @@ -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 Loading Loading @@ -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; } Loading @@ -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); Loading Loading @@ -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>( Loading
media/codec2/components/avc/C2SoftAvcEnc.h +10 −2 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -167,7 +168,6 @@ private: bool mSpsPpsHeaderReceived; bool mSawInputEOS; bool mSawOutputEOS; bool mSignalledError; bool mIntra4x4; bool mEnableFastSad; Loading @@ -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; Loading Loading @@ -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); }; Loading
media/codec2/components/hevc/C2SoftHevcEnc.cpp +126 −54 Original line number Diff line number Diff line Loading @@ -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( Loading Loading @@ -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: Loading Loading @@ -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); { Loading Loading @@ -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)); Loading Loading @@ -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; } Loading @@ -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) { Loading @@ -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; } } Loading @@ -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>( Loading @@ -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); Loading @@ -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, Loading @@ -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() */ Loading @@ -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); } } Loading
media/codec2/components/hevc/C2SoftHevcEnc.h +13 −3 File changed.Preview size limit exceeded, changes collapsed. Show changes