mirror of
				https://github.com/nyanmisaka/mpp.git
				synced 2025-10-31 12:36:44 +08:00 
			
		
		
		
	 2b35cee0ce
			
		
	
	2b35cee0ce
	
	
	
		
			
			1. Move mpp_log.h to inc for external user. 2. Add mpp_debug.h for mpp internal logging. 3. Fix some warning. 4. Add log level setup function. 5. Check env log_level value in mpp_get_log_level call. NOTE: 1. mpp internal module should use mpp_debug.h and mpp external user should use mpp_log.h 2. Use mpp_get_log_level to update mpp_log_level when the env changed. Change-Id: I90a55a02a72db177533013280dfe111ca3479229 Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
		
			
				
	
	
		
			1163 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1163 lines
		
	
	
		
			35 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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;
 | |
|     MppBuffer       enc_pkt_buf;
 | |
|     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);
 | |
| 
 | |
|     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_denorm = 1;
 | |
|     rc_cfg->fps_out_denorm = 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_denorm",  rc_cfg->fps_in_denorm);
 | |
|     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_denorm", rc_cfg->fps_out_denorm);
 | |
|     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);
 | |
| 
 | |
|                     /* 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;
 | |
|     }
 | |
| 
 | |
|     ret = mpp_buffer_get(ctx->pkt_grp, &ctx->enc_pkt_buf, packet_size);
 | |
|     if (ret) {
 | |
|         mpp_err("failed to get buffer for input frame 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->enc_pkt_buf) {
 | |
|         mpp_buffer_put(ctx->enc_pkt_buf);
 | |
|         ctx->enc_pkt_buf = NULL;
 | |
|     }
 | |
| 
 | |
|     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->enc_pkt_buf) {
 | |
|         mpp_buffer_put(ctx->enc_pkt_buf);
 | |
|         ctx->enc_pkt_buf = 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;
 | |
| }
 |