From 4695642189701a745de4ec3e1415da64d98723e6 Mon Sep 17 00:00:00 2001 From: dvab-sarma Date: Fri, 28 Nov 2025 20:03:56 -0600 Subject: [PATCH] minor modifications minor modifications were added as a part of testing codec2 service on rockchip SoC. These mods are only for testing and wouldn't impact the functionality --- .vscode/settings.json | 12 +++ Android.bp | 1 + C2FFMPEGVideoDecodeComponent.cpp | 125 +++++++++++++++++++++++++++++-- C2FFMPEGVideoDecodeComponent.h | 8 +- ffmpeg_utils/ffmpeg_hwaccel.c | 27 +++++-- ffmpeg_utils/ffmpeg_hwaccel.h | 10 +++ 6 files changed, 168 insertions(+), 15 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f3fc25a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "files.associations": { + "bitset": "cpp", + "forward_list": "cpp", + "array": "cpp", + "string": "cpp", + "string_view": "cpp", + "span": "cpp", + "vector": "cpp", + "__locale": "cpp" + } +} \ No newline at end of file diff --git a/Android.bp b/Android.bp index 8d38a08..6e165f7 100644 --- a/Android.bp +++ b/Android.bp @@ -28,6 +28,7 @@ cc_defaults { "libswresample", "libswscale", "libutils", + "libyuv", ], } diff --git a/C2FFMPEGVideoDecodeComponent.cpp b/C2FFMPEGVideoDecodeComponent.cpp index 1d33485..44e59ac 100644 --- a/C2FFMPEGVideoDecodeComponent.cpp +++ b/C2FFMPEGVideoDecodeComponent.cpp @@ -23,6 +23,7 @@ #include "C2FFMPEGVideoDecodeComponent.h" #include "ffmpeg_hwaccel.h" + #define DEBUG_FRAMES 0 #define DEBUG_WORKQUEUE 0 #define DEBUG_EXTRADATA 0 @@ -282,6 +283,95 @@ c2_status_t C2FFMPEGVideoDecodeComponent::getOutputBuffer(C2GraphicView* outBuff return C2_OK; } +/*NOTE - This function was added to test the performance difference between Libyuv vs sws_scale. + Since the tests are not completed. Keeping it here.*/ +// c2_status_t C2FFMPEGVideoDecodeComponent::getOutputBuffer(C2GraphicView* outBuffer) { +// // output planes +// uint8_t* dst_y = outBuffer->data()[C2PlanarLayout::PLANE_Y]; +// uint8_t* dst_u = outBuffer->data()[C2PlanarLayout::PLANE_U]; +// uint8_t* dst_v = outBuffer->data()[C2PlanarLayout::PLANE_V]; + +// C2PlanarLayout layout = outBuffer->layout(); +// int dst_stride_y = layout.planes[C2PlanarLayout::PLANE_Y].rowInc; +// int dst_stride_u = layout.planes[C2PlanarLayout::PLANE_U].rowInc; +// int dst_stride_v = layout.planes[C2PlanarLayout::PLANE_V].rowInc; + +// // validate frame pointer +// if (!mFrame) { +// ALOGE("getOutputBuffer: invalid frame"); +// return C2_BAD_STATE; +// } + +// const int width = mFrame->width; +// const int height = mFrame->height; + + +// if (mFrame->format == AV_PIX_FMT_NV12) { +// //ALOGE("getOutputBuffer: libyuv: initiated"); +// const uint8_t* src_y = mFrame->data[0]; +// const uint8_t* src_uv = mFrame->data[1]; +// int src_stride_y = mFrame->linesize[0]; +// int src_stride_uv = mFrame->linesize[1]; + +// if (src_y && src_uv) { +// // Use libyuv for fast NV12->I420 conversion (hardware decoded only) +// // NV12ToI420 handles interleaved UV conversion efficiently +// int ret = libyuv::NV12ToI420( +// src_y, src_stride_y, +// src_uv, src_stride_uv, +// dst_y, dst_stride_y, +// dst_u, dst_stride_u, +// dst_v, dst_stride_v, +// width, height); + +// if (ret == 0) { +// //ALOGE("getOutputBuffer: libyuv: NV12->I420 (hw decode) conversion successful"); +// return C2_OK; +// } + +// //ALOGE("getOutputBuffer: libyuv: NV12->I420 conversion failed with ret: %d", ret); +// } else { +// //ALOGE("getOutputBuffer: libyuv: invalid source buffers for NV12"); +// } +// // Fall through to sws fallback only if NV12 conversion failed +// } + +// // Fallback: use sws_scale for software decoded formats (YUV422, YUV420P) or if NV12 conversion failed +// // Fallback: use sws_scale for other formats or if libyuv fails +// uint8_t* data[4]; +// int linesize[4]; +// data[0] = outBuffer->data()[C2PlanarLayout::PLANE_Y]; +// data[1] = outBuffer->data()[C2PlanarLayout::PLANE_U]; +// data[2] = outBuffer->data()[C2PlanarLayout::PLANE_V]; +// //data[3] = NULL; +// linesize[0] = layout.planes[C2PlanarLayout::PLANE_Y].rowInc; +// linesize[1] = layout.planes[C2PlanarLayout::PLANE_U].rowInc; +// linesize[2] = layout.planes[C2PlanarLayout::PLANE_V].rowInc; +// //linesize[3] = 0; + +// struct SwsContext* currentImgConvertCtx = mImgConvertCtx; +// mImgConvertCtx = sws_getCachedContext( +// currentImgConvertCtx, +// width, height, (AVPixelFormat)mFrame->format, +// width, height, AV_PIX_FMT_YUV420P, +// SWS_BICUBIC, NULL, NULL, NULL); + +// if (mImgConvertCtx && mImgConvertCtx != currentImgConvertCtx) { +// ALOGD("getOutputBuffer: created video converter - %s => %s", +// av_get_pix_fmt_name((AVPixelFormat)mFrame->format), +// av_get_pix_fmt_name(AV_PIX_FMT_YUV420P)); +// } else if (!mImgConvertCtx) { +// ALOGE("getOutputBuffer: cannot initialize the conversion context"); +// return C2_NO_MEMORY; +// } + +// sws_scale(mImgConvertCtx, mFrame->data, mFrame->linesize, +// 0, height, data, linesize); + +// ALOGD("getOutputBuffer: sws_scale conversion complete"); +// return C2_OK; +// } + static void fillEmptyWork(const std::unique_ptr& work) { work->worklets.front()->output.flags = (C2FrameData::flags_t)(work->input.flags & C2FrameData::FLAG_END_OF_STREAM); @@ -306,17 +396,38 @@ void C2FFMPEGVideoDecodeComponent::pushPendingWork(const std::unique_ptr uint32_t newOutputDelay = outputDelay; std::vector> configUpdate; + uint32_t frameSize = mFrame->height * mFrame->width; + switch (mCtx->codec_id) { case AV_CODEC_ID_HEVC: case AV_CODEC_ID_H264: - // Increase output delay step-wise. - if (outputDelay >= 18u) { - newOutputDelay = 34u; - } else if (outputDelay >= 8u) { - newOutputDelay = 18u; - } else { - newOutputDelay = 8u; + + if(frameSize <= RKVDEC_1080P_PIXELS){ + if (outputDelay >= 8u){ + newOutputDelay = 16u; + } + else { + newOutputDelay = 8u; + } + } else if (frameSize <= RKVDEC_4K_PIXELS){ + if(outputDelay >= 16u){ + newOutputDelay = 32u; + } + else { + newOutputDelay = 16u; + } + } else if (frameSize <= RKVDEC_8K_PIXELS){ + if (outputDelay >= 32u){ + newOutputDelay = 64u; + } else if (outputDelay >= 16u) { + newOutputDelay = 32u; + } else { + newOutputDelay = 16u; + } } + + + break; default: // Other codecs use constant output delay. diff --git a/C2FFMPEGVideoDecodeComponent.h b/C2FFMPEGVideoDecodeComponent.h index 241ddcf..3f4413f 100644 --- a/C2FFMPEGVideoDecodeComponent.h +++ b/C2FFMPEGVideoDecodeComponent.h @@ -23,6 +23,12 @@ #include "C2FFMPEGCommon.h" #include "C2FFMPEGVideoDecodeInterface.h" +#include "libyuv/convert.h" + +#define RKVDEC_1080P_PIXELS (1920 * 1080) +#define RKVDEC_4K_PIXELS (4096 * 2304) +#define RKVDEC_8K_PIXELS (7680 * 4320) + namespace android { typedef std::pair PendingWork; @@ -75,7 +81,7 @@ private: bool mCodecAlreadyOpened; bool mExtradataReady; bool mEOSSignalled; - std::deque mPendingWorkQueue; + std::deque mPendingWorkQueue; }; } // namespace android diff --git a/ffmpeg_utils/ffmpeg_hwaccel.c b/ffmpeg_utils/ffmpeg_hwaccel.c index f6cdcf1..912497b 100644 --- a/ffmpeg_utils/ffmpeg_hwaccel.c +++ b/ffmpeg_utils/ffmpeg_hwaccel.c @@ -4,10 +4,12 @@ #include #include "ffmpeg_hwaccel.h" -#include "libavutil/opt.h" + + + int ffmpeg_hwaccel_init(AVCodecContext *avctx) { - if (avctx->codec_id != AV_CODEC_ID_HEVC || !property_get_bool("persist.vendor.ffmpeg_codec2.v4l2.h265", 0)) + if (!property_get_bool("persist.vendor.ffmpeg_codec2.v4l2.h265", 0)) return 0; // Find codec information. At this point, AVCodecContext.codec may not be @@ -69,19 +71,30 @@ int ffmpeg_hwaccel_get_frame(AVCodecContext *avctx __unused, AVFrame *frame) { return AVERROR(ENOMEM); } - output->format = AV_PIX_FMT_NV12; + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get((int)frame->format); + + bool is_10bit = (desc && desc->comp[0].depth > 8); + + if(is_10bit){ + output->format = AV_PIX_FMT_NV15; + + } + else { + output->format = AV_PIX_FMT_NV12; + + } + + err = av_hwframe_transfer_data(output, frame, 0); if (err < 0) { - ALOGE("ffmpeg_hwaccel_get_frame failed to transfer data: %s (%08x)", - av_err2str(err), err); + goto fail; } err = av_frame_copy_props(output, frame); if (err < 0) { - ALOGE("ffmpeg_hwaccel_get_frame failed to copy frame properties: %s (%08x)", - av_err2str(err), err); + goto fail; } diff --git a/ffmpeg_utils/ffmpeg_hwaccel.h b/ffmpeg_utils/ffmpeg_hwaccel.h index 0d520d1..777dcf0 100644 --- a/ffmpeg_utils/ffmpeg_hwaccel.h +++ b/ffmpeg_utils/ffmpeg_hwaccel.h @@ -1,11 +1,21 @@ #ifndef FFMPEG_HWACCEL_H #define FFMPEG_HWACCEL_H + #ifdef __cplusplus extern "C" { + + #endif #include "libavcodec/avcodec.h" +#include "libavformat/avformat.h" +#include "libswscale/swscale.h" +#include "libswresample/swresample.h" +#include "libavutil/opt.h" +#include "libavutil/pixdesc.h" + + extern int ffmpeg_hwaccel_init(AVCodecContext *avctx); extern void ffmpeg_hwaccel_deinit(AVCodecContext *avctx);