luckfox-pico-sdk/media/samples/example/test/sample_venc_stresstest.c
luckfox-eng29 8f34c2760d project:build.sh: Added fastboot support; custom modifications to U-Boot and kernel implemented using patches.
project:cfg:BoardConfig_IPC: Added fastboot BoardConfig file and firmware post-scripts, distinguishing between
the BoardConfigs for Luckfox Pico Pro and Luckfox Pico Max. project:app: Added fastboot_client and rk_smart_door
for quick boot applications; updated rkipc app to adapt to the latest media library. media:samples: Added more
usage examples. media:rockit: Fixed bugs; removed support for retrieving data frames from VPSS. media:isp:
Updated rkaiq library and related tools to support connection to RKISP_Tuner. sysdrv:Makefile: Added support for
compiling drv_ko on Luckfox Pico Ultra W using Ubuntu; added support for custom root filesystem.
sysdrv:tools:board: Updated Buildroot optional mirror sources, updated some software versions, and stored device
tree files and configuration files that undergo multiple modifications for U-Boot and kernel separately.
sysdrv:source:mcu: Used RISC-V MCU SDK with RT-Thread system, mainly for initializing camera AE during quick
boot. sysdrv:source:uboot: Added support for fastboot; added high baud rate DDR bin for serial firmware upgrades.
sysdrv:source:kernel: Upgraded to version 5.10.160; increased NPU frequency for RV1106G3; added support for
fastboot.

Signed-off-by: luckfox-eng29 <eng29@luckfox.com>
2024-10-14 09:47:04 +08:00

1180 lines
35 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright 2023 Rockchip Electronics Co. LTD
*
* 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.
*
*/
#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <time.h>
#include <unistd.h>
#include "rtsp_demo.h"
#include "sample_comm.h"
#define BUFFER_SIZE 255
#define MODULE_TEST_DELAY_SECOND_TIME 3 /* (unit: second) */
typedef struct _rkModeTest {
RK_BOOL bIfMainThreadQuit;
RK_BOOL bIfVencThreadQuit;
RK_BOOL bModuleTestThreadQuit;
RK_BOOL bModuleTestIfopen;
RK_S32 s32ModuleTestType;
RK_S32 s32ModuleTestLoop;
RK_U32 u32TestFrameCount;
RK_U32 u32VencGetFrameCount;
} g_mode_test;
typedef struct _rkMpiCtx {
SAMPLE_VI_CTX_S vi;
SAMPLE_VENC_CTX_S venc;
} SAMPLE_MPI_CTX_S;
/* global param */
g_mode_test *gModeTest;
SAMPLE_MPI_CTX_S *ctx;
RK_S32 g_exit_result = RK_SUCCESS;
sem_t g_sem_module_test;
pthread_mutex_t g_frame_count_mutex;
RK_BOOL g_rtsp_ifenbale = RK_FALSE;
rtsp_demo_handle g_rtsplive = NULL;
static rtsp_session_handle g_rtsp_session;
static void program_handle_error(const char *func, RK_U32 line) {
RK_LOGE("func: <%s> line: <%d> error exit!", func, line);
g_exit_result = RK_FAILURE;
gModeTest->bIfMainThreadQuit = RK_TRUE;
}
static void program_normal_exit(const char *func, RK_U32 line) {
RK_LOGE("func: <%s> line: <%d> normal exit!", func, line);
gModeTest->bIfMainThreadQuit = RK_TRUE;
}
static void sigterm_handler(int sig) {
fprintf(stderr, "signal %d\n", sig);
program_normal_exit(__func__, __LINE__);
}
static RK_CHAR optstr[] = "?::a::w:h:o:l:m:e:r:f:t:c:";
static const struct option long_options[] = {
{"aiq", optional_argument, NULL, 'a'},
{"width", required_argument, NULL, 'w'},
{"height", required_argument, NULL, 'h'},
{"output_path", required_argument, NULL, 'o'},
{"loop_count", required_argument, NULL, 'l'},
{"mode_test_type", required_argument, NULL, 'm'},
{"encode", required_argument, NULL, 'e'},
{"wrap", required_argument, NULL, 'r'},
{"fps", required_argument, NULL, 'f'},
{"mode_test_loop", required_argument, NULL, 't' + 'l'},
{"test_frame_count", required_argument, NULL, 'c'},
{"help", optional_argument, NULL, '?'},
{NULL, 0, NULL, 0},
};
/******************************************************************************
* function : show usage
******************************************************************************/
static void print_usage(const RK_CHAR *name) {
printf("usage example:\n");
printf("\t%s -w 1920 -h 1080 -a /etc/iqfiles/ -l 10 -o /userdata/\n", name);
#ifdef RKAIQ
printf(
"\t-a | --aiq : enable aiq with dirpath provided, eg:-a /etc/iqfiles/, \n"
"\t set dirpath empty to using path by default, without this option aiq \n"
"\t should run in other application\n");
#endif
printf("\t-w | --width : camera with, Default: 1920\n");
printf("\t-h | --height : camera height, Default: 1080\n");
printf("\t-o | --output_path : encode output file path, Default: NULL\n");
printf("\t-l | --loop_count : loop count, Default: -1\n");
printf("\t-m | --mode_test_type : test type, 0:none, 1:encode resolution switch, \n"
"\t 2:encode type switch, 3:smartp switch test, 4:SVC mode switch, \n"
"\t 5:motion deblur test, 6:force IDR test, 7: venc chn Rotation test, "
"Default: 0\n");
printf("\t-e | --encode : set encode type, Value: h264cbr, h264vbr, h265cbr, "
"h265vbr, default: h264cbr \n");
printf("\t-r | --wrap : wrap for Vi and Venc, 0: close 1: open, Default: 0\n");
printf("\t-f | --fps : encode output frame rate, Default: 25\n");
printf("\t--mode_test_loop : module test loop, default: -1\n");
printf("\t--test_frame_count : set the venc reveive frame count for every test "
"loop, default: 500\n");
}
static void *venc_get_stream(void *pArgs) {
SAMPLE_VENC_CTX_S *ctx = (SAMPLE_VENC_CTX_S *)pArgs;
RK_S32 s32Ret = RK_FAILURE;
FILE *fp = RK_NULL;
RK_S32 loopCount = 0;
RK_VOID *pData = RK_NULL;
RK_CHAR name[BUFFER_SIZE] = {0};
if (ctx->dstFilePath) {
snprintf(name, sizeof(name), "/%s/vi_%d.bin", ctx->dstFilePath, ctx->s32ChnId);
fp = fopen(name, "wb");
if (fp == RK_NULL) {
RK_LOGE("chn %d can't open %s file !\n", ctx->s32ChnId, ctx->dstFilePath);
program_handle_error(__func__, __LINE__);
return RK_NULL;
}
}
while (!gModeTest->bIfVencThreadQuit) {
s32Ret = SAMPLE_COMM_VENC_GetStream(ctx, &pData);
if (s32Ret == RK_SUCCESS) {
if (ctx->s32loopCount > 0) {
if (loopCount >= ctx->s32loopCount) {
SAMPLE_COMM_VENC_ReleaseStream(ctx);
program_normal_exit(__func__, __LINE__);
break;
}
}
if (fp) {
fwrite(pData, 1, ctx->stFrame.pstPack->u32Len, fp);
fflush(fp);
}
if (g_rtsp_ifenbale) {
rtsp_tx_video(g_rtsp_session, pData, ctx->stFrame.pstPack->u32Len,
ctx->stFrame.pstPack->u64PTS);
rtsp_do_event(g_rtsplive);
} else {
RK_LOGE("venc get_stream count: %d", loopCount);
}
if (gModeTest->bModuleTestIfopen) {
pthread_mutex_lock(&g_frame_count_mutex);
gModeTest->u32VencGetFrameCount++;
pthread_mutex_unlock(&g_frame_count_mutex);
if (gModeTest->u32VencGetFrameCount == gModeTest->u32TestFrameCount) {
sem_post(&g_sem_module_test);
}
}
if (ctx->enCodecType == RK_CODEC_TYPE_H264) {
RK_LOGD("venc get_stream count: %d pack_type:%d", loopCount,
ctx->stFrame.pstPack->DataType.enH264EType);
} else if (ctx->enCodecType == RK_CODEC_TYPE_H265) {
RK_LOGD("venc get_stream count: %d pack_type:%d", loopCount,
ctx->stFrame.pstPack->DataType.enH265EType);
} else {
RK_LOGD("venc get_stream count: %d", loopCount);
}
SAMPLE_COMM_VENC_ReleaseStream(ctx);
loopCount++;
}
}
if (fp)
fclose(fp);
RK_LOGE("venc_get_stream exit");
return RK_NULL;
}
static void wait_module_test_switch_success(void) {
pthread_mutex_lock(&g_frame_count_mutex);
gModeTest->u32VencGetFrameCount = 0;
pthread_mutex_unlock(&g_frame_count_mutex);
sem_wait(&g_sem_module_test);
}
static void venc_resolution_switch(RK_S32 test_loop) {
RK_S32 s32TestCount = 0;
RK_S32 s32Ret = RK_FAILURE;
RK_U32 u32DstWidth = 704;
RK_U32 u32DstHeight = 576;
VENC_CHN_ATTR_S pstChnAttr;
VI_CHN_ATTR_S vipstChnAttr;
MPP_CHN_S stSrcChn, stDestChn;
while (!gModeTest->bModuleTestThreadQuit) {
// unBind vi and venc
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = ctx->vi.s32DevId;
stSrcChn.s32ChnId = ctx->vi.s32ChnId;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = ctx->venc.s32ChnId;
s32Ret = SAMPLE_COMM_UnBind(&stSrcChn, &stDestChn);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("vi devid:%d chnid:%d unband to venc chnid:%d failure",
ctx->vi.s32DevId, ctx->vi.s32ChnId, ctx->venc.s32ChnId);
program_handle_error(__func__, __LINE__);
break;
}
memset(&pstChnAttr, 0, sizeof(VENC_CHN_ATTR_S));
s32Ret = RK_MPI_VENC_GetChnAttr(ctx->venc.s32ChnId, &pstChnAttr);
RK_LOGD("w: %d h: %d", pstChnAttr.stVencAttr.u32PicWidth,
pstChnAttr.stVencAttr.u32PicHeight);
if (pstChnAttr.stVencAttr.u32PicWidth == ctx->venc.u32Width) {
pstChnAttr.stVencAttr.u32PicWidth = u32DstWidth;
pstChnAttr.stVencAttr.u32PicHeight = u32DstHeight;
pstChnAttr.stVencAttr.u32VirWidth = RK_ALIGN_2(u32DstWidth);
pstChnAttr.stVencAttr.u32VirHeight = RK_ALIGN_2(u32DstHeight);
} else {
pstChnAttr.stVencAttr.u32PicWidth = ctx->venc.u32Width;
pstChnAttr.stVencAttr.u32PicHeight = ctx->venc.u32Height;
pstChnAttr.stVencAttr.u32VirWidth = RK_ALIGN_2(ctx->venc.u32Width);
pstChnAttr.stVencAttr.u32VirHeight = RK_ALIGN_2(ctx->venc.u32Height);
}
s32Ret |= RK_MPI_VENC_SetChnAttr(ctx->venc.s32ChnId, &pstChnAttr);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("venc set chn resolution failure");
program_handle_error(__func__, __LINE__);
break;
}
memset(&vipstChnAttr, 0, sizeof(VI_CHN_ATTR_S));
s32Ret = RK_MPI_VI_GetChnAttr(ctx->vi.u32PipeId, ctx->vi.s32ChnId, &vipstChnAttr);
RK_LOGD("w: %d h: %d", vipstChnAttr.stSize.u32Width,
vipstChnAttr.stSize.u32Height);
if (vipstChnAttr.stSize.u32Width == ctx->vi.u32Width) {
vipstChnAttr.stSize.u32Width = u32DstWidth;
vipstChnAttr.stSize.u32Height = u32DstHeight;
} else {
vipstChnAttr.stSize.u32Width = ctx->vi.u32Width;
vipstChnAttr.stSize.u32Height = ctx->vi.u32Height;
}
s32Ret |=
RK_MPI_VI_SetChnAttr(ctx->vi.u32PipeId, ctx->vi.s32ChnId, &vipstChnAttr);
if (s32Ret != RK_SUCCESS) {
RK_LOGE(" set resolution failure");
program_handle_error(__func__, __LINE__);
break;
}
// Bind vi and venc
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = ctx->vi.s32DevId;
stSrcChn.s32ChnId = ctx->vi.s32ChnId;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = ctx->venc.s32ChnId;
s32Ret = SAMPLE_COMM_Bind(&stSrcChn, &stDestChn);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("vi devid:%d chnid:%d band to venc chnid:%d failure",
ctx->vi.s32DevId, ctx->vi.s32ChnId, ctx->venc.s32ChnId);
program_handle_error(__func__, __LINE__);
break;
}
RK_LOGE("------------------------Venc resolution switch to %dx%d",
vipstChnAttr.stSize.u32Width, vipstChnAttr.stSize.u32Height);
wait_module_test_switch_success();
s32TestCount++;
RK_LOGE(
"-------------------Venc resolution Switch Test success Total: %d Now Count: "
"%d-------------------",
test_loop, s32TestCount);
if (test_loop > 0 && s32TestCount >= test_loop) {
RK_LOGE("------------------Venc resolution switch test end(pass/success) "
"count: %d-----------------",
s32TestCount);
gModeTest->bModuleTestIfopen = RK_FALSE;
program_normal_exit(__func__, __LINE__);
break;
}
}
RK_LOGE("venc_resolution_switch exit");
}
static RK_S32 encode_destroy_and_restart(CODEC_TYPE_E enCodecType,
VENC_RC_MODE_E enRcMode, RK_U32 u32Profile,
RK_BOOL bIfSliceSplit) {
RK_S32 s32Ret = RK_FAILURE;
MPP_CHN_S stSrcChn, stDestChn;
gModeTest->bIfVencThreadQuit = RK_TRUE;
if (ctx->venc.getStreamCbFunc) {
pthread_join(ctx->venc.getStreamThread, RK_NULL);
}
// unBind vi and venc
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = ctx->vi.s32DevId;
stSrcChn.s32ChnId = ctx->vi.s32ChnId;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = ctx->venc.s32ChnId;
s32Ret = SAMPLE_COMM_UnBind(&stSrcChn, &stDestChn);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("vi devid:%d chnid:%d unband to venc chnid:%d failure", ctx->vi.s32DevId,
ctx->vi.s32ChnId, ctx->venc.s32ChnId);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
// Destroy venc
s32Ret = SAMPLE_COMM_VENC_DestroyChn(&ctx->venc);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("SAMPLE_COMM_VENC_DestroyChn 0 Failure s32Ret:%#X", s32Ret);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
ctx->venc.enCodecType = enCodecType;
ctx->venc.enRcMode = enRcMode;
ctx->venc.stChnAttr.stVencAttr.u32Profile = u32Profile;
gModeTest->bIfVencThreadQuit = RK_FALSE;
// Init VENC
s32Ret = SAMPLE_COMM_VENC_CreateChn(&ctx->venc);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("SAMPLE_COMM_VENC_DestroyChn 0 Failure s32Ret:%#X", s32Ret);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
// Bind vi and venc
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = ctx->vi.s32DevId;
stSrcChn.s32ChnId = ctx->vi.s32ChnId;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = ctx->venc.s32ChnId;
s32Ret = SAMPLE_COMM_Bind(&stSrcChn, &stDestChn);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("vi devid:%d chnid:%d band to venc chnid:%d failure", ctx->vi.s32DevId,
ctx->vi.s32ChnId, ctx->venc.s32ChnId);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
return s32Ret;
}
static RK_S32 encode_type_switch(RK_S32 test_loop) {
RK_S32 s32Ret = RK_FAILURE;
RK_S32 now_test_loop = 0;
g_rtsp_ifenbale = RK_FALSE;
while (!gModeTest->bModuleTestThreadQuit) {
switch (now_test_loop % 2) {
case 0: /* H264 CBR */
RK_LOGE("-------------Switch To H264CBR---------------");
s32Ret = encode_destroy_and_restart(RK_CODEC_TYPE_H264, VENC_RC_MODE_H264CBR,
100, RK_FALSE);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("switch to 264_cbr failure");
program_handle_error(__func__, __LINE__);
return RK_FAILURE;
}
break;
case 1: /* H265 CBR */
RK_LOGE("-------------Switch To H265CBR---------------");
s32Ret = encode_destroy_and_restart(RK_CODEC_TYPE_H265, VENC_RC_MODE_H265CBR,
0, RK_FALSE);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("switch to 265_cbr failure");
program_handle_error(__func__, __LINE__);
return RK_FAILURE;
}
break;
default:
break;
}
wait_module_test_switch_success();
now_test_loop++;
RK_LOGE("---------------------------------------switch success total:%d "
"time:%d--------------------------------",
test_loop, now_test_loop);
if (test_loop > 0 && now_test_loop > test_loop) {
RK_LOGE("encode_type_switch_test end and passed(success)!!!");
gModeTest->bModuleTestIfopen = RK_FALSE;
program_normal_exit(__func__, __LINE__);
break;
}
}
RK_LOGE("encode_type_switch exit");
return s32Ret;
}
static RK_S32 smartp_mode(RK_S32 test_loop) {
RK_S32 s32TestCount = 0;
RK_S32 s32Ret = RK_FAILURE;
RK_BOOL eSmartpIfEnable = RK_TRUE;
MPP_CHN_S stSrcChn, stDestChn;
while (!gModeTest->bModuleTestThreadQuit) {
gModeTest->bIfVencThreadQuit = RK_TRUE;
if (ctx->venc.getStreamCbFunc) {
pthread_join(ctx->venc.getStreamThread, RK_NULL);
}
// unBind vi and venc
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = ctx->vi.s32DevId;
stSrcChn.s32ChnId = ctx->vi.s32ChnId;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = ctx->venc.s32ChnId;
s32Ret = SAMPLE_COMM_UnBind(&stSrcChn, &stDestChn);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("vi devid:%d chnid:%d unband to venc chnid:%d failure",
ctx->vi.s32DevId, ctx->vi.s32ChnId, ctx->venc.s32ChnId);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
// Destroy venc
s32Ret = SAMPLE_COMM_VENC_DestroyChn(&ctx->venc);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("SAMPLE_COMM_VENC_DestroyChn 0 Failure s32Ret:%#X", s32Ret);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
if (eSmartpIfEnable) {
ctx->venc.stChnAttr.stGopAttr.enGopMode = VENC_GOPMODE_SMARTP;
ctx->venc.stChnAttr.stGopAttr.s32VirIdrLen = ctx->venc.u32Gop / 2;
RK_LOGE("------------------GopMode set to VENC_GOPMODE_SMARTP");
} else {
ctx->venc.stChnAttr.stGopAttr.enGopMode = VENC_GOPMODE_NORMALP;
RK_LOGE("------------------GopMode set to VENC_GOPMODE_NORMALP");
}
gModeTest->bIfVencThreadQuit = RK_FALSE;
eSmartpIfEnable = !eSmartpIfEnable;
// Init VENC
s32Ret = SAMPLE_COMM_VENC_CreateChn(&ctx->venc);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("SAMPLE_COMM_VENC_DestroyChn 0 Failure s32Ret:%#X", s32Ret);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
// Bind vi and venc
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = ctx->vi.s32DevId;
stSrcChn.s32ChnId = ctx->vi.s32ChnId;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = ctx->venc.s32ChnId;
s32Ret = SAMPLE_COMM_Bind(&stSrcChn, &stDestChn);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("vi devid:%d chnid:%d band to venc chnid:%d failure",
ctx->vi.s32DevId, ctx->vi.s32ChnId, ctx->venc.s32ChnId);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
wait_module_test_switch_success();
s32TestCount++;
RK_LOGE(
"---------------------------------------Smartp mode switch success total:%d "
"time:%d--------------------------------",
test_loop, s32TestCount);
if (test_loop > 0 && s32TestCount > test_loop) {
RK_LOGE("Smartp mode switch test end and passed(success)!!!");
gModeTest->bModuleTestIfopen = RK_FALSE;
program_normal_exit(__func__, __LINE__);
break;
}
}
RK_LOGE("smartp_mode exit");
return RK_SUCCESS;
}
static RK_S32 smart_encode(RK_S32 test_loop) {
RK_S32 s32TestCount = 0;
RK_S32 s32Ret = RK_FAILURE;
RK_BOOL eSvcIfEnable = RK_TRUE;
MPP_CHN_S stSrcChn, stDestChn;
while (!gModeTest->bModuleTestThreadQuit) {
gModeTest->bIfVencThreadQuit = RK_TRUE;
if (ctx->venc.getStreamCbFunc) {
pthread_join(ctx->venc.getStreamThread, RK_NULL);
}
// unBind vi and venc
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = ctx->vi.s32DevId;
stSrcChn.s32ChnId = ctx->vi.s32ChnId;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = ctx->venc.s32ChnId;
s32Ret = SAMPLE_COMM_UnBind(&stSrcChn, &stDestChn);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("vi devid:%d chnid:%d unband to venc chnid:%d failure",
ctx->vi.s32DevId, ctx->vi.s32ChnId, ctx->venc.s32ChnId);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
// Destroy venc
s32Ret = SAMPLE_COMM_VENC_DestroyChn(&ctx->venc);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("SAMPLE_COMM_VENC_DestroyChn 0 Failure s32Ret:%#X", s32Ret);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
if (eSvcIfEnable) {
ctx->venc.bSvcIfEnable = eSvcIfEnable;
if (ctx->venc.enCodecType == RK_CODEC_TYPE_H265) {
ctx->venc.enRcMode = VENC_RC_MODE_H265VBR;
} else if (ctx->venc.enCodecType == RK_CODEC_TYPE_H264) {
ctx->venc.enRcMode = VENC_RC_MODE_H264VBR;
}
RK_LOGE("---------------------Smart video coding enable");
} else {
ctx->venc.bSvcIfEnable = eSvcIfEnable;
RK_LOGE("---------------------Smart video coding disable");
}
eSvcIfEnable = !eSvcIfEnable;
gModeTest->bIfVencThreadQuit = RK_FALSE;
// Init VENC
s32Ret = SAMPLE_COMM_VENC_CreateChn(&ctx->venc);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("SAMPLE_COMM_VENC_DestroyChn 0 Failure s32Ret:%#X", s32Ret);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
// Bind vi and venc
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = ctx->vi.s32DevId;
stSrcChn.s32ChnId = ctx->vi.s32ChnId;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = ctx->venc.s32ChnId;
s32Ret = SAMPLE_COMM_Bind(&stSrcChn, &stDestChn);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("vi devid:%d chnid:%d band to venc chnid:%d failure",
ctx->vi.s32DevId, ctx->vi.s32ChnId, ctx->venc.s32ChnId);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
wait_module_test_switch_success();
s32TestCount++;
RK_LOGE("-------------------Smart Video Coding Switch Test success Total: %d Now "
"Count: "
"%d-------------------",
test_loop, s32TestCount);
if (test_loop > 0 && s32TestCount >= test_loop) {
RK_LOGE("------------------Smart Video Coding Switch test end(pass/success) "
"count: "
"%d-----------------",
s32TestCount);
gModeTest->bModuleTestIfopen = RK_FALSE;
program_normal_exit(__func__, __LINE__);
break;
}
}
RK_LOGE("smart_encode exit");
return RK_SUCCESS;
}
static RK_S32 motion_deblur_test(RK_S32 test_loop) {
RK_S32 s32TestCount = 0;
RK_S32 s32Ret = RK_FAILURE;
RK_BOOL eMotionDeblurIfEnable = RK_TRUE;
MPP_CHN_S stSrcChn, stDestChn;
while (!gModeTest->bModuleTestThreadQuit) {
gModeTest->bIfVencThreadQuit = RK_TRUE;
if (ctx->venc.getStreamCbFunc) {
pthread_join(ctx->venc.getStreamThread, RK_NULL);
}
// unBind vi and venc
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = ctx->vi.s32DevId;
stSrcChn.s32ChnId = ctx->vi.s32ChnId;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = ctx->venc.s32ChnId;
s32Ret = SAMPLE_COMM_UnBind(&stSrcChn, &stDestChn);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("vi devid:%d chnid:%d unband to venc chnid:%d failure",
ctx->vi.s32DevId, ctx->vi.s32ChnId, ctx->venc.s32ChnId);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
// Destroy venc
s32Ret = SAMPLE_COMM_VENC_DestroyChn(&ctx->venc);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("SAMPLE_COMM_VENC_DestroyChn 0 Failure s32Ret:%#X", s32Ret);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
if (eMotionDeblurIfEnable) {
ctx->venc.bMotionDeblurIfEnable = eMotionDeblurIfEnable;
RK_LOGE("------------------------------Motion Deblur enable");
} else {
ctx->venc.bMotionDeblurIfEnable = eMotionDeblurIfEnable;
RK_LOGE("------------------------------Motion Deblur disable");
}
eMotionDeblurIfEnable = !eMotionDeblurIfEnable;
gModeTest->bIfVencThreadQuit = RK_FALSE;
// Init VENC
s32Ret = SAMPLE_COMM_VENC_CreateChn(&ctx->venc);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("SAMPLE_COMM_VENC_DestroyChn 0 Failure s32Ret:%#X", s32Ret);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
// Bind vi and venc
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = ctx->vi.s32DevId;
stSrcChn.s32ChnId = ctx->vi.s32ChnId;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = ctx->venc.s32ChnId;
s32Ret = SAMPLE_COMM_Bind(&stSrcChn, &stDestChn);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("vi devid:%d chnid:%d band to venc chnid:%d failure",
ctx->vi.s32DevId, ctx->vi.s32ChnId, ctx->venc.s32ChnId);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
wait_module_test_switch_success();
s32TestCount++;
RK_LOGE("-------------------Motion Deblur Test success Total: %d Now Count: "
"%d-------------------",
test_loop, s32TestCount);
if (test_loop > 0 && s32TestCount >= test_loop) {
RK_LOGE("------------------Motion Deblur test end(pass/success) count: "
"%d-----------------",
s32TestCount);
gModeTest->bModuleTestIfopen = RK_FALSE;
program_normal_exit(__func__, __LINE__);
break;
}
}
RK_LOGE("motion_deblur_test exit");
return RK_SUCCESS;
}
static RK_S32 venc_force_idr_test(RK_S32 test_loop) {
RK_S32 s32TestCount = 0;
RK_S32 s32Ret = RK_FAILURE;
while (!gModeTest->bModuleTestThreadQuit) {
RK_LOGE("-------------------venc set force idr");
s32Ret = RK_MPI_VENC_RequestIDR(ctx->venc.s32ChnId, RK_FALSE);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("RK_MPI_VENC_RequestIDR failure: %X", s32Ret);
program_handle_error(__func__, __LINE__);
return s32Ret;
}
wait_module_test_switch_success();
s32TestCount++;
RK_LOGE("-------------------Venc Force IDR Test success Total: %d Now Count: "
"%d-------------------",
test_loop, s32TestCount);
if (test_loop > 0 && s32TestCount >= test_loop) {
RK_LOGE("------------------Venc Force IDR test end(pass/success) count: "
"%d-----------------",
s32TestCount);
gModeTest->bModuleTestIfopen = RK_FALSE;
program_normal_exit(__func__, __LINE__);
break;
}
}
RK_LOGE("venc_force_idr exit");
return RK_SUCCESS;
}
static RK_S32 venc_set_rotation(RK_S32 test_loop) {
RK_S32 s32TestCount = 0;
RK_S32 s32Ret = RK_FAILURE;
ROTATION_E enRotation;
while (!gModeTest->bModuleTestThreadQuit) {
memset(&enRotation, 0, sizeof(ROTATION_E));
s32Ret = RK_MPI_VENC_GetChnRotation(ctx->venc.s32ChnId, &enRotation);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("RK_MPI_VENC_GetChnRotation failure:%X", s32Ret);
return RK_FAILURE;
}
if (enRotation == ROTATION_0) {
enRotation = ROTATION_90;
} else if (enRotation == ROTATION_90) {
enRotation = ROTATION_180;
} else if (enRotation == ROTATION_180) {
enRotation = ROTATION_270;
} else if (enRotation == ROTATION_270) {
enRotation = ROTATION_0;
} else {
enRotation = ROTATION_0;
}
s32Ret = RK_MPI_VENC_SetChnRotation(ctx->venc.s32ChnId, enRotation);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("RK_MPI_VENC_SetChnRotation failure:%X", s32Ret);
return RK_FAILURE;
}
RK_LOGE("----------------------venc chn Rotation switch to:%d", enRotation);
wait_module_test_switch_success();
s32TestCount++;
RK_LOGE(
"-------------------Venc chn Rotation switch success Total: %d Now Count: "
"%d-------------------",
test_loop, s32TestCount);
if (test_loop > 0 && s32TestCount >= test_loop) {
RK_LOGE("------------------Venc chn Rotation test end(pass/success) count: "
"%d-----------------",
s32TestCount);
gModeTest->bModuleTestIfopen = RK_FALSE;
program_normal_exit(__func__, __LINE__);
break;
}
}
RK_LOGE("venc_set_rotation exit");
return RK_SUCCESS;
}
static void *sample_venc_stress_test(void *pArgs) {
prctl(PR_SET_NAME, "venc_stress_test");
sleep(MODULE_TEST_DELAY_SECOND_TIME);
SAMPLE_COMM_DumpMeminfo("Enter sample_venc_stress_test",
gModeTest->s32ModuleTestType);
switch (gModeTest->s32ModuleTestType) {
case 1:
/* venc resolutio switch */
venc_resolution_switch(gModeTest->s32ModuleTestLoop);
break;
case 2:
/* encode type switch */
encode_type_switch(gModeTest->s32ModuleTestLoop);
break;
case 3:
/* smartp test*/
smartp_mode(gModeTest->s32ModuleTestLoop);
break;
case 4:
/* smart video coding*/
smart_encode(gModeTest->s32ModuleTestLoop);
break;
case 5:
/*motion deblur test*/
motion_deblur_test(gModeTest->s32ModuleTestLoop);
break;
case 6:
/*force idr test*/
venc_force_idr_test(gModeTest->s32ModuleTestLoop);
break;
case 7:
/* venc set chn rotation*/
venc_set_rotation(gModeTest->s32ModuleTestLoop);
break;
default:
RK_LOGE("mode test type:%d is unsupported", gModeTest->s32ModuleTestType);
}
SAMPLE_COMM_DumpMeminfo("Exit sample_venc_stress_test", gModeTest->s32ModuleTestType);
RK_LOGE("venc_stress_test exit");
return RK_NULL;
}
static RK_S32 rtsp_init(CODEC_TYPE_E enCodecType) {
g_rtsplive = create_rtsp_demo(554);
g_rtsp_session = rtsp_new_session(g_rtsplive, "/live/0");
if (enCodecType == RK_CODEC_TYPE_H264) {
rtsp_set_video(g_rtsp_session, RTSP_CODEC_ID_VIDEO_H264, NULL, 0);
} else if (enCodecType == RK_CODEC_TYPE_H265) {
rtsp_set_video(g_rtsp_session, RTSP_CODEC_ID_VIDEO_H265, NULL, 0);
} else {
RK_LOGE("not support other type\n");
g_rtsp_ifenbale = RK_FALSE;
return RK_SUCCESS;
}
rtsp_sync_video_ts(g_rtsp_session, rtsp_get_reltime(), rtsp_get_ntptime());
g_rtsp_ifenbale = RK_TRUE;
return RK_SUCCESS;
}
static RK_S32 rtsp_deinit(void) {
if (g_rtsplive)
rtsp_del_demo(g_rtsplive);
return RK_SUCCESS;
}
static RK_S32 global_param_init(void) {
ctx = (SAMPLE_MPI_CTX_S *)malloc(sizeof(SAMPLE_MPI_CTX_S));
if (ctx == RK_NULL) {
RK_LOGE("malloc for ctx failure");
return RK_FAILURE;
}
memset(ctx, 0, sizeof(SAMPLE_MPI_CTX_S));
gModeTest = (g_mode_test *)malloc(sizeof(g_mode_test));
if (gModeTest == RK_NULL) {
RK_LOGE("malloc for gModeTest failure");
return RK_FAILURE;
}
memset(gModeTest, 0, sizeof(g_mode_test));
gModeTest->s32ModuleTestLoop = -1;
gModeTest->u32TestFrameCount = 500;
sem_init(&g_sem_module_test, 0, 0);
if (pthread_mutex_init(&g_frame_count_mutex, NULL) != 0) {
RK_LOGE("mutex init failure \n");
return RK_FAILURE;
}
return RK_SUCCESS;
}
static RK_S32 global_param_deinit(void) {
if (ctx) {
free(ctx);
ctx = RK_NULL;
}
if (gModeTest) {
free(gModeTest);
gModeTest = RK_NULL;
}
sem_destroy(&g_sem_module_test);
pthread_mutex_destroy(&g_frame_count_mutex);
return RK_SUCCESS;
}
int main(int argc, char *argv[]) {
RK_S32 s32Ret = RK_FAILURE;
RK_S32 s32VideoWidth = 1920;
RK_S32 s32VideoHeight = 1080;
RK_CHAR *pOutPathVenc = RK_NULL;
RK_CHAR *pIqFileDir = RK_NULL;
RK_S32 s32CamId = 0;
RK_S32 s32LoopCnt = -1;
RK_U32 u32VencFps = 25;
RK_U32 u32BitRate = 4 * 1024;
PIXEL_FORMAT_E enPixelFormat = RK_FMT_YUV420SP;
CODEC_TYPE_E enCodecType = RK_CODEC_TYPE_H264;
VENC_RC_MODE_E enRcMode = VENC_RC_MODE_H264CBR;
RK_BOOL bMultictx = RK_FALSE;
RK_BOOL bWrapIfEnable = RK_FALSE;
MPP_CHN_S stSrcChn, stDestChn;
rk_aiq_working_mode_t eHdrMode = RK_AIQ_WORKING_MODE_NORMAL;
pthread_t modeTest_thread_id;
if (argc < 2) {
print_usage(argv[0]);
g_exit_result = RK_FAILURE;
goto __PARAM_INIT_FAILED;
}
SAMPLE_COMM_CheckFd(RK_TRUE);
s32Ret = global_param_init();
if (s32Ret != RK_SUCCESS) {
RK_LOGE("global_param_init failure");
g_exit_result = RK_FAILURE;
goto __PARAM_INIT_FAILED;
}
signal(SIGINT, sigterm_handler);
RK_S32 c = 0;
while ((c = getopt_long(argc, argv, optstr, long_options, NULL)) != -1) {
const char *tmp_optarg = optarg;
switch (c) {
case 'a':
if (!optarg && NULL != argv[optind] && '-' != argv[optind][0]) {
tmp_optarg = argv[optind++];
}
if (tmp_optarg) {
pIqFileDir = (char *)tmp_optarg;
} else {
pIqFileDir = NULL;
}
break;
case 'w':
s32VideoWidth = atoi(optarg);
break;
case 'h':
s32VideoHeight = atoi(optarg);
break;
case 'o':
pOutPathVenc = optarg;
break;
case 'l':
s32LoopCnt = atoi(optarg);
break;
case 'm':
gModeTest->s32ModuleTestType = atoi(optarg);
break;
case 'e':
if (!strcmp(optarg, "h264cbr")) {
enCodecType = RK_CODEC_TYPE_H264;
enRcMode = VENC_RC_MODE_H264CBR;
} else if (!strcmp(optarg, "h264vbr")) {
enCodecType = RK_CODEC_TYPE_H264;
enRcMode = VENC_RC_MODE_H264VBR;
} else if (!strcmp(optarg, "h264avbr")) {
enCodecType = RK_CODEC_TYPE_H264;
enRcMode = VENC_RC_MODE_H264AVBR;
} else if (!strcmp(optarg, "h265cbr")) {
enCodecType = RK_CODEC_TYPE_H265;
enRcMode = VENC_RC_MODE_H265CBR;
} else if (!strcmp(optarg, "h265vbr")) {
enCodecType = RK_CODEC_TYPE_H265;
enRcMode = VENC_RC_MODE_H265VBR;
} else if (!strcmp(optarg, "h265avbr")) {
enCodecType = RK_CODEC_TYPE_H265;
enRcMode = VENC_RC_MODE_H265AVBR;
} else {
printf("ERROR: Invalid encoder type.\n");
print_usage(argv[0]);
g_exit_result = RK_FAILURE;
goto __PARAM_INIT_FAILED;
}
break;
case 'r':
bWrapIfEnable = atoi(optarg);
break;
case 'f':
u32VencFps = atoi(optarg);
break;
case 't' + 'l':
gModeTest->s32ModuleTestLoop = atoi(optarg);
break;
case 'c':
gModeTest->u32TestFrameCount = atoi(optarg);
break;
case '?':
default:
print_usage(argv[0]);
return 0;
}
}
if (pIqFileDir) {
#ifdef RKAIQ
printf("#Rkaiq XML DirPath: %s\n", pIqFileDir);
printf("#bMultictx: %d\n\n", bMultictx);
RK_LOGE("eHdrMode: %d", eHdrMode);
s32Ret = SAMPLE_COMM_ISP_Init(s32CamId, eHdrMode, bMultictx, pIqFileDir);
s32Ret |= SAMPLE_COMM_ISP_Run(s32CamId);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("ISP init failure");
g_exit_result = RK_FAILURE;
goto __FAILED2;
}
#endif
}
if (RK_MPI_SYS_Init() != RK_SUCCESS) {
RK_LOGE("RK_MPI_SYS_Init failure");
g_exit_result = RK_FAILURE;
goto __FAILED;
}
s32Ret = rtsp_init(enCodecType);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("rtsp_init failure");
g_exit_result = RK_FAILURE;
goto __FAILED;
}
/* Init VI */
ctx->vi.u32Width = s32VideoWidth;
ctx->vi.u32Height = s32VideoHeight;
ctx->vi.s32DevId = s32CamId;
ctx->vi.u32PipeId = ctx->vi.s32DevId;
ctx->vi.s32ChnId = 0;
#ifdef RV1126
ctx->vi.s32ChnId = 1;
#endif
ctx->vi.stChnAttr.stIspOpt.stMaxSize.u32Width = s32VideoWidth;
ctx->vi.stChnAttr.stIspOpt.stMaxSize.u32Height = s32VideoHeight;
ctx->vi.stChnAttr.stIspOpt.u32BufCount = 3;
ctx->vi.stChnAttr.stIspOpt.enMemoryType = VI_V4L2_MEMORY_TYPE_DMABUF;
ctx->vi.stChnAttr.u32Depth = 1;
ctx->vi.stChnAttr.enPixelFormat = enPixelFormat;
ctx->vi.stChnAttr.enCompressMode = COMPRESS_MODE_NONE;
ctx->vi.stChnAttr.stFrameRate.s32SrcFrameRate = 25;
ctx->vi.stChnAttr.stFrameRate.s32DstFrameRate = u32VencFps;
ctx->vi.bWrapIfEnable = bWrapIfEnable;
ctx->vi.u32BufferLine = ctx->vi.u32Height / 4;
s32Ret = SAMPLE_COMM_VI_CreateChn(&ctx->vi);
if (s32Ret != RK_SUCCESS) {
g_exit_result = RK_FAILURE;
RK_LOGE("SAMPLE_COMM_VI_CreateChn failure:%d", s32Ret);
goto __FAILED;
}
/* Init VENC */
ctx->venc.s32ChnId = 0;
ctx->venc.u32Width = s32VideoWidth;
ctx->venc.u32Height = s32VideoHeight;
ctx->venc.u32Fps = u32VencFps;
ctx->venc.u32Gop = 50;
ctx->venc.u32BitRate = u32BitRate;
ctx->venc.enCodecType = enCodecType;
ctx->venc.enRcMode = enRcMode;
ctx->venc.getStreamCbFunc = venc_get_stream;
ctx->venc.s32loopCount = s32LoopCnt;
ctx->venc.dstFilePath = pOutPathVenc;
ctx->venc.enPixelFormat = enPixelFormat;
ctx->venc.bWrapIfEnable = bWrapIfEnable;
ctx->venc.u32BufferLine = ctx->venc.u32Height / 4;
/*
H264 66Baseline 77Main Profile 100High Profile
H265 0Main Profile 1Main 10 Profile
MJPEG 0Baseline
*/
if (RK_CODEC_TYPE_H264 != enCodecType) {
ctx->venc.stChnAttr.stVencAttr.u32Profile = 0;
} else {
ctx->venc.stChnAttr.stVencAttr.u32Profile = 100;
}
/* VENC_GOPMODE_SMARTP */
ctx->venc.stChnAttr.stGopAttr.enGopMode = VENC_GOPMODE_NORMALP;
SAMPLE_COMM_VENC_CreateChn(&ctx->venc);
if (gModeTest->s32ModuleTestType) {
gModeTest->bModuleTestIfopen = RK_TRUE;
pthread_create(&modeTest_thread_id, 0, sample_venc_stress_test,
(void *)(gModeTest));
}
/* VI bind VENC */
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = ctx->vi.s32DevId;
stSrcChn.s32ChnId = ctx->vi.s32ChnId;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = ctx->venc.s32ChnId;
s32Ret = SAMPLE_COMM_Bind(&stSrcChn, &stDestChn);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("VI and VENC bind failure:%X", s32Ret);
program_handle_error(__func__, __LINE__);
g_exit_result = RK_FAILURE;
}
printf("%s initial finish\n", __func__);
while (!gModeTest->bIfMainThreadQuit) {
sleep(1);
}
/* mode_test_deinit */
if (gModeTest->s32ModuleTestType) {
gModeTest->bModuleTestThreadQuit = RK_TRUE;
pthread_join(modeTest_thread_id, NULL);
}
/* Venc deinit */
gModeTest->bIfVencThreadQuit = RK_TRUE;
pthread_join(ctx->venc.getStreamThread, NULL);
/* VI unbind VENC */
stSrcChn.enModId = RK_ID_VI;
stSrcChn.s32DevId = ctx->vi.s32DevId;
stSrcChn.s32ChnId = ctx->vi.s32ChnId;
stDestChn.enModId = RK_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = ctx->venc.s32ChnId;
s32Ret = SAMPLE_COMM_UnBind(&stSrcChn, &stDestChn);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("VI and VENC bind failure:%X", s32Ret);
g_exit_result = RK_FAILURE;
}
/* destroy venc */
SAMPLE_COMM_VENC_DestroyChn(&ctx->venc);
/* rtsp deinit */
rtsp_deinit();
/* Destroy VI */
s32Ret = SAMPLE_COMM_VI_DestroyChn(&ctx->vi);
if (s32Ret != RK_SUCCESS) {
RK_LOGE("SAMPLE_COMM_VI_DestroyChn failure:%X", s32Ret);
g_exit_result = RK_FAILURE;
}
__FAILED:
RK_MPI_SYS_Exit();
if (pIqFileDir) {
#ifdef RKAIQ
SAMPLE_COMM_ISP_Stop(s32CamId);
#endif
}
__FAILED2:
global_param_deinit();
SAMPLE_COMM_CheckFd(RK_FALSE);
__PARAM_INIT_FAILED:
return g_exit_result;
}
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */