/* * Copyright (c) 2019 Amlogic, Inc. All rights reserved. * * This source code is subject to the terms and conditions defined in below * which is part of this source code package. * * Description: */ // Copyright (C) 2019 Amlogic, Inc. All rights reserved. // // All information contained herein is Amlogic confidential. // // This software is provided to you pursuant to Software License // Agreement (SLA) with Amlogic Inc ("Amlogic"). This software may be // used only in accordance with the terms of this agreement. // // Redistribution and use in source and binary forms, with or without // modification is strictly prohibited without prior written permission // from Amlogic. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include #include #include #include #include #include #include #include #include #include #include #include "vdi.h" #include "tahoe.h" #include "tahoe_register.h" #include "libvptahoe_codec.h" #include #include "enc_driver.h" //#define TAHOE_DEVICE_NAME "/dev/tahoe" #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 #define POWER_TEST_NUM_MAX 7 #define WIDTH 3840 #define HEIGHT 3840 // consider rotated frame #define FRAMERATE 60 #define ENC_STREAM_BUF_SIZE 0x100000 #if VENDOR_FW #define FW_PATH "/vendor/lib/firmware/encoder/fw.bin" #else #define FW_PATH "/lib/firmware/encoder/fw.bin" #endif typedef struct { int osdNum; //int enable; int format; /*0:ARGB8888 1:ARGB4444 2:ARGB1555 3:NV21 4:NV12 5:BITMAP*/ int alpha_mode; int r2y_mode; //int endian; //int y_baseaddr_h2bit; //int c_baseaddr_h2bit; //int cmn_rsv; int x; int y; int w; int h; int alpha; int bitmap_y; int bitmap_u; int bitmap_v; //int y_baseaddr; //int c_baseaddr; //int stride; char osdfile[ENCODER_STRING_LEN_MAX]; }osdCfgParam; typedef struct { int ds_only; int ds_osd; int ds_w; int ds_h; char dsfile[ENCODER_STRING_LEN_MAX]; }dsCfgParam; typedef struct { int x; int y; int w; int h; }cropCfgParam; typedef struct { int roiNum; int enable; int x; int y; int w; int h; int region_inv; int QpMode; int roiQp; int lossless; int EncBiasMode; int maxQp; int minQp; }roiCfgParam; 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; int chnid; struct timeval timeFrameStart; struct timeval timeFrameEnd; int encodeEnd; 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 : yuv420p(yv12/yu12) int buf_type; // 0:vmalloc, 3:dma buffer int num_planes; // used for dma buffer case. 2 : nv12/nv21, 3 : yuv420p(yv12/yu12) int codec_id; // 4 : h.264, 5 : h.265 unsigned 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 */ int roi_enabled; int roi_map_enabled; char roifile[ENCODER_STRING_LEN_MAX]; // optional, roi info url in root fs, no present if roi is disabled int cfg_upd_enabled; int has_cfg_update; 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_parameter; // optional, High 16 bit bitrate window (frames max 120). low 16 bit bitrate threshold (percent) int forcePicQpIPB; int profile; int level; int tier; int osd_enabled; char osdfile[ENCODER_STRING_LEN_MAX]; int ds_enabled; char dsfile[ENCODER_STRING_LEN_MAX]; int crop_enabled; char cropfile[ENCODER_STRING_LEN_MAX]; int forcePicQpI; int forcePicQpPB; int rc_mode; unsigned int frame_rotation; unsigned int frame_mirroring; int power_test_enabled; } encodecCfgParam; //int venc_init_flag = 0; static int ParseRoiCfgFile(FILE *fp, roiCfgParam *cfg_roi); static int ParseOsdCfgFile(FILE *fp, osdCfgParam *cfg_osd); static int ParseDsCfgFile(FILE *fp, dsCfgParam *cfg_ds); static int ParseCropCfgFile(FILE *fp, cropCfgParam *cfg_crop); static int ParseEncodeCfgFile(FILE *fp, encodecCfgParam *cfg_encode); static int ParseCfgUpdateFile(FILE *fp, CfgChangeParam *cfg_update); static unsigned int uTimeDiff(struct timeval end, struct timeval start) { return (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); } //return timeDiff in u64 static unsigned long long uTimeDiffLL(struct timeval end, struct timeval start) { return (unsigned long long )(end.tv_sec - start.tv_sec) * 1000000 + (unsigned long long )(end.tv_usec - start.tv_usec); } 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; } int update_cfg(FILE *fp_cfg, int frame_num, handle_t *encode_info, encodecCfgParam *cfg_encode, CfgChangeParam *cfgChange) { 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) { encode_info->enc_frame_type = FRAME_TYPE_I; printf("force I frame on %d \n", frame_num); } } // if (cfgChange.enable_option // & FORCE_PICTURE_SKIP) // { // vl_video_encoder_skip_frame(handle_enc); // printf("force skip frame on %d \n", // frame_num); // } if (cfgChange->enable_option & CHANGE_TARGET_RATE) { vl_video_encoder_change_bitrate( encode_info, cfgChange->bitRate); printf("Change bitrate to %d on %d \n", cfgChange->bitRate, frame_num); } // if (cfgChange.enable_option // & CHANGE_MIN_MAX_QP) // { // vl_video_encoder_change_qp( // handle_enc, // cfgChange.minQpI,cfgChange.maxQpI, // cfgChange.maxDeltaQp, // cfgChange.minQpP,cfgChange.maxQpP, // cfgChange.minQpB,cfgChange.maxQpB); // printf("Change QP table on %d QPs: ", // frame_num); // printf("%d %d %d %d %d %d %d\n", // cfgChange.minQpI,cfgChange.maxQpI, // cfgChange.maxDeltaQp, // cfgChange.minQpP,cfgChange.maxQpP, // cfgChange.minQpB,cfgChange.maxQpB); // playStat.minQpI_base = cfgChange.minQpI; // playStat.maxQpI_base = cfgChange.maxQpI; // playStat.maxDeltaQp_base = // cfgChange.maxDeltaQp; // playStat.minQpP_base = cfgChange.minQpP; // playStat.maxQpP_base = cfgChange.maxQpP; // playStat.minQpB_base = cfgChange.minQpB; // playStat.maxQpB_base = cfgChange.maxQpB; // } if (cfgChange->enable_option & CHANGE_GOP_PERIOD) { vl_video_encoder_change_gop( encode_info, cfgChange->intraQP, cfgChange->GOPPeriod); printf("Change gop on %d QP %d %d\n", frame_num, cfgChange->intraQP, cfgChange->GOPPeriod); // playStat.CurGOPSize = cfgChange.GOPPeriod; // if (playStat.CurGOPCounter >= playStat.CurGOPSize) // playStat.CurGOPCounter = 0; } // if ((cfgChange.enable_option // & LONGTERM_REF_SET) && ltf_enabled) // { // vl_video_encoder_longterm_ref( // handle_enc, // cfgChange.LTRFlags); // printf("Longterm Ref on %d flag 0x%x\n", // frame_num, cfgChange.LTRFlags); // } // if (cfgChange.enable_option // & CUST_SIZE_SMOOTH) // { // if (cfgChange.smooth_level) { // playStat.cust_size_smooth_enable = 1; // if (cfgChange.smooth_level< 100) // playStat.smooth_qpdelta = 4; // else // playStat.smooth_qpdelta = 6; // } else { // playStat.cust_size_smooth_enable = 0; // playStat.smooth_qpdelta = 0; // playStat.qp_ltr = -1; // playStat.qp_idr = -1; // } // printf("Set CustSizeSmooth on %d level %d \n", // frame_num, cfgChange.smooth_level); // } // if ((cfgChange.enable_option // & CUST_APP_H264_PLUS) && ltf_enabled) // { // if (cfgChange.newIDRInterval) { //enable // if (playStat.cust_ltr_enable == 0) { // playStat.cust_ltr_enable = 1; // playStat.GopLTRInterval = playStat.CurGOPSize; // playStat.GopLTRCounter = playStat.CurGOPCounter; // } // if (playStat.CurGOPSize != cfgChange.newIDRInterval) // { // vl_video_encoder_change_gop( // handle_enc, // playStat.PrevFrameQP, // cfgChange.newIDRInterval // ); // printf("Gop change on %d to %d qp %d\n", // frame_num, cfgChange.newIDRInterval, // playStat.PrevFrameQP); // } // playStat.CurGOPSize = cfgChange.newIDRInterval; // playStat.QPdelta_IDR = cfgChange.QPdelta_IDR; // playStat.QPdelta_LTR = cfgChange.QPdelta_LTR; // if ( playStat.CurGOPCounter >= playStat.CurGOPSize) // playStat.CurGOPCounter = 0; // if (playStat.GopLTRCounter >= playStat.GopLTRInterval) // playStat.GopLTRCounter = 0; // } else { // if (playStat.cust_ltr_enable == 1) { // playStat.cust_ltr_enable = 0; // playStat.CurGOPSize = playStat.GopLTRInterval; // vl_video_encoder_change_gop( // handle_enc, // playStat.PrevFrameQP, // playStat.CurGOPSize); // printf("Gop change on %d to %d qp %d\n", // frame_num, // playStat.CurGOPSize, // playStat.PrevFrameQP); // if (playStat.CurGOPCounter >= playStat.CurGOPSize) // playStat.CurGOPCounter = 0; // playStat.GopLTRInterval = 0; // playStat.GopLTRCounter = 0; // playStat.QPdelta_IDR = 0; // playStat.QPdelta_LTR = 0; // playStat.qp_ltr = -1; // playStat.qp_idr = -1; // } // } // printf("Set Cust APP H264+ on %d interval %d qp delta idr %d, ltr %d \n", // frame_num, cfgChange.newIDRInterval, // cfgChange.QPdelta_IDR, // cfgChange.QPdelta_LTR); // } // if (cfgChange.enable_option // & CHANGE_MULTI_SLICE) // { // vl_video_encoder_change_multi_slice( // handle_enc, // cfgChange.Slice_Mode, // cfgChange.Slice_Para); // printf("Change slice on %d mode %d %d\n", // frame_num, // cfgChange.Slice_Mode, // cfgChange.Slice_Para); // } if (cfgChange->enable_option & CHANGE_STRICT_RC) { vl_video_encoder_change_strict_rc( encode_info, cfgChange->bitrate_window, cfgChange->pskip_threshold); printf("Change strict rate control on %d window %d threshold %d\n", frame_num, cfgChange->bitrate_window, cfgChange->pskip_threshold); } } if (cfgChange->FrameNum <= frame_num) { cfg_encode->has_cfg_update = ParseCfgUpdateFile(fp_cfg, cfgChange); } return 0; } static void *encode_thread(void *param) { int chn_id; int outfd = -1; int ret = 0; int i = 0; int k = 0; FILE *fp = NULL; FILE *fp_osdcfg = NULL; FILE *fp_osd[MAX_OSD_NUM]; FILE *fp_ds = NULL; FILE *fp_crop = NULL; FILE *fp_cfg = NULL; FILE *fp_roicfg = NULL; FILE *fp_roimap = NULL; int dsfd = -1; unsigned char *outbuffer = NULL; unsigned int outbuffer_len = 0; unsigned int dataLength = 0; unsigned char *inputBuffer = NULL; unsigned char *osd_buffer[MAX_OSD_NUM]; venc_buffer_t pFbPwSrcMem[POWER_TEST_NUM_MAX]; venc_buffer_t pFbSrcMem; venc_buffer_t posdMem[MAX_OSD_NUM]; venc_buffer_t bsBuffer[3]; unsigned int framesize; unsigned int osdsize; unsigned ysize; unsigned usize; unsigned vsize; unsigned uvsize; int intraRefresh; roiCfgParam cfg_roi[MAX_ROI_NUM]; osdCfgParam cfg_osd[MAX_OSD_NUM]; dsCfgParam cfg_ds; cropCfgParam cfg_crop; encodecCfgParam *cfg_encode = NULL; CfgChangeParam cfgChange; //vl_codec_handle_t handle_enc = 0; handle_t encode_info; signed char frame_type = -1; unsigned char *roimap_buffer = NULL; int roimap_macroblock; venc_buffer_t proiMem; unsigned int roimapsize; unsigned int frameWriteTime = 0; unsigned long long totalTime = 0, ioTime = 0, encodeoneTime = 0; struct timeval timeStart, timeEnd, readStart, readEnd, writeStart, writeEnd; int frame_num; int End_status = 0; int pw = 0; if (NULL != param) cfg_encode = (encodecCfgParam *)param; else { End_status = -1; goto end; } switch (cfg_encode->codec_id) { case 4: cfg_encode->codec_id = CODEC_ID_H264; break; case 5: cfg_encode->codec_id = CODEC_ID_H265; break; default: break; } if ((cfg_encode->framerate < 0) || (cfg_encode->framerate > FRAMERATE)) { printf("invalid framerate %d \n", cfg_encode->framerate); End_status = -1; goto end; } if (cfg_encode->bitrate <= 0) { printf("invalid bitrate \n"); End_status = -1; goto end; } if (cfg_encode->num < 0) { printf("invalid num \n"); End_status = -1; goto end; } cfg_encode->num_planes = 1; if (cfg_encode->buf_type == 3 && (cfg_encode->num_planes < 1 || cfg_encode->num_planes > 3)) { printf("invalid num_planes \n"); End_status = -1; goto end; } if (cfg_encode->src_buf_stride && cfg_encode->src_buf_stride < cfg_encode->width) { printf("incorrect cust source stride %d width %d", cfg_encode->src_buf_stride, cfg_encode->width); End_status = -1; goto end; } printf("src_url is\t: %s ;\n", cfg_encode->srcfile); printf("out_url is\t: %s ;\n", cfg_encode->outfile); printf("width is\t: %d ;\n", cfg_encode->width); printf("height is\t: %d ;\n", cfg_encode->height); printf("gop is\t: %d ;\n", cfg_encode->gop); printf("frmrate is\t: %d ;\n", cfg_encode->framerate); printf("bitrate is\t: %d ;\n", cfg_encode->bitrate); printf("frm_num is\t: %d ;\n", cfg_encode->num); printf("fmt is\t: %d ;\n", cfg_encode->fmt); printf("buf_type is\t: %d ;\n", cfg_encode->buf_type); printf("num_planes is\t: %d ;\n", cfg_encode->num_planes); printf("codec is\t: %d ;\n", cfg_encode->codec_id); if (cfg_encode->codec_id == CODEC_ID_H265) printf("codec is H265\n"); else printf("codec is H264\n"); outbuffer_len = 8 * 1024 * 1024 * sizeof(char); outbuffer = (unsigned char *) malloc(outbuffer_len); if (outbuffer == NULL) { printf("Can not malloc outbuffer\n"); End_status = -1; goto end; } if (cfg_encode->src_buf_stride) { if (cfg_encode->fmt == IMG_FMT_RGB888) { framesize = cfg_encode->src_buf_stride * cfg_encode->height * 3; } else if (cfg_encode->fmt == IMG_FMT_RGBA8888) { framesize = cfg_encode->src_buf_stride * cfg_encode->height * 4; } else { framesize = cfg_encode->src_buf_stride * cfg_encode->height * 3 / 2; } ysize = cfg_encode->src_buf_stride * cfg_encode->height; usize = cfg_encode->src_buf_stride * cfg_encode->height / 4; vsize = cfg_encode->src_buf_stride * cfg_encode->height / 4; uvsize = cfg_encode->src_buf_stride * cfg_encode->height / 2; } else { if (cfg_encode->fmt == IMG_FMT_RGB888) { framesize = cfg_encode->width * cfg_encode->height * 3; } else if (cfg_encode->fmt == IMG_FMT_RGBA8888) { framesize = cfg_encode->width * cfg_encode->height * 4; } else { framesize = cfg_encode->width * cfg_encode->height * 3 / 2; } ysize = cfg_encode->width * cfg_encode->height; usize = cfg_encode->width * cfg_encode->height / 4; vsize = cfg_encode->width * cfg_encode->height / 4; uvsize = cfg_encode->width * cfg_encode->height / 2; } inputBuffer = (unsigned char *) malloc(framesize); if (inputBuffer == NULL) { printf("Can not allocat inputBuffer\n"); End_status = -1; goto exit; } fp = fopen((const char*)cfg_encode->srcfile, "rb"); if (fp == NULL) { printf("open src file error!\n"); End_status = -1; goto exit; } if (cfg_encode->cfg_upd_enabled) { fp_cfg = fopen((const char*)cfg_encode->cfg_file, "r"); if (fp_cfg == NULL) { printf("open cfg file error!\n"); End_status = -1; goto exit; } cfg_encode->has_cfg_update = ParseCfgUpdateFile(fp_cfg, &cfgChange); printf("==%s, %d, cfgChange.bitRate:%d\n", __func__, __LINE__, cfgChange.bitRate); printf("==%s, %d, cfgChange.picType:%d\n", __func__, __LINE__, cfgChange.picType); printf("==%s, %d, minQpI:%d, maxQpI:%d, minQpP:%d, maxQpP:%d\n", __func__, __LINE__, cfgChange.minQpI, cfgChange.maxQpI, cfgChange.minQpP, cfgChange.maxQpP); printf("==%s, %d, cfgChange.GOPPeriod:%d\n", __func__, __LINE__, cfgChange.GOPPeriod); printf("==%s, %d, cfgChange.bitrate_window:%d\n", __func__, __LINE__, cfgChange.bitrate_window); } if (cfg_encode->roi_enabled) { fp_roicfg = fopen((const char*)cfg_encode->roifile, "r"); if (fp_roicfg == NULL) { printf("open osd config file error!\n"); goto exit; } memset(cfg_roi, 0, MAX_ROI_NUM * sizeof(roiCfgParam)); ParseRoiCfgFile(fp_roicfg, cfg_roi); fclose(fp_roicfg); } if (cfg_encode->osd_enabled) { fp_osdcfg = fopen((const char*)cfg_encode->osdfile, "r"); if (fp_osdcfg == NULL) { printf("open osd config file error!\n"); End_status = -1; goto exit; } memset(cfg_osd, 0, MAX_OSD_NUM * sizeof(osdCfgParam)); ParseOsdCfgFile(fp_osdcfg, cfg_osd); fclose(fp_osdcfg); } if (cfg_encode->ds_enabled) { fp_ds = fopen((const char*)cfg_encode->dsfile, "r"); if (fp_ds == NULL) { printf("open ds config file error!\n"); End_status = -1; goto exit; } memset(&cfg_ds, 0, sizeof(dsCfgParam)); ParseDsCfgFile(fp_ds, &cfg_ds); fclose(fp_ds); } if (cfg_encode->crop_enabled) { fp_crop = fopen((const char*)cfg_encode->cropfile, "r"); if (fp_crop == NULL) { printf("open crop config file error!\n"); End_status = -1; goto exit; } memset(&cfg_crop, 0, sizeof(cropCfgParam)); ParseCropCfgFile(fp_crop, &cfg_crop); fclose(fp_crop); } outfd = open((const char*)cfg_encode->outfile, O_CREAT | O_RDWR | O_TRUNC, 0644); if (outfd < 0) { printf("open dest file error!\n"); End_status = -1; goto exit; } memset(&encode_info, 0, sizeof(handle_t)); encode_info.init_qp = 30; encode_info.enc_rc_mode = 2; encode_info.chn_id = cfg_encode->chnid; encode_info.enc_fmt = cfg_encode->codec_id; // 0: h264 1: h265 encode_info.enc_width = cfg_encode->width; encode_info.enc_height = cfg_encode->height; encode_info.poc = 0; encode_info.enc_fps = cfg_encode->framerate; encode_info.enc_gop = cfg_encode->gop; encode_info.buf_stride = cfg_encode->src_buf_stride; encode_info.level = cfg_encode->level; encode_info.tier = cfg_encode->tier; encode_info.enc_bitrate = cfg_encode->bitrate; if (cfg_encode->rc_mode == 3) { encode_info.svc_enable = 1; } else { if (cfg_encode->rc_mode) encode_info.enc_rc_mode = cfg_encode->rc_mode; } if (cfg_encode->buf_type == 0) encode_info.golden_match_flag = 1; if (cfg_encode->codec_id == CODEC_ID_H265) { if (cfg_encode->profile == 1) encode_info.profile = HEVC_MAIN; else encode_info.profile = 0; } else { if (cfg_encode->profile == 1) encode_info.profile = AVC_BASELINE; else if (cfg_encode->profile == 2) encode_info.profile = AVC_MAIN; else if (cfg_encode->profile == 3) encode_info.profile = AVC_HIGH; else encode_info.profile = 0; } if (cfg_encode->forcePicQpI && cfg_encode->forcePicQpPB) { encode_info.fix_qp_I = cfg_encode->forcePicQpI; encode_info.fix_qp_P = cfg_encode->forcePicQpPB; } if (cfg_encode->frame_rotation == 0) encode_info.rotation_mode = 0; else if (cfg_encode->frame_rotation == 1) encode_info.rotation_mode = 1; else if (cfg_encode->frame_rotation == 2) encode_info.rotation_mode = 2; else if (cfg_encode->frame_rotation == 3) encode_info.rotation_mode = 3; else { printf("frame rotation angle is wrong\n"); encode_info.rotation_mode = 0; } if (cfg_encode->frame_mirroring <= 3) encode_info.mirror_mode = cfg_encode->frame_mirroring; else encode_info.mirror_mode = 0; if (cfg_encode->roi_map_enabled) { if (cfg_encode->codec_id == CODEC_ID_H264) roimap_macroblock = 16; else if (cfg_encode->codec_id == CODEC_ID_H265) roimap_macroblock = 32; roimapsize = ((cfg_encode->width + roimap_macroblock - 1) / roimap_macroblock) * ((cfg_encode->height + roimap_macroblock - 1 ) / roimap_macroblock); memset(&proiMem, 0, sizeof(venc_buffer_t)); proiMem.size = roimapsize; proiMem.cached = 1; if (vdi_allocate_dma_memory(&proiMem) < 0) { printf("Can not allocat dma Buffer\n"); goto end; } fp_roimap = fopen((const char*)cfg_encode->roifile, "rb"); if (fp_roimap == NULL) { printf("open roi map file error!\n"); goto exit; } roimap_buffer = (unsigned char *) malloc(roimapsize); if (roimap_buffer == NULL) { printf("Can not allocat roi map buffer\n"); goto end; } if (fread(roimap_buffer, 1, roimapsize, fp_roimap) != roimapsize) { printf("read roi_map file error!\n"); } safe_memcpy((void *)((unsigned long)proiMem.virt_addr), roimap_buffer, roimapsize); encode_info.tahoe_enc_pic.prp_roi_map_enable = cfg_encode->roi_map_enabled; encode_info.tahoe_enc_pic.prp_roi_map_addr = proiMem.phys_addr; } if (cfg_encode->osd_enabled) { encode_info.tahoe_enc_pic.osd_enable = 1; printf("[%s][%d]cfg_osd[0].osdNum:%d\n",__func__,__LINE__, cfg_osd[0].osdNum); for (i = 0; i < cfg_osd[0].osdNum; i ++) { if (i >= MAX_OSD_NUM) break; switch (cfg_osd[i].format) /*0:ARGB8888 1:ARGB4444 2:ARGB1555 3:NV21 4:NV12 5:BITMAP*/ { case 0: osdsize = cfg_osd[i].w * cfg_osd[i].h * 4; encode_info.tahoe_enc_pic.osd_config[i].format = OSD_FMT_ARGB8888; encode_info.tahoe_enc_pic.osd_config[i].stride = cfg_osd[i].w * 4; break; case 1: osdsize = cfg_osd[i].w * cfg_osd[i].h * 2; encode_info.tahoe_enc_pic.osd_config[i].format = OSD_FMT_ARGB4444; encode_info.tahoe_enc_pic.osd_config[i].stride = cfg_osd[i].w * 2; break; case 2: osdsize = cfg_osd[i].w * cfg_osd[i].h * 2; encode_info.tahoe_enc_pic.osd_config[i].format = OSD_FMT_ARGB1555; encode_info.tahoe_enc_pic.osd_config[i].stride = cfg_osd[i].w * 2; break; case 3: osdsize = cfg_osd[i].w * cfg_osd[i].h * 3 / 2; encode_info.tahoe_enc_pic.osd_config[i].format = OSD_FMT_NV21; encode_info.tahoe_enc_pic.osd_config[i].stride = cfg_osd[i].w; break; case 4: osdsize = cfg_osd[i].w * cfg_osd[i].h * 3 / 2; encode_info.tahoe_enc_pic.osd_config[i].format = OSD_FMT_NV12; encode_info.tahoe_enc_pic.osd_config[i].stride = cfg_osd[i].w; break; case 5: osdsize = cfg_osd[i].w * cfg_osd[i].h / 8; encode_info.tahoe_enc_pic.osd_config[i].format = OSD_FMT_BITMAP; encode_info.tahoe_enc_pic.osd_config[i].stride = cfg_osd[i].w / 8; break; default: break; } encode_info.tahoe_enc_pic.osd_config[i].enable = 1; //encode_info.tahoe_enc_pic.osd_config[i].format = cfg_osd[i].format; encode_info.tahoe_enc_pic.osd_config[i].alpha_mode = cfg_osd[i].alpha_mode; encode_info.tahoe_enc_pic.osd_config[i].r2y_mode = cfg_osd[i].r2y_mode; encode_info.tahoe_enc_pic.osd_config[i].endian = 0; encode_info.tahoe_enc_pic.osd_config[i].y_baseaddr_h2bit = 0; encode_info.tahoe_enc_pic.osd_config[i].c_baseaddr_h2bit = 0; encode_info.tahoe_enc_pic.osd_config[i].cmn_rsv = 0; encode_info.tahoe_enc_pic.osd_config[i].region_x = cfg_osd[i].x; encode_info.tahoe_enc_pic.osd_config[i].region_y = cfg_osd[i].y; encode_info.tahoe_enc_pic.osd_config[i].region_width = cfg_osd[i].w; encode_info.tahoe_enc_pic.osd_config[i].region_height = cfg_osd[i].h; encode_info.tahoe_enc_pic.osd_config[i].alpha = cfg_osd[i].alpha; encode_info.tahoe_enc_pic.osd_config[i].bitmap_y = cfg_osd[i].bitmap_y; encode_info.tahoe_enc_pic.osd_config[i].bitmap_u = cfg_osd[i].bitmap_u; encode_info.tahoe_enc_pic.osd_config[i].bitmap_v = cfg_osd[i].bitmap_v; //encode_info.tahoe_enc_pic.osd_config[i].y_baseaddr = 0; encode_info.tahoe_enc_pic.osd_config[i].c_baseaddr = 0; //encode_info.tahoe_enc_pic.osd_config[i].stride = 1; memset(&posdMem[i], 0, sizeof(venc_buffer_t)); posdMem[i].size = osdsize; posdMem[i].cached = 1; if (vdi_allocate_dma_memory(&posdMem[i]) < 0) { printf("Can not allocat dma Buffer\n"); End_status = -1; goto end; } fp_osd[i] = fopen((const char*)cfg_osd[i].osdfile, "rb"); if (fp_osd[i] == NULL) { printf("open osd file %d error!\n", i); End_status = -1; goto exit; } osd_buffer[i] = (unsigned char *) malloc(osdsize); if (osd_buffer[i] == NULL) { printf("Can not allocat roi_buffer\n"); End_status = -1; goto end; } } } if (cfg_encode->ds_enabled) { encode_info.ds_only = cfg_ds.ds_only; encode_info.ds_osd = cfg_ds.ds_osd; encode_info.ds_w = cfg_ds.ds_w; encode_info.ds_h = cfg_ds.ds_h; dsfd = open((const char*)cfg_ds.dsfile, O_CREAT | O_RDWR | O_TRUNC, 0644); if (dsfd < 0) { printf("open ds file error!\n"); End_status = -1; goto end; } } if (cfg_encode->crop_enabled) { encode_info.crop_enable = cfg_encode->crop_enabled; encode_info.crop_x = cfg_crop.x; encode_info.crop_y = cfg_crop.y; encode_info.crop_w = cfg_crop.w; encode_info.crop_h = cfg_crop.h; } if (cfg_encode->roi_enabled) { encode_info.tahoe_enc_pic.roi_enable = cfg_encode->roi_enabled; for (i = 0; i < cfg_roi[0].roiNum; i++) { if (i >= MAX_ROI_NUM) break; if (cfg_roi[i].enable) { encode_info.tahoe_enc_pic.roi_config[i].enable = cfg_roi[i].enable; encode_info.tahoe_enc_pic.roi_config[i].region_x = cfg_roi[i].x; encode_info.tahoe_enc_pic.roi_config[i].region_y = cfg_roi[i].y; encode_info.tahoe_enc_pic.roi_config[i].region_w = cfg_roi[i].w; encode_info.tahoe_enc_pic.roi_config[i].region_h = cfg_roi[i].h; encode_info.tahoe_enc_pic.roi_config[i].region_inv = cfg_roi[i].region_inv; encode_info.tahoe_enc_pic.roi_config[i].QpMode = cfg_roi[i].QpMode; encode_info.tahoe_enc_pic.roi_config[i].roiQp = cfg_roi[i].roiQp; encode_info.tahoe_enc_pic.roi_config[i].lossless = cfg_roi[i].lossless; encode_info.tahoe_enc_pic.roi_config[i].EncBiasMode = cfg_roi[i].EncBiasMode; encode_info.tahoe_enc_pic.roi_config[i].maxQp = cfg_roi[i].maxQp; encode_info.tahoe_enc_pic.roi_config[i].minQp = cfg_roi[i].minQp; } } } if (cfg_encode->fmt == IMG_FMT_NV12) { printf("img_format is IMG_FMT_NV12 \n"); encode_info.mfdin_input_fmt = MFDI_INPUT_FMT_NV12; } else if (cfg_encode->fmt == IMG_FMT_NV21) { printf("img_format is IMG_FMT_NV21 \n"); encode_info.mfdin_input_fmt = MFDI_INPUT_FMT_NV21; } else if (cfg_encode->fmt == IMG_FMT_YUV420P) { printf("img_format is IMG_FMT_YUV420P \n"); encode_info.mfdin_input_fmt = MFDI_INPUT_FMT_YUV420_PLANAR; } else if (cfg_encode->fmt == IMG_FMT_RGB888) { printf("img_format is IMG_FMT_RGB888 \n"); encode_info.mfdin_input_fmt = MFDI_INPUT_FMT_RGB888; } else if (cfg_encode->fmt == IMG_FMT_RGBA8888) { printf("img_format is IMG_FMT_RGBA8888 \n"); encode_info.mfdin_input_fmt = MFDI_INPUT_FMT_RGBA8888; } if (cfg_encode->power_test_enabled) { memset(pFbPwSrcMem, 0, sizeof(pFbPwSrcMem)); for (pw = 0; pw < POWER_TEST_NUM_MAX; pw++) { pFbPwSrcMem[pw].size = framesize; pFbPwSrcMem[pw].cached = 1; if (vdi_allocate_dma_memory(&pFbPwSrcMem[pw]) < 0) { printf("Can not allocat dma Buffer chnid %d\n", encode_info.chn_id); goto end; } } } else { memset(&pFbSrcMem, 0, sizeof(pFbSrcMem)); pFbSrcMem.size = framesize; pFbSrcMem.cached = 1; if (vdi_allocate_dma_memory(&pFbSrcMem) < 0) { printf("Can not allocat dma Buffer chnid %d\n", encode_info.chn_id); End_status = -1; goto end; } } //for vps/sps/pps for (i = 0; i < 3; i++) { memset(&bsBuffer[i], 0, sizeof(bsBuffer[i])); bsBuffer[i].size = ENC_STREAM_BUF_SIZE; if (vdi_allocate_dma_memory(&bsBuffer[i]) < 0) { printf("Can not allocat dma Buffer chnid %d\n", encode_info.chn_id); End_status = -1; goto end; } printf("[%s][%d]bsBuffer[%d].phys_addr:0x%x\n", \ __func__,__LINE__, i, bsBuffer[i].phys_addr); } if (!encode_info.buf_stride) { encode_info.buf_stride = encode_info.enc_width; } printf("handle[chn_id].buf_stride is: %d \n", encode_info.buf_stride); if (!cfg_encode->power_test_enabled) { encode_info.tahoe_enc_pic.inpt_buf_addr[0] = pFbSrcMem.phys_addr; if ((cfg_encode->fmt == IMG_FMT_NV12) || (cfg_encode->fmt == IMG_FMT_NV21)) { encode_info.tahoe_enc_pic.inpt_buf_addr[1] = pFbSrcMem.phys_addr + encode_info.buf_stride * encode_info.enc_height; encode_info.tahoe_enc_pic.inpt_buf_addr[2] = encode_info.tahoe_enc_pic.inpt_buf_addr[1]; } else if (cfg_encode->fmt == IMG_FMT_YUV420P) { encode_info.tahoe_enc_pic.inpt_buf_addr[1] = pFbSrcMem.phys_addr + encode_info.buf_stride * encode_info.enc_height; encode_info.tahoe_enc_pic.inpt_buf_addr[2] = pFbSrcMem.phys_addr + (encode_info.buf_stride * encode_info.enc_height * 5 / 4); } } encode_info.header_buf_addr[0] = bsBuffer[0].phys_addr; encode_info.header_buf_addr[1] = bsBuffer[1].phys_addr; encode_info.header_buf_addr[2] = bsBuffer[2].phys_addr; printf("header buf addr:%lx %lx %lx\n",encode_info.header_buf_addr[0],encode_info.header_buf_addr[1],encode_info.header_buf_addr[2]); printf("New allocate frame address y:0x%x cb:0x%x cr:0x%x\n", encode_info.tahoe_enc_pic.inpt_buf_addr[0], encode_info.tahoe_enc_pic.inpt_buf_addr[1], encode_info.tahoe_enc_pic.inpt_buf_addr[2]); if (vl_tahoe_encoder_init(encode_info.enc_fmt, encode_info) < 0) { printf("vl_tahoe_encoder_init failed chnid %d\n", encode_info.chn_id); End_status = -1; goto exit; } if (cfg_encode->power_test_enabled) { for (pw = 0; pw < POWER_TEST_NUM_MAX; pw++) { if (fread(inputBuffer, 1, framesize, fp) != framesize) { rewind(fp); clearerr(fp); if (fread(inputBuffer, 1, framesize, fp) != framesize) { printf("read input file error!\n"); End_status = -1; goto exit; } } memcpy((void *)((unsigned long)pFbPwSrcMem[pw].virt_addr), inputBuffer, framesize); } } gettimeofday(&timeStart, NULL); for (i = 0; i < cfg_encode->num; i++) { //for (int chn_id = 0; chn_id < MAX_CHANNEL; chn_id++) { gettimeofday(&readStart, NULL); if (cfg_encode->power_test_enabled) { pw = i % POWER_TEST_NUM_MAX; encode_info.tahoe_enc_pic.inpt_buf_addr[0] = pFbPwSrcMem[pw].phys_addr; if ((cfg_encode->fmt == IMG_FMT_NV12) || (cfg_encode->fmt == IMG_FMT_NV21)) { encode_info.tahoe_enc_pic.inpt_buf_addr[1] = pFbPwSrcMem[pw].phys_addr + encode_info.buf_stride * encode_info.enc_height; encode_info.tahoe_enc_pic.inpt_buf_addr[2] = encode_info.tahoe_enc_pic.inpt_buf_addr[1]; } else if (cfg_encode->fmt == IMG_FMT_YUV420P) { encode_info.tahoe_enc_pic.inpt_buf_addr[1] = pFbPwSrcMem[pw].phys_addr + encode_info.buf_stride * encode_info.enc_height; encode_info.tahoe_enc_pic.inpt_buf_addr[2] = pFbPwSrcMem[pw].phys_addr + (encode_info.buf_stride * encode_info.enc_height * 5 / 4); } } else { if (fread(inputBuffer, 1, framesize, fp) != framesize) { rewind(fp); clearerr(fp); if (fread(inputBuffer, 1, framesize, fp) != framesize) { printf("read input file error!\n"); End_status = -1; goto exit; } } memcpy((void *)((unsigned long)pFbSrcMem.virt_addr), inputBuffer, framesize); } if (cfg_encode->osd_enabled) { for (k = 0; k < cfg_osd[0].osdNum; k++) { size_t n = fread(osd_buffer[k], 1, posdMem[k].size, fp_osd[k]); if (n != posdMem[k].size) { fseek(fp_osd[k], 0, SEEK_SET); clearerr(fp_osd[k]); fread(osd_buffer[k] + n, 1, posdMem[k].size - n, fp_osd[k]); } memcpy((void *)((unsigned long)posdMem[k].virt_addr), osd_buffer[k], posdMem[k].size); encode_info.tahoe_enc_pic.osd_config[k].y_baseaddr = posdMem[k].phys_addr; } } gettimeofday(&readEnd, NULL); ioTime += uTimeDiff(readEnd, readStart); gettimeofday(&cfg_encode->timeFrameStart, NULL); encode_info.enc_frame_type = FRAME_TYPE_AUTO; if (cfg_encode->cfg_upd_enabled && cfg_encode->has_cfg_update) { update_cfg(fp_cfg, i, &encode_info, cfg_encode, &cfgChange); } if (encode_info.poc == 0 || encode_info.poc % encode_info.enc_gop == 0) encode_info.enc_frame_type = FRAME_TYPE_IDR; if (encode_info.enc_frame_type == FRAME_TYPE_IDR || encode_info.enc_frame_type == FRAME_TYPE_I) encode_info.poc = 0; if (encode_info.enc_frame_type == FRAME_TYPE_IDR || encode_info.enc_frame_type == FRAME_TYPE_I) { vl_tahoe_encoder_generate_header(&encode_info); ret = get_header(&encode_info, outbuffer, (unsigned int *)&dataLength); if (ret == 0) { write(outfd, (unsigned char *) outbuffer, dataLength); } } vl_tahoe_encoder_encode(&encode_info); ret = get_bsbframe(&encode_info, outbuffer, (unsigned int *)&dataLength, &frame_type); gettimeofday(&writeStart, NULL); if (ret == 0) { write(outfd, (unsigned char *) outbuffer, dataLength); } if (cfg_encode->ds_enabled) { ret = get_dsframe(&encode_info, outbuffer, (unsigned int *)&dataLength); if (ret == 0) { write(dsfd, (unsigned char *) outbuffer, dataLength); } } gettimeofday(&writeEnd, NULL); frameWriteTime = uTimeDiff(writeEnd, writeStart); ioTime += frameWriteTime; gettimeofday(&cfg_encode->timeFrameEnd, NULL); encode_info.poc++; encodeoneTime = uTimeDiff(writeStart, readEnd); printf("==%s, %d, chn_id:%d num %d, Encode one frame time %llu us\n", __func__, __LINE__, encode_info.chn_id, i, encodeoneTime); frame_num = i; } gettimeofday(&timeEnd, NULL); totalTime = uTimeDiffLL(timeEnd, timeStart); printf("[Total time: %llu us], [IO time: %llu us]\n", totalTime, ioTime); if (frame_num > 1) { printf("[Encode Total time: %llu us], [avgTime: %llu us], [avgfps: %d]\n", totalTime - ioTime, (totalTime - ioTime) / frame_num, 1*1000*1000/((totalTime - ioTime) / frame_num)); } exit: vl_tahoe_encoder_destroy(encode_info); if (inputBuffer) free(inputBuffer); if (outbuffer) free(outbuffer); if (outfd >= 0) close(outfd); if (fp) fclose(fp); if (fp_roimap) fclose(fp_roimap); for (i = 0; i < MAX_OSD_NUM; i++) { if (osd_buffer[i]) { free(osd_buffer[i]); osd_buffer[i] = NULL; } if (fp_osd[i]) { fclose(fp_osd[i]); fp_osd[i] = NULL; } } if (dsfd >= 0) close(dsfd); if (End_status == 0) printf("Encode End Succeeded! width:%d\n", cfg_encode->width); else if (End_status == -1) printf("Encode Failed! width:%d\n", cfg_encode->width); else printf("Encode End with unknown status:%d\n", End_status); end: cfg_encode->encodeEnd = 1; pthread_exit(0); return NULL; } int main(int argc, char **argv) { int i = 0; int arg_count = 0; int len = 0; FILE *fp_cfg_encode = NULL; int roi_type; encodecCfgParam cfg_encode[MAX_INSTANCE]; tahoe_set_log_level(NONE); if ((argc != 2) && (argc < 13)) { printf("Amlogic Encoder API \n"); printf(" usage: tahoe_test " "[srcfile][outfile][width][height][gop][framerate][bitrate][num][fmt][" "buf type][num_planes][codec_id] \n"); printf(" options \t:\n"); printf(" srcfile \t: yuv data url in your root fs\n"); printf(" outfile \t: stream url in your root fs\n"); printf(" width \t: width\n"); printf(" height \t: height\n"); printf(" gop \t: I frame refresh interval\n"); printf(" framerate\t: framerate \n"); printf(" bitrate \t: bit rate \n"); printf(" num \t: encode frame count \n"); printf(" fmt \t: encode input fmt 1 : nv12, 2 : nv21, 3 : yuv420p(yv12/yu12), 5 : RGB888, 6 : RGBA8888\n"); printf(" buf_type (golden_match: 0 bitmatch, 1 mismatch) \t: 0:vmalloc, 3:dma buffer\n"); printf(" num_planes \t: used for dma buffer case. 2 : nv12/nv21, 3 : yuv420p(yv12/yu12)\n"); printf(" codec_id \t: 4 : h.264, 5 : h.265\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 10: IP_SVC5\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 rc mode. 1: CBR 2: VBR (default)\n"); printf(" \t\t bit 11: profile 0: auto (default), h.264 (1: BASELINE, 2: MAIN, 3: HIGH), h.265 (1: MAIN)\n"); printf(" \t\t bit 12: level 0: auto (default)\n"); printf(" \t\t bit 13: tier 0: auto (default)\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 mirror mode: bit1 : mirror; bit2: flip;\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(" \t\t bit 24: osd control. 0: disabled (default) 1: enabled\n"); printf(" \t\t bit 25: ds control. 0: disabled (default) 1: enabled\n"); printf(" \t\t bit 26: crop control. 0: disabled (default) 1: enabled\n"); printf(" \t\t bit 31: power test control. 0: disabled (default) 1: enabled\n"); printf(" roifile \t: optional, roi info url in root fs, no present if roi is disabled\n"); printf(" cfg_file \t: optional, cfg update info url. no present if update is disabled\n"); printf(" src_buf_stride \t: optional, source buffer stride\n"); printf(" intraRefresh \t: optional, lower 4 bits for intra-refresh mode; others for refresh parameter, controlled by intraRefresh bit\n"); printf(" bitStreamBuf \t: optional, encoded bitstream buffer size in MB\n"); printf(" MultiSlice parameter \t: optional, multi slice parameter in MB/CTU or CTU and size (HIGH_16bits size + LOW_16bit CTU) combined\n"); printf(" cust_qp_delta \t: optional, cust_qp_delta apply to P frames value >0 lower; <0 increase the quality \n"); printf(" strict rate control parameter \t: optional, High 16 bit bitrate window (frames max 120). low 16 bit bitrate threshold (percent)\n"); printf(" forcePicQpIPB: force qp value\n"); printf(" osdfile \t: optional, osd info url in root fs, no present if osd is disabled\n"); printf(" dsfile \t: optional, ds info url in root fs, no present if ds is disabled\n"); printf(" cropfile \t: optional, crop info url in root fs, no present if crop is disabled\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, MAX_INSTANCE * 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]); cfg_encode[0].codec_id = atoi(argv[12]); if (argc > 13) { cfg_encode[0].cfg_opt = (int)strtol(argv[13], NULL, 16);//atoi(argv[13]); } if (argc > 14) { arg_count = 14; if ((cfg_encode[0].cfg_opt & 0x1) && argc > arg_count) { if (strlen(argv[arg_count]) >= ENCODER_STRING_LEN_MAX) { printf("Warning: roi filename too long (max length: %d), will be truncated\n", ENCODER_STRING_LEN_MAX - 1); } roi_type = atoi(argv[arg_count]); arg_count++; // roi_type: 1 region, 2 map; if (roi_type == 1) cfg_encode[0].roi_enabled = 1; else if (roi_type == 2) cfg_encode[0].roi_map_enabled = 1; snprintf(cfg_encode[0].roifile, ENCODER_STRING_LEN_MAX, "%s", argv[arg_count]); printf("roi_url is\t: %s ;\n", cfg_encode[0].roifile); arg_count ++; } if ((cfg_encode[0].cfg_opt & 0x2) == 0x2 && argc > arg_count) { if (strlen(argv[arg_count]) >= ENCODER_STRING_LEN_MAX) { printf("Warning: config filename too long (max length: %d), will be truncated\n", ENCODER_STRING_LEN_MAX - 1); } cfg_encode[0].cfg_upd_enabled = 1; snprintf(cfg_encode[0].cfg_file, ENCODER_STRING_LEN_MAX, "%s", argv[arg_count]); printf("cfg_upd_url is\t: %s ;\n", cfg_encode[0].cfg_file); arg_count ++; } if ((cfg_encode[0].cfg_opt & 0x100) == 0x100 && argc > arg_count) { cfg_encode[0].src_buf_stride = atoi(argv[arg_count]); arg_count ++; } if ((cfg_encode[0].cfg_opt >> 10) & 0x1 && argc > arg_count) { cfg_encode[0].rc_mode = atoi(argv[arg_count]); printf("rc_mode %d\n", cfg_encode[0].rc_mode); arg_count ++; } if ((cfg_encode[0].cfg_opt >> 11) & 0x1 && argc > arg_count) { cfg_encode[0].profile = atoi(argv[arg_count]); printf("profile %d\n", cfg_encode[0].profile); arg_count ++; } if ((cfg_encode[0].cfg_opt >> 12) & 0x1 && argc > arg_count) { cfg_encode[0].level = atoi(argv[arg_count]); printf("level %d\n", cfg_encode[0].level); arg_count ++; } if ((cfg_encode[0].cfg_opt >> 13) & 0x1 && argc > arg_count) { cfg_encode[0].tier = atoi(argv[arg_count]); printf("tier %d\n",cfg_encode[0].tier); arg_count ++; } /*if ((cfg_opt & 0x400) == 0x400 && argc > arg_count) { intraRefresh = atoi(argv[arg_count]); printf("IntraRefresh mode %d, arg %d;\n", (intraRefresh & 0xf), (intraRefresh >> 4)); arg_count ++; } if ((cfg_opt & 0x40000) == 0x40000 && argc > arg_count) { bitStreamBuf = atoi(argv[arg_count]); printf("bitstream_buf_size: %d \n", bitStreamBuf); arg_count ++; } if ((cfg_opt >> 19) & 0x3 && argc > arg_count) { MultiSlice_parameter = atoi(argv[arg_count]); printf("Multi-slices para %d \n", MultiSlice_parameter); arg_count ++; } if ((cfg_opt >> 21) & 0x1 && argc > arg_count) { cust_qp_delta = atoi(argv[arg_count]); printf("cust_qp_delta %d \n", cust_qp_delta); arg_count ++; } if ((cfg_opt >> 22) & 0x1 && argc > arg_count) { strict_rate_control_parameter = atoi(argv[arg_count]); printf("strict_rate_control_parameter %d\n", strict_rate_control_parameter); printf("bit-rate window %d frames, skip_threshold %d\n", strict_rate_control_parameter>>16, strict_rate_control_parameter& 0xffff); arg_count ++; }*/ if ((cfg_encode[0].cfg_opt >> 23) & 0x1 && argc > arg_count) { cfg_encode[0].forcePicQpI = atoi(argv[arg_count]); arg_count++; cfg_encode[0].forcePicQpPB = atoi(argv[arg_count]); printf("forcePicQpI %d, forcePicQpPB %d\n", cfg_encode[0].forcePicQpI, cfg_encode[0].forcePicQpPB); arg_count ++; } if ((cfg_encode[0].cfg_opt >> 24) & 0x1 && argc > arg_count) { if (strlen(argv[arg_count]) >= ENCODER_STRING_LEN_MAX) { printf("Warning: roi filename too long (max length: %d), will be truncated\n", ENCODER_STRING_LEN_MAX - 1); } cfg_encode[0].osd_enabled = 1; snprintf(cfg_encode[0].osdfile, ENCODER_STRING_LEN_MAX, "%s", argv[arg_count]); printf("osdfile is\t: %s ;\n", cfg_encode[0].osdfile); arg_count ++; } if ((cfg_encode[0].cfg_opt >> 25) & 0x1 && argc > arg_count) { if (strlen(argv[arg_count]) >= ENCODER_STRING_LEN_MAX) { printf("Warning: ds filename too long (max length: %d), will be truncated\n", ENCODER_STRING_LEN_MAX - 1); } cfg_encode[0].ds_enabled = 1; snprintf(cfg_encode[0].dsfile, ENCODER_STRING_LEN_MAX, "%s", argv[arg_count]); printf("dsfile is\t: %s ;\n", cfg_encode[0].dsfile); arg_count ++; } if ((cfg_encode[0].cfg_opt >> 26) & 0x1 && argc > arg_count) { if (strlen(argv[arg_count]) >= ENCODER_STRING_LEN_MAX) { printf("Warning: ds filename too long (max length: %d), will be truncated\n", ENCODER_STRING_LEN_MAX - 1); } cfg_encode[0].crop_enabled = 1; snprintf(cfg_encode[0].cropfile, ENCODER_STRING_LEN_MAX, "%s", argv[arg_count]); printf("cropfile is\t: %s ;\n", cfg_encode[0].cropfile); arg_count ++; } if (arg_count != argc) { printf("config no match conf %d argc %d\n", cfg_encode[0].cfg_opt, argc); return -1; } } if (cfg_encode[0].cfg_opt > 0) { cfg_encode[0].frame_rotation = (cfg_encode[0].cfg_opt >> 14) & 0x03; cfg_encode[0].frame_mirroring = (cfg_encode[0].cfg_opt >> 16) & 0x03; cfg_encode[0].power_test_enabled = (cfg_encode[0].cfg_opt >> 31) & 0x1; printf("frame_rotation=%d, frame_mirroring=%d, power_test=%d\n", cfg_encode[0].frame_rotation, cfg_encode[0].frame_mirroring, cfg_encode[0].power_test_enabled); } cfg_encode[0].seqNum = 1; } encoder_open(/*"fw.bin"*/FW_PATH); printf("==%s, %d, cfg_encode[0].seqNum:%d\n", __func__, __LINE__, cfg_encode[0].seqNum); pthread_t tid[MAX_INSTANCE]; for (i = 0; i < cfg_encode[0].seqNum; i ++) { if (i >= MAX_INSTANCE) break; cfg_encode[i].chnid = i; pthread_create(&tid[i], NULL, encode_thread, &cfg_encode[i]); } for (i = 0; i < cfg_encode[0].seqNum; i ++) { if (i >= MAX_INSTANCE) break; pthread_join(tid[i], NULL); } encoder_close(); return 0; } //#osdfile format x y w h alpha alpha_mode r2ymode bitmap_y bitmap_u bitmap_v //#format 0:ARGB8888 1:ARGB4444 2:ARGB1555 3:NV21 4:NV12 5:BITMAP static int ParseOsdCfgFile(FILE *fp, osdCfgParam *cfg_osd) { char* token = NULL; const char *delim = " "; static char lineStr[ENCODER_STRING_LEN_MAX*4] = {0}; char valueStr[ENCODER_STRING_LEN_MAX] = {0}; int i = 0; while (1) { if (i >= MAX_OSD_NUM) 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 snprintf(valueStr, sizeof(valueStr), "%s", lineStr); //param is separated by ' ' token = strtok(valueStr, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } snprintf(cfg_osd[i].osdfile, ENCODER_STRING_LEN_MAX, "%s", token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_osd[i].format = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_osd[i].x = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_osd[i].y = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_osd[i].w = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_osd[i].h = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_osd[i].alpha = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_osd[i].alpha_mode = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_osd[i].r2y_mode = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_osd[i].bitmap_y = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_osd[i].bitmap_u = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_osd[i].bitmap_v = atoi(token); i++; cfg_osd[0].osdNum++; lineStr[0] = 0x0; continue; } return 0; } //#dsfile ds_only ds_osd w h static int ParseDsCfgFile(FILE *fp, dsCfgParam *cfg_ds) { char* token = NULL; const char *delim = " "; static char lineStr[ENCODER_STRING_LEN_MAX*4] = {0}; char valueStr[ENCODER_STRING_LEN_MAX] = {0}; while (1) { 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; } snprintf(cfg_ds->dsfile, ENCODER_STRING_LEN_MAX, "%s", token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_ds->ds_only = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_ds->ds_osd = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_ds->ds_w = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_ds->ds_h = atoi(token); lineStr[0] = 0x0; continue; } return 0; } //#cropfile x y w h static int ParseCropCfgFile(FILE *fp, cropCfgParam *cfg_crop) { char* token = NULL; const char *delim = " "; static char lineStr[ENCODER_STRING_LEN_MAX*4] = {0}; char valueStr[ENCODER_STRING_LEN_MAX] = {0}; while (1) { 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; } cfg_crop->x = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_crop->y = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_crop->w = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_crop->h = atoi(token); lineStr[0] = 0x0; continue; } return 0; } static int ParseEncodeCfgFile(FILE *fp, encodecCfgParam *cfg_encode) { char* token = NULL; const char *delim = " \t\r\n"; static char lineStr[ENCODER_STRING_LEN_MAX*4] = {0}; char valueStr[ENCODER_STRING_LEN_MAX] = {0}; int i = 0; int len = 0; int roi_type; while (1) { if (i >= MAX_INSTANCE) 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); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_encode[i].codec_id = 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 = (int)strtol(token, NULL, 0); token = strtok(NULL, delim); if (token == NULL) { i++; cfg_encode[0].seqNum++; lineStr[0] = 0x0; continue; } if (cfg_encode[i].cfg_opt > 0) { cfg_encode[i].frame_rotation = (cfg_encode[i].cfg_opt >> 14) & 0x03; cfg_encode[i].frame_mirroring = (cfg_encode[i].cfg_opt >> 16) & 0x03; printf("frame_rotation=%d, frame_mirroring=%d\n", cfg_encode[i].frame_rotation, cfg_encode[i].frame_mirroring); } if ((cfg_encode[i].cfg_opt & 0x1) == 0x1) { roi_type = atoi(token);// roi_type: 1 region, 2 map; token = strtok(NULL, delim); if (token == NULL) { printf("missing forcePicQpPB\n"); continue; } if (roi_type == 1) cfg_encode[i].roi_enabled = 1; else if (roi_type == 2) cfg_encode[i].roi_map_enabled = 1; len = strlen(token) > ENCODER_STRING_LEN_MAX ? ENCODER_STRING_LEN_MAX : strlen(token); mystrncpy(cfg_encode[i].roifile, token, len); printf("roi_url is\t: %s ;\n", cfg_encode[i].roifile); 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); cfg_encode[i].cfg_upd_enabled = 1; 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; } } if ((cfg_encode[i].cfg_opt & 0x100) == 0x100) { cfg_encode[i].src_buf_stride = atoi(token); token = strtok(NULL, delim); if (token == NULL) { i++; cfg_encode[0].seqNum++; lineStr[0] = 0x0; continue; } } if ((cfg_encode[i].cfg_opt >> 11) & 0x1) { cfg_encode[i].profile = atoi(token); printf("profile %d\n", cfg_encode[i].profile); token = strtok(NULL, delim); if (token == NULL) { i++; cfg_encode[0].seqNum++; lineStr[0] = 0x0; continue; } } if ((cfg_encode[i].cfg_opt >> 12) & 0x1) { cfg_encode[i].level = atoi(token); printf("level %d\n", cfg_encode[i].level); token = strtok(NULL, delim); if (token == NULL) { i++; cfg_encode[0].seqNum++; lineStr[0] = 0x0; continue; } } if ((cfg_encode[i].cfg_opt >> 13) & 0x1) { cfg_encode[i].tier = atoi(token); printf("tier %d\n",cfg_encode[i].tier); token = strtok(NULL, delim); if (token == NULL) { i++; cfg_encode[0].seqNum++; lineStr[0] = 0x0; continue; } } if ((cfg_encode[i].cfg_opt >> 23) & 0x1) { cfg_encode[i].forcePicQpI = atoi(token); token = strtok(NULL, delim); if (token == NULL) { printf("missing forcePicQpPB\n"); continue; } cfg_encode[i].forcePicQpPB = atoi(token); printf("forcePicQpI %d, forcePicQpPB %d\n", cfg_encode[i].forcePicQpI, cfg_encode[i].forcePicQpPB); token = strtok(NULL, delim); if (token == NULL) { i++; cfg_encode[0].seqNum++; lineStr[0] = 0x0; continue; } } if ((cfg_encode[i].cfg_opt >> 24) & 0x1) { len = strlen(token) > ENCODER_STRING_LEN_MAX ? ENCODER_STRING_LEN_MAX : strlen(token); mystrncpy(cfg_encode[i].osdfile, token, len); cfg_encode[i].osd_enabled = 1; printf("osdfile is\t: %s ;\n", cfg_encode[i].osdfile); token = strtok(NULL, delim); if (token == NULL) { i++; cfg_encode[0].seqNum++; lineStr[0] = 0x0; continue; } } if ((cfg_encode[i].cfg_opt >> 25) & 0x1) { len = strlen(token) > ENCODER_STRING_LEN_MAX ? ENCODER_STRING_LEN_MAX : strlen(token); printf("len %d\n", len); mystrncpy(cfg_encode[i].dsfile, token, len); cfg_encode[i].ds_enabled = 1; printf("dsfile is\t: %s ;\n", cfg_encode[i].dsfile); token = strtok(NULL, delim); if (token == NULL) { i++; cfg_encode[0].seqNum++; lineStr[0] = 0x0; continue; } } if ((cfg_encode[i].cfg_opt >> 26) & 0x1) { len = strlen(token) > ENCODER_STRING_LEN_MAX ? ENCODER_STRING_LEN_MAX : strlen(token); printf("len %d\n", len); memset(cfg_encode[i].cropfile, 0, ENCODER_STRING_LEN_MAX); snprintf(cfg_encode[i].cropfile, sizeof(cfg_encode[i].cropfile), "%s", token); cfg_encode[i].crop_enabled = 1; printf("cropfile is\t: %s ;\n", cfg_encode[i].cropfile); 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; } //#roifile enable x y w h region_inv QpMode roiQp lossless EncBiasMode maxQp minQp static int ParseRoiCfgFile(FILE *fp, roiCfgParam *cfg_roi) { char* token = NULL; const char *delim = " "; static char lineStr[ENCODER_STRING_LEN_MAX*4] = {0}; char valueStr[ENCODER_STRING_LEN_MAX] = {0}; int i = 0; while (1) { if (i >= MAX_ROI_NUM) 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; } cfg_roi[i].enable = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_roi[i].x = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_roi[i].y = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_roi[i].w = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_roi[i].h = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_roi[i].region_inv = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_roi[i].QpMode = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_roi[i].roiQp = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_roi[i].lossless = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_roi[i].EncBiasMode = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_roi[i].maxQp = atoi(token); token = strtok(NULL, delim); if (token == NULL) { lineStr[0] = 0x0; continue; } cfg_roi[i].minQp = atoi(token); i++; cfg_roi[0].roiNum++; 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; } }