aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-14 01:01:14 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-14 01:01:14 +0000
commit0e5b314e329a04c291a001337c1243c9e9eddb55 (patch)
tree16f08d9b01325bb5be6ce325d095648e94f9d94f
parent54f5dd1ef793928aeb8180d5287e217422a8794e (diff)
parent9c42d7b37592420d4c44b4810ed134e92f474b4b (diff)
downloadgoldfish-opengl-0e5b314e329a04c291a001337c1243c9e9eddb55.tar.gz
Snap for 8590907 from 9c42d7b37592420d4c44b4810ed134e92f474b4b to tm-release
Change-Id: I98ecdd7065ce4377932665af84eaf0f6b87e0c4a
-rw-r--r--system/codecs/c2/decoders/hevcdec/Android.bp4
-rw-r--r--system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp84
-rw-r--r--system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.h3
-rw-r--r--system/codecs/c2/decoders/hevcdec/GoldfishHevcHelper.cpp326
-rw-r--r--system/codecs/c2/decoders/hevcdec/GoldfishHevcHelper.h67
5 files changed, 443 insertions, 41 deletions
diff --git a/system/codecs/c2/decoders/hevcdec/Android.bp b/system/codecs/c2/decoders/hevcdec/Android.bp
index fddd276d..f1b9c82d 100644
--- a/system/codecs/c2/decoders/hevcdec/Android.bp
+++ b/system/codecs/c2/decoders/hevcdec/Android.bp
@@ -15,6 +15,7 @@ cc_library_shared {
],
srcs: ["C2GoldfishHevcDec.cpp",
+ "GoldfishHevcHelper.cpp",
"MediaHevcDecoder.cpp",
],
@@ -28,5 +29,8 @@ cc_library_shared {
"libgralloc_cb.ranchu",
],
+ static_libs: ["libhevcdec",
+ ],
+
}
diff --git a/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp b/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp
index 51934d5d..b2f684a6 100644
--- a/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp
+++ b/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.cpp
@@ -457,6 +457,7 @@ status_t C2GoldfishHevcDec::createDecoder() {
}
mContext->initHevcContext(mWidth, mHeight, mWidth, mHeight,
MediaHevcDecoder::PixelFormat::YUV420P);
+
return OK;
}
@@ -884,11 +885,6 @@ void C2GoldfishHevcDec::process(const std::unique_ptr<C2Work> &work,
return;
}
- if (false == mHeaderDecoded) {
- /* Decode header and get dimensions */
- setParams(mStride);
- }
-
DDD("flag is %x", work->input.flags);
if (work->input.flags & C2FrameData::FLAG_CODEC_CONFIG) {
hasPicture = false;
@@ -903,9 +899,50 @@ void C2GoldfishHevcDec::process(const std::unique_ptr<C2Work> &work,
removePts(mPts);
}
+ bool whChanged = false;
+ if (GoldfishHevcHelper::isVpsFrame(mInPBuffer, mInPBufferSize)) {
+ mHevcHelper.reset(new GoldfishHevcHelper(mWidth, mHeight));
+ whChanged = mHevcHelper->decodeHeader(mInPBuffer, mInPBufferSize);
+ if (whChanged) {
+ DDD("w changed from old %d to new %d\n", mWidth, mHevcHelper->getWidth());
+ DDD("h changed from old %d to new %d\n", mHeight, mHevcHelper->getHeight());
+ if (1) {
+ drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
+ resetDecoder();
+ resetPlugin();
+ work->workletsProcessed = 0u;
+ }
+ {
+ mWidth = mHevcHelper->getWidth();
+ mHeight = mHevcHelper->getHeight();
+ C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
+ std::vector<std::unique_ptr<C2SettingResult>> failures;
+ c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
+ if (err == OK) {
+ work->worklets.front()->output.configUpdate.push_back(
+ C2Param::Copy(size));
+ ensureDecoderState(pool);
+ } else {
+ ALOGE("Cannot set width and height");
+ mSignalledError = true;
+ work->workletsProcessed = 1u;
+ work->result = C2_CORRUPTED;
+ return;
+ }
+ }
+ if (!mContext) {
+ DDD("creating decoder context to host in process work");
+ checkMode(pool);
+ createDecoder();
+ }
+ continue;//return;
+ } // end of whChanged
+ } // end of isVpsFrame
+
uint32_t delay;
GETTIME(&mTimeStart, nullptr);
TIME_DIFF(mTimeEnd, mTimeStart, delay);
+ (void)delay;
//(void) ivdec_api_function(mDecHandle, &s_decode_ip, &s_decode_op);
DDD("decoding");
hevc_result_t hevcRes =
@@ -922,44 +959,9 @@ void C2GoldfishHevcDec::process(const std::unique_ptr<C2Work> &work,
uint32_t decodeTime;
GETTIME(&mTimeEnd, nullptr);
TIME_DIFF(mTimeStart, mTimeEnd, decodeTime);
- }
- // TODO: handle res change
- if (0) {
- DDD("resolution changed");
- drainInternal(DRAIN_COMPONENT_NO_EOS, pool, work);
- resetDecoder();
- resetPlugin();
- work->workletsProcessed = 0u;
-
- /* Decode header and get new dimensions */
- setParams(mStride);
- // (void) ivdec_api_function(mDecHandle, &s_decode_ip,
- // &s_decode_op);
+ (void)decodeTime;
}
if (mImg.data != nullptr) {
- // check for new width and height
- auto decodedW = mImg.width;
- auto decodedH = mImg.height;
- if (decodedW != mWidth || decodedH != mHeight) {
- mWidth = decodedW;
- mHeight = decodedH;
-
- C2StreamPictureSizeInfo::output size(0u, mWidth, mHeight);
- std::vector<std::unique_ptr<C2SettingResult>> failures;
- c2_status_t err = mIntf->config({&size}, C2_MAY_BLOCK, &failures);
- if (err == OK) {
- work->worklets.front()->output.configUpdate.push_back(
- C2Param::Copy(size));
- ensureDecoderState(pool);
- } else {
- ALOGE("Cannot set width and height");
- mSignalledError = true;
- work->workletsProcessed = 1u;
- work->result = C2_CORRUPTED;
- return;
- }
- }
-
DDD("got data %" PRIu64 " with pts %" PRIu64, getWorkIndex(mImg.pts), mImg.pts);
mHeaderDecoded = true;
copyImageData(mImg);
diff --git a/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.h b/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.h
index 575689a1..fe080cfa 100644
--- a/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.h
+++ b/system/codecs/c2/decoders/hevcdec/C2GoldfishHevcDec.h
@@ -22,6 +22,7 @@
#include <media/stagefright/foundation/ColorUtils.h>
#include "MediaHevcDecoder.h"
+#include "GoldfishHevcHelper.h"
#include <SimpleC2Component.h>
#include <atomic>
#include <map>
@@ -152,6 +153,8 @@ class C2GoldfishHevcDec : public SimpleC2Component {
std::vector<uint8_t> mCsd1;
void decodeHeaderAfterFlush();
+ std::unique_ptr<GoldfishHevcHelper> mHevcHelper;
+
C2_DO_NOT_COPY(C2GoldfishHevcDec);
};
diff --git a/system/codecs/c2/decoders/hevcdec/GoldfishHevcHelper.cpp b/system/codecs/c2/decoders/hevcdec/GoldfishHevcHelper.cpp
new file mode 100644
index 00000000..5bf2672d
--- /dev/null
+++ b/system/codecs/c2/decoders/hevcdec/GoldfishHevcHelper.cpp
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GoldfishHevcHelper.h"
+
+#define LOG_TAG "GoldfishHevcHelper"
+#include <log/log.h>
+
+#include "ihevc_typedefs.h"
+#include "ihevcd_cxa.h"
+
+#define DEBUG 0
+#if DEBUG
+#define DDD(...) ALOGD(__VA_ARGS__)
+#else
+#define DDD(...) ((void)0)
+#endif
+
+
+#include <Codec2Mapper.h>
+
+#define ivdec_api_function ihevcd_cxa_api_function
+#define ivdext_create_ip_t ihevcd_cxa_create_ip_t
+#define ivdext_create_op_t ihevcd_cxa_create_op_t
+#define ivdext_delete_ip_t ihevcd_cxa_delete_ip_t
+#define ivdext_delete_op_t ihevcd_cxa_delete_op_t
+#define ivdext_ctl_set_num_cores_ip_t ihevcd_cxa_ctl_set_num_cores_ip_t
+#define ivdext_ctl_set_num_cores_op_t ihevcd_cxa_ctl_set_num_cores_op_t
+#define ivdext_ctl_get_vui_params_ip_t ihevcd_cxa_ctl_get_vui_params_ip_t
+#define ivdext_ctl_get_vui_params_op_t ihevcd_cxa_ctl_get_vui_params_op_t
+#define ALIGN128(x) ((((x) + 127) >> 7) << 7)
+#define MAX_NUM_CORES 4
+#define IVDEXT_CMD_CTL_SET_NUM_CORES \
+ (IVD_CONTROL_API_COMMAND_TYPE_T) IHEVCD_CXA_CMD_CTL_SET_NUM_CORES
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+namespace android {
+
+static void *ivd_aligned_malloc(void *ctxt, WORD32 alignment, WORD32 size) {
+ (void) ctxt;
+ return memalign(alignment, size);
+}
+
+static void ivd_aligned_free(void *ctxt, void *mem) {
+ (void) ctxt;
+ free(mem);
+}
+
+
+GoldfishHevcHelper::GoldfishHevcHelper(int w, int h):mWidth(w),mHeight(h) { createDecoder(); }
+
+GoldfishHevcHelper::~GoldfishHevcHelper() {
+ destroyDecoder();
+ if (mOutBufferFlush) {
+ ivd_aligned_free(nullptr, mOutBufferFlush);
+ mOutBufferFlush = nullptr;
+ }
+}
+
+void GoldfishHevcHelper::createDecoder() {
+ ivdext_create_ip_t s_create_ip = {};
+ ivdext_create_op_t s_create_op = {};
+
+ s_create_ip.s_ivd_create_ip_t.u4_size = sizeof(ivdext_create_ip_t);
+ s_create_ip.s_ivd_create_ip_t.e_cmd = IVD_CMD_CREATE;
+ s_create_ip.s_ivd_create_ip_t.u4_share_disp_buf = 0;
+ s_create_ip.s_ivd_create_ip_t.e_output_format = mIvColorformat;
+ s_create_ip.s_ivd_create_ip_t.pf_aligned_alloc = ivd_aligned_malloc;
+ s_create_ip.s_ivd_create_ip_t.pf_aligned_free = ivd_aligned_free;
+ s_create_ip.s_ivd_create_ip_t.pv_mem_ctxt = nullptr;
+ s_create_op.s_ivd_create_op_t.u4_size = sizeof(ivdext_create_op_t);
+ IV_API_CALL_STATUS_T status =
+ ivdec_api_function(mDecHandle, &s_create_ip, &s_create_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("error in %s: 0x%x", __func__,
+ s_create_op.s_ivd_create_op_t.u4_error_code);
+ return;
+ }
+ mDecHandle = (iv_obj_t *)s_create_op.s_ivd_create_op_t.pv_handle;
+ mDecHandle->pv_fxns = (void *)ivdec_api_function;
+ mDecHandle->u4_size = sizeof(iv_obj_t);
+
+ mStride = ALIGN128(mWidth);
+
+ setNumCores();
+}
+
+void GoldfishHevcHelper::destroyDecoder() {
+ if (mDecHandle) {
+ ivdext_delete_ip_t s_delete_ip = {};
+ ivdext_delete_op_t s_delete_op = {};
+
+ s_delete_ip.s_ivd_delete_ip_t.u4_size = sizeof(ivdext_delete_ip_t);
+ s_delete_ip.s_ivd_delete_ip_t.e_cmd = IVD_CMD_DELETE;
+ s_delete_op.s_ivd_delete_op_t.u4_size = sizeof(ivdext_delete_op_t);
+ IV_API_CALL_STATUS_T status =
+ ivdec_api_function(mDecHandle, &s_delete_ip, &s_delete_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("error in %s: 0x%x", __func__,
+ s_delete_op.s_ivd_delete_op_t.u4_error_code);
+ }
+ mDecHandle = nullptr;
+ }
+}
+
+void GoldfishHevcHelper::setNumCores() {
+ ivdext_ctl_set_num_cores_ip_t s_set_num_cores_ip = {};
+ ivdext_ctl_set_num_cores_op_t s_set_num_cores_op = {};
+
+ s_set_num_cores_ip.u4_size = sizeof(ivdext_ctl_set_num_cores_ip_t);
+ s_set_num_cores_ip.e_cmd = IVD_CMD_VIDEO_CTL;
+ s_set_num_cores_ip.e_sub_cmd = IVDEXT_CMD_CTL_SET_NUM_CORES;
+ s_set_num_cores_ip.u4_num_cores = mNumCores;
+ s_set_num_cores_op.u4_size = sizeof(ivdext_ctl_set_num_cores_op_t);
+ IV_API_CALL_STATUS_T status = ivdec_api_function(
+ mDecHandle, &s_set_num_cores_ip, &s_set_num_cores_op);
+ if (IV_SUCCESS != status) {
+ DDD("error in %s: 0x%x", __func__, s_set_num_cores_op.u4_error_code);
+ }
+}
+
+void GoldfishHevcHelper::resetDecoder() {
+ ivd_ctl_reset_ip_t s_reset_ip = {};
+ ivd_ctl_reset_op_t s_reset_op = {};
+
+ s_reset_ip.u4_size = sizeof(ivd_ctl_reset_ip_t);
+ s_reset_ip.e_cmd = IVD_CMD_VIDEO_CTL;
+ s_reset_ip.e_sub_cmd = IVD_CMD_CTL_RESET;
+ s_reset_op.u4_size = sizeof(ivd_ctl_reset_op_t);
+ IV_API_CALL_STATUS_T status =
+ ivdec_api_function(mDecHandle, &s_reset_ip, &s_reset_op);
+ if (IV_SUCCESS != status) {
+ ALOGE("error in %s: 0x%x", __func__, s_reset_op.u4_error_code);
+ }
+ setNumCores();
+}
+
+void GoldfishHevcHelper::setParams(size_t stride,
+ IVD_VIDEO_DECODE_MODE_T dec_mode) {
+ ihevcd_cxa_ctl_set_config_ip_t s_hevcd_set_dyn_params_ip = {};
+ ihevcd_cxa_ctl_set_config_op_t s_hevcd_set_dyn_params_op = {};
+ ivd_ctl_set_config_ip_t *ps_set_dyn_params_ip =
+ &s_hevcd_set_dyn_params_ip.s_ivd_ctl_set_config_ip_t;
+ ivd_ctl_set_config_op_t *ps_set_dyn_params_op =
+ &s_hevcd_set_dyn_params_op.s_ivd_ctl_set_config_op_t;
+
+ ps_set_dyn_params_ip->u4_size = sizeof(ihevcd_cxa_ctl_set_config_ip_t);
+ ps_set_dyn_params_ip->e_cmd = IVD_CMD_VIDEO_CTL;
+ ps_set_dyn_params_ip->e_sub_cmd = IVD_CMD_CTL_SETPARAMS;
+ ps_set_dyn_params_ip->u4_disp_wd = (UWORD32)stride;
+ ps_set_dyn_params_ip->e_frm_skip_mode = IVD_SKIP_NONE;
+ ps_set_dyn_params_ip->e_frm_out_mode = IVD_DISPLAY_FRAME_OUT;
+ ps_set_dyn_params_ip->e_vid_dec_mode = dec_mode;
+ ps_set_dyn_params_op->u4_size = sizeof(ihevcd_cxa_ctl_set_config_op_t);
+ IV_API_CALL_STATUS_T status = ivdec_api_function(
+ mDecHandle, ps_set_dyn_params_ip, ps_set_dyn_params_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("error in %s: 0x%x", __func__,
+ ps_set_dyn_params_op->u4_error_code);
+ }
+}
+
+bool GoldfishHevcHelper::isVpsFrame(const uint8_t* frame, int inSize) {
+ if (inSize < 5) return false;
+ if (frame[0] == 0 && frame[1] == 0 && frame[2] == 0 && frame[3] == 1) {
+ const bool forbiddenBitIsInvalid = 0x80 & frame[4];
+ if (forbiddenBitIsInvalid) {
+ return false;
+ }
+ // nalu type is the lower 6 bits after shiftting to right 1 bit
+ uint8_t naluType = 0x3f & (frame[4] >> 1);
+ if (naluType == 32
+ || naluType == 33
+ || naluType == 34
+ ) return true;
+ else return false;
+ } else {
+ return false;
+ }
+}
+
+bool GoldfishHevcHelper::decodeHeader(const uint8_t *frame, int inSize) {
+ // should we check the header for vps/sps/pps frame ? otherwise
+ // there is no point calling decoder
+ if (!isVpsFrame(frame, inSize)) {
+ DDD("could not find valid vps frame");
+ return false;
+ } else {
+ DDD("found valid vps frame");
+ }
+
+ ihevcd_cxa_video_decode_ip_t s_hevcd_decode_ip = {};
+ ihevcd_cxa_video_decode_op_t s_hevcd_decode_op = {};
+ ivd_video_decode_ip_t *ps_decode_ip =
+ &s_hevcd_decode_ip.s_ivd_video_decode_ip_t;
+ ivd_video_decode_op_t *ps_decode_op =
+ &s_hevcd_decode_op.s_ivd_video_decode_op_t;
+
+ // setup input/output arguments to decoder
+ setDecodeArgs(ps_decode_ip, ps_decode_op, frame, mStride,
+ 0, // offset
+ inSize, // size
+ 0 // time-stamp, does not matter
+ );
+
+ setParams(mStride, IVD_DECODE_HEADER);
+
+ // now kick off the decoding
+ IV_API_CALL_STATUS_T status = ivdec_api_function(mDecHandle, ps_decode_ip, ps_decode_op);
+ if (status != IV_SUCCESS) {
+ ALOGE("failed to call decoder function for header\n");
+ ALOGE("error in %s: 0x%x", __func__,
+ ps_decode_op->u4_error_code);
+ }
+
+ if (IVD_RES_CHANGED == (ps_decode_op->u4_error_code & IVD_ERROR_MASK)) {
+ DDD("resolution changed, reset decoder");
+ resetDecoder();
+ setParams(mStride, IVD_DECODE_HEADER);
+ ivdec_api_function(mDecHandle, ps_decode_ip, ps_decode_op);
+ }
+
+ // get the w/h and update
+ if (0 < ps_decode_op->u4_pic_wd && 0 < ps_decode_op->u4_pic_ht) {
+ DDD("success decode w/h %d %d", ps_decode_op->u4_pic_wd , ps_decode_op->u4_pic_ht);
+ DDD("existing w/h %d %d", mWidth, mHeight);
+ if (ps_decode_op->u4_pic_wd != mWidth || ps_decode_op->u4_pic_ht != mHeight) {
+ mWidth = ps_decode_op->u4_pic_wd;
+ mHeight = ps_decode_op->u4_pic_ht;
+ return true;
+ } else {
+ DDD("success decode w/h, but they are the same %d %d", ps_decode_op->u4_pic_wd , ps_decode_op->u4_pic_ht);
+ }
+ } else {
+ ALOGE("could not decode w/h");
+ }
+
+ // get output delay
+ if (ps_decode_op->i4_reorder_depth >= 0) {
+ if (mOutputDelay != ps_decode_op->i4_reorder_depth) {
+ mOutputDelay = ps_decode_op->i4_reorder_depth;
+ DDD("New Output delay %d ", mOutputDelay);
+ } else {
+ DDD("same Output delay %d ", mOutputDelay);
+ }
+ }
+
+ return false;
+}
+
+bool GoldfishHevcHelper::setDecodeArgs(ivd_video_decode_ip_t *ps_decode_ip,
+ ivd_video_decode_op_t *ps_decode_op,
+ const uint8_t *inBuffer,
+ uint32_t displayStride, size_t inOffset,
+ size_t inSize, uint32_t tsMarker) {
+ uint32_t displayHeight = mHeight;
+ size_t lumaSize = displayStride * displayHeight;
+ size_t chromaSize = lumaSize >> 2;
+
+ if (mStride != displayStride) {
+ mStride = displayStride;
+ }
+
+ // force decoder to always decode header and get dimensions,
+ // hope this will be quick and cheap
+ setParams(mStride, IVD_DECODE_HEADER);
+
+ ps_decode_ip->u4_size = sizeof(ihevcd_cxa_video_decode_ip_t);
+ ps_decode_ip->e_cmd = IVD_CMD_VIDEO_DECODE;
+ if (inBuffer) {
+ ps_decode_ip->u4_ts = tsMarker;
+ ps_decode_ip->pv_stream_buffer = const_cast<uint8_t *>(inBuffer) + inOffset;
+ ps_decode_ip->u4_num_Bytes = inSize;
+ } else {
+ ps_decode_ip->u4_ts = 0;
+ ps_decode_ip->pv_stream_buffer = nullptr;
+ ps_decode_ip->u4_num_Bytes = 0;
+ }
+ DDD("setting pv_stream_buffer 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x",
+ ((uint8_t*)(ps_decode_ip->pv_stream_buffer))[0],
+ ((uint8_t*)(ps_decode_ip->pv_stream_buffer))[1],
+ ((uint8_t*)(ps_decode_ip->pv_stream_buffer))[2],
+ ((uint8_t*)(ps_decode_ip->pv_stream_buffer))[3],
+ ((uint8_t*)(ps_decode_ip->pv_stream_buffer))[4],
+ ((uint8_t*)(ps_decode_ip->pv_stream_buffer))[5],
+ ((uint8_t*)(ps_decode_ip->pv_stream_buffer))[6],
+ ((uint8_t*)(ps_decode_ip->pv_stream_buffer))[7]
+ );
+ DDD("input bytes %d", ps_decode_ip->u4_num_Bytes);
+
+ ps_decode_ip->s_out_buffer.u4_min_out_buf_size[0] = lumaSize;
+ ps_decode_ip->s_out_buffer.u4_min_out_buf_size[1] = chromaSize;
+ ps_decode_ip->s_out_buffer.u4_min_out_buf_size[2] = chromaSize;
+ if (!mOutBufferFlush) {
+ uint32_t displayStride = mStride;
+ uint32_t displayHeight = mHeight;
+ uint32_t bufferSize = displayStride * displayHeight * 3 / 2;
+ mOutBufferFlush = (uint8_t *)ivd_aligned_malloc(nullptr, 128, bufferSize);
+ }
+ {
+ ps_decode_ip->s_out_buffer.pu1_bufs[0] = mOutBufferFlush;
+ ps_decode_ip->s_out_buffer.pu1_bufs[1] = mOutBufferFlush + lumaSize;
+ ps_decode_ip->s_out_buffer.pu1_bufs[2] =
+ mOutBufferFlush + lumaSize + chromaSize;
+ }
+ ps_decode_ip->s_out_buffer.u4_num_bufs = 3;
+ ps_decode_op->u4_size = sizeof(ihevcd_cxa_video_decode_op_t);
+ ps_decode_op->u4_output_present = 0;
+
+ return true;
+}
+
+} // namespace android
diff --git a/system/codecs/c2/decoders/hevcdec/GoldfishHevcHelper.h b/system/codecs/c2/decoders/hevcdec/GoldfishHevcHelper.h
new file mode 100644
index 00000000..22615433
--- /dev/null
+++ b/system/codecs/c2/decoders/hevcdec/GoldfishHevcHelper.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GOLDFISH_HEVC_HELPER_H_
+#define GOLDFISH_HEVC_HELPER_H_
+
+#include <inttypes.h>
+#include "ihevc_typedefs.h"
+#include "ihevcd_cxa.h"
+
+
+namespace android {
+
+// this class is just to provide some functions to decode header
+// so that we know w/h of each sps
+class GoldfishHevcHelper {
+ public:
+ GoldfishHevcHelper(int w, int h);
+ ~GoldfishHevcHelper();
+
+ // check whether the frame is vps; typical hevc will have
+ // a frame that is vps/sps/pps together
+ static bool isVpsFrame(const uint8_t* frame, int inSize);
+ public:
+ // return true if decoding finds out w/h changed;
+ // otherwise false
+ bool decodeHeader(const uint8_t *frame, int inSize);
+ int getWidth() const { return mWidth; }
+ int getHeight() const { return mHeight; }
+
+ private:
+ void createDecoder();
+ void destroyDecoder();
+ void resetDecoder();
+ void setNumCores();
+ void setParams(size_t stride, IVD_VIDEO_DECODE_MODE_T dec_mode);
+ bool setDecodeArgs(ivd_video_decode_ip_t *ps_decode_ip,
+ ivd_video_decode_op_t *ps_decode_op,
+ const uint8_t *inBuffer, uint32_t displayStride,
+ size_t inOffset, size_t inSize, uint32_t tsMarker);
+
+ private:
+ iv_obj_t *mDecHandle = nullptr;
+ int mWidth = 320;
+ int mHeight = 240;
+ int mNumCores = 1;
+ int mStride = 16;
+ int mOutputDelay = 8; // default
+ uint8_t* mOutBufferFlush = nullptr;
+ IV_COLOR_FORMAT_T mIvColorformat = IV_YUV_420P;
+};
+
+} // namespace android
+#endif