#include "hevc_enc/vp_hevc_codec_1_0.h" #include #include #include #include #include #include #include #include #include #include #include #include #include extern "C"{ #include "test_dma_api.h" } #define ENCODER_STRING_LEN_MAX 256 #define CFG_ENCODE_NUM_MAX 6 #define FORCE_PICTURE_TYPE 0x1 #define CHANGE_TARGET_RATE 0x2 #define CHANGE_MIN_MAX_QP 0x4 #define CHANGE_GOP_PERIOD 0x8 #define LONGTERM_REF_SET 0x10 #define CUST_SIZE_SMOOTH 0x20 #define CUST_APP_H264_PLUS 0x40 #define CHANGE_MULTI_SLICE 0x80 #define FORCE_PICTURE_SKIP 0x100 #define CHANGE_STRICT_RC 0x200 #define ENCODER_STRING_LEN_MAX 256 typedef struct { int FrameNum; //change frame number int enable_option; //FORCE_PICTURE_TYPE int picType; //vl_frame_type_t //CHANGE_TARGET_RATE int bitRate; //CHANGE_MIN_MAX_QP int minQpI; int maxQpI; int maxDeltaQp; int minQpP; int maxQpP; int minQpB; int maxQpB; //CHANGE_GOP_PERIOD int intraQP; int GOPPeriod; //LONGTERM_REF_SET int LTRFlags; //bit 0: UseCurSrcAsLongtermPic; bit 1: Use LTR frame // CUST_SIZE_SMOOTH int smooth_level; //0 normal, 50(middle), 100 (high) // CUST_APP_H264_PLUS int newIDRInterval; // shall be multiply of gop length int QPdelta_IDR; // QP delta apply to IDRs int QPdelta_LTR; // QP delta apply to LTR P frames // Change multi-slice int Slice_Mode; //multi slice mode int Slice_Para; //para // Change strict bitrate control int bitrate_window; //bitrate cal window int pskip_threshold; //threshold for pskip } CfgChangeParam; typedef struct { int seqNum; char srcfile[ENCODER_STRING_LEN_MAX]; // yuv data url in your root fs char outfile[ENCODER_STRING_LEN_MAX]; // stream url in your root fs int width; // width int height; // height int gop; // I frame refresh interval int framerate; // framerate int bitrate; // bit rate int num; // encode frame count int fmt; // encode input fmt 1:nv12, 2:nv21, 3:420p int buf_type; // 0:vmalloc, 3:dma buffer int num_planes; // used for dma buffer case. 2 : nv12/nv21, 3 : yuv420p(yv12/yu12) int cfg_opt; /* optional, flags to control the encode feature settings bit 0:roi control. 0: disabled (default) 1: enabled bit 1: update control. 0: disabled (default) 1: enabled bit 2 ~ bit 6 encode GOP pattern options: 0 default(IP) 1:I only 2:IP_only 3: IBBBP 4:IP_SVC1 5:IP_SVC2 6: IP_SVC3 7: IP_SVC4 8: CUSTP bit 7:long term references. 0: disabled (default) 1: enabled bit 8:cust source buffer stride . 0: disabled (default) 1: enabled bit 9: convert normal source file stride to cust source stride. 0: disabled (default) 1: enabled bit 10:enable intraRefresh. 0: disabled (default) 1: enabled bit 11 ~ bit 13: profile 0: auto (default) others as following 1: BASELINE(AVC) MAIN (HEVC); 2 MAIN (AVC) main10 (HEVC) 3: HIGH (AVC) STILLPICTURE (HEVC); 4 HIGH10 (AVC) bit 14 ~ bit 15: frame rotation(counter-clockwise, in degree): 0:none, 1:90, 2:180, 3:270 bit 16 ~ bit 17: frame mirroring: 0:none, 1:vertical, 2:horizontal, 3:both V and H bit 18: enable customer bitstream buffer size bit 19 ~ bit 20: enable multi slice mode: 0, one slice(no para), 1 by MB(16x16)/CTU(64x64), 2 by CTU + size(byte) bit 21 cust_qp_delta_en bit 22 strict_rate_ctrl_en (skipP allowed to limit bitrate) default 0 bit 23 forcePicQpEnable default 0 */ char roifile[ENCODER_STRING_LEN_MAX]; // optional, roi info url in root fs, no present if roi is disabled char cfg_file[ENCODER_STRING_LEN_MAX]; // optional, cfg update info url. no present if update is disabled int src_buf_stride; // optional, source buffer stride int intraRefresh ; // optional, lower 4 bits for intra-refresh mode; others for refresh parameter, controlled by intraRefresh bit int bitStreamBuf ; // optional, encoded bitstream buffer size in MB int MultiSlice_parameter; // optional, multi slice parameter in MB/CTU or CTU and size (HIGH_16bits size + LOW_16bit CTU) combined int cust_qp_delta; // optional, cust_qp_delta apply to P frames value >0 lower; <0 increase the quality int strict_rate_control_parmeter; // optional, High 16 bit bitrate window (frames max 120). low 16 bit bitrate threshold (percent) int forcePicQpIPB; } encodecCfgParam; static int ParseCfgUpdateFile(FILE *fp, CfgChangeParam *cfg_update); static int ParseEncodeCfgFile(FILE *fp, encodecCfgParam *cfg_encode); static void *encode_thread(void *param); int main(int argc, const char *argv[]){ int i = 0; int len = 0; int arg_count = 0; FILE *fp_cfg_encode = NULL; encodecCfgParam cfg_encode[CFG_ENCODE_NUM_MAX]; if ((argc != 2) && (argc < 12)) { printf("Amlogic AVC Encode API \n"); printf(" usage: output [srcfile][outfile][width][height][gop][framerate][bitrate][num][fmt][buf_type][num_planes]\n"); printf(" options :\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:420p\n "); printf(" buf_type \t: 0:vmalloc, 3:dma buffer\n"); printf(" num_planes \t: used for dma buffer case. 1 package, 2 : nv12/nv21, 3 : yuv420p\n"); printf(" cfg_opt \t: optional, flags to control the encode feature settings\n"); printf(" \t\t bit 0:roi control. 0: disabled (default) 1: enabled\n"); printf(" \t\t bit 1: update control. 0: disabled (default) 1: enabled\n"); printf(" \t\t bit 2 ~ bit 6 encode GOP pattern options:\n"); printf(" \t\t\t 0 default(IP) 1:I only 2:IP_only 3: IBBBP\n"); printf(" \t\t\t 4:IP_SVC1 5:IP_SVC2 6: IP_SVC3 7: IP_SVC4 8: CUSTP \n"); printf(" \t\t bit 7:long term references. 0: disabled (default) 1: enabled\n"); printf(" \t\t bit 8:cust source buffer stride . 0: disabled (default) 1: enabled\n"); printf(" \t\t bit 9: convert normal source file stride to cust source stride. 0: disabled (default) 1: enabled\n"); printf(" \t\t bit 10:enable intraRefresh. 0: disabled (default) 1: enabled\n"); printf(" \t\t bit 11 ~ bit 13: profile 0: auto (default) others as following\n"); printf(" \t\t 1: BASELINE(AVC) MAIN (HEVC); 2 MAIN (AVC) main10 (HEVC) \n"); printf(" \t\t 3: HIGH (AVC) STILLPICTURE (HEVC); 4 HIGH10 (AVC) \n"); printf(" \t\t bit 14 ~ bit 15: frame rotation(counter-clockwise, in degree): 0:none, 1:90, 2:180, 3:270\n"); printf(" \t\t bit 16 ~ bit 17: frame mirroring: 0:none, 1:vertical, 2:horizontal, 3:both V and H\n"); printf(" \t\t bit 18: enable customer bitstream buffer size\n"); printf(" \t\t bit 19 ~ bit 20: enable multi slice mode: 0, one slice(no para), 1 by MB(16x16)/CTU(64x64), 2 by CTU + size(byte)\n"); printf(" \t\t bit 21 cust_qp_delta_en \n"); printf(" \t\t bit 22 strict_rate_ctrl_en (skipP allowed to limit bitrate) default 0 \n"); printf(" \t\t bit 23 forcePicQpEnable default 0 \n"); printf(" cfg_file \t: optional, cfg update info url. no present if update is disabled\n"); printf("or\n"); printf(" usage: aml_enc_test " "[encode_cfg_file]\n"); printf(" options \t:\n"); printf(" encode_cfg_file \t: encode cfg file info url\n"); return -1; } else if (argc == 2) { printf("argv[1]:%s\n", argv[1]); fp_cfg_encode = fopen((argv[1]), "r"); if (fp_cfg_encode == NULL) { printf("open encode cfg file error!\n"); return 0; } memset(cfg_encode, 0, CFG_ENCODE_NUM_MAX * sizeof(encodecCfgParam)); ParseEncodeCfgFile(fp_cfg_encode, cfg_encode); fclose(fp_cfg_encode); if (cfg_encode[0].seqNum == 0) return 0; } else { memset(&cfg_encode[0], 0, sizeof(encodecCfgParam)); len = strlen(argv[1]) > ENCODER_STRING_LEN_MAX ? ENCODER_STRING_LEN_MAX : strlen(argv[1]); strncpy(cfg_encode[0].srcfile, argv[1], len); len = strlen(argv[2]) > ENCODER_STRING_LEN_MAX ? ENCODER_STRING_LEN_MAX : strlen(argv[2]); strncpy(cfg_encode[0].outfile, argv[2], len); cfg_encode[0].width = atoi(argv[3]); cfg_encode[0].height = atoi(argv[4]); cfg_encode[0].gop = atoi(argv[5]); cfg_encode[0].framerate = atoi(argv[6]); cfg_encode[0].bitrate = atoi(argv[7]); cfg_encode[0].num = atoi(argv[8]); cfg_encode[0].fmt = atoi(argv[9]); cfg_encode[0].buf_type = atoi(argv[10]); cfg_encode[0].num_planes = atoi(argv[11]); if (argc > 12) { cfg_encode[0].cfg_opt = atoi(argv[12]); } if (argc > 13) { arg_count = 13; if ((cfg_encode[0].cfg_opt & 0x2) == 0x2 && argc > arg_count) { len = strlen(argv[arg_count]) > ENCODER_STRING_LEN_MAX ? ENCODER_STRING_LEN_MAX : strlen(argv[arg_count]); strncpy(cfg_encode[0].cfg_file, argv[arg_count], len); printf("cfg_upd_url is\t: %s ;\n", cfg_encode[0].cfg_file); arg_count ++; } if (arg_count != argc) { printf("config no match conf %d argc %d\n", cfg_encode[0].cfg_opt, argc); return -1; } } cfg_encode[0].seqNum = 1; } pthread_t tid[CFG_ENCODE_NUM_MAX]; for (i = 0; i < cfg_encode[0].seqNum; i ++) { if (i >= CFG_ENCODE_NUM_MAX) break; pthread_create(&tid[i], NULL, encode_thread, &cfg_encode[i]); } for (i = 0; i < cfg_encode[0].seqNum; i ++) { if (i >= CFG_ENCODE_NUM_MAX) break; pthread_join(tid[i], NULL); } return 0; } static void *encode_thread(void *param) { int ret = 0; int width, height, gop, framerate, bitrate, num; int outfd = -1; FILE *fp = NULL; FILE *fp_cfg = NULL; // int datalen = 0; vl_img_format_hevc_t fmt = IMG_FMT_NONE; int buf_type = 0; int num_planes = 1; int src_buf_stride = 0; int bitstream_buf_size = 0; struct usr_ctx_s ctx; int cfg_upd_enabled = 0, has_cfg_update = 0; CfgChangeParam cfgChange; vl_frame_type_hevc_t enc_frame_type; int cfg_option = 0; int frame_num = 0; int qp_mode = 0; qp_param_hevc_t qp_tbl; unsigned char *vaddr = NULL; vl_codec_handle_hevc_t handle_enc; vl_encode_info_hevc_t encode_info; encoding_metadata_hevc_t encoding_metadata; encodecCfgParam *cfg_encode = NULL; unsigned int framesize = 0; unsigned int ysize = 0; unsigned int usize = 0; unsigned int vsize = 0; unsigned int uvsize = 0; unsigned int outputBufferLen = 0; unsigned char *inputBuffer = NULL; unsigned char *outputBuffer = NULL; vl_buffer_info_hevc_t inbuf_info; vl_dma_info_hevc_t *dma_info = NULL; unsigned char *input[3] = { NULL }; pthread_detach(pthread_self()); if (NULL != param) cfg_encode = (encodecCfgParam *)param; else { goto end; } width = cfg_encode->width; if ((width < 1) || (width > 3840/*1920*/)) { printf("invalid width \n"); goto end; } height = cfg_encode->height; if ((height < 1) || (height > 2160/*1080*/)) { printf("invalid height \n"); goto end; } gop = cfg_encode->gop; framerate = cfg_encode->framerate; bitrate = cfg_encode->bitrate; num = cfg_encode->num; fmt = (vl_img_format_hevc_t)cfg_encode->fmt; buf_type = cfg_encode->buf_type; num_planes = cfg_encode->num_planes; if ((framerate < 0) || (framerate > 60)) { printf("invalid framerate \n"); goto end; } if (bitrate <= 0) { printf("invalid bitrate \n"); goto end; } if (num < 0) { printf("invalid num \n"); goto end; } if (buf_type == 3 && (num_planes < 1 || num_planes > 3)) { printf("invalid num_planes \n"); goto end; } printf("src_url is: %s ;\n", cfg_encode->srcfile); printf("out_url is: %s ;\n", cfg_encode->outfile); printf("width is: %d ;\n", width); printf("height is: %d ;\n", height); printf("gop is: %d ;\n", gop); printf("frmrate is: %d ;\n", framerate); printf("bitrate is: %d ;\n", bitrate); printf("frm_num is: %d ;\n", num); printf("fmt is\t: %d ;\n", fmt); printf("buf_type is\t: %d ;\n", buf_type); printf("num_planes is\t: %d ;\n", num_planes); if (cfg_encode->cfg_opt > 0) { cfg_option = cfg_encode->cfg_opt; if ((cfg_option & 0x2) == 0x2 && (strlen(cfg_encode->cfg_file) > 1)) { printf("cfg_upd_url is\t: %s ;\n", cfg_encode->cfg_file); cfg_upd_enabled = 1; } } outputBufferLen = 1024 * 1024 * sizeof(char); if (bitstream_buf_size > 8) outputBufferLen = bitstream_buf_size*1024 * 1024 * sizeof(char); outputBuffer = (unsigned char *)malloc(outputBufferLen); if (src_buf_stride) { framesize = src_buf_stride * height * 3 / 2; ysize = src_buf_stride * height; usize = src_buf_stride * height / 4; vsize = src_buf_stride * height / 4; uvsize = src_buf_stride * height / 2; } else { framesize = width * height * 3 / 2; ysize = width * height; usize = width * height / 4; vsize = width * height / 4; uvsize = width * height / 2; } memset(&inbuf_info, 0, sizeof(vl_buffer_info_hevc_t)); inbuf_info.buf_type = (vl_buffer_type_hevc_t) buf_type; inbuf_info.buf_stride = src_buf_stride; inbuf_info.buf_fmt = fmt; memset(&qp_tbl, 0, sizeof(qp_param_hevc_t)); qp_tbl.qp_min = 0; qp_tbl.qp_max = 51; qp_tbl.qp_base = 30; memset(&encode_info, 0, sizeof(vl_encode_info_hevc_t)); encode_info.width = width; encode_info.height = height; encode_info.bit_rate = bitrate; encode_info.frame_rate = framerate; encode_info.gop = gop; encode_info.img_format = fmt; encode_info.qp_mode = qp_mode; encode_info.prepend_spspps_to_idr_frames = false; if (cfg_upd_enabled) { encode_info.enc_feature_opts |= ENABLE_PARA_UPDATE; memset(&cfgChange, 0, sizeof(CfgChangeParam)); } if (inbuf_info.buf_type == DMA_TYPE) { dma_info = &(inbuf_info.buf_info.dma_info); dma_info->num_planes = 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 (fmt != IMG_FMT_YUV420P) { printf("error fmt %d\n", 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; } printf("hoan debug canvas >> alloc_dma_buffer y,ret=%d, vaddr=0x%p\n", ret,vaddr); 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; printf("hoan debug canvas >> alloc_dma_buffer v,ret=%d, vaddr=0x%p\n", ret,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 (fmt != IMG_FMT_NV12 && fmt != IMG_FMT_NV21) { printf("error fmt %d\n", 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]); } else { inputBuffer = (unsigned char *) malloc(framesize); if (inputBuffer == NULL) { printf("Can not allocat inputBuffer\n"); goto exit; } inbuf_info.buf_info.in_ptr[0] = (ulong) (inputBuffer); inbuf_info.buf_info.in_ptr[1] = (ulong) (inputBuffer + ysize); inbuf_info.buf_info.in_ptr[2] = (ulong) (inputBuffer + ysize + usize); } fp = fopen((char *)cfg_encode->srcfile, "rb"); if (fp == NULL) { printf("open src file error!\n"); goto exit; } if (cfg_upd_enabled) { fp_cfg = fopen((const char*)cfg_encode->cfg_file, "r"); if (fp_cfg == NULL) { printf("open cfg file error!\n"); goto exit; } has_cfg_update = ParseCfgUpdateFile(fp_cfg, &cfgChange); } outfd = open((char *)cfg_encode->outfile, O_CREAT | O_RDWR | O_TRUNC, 0644); if (outfd < 0) { printf("open dst file error!\n"); goto exit; } handle_enc = vl_video_encoder_init_hevc(CODEC_ID_H265, encode_info, &qp_tbl); while (num > 0) { if (inbuf_info.buf_type == DMA_TYPE) { // 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(inputBuffer, 1, framesize, fp) != framesize) { printf("read input file error!\n"); goto exit; } } if (cfg_upd_enabled && has_cfg_update) { if (cfgChange.FrameNum == frame_num) { // apply updates if (cfgChange.enable_option & FORCE_PICTURE_TYPE) { if (cfgChange.picType == FRAME_TYPE_IDR || cfgChange.picType == FRAME_TYPE_I) { enc_frame_type = FRAME_TYPE_I; printf("force I frame on %d \n", frame_num); } } if (cfgChange.enable_option & CHANGE_TARGET_RATE) { vl_video_encoder_change_bitrate_hevc( handle_enc, cfgChange.bitRate); printf("Change bitrate to %d on %d \n", cfgChange.bitRate, frame_num); } } if (cfgChange.FrameNum <= frame_num) { has_cfg_update = ParseCfgUpdateFile(fp_cfg, &cfgChange); } } memset(outputBuffer, 0, outputBufferLen); if (inbuf_info.buf_type == DMA_TYPE) { sync_cpu(&ctx); } encoding_metadata = vl_video_encoder_encode_hevc(handle_enc, FRAME_TYPE_AUTO, outputBuffer, &inbuf_info); if (encoding_metadata.is_valid) { write(outfd, (unsigned char *) outputBuffer, encoding_metadata.encoded_data_length_in_bytes); } else { printf("encode error %d!\n", encoding_metadata.encoded_data_length_in_bytes); } num--; frame_num++; } exit: if (handle_enc) vl_video_encoder_destroy_hevc(handle_enc); if (outputBuffer) free(outputBuffer); if (outfd >= 0) close(outfd); if (fp) fclose(fp); if (inbuf_info.buf_type == DMA_TYPE) { 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 (inputBuffer) free(inputBuffer); } printf("Encode End!width:%d\n",width); end: pthread_exit(0); return NULL; } static char*mystrncpy(char* dest, const char* src, int len) { assert(dest != NULL && src != NULL); char* temp = dest; int i=0; //while (i++ < len && (*temp++ = *src++) != '\0') {} while (i++ < len && (*temp = *src) != '\n' && (*temp++ = *src++) != '\0') {} if (*(temp) != '\0') *temp = '\0'; return dest; } static int ParseEncodeCfgFile(FILE *fp, encodecCfgParam *cfg_encode) { char* token = NULL; char delim[2] = " "; static char lineStr[ENCODER_STRING_LEN_MAX*4] = {0}; char valueStr[ENCODER_STRING_LEN_MAX] = {0}; int i = 0; int len = 0; while (1) { if (i >= CFG_ENCODE_NUM_MAX) return 0; if (lineStr[0] == 0x0) { //need a new line; if (fgets(lineStr, ENCODER_STRING_LEN_MAX*4, fp) == NULL) { if (feof(fp)) return 0; continue; } } if (strlen(lineStr) == 1) { // skip null lineStr[0] = 0x0; continue; } if ((lineStr[0] == '#') ||(lineStr[0] == ';')||(lineStr[0] == ':')) { // skip comments lineStr[0] = 0x0; continue; } //printf("[%s][%d]:%s\n",__func__,__LINE__,lineStr); // keep the original memcpy(valueStr, lineStr, strlen(lineStr)); //param is separated by ' ' token = strtok(valueStr, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } len = strlen(token) > ENCODER_STRING_LEN_MAX ? ENCODER_STRING_LEN_MAX : strlen(token); mystrncpy(cfg_encode[i].srcfile, token, len); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } len = strlen(token) > ENCODER_STRING_LEN_MAX ? ENCODER_STRING_LEN_MAX : strlen(token); mystrncpy(cfg_encode[i].outfile, token, len); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_encode[i].width = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_encode[i].height = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_encode[i].gop = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_encode[i].framerate = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_encode[i].bitrate = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_encode[i].num = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_encode[i].fmt = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_encode[i].buf_type = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_encode[i].num_planes = atoi(token); token = strtok(NULL, delim);//cfg_opt optional if (token == NULL) { i++; cfg_encode[0].seqNum++; lineStr[0] = 0x0; continue; } cfg_encode[i].cfg_opt = atoi(token); token = strtok(NULL, delim); if (token == NULL) { i++; cfg_encode[0].seqNum++; lineStr[0] = 0x0; continue; } if ((cfg_encode[i].cfg_opt & 0x2) == 0x2) { len = strlen(token) > ENCODER_STRING_LEN_MAX ? ENCODER_STRING_LEN_MAX : strlen(token); mystrncpy(cfg_encode[i].cfg_file, token, len); printf("cfg_upd_url[%d] is\t: %s ;\n", i, cfg_encode[i].cfg_file); token = strtok(NULL, delim); if (token == NULL) { i++; cfg_encode[0].seqNum++; lineStr[0] = 0x0; continue; } } token = strtok(NULL, delim); if (token == NULL) { i++; cfg_encode[0].seqNum++; lineStr[0] = 0x0; continue; } else { //config no match printf("config no match conf %d command: %s\n", cfg_encode[i].cfg_opt, lineStr); lineStr[0] = 0x0; continue; } } return 0; } static int ParseCfgUpdateFile(FILE *fp, CfgChangeParam *cfg_update) { int parsed_num = 0, frameIdx = 0; char* token = NULL; static char lineStr[256] = {0, }; char valueStr[256] = {0, }; int has_update = 0; while (1) { if (lineStr[0] == 0x0) { //need a new line; if (fgets(lineStr, 256, fp) == NULL ) { if (cfg_update->enable_option && has_update) return 1; else { if (feof(fp)) return 0; continue; } } } if ((lineStr[0] == '#') ||(lineStr[0] == ';')||(lineStr[0] == ':')) { // skip comments lineStr[0] = 0x0; continue; } // keep the original memcpy(valueStr, lineStr, strlen(lineStr)); //frame number is separated by ' ' or ':' token = strtok(valueStr, ": "); if (token == NULL) { lineStr[0] = 0x0; continue; } frameIdx = atoi(token); if (frameIdx <0 || frameIdx < cfg_update->FrameNum) { // invid number lineStr[0] = 0x0; continue; } else if (frameIdx > cfg_update->FrameNum && has_update) {// done the current frame; if (cfg_update->enable_option) return 1; has_update = 0; continue; } else if (has_update ==0) {// clear the options cfg_update->FrameNum = frameIdx; cfg_update->enable_option = 0; has_update = 1; } token = strtok(NULL, " :"); // check the operation code while (token && strlen(token) == 1 && strncmp(token, " ", 1) == 0) token = strtok(NULL, " :"); // skip spaces if (token == NULL) { // no operate code lineStr[0] = 0x0; continue; } if (strcasecmp("ForceType",token) == 0) { // force picture type token = strtok(NULL, ":\r\n"); while (token && strlen(token) == 1 && strncmp(token, " ", 1) == 0) token = strtok(NULL, ":\r\n"); //check space if (token) { while ( *token == ' ' ) token++;//skip spaces; cfg_update->picType = atoi(token); cfg_update->enable_option |= FORCE_PICTURE_TYPE; } } else if (strcasecmp("ForceSkip",token) == 0) { // force picture type if (token) { cfg_update->enable_option |= FORCE_PICTURE_SKIP; } } else if (strcasecmp("ChangeBitRate",token) == 0) { token = strtok(NULL, ":\r\n"); while ( token && strlen(token) == 1 && strncmp(token, " ", 1) == 0) token = strtok(NULL, ":\r\n"); //check space if (token) { while ( *token == ' ' ) token++;//skip spaces; cfg_update->bitRate = atoi(token); cfg_update->enable_option |= CHANGE_TARGET_RATE; } } else if (strcasecmp("ChangeMinMaxQP",token) == 0) { token = strtok(NULL, ":\r\n"); while (token && strlen(token) == 1 && strncmp(token, " ", 1) == 0) token = strtok(NULL, ":\r\n"); //check space if (token) { while ( *token == ' ' ) token++;//skip spaces; parsed_num = sscanf(token, "%d %d %d %d %d %d %d", &cfg_update->minQpI, &cfg_update->maxQpI, &cfg_update->maxDeltaQp, &cfg_update->minQpP, &cfg_update->maxQpP, &cfg_update->minQpB, &cfg_update->maxQpB); if (parsed_num == 7) cfg_update->enable_option |= CHANGE_MIN_MAX_QP; } } else if (strcasecmp("ChangePeriodGOP",token) == 0) { token = strtok(NULL, ":\r\n"); while ( token && strlen(token) == 1 && strncmp(token, " ", 1) == 0) token = strtok(NULL, ":\r\n"); //check space if (token) { while ( *token == ' ' ) token++;//skip spaces; parsed_num = sscanf(token, "%d %d", &cfg_update->intraQP, &cfg_update->GOPPeriod); if (parsed_num == 2) cfg_update->enable_option |= CHANGE_GOP_PERIOD; } } else if (strcasecmp("SetLongTermRef",token) == 0) { token = strtok(NULL, ":\r\n"); while ( token && strlen(token) == 1 && strncmp(token, " ", 1) == 0) token = strtok(NULL, ":\r\n"); //check space if (token) { while ( *token == ' ' ) token++;//skip spaces; cfg_update->LTRFlags = atoi(token); cfg_update->enable_option |= LONGTERM_REF_SET; } } else if (strcasecmp("SetCustSmooth",token) == 0) { token = strtok(NULL, ":\r\n"); while ( token && strlen(token) == 1 && strncmp(token, " ", 1) == 0) token = strtok(NULL, ":\r\n"); //check space if (token) { while ( *token == ' ' ) token++;//skip spaces; cfg_update->smooth_level = atoi(token); cfg_update->enable_option |= CUST_SIZE_SMOOTH; } } else if (strcasecmp("SetCustH264P",token) == 0) { token = strtok(NULL, ":\r\n"); while ( token && strlen(token) == 1 && strncmp(token, " ", 1) == 0) token = strtok(NULL, ":\r\n"); //check space if (token) { while ( *token == ' ' ) token++;//skip spaces; parsed_num = sscanf(token, "%d %d %d", &cfg_update->newIDRInterval, &cfg_update->QPdelta_IDR, &cfg_update->QPdelta_LTR); if (parsed_num == 3) cfg_update->enable_option |= CUST_APP_H264_PLUS; } } else if (strcasecmp("ChangeMultiSlice",token) == 0) { token = strtok(NULL, ":\r\n"); while ( token && strlen(token) == 1 && strncmp(token, " ", 1) == 0) token = strtok(NULL, ":\r\n"); //check space if (token) { while ( *token == ' ' ) token++;//skip spaces; parsed_num = sscanf(token, "%d %d", &cfg_update->Slice_Mode, &cfg_update->Slice_Para); if (parsed_num == 2) cfg_update->enable_option |= CHANGE_MULTI_SLICE; } } else if (strcasecmp("ChangeStrictRC",token) == 0) { token = strtok(NULL, ":\r\n"); while ( token && strlen(token) == 1 && strncmp(token, " ", 1) == 0) token = strtok(NULL, ":\r\n"); //check space if (token) { while ( *token == ' ' ) token++;//skip spaces; parsed_num = sscanf(token, "%d %d", &cfg_update->bitrate_window, &cfg_update->pskip_threshold); if (parsed_num == 2) cfg_update->enable_option |= CHANGE_STRICT_RC; } } lineStr[0] = 0x0; continue; } }