#include "bjunion_enc/vpcodec_1_0.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __ANDROID__ #include using namespace android; #endif extern "C"{ #include "test_dma_api.h" } #include "enc_define.h" #define COMBINE_STR " = " #define MAX_ENCODER_INSTANCE 3 typedef struct { int instance_index; char src_file[256]; char dst_file[256]; int width; int height; int gop; int framerate; int bitrate; int num; int fmt; int buf_type; int num_planes; int fix_qp; int i_qp_min; int i_qp_max; int p_qp_min; int p_qp_max; }config_param_t; bool get_valid_int_param(char *linestr,const char *var_str,int *param) { char *valid_str = NULL; char sub_str[256] = {0}; if (NULL == var_str || NULL == linestr || NULL == param) { //printf("%s return",var_str); return false; } sprintf(sub_str,"%s%s",var_str,COMBINE_STR); valid_str = strstr(linestr,sub_str); if (NULL == valid_str) { //printf("sub_str:%s return\n",sub_str); return false; } valid_str += strlen(sub_str); //printf("sub_str:%s,valid_str:%s",sub_str,valid_str); if (valid_str) { *param = atoi(valid_str); //printf("%s%d\n",sub_str,*param); return true; } return false; } int get_end_str_len(char *linestr) { if (strstr(linestr,"\r\n")) return 2; else if (strstr(linestr,"\r")) return 1; else if (strstr(linestr,"\n")) return 1; return 0; } bool get_valid_str_param(char *linestr,const char *var_str,char *param) { char *valid_str = NULL; char sub_str[256] = {0}; char end_str_len = 0; if (NULL == var_str || NULL == linestr || NULL == param) { //printf("var_str return",var_str); return false; } end_str_len = get_end_str_len(linestr); sprintf(sub_str,"%s%s",var_str,COMBINE_STR); valid_str = strstr(linestr,sub_str); if (NULL == valid_str) { //printf("sub_str:%s return\n",sub_str); return false; } valid_str += strlen(sub_str); //printf("sub_str:%s,valid_str:%s",sub_str,valid_str); if (valid_str) { strncpy(param,valid_str,strlen(valid_str) - end_str_len); //except '\r\n' //printf("%s%s",sub_str,param); return true; } return false; } bool parse_config_file(const char *cfg_file,config_param_t *param) { FILE *fp = NULL; char lineStr[256] = {0}; char *valid_str = NULL; printf("parse config file:%s\n",cfg_file); fp = fopen(cfg_file, "rb"); if (fp == NULL) { printf("open cfg file error!\n"); return false; } while (!feof(fp)) { if (fgets(lineStr, sizeof(lineStr), fp) == NULL ) { continue; } //printf("linestr:%s",lineStr); if (lineStr[0] == '#') continue; if (get_valid_str_param(lineStr,"src_file",param->src_file)) continue; if (get_valid_str_param(lineStr,"dst_file",param->dst_file)) continue; if (get_valid_int_param(lineStr,"width",¶m->width)) continue; if (get_valid_int_param(lineStr,"height",¶m->height)) continue; if (get_valid_int_param(lineStr,"gop",¶m->gop)) continue; if (get_valid_int_param(lineStr,"framerate",¶m->framerate)) continue; if (get_valid_int_param(lineStr,"bitrate",¶m->bitrate)) continue; if (get_valid_int_param(lineStr,"num",¶m->num)) continue; if (get_valid_int_param(lineStr,"fmt",¶m->fmt)) continue; if (get_valid_int_param(lineStr,"buf_type",¶m->buf_type)) continue; if (get_valid_int_param(lineStr,"num_planes",¶m->num_planes)) continue; if (get_valid_int_param(lineStr,"fix_qp",¶m->fix_qp)) continue; if (get_valid_int_param(lineStr,"i_qp_min",¶m->i_qp_min)) continue; if (get_valid_int_param(lineStr,"i_qp_max",¶m->i_qp_max)) continue; if (get_valid_int_param(lineStr,"p_qp_min",¶m->p_qp_min)) continue; if (get_valid_int_param(lineStr,"p_qp_max",¶m->p_qp_max)) continue; } if (fp) { fclose(fp); fp = NULL; } return true; } bool parse_config_param(const char *argv[],int argc,config_param_t *param) { if (NULL == argv || NULL == param || argc < 9) return false; memcpy(param->src_file,argv[1],strlen(argv[1])); memcpy(param->dst_file,argv[2],strlen(argv[2])); param->width = atoi(argv[3]); param->height = atoi(argv[4]); param->gop = atoi(argv[5]); param->framerate = atoi(argv[6]); param->bitrate = atoi(argv[7]); param->num = atoi(argv[8]); param->fmt = atoi(argv[9]); param->buf_type = atoi(argv[10]); param->num_planes = atoi(argv[11]); if (argc == 13) { param->fix_qp = atoi(argv[12]); } if (argc == 17) { param->i_qp_min = atoi(argv[13]); param->i_qp_max = atoi(argv[14]); param->p_qp_min = atoi(argv[15]); param->p_qp_max = atoi(argv[16]); } return true; } bool check_params(config_param_t *pconfig_param) { if (NULL == pconfig_param) return false; if ((pconfig_param->width < 1) || (pconfig_param->width > 1920)) { printf("instance:%d,invalid width \n",pconfig_param->instance_index); return false;//-1; } if ((pconfig_param->height < 1) || (pconfig_param->height > 1080)) { printf("instance:%d,invalid height \n",pconfig_param->instance_index); return false;// -1; } if ((pconfig_param->framerate < 0) || (pconfig_param->framerate > 30)) { printf("instance:%d,invalid framerate %d \n",pconfig_param->instance_index,pconfig_param->framerate); return false;// -1; } if (pconfig_param->bitrate <= 0) { printf("instance:%d,invalid bitrate \n",pconfig_param->instance_index); return false;// -1; } if (pconfig_param->num < 0) { printf("instance:%d,invalid num \n",pconfig_param->instance_index); return false;// -1; } printf("*******instance %d param list*****\n",pconfig_param->instance_index); printf("src_url is: %s ;\n", pconfig_param->src_file); printf("out_url is: %s ;\n", pconfig_param->dst_file); printf("width is: %d ;\n", pconfig_param->width); printf("height is: %d ;\n", pconfig_param->height); printf("gop is: %d ;\n", pconfig_param->gop); printf("frmrate is: %d ;\n", pconfig_param->framerate); printf("bitrate is: %d ;\n", pconfig_param->bitrate); printf("frm_num is: %d ;\n", pconfig_param->num); printf("buf_type is: %d ;\n", pconfig_param->buf_type); printf("num_planes is: %d ;\n", pconfig_param->num_planes); printf("fix_qp is: %d ;\n", pconfig_param->fix_qp); printf("i frame qp min:%d\n",pconfig_param->i_qp_min); printf("i frame qp max:%d\n",pconfig_param->i_qp_max); printf("p frame qp min:%d\n",pconfig_param->p_qp_min); printf("p frame qp max:%d\n",pconfig_param->p_qp_max); return true; } static void *encode_thread(void *param) { int outfd = -1; FILE *fp = NULL; int datalen = 0; unsigned ysize; unsigned usize; unsigned vsize; unsigned uvsize; unsigned char *vaddr = NULL; vl_dma_info_t dma_info; struct usr_ctx_s ctx; vl_codec_handle_t handle_enc = 0; config_param_t *pconfig_param = (config_param_t *)param; int64_t total_encode_time=0, t1,t2; int num_actually_encoded=0; int ret = -1; vl_init_params_t init_param; vl_frame_info_t frame_info; vl_frame_type_t frame_type = FRAME_TYPE_NONE; vl_enc_result_e result = ENC_FAILED; pthread_detach(pthread_self()); unsigned framesize = pconfig_param->width * pconfig_param->height * 3 / 2; ysize = pconfig_param->width * pconfig_param->height; usize = pconfig_param->width * pconfig_param->height / 4; vsize = pconfig_param->width * pconfig_param->height / 4; uvsize = pconfig_param->width * pconfig_param->height / 2; if (pconfig_param->fmt == IMG_FMT_RGB888 || pconfig_param->fmt == IMG_FMT_BGR888) { /* modify for yuv size calc */ framesize = pconfig_param->width * pconfig_param->height * 3; } unsigned int output_size = 1024 * 1024 * sizeof(char); unsigned char *output_buffer = (unsigned char *)malloc(output_size); unsigned char *input_buffer = NULL; unsigned char *input[3] = { NULL }; memset(&init_param, 0, sizeof(init_param)); memset(&frame_info, 0, sizeof(frame_info)); if (pconfig_param->buf_type == DMA_BUFF) { memset(&dma_info, 0, sizeof(dma_info)); dma_info.num_planes = pconfig_param->num_planes; dma_info.shared_fd[0] = -1; // dma buf fd dma_info.shared_fd[1] = -1; dma_info.shared_fd[2] = -1; ret = create_ctx(&ctx); if (ret < 0) { printf("gdc create fail ret=%d\n", ret); goto exit; } if (dma_info.num_planes == 3) { if (pconfig_param->fmt != IMG_FMT_YV12) { printf("error fmt %d\n", pconfig_param->fmt); goto exit; } ret = alloc_dma_buffer(&ctx, INPUT_BUFF_TYPE, ysize); if (ret < 0) { printf("alloc fail ret=%d, len=%u\n", ret, ysize); goto exit; } vaddr = (unsigned char *) ctx.i_buff[0]; if (!vaddr) { printf("mmap failed,Not enough memory\n"); goto exit; } dma_info.shared_fd[0] = ret; input[0] = vaddr; ret = alloc_dma_buffer(&ctx, INPUT_BUFF_TYPE, usize); if (ret < 0) { printf("alloc fail ret=%d, len=%u\n", ret, usize); goto exit; } vaddr = (unsigned char *) ctx.i_buff[1]; if (!vaddr) { printf("mmap failed,Not enough memory\n"); goto exit; } dma_info.shared_fd[1] = ret; input[1] = vaddr; ret = alloc_dma_buffer(&ctx, INPUT_BUFF_TYPE, vsize); if (ret < 0) { printf("alloc fail ret=%d, len=%u\n", ret, vsize); goto exit; } vaddr = (unsigned char *) ctx.i_buff[2]; if (!vaddr) { printf("mmap failed,Not enough memory\n"); goto exit; } dma_info.shared_fd[2] = ret; input[2] = vaddr; } else if (dma_info.num_planes == 2) { ret = alloc_dma_buffer(&ctx, INPUT_BUFF_TYPE, ysize); if (ret < 0) { printf("alloc fail ret=%d, len=%u\n", ret, ysize); goto exit; } vaddr = (unsigned char *) ctx.i_buff[0]; if (!vaddr) { printf("mmap failed,Not enough memory\n"); goto exit; } dma_info.shared_fd[0] = ret; input[0] = vaddr; if (pconfig_param->fmt != IMG_FMT_NV12 && pconfig_param->fmt != IMG_FMT_NV21) { printf("error fmt %d\n", pconfig_param->fmt); goto exit; } ret = alloc_dma_buffer(&ctx, INPUT_BUFF_TYPE, uvsize); if (ret < 0) { printf("alloc fail ret=%d, len=%u\n", ret, uvsize); goto exit; } vaddr = (unsigned char *) ctx.i_buff[1]; if (!vaddr) { printf("mmap failed,Not enough memory\n"); goto exit; } dma_info.shared_fd[1] = ret; input[1] = vaddr; } else if (dma_info.num_planes == 1) { ret = alloc_dma_buffer(&ctx, INPUT_BUFF_TYPE, framesize); if (ret < 0) { printf("alloc fail ret=%d, len=%u\n", ret, framesize); goto exit; } vaddr = (unsigned char *) ctx.i_buff[0]; if (!vaddr) { printf("mmap failed,Not enough memory\n"); goto exit; } dma_info.shared_fd[0] = ret; input[0] = vaddr; } printf("in[0] %d, in[1] %d, in[2] %d\n", dma_info.shared_fd[0], dma_info.shared_fd[1], dma_info.shared_fd[2]); printf("input[0] %p, input[1] %p,input[2] %p\n", input[0], input[1], input[2]); frame_info.plane_num = dma_info.num_planes; frame_info.YCbCr[0] = dma_info.shared_fd[0]; frame_info.YCbCr[1] = dma_info.shared_fd[1]; frame_info.YCbCr[2] = dma_info.shared_fd[2]; } else { input_buffer = (unsigned char *) malloc(framesize); if (input_buffer == NULL) { printf("Can not allocat inputBuffer\n"); goto exit; } frame_info.YCbCr[0] = (ulong) (input_buffer); frame_info.YCbCr[1] = (ulong) (input_buffer + ysize); frame_info.YCbCr[2] = (ulong) (input_buffer + ysize + usize); } fp = fopen(pconfig_param->src_file, "rb"); if (fp == NULL) { printf("open src file error!\n"); goto exit; } outfd = open(pconfig_param->dst_file, O_CREAT | O_RDWR | O_TRUNC, 0644); if (outfd < 0) { printf("open dist file error!\n"); goto exit; } init_param.width = pconfig_param->width; init_param.height = pconfig_param->height; init_param.frame_rate = pconfig_param->framerate; init_param.bit_rate = pconfig_param->bitrate; init_param.gop = pconfig_param->gop; init_param.i_qp_min = pconfig_param->i_qp_min; init_param.i_qp_max = pconfig_param->i_qp_max; init_param.p_qp_min = pconfig_param->p_qp_min; init_param.p_qp_max = pconfig_param->p_qp_max; frame_info.type = (vl_buffer_type_e)pconfig_param->buf_type; frame_info.frame_type = FRAME_TYPE_AUTO; frame_info.frame_size = framesize; frame_info.fmt = (vl_img_format_t)pconfig_param->fmt; frame_info.pitch = pconfig_param->width; frame_info.height = pconfig_param->height; //frame_info.coding_timestamp = 0; //frame_info.canvas = 0; //frame_info.scale_width = 0; //frame_info.scale_height = 0; //frame_info.crop_left = 0; //frame_info.crop_right = 0; //frame_info.crop_top = 0; //frame_info.crop_bottom = 0; frame_info.bitrate = pconfig_param->bitrate; frame_info.frame_rate = pconfig_param->framerate * 1000; handle_enc = vl_video_encoder_init(CODEC_ID_H264, init_param); while (pconfig_param->num > 0) { if (pconfig_param->buf_type == DMA_BUFF) { // read data to dma buf vaddr if (dma_info.num_planes == 1) { if (fread(input[0], 1, framesize, fp) != framesize) { printf("read input file error!\n"); goto exit; } } else if (dma_info.num_planes == 2) { if (fread(input[0], 1, ysize, fp) != ysize) { printf("read input file error!\n"); goto exit; } if (fread(input[1], 1, uvsize, fp) != uvsize) { printf("read input file error!\n"); goto exit; } } else if (dma_info.num_planes == 3) { if (fread(input[0], 1, ysize, fp) != ysize) { printf("read input file error!\n"); goto exit; } if (fread(input[1], 1, usize, fp) != usize) { printf("read input file error!\n"); goto exit; } if (fread(input[2], 1, vsize, fp) != vsize) { printf("read input file error!\n"); goto exit; } } } else { // read data to vmalloc buf vaddr if (fread(input_buffer, 1, framesize, fp) != framesize) { printf("read input file error!\n"); goto exit; } } memset(output_buffer, 0, output_size); #ifdef __ANDROID__ t1=ALooper::GetNowUs(); #endif result = vl_video_encoder_encode_frame(handle_enc, frame_info, output_buffer, &datalen, &frame_type); #ifdef __ANDROID__ t2=ALooper::GetNowUs(); total_encode_time+=t2-t1; #endif if (result != ENC_FAILED) { num_actually_encoded++; write(outfd, (unsigned char *)output_buffer, datalen); } pconfig_param->num--; } vl_video_encoder_destroy(handle_enc); #ifdef __ANDROID__ printf("instance:%d,total_encode_time: %lld, num_actually_encoded: %d, fps=%3.3f\n", pconfig_param->instance_index,total_encode_time, num_actually_encoded, num_actually_encoded*1.0*1000000/total_encode_time); #endif exit: if (pconfig_param->buf_type == DMA_BUFF) { if (dma_info.shared_fd[0] >= 0) close(dma_info.shared_fd[0]); if (dma_info.shared_fd[1] >= 0) close(dma_info.shared_fd[1]); if (dma_info.shared_fd[2] >= 0) close(dma_info.shared_fd[2]); destroy_ctx(&ctx); } else { if (input_buffer) free(input_buffer); } if (output_buffer) free(output_buffer); if (outfd >= 0) close(outfd); if (fp) fclose(fp); return NULL; } void print_help() { printf("Amlogic AVC Encode API \n"); printf("single instance can run like this below:\n"); printf(" usage: output [instancenum][usecfgfile][srcfile][outfile][width][height][gop][framerate][bitrate][num][fmt][buf_type][num_planes][const_qp][i_qp_in][i_qp_max][p_qp_min][p_qp_max]\n"); printf("multi instance can run like this below \n"); printf(" usage: output [instancenum][usecfgfile][cfgfile1][cfgfile2][cfgfile3]...[cfgfile_instancenum]\n"); printf(" options :\n"); printf(" instance num : the count of encoder instances,max is 3,multi instance must use cfg file option\n"); printf(" usecfgfile : 0:not use cfgfile 1:use cfgfile\n"); printf(" ******************plese set filesrc when cfgfile = 1********************\n"); printf(" srcfile1 : cfg file url1 in your root fs when multi instance\n"); printf(" srcfile2 : cfg file url2 in your root fs when multi instance\n"); printf(" srcfile3 : cfg file url3 in your root fs when multi instance\n"); printf(" ...\n"); printf(" ******************plese set params when cfgfile = 0********************\n"); printf(" srcfile : yuv data url in your root fs\n"); printf(" outfile : stream url in your root fs\n"); printf(" width : width\n"); printf(" height : height\n"); printf(" gop : I frame refresh interval\n"); printf(" framerate: framerate \n "); printf(" bitrate : bit rate \n "); printf(" num : encode frame count \n "); printf(" fmt : encode input fmt 1:nv12 2:nv21 3:yv12 4:rgb888 5:bgr888\n "); printf(" buf_type : 0:vmalloc, 3:dma buffer\n"); printf(" num_planes : used for dma buffer case. 2 : nv12/nv21, 3 : yuv420p(yv12/yu12)\n"); printf(" const_qp : optional, [0-51]\n "); printf(" i_qp_min : i frame qp min\n "); printf(" i_qp_max : i frame qp max\n "); printf(" p_qp_min : p frame qp min\n "); printf(" p_qp_max : p frame qp max\n "); } int main(int argc, const char *argv[]) { config_param_t config_param[MAX_ENCODER_INSTANCE] = {0}; bool use_cfg_file = false; unsigned char inst_num = 0; pthread_t tid[MAX_ENCODER_INSTANCE]; int iloop = 0; if (argc < 2) { print_help(); return -1; } inst_num = atoi(argv[1]); use_cfg_file = atoi(argv[2]); if (inst_num <= 0 || inst_num > MAX_ENCODER_INSTANCE) { printf("invalid instance num!\n"); return -1; } if (use_cfg_file == 0 && argc < 9) //1 instance,use param { print_help(); return -1; } else { printf("instance num:%s\n", argv[1]); printf("use_cfg_file:%s\n", argv[2]); } if (inst_num > 1 && (!use_cfg_file)) { printf("please use config file when test multi param\n"); return -1; } if (use_cfg_file && argc < (inst_num + 2)) { printf("please enter right number of param!\n"); return -1; } if (1 == inst_num && 0 == use_cfg_file) { parse_config_param(&argv[2],argc-2,&config_param[0]); check_params(&config_param[0]); } else { for (iloop = 0;iloop < inst_num;iloop++) { config_param[iloop].instance_index = iloop; parse_config_file(argv[iloop + 2 + 1], &config_param[iloop]); check_params(&config_param[iloop]); } } for (iloop = 0;iloop < inst_num;iloop++) { pthread_create(&tid[iloop], NULL, encode_thread, &config_param[iloop]); } for (iloop = 0;iloop < inst_num;iloop++) { pthread_join(tid[iloop], NULL); } return 0; }