📄 libmp4enc.c
字号:
#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <sys/mman.h>#include <sys/socket.h>#include <netinet/in.h>#include <sys/types.h>#include <unistd.h>//#include "yuv2yuv.h"#include "dmablib.h" #include "basetype.h"#include "libmp4enc.h"#include "MP4EncApi.h"#define STRMBUFSIZE 100*1024 /* Encoder variables/structs */MP4API_EncInput encInp;MP4API_EncOutput encOut;/* Stream variables */unsigned int* pStrm = NULL; /* variables for linear memory */DMABUF_T physMem;int dmabHandle = 0;int max_iframe_interval;int y_max,x_max;/************************************************************************/void* wkads_mp4_encoder_init(MP4API_EncScheme encode_scheme){ int ret,i; int done = 0; unsigned int vop = 0; static int iFrame = 0; void* pEncInst = NULL; MP4API_EncParam_ErrorTools params; switch(encode_scheme){ case MP4API_ENC_SCHEME_QCIF_15FPS_64KB_PLAIN: case MP4API_ENC_SCHEME_QCIF_15FPS_64KB_VP: case MP4API_ENC_SCHEME_QCIF_10FPS_32KB_VP: case MP4API_ENC_SCHEME_QCIF_30FPS_128KB_VP: case MP4API_ENC_SCHEME_QCIF_15FPS_64KB_SVH: y_max = 144; x_max = 176; break; case MP4API_ENC_SCHEME_CIF_15FPS_128KB_VP: case MP4API_ENC_SCHEME_CIF_15FPS_384KB_VP: case MP4API_ENC_SCHEME_CIF_15FPS_384KB_PLAIN: case MP4API_ENC_SCHEME_CIF_30FPS_384KB_VP: case MP4API_ENC_SCHEME_CIF_15FPS_384KB_SVH: y_max = 288; x_max = 352; break; case MP4API_ENC_SCHEME_QVGA_15FPS_384KB_VP: y_max = 240; x_max = 320; break; default: printf("Sorry,the format could't be supported!\n"); return 0; } /* allocate linear buffer for the YUV data */ dmabHandle = dmab_init(NULL,1); if (dmabHandle < 0) { printf("Linear memory handler init (dmab_init) failed\n"); return; } if (!dmab_get(dmabHandle, x_max*y_max*3/2, &physMem)) { printf("Failed to alloc physMem\n"); return; } /* allocate mpeg4 stream buffer */ pStrm = malloc(STRMBUFSIZE); if(pStrm == NULL) { printf("Cannot allocate memory for MPEG-4 stream\n"); dmab_free(dmabHandle, &physMem); dmab_exit(dmabHandle); return; } /* initialize encoder */ pEncInst = MP4API_EncoderInit(encode_scheme); if(pEncInst == NULL) { printf("Cannot initialize MPEG-4 encoder\n"); dmab_free(dmabHandle, &physMem); dmab_exit(dmabHandle); free(pStrm); return; } /* configure encoder */ /* Disable video packets */ params.u8_VideoPacketsEnable = 0; /* disabled */ params.u8_DataPartitionEnable = 0; /* disabled */ params.u8_RVlcEnable = 0; /* disabled */ ret = MP4API_EncoderConfig(pEncInst,¶ms, MP4API_ENC_PID_ERROR_TOOLS); if(ret) { printf("Cannot reconfigure MPEG-4 encoder\n"); dmab_free(dmabHandle, &physMem); dmab_exit(dmabHandle); free(pStrm); MP4API_EncoderShutdown(pEncInst); return; } return pEncInst;}int wkads_mp4_encode_start_stream(void *pEncInst,unsigned char *pOutput){ int ret; /* Start stream */ encInp.pu32_Picture = (unsigned int*)physMem.phys; encInp.u32_TimeIncrement = 0; encInp.pu32_OutputBuffer = pStrm; encInp.u32_OutBufSize = STRMBUFSIZE; encInp.VopCodingType = MP4API_ENC_VOP_CODING_TYPE_INTRA; /* 1st = intra */ ret = MP4API_EncoderStartStream(pEncInst, &encInp, &encOut); memcpy(pOutput,(u8 *)encInp.pu32_OutputBuffer,encOut.u32_Size); return encOut.u32_Size; }int wkads_mp4_encoder_config(void *pEncInst,mp4_encoder_para *para){ u32 tmp; u32 bps = para->bitrate; u32 rvlc = para->rvlc; u32 dp = para->dp; u32 qp = para->qp; u32 vp_size = para->vp_size; u32 cir = para->cir; u32 fps = para->fps; int mode = para->mode; u32 prp = para->prp; u32 fourmotionvector = para->mv4; u32 ac_predict = para->ac_pre; u32 frm_skip = para->frm_skip; MP4API_EncParam_CameraStabilization cs; MP4API_EncParam_RateControl rc; MP4API_EncParam_PictureSize ps; MP4API_EncParam_ErrorTools errt; MP4API_EncParam_ShortVideoHeader svht; MP4API_EncParam_CompressionParameters cp; int rt; max_iframe_interval = para->i_frame_interval; /* set cir */ MP4API_EncParam_CyclicIntraRefresh cir_cfg; MP4API_EncoderGetInfo(pEncInst, &cir_cfg, MP4API_ENC_PID_CYCLIC_INTRA_REFRESH); if (cir){ cir_cfg.u32_CirEnable = 1; cir_cfg.u32_IntraPerVop = cir; } else { cir_cfg.u32_CirEnable = 0; cir_cfg.u32_IntraPerVop = 0; } rt= MP4API_EncoderConfig(pEncInst, &cir_cfg,MP4API_ENC_PID_CYCLIC_INTRA_REFRESH); if (rt) { printf("enccfg cir %d err %X\n", cir, rt); } /* set rate control and set default QP */ MP4API_EncoderGetInfo(pEncInst, &rc, MP4API_ENC_PID_RATE_CTRL); rc.u32_RateCtrlEnable = para->rc; if (bps) { rc.u32_TargetBitRate = bps * 1000; } /* vbv setting */ if(bps) { /* cbr mode */ if(bps >= 384) { if(bps <= 2000) { /* main profile level 2 */ rc.vbv_params.u32_Set = 1; rc.vbv_params.u32_BufSize = 80*16384; rc.vbv_params.u32_InitOccupancy = 80*170*64; } else { printf("CBR bit rate is too high!\n"); } } } else { /* vbr mode */ if(qp <= 5) { /* main profile level 2 */ rc.vbv_params.u32_Set = 1; rc.vbv_params.u32_BufSize = 80*16384; rc.vbv_params.u32_InitOccupancy = 80*170*64; } } /* ac prediction */ if(ac_predict) { MP4API_EncoderGetInfo(pEncInst, &cp, MP4API_ENC_PID_COMPRESSION_PARAMS); cp.u8_AcPredictionEnable = ac_predict; rt = MP4API_EncoderConfig(pEncInst, &cp, MP4API_ENC_PID_COMPRESSION_PARAMS); if (rt) { printf("enccfg cp err %X\n", rt); } } /* frame rate */ if (fps) { rc.u32_TargetFrameRate = fps; } else { fps = rc.u32_TargetFrameRate; } /* default qp */ if (qp) { rc.u32_DefaultQuantParameter = qp; } /* frame skip */ if(frm_skip) { rc.u32_FrameSkipEnable = 1; } else { rc.u32_FrameSkipEnable = 0; } /* 4MV */ if(fourmotionvector) { rc.u32_FourMotionVectorsEnable = 1; } else { rc.u32_FourMotionVectorsEnable = 0; } /* time resolution must be set before RC */ if (mode < 2) { tmp = fps; rt = MP4API_EncoderConfig(pEncInst, &tmp, MP4API_ENC_PID_TIME_RESOLUTION); if (rt) { printf("enccfg res %d err %X\n", tmp, rt); } } /* Rate ctrl setting */ rt = MP4API_EncoderConfig(pEncInst, &rc, MP4API_ENC_PID_RATE_CTRL); if (rt) { printf("enccfg rc err %X\n", rt); } /* VP size */ MP4API_EncoderGetInfo(pEncInst, &tmp, MP4API_ENC_PID_VIDEO_PACKET_SIZE); if (vp_size) { tmp = vp_size; } rt = MP4API_EncoderConfig(pEncInst, &tmp, MP4API_ENC_PID_VIDEO_PACKET_SIZE); if (rt) { printf("enccfg vpsize %d err %X\n", tmp, rt); }#if 0 MP4API_EncoderGetInfo(pEncInst, &errt, MP4API_ENC_PID_ERROR_TOOLS); if ((mode == 1 && !errt.u8_VideoPacketsEnable) || (mode != 1 && errt.u8_VideoPacketsEnable)) { errt.u8_VideoPacketsEnable ^= 1; rt = MP4API_EncoderConfig(pEncInst, &errt,MP4API_ENC_PID_ERROR_TOOLS); if (rt) { printf("enccfg vpmode %d err %X\n", errt.u8_VideoPacketsEnable, rt); } } /* error tools */ if(dp || rvlc) { if(errt.u8_VideoPacketsEnable) { /* dp and rvlc can be used in conjunction with vp only */ MP4API_EncoderGetInfo(pEncInst, &errt, MP4API_ENC_PID_ERROR_TOOLS); errt.u8_DataPartitionEnable &= dp; errt.u8_RVlcEnable &= dp&rvlc; MP4API_EncoderConfig(pEncInst, &errt, MP4API_ENC_PID_ERROR_TOOLS); } else { dp = 0; rvlc = 0; } }#endif /* preprocessing */ if(prp){ tmp = prp; rt = MP4API_EncoderConfig(pEncInst, &tmp, MP4API_ENC_PID_PREPROCESSING_ENABLE); } if (rt) { printf("enccfg prpen %d err %X\n", tmp, rt); } /* camera stabilization */#if 0 MP4API_EncoderGetInfo(pEncInst, &cs, MP4API_ENC_PID_CAM_STAB); cs.u32_CamStabEnable = 1; cs.u32_FrameWidth = 352; cs.u32_FrameHeight = 288; rt = MP4API_EncoderConfig(pEncInst, &cs, MP4API_ENC_PID_CAM_STAB); if (rt) { printf("enccfg camstab %d err %X\n", cs.u32_CamStabEnable, rt); }#endif return 0; }int wkads_mp4_encode(void *pEncInst, unsigned char* pInput, unsigned char* pOutput){ static int iFrame = 0; static int vop = 0; int ret,donae; static int count = 0; static int first = 1; //yuv4222yuv420(x_max,y_max,pInput,(unsigned char*)physMem.user); memcpy((unsigned char*)physMem.user, pInput, x_max*y_max*3/2); //physMem.user = pInput; /* Set encoder parameters */ encInp.pu32_Picture = (unsigned int*)physMem.phys; encInp.pu32_OutputBuffer = (unsigned int *)pOutput; //encInp.pu32_OutputBuffer = pStrm; encInp.u32_OutBufSize = STRMBUFSIZE; iFrame++; if(first) count++; if(iFrame == max_iframe_interval){ vop = 0; iFrame = 0; } if(count < 50) vop = 0; else first = 0; if(vop == 0) /* First VOP */ { /*aterst VOP must be always intra coded */ encInp.VopCodingType = MP4API_ENC_VOP_CODING_TYPE_INTRA; /* No previous VOPs => no time passed from prev */ encInp.u32_TimeIncrement = 0; vop = 1; } else { /* After first frame always use predicted inter frames. OK here but in real life there should be also some intra frames every now and then to enable jumpping in the stream (player seek) */ encInp.VopCodingType = MP4API_ENC_VOP_CODING_TYPE_INTER; //encInp.VopCodingType = MP4API_ENC_VOP_CODING_TYPE_INTRA; encInp.u32_TimeIncrement = 1; } ret = MP4API_Encode(pEncInst, &encInp, &encOut); if(encOut.Code != MP4API_ENC_PICTURE_READY){ //encInp.VopCodingType = MP4API_ENC_VOP_CODING_TYPE_INTRA; printf("Error in encoding!\n"); } if(encOut.Code != 0){ encInp.VopCodingType = MP4API_ENC_VOP_CODING_TYPE_INTRA; //printf("Error in encoding!\n"); } //memcpy(pOutput,(u8 *)encInp.pu32_OutputBuffer,encOut.u32_Size); return encOut.u32_Size;}int wkads_mp4_encoder_destroy(void *pEncInst,unsigned char *pOutput){ int ret; /* end stream */ ret = MP4API_EncoderEndStream(pEncInst, &encInp, &encOut); memcpy(pOutput,(u8*)encInp.pu32_OutputBuffer,encOut.u32_Size); /* Close files, free allocated resources */ dmab_free(dmabHandle, &physMem); dmab_exit(dmabHandle); free(pStrm); MP4API_EncoderShutdown(pEncInst); return encOut.u32_Size;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -