123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158 |
- /*
- * Copyright 2021 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.
- */
- #define MODULE_TAG "mpi_rc_test"
- #include <string.h>
- #include <math.h>
- #include "rk_mpi.h"
- #include "mpp_env.h"
- #include "mpp_mem.h"
- #include "mpp_time.h"
- #include "mpp_common.h"
- #include "mpi_dec_utils.h"
- #include "mpi_enc_utils.h"
- #define MPI_BIT_DEPTH 8
- #define MPI_PIXEL_MAX ((1 << MPI_BIT_DEPTH) - 1)
- typedef RK_U8 pixel;
- typedef struct {
- double psnr_y;
- double ssim_y;
- RK_U32 avg_bitrate; // Every sequence, byte per second
- RK_U32 ins_bitrate; // Every second, byte per second
- RK_U32 frame_size; // Every frame, byte
- } MpiRcStat;
- typedef struct {
- FILE *fp_input;
- FILE *fp_enc_out;
- FILE *fp_stat;
- } MpiRcFile;
- typedef struct {
- MpiEncTestArgs* enc_cmd;
- MpiRcStat stat;
- MpiRcFile file;
- RK_U8 *com_buf;
- MppCtx enc_ctx;
- MppCtx dec_ctx_post;
- MppCtx dec_ctx_pre;
- MppApi *enc_mpi;
- MppApi *dec_mpi_post;
- MppApi *dec_mpi_pre;
- /* 1. pre-decoder data */
- FileReader reader;
- MppCodingType dec_type;
- RK_S32 pre_pkt_idx;
- RK_S32 pre_frm_idx;
- RK_S32 pre_frm_num;
- MppPacket dec_pkt_pre;
- RK_U8 *dec_in_buf_pre;
- RK_U32 dec_in_buf_pre_size;
- /* 2. encoder data */
- MppBufferGroup pkt_grp;
- MppPacket enc_pkt;
- MppEncRcCfg rc_cfg;
- MppEncPrepCfg prep_cfg;
- MppTask enc_in_task;
- MppTask enc_out_task;
- /* 3. post-decoder data */
- MppPacket dec_pkt_post;
- RK_U8 *dec_in_buf_post;
- RK_U32 dec_in_buf_post_size;
- RK_U32 loop_end;
- RK_U32 pkt_eos;
- RK_S32 frm_eos;
- RK_U32 enc_pkt_eos;
- MppEncCfg cfg;
- RK_S32 frm_idx;
- RK_U64 total_bits;
- double total_psnrs;
- double total_ssims;
- RK_U32 calc_base_idx;
- RK_U32 stream_size_1s;
- pthread_t dec_thr;
- RK_S64 start_enc;
- } MpiRc2TestCtx;
- static void mpi_rc_deinit(MpiRc2TestCtx *ctx)
- {
- MpiRcFile *file = &ctx->file;
- if (file->fp_enc_out) {
- fclose(file->fp_enc_out);
- file->fp_enc_out = NULL;
- }
- if (file->fp_stat) {
- fclose(file->fp_stat);
- file->fp_stat = NULL;
- }
- if (file->fp_input) {
- fclose(file->fp_input);
- file->fp_input = NULL;
- }
- if (ctx->reader) {
- reader_deinit(ctx->reader);
- ctx->reader = NULL;
- }
- MPP_FREE(ctx->com_buf);
- }
- static MPP_RET mpi_rc_init(MpiRc2TestCtx *ctx)
- {
- MpiEncTestArgs* enc_cmd = ctx->enc_cmd;
- if (enc_cmd->file_input)
- reader_init(&ctx->reader, enc_cmd->file_input, enc_cmd->type_src);
- if (NULL == ctx->reader) {
- mpp_err("failed to open dec input file %s\n", enc_cmd->file_input);
- return MPP_NOK;
- }
- mpp_log("input file %s size %ld\n", enc_cmd->file_input, reader_size(ctx->reader));
- ctx->dec_type = enc_cmd->type_src;
- if (enc_cmd->file_output) {
- MpiRcFile *file = &ctx->file;
- file->fp_enc_out = fopen(enc_cmd->file_output, "w+b");
- if (NULL == file->fp_enc_out) {
- mpp_err("failed to open enc output file %s\n", enc_cmd->file_output);
- return MPP_ERR_OPEN_FILE;
- }
- }
- return MPP_OK;
- }
- static MPP_RET mpi_rc_cmp_frame(MppFrame frame_in, MppFrame frame_out)
- {
- void *enc_buf = mpp_buffer_get_ptr(mpp_frame_get_buffer(frame_in));
- void *dec_buf = mpp_buffer_get_ptr(mpp_frame_get_buffer(frame_out));
- RK_U32 enc_width = mpp_frame_get_width(frame_in);
- RK_U32 enc_height = mpp_frame_get_height(frame_in);
- RK_U32 dec_width = mpp_frame_get_width(frame_out);
- RK_U32 dec_height = mpp_frame_get_height(frame_out);
- if (!enc_buf) {
- mpp_err_f("enc buf is NULL");
- return MPP_NOK;
- }
- if (!dec_buf) {
- mpp_err_f("dec buf is NULL");
- return MPP_NOK;
- }
- if (enc_width != dec_width) {
- mpp_err_f("enc_width %d != dec_width %d", enc_width, dec_width);
- return MPP_NOK;
- }
- if (enc_height != dec_height) {
- mpp_err_f("enc_height %d != dec_height %d", enc_height, dec_height);
- return MPP_NOK;
- }
- return MPP_OK;
- }
- static void mpi_rc_calc_psnr(MpiRcStat *stat, MppFrame frame_in,
- MppFrame frame_out)
- {
- RK_U32 x, y;
- RK_S32 tmp;
- double ssd_y = 0.0;
- double mse_y = 0.0;
- double psnr_y = 0.0;
- RK_U32 width = mpp_frame_get_width(frame_in);
- RK_U32 height = mpp_frame_get_height(frame_in);
- RK_U32 luma_size = width * height;
- RK_U32 enc_hor_stride = mpp_frame_get_hor_stride(frame_in);
- RK_U32 dec_hor_stride = mpp_frame_get_hor_stride(frame_out);
- RK_U8 *enc_buf = (RK_U8 *)mpp_buffer_get_ptr(mpp_frame_get_buffer(frame_in));
- RK_U8 *dec_buf = (RK_U8 *)mpp_buffer_get_ptr(mpp_frame_get_buffer(frame_out));
- RK_U8 *enc_buf_y = enc_buf;
- RK_U8 *dec_buf_y = dec_buf;
- for (y = 0 ; y < height; y++) {
- for (x = 0; x < width; x++) {
- tmp = enc_buf_y[x + y * enc_hor_stride] -
- dec_buf_y[x + y * dec_hor_stride];
- tmp *= tmp;
- ssd_y += tmp;
- }
- }
- // NOTE: should be 65025.0 rather than 65025,
- // because 65025*luma_size may exceed
- // 1 << 32.
- mse_y = ssd_y / (65025.0 * luma_size); // 65025=255*255
- if (mse_y <= 0.0000000001)
- psnr_y = 100;
- else
- psnr_y = -10.0 * log10f(mse_y);
- stat->psnr_y = psnr_y;
- }
- static float ssim_end1( int s1, int s2, int ss, int s12 )
- {
- /*
- * Maximum value for 10-bit is: ss*64 = (2^10-1)^2*16*4*64 = 4286582784,
- * which will overflow in some cases.
- * s1*s1, s2*s2, and s1*s2 also obtain this value for edge cases:
- * ((2^10-1)*16*4)^2 = 4286582784.
- * Maximum value for 9-bit is: ss*64 = (2^9-1)^2*16*4*64 = 1069551616,
- * which will not overflow.
- */
- static const int ssim_c1 =
- (int)(.01 * .01 * MPI_PIXEL_MAX * MPI_PIXEL_MAX * 64 + .5);
- static const int ssim_c2 =
- (int)(.03 * .03 * MPI_PIXEL_MAX * MPI_PIXEL_MAX * 64 * 63 + .5);
- int fs1 = s1;
- int fs2 = s2;
- int fss = ss;
- int fs12 = s12;
- int vars = fss * 64 - fs1 * fs1 - fs2 * fs2;
- int covar = fs12 * 64 - fs1 * fs2;
- return (float)(2 * fs1 * fs2 + ssim_c1) *
- (float)(2 * covar + ssim_c2) /
- ((float)(fs1 * fs1 + fs2 * fs2 + ssim_c1) *
- (float)(vars + ssim_c2));
- }
- static float ssim_end4( int sum0[5][4], int sum1[5][4], int width )
- {
- double ssim = 0.0;
- int i = 0;
- for (i = 0; i < width; i++ )
- ssim += ssim_end1(sum0[i][0] + sum0[i + 1][0] +
- sum1[i][0] + sum1[i + 1][0],
- sum0[i][1] + sum0[i + 1][1] +
- sum1[i][1] + sum1[i + 1][1],
- sum0[i][2] + sum0[i + 1][2] +
- sum1[i][2] + sum1[i + 1][2],
- sum0[i][3] + sum0[i + 1][3] +
- sum1[i][3] + sum1[i + 1][3] );
- return ssim;
- }
- static void ssim_4x4x2_core( const pixel *pix1, intptr_t stride1,
- const pixel *pix2, intptr_t stride2,
- int sums[2][4] )
- {
- int a = 0;
- int b = 0;
- int x = 0;
- int y = 0;
- int z = 0;
- for (z = 0; z < 2; z++ ) {
- uint32_t s1 = 0, s2 = 0, ss = 0, s12 = 0;
- for (y = 0; y < 4; y++ )
- for ( x = 0; x < 4; x++ ) {
- a = pix1[x + y * stride1];
- b = pix2[x + y * stride2];
- s1 += a;
- s2 += b;
- ss += a * a;
- ss += b * b;
- s12 += a * b;
- }
- sums[z][0] = s1;
- sums[z][1] = s2;
- sums[z][2] = ss;
- sums[z][3] = s12;
- pix1 += 4;
- pix2 += 4;
- }
- }
- static float calc_ssim(pixel *pix1, RK_U32 stride1,
- pixel *pix2, RK_U32 stride2,
- int width, int height, void *buf, int *cnt)
- {
- int x = 0;
- int y = 0;
- int z = 0;
- float ssim = 0.0;
- int (*sum0)[4] = buf;
- int (*sum1)[4] = sum0 + (width >> 2) + 3;
- width >>= 2;
- height >>= 2;
- for ( y = 1; y < height; y++ ) {
- for ( ; z <= y; z++ ) {
- MPP_SWAP( void*, sum0, sum1 );
- for ( x = 0; x < width; x += 2 )
- ssim_4x4x2_core(&pix1[4 * (x + z * stride1)],
- stride1, &pix2[4 * (x + z * stride2)],
- stride2, &sum0[x] );
- }
- for ( x = 0; x < width - 1; x += 4 )
- ssim += ssim_end4(sum0 + x, sum1 + x,
- MPP_MIN(4, width - x - 1));
- }
- *cnt = (height - 1) * (width - 1);
- return ssim;
- }
- static void mpi_rc_calc_ssim(MpiRc2TestCtx *ctx, MppFrame frame_in, MppFrame frame_out)
- {
- int cnt = 0;
- float ssim = 0;
- MpiRcStat *stat = &ctx->stat;
- RK_U32 width = mpp_frame_get_width(frame_in);
- RK_U32 height = mpp_frame_get_height(frame_in);
- RK_U32 enc_hor_stride = mpp_frame_get_hor_stride(frame_in);
- RK_U32 dec_hor_stride = mpp_frame_get_hor_stride(frame_out);
- pixel *enc_buf =
- (RK_U8 *)mpp_buffer_get_ptr(mpp_frame_get_buffer(frame_in));
- pixel *dec_buf =
- (RK_U8 *)mpp_buffer_get_ptr(mpp_frame_get_buffer(frame_out));
- pixel *enc_buf_y = enc_buf;
- pixel *dec_buf_y = dec_buf;
- if (NULL == ctx->com_buf)
- ctx->com_buf = mpp_malloc(RK_U8, enc_hor_stride * mpp_frame_get_ver_stride(frame_out) * 2);
- ssim = calc_ssim(enc_buf_y, enc_hor_stride, dec_buf_y, dec_hor_stride,
- width - 2, height - 2, ctx->com_buf, &cnt);
- ssim /= (float)cnt;
- stat->ssim_y = (double)ssim;
- }
- static MPP_RET mpi_rc_calc_stat(MpiRc2TestCtx *ctx,
- MppFrame frame_in, MppFrame frame_out)
- {
- MPP_RET ret = MPP_OK;
- MpiRcStat *stat = &ctx->stat;
- ret = mpi_rc_cmp_frame(frame_in, frame_out);
- if (ret) {
- mpp_err_f("mpi_rc_cmp_frame failed ret %d", ret);
- return MPP_NOK;
- }
- if (ctx->enc_cmd->psnr_en) {
- mpi_rc_calc_psnr(stat, frame_in, frame_out);
- ctx->total_psnrs += stat->psnr_y;
- }
- if (ctx->enc_cmd->ssim_en) {
- mpi_rc_calc_ssim(ctx, frame_in, frame_out);
- ctx->total_ssims += stat->ssim_y;
- }
- return ret;
- }
- static void mpi_rc_log_stat(MpiRc2TestCtx *ctx, RK_U32 frame_count,
- RK_U32 one_second, RK_U32 seq_end)
- {
- //static char rc_log_str[1024] = {0};
- MpiRcStat *stat = &ctx->stat;
- MpiRcFile *file = &ctx->file;
- FILE *fp = file->fp_stat;
- mpp_log("frame %3d | frame_size %6d bytes | psnr %5.2f | ssim %5.5f",
- frame_count, stat->frame_size, stat->psnr_y, stat->ssim_y);
- if (one_second)
- mpp_log("ins_bitrate %f kbps", stat->ins_bitrate * 8.0 / 1000);
- if (fp) {
- fprintf(fp, "%3d,%6d,%5.2f,%5.5f,",
- frame_count, stat->frame_size, stat->psnr_y, stat->ssim_y);
- if (one_second)
- fprintf(fp, "bitsrate: %d,", stat->ins_bitrate);
- if (!seq_end)
- fprintf(fp, "\n");
- }
- }
- static MPP_RET mpi_rc_enc_init(MpiRc2TestCtx *ctx)
- {
- MpiEncTestArgs* enc_cmd = ctx->enc_cmd;
- MppApi *enc_mpi = NULL;
- MppCtx enc_ctx = NULL;
- MppPollType block = MPP_POLL_NON_BLOCK;
- MppEncRcCfg *rc_cfg = &ctx->rc_cfg;
- MppEncSeiMode sei_mode = MPP_ENC_SEI_MODE_ONE_SEQ;
- MppEncCfg cfg = ctx->cfg;
- RK_U32 debreath_en = 0;
- RK_U32 debreath_s = 0;
- MPP_RET ret = MPP_OK;
- // encoder init
- ret = mpp_create(&ctx->enc_ctx, &ctx->enc_mpi);
- if (ret) {
- mpp_err("mpp_create encoder failed\n");
- goto MPP_TEST_OUT;
- }
- enc_mpi = ctx->enc_mpi;
- enc_ctx = ctx->enc_ctx;
- rc_cfg->fps_in_denom = 1;
- rc_cfg->fps_out_denom = 1;
- rc_cfg->fps_in_num = 30;
- rc_cfg->fps_out_num = 30;
- rc_cfg->fps_in_flex = 0;
- rc_cfg->fps_out_flex = 0;
- rc_cfg->max_reenc_times = 1;
- rc_cfg->gop = enc_cmd->gop_len;
- block = MPP_POLL_BLOCK;
- ret = enc_mpi->control(enc_ctx, MPP_SET_INPUT_TIMEOUT, (MppParam)&block);
- if (ret) {
- mpp_err("enc_mpi->control MPP_SET_INPUT_TIMEOUT failed\n");
- goto MPP_TEST_OUT;
- }
- block = MPP_POLL_BLOCK;
- ret = enc_mpi->control(enc_ctx, MPP_SET_OUTPUT_TIMEOUT, (MppParam)&block);
- if (ret) {
- mpp_err("enc_mpi->control MPP_SET_OUTPUT_TIMEOUT failed\n");
- goto MPP_TEST_OUT;
- }
- ret = mpp_init(enc_ctx, MPP_CTX_ENC, enc_cmd->type);
- if (ret) {
- mpp_err("mpp_init enc failed\n");
- goto MPP_TEST_OUT;
- }
- if (enc_cmd->width)
- mpp_enc_cfg_set_s32(cfg, "prep:width", enc_cmd->width);
- if (enc_cmd->height)
- mpp_enc_cfg_set_s32(cfg, "prep:height", enc_cmd->height);
- if (enc_cmd->hor_stride)
- mpp_enc_cfg_set_s32(cfg, "prep:hor_stride", enc_cmd->hor_stride);
- if (enc_cmd->ver_stride)
- mpp_enc_cfg_set_s32(cfg, "prep:ver_stride", enc_cmd->ver_stride);
- mpp_enc_cfg_set_s32(cfg, "prep:format", MPP_FMT_YUV420SP);
- mpp_enc_cfg_set_s32(cfg, "rc:mode", enc_cmd->rc_mode);
- switch (enc_cmd->rc_mode) {
- case MPP_ENC_RC_MODE_FIXQP : {
- /* do not set bps on fix qp mode */
- } break;
- case MPP_ENC_RC_MODE_CBR : {
- /* CBR mode has narrow bound */
- mpp_enc_cfg_set_s32(cfg, "rc:bps_target", enc_cmd->bps_target);
- mpp_enc_cfg_set_s32(cfg, "rc:bps_max", enc_cmd->bps_max ? enc_cmd->bps_max : enc_cmd->bps_target * 3 / 2);
- mpp_enc_cfg_set_s32(cfg, "rc:bps_min", enc_cmd->bps_min ? enc_cmd->bps_max : enc_cmd->bps_target / 2);
- } break;
- case MPP_ENC_RC_MODE_VBR : {
- /* CBR mode has wide bound */
- mpp_enc_cfg_set_s32(cfg, "rc:bps_target", enc_cmd->bps_target);
- mpp_enc_cfg_set_s32(cfg, "rc:bps_max", enc_cmd->bps_max ? enc_cmd->bps_max : enc_cmd->bps_target * 17 / 16);
- mpp_enc_cfg_set_s32(cfg, "rc:bps_min", enc_cmd->bps_min ? enc_cmd->bps_max : enc_cmd->bps_target * 1 / 16);
- } break;
- default : {
- mpp_err_f("unsupport encoder rc mode %d\n", enc_cmd->rc_mode);
- } break;
- }
- /* fix input / output frame rate */
- mpp_enc_cfg_set_s32(cfg, "rc:fps_in_flex", rc_cfg->fps_in_flex);
- mpp_enc_cfg_set_s32(cfg, "rc:fps_in_num", rc_cfg->fps_in_num);
- mpp_enc_cfg_set_s32(cfg, "rc:fps_in_denom", rc_cfg->fps_in_denom);
- mpp_enc_cfg_set_s32(cfg, "rc:fps_out_flex", rc_cfg->fps_out_flex);
- mpp_enc_cfg_set_s32(cfg, "rc:fps_out_num", rc_cfg->fps_out_num);
- mpp_enc_cfg_set_s32(cfg, "rc:fps_out_denom", rc_cfg->fps_out_denom);
- mpp_enc_cfg_set_s32(cfg, "rc:gop", enc_cmd->gop_len ? enc_cmd->gop_len : 30 * 2);
- /* drop frame or not when bitrate overflow */
- mpp_enc_cfg_set_u32(cfg, "rc:drop_mode", MPP_ENC_RC_DROP_FRM_DISABLED);
- mpp_enc_cfg_set_u32(cfg, "rc:drop_thd", 20); /* 20% of max bps */
- mpp_enc_cfg_set_u32(cfg, "rc:drop_gap", 1); /* Do not continuous drop frame */
- mpp_env_get_u32("dbrh_en", &debreath_en, 0);
- mpp_env_get_u32("dbrh_s", &debreath_s, 16);
- mpp_enc_cfg_set_u32(cfg, "rc:debreath_en", debreath_en);
- mpp_enc_cfg_set_u32(cfg, "rc:debreath_strength", debreath_s);
- /* setup codec */
- mpp_enc_cfg_set_s32(cfg, "codec:type", enc_cmd->type);
- switch (enc_cmd->type) {
- case MPP_VIDEO_CodingAVC : {
- /*
- * H.264 profile_idc parameter
- * 66 - Baseline profile
- * 77 - Main profile
- * 100 - High profile
- */
- mpp_enc_cfg_set_s32(cfg, "h264:profile", 100);
- /*
- * H.264 level_idc parameter
- * 10 / 11 / 12 / 13 - qcif@15fps / cif@7.5fps / cif@15fps / cif@30fps
- * 20 / 21 / 22 - cif@30fps / half-D1@@25fps / D1@12.5fps
- * 30 / 31 / 32 - D1@25fps / 720p@30fps / 720p@60fps
- * 40 / 41 / 42 - 1080p@30fps / 1080p@30fps / 1080p@60fps
- * 50 / 51 / 52 - 4K@30fps
- */
- mpp_enc_cfg_set_s32(cfg, "h264:level", 40);
- mpp_enc_cfg_set_s32(cfg, "h264:cabac_en", 1);
- mpp_enc_cfg_set_s32(cfg, "h264:cabac_idc", 0);
- mpp_enc_cfg_set_s32(cfg, "h264:trans8x8", 1);
- if (enc_cmd->rc_mode == MPP_ENC_RC_MODE_FIXQP) {
- mpp_enc_cfg_set_s32(cfg, "h264:qp_init", 20);
- mpp_enc_cfg_set_s32(cfg, "h264:qp_max", 16);
- mpp_enc_cfg_set_s32(cfg, "h264:qp_min", 16);
- mpp_enc_cfg_set_s32(cfg, "h264:qp_max_i", 20);
- mpp_enc_cfg_set_s32(cfg, "h264:qp_min_i", 20);
- } else {
- mpp_enc_cfg_set_s32(cfg, "h264:qp_init", 26);
- mpp_enc_cfg_set_s32(cfg, "h264:qp_max", 51);
- mpp_enc_cfg_set_s32(cfg, "h264:qp_min", 10);
- mpp_enc_cfg_set_s32(cfg, "h264:qp_max_i", 46);
- mpp_enc_cfg_set_s32(cfg, "h264:qp_min_i", 18);
- }
- } break;
- case MPP_VIDEO_CodingMJPEG : {
- mpp_enc_cfg_set_s32(cfg, "jpeg:q_factor", 80);
- mpp_enc_cfg_set_s32(cfg, "jpeg:qf_max", 99);
- mpp_enc_cfg_set_s32(cfg, "jpeg:qf_min", 1);
- } break;
- case MPP_VIDEO_CodingVP8 : {
- mpp_enc_cfg_set_s32(cfg, "vp8:qp_init", 40);
- mpp_enc_cfg_set_s32(cfg, "vp8:qp_max", 127);
- mpp_enc_cfg_set_s32(cfg, "vp8:qp_min", 0);
- mpp_enc_cfg_set_s32(cfg, "vp8:qp_max_i", 127);
- mpp_enc_cfg_set_s32(cfg, "vp8:qp_min_i", 0);
- } break;
- case MPP_VIDEO_CodingHEVC : {
- mpp_enc_cfg_set_s32(cfg, "h265:qp_init", enc_cmd->rc_mode == MPP_ENC_RC_MODE_FIXQP ? -1 : 26);
- mpp_enc_cfg_set_s32(cfg, "h265:qp_max", 51);
- mpp_enc_cfg_set_s32(cfg, "h265:qp_min", 10);
- mpp_enc_cfg_set_s32(cfg, "h265:qp_max_i", 46);
- mpp_enc_cfg_set_s32(cfg, "h265:qp_min_i", 18);
- } break;
- default : {
- mpp_err_f("unsupport encoder coding type %d\n", enc_cmd->type);
- } break;
- }
- ret = enc_mpi->control(enc_ctx, MPP_ENC_SET_CFG, cfg);
- if (ret) {
- mpp_err("mpi control enc set cfg failed ret %d\n", ret);
- goto MPP_TEST_OUT;
- }
- /* optional */
- ret = enc_mpi->control(enc_ctx, MPP_ENC_SET_SEI_CFG, &sei_mode);
- if (ret) {
- mpp_err("mpi control enc set sei cfg failed ret %d\n", ret);
- goto MPP_TEST_OUT;
- }
- MPP_TEST_OUT:
- return ret;
- }
- static MPP_RET mpi_rc_post_dec_init(MpiRc2TestCtx *ctx)
- {
- MpiEncTestArgs *enc_cmd = ctx->enc_cmd;
- MppApi *dec_mpi = NULL;
- MppCtx dec_ctx = NULL;
- MppPollType block = MPP_POLL_NON_BLOCK;
- RK_U32 need_split = 0;
- MPP_RET ret = MPP_OK;
- // decoder init
- ret = mpp_create(&ctx->dec_ctx_post, &ctx->dec_mpi_post);
- if (ret) {
- mpp_err("mpp_create decoder failed\n");
- goto MPP_TEST_OUT;
- }
- dec_mpi = ctx->dec_mpi_post;
- dec_ctx = ctx->dec_ctx_post;
- ret = mpp_packet_init(&ctx->dec_pkt_post,
- ctx->dec_in_buf_post, ctx->dec_in_buf_post_size);
- if (ret) {
- mpp_err("mpp_packet_init failed\n");
- goto MPP_TEST_OUT;
- }
- ret = dec_mpi->control(dec_ctx, MPP_DEC_SET_PARSER_SPLIT_MODE, &need_split);
- if (ret) {
- mpp_err("dec_mpi->control failed\n");
- goto MPP_TEST_OUT;
- }
- ret = dec_mpi->control(dec_ctx, MPP_SET_INPUT_TIMEOUT, (MppParam)&block);
- if (ret) {
- mpp_err("dec_mpi->control dec MPP_SET_INPUT_TIMEOUT failed\n");
- goto MPP_TEST_OUT;
- }
- block = MPP_POLL_NON_BLOCK;
- ret = dec_mpi->control(dec_ctx, MPP_SET_OUTPUT_TIMEOUT, (MppParam)&block);
- if (ret) {
- mpp_err("dec_mpi->control MPP_SET_OUTPUT_TIMEOUT failed\n");
- goto MPP_TEST_OUT;
- }
- ret = mpp_init(dec_ctx, MPP_CTX_DEC, enc_cmd->type);
- if (ret) {
- mpp_err("mpp_init dec failed\n");
- goto MPP_TEST_OUT;
- }
- MPP_TEST_OUT:
- return ret;
- }
- static MPP_RET mpi_rc_dec_post_decode(MpiRc2TestCtx *ctx, MppFrame orig_frm)
- {
- MPP_RET ret = MPP_OK;
- RK_S32 dec_pkt_done = 0;
- MppFrame out_frm = NULL;
- do {
- if (ctx->pkt_eos)
- mpp_packet_set_eos(ctx->dec_pkt_post);
- // send the packet first if packet is not done
- if (!dec_pkt_done) {
- ret = ctx->dec_mpi_post->decode_put_packet(ctx->dec_ctx_post,
- ctx->dec_pkt_post);
- if (MPP_OK == ret)
- dec_pkt_done = 1;
- }
- // then get all available frame and release
- do {
- RK_S32 dec_get_frm = 0;
- RK_U32 dec_frm_eos = 0;
- ret = ctx->dec_mpi_post->decode_get_frame(ctx->dec_ctx_post,
- &out_frm);
- if (ret) {
- mpp_err("decode_get_frame failed ret %d\n", ret);
- break;
- }
- if (out_frm) {
- if (mpp_frame_get_info_change(out_frm)) {
- mpp_log("decode_get_frame get info changed found\n");
- ctx->dec_mpi_post->control(ctx->dec_ctx_post,
- MPP_DEC_SET_INFO_CHANGE_READY,
- NULL);
- } else {
- mpi_rc_calc_stat(ctx, orig_frm, out_frm);
- mpi_rc_log_stat(ctx, ctx->frm_idx,
- !((ctx->frm_idx - ctx->calc_base_idx + 1) %
- ctx->rc_cfg.fps_in_num),
- 0);
- dec_get_frm = 1;
- }
- dec_frm_eos = mpp_frame_get_eos(out_frm);
- mpp_frame_deinit(&out_frm);
- out_frm = NULL;
- }
- // if last packet is send but last frame is not found continue
- if (ctx->pkt_eos && dec_pkt_done && !dec_frm_eos)
- continue;
- if (dec_get_frm)
- break;
- } while (1);
- if (dec_pkt_done)
- break;
- msleep(5);
- } while (1);
- return ret;
- }
- static MPP_RET mpi_rc_pre_dec_init(MpiRc2TestCtx *ctx)
- {
- RK_U32 need_split = 1;
- MppPollType block = MPP_POLL_NON_BLOCK;
- RK_U32 fast_en = 0;
- MppApi *dec_mpi = NULL;
- MppCtx dec_ctx = NULL;
- MppFrameFormat format = MPP_FMT_YUV420SP;
- RK_U32 fbc_en = 0;
- MPP_RET ret = MPP_OK;
- mpp_env_get_u32("fbc_dec_en", &fbc_en, 0);
- mpp_env_get_u32("fast_en", &fast_en, 0);
- if (fbc_en)
- format = format | MPP_FRAME_FBC_AFBC_V2;
- // decoder init
- ret = mpp_create(&ctx->dec_ctx_pre, &ctx->dec_mpi_pre);
- if (ret) {
- mpp_err("mpp_create decoder failed\n");
- goto MPP_TEST_OUT;
- }
- dec_mpi = ctx->dec_mpi_pre;
- dec_ctx = ctx->dec_ctx_pre;
- ret = mpp_packet_init(&ctx->dec_pkt_pre, ctx->dec_in_buf_pre, ctx->dec_in_buf_pre_size);
- if (ret) {
- mpp_err("mpp_packet_init failed\n");
- goto MPP_TEST_OUT;
- }
- ret = dec_mpi->control(dec_ctx, MPP_DEC_SET_PARSER_SPLIT_MODE, &need_split);
- if (ret) {
- mpp_err("dec_mpi->control failed\n");
- goto MPP_TEST_OUT;
- }
- ret = dec_mpi->control(dec_ctx, MPP_DEC_SET_PARSER_FAST_MODE, &fast_en);
- if (ret) {
- mpp_err("dec_mpi->control failed\n");
- goto MPP_TEST_OUT;
- }
- ret = dec_mpi->control(dec_ctx, MPP_SET_INPUT_TIMEOUT, (MppParam)&block);
- if (ret) {
- mpp_err("dec_mpi->control dec MPP_SET_INPUT_TIMEOUT failed\n");
- goto MPP_TEST_OUT;
- }
- block = MPP_POLL_NON_BLOCK;
- ret = dec_mpi->control(dec_ctx, MPP_SET_OUTPUT_TIMEOUT, (MppParam)&block);
- if (ret) {
- mpp_err("dec_mpi->control MPP_SET_OUTPUT_TIMEOUT failed\n");
- goto MPP_TEST_OUT;
- }
- ret = mpp_init(dec_ctx, MPP_CTX_DEC, ctx->dec_type);
- if (ret) {
- mpp_err("mpp_init dec failed\n");
- goto MPP_TEST_OUT;
- }
- ret = dec_mpi->control(dec_ctx, MPP_DEC_SET_OUTPUT_FORMAT, &format);
- if (ret) {
- mpp_err("dec_mpi->control failed\n");
- goto MPP_TEST_OUT;
- }
- MPP_TEST_OUT:
- return ret;
- }
- static MPP_RET mpi_rc_info_change(MpiRc2TestCtx *ctx, MppFrame frm)
- {
- MPP_RET ret = MPP_OK;
- mpp_enc_cfg_set_s32(ctx->cfg, "prep:width", mpp_frame_get_width(frm));
- mpp_enc_cfg_set_s32(ctx->cfg, "prep:height", mpp_frame_get_height(frm));
- mpp_enc_cfg_set_s32(ctx->cfg, "prep:hor_stride", mpp_frame_get_hor_stride(frm));
- mpp_enc_cfg_set_s32(ctx->cfg, "prep:ver_stride", mpp_frame_get_ver_stride(frm));
- mpp_enc_cfg_set_s32(ctx->cfg, "prep:format", mpp_frame_get_fmt(frm));
- ret = ctx->enc_mpi->control(ctx->enc_ctx, MPP_ENC_SET_CFG, ctx->cfg);
- ctx->dec_mpi_post->control(ctx->dec_ctx_post, MPP_DEC_SET_FRAME_INFO, (MppParam)frm);
- return ret;
- }
- static MPP_RET mpi_rc_enc(MpiRc2TestCtx *ctx)
- {
- MPP_RET ret = MPP_OK;
- MppApi *mpi = ctx->dec_mpi_pre;
- MppCtx dec_ctx = ctx->dec_ctx_pre;
- MppFrame frm = NULL;
- do {
- ret = mpi->decode_get_frame(dec_ctx, &frm);
- if (ret) {
- mpp_err("decode_get_frame failed ret %d\n", ret);
- break;
- }
- if (frm) {
- ctx->frm_eos = mpp_frame_get_eos(frm);
- if (mpp_frame_get_info_change(frm)) {
- mpp_log("decode_get_frame get info changed found\n");
- mpi->control(dec_ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
- mpi_rc_info_change(ctx, frm);
- ctx->start_enc = mpp_time();
- } else {
- void *ptr;
- size_t len;
- /*force eos*/
- if ((ctx->enc_cmd->frame_num > 0) && (ctx->frm_idx > ctx->enc_cmd->frame_num)) {
- ctx->loop_end = 1;
- mpp_frame_set_eos(frm, 1);
- ctx->frm_eos = mpp_frame_get_eos(frm);
- }
- #ifndef ASYN_ENC
- ctx->enc_mpi->encode_put_frame(ctx->enc_ctx, frm);
- ctx->enc_mpi->encode_get_packet(ctx->enc_ctx, &ctx->enc_pkt);
- #else
- LAST_PACKET:
- ctx->enc_mpi->encode(ctx->enc_ctx, frm, &ctx->enc_pkt);
- frm = NULL; //ASYN_ENC will free after get packet
- #endif
- if (ctx->enc_pkt) {
- len = mpp_packet_get_length(ctx->enc_pkt);
- ctx->stat.frame_size = len;
- ctx->stream_size_1s += len;
- ctx->total_bits += len * 8;
- if ((ctx->frm_idx - ctx->calc_base_idx + 1) %
- ctx->rc_cfg.fps_in_num == 0) {
- ctx->stat.ins_bitrate = ctx->stream_size_1s;
- ctx->stream_size_1s = 0;
- }
- ptr = mpp_packet_get_pos(ctx->enc_pkt);
- if (ctx->file.fp_enc_out)
- fwrite(ptr, 1, len, ctx->file.fp_enc_out);
- /* check post packet first */
- if (len > ctx->dec_in_buf_post_size) {
- RK_U32 buf_size = MPP_ALIGN(len, SZ_4K);
- ctx->dec_in_buf_post = mpp_realloc(ctx->dec_in_buf_post, RK_U8, buf_size);
- ctx->dec_in_buf_post_size = buf_size;
- mpp_packet_set_data(ctx->dec_pkt_post, ctx->dec_in_buf_post);
- mpp_packet_set_size(ctx->dec_pkt_post, buf_size);
- mpp_packet_set_pos(ctx->dec_pkt_post, ctx->dec_in_buf_post);
- mpp_packet_set_length(ctx->dec_pkt_post, 0);
- }
- /* decode one frame */
- // write packet to dec input
- mpp_packet_write(ctx->dec_pkt_post, 0, ptr, len);
- // reset pos
- mpp_packet_set_pos(ctx->dec_pkt_post, ctx->dec_in_buf_post);
- mpp_packet_set_length(ctx->dec_pkt_post, len);
- mpp_packet_set_size(ctx->dec_pkt_post, len);
- if (mpp_packet_has_meta(ctx->enc_pkt)) {
- MppFrame frame = NULL;
- MppMeta meta = mpp_packet_get_meta(ctx->enc_pkt);
- mpp_meta_get_frame(meta, KEY_INPUT_FRAME, &frame);
- if (ctx->enc_cmd->ssim_en || ctx->enc_cmd->psnr_en) {
- mpp_packet_write(ctx->dec_pkt_post, 0, ptr, len);
- mpi_rc_dec_post_decode(ctx, frame);
- }
- if (frame) {
- frm = frame; //ASYN_ENC delay free
- }
- } else {
- if (ctx->enc_cmd->ssim_en || ctx->enc_cmd->psnr_en) {
- mpp_packet_write(ctx->dec_pkt_post, 0, ptr, len);
- mpi_rc_dec_post_decode(ctx, frm);
- }
- }
- ctx->enc_pkt_eos = mpp_packet_get_eos(ctx->enc_pkt);
- ctx->frm_idx++;
- mpp_packet_deinit(&ctx->enc_pkt);
- }
- }
- mpp_frame_deinit(&frm);
- frm = NULL;
- } else {
- msleep(3);
- continue;
- }
- #ifdef ANSY_ENC
- if (ctx->frm_eos && !ctx->enc_pkt_eos) {
- goto LAST_PACKET;
- }
- #endif
- if (ctx->enc_pkt_eos) {
- break;
- }
- } while (1);
- return ret;
- }
- static MPP_RET mpi_rc_buffer_init(MpiRc2TestCtx *ctx)
- {
- /* NOTE: packet buffer may overflow */
- size_t packet_size = SZ_256K;
- MPP_RET ret = MPP_OK;
- ret = mpp_buffer_group_get_internal(&ctx->pkt_grp, MPP_BUFFER_TYPE_ION);
- if (ret) {
- mpp_err("failed to get buffer group for output packet ret %d\n", ret);
- goto RET;
- }
- ctx->dec_in_buf_post = mpp_calloc(RK_U8, packet_size);
- if (NULL == ctx->dec_in_buf_post) {
- mpp_err("mpi_dec_test malloc input stream buffer failed\n");
- goto RET;
- }
- ctx->dec_in_buf_post_size = packet_size;
- ctx->frm_idx = 0;
- ctx->calc_base_idx = 0;
- ctx->stream_size_1s = 0;
- return ret;
- RET:
- ctx->dec_ctx_pre = NULL;
- ctx->dec_ctx_post = NULL;
- MPP_FREE(ctx->dec_in_buf_post);
- if (ctx->pkt_grp) {
- mpp_buffer_group_put(ctx->pkt_grp);
- ctx->pkt_grp = NULL;
- }
- return ret;
- }
- #define CHECK_RET(x) do { \
- if (x < 0) { \
- mpp_err_f("%d failed\n"); \
- goto MPP_TEST_OUT; \
- } \
- } while (0)
- static void *rc2_pre_dec_thread(void *param)
- {
- MpiRc2TestCtx *ctx = (MpiRc2TestCtx *)param;
- FileReader reader = ctx->reader;
- FileBufSlot *slot = NULL;
- MppPacket packet = ctx->dec_pkt_pre;
- MppApi *mpi = ctx->dec_mpi_pre;
- MppCtx dec_ctx = ctx->dec_ctx_pre;
- MPP_RET ret = MPP_OK;
- RK_S32 dec_pkt_done = 0;
- while (!ctx->loop_end) {
- RK_U32 pkt_eos = 0;
- dec_pkt_done = 0;
- ret = reader_index_read(reader, ctx->pre_pkt_idx++, &slot);
- pkt_eos = slot->eos;
- if (pkt_eos) {
- if (ctx->enc_cmd->frame_num < 0) {
- ctx->pre_pkt_idx = 0;
- pkt_eos = 0;
- } else if (!ctx->enc_cmd->frame_num) {
- ctx->loop_end = 1;
- } else {
- ctx->pre_pkt_idx = 0;
- pkt_eos = 0;
- }
- }
- if ((ctx->enc_cmd->frame_num > 0) && (ctx->frm_idx > ctx->enc_cmd->frame_num)) {
- mpp_log("frm_idx %d, frame_num %d",
- ctx->frm_idx, ctx->enc_cmd->frame_num);
- ctx->loop_end = 1;
- }
- mpp_packet_set_data(packet, slot->data);
- mpp_packet_set_size(packet, slot->size);
- mpp_packet_set_pos(packet, slot->data);
- mpp_packet_set_length(packet, slot->size);
- if (ctx->loop_end) {
- mpp_packet_set_eos(packet);
- ctx->pkt_eos = 1;
- }
- do {
- ret = mpi->decode_put_packet(dec_ctx, packet);
- if (MPP_OK == ret)
- dec_pkt_done = 1;
- else
- msleep(5);
- if (ctx->loop_end) {
- break;
- }
- } while (!dec_pkt_done);
- if (ctx->pkt_eos) {
- mpp_log("dec stream finish\n");
- break;
- }
- }
- mpp_log("rc2_pre_dec_thread exit");
- return NULL;
- }
- static MPP_RET mpi_rc_codec(MpiRc2TestCtx *ctx)
- {
- MPP_RET ret = MPP_OK;
- RK_S64 t_e;
- CHECK_RET(mpi_rc_buffer_init(ctx));
- CHECK_RET(mpi_rc_post_dec_init(ctx));
- CHECK_RET(mpi_rc_pre_dec_init(ctx));
- CHECK_RET(mpp_enc_cfg_init(&ctx->cfg));
- CHECK_RET(mpi_rc_enc_init(ctx));
- pthread_create(&ctx->dec_thr, NULL, rc2_pre_dec_thread, ctx);
- while (1) {
- mpi_rc_enc(ctx);
- if (ctx->enc_pkt_eos) {
- mpp_log("stream finish\n");
- break;
- }
- }
- t_e = mpp_time();
- RK_U64 elapsed_time = t_e - ctx->start_enc;
- float frame_rate = (float)ctx->frm_idx * 1000000 / elapsed_time;
- mpp_log("enc_dec %d frame use time %lld ms frm rate %.2f\n",
- ctx->frm_idx, elapsed_time / 1000, frame_rate);
- if (ctx->frm_idx) {
- MpiEncTestArgs* enc_cmd = ctx->enc_cmd;
- mpp_log("%s: %s: average: bps %d | psnr %5.2f | ssim %5.5f",
- enc_cmd->file_input, enc_cmd->gop_mode ? "smart_p" : "normal_p",
- 30 * (RK_U32)(ctx->total_bits / ctx->frm_idx),
- ctx->total_psnrs / ctx->frm_idx, ctx->total_ssims / ctx->frm_idx);
- if (ctx->file.fp_stat)
- fprintf(ctx->file.fp_stat, "%s: %s: average: bps %dk | psnr %5.2f | ssim %5.5f \n",
- enc_cmd->file_input, enc_cmd->gop_mode ? "smart_p" : "normal_p",
- 30 * (RK_U32)(ctx->total_bits / ctx->frm_idx) / 1000,
- ctx->total_psnrs / ctx->frm_idx, ctx->total_ssims / ctx->frm_idx);
- }
- CHECK_RET(ctx->enc_mpi->reset(ctx->enc_ctx));
- CHECK_RET(ctx->dec_mpi_pre->reset(ctx->dec_ctx_pre));
- CHECK_RET(ctx->dec_mpi_post->reset(ctx->dec_ctx_post));
- MPP_TEST_OUT:
- // encoder deinit
- pthread_join(ctx->dec_thr, NULL);
- if (ctx->enc_ctx) {
- mpp_destroy(ctx->enc_ctx);
- ctx->enc_ctx = NULL;
- }
- if (ctx->pkt_grp) {
- mpp_buffer_group_put(ctx->pkt_grp);
- ctx->pkt_grp = NULL;
- }
- // decoder deinit
- if (ctx->dec_pkt_post) {
- mpp_packet_deinit(&ctx->dec_pkt_post);
- ctx->dec_pkt_post = NULL;
- }
- if (ctx->dec_pkt_pre) {
- mpp_packet_deinit(&ctx->dec_pkt_pre);
- ctx->dec_pkt_pre = NULL;
- }
- if (ctx->cfg) {
- mpp_enc_cfg_deinit(ctx->cfg);
- ctx->cfg = NULL;
- }
- if (ctx->dec_ctx_post) {
- mpp_destroy(ctx->dec_ctx_post);
- ctx->dec_ctx_post = NULL;
- }
- if (ctx->dec_ctx_pre) {
- mpp_destroy(ctx->dec_ctx_pre);
- ctx->dec_ctx_pre = NULL;
- }
- MPP_FREE(ctx->dec_in_buf_post);
- MPP_FREE(ctx->dec_in_buf_pre);
- return ret;
- }
- int main(int argc, char **argv)
- {
- MpiEncTestArgs* enc_cmd = mpi_enc_test_cmd_get();
- MpiRc2TestCtx *ctx = NULL;
- MPP_RET ret = MPP_OK;
- ret = mpi_enc_test_cmd_update_by_args(enc_cmd, argc, argv);
- if (ret)
- goto DONE;
- mpi_enc_test_cmd_show_opt(enc_cmd);
- ctx = mpp_calloc(MpiRc2TestCtx, 1);
- if (NULL == ctx) {
- ret = MPP_ERR_MALLOC;
- goto DONE;
- }
- ctx->enc_cmd = enc_cmd;
- ret = mpi_rc_init(ctx);
- if (ret) {
- mpp_err("mpi_rc_init failded ret %d", ret);
- goto DONE;
- }
- ret = mpi_rc_codec(ctx);
- if (ret)
- mpp_err("mpi_rc_codec failded ret %d", ret);
- DONE:
- if (ctx) {
- mpi_rc_deinit(ctx);
- ctx = NULL;
- }
- mpi_enc_test_cmd_put(enc_cmd);
- return (int)ret;
- }
|