├── enc └── gx_enc_fast │ ├── parser.h │ ├── rate_control_gx_fast.h │ ├── gxvenclib_fast.h │ ├── parser.cpp │ ├── rate_control_gx_fast.cpp │ └── gxvenclib_fast.cpp ├── Android.mk ├── include ├── vpcodec_1_0.h ├── AML_HWEncoder.h └── enc_define.h ├── Makefile ├── enc_api.h ├── libvpcodec.cpp ├── enc_api.cpp └── AML_HWEncoder.cpp /enc/gx_enc_fast/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef _DUMP_H_ 2 | #define _DUMP_H_ 3 | 4 | extern int Parser_DumpInfo(gx_fast_enc_drv_t* p); 5 | #endif 6 | -------------------------------------------------------------------------------- /Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | include $(CLEAR_VARS) 3 | 4 | LOCAL_SRC_FILES := \ 5 | libvpcodec.cpp 6 | 7 | LOCAL_SRC_FILES += AML_HWEncoder.cpp \ 8 | enc_api.cpp \ 9 | enc/common/fill_buffer.cpp \ 10 | enc/m8_enc_fast/rate_control_m8_fast.cpp \ 11 | enc/m8_enc_fast/m8venclib_fast.cpp \ 12 | enc/m8_enc/dump.cpp \ 13 | enc/m8_enc/m8venclib.cpp \ 14 | enc/m8_enc/rate_control_m8.cpp \ 15 | enc/m8_enc/noise_reduction.cpp \ 16 | decoder/decoder.c \ 17 | decoder/amlv4l.c \ 18 | decoder/amvideo.c \ 19 | enc/gx_enc_fast/gxvenclib_fast.cpp \ 20 | enc/gx_enc_fast/rate_control_gx_fast.cpp \ 21 | enc/gx_enc_fast/parser.cpp 22 | 23 | LOCAL_SRC_FILES += enc/intra_search/pred.cpp \ 24 | enc/intra_search/pred_neon_asm.s 25 | 26 | ifneq (,$(wildcard vendor/amlogic/frameworks/av/LibPlayer)) 27 | LIBPLAYER_DIR:=$(TOP)/vendor/amlogic/frameworks/av/LibPlayer 28 | else 29 | LIBPLAYER_DIR:=$(TOP)/packages/amlogic/LibPlayer 30 | endif 31 | 32 | LOCAL_SHARED_LIBRARIES += libcutils \ 33 | libion \ 34 | libamplayer 35 | 36 | 37 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include \ 38 | $(LIBPLAYER_DIR)/amcodec/include \ 39 | $(TOP)/hardware/amlogic/gralloc \ 40 | $(LOCAL_PATH)/decoder 41 | 42 | LOCAL_ARM_MODE := arm 43 | LOCAL_MODULE:= libvpcodec 44 | LOCAL_MODULE_TAGS := optional 45 | LOCAL_PRELINK_MODULE := false 46 | include $(BUILD_SHARED_LIBRARY) 47 | 48 | -------------------------------------------------------------------------------- /enc/gx_enc_fast/rate_control_gx_fast.h: -------------------------------------------------------------------------------- 1 | #ifndef AMLOGIC_GX_FAST_RATECONTROL_ 2 | #define AMLOGIC_GX_FAST_RATECONTROL_ 3 | 4 | #include "gxvenclib_fast.h" 5 | 6 | typedef struct GxFastEncRateControl_s 7 | { 8 | bool rcEnable; /* enable rate control, '1' on, '0' const QP */ 9 | int initQP; /* initial QP */ 10 | int bitRate; /* target bit rate for the overall clip in bits/second*/ 11 | float frame_rate; /* frame rate */ 12 | int skip_next_frame; 13 | 14 | int32 cpbSize; /* coded picture buffer size in bytes */ 15 | 16 | /* this part comes from MPEG4 rate control */ 17 | int Rc; /*bits used for the current frame. It is the bit count obtained after encoding. */ 18 | 19 | /*If the macroblock is intra coded, the original spatial pixel values are summed.*/ 20 | int Qc; /*quantization level used for the current frame. */ 21 | int T; /*target bit to be used for the current frame.*/ 22 | int Bs; /*buffer size e.g., R/2 */ 23 | 24 | int numFrameBits; /* keep track of number of bits of the current frame */ 25 | int bitsPerFrame; 26 | 27 | /* BX rate control, something like TMN8 rate control*/ 28 | 29 | 30 | int encoded_frames; /* counter for all encoded frames */ 31 | /* End BX */ 32 | double average_rate; 33 | double average_delta; 34 | double reaction_rate; 35 | double reaction_delta; 36 | int reaction_ratio; 37 | double actual_quant; 38 | double average_qp; 39 | int last_IDR_bits; 40 | int last_pframe_bits; 41 | double actual_Qstep; 42 | int64_t buffer_fullness; 43 | int max_idr_qp; 44 | int max_p_qp; 45 | int last_IDR_qp_delta; 46 | int max_inc_qp_step; 47 | int max_dec_qp_step; 48 | 49 | bool refresh; 50 | bool force_IDR; 51 | } GxFastEncRateControl; 52 | 53 | extern AMVEnc_Status GxFastRCUpdateFrame(void *dev, void *rc, bool IDR, int* skip_num, int numFrameBits); 54 | extern AMVEnc_Status GxFastRCInitFrameQP(void *dev, void *rc,bool IDR,int bitrate, float frame_rate); 55 | extern AMVEnc_Status GxFastRCUpdateBuffer(void *dev, void *rc, int timecode, bool force_IDR); 56 | extern void GxFastCleanupRateControlModule(void *rc); 57 | extern void* GxFastInitRateControlModule(amvenc_initpara_t* init_para); 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /include/vpcodec_1_0.h: -------------------------------------------------------------------------------- 1 | #ifndef _INCLUDED_COM_VIDEOPHONE_CODEC 2 | #define _INCLUDED_COM_VIDEOPHONE_CODEC 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define vl_codec_handle_t long 9 | 10 | typedef enum vl_codec_id_e { 11 | CODEC_ID_NONE, 12 | CODEC_ID_VP8, 13 | CODEC_ID_H261, 14 | CODEC_ID_H263, 15 | CODEC_ID_H264, /* Currently, suport H264 only */ 16 | CODEC_ID_H265, 17 | 18 | } vl_codec_id_t; 19 | 20 | typedef enum vl_img_format_e 21 | { 22 | IMG_FMT_NONE, 23 | IMG_FMT_NV12, 24 | 25 | } vl_img_format_t; 26 | 27 | typedef enum vl_frame_type_e 28 | { 29 | FRAME_TYPE_NONE, 30 | FRAME_TYPE_AUTO, 31 | FRAME_TYPE_IDR, 32 | FRAME_TYPE_I, 33 | FRAME_TYPE_P, 34 | 35 | } vl_frame_type_t; 36 | 37 | /** 38 | * Get codec version info 39 | * 40 | *@return : codec version 41 | */ 42 | extern const char *vl_get_version(); 43 | 44 | /** 45 | * initialize encoder codec 46 | * 47 | *@param : codec_id 48 | *@param : width 49 | *@param : height 50 | *@param : frame_rate 51 | *@param : bit_rate 52 | *@param : gop GOP value 53 | *@param : img_format 54 | *@return : if success return encoder codec handle,else return <= 0 55 | */ 56 | extern vl_codec_handle_t vl_video_encoder_init(vl_codec_id_t codec_id, int width, int height, int frame_rate, int bit_rate, int gop, vl_img_format_t img_format); 57 | 58 | /** 59 | * encode image 60 | * 61 | *@param : handle: encoder handle 62 | *@param : type: frame tpye 63 | *@param : in: input data 64 | *@param : in_size: input data size (not used currently) 65 | *@param : out: out put data 66 | *@return :if success return the data lenght of out put data, else return <= 0 67 | */ 68 | extern int vl_video_encoder_encode(vl_codec_handle_t handle, vl_frame_type_t type, char *in, int in_size, char **out); 69 | 70 | /** 71 | * destroy encoder 72 | * 73 | *@param :handle: encoder handle 74 | *@return :if succes return 1,else 0 75 | */ 76 | extern int vl_video_encoder_destory(vl_codec_handle_t handle); 77 | 78 | 79 | #ifdef __cplusplus 80 | } 81 | #endif 82 | 83 | #endif /* _INCLUDED_COM_VIDEOPHONE_CODEC */ 84 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # object building. 2 | ifeq ($(ARM), 1) 3 | CC=arm-none-linux-gnueabi-gcc 4 | AR=arm-none-linux-gnueabi-ar 5 | else 6 | CC=gcc 7 | AR=ar 8 | endif 9 | 10 | TARGET= libvpcodec.so 11 | 12 | CODEOBJECT = AML_HWEncoder.o enc_api.o gxvenclib_fast.o rate_control_gx_fast.o parser.o libvpcodec.o \ 13 | # rate_control_m8_fasth.o m8venclib_fast.o dump.o m8venclib.o rate_control_m8.o noise_reduction.o fill_buffer.o pred_neon_asm.o 14 | 15 | libvpcodec.so: $(CODEOBJECT) 16 | $(CC) $(CFLAGS) $(CODEOBJECT) -o $(TARGET) 17 | 18 | AML_HWEncoder.o: AML_HWEncoder.cpp include/AML_HWEncoder.h 19 | $(CC) $(CFLAGS) -c $< 20 | 21 | enc_api.o: enc_api.cpp enc_api.h 22 | $(CC) $(CFLAGS) -c $< 23 | 24 | #fill_buffer.o: enc/common/fill_buffer.cpp 25 | # $(CC) $(CFLAGS) -c $< 26 | # 27 | #rate_control_m8_fasth.o: .enc/m8_enc_fast/rate_control_m8_fastcpp .enc/m8_enc_fast/rate_control_m8_fasth 28 | # $(CC) $(CFLAGS) -c $< 29 | # 30 | #m8venclib_fast.o: enc/m8_enc_fast/m8venclib_fast.cpp enc/m8_enc_fast/m8venclib_fast.h 31 | # $(CC) $(CFLAGS) -c $< 32 | # 33 | #dump.o: enc/m8_enc/dump.cpp enc/m8_enc/dump.h 34 | # $(CC) $(CFLAGS) -c $< 35 | # 36 | #m8venclib.o: enc/m8_enc/m8venclib.cpp enc/m8_enc/m8venclib.h 37 | # $(CC) $(CFLAGS) -c $< 38 | # 39 | #rate_control_m8.o: enc/m8_enc/rate_control_m8.cpp enc/m8_enc/rate_control_m8.h 40 | # $(CC) $(CFLAGS) -c $< 41 | # 42 | #noise_reduction.o: enc/m8_enc/noise_reduction.cpp enc/m8_enc/noise_reduction.h 43 | # $(CC) $(CFLAGS) -c $< 44 | # 45 | gxvenclib_fast.o: enc/gx_enc_fast/gxvenclib_fast.cpp enc/gx_enc_fast/gxvenclib_fast.h 46 | $(CC) $(CFLAGS) -c $< 47 | 48 | rate_control_gx_fast.o: enc/gx_enc_fast/rate_control_gx_fast.cpp enc/gx_enc_fast/rate_control_gx_fast.h 49 | $(CC) $(CFLAGS) -c $< 50 | 51 | parser.o: enc/gx_enc_fast/parser.cpp enc/gx_enc_fast/parser.h 52 | $(CC) $(CFLAGS) -c $< 53 | 54 | pred.o: enc/intra_search/pred.cpp enc/intra_search/pred.h 55 | $(CC) $(CFLAGS) -c $< 56 | 57 | #pred_neon_asm.o: enc/intra_search/pred_neon_asm.s 58 | # $(CC) $(CFLAGS) -c $< 59 | 60 | libvpcodec.o: libvpcodec.cpp include/vpcodec_1_0.h 61 | $(CC) $(CFLAGS) -c $< 62 | 63 | LDFLAGS += -lm -lrt 64 | ifeq ($(ARM), 1) 65 | CFLAGS+=-DARM 66 | else 67 | CFLAGS+=-O2 68 | endif 69 | 70 | ifeq ($(REAP), 1) 71 | CFLAGS+=-DREAP_MODE 72 | endif 73 | 74 | CFLAGS+= -Wall -g -ftree-vectorize -ffast-math -Iinclude -shared -fPIC 75 | 76 | clean: 77 | -rm -f *.o 78 | -rm -f $(TARGET) 79 | 80 | 81 | -------------------------------------------------------------------------------- /enc_api.h: -------------------------------------------------------------------------------- 1 | #ifndef AMLOGIC_ENCODER_API_ 2 | #define AMLOGIC_ENCODER_API_ 3 | 4 | #include "AML_HWEncoder.h" 5 | #include "enc_define.h" 6 | 7 | typedef void* (*AMVencHWFunc_Init)(int fd, amvenc_initpara_t* init_para); 8 | typedef AMVEnc_Status (*AMVencHWFunc_InitFrame)(void *dev, ulong *yuv, AMVEncBufferType type, AMVEncFrameFmt fmt, bool IDRframe); 9 | typedef AMVEnc_Status (*AMVencHWFunc_EncodeSPS_PPS)(void *dev, unsigned char* outptr,int* datalen); 10 | typedef AMVEnc_Status (*AMVencHWFunc_EncodeSlice)(void *dev, unsigned char* outptr,int* datalen, bool re_encode); 11 | typedef AMVEnc_Status (*AMVencHWFunc_CommitEncode)(void *dev, bool IDR); 12 | typedef void (*AMVencHWFunc_Release)(void *dev); 13 | 14 | typedef struct tagAMVencHWFuncPtr 15 | { 16 | AMVencHWFunc_Init Initialize; 17 | AMVencHWFunc_InitFrame InitFrame; 18 | AMVencHWFunc_EncodeSPS_PPS EncodeSPS_PPS; 19 | AMVencHWFunc_EncodeSlice EncodeSlice; 20 | AMVencHWFunc_CommitEncode Commit; 21 | AMVencHWFunc_Release Release; 22 | } AMVencHWFuncPtr; 23 | 24 | 25 | typedef void* (*AMVencRCFunc_Init)(amvenc_initpara_t* init_para); 26 | typedef AMVEnc_Status (*AMVencRCFunc_PreControl)(void *dev, void *rc, int frameInc, bool force_IDR); 27 | typedef AMVEnc_Status (*AMVencRCFunc_PostControl)(void *dev, void *rc, bool IDR, int* skip_num, int numFrameBits); 28 | typedef AMVEnc_Status (*AMVencFunc_InitFrameQP)(void *dev, void *rc,bool IDR, int bitrate, float frame_rate); 29 | typedef void (*AMVencRCFunc_Release)(void *rc); 30 | 31 | typedef struct tagAMVencRCFuncPtr 32 | { 33 | AMVencRCFunc_Init Initialize; 34 | AMVencRCFunc_PreControl PreControl; 35 | AMVencRCFunc_PostControl PostControl; 36 | AMVencFunc_InitFrameQP InitFrameQP; 37 | AMVencRCFunc_Release Release; 38 | } AMVencRCFuncPtr; 39 | 40 | extern AMVEnc_Status AMInitRateControlModule(amvenc_hw_t* hw_info); 41 | extern AMVEnc_Status AMPreRateControl(amvenc_hw_t* hw_info, int frameInc, bool force_IDR); 42 | extern AMVEnc_Status AMPostRateControl(amvenc_hw_t* hw_info, bool IDR, int* skip_num, int numFrameBits); 43 | extern AMVEnc_Status AMRCInitFrameQP(amvenc_hw_t* hw_info, bool IDR, int bitrate, float frame_rate); 44 | extern void AMCleanupRateControlModule(amvenc_hw_t* hw_info); 45 | 46 | extern AMVEnc_Status InitAMVEncode(amvenc_hw_t* hw_info, int force_mode); 47 | extern AMVEnc_Status AMVEncodeInitFrame(amvenc_hw_t* hw_info, ulong *yuv, AMVEncBufferType type, AMVEncFrameFmt fmt, bool IDRframe); 48 | extern AMVEnc_Status AMVEncodeSPS_PPS(amvenc_hw_t* hw_info, unsigned char* outptr,int* datalen); 49 | extern AMVEnc_Status AMVEncodeSlice(amvenc_hw_t* hw_info, unsigned char* outptr,int* datalen, bool re_encode); 50 | extern AMVEnc_Status AMVEncodeCommit(amvenc_hw_t* hw_info, bool IDR); 51 | extern void UnInitAMVEncode(amvenc_hw_t* hw_info); 52 | #endif 53 | -------------------------------------------------------------------------------- /enc/gx_enc_fast/gxvenclib_fast.h: -------------------------------------------------------------------------------- 1 | #ifndef AML_VIDEO_ENCODER_GX_FAST_ 2 | #define AML_VIDEO_ENCODER_GX_FAST_ 3 | 4 | #include 5 | #include 6 | #include "AML_HWEncoder.h" 7 | #include "enc_define.h" 8 | 9 | #define FASTGX_AVC_IOC_MAGIC 'E' 10 | 11 | #define FASTGX_AVC_IOC_GET_ADDR _IOW(FASTGX_AVC_IOC_MAGIC, 0x00, unsigned int) 12 | #define FASTGX_AVC_IOC_INPUT_UPDATE _IOW(FASTGX_AVC_IOC_MAGIC, 0x01, unsigned int) 13 | #define FASTGX_AVC_IOC_NEW_CMD _IOW(FASTGX_AVC_IOC_MAGIC, 0x02, unsigned int) 14 | #define FASTGX_AVC_IOC_GET_STAGE _IOW(FASTGX_AVC_IOC_MAGIC, 0x03, unsigned int) 15 | #define FASTGX_AVC_IOC_GET_OUTPUT_SIZE _IOW(FASTGX_AVC_IOC_MAGIC, 0x04, unsigned int) 16 | #define FASTGX_AVC_IOC_CONFIG_INIT _IOW(FASTGX_AVC_IOC_MAGIC, 0x05, unsigned int) 17 | #define FASTGX_AVC_IOC_FLUSH_CACHE _IOW(FASTGX_AVC_IOC_MAGIC, 0x06, unsigned int) 18 | #define FASTGX_AVC_IOC_FLUSH_DMA _IOW(FASTGX_AVC_IOC_MAGIC, 0x07, unsigned int) 19 | #define FASTGX_AVC_IOC_GET_BUFFINFO _IOW(FASTGX_AVC_IOC_MAGIC, 0x08, unsigned int) 20 | #define FASTGX_AVC_IOC_SUBMIT_ENCODE_DONE _IOW(FASTGX_AVC_IOC_MAGIC, 0x09, unsigned int) 21 | #define FASTGX_AVC_IOC_READ_CANVAS _IOW(FASTGX_AVC_IOC_MAGIC, 0x0a, unsigned int) 22 | 23 | #define UCODE_MODE_FULL 0 24 | #define UCODE_MODE_SW_MIX 1 25 | 26 | typedef struct{ 27 | short mvx; 28 | short mvy; 29 | }mv_t; 30 | 31 | typedef struct{ 32 | unsigned char imode; 33 | unsigned char LPred[16]; 34 | unsigned char CPred; 35 | unsigned short sad; 36 | }intra_info_t; 37 | 38 | typedef struct{ 39 | mv_t mv[16]; 40 | unsigned short sad; 41 | }inter_info_t; 42 | 43 | typedef struct{ 44 | uint32_t mbx; 45 | uint32_t mby; 46 | unsigned char mb_type; 47 | 48 | unsigned char quant; 49 | unsigned char cbp; 50 | unsigned short bits; 51 | 52 | intra_info_t intra; 53 | inter_info_t inter; 54 | 55 | int final_sad; 56 | }mb_t; 57 | 58 | typedef struct 59 | { 60 | int pix_width; 61 | int pix_height; 62 | 63 | int mb_width; 64 | int mb_height; 65 | int mbsize; 66 | 67 | int framesize; 68 | AMVEncBufferType type; 69 | AMVEncFrameFmt fmt; 70 | uint32_t canvas; 71 | ulong plane[3]; 72 | } gx_fast_input_t; 73 | 74 | typedef struct{ 75 | unsigned char* addr; 76 | uint32_t size; 77 | }gx_fast_buff_t; 78 | 79 | typedef struct 80 | { 81 | int fd; 82 | bool IDRframe; 83 | bool mCancel; 84 | 85 | uint32_t enc_width; 86 | uint32_t enc_height; 87 | uint32_t quant; 88 | 89 | int fix_qp; 90 | int nr_mode; 91 | 92 | bool gotSPS; 93 | uint32_t sps_len; 94 | bool gotPPS; 95 | uint32_t pps_len; 96 | 97 | uint32_t total_encode_frame; 98 | uint32_t total_encode_time; 99 | 100 | gx_fast_input_t src; 101 | 102 | uint32_t me_weight; 103 | uint32_t i4_weight; 104 | uint32_t i16_weight; 105 | 106 | gx_fast_buff_t mmap_buff; 107 | gx_fast_buff_t input_buf; 108 | gx_fast_buff_t ref_buf_y[2]; 109 | gx_fast_buff_t ref_buf_uv[2]; 110 | gx_fast_buff_t output_buf; 111 | gx_fast_buff_t dump_buf; 112 | 113 | mb_t* mb_info; 114 | 115 | bool logtime; 116 | struct timeval start_test; 117 | struct timeval end_test; 118 | }gx_fast_enc_drv_t; 119 | 120 | extern void* GxInitFastEncode(int fd, amvenc_initpara_t* init_para); 121 | extern AMVEnc_Status GxFastEncodeInitFrame(void *dev, ulong *yuv, AMVEncBufferType type, AMVEncFrameFmt fmt,bool IDRframe); 122 | extern AMVEnc_Status GxFastEncodeSPS_PPS(void *dev, unsigned char* outptr,int* datalen); 123 | extern AMVEnc_Status GxFastEncodeSlice(void *dev, unsigned char* outptr,int* datalen, bool re_encode); 124 | extern AMVEnc_Status GxFastEncodeCommit(void* dev, bool IDR); 125 | extern void GxUnInitFastEncode(void *dev); 126 | 127 | #endif 128 | -------------------------------------------------------------------------------- /include/AML_HWEncoder.h: -------------------------------------------------------------------------------- 1 | #ifndef AMLOGIC_HWENCODER_ 2 | #define AMLOGIC_HWENCODER_ 3 | 4 | #include "enc_define.h" 5 | 6 | typedef struct amvenc_initpara_s 7 | { 8 | uint32 enc_width; 9 | uint32 enc_height; 10 | uint32 nSliceHeaderSpacing; 11 | uint32 MBsIntraRefresh; 12 | uint32 MBsIntraOverlap; 13 | int initQP; 14 | bool rcEnable; 15 | uint32 bitrate; 16 | uint32 frame_rate; 17 | uint32 cpbSize; 18 | bool bitrate_scale; 19 | uint8 encode_once; 20 | }amvenc_initpara_t; 21 | 22 | typedef struct amvenc_hw_s 23 | { 24 | ENC_DEV_TYPE dev_id; 25 | int dev_fd; 26 | void* rc_data; 27 | void* dev_data; 28 | amvenc_initpara_t init_para; 29 | }amvenc_hw_t; 30 | 31 | typedef struct FrameIO_s 32 | { 33 | ulong YCbCr[3]; 34 | AMVEncBufferType type; 35 | AMVEncFrameFmt fmt; 36 | int pitch; 37 | int height; 38 | uint32 coding_order; 39 | uint32 disp_order; 40 | uint is_reference; 41 | uint32 coding_timestamp; 42 | uint32 op_flag; 43 | uint32 canvas; 44 | uint32 bitrate; 45 | float frame_rate; 46 | uint32 scale_width; 47 | uint32 scale_height; 48 | uint32 crop_left; 49 | uint32 crop_right; 50 | uint32 crop_top; 51 | uint32 crop_bottom; 52 | }AMVEncFrameIO; 53 | 54 | typedef struct EncParams_s 55 | { 56 | /* if profile/level is set to zero, encoder will choose the closest one for you */ 57 | AVCProfile profile; /* profile of the bitstream to be compliant with*/ 58 | AVCLevel level; /* level of the bitstream to be compliant with*/ 59 | 60 | int width; /* width of an input frame in pixel */ 61 | int height; /* height of an input frame in pixel */ 62 | 63 | int num_ref_frame; /* number of reference frame used */ 64 | int num_slice_group; /* number of slice group */ 65 | 66 | uint32 nSliceHeaderSpacing; 67 | 68 | AVCFlag auto_scd; /* scene change detection on or off */ 69 | int idr_period; /* idr frame refresh rate in number of target encoded frame (no concept of actual time).*/ 70 | 71 | AVCFlag fullsearch; /* enable full-pel full-search mode */ 72 | int search_range; /* search range for motion vector in (-search_range,+search_range) pixels */ 73 | //AVCFlag sub_pel; /* enable sub pel prediction */ 74 | //AVCFlag submb_pred; /* enable sub MB partition mode */ 75 | 76 | AVCFlag rate_control; /* rate control enable, on: RC on, off: constant QP */ 77 | int initQP; /* initial QP */ 78 | uint32 bitrate; /* target encoding bit rate in bits/second */ 79 | uint32 CPB_size; /* coded picture buffer in number of bits */ 80 | uint32 init_CBP_removal_delay; /* initial CBP removal delay in msec */ 81 | 82 | uint32 frame_rate; /* frame rate in the unit of frames per 1000 second */ 83 | /* note, frame rate is only needed by the rate control, AVC is timestamp agnostic. */ 84 | 85 | uint32 MBsIntraRefresh; 86 | uint32 MBsIntraOverlap; 87 | 88 | AVCFlag out_of_band_param_set; /* flag to set whether param sets are to be retrieved up front or not */ 89 | AVCFlag FreeRun; 90 | AVCFlag BitrateScale; 91 | uint32 dev_id; /* ID to identify the hardware encoder version */ 92 | uint8 encode_once; /* flag to indicate encode once or twice */ 93 | } AMVEncParams; 94 | 95 | typedef struct{ 96 | uint32 enc_width; 97 | uint32 enc_height; 98 | 99 | AMVEnc_State state; 100 | 101 | AVCFlag outOfBandParamSet; 102 | AVCFlag fullsearch_enable; 103 | AVCFlag scdEnable; 104 | int search_range; 105 | bool rcEnable; /* rate control enable, on: RC on, off: constant QP */ 106 | int initQP; /* initial QP */ 107 | uint32 bitrate; /* target encoding bit rate in bits/second */ 108 | uint32 cpbSize; /* coded picture buffer in number of bits */ 109 | uint32 initDelayOffset; /* initial CBP removal delay in msec */ 110 | 111 | AVCNalUnitType nal_unit_type; 112 | AVCSliceType slice_type; 113 | 114 | uint32 nSliceHeaderSpacing; 115 | uint32 MBsIntraRefresh; 116 | uint32 MBsIntraOverlap; 117 | 118 | uint32 coding_order; 119 | uint32 modTimeRef; /* Reference modTime update every I-Vop*/ 120 | uint32 wrapModTime; /* Offset to modTime Ref, rarely used */ 121 | 122 | uint32 frame_rate; /* frame rate */ 123 | int idrPeriod; /* IDR period in number of frames */ 124 | bool first_frame; /* a flag for the first frame */ 125 | 126 | int skip_next_frame; 127 | int late_frame_count; 128 | 129 | uint prevProcFrameNum; /* previously processed frame number, could be skipped */ 130 | uint prevCodedFrameNum; /* previously encoded frame number */ 131 | 132 | uint prevProcFrameNumOffset; 133 | uint32 lastTimeRef; 134 | bool freerun; 135 | 136 | amvenc_hw_t hw_info; 137 | }amvenc_info_t; 138 | 139 | typedef struct AMVEncHandle_s 140 | { 141 | void *object; 142 | void *userData; 143 | uint32 debugEnable; 144 | 145 | AMVEncParams mEncParams; 146 | bool mSpsPpsHeaderReceived; 147 | uint8_t mSPSPPSDataSize; 148 | uint8_t *mSPSPPSData; 149 | int32_t mNumInputFrames; 150 | bool mKeyFrameRequested; 151 | } AMVEncHandle; 152 | 153 | extern AMVEnc_Status AML_HWEncInitialize(AMVEncHandle *Handle, AMVEncParams *encParam, bool* has_mix, int force_mode); 154 | extern AMVEnc_Status AML_HWSetInput(AMVEncHandle *Handle, AMVEncFrameIO *input); 155 | extern AMVEnc_Status AML_HWEncNAL(AMVEncHandle *Handle, unsigned char *buffer, unsigned int *buf_nal_size, int *nal_type); 156 | extern AMVEnc_Status AML_HWEncRelease(AMVEncHandle *Handle); 157 | 158 | #endif 159 | -------------------------------------------------------------------------------- /libvpcodec.cpp: -------------------------------------------------------------------------------- 1 | #include "vpcodec_1_0.h" 2 | #include 3 | #include 4 | //#include 5 | 6 | #include 7 | #include 8 | 9 | const char version[] = "Amlogic libvpcodec version 1.0"; 10 | 11 | const char *vl_get_version() 12 | { 13 | return version; 14 | } 15 | 16 | int initEncParams(AMVEncHandle *handle, int width, int height, int frame_rate, int bit_rate, int gop) 17 | { 18 | memset(&(handle->mEncParams), 0, sizeof(AMVEncParams)); 19 | //ALOGD("bit_rate:%d", bit_rate); 20 | if ((width % 16 != 0 || height % 2 != 0)) 21 | { 22 | //ALOGE("Video frame size %dx%d must be a multiple of 16", width, height); 23 | return -1; 24 | } 25 | else if (height % 16 != 0) 26 | { 27 | //ALOGD("Video frame height is not standard:%d", height); 28 | } 29 | else 30 | { 31 | //ALOGD("Video frame size is %d x %d", width, height); 32 | } 33 | handle->mEncParams.rate_control = AVC_ON; 34 | handle->mEncParams.initQP = 0; 35 | handle->mEncParams.init_CBP_removal_delay = 1600; 36 | handle->mEncParams.auto_scd = AVC_ON; 37 | handle->mEncParams.out_of_band_param_set = AVC_ON; 38 | handle->mEncParams.num_ref_frame = 1; 39 | handle->mEncParams.num_slice_group = 1; 40 | handle->mEncParams.nSliceHeaderSpacing = 0; 41 | handle->mEncParams.fullsearch = AVC_OFF; 42 | handle->mEncParams.search_range = 16; 43 | //handle->mEncParams.sub_pel = AVC_OFF; 44 | //handle->mEncParams.submb_pred = AVC_OFF; 45 | handle->mEncParams.width = width; 46 | handle->mEncParams.height = height; 47 | handle->mEncParams.bitrate = bit_rate; 48 | handle->mEncParams.frame_rate = 1000 * frame_rate; // In frames/ms! 49 | handle->mEncParams.CPB_size = (uint32)(bit_rate >> 1); 50 | handle->mEncParams.FreeRun = AVC_OFF; 51 | handle->mEncParams.MBsIntraRefresh = 0; 52 | handle->mEncParams.MBsIntraOverlap = 0; 53 | // Set IDR frame refresh interval 54 | if ((unsigned) gop == 0xffffffff) 55 | { 56 | handle->mEncParams.idr_period = -1;//(mIDRFrameRefreshIntervalInSec * mVideoFrameRate); 57 | } 58 | else if (gop == 0) 59 | { 60 | handle->mEncParams.idr_period = 0; // All I frames 61 | } 62 | else 63 | { 64 | handle->mEncParams.idr_period = gop + 1; 65 | } 66 | // Set profile and level 67 | handle->mEncParams.profile = AVC_BASELINE; 68 | handle->mEncParams.level = AVC_LEVEL4; 69 | handle->mEncParams.initQP = 30; 70 | handle->mEncParams.BitrateScale = AVC_OFF; 71 | return 0; 72 | } 73 | 74 | 75 | vl_codec_handle_t vl_video_encoder_init(vl_codec_id_t codec_id, int width, int height, int frame_rate, int bit_rate, int gop, vl_img_format_t img_format) 76 | { 77 | int ret; 78 | AMVEncHandle *mHandle = new AMVEncHandle; 79 | bool has_mix = false; 80 | if (mHandle == NULL) 81 | goto exit; 82 | memset(mHandle, 0, sizeof(AMVEncHandle)); 83 | ret = initEncParams(mHandle, width, height, frame_rate, bit_rate, gop); 84 | if (ret < 0) 85 | goto exit; 86 | ret = AML_HWEncInitialize(mHandle, &(mHandle->mEncParams), &has_mix, 2); 87 | if (ret < 0) 88 | goto exit; 89 | mHandle->mSpsPpsHeaderReceived = false; 90 | mHandle->mNumInputFrames = -1; // 1st two buffers contain SPS and PPS 91 | return (vl_codec_handle_t) mHandle; 92 | exit: 93 | if (mHandle != NULL) 94 | delete mHandle; 95 | return (vl_codec_handle_t) NULL; 96 | } 97 | 98 | 99 | 100 | int vl_video_encoder_encode(vl_codec_handle_t codec_handle, vl_frame_type_t frame_type, char *in, int in_size, char **out) 101 | { 102 | int ret; 103 | uint8_t *outPtr = NULL; 104 | uint32_t dataLength = 0; 105 | int type; 106 | AMVEncHandle *handle = (AMVEncHandle *)codec_handle; 107 | if (!handle->mSpsPpsHeaderReceived) 108 | { 109 | ret = AML_HWEncNAL(handle, (unsigned char *)*out, (unsigned int *)&in_size/*should be out size*/, &type); 110 | if (ret == AMVENC_SUCCESS) 111 | { 112 | handle->mSPSPPSDataSize = 0; 113 | handle->mSPSPPSData = (uint8_t *)malloc(in_size); 114 | if (handle->mSPSPPSData) 115 | { 116 | handle->mSPSPPSDataSize = in_size; 117 | memcpy(handle->mSPSPPSData, (unsigned char *)*out, handle->mSPSPPSDataSize); 118 | //ALOGI("get mSPSPPSData size= %d at line %d \n", handle->mSPSPPSDataSize, __LINE__); 119 | } 120 | handle->mNumInputFrames = 0; 121 | handle->mSpsPpsHeaderReceived = true; 122 | } 123 | else 124 | { 125 | //ALOGE("Encode SPS and PPS error, encoderStatus = %d. handle: %p", ret, (void *)handle); 126 | return -1; 127 | } 128 | } 129 | if (handle->mNumInputFrames >= 0) 130 | { 131 | AMVEncFrameIO videoInput; 132 | memset(&videoInput, 0, sizeof(videoInput)); 133 | videoInput.height = handle->mEncParams.height; 134 | videoInput.pitch = ((handle->mEncParams.width + 15) >> 4) << 4; 135 | /* TODO*/ 136 | videoInput.bitrate = handle->mEncParams.bitrate; 137 | videoInput.frame_rate = handle->mEncParams.frame_rate / 1000; 138 | videoInput.coding_timestamp = handle->mNumInputFrames * 1000 / videoInput.frame_rate; // in ms 139 | videoInput.fmt = AMVENC_NV21; 140 | videoInput.YCbCr[0] = (unsigned long)in; 141 | videoInput.YCbCr[1] = (unsigned long)(videoInput.YCbCr[0] + videoInput.height * videoInput.pitch); 142 | videoInput.YCbCr[2] = 0; 143 | videoInput.canvas = 0xffffffff; 144 | videoInput.type = VMALLOC_BUFFER; 145 | videoInput.disp_order = handle->mNumInputFrames; 146 | videoInput.op_flag = 0; 147 | if (handle->mKeyFrameRequested == true) 148 | { 149 | videoInput.op_flag = AMVEncFrameIO_FORCE_IDR_FLAG; 150 | handle->mKeyFrameRequested = false; 151 | } 152 | ret = AML_HWSetInput(handle, &videoInput); 153 | if (ret == AMVENC_SUCCESS || ret == AMVENC_NEW_IDR) 154 | { 155 | ++(handle->mNumInputFrames); 156 | 157 | if (ret == AMVENC_NEW_IDR) 158 | { 159 | outPtr = (uint8_t *) *out + handle->mSPSPPSDataSize; 160 | dataLength = /*should be out size */in_size - handle->mSPSPPSDataSize; 161 | } 162 | else 163 | { 164 | outPtr = (uint8_t *) *out; 165 | dataLength = /*should be out size */in_size; 166 | } 167 | } 168 | else if (ret < AMVENC_SUCCESS) 169 | { 170 | //ALOGE("encoderStatus = %d at line %d, handle: %p", ret, __LINE__, (void *)handle); 171 | return -1; 172 | } 173 | 174 | ret = AML_HWEncNAL(handle, (unsigned char *)outPtr, (unsigned int *)&dataLength, &type); 175 | if (ret == AMVENC_PICTURE_READY) 176 | { 177 | if (type == AVC_NALTYPE_IDR) 178 | { 179 | if (handle->mSPSPPSData) 180 | { 181 | memcpy((uint8_t *) *out, handle->mSPSPPSData, handle->mSPSPPSDataSize); 182 | dataLength += handle->mSPSPPSDataSize; 183 | //ALOGI("copy mSPSPPSData to buffer size= %d at line %d \n", handle->mSPSPPSDataSize, __LINE__); 184 | } 185 | } 186 | } 187 | else if ((ret == AMVENC_SKIPPED_PICTURE) || (ret == AMVENC_TIMEOUT)) 188 | { 189 | dataLength = 0; 190 | if (ret == AMVENC_TIMEOUT) 191 | { 192 | handle->mKeyFrameRequested = true; 193 | ret = AMVENC_SKIPPED_PICTURE; 194 | } 195 | //ALOGD("ret = %d at line %d, handle: %p", ret, __LINE__, (void *)handle); 196 | } 197 | else if (ret != AMVENC_SUCCESS) 198 | { 199 | dataLength = 0; 200 | } 201 | 202 | if (ret < AMVENC_SUCCESS) 203 | { 204 | //ALOGE("encoderStatus = %d at line %d, handle: %p", ret , __LINE__, (void *)handle); 205 | return -1; 206 | } 207 | } 208 | return dataLength; 209 | } 210 | 211 | int vl_video_encoder_destory(vl_codec_handle_t codec_handle) 212 | { 213 | AMVEncHandle *handle = (AMVEncHandle *)codec_handle; 214 | AML_HWEncRelease(handle); 215 | if (handle->mSPSPPSData) 216 | free(handle->mSPSPPSData); 217 | if (handle) 218 | delete handle; 219 | return 1; 220 | } 221 | -------------------------------------------------------------------------------- /enc/gx_enc_fast/parser.cpp: -------------------------------------------------------------------------------- 1 | //#define LOG_NDEBUG 0 2 | #define LOG_TAG "GXVENC_PARSER" 3 | //#include 4 | 5 | #include "gxvenclib_fast.h" 6 | #include "enc_define.h" 7 | #include "parser.h" 8 | 9 | //For Intra4x4/Intra16x16/Inter16x16/Inter16x8/Inter8x16 10 | #define get_mb_x(addr) *((unsigned char *)(addr+7)) 11 | #define get_mb_y(addr) *((unsigned char *)(addr+6)) 12 | #define get_mb_type(addr) *((unsigned char *)(addr+5)) 13 | #define get_mb_CPred(addr) *((unsigned char *)(addr+4)) 14 | 15 | #define get_mb_LPred_I4(addr, mode) \ 16 | mode[0] = *((unsigned char *)(addr+12)) & 0xf; \ 17 | mode[1] = (*((unsigned char *)(addr+12)) >> 4) & 0xf; \ 18 | mode[2] = *((unsigned char *)(addr+13)) & 0xf; \ 19 | mode[3] = (*((unsigned char *)(addr+13)) >> 4) & 0xf; \ 20 | mode[4] = *((unsigned char *)(addr+14)) & 0xf; \ 21 | mode[5] = (*((unsigned char *)(addr+14)) >> 4) & 0xf; \ 22 | mode[6] = *((unsigned char *)(addr+15)) & 0xf; \ 23 | mode[7] = (*((unsigned char *)(addr+15)) >> 4) & 0xf; \ 24 | mode[8] = *((unsigned char *)(addr+0)) & 0xf; \ 25 | mode[9] = (*((unsigned char *)(addr+0)) >> 4) & 0xf; \ 26 | mode[10] = *((unsigned char *)(addr+1)) & 0xf; \ 27 | mode[11] = (*((unsigned char *)(addr+1)) >> 4) & 0xf; \ 28 | mode[12] = *((unsigned char *)(addr+2)) & 0xf; \ 29 | mode[13] = (*((unsigned char *)(addr+2)) >> 4) & 0xf; \ 30 | mode[14] = *((unsigned char *)(addr+3)) & 0xf; \ 31 | mode[15] = (*((unsigned char *)(addr+3)) >> 4) & 0xf; 32 | 33 | #define get_mb_mv_P16x16(addr, mv) \ 34 | { \ 35 | int k = 0; \ 36 | while(k<16){ \ 37 | mv[k].mvx = *((short *)(addr+0)); \ 38 | mv[k].mvy = *((short *)(addr+2)); \ 39 | k++; \ 40 | } \ 41 | } 42 | 43 | #define get_mb_mv_P16x8(addr, mv) \ 44 | { \ 45 | int k = 0; \ 46 | while(k<8){ \ 47 | mv[k].mvx = *((short *)(addr+0)); \ 48 | mv[k].mvy = *((short *)(addr+2)); \ 49 | mv[k+8].mvx = *((short *)(addr+12)); \ 50 | mv[k+8].mvy = *((short *)(addr+14)); \ 51 | k++; \ 52 | } \ 53 | } 54 | 55 | #define get_mb_mv_P8x16(addr, mv) \ 56 | { \ 57 | int k = 0; \ 58 | while(k<4){ \ 59 | mv[k].mvx = *((short *)(addr+0)); \ 60 | mv[k].mvy = *((short *)(addr+2)); \ 61 | mv[k+8].mvx = *((short *)(addr+0)); \ 62 | mv[k+8].mvy = *((short *)(addr+2)); \ 63 | mv[k+4].mvx = *((short *)(addr+12)); \ 64 | mv[k+4].mvy = *((short *)(addr+14)); \ 65 | mv[k+12].mvx = *((short *)(addr+12)); \ 66 | mv[k+12].mvy = *((short *)(addr+14)); \ 67 | k++; \ 68 | } \ 69 | } 70 | 71 | #define get_mb_LPred_I16(addr) *((unsigned char *)(addr+12)) & 0xf 72 | #define get_mb_quant(addr) *((unsigned char *)(addr+11)) 73 | #define get_mb_cbp(addr) *((unsigned char *)(addr+10)) 74 | #define get_mb_IntraSAD(addr) *((unsigned short *)(addr+8)) 75 | #define get_mb_InterSAD(addr) *((unsigned short *)(addr+22)) 76 | #define get_mb_bits(addr) *((unsigned short *)(addr+16)) 77 | 78 | #define get_mb_quant_ex(addr) *((unsigned char *)(addr+67)) 79 | #define get_mb_cbp_ex(addr) *((unsigned char *)(addr+66)) 80 | #define get_mb_IntraSAD_ex(addr) *((unsigned short *)(addr+64)) 81 | #define get_mb_InterSAD_ex(addr) *((unsigned short *)(addr+78)) 82 | #define get_mb_bits_ex(addr) *((unsigned short *)(addr+72)) 83 | 84 | #define get_mb_mv_P8x8(addr, mv) \ 85 | { \ 86 | int k = 0, j, offset; \ 87 | while(k<8){ \ 88 | j = k << 1; \ 89 | offset = k << 3; \ 90 | mv[j].mvx = *((short *)(addr+0+offset)); \ 91 | mv[j].mvy = *((short *)(addr+2+offset)); \ 92 | mv[j+1].mvx = *((short *)(addr+12+offset)); \ 93 | mv[j+1].mvy = *((short *)(addr+14+offset)); \ 94 | k++; \ 95 | } \ 96 | } 97 | 98 | int Parser_DumpInfo(gx_fast_enc_drv_t* p) 99 | { 100 | int x,y; 101 | mb_t* info = p->mb_info; 102 | unsigned char* cur_mb = p->dump_buf.addr; 103 | unsigned char* next_mb = cur_mb; 104 | for(y = 0; y < p->src.mb_height; y++){ 105 | for(x = 0; x < p->src.mb_width; x++){ 106 | cur_mb = next_mb; 107 | info->mbx = get_mb_x(cur_mb); 108 | info->mby = get_mb_y(cur_mb); 109 | if((x != info->mbx)||(y != info->mby)) { 110 | //ALOGE("parser mb poistion error: actual: %dx%d, info:%dx%d",x,y,info->mbx,info->mby); 111 | return -1; 112 | } 113 | info->mb_type = get_mb_type(cur_mb); 114 | if((info->mb_type == HENC_MB_Type_I4MB) 115 | || (info->mb_type == HENC_MB_Type_I16MB)){ 116 | info->intra.CPred = get_mb_CPred(cur_mb); 117 | if(info->mb_type == HENC_MB_Type_I16MB) { 118 | info->intra.LPred[0] = get_mb_LPred_I16(cur_mb); 119 | } else { 120 | get_mb_LPred_I4(cur_mb, info->intra.LPred); 121 | } 122 | info->intra.sad = get_mb_IntraSAD(cur_mb); 123 | info->inter.sad = get_mb_InterSAD(cur_mb); 124 | info->quant= get_mb_quant(cur_mb); 125 | info->cbp = get_mb_cbp(cur_mb); 126 | info->bits = get_mb_bits(cur_mb); 127 | next_mb = cur_mb + 24; 128 | if(info->mb_type == HENC_MB_Type_I16MB) 129 | info->final_sad = info->intra.sad - p->i16_weight; 130 | else 131 | info->final_sad = info->intra.sad - p->i4_weight; 132 | } else if((info->mb_type == HENC_MB_Type_P16x16) 133 | || (info->mb_type == HENC_MB_Type_P16x8) 134 | || (info->mb_type == HENC_MB_Type_P8x16) 135 | || (info->mb_type == HENC_MB_Type_PSKIP)){ 136 | if((info->mb_type == HENC_MB_Type_P16x16) 137 | || (info->mb_type == HENC_MB_Type_PSKIP)) { 138 | get_mb_mv_P16x16(cur_mb, info->inter.mv); 139 | } else if(info->mb_type == HENC_MB_Type_P16x8) { 140 | get_mb_mv_P16x8(cur_mb, info->inter.mv); 141 | } else { 142 | get_mb_mv_P8x16(cur_mb, info->inter.mv); 143 | } 144 | info->intra.sad = get_mb_IntraSAD(cur_mb); 145 | info->inter.sad = get_mb_InterSAD(cur_mb); 146 | info->quant= get_mb_quant(cur_mb); 147 | info->cbp = get_mb_cbp(cur_mb); 148 | info->bits = get_mb_bits(cur_mb); 149 | next_mb = cur_mb + 24; 150 | info->final_sad = info->inter.sad - p->me_weight; 151 | } else if (info->mb_type == HENC_MB_Type_P8x8) { 152 | get_mb_mv_P8x8(cur_mb, info->inter.mv); 153 | info->intra.sad = get_mb_IntraSAD_ex(cur_mb); 154 | info->inter.sad = get_mb_InterSAD_ex(cur_mb); 155 | info->quant= get_mb_quant_ex(cur_mb); 156 | info->cbp = get_mb_cbp_ex(cur_mb); 157 | info->bits = get_mb_bits_ex(cur_mb); 158 | next_mb = cur_mb + 80; 159 | info->final_sad = info->inter.sad - p->me_weight; 160 | } else if (info->mb_type == HENC_MB_Type_AUTO) { // work around 161 | info->intra.sad = get_mb_IntraSAD(cur_mb); 162 | info->inter.sad = get_mb_InterSAD(cur_mb); 163 | info->quant= get_mb_quant(cur_mb); 164 | info->cbp = get_mb_cbp(cur_mb); 165 | info->bits = get_mb_bits(cur_mb); 166 | next_mb = cur_mb + 24; 167 | if(info->inter.sad < info->intra.sad) { 168 | get_mb_mv_P16x16(cur_mb, info->inter.mv); 169 | info->final_sad = info->inter.sad - p->me_weight; 170 | //ALOGV("frame:%d, parser mb (%dx%d) type %d warning--set as inter 16x16, cur_mb:0x%x, inter sad:%d, intra sad:%d", 171 | // p->total_encode_frame+1, x, y, info->mb_type, (ulong)(cur_mb-p->dump_buf.addr), info->inter.sad, info->intra.sad); 172 | info->mb_type = HENC_MB_Type_P16x16; 173 | } else { 174 | info->intra.CPred = get_mb_CPred(cur_mb); 175 | info->intra.LPred[0] = get_mb_LPred_I16(cur_mb); 176 | info->final_sad = info->intra.sad - p->i16_weight; 177 | //ALOGV("frame:%d, parser mb (%dx%d) type %d warning--set as I16(mode %d), cur_mb:0x%x, inter sad:%d, intra sad:%d", 178 | // p->total_encode_frame+1, x, y, info->mb_type, info->intra.LPred[0], (ulong)(cur_mb-p->dump_buf.addr), info->inter.sad, info->intra.sad); 179 | info->mb_type == HENC_MB_Type_I16MB; 180 | } 181 | } else { 182 | //ALOGE("parser mb (%dx%d) type %d error, cur_mb:0x%x", x, y, info->mb_type, (ulong)(cur_mb-p->dump_buf.addr)); 183 | return -1; 184 | } 185 | if (info->final_sad <0) 186 | info->final_sad = 0; 187 | } 188 | } 189 | return 0; 190 | } 191 | 192 | -------------------------------------------------------------------------------- /include/enc_define.h: -------------------------------------------------------------------------------- 1 | #ifndef AMLOGIC_ENCODER_DEFINE_ 2 | #define AMLOGIC_ENCODER_DEFINE_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define AVC_ABS(x) (((x)<0)? -(x) : (x)) 9 | #define AVC_MAX(x,y) ((x)>(y)? (x):(y)) 10 | #define AVC_MIN(x,y) ((x)<(y)? (x):(y)) 11 | #define AVC_MEDIAN(A,B,C) ((A) > (B) ? ((A) < (C) ? (A) : (B) > (C) ? (B) : (C)): (B) < (C) ? (B) : (C) > (A) ? (C) : (A)) 12 | 13 | //--------------------------------------------------- 14 | // ENCODER_STATUS define 15 | //--------------------------------------------------- 16 | #define ENCODER_IDLE 0 17 | #define ENCODER_SEQUENCE 1 18 | #define ENCODER_PICTURE 2 19 | #define ENCODER_IDR 3 20 | #define ENCODER_NON_IDR 4 21 | #define ENCODER_MB_HEADER 5 22 | #define ENCODER_MB_DATA 6 23 | 24 | #define ENCODER_SEQUENCE_DONE 7 25 | #define ENCODER_PICTURE_DONE 8 26 | #define ENCODER_IDR_DONE 9 27 | #define ENCODER_NON_IDR_DONE 10 28 | #define ENCODER_MB_HEADER_DONE 11 29 | #define ENCODER_MB_DATA_DONE 12 30 | 31 | 32 | /* defines for H.264 IntraPredMode */ 33 | // 4x4 intra prediction modes 34 | #define HENC_VERT_PRED 0 35 | #define HENC_HOR_PRED 1 36 | #define HENC_DC_PRED 2 37 | #define HENC_DIAG_DOWN_LEFT_PRED 3 38 | #define HENC_DIAG_DOWN_RIGHT_PRED 4 39 | #define HENC_VERT_RIGHT_PRED 5 40 | #define HENC_HOR_DOWN_PRED 6 41 | #define HENC_VERT_LEFT_PRED 7 42 | #define HENC_HOR_UP_PRED 8 43 | 44 | // 16x16 intra prediction modes 45 | #define HENC_VERT_PRED_16 0 46 | #define HENC_HOR_PRED_16 1 47 | #define HENC_DC_PRED_16 2 48 | #define HENC_PLANE_16 3 49 | 50 | // 8x8 chroma intra prediction modes 51 | #define HENC_DC_PRED_8 0 52 | #define HENC_HOR_PRED_8 1 53 | #define HENC_VERT_PRED_8 2 54 | #define HENC_PLANE_8 3 55 | 56 | /******************************************** 57 | * defines for H.264 mb_type 58 | ********************************************/ 59 | #define HENC_MB_Type_PBSKIP 0x0 60 | #define HENC_MB_Type_PSKIP 0x0 61 | #define HENC_MB_Type_BSKIP_DIRECT 0x0 62 | #define HENC_MB_Type_P16x16 0x1 63 | #define HENC_MB_Type_P16x8 0x2 64 | #define HENC_MB_Type_P8x16 0x3 65 | #define HENC_MB_Type_SMB8x8 0x4 66 | #define HENC_MB_Type_SMB8x4 0x5 67 | #define HENC_MB_Type_SMB4x8 0x6 68 | #define HENC_MB_Type_SMB4x4 0x7 69 | #define HENC_MB_Type_P8x8 0x8 70 | #define HENC_MB_Type_I4MB 0x9 71 | #define HENC_MB_Type_I16MB 0xa 72 | #define HENC_MB_Type_IBLOCK 0xb 73 | #define HENC_MB_Type_SI4MB 0xc 74 | #define HENC_MB_Type_I8MB 0xd 75 | #define HENC_MB_Type_IPCM 0xe 76 | #define HENC_MB_Type_AUTO 0xf 77 | 78 | #define HENC_MB_Type_P16MB_HORIZ_ONLY 0x7f 79 | #define HENC_MB_CBP_AUTO 0xff 80 | #define HENC_SKIP_RUN_AUTO 0xffff 81 | 82 | #define ENCODER_BUFFER_INPUT 0 83 | #define ENCODER_BUFFER_REF0 1 84 | #define ENCODER_BUFFER_REF1 2 85 | #define ENCODER_BUFFER_OUTPUT 3 86 | #define ENCODER_BUFFER_INTER_INFO 4 87 | #define ENCODER_BUFFER_INTRA_INFO 5 88 | #define ENCODER_BUFFER_QP 6 89 | 90 | #define I_FRAME 2 91 | 92 | typedef uint8_t uint8; 93 | typedef uint16_t uint16; 94 | typedef int16_t int16; 95 | typedef uint32_t uint32; 96 | typedef int32_t int32; 97 | typedef unsigned int uint; 98 | typedef unsigned long ulong; 99 | 100 | typedef enum 101 | { 102 | NO_DEFINE = -1, 103 | M8_FAST = 0, 104 | M8 = 1, 105 | GXBB = 2, 106 | MAX_DEV = 3, 107 | } ENC_DEV_TYPE; 108 | 109 | typedef enum 110 | { 111 | VMALLOC_BUFFER = 0, 112 | CANVAS_BUFFER = 1, 113 | PHYSICAL_BUFF = 2, 114 | MAX_TYPE =3, 115 | }AMVEncBufferType; 116 | 117 | typedef enum 118 | { 119 | AMVENC_YUV422_SINGLE = 0, 120 | AMVENC_YUV444_SINGLE, 121 | AMVENC_NV21, 122 | AMVENC_NV12, 123 | AMVENC_YUV420, 124 | AMVENC_YUV444_PLANE, 125 | AMVENC_RGB888, 126 | AMVENC_RGB888_PLANE, 127 | AMVENC_RGB565, 128 | AMVENC_RGBA8888, 129 | AMVENC_FRAME_FMT 130 | }AMVEncFrameFmt; 131 | 132 | typedef enum 133 | { 134 | /** 135 | Fail information, need to add more error code for more specific info 136 | */ 137 | AMVENC_TIMEOUT = -36, 138 | AMVENC_TRAILINGONES_FAIL = -35, 139 | AMVENC_SLICE_EMPTY = -34, 140 | AMVENC_POC_FAIL = -33, 141 | AMVENC_CONSECUTIVE_NONREF = -32, 142 | AMVENC_CABAC_FAIL = -31, 143 | AMVENC_PRED_WEIGHT_TAB_FAIL = -30, 144 | AMVENC_DEC_REF_PIC_MARK_FAIL = -29, 145 | AMVENC_SPS_FAIL = -28, 146 | AMVENC_BITSTREAM_BUFFER_FULL = -27, 147 | AMVENC_BITSTREAM_INIT_FAIL = -26, 148 | AMVENC_CHROMA_QP_FAIL = -25, 149 | AMVENC_INIT_QS_FAIL = -24, 150 | AMVENC_INIT_QP_FAIL = -23, 151 | AMVENC_WEIGHTED_BIPRED_FAIL = -22, 152 | AMVENC_INVALID_INTRA_PERIOD = -21, 153 | AMVENC_INVALID_CHANGE_RATE = -20, 154 | AMVENC_INVALID_BETA_OFFSET = -19, 155 | AMVENC_INVALID_ALPHA_OFFSET = -18, 156 | AMVENC_INVALID_DEBLOCK_IDC = -17, 157 | AMVENC_INVALID_REDUNDANT_PIC = -16, 158 | AMVENC_INVALID_FRAMERATE = -15, 159 | AMVENC_INVALID_NUM_SLICEGROUP = -14, 160 | AMVENC_INVALID_POC_LSB = -13, 161 | AMVENC_INVALID_NUM_REF = -12, 162 | AMVENC_INVALID_FMO_TYPE = -11, 163 | AMVENC_ENCPARAM_MEM_FAIL = -10, 164 | AMVENC_LEVEL_NOT_SUPPORTED = -9, 165 | AMVENC_LEVEL_FAIL = -8, 166 | AMVENC_PROFILE_NOT_SUPPORTED = -7, 167 | AMVENC_TOOLS_NOT_SUPPORTED = -6, 168 | AMVENC_WRONG_STATE = -5, 169 | AMVENC_UNINITIALIZED = -4, 170 | AMVENC_ALREADY_INITIALIZED = -3, 171 | AMVENC_NOT_SUPPORTED = -2, 172 | AMVENC_MEMORY_FAIL = -1, 173 | AMVENC_FAIL = 0, 174 | /** 175 | Generic success value 176 | */ 177 | AMVENC_SUCCESS = 1, 178 | AMVENC_PICTURE_READY = 2, 179 | AMVENC_NEW_IDR = 3, /* upon getting this, users have to call PVAVCEncodeSPS and PVAVCEncodePPS to get a new SPS and PPS*/ 180 | AMVENC_SKIPPED_PICTURE = 4, /* continuable error message */ 181 | AMVENC_REENCODE_PICTURE = 5, /* re-encode the picutre */ 182 | AMVENC_FORCE_IDR_NEXT = 6, /* force IDR next picutre */ 183 | } AMVEnc_Status; 184 | 185 | typedef enum 186 | { 187 | AMVEnc_Initializing = 0, 188 | AMVEnc_Encoding_SPS, 189 | AMVEnc_Encoding_PPS, 190 | AMVEnc_Analyzing_Frame, 191 | AMVEnc_WaitingForBuffer, // pending state 192 | AMVEnc_Encoding_Frame, 193 | } AMVEnc_State ; 194 | 195 | typedef enum 196 | { 197 | AVC_BASELINE = 66, 198 | AVC_MAIN = 77, 199 | AVC_EXTENDED = 88, 200 | AVC_HIGH = 100, 201 | AVC_HIGH10 = 110, 202 | AVC_HIGH422 = 122, 203 | AVC_HIGH444 = 144 204 | } AVCProfile; 205 | 206 | typedef enum 207 | { 208 | AVC_LEVEL_AUTO = 0, 209 | AVC_LEVEL1_B = 9, 210 | AVC_LEVEL1 = 10, 211 | AVC_LEVEL1_1 = 11, 212 | AVC_LEVEL1_2 = 12, 213 | AVC_LEVEL1_3 = 13, 214 | AVC_LEVEL2 = 20, 215 | AVC_LEVEL2_1 = 21, 216 | AVC_LEVEL2_2 = 22, 217 | AVC_LEVEL3 = 30, 218 | AVC_LEVEL3_1 = 31, 219 | AVC_LEVEL3_2 = 32, 220 | AVC_LEVEL4 = 40, 221 | AVC_LEVEL4_1 = 41, 222 | AVC_LEVEL4_2 = 42, 223 | AVC_LEVEL5 = 50, 224 | AVC_LEVEL5_1 = 51 225 | } AVCLevel; 226 | 227 | typedef enum 228 | { 229 | AVC_NALTYPE_SLICE = 1, /* non-IDR non-data partition */ 230 | AVC_NALTYPE_DPA = 2, /* data partition A */ 231 | AVC_NALTYPE_DPB = 3, /* data partition B */ 232 | AVC_NALTYPE_DPC = 4, /* data partition C */ 233 | AVC_NALTYPE_IDR = 5, /* IDR NAL */ 234 | AVC_NALTYPE_SEI = 6, /* supplemental enhancement info */ 235 | AVC_NALTYPE_SPS = 7, /* sequence parameter set */ 236 | AVC_NALTYPE_PPS = 8, /* picture parameter set */ 237 | AVC_NALTYPE_AUD = 9, /* access unit delimiter */ 238 | AVC_NALTYPE_EOSEQ = 10, /* end of sequence */ 239 | AVC_NALTYPE_EOSTREAM = 11, /* end of stream */ 240 | AVC_NALTYPE_FILL = 12 /* filler data */ 241 | } AVCNalUnitType; 242 | 243 | typedef enum 244 | { 245 | AVC_P_SLICE = 0, 246 | AVC_B_SLICE = 1, 247 | AVC_I_SLICE = 2, 248 | AVC_SP_SLICE = 3, 249 | AVC_SI_SLICE = 4, 250 | AVC_P_ALL_SLICE = 5, 251 | AVC_B_ALL_SLICE = 6, 252 | AVC_I_ALL_SLICE = 7, 253 | AVC_SP_ALL_SLICE = 8, 254 | AVC_SI_ALL_SLICE = 9 255 | } AVCSliceType; 256 | 257 | typedef enum 258 | { 259 | AVC_OFF = 0, 260 | AVC_ON = 1 261 | } AVCFlag; 262 | 263 | #define AMVEncFrameIO_NONE_FLAG 0x00000000 264 | #define AMVEncFrameIO_FORCE_IDR_FLAG 0x00000001 265 | #define AMVEncFrameIO_FORCE_SKIP_FLAG 0x00000002 266 | 267 | #define AMVENC_FLUSH_FLAG_INPUT 0x1 268 | #define AMVENC_FLUSH_FLAG_OUTPUT 0x2 269 | #define AMVENC_FLUSH_FLAG_REFERENCE 0x4 270 | #define AMVENC_FLUSH_FLAG_INTRA_INFO 0x8 271 | #define AMVENC_FLUSH_FLAG_INTER_INFO 0x10 272 | #define AMVENC_FLUSH_FLAG_QP 0x20 273 | 274 | #endif 275 | -------------------------------------------------------------------------------- /enc_api.cpp: -------------------------------------------------------------------------------- 1 | 2 | //#define LOG_NDEBUG 0 3 | #define LOG_TAG "AMLVENC_API" 4 | //#include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "enc_api.h" 17 | //#include 18 | 19 | //#if !defined(__aarch64__) 20 | //#include "enc/m8_enc_fast/m8venclib_fast.h" 21 | //#include "enc/m8_enc_fast/rate_control_m8_fast.h" 22 | //#include "enc/m8_enc/m8venclib.h" 23 | //#include "enc/m8_enc/rate_control_m8.h" 24 | //#endif 25 | #include "enc/gx_enc_fast/gxvenclib_fast.h" 26 | #include "enc/gx_enc_fast/rate_control_gx_fast.h" 27 | 28 | #define ENCODER_PATH "/dev/amvenc_avc" 29 | 30 | #define AMVENC_DEVINFO_M8 "AML-M8" 31 | #define AMVENC_DEVINFO_G9 "AML-G9" 32 | #define AMVENC_DEVINFO_GXBB "AML-GXBB" 33 | #define AMVENC_DEVINFO_GXTVBB "AML-GXTVBB" 34 | 35 | #define AMVENC_AVC_IOC_MAGIC 'E' 36 | #define AMVENC_AVC_IOC_GET_DEVINFO _IOW(AMVENC_AVC_IOC_MAGIC, 0xf0, unsigned int) 37 | 38 | const AMVencHWFuncPtr gx_fast_dev = { 39 | GxInitFastEncode, 40 | GxFastEncodeInitFrame, 41 | GxFastEncodeSPS_PPS, 42 | GxFastEncodeSlice, 43 | GxFastEncodeCommit, 44 | GxUnInitFastEncode, 45 | }; 46 | 47 | const AMVencRCFuncPtr gx_fast_rc = { 48 | GxFastInitRateControlModule, 49 | GxFastRCUpdateBuffer, 50 | GxFastRCUpdateFrame, 51 | GxFastRCInitFrameQP, 52 | GxFastCleanupRateControlModule, 53 | }; 54 | 55 | //#if !defined(__aarch64__) 56 | //const AMVencHWFuncPtr m8_fast_dev = { 57 | // InitFastEncode, 58 | // FastEncodeInitFrame, 59 | // FastEncodeSPS_PPS, 60 | // FastEncodeSlice, 61 | // FastEncodeCommit, 62 | // UnInitFastEncode, 63 | //}; 64 | // 65 | //const AMVencHWFuncPtr m8_dev = { 66 | // InitM8VEncode, 67 | // M8VEncodeInitFrame, 68 | // M8VEncodeSPS_PPS, 69 | // M8VEncodeSlice, 70 | // M8VEncodeCommit, 71 | // UnInitM8VEncode, 72 | //}; 73 | // 74 | //const AMVencRCFuncPtr m8_fast_rc = { 75 | // FastInitRateControlModule, 76 | // FastRCUpdateBuffer, 77 | // FastRCUpdateFrame, 78 | // FastRCInitFrameQP, 79 | // FastCleanupRateControlModule, 80 | //}; 81 | // 82 | //const AMVencRCFuncPtr m8_rc = { 83 | // M8InitRateControlModule, 84 | // M8RCUpdateBuffer, 85 | // M8RCUpdateFrame, 86 | // M8RCInitFrameQP, 87 | // M8CleanupRateControlModule, 88 | //}; 89 | //#endif /* __aarch64__ */ 90 | // 91 | const AMVencHWFuncPtr *gdev[] = { 92 | //#if defined(__aarch64__) 93 | // NULL, 94 | // NULL, 95 | //#else 96 | // &m8_fast_dev, 97 | // &m8_dev, 98 | //#endif 99 | &gx_fast_dev, 100 | NULL, 101 | }; 102 | 103 | const AMVencRCFuncPtr *grc[] = { 104 | //#if defined(__aarch64__) 105 | // NULL, 106 | // NULL, 107 | //#else 108 | // &m8_fast_rc, 109 | // &m8_rc, 110 | //#endif 111 | &gx_fast_rc, 112 | NULL, 113 | }; 114 | 115 | AMVEnc_Status AMInitRateControlModule(amvenc_hw_t* hw_info) 116 | { 117 | if(!hw_info) 118 | return AMVENC_MEMORY_FAIL; 119 | 120 | if((hw_info->dev_id<=NO_DEFINE)||(hw_info->dev_id>=MAX_DEV)||(hw_info->dev_fd<0)||(!hw_info->dev_data)) 121 | return AMVENC_FAIL; 122 | 123 | if(grc[hw_info->dev_id]->Initialize != NULL) 124 | hw_info->rc_data = grc[hw_info->dev_id]->Initialize(&hw_info->init_para); 125 | 126 | if(!hw_info->rc_data){ 127 | //ALOGD("AMInitRateControlModule Fail, dev type:%d. fd:%d",hw_info->dev_id, hw_info->dev_fd); 128 | return AMVENC_FAIL; 129 | } 130 | return AMVENC_SUCCESS; 131 | } 132 | 133 | AMVEnc_Status AMPreRateControl(amvenc_hw_t* hw_info, int frameInc, bool force_IDR) 134 | { 135 | AMVEnc_Status ret = AMVENC_FAIL; 136 | if(!hw_info) 137 | return AMVENC_MEMORY_FAIL; 138 | 139 | if((hw_info->dev_id<=NO_DEFINE)||(hw_info->dev_id>=MAX_DEV)||(!hw_info->rc_data)) 140 | return AMVENC_FAIL; 141 | 142 | if(grc[hw_info->dev_id]->PreControl!= NULL) 143 | ret = grc[hw_info->dev_id]->PreControl(hw_info->dev_data, hw_info->rc_data, frameInc, force_IDR); 144 | 145 | return ret; 146 | } 147 | 148 | AMVEnc_Status AMPostRateControl(amvenc_hw_t* hw_info, bool IDR, int* skip_num, int numFrameBits) 149 | { 150 | AMVEnc_Status ret = AMVENC_FAIL; 151 | if(!hw_info) 152 | return AMVENC_MEMORY_FAIL; 153 | 154 | if((hw_info->dev_id<=NO_DEFINE)||(hw_info->dev_id>=MAX_DEV)||(!hw_info->rc_data)) 155 | return AMVENC_FAIL; 156 | 157 | if(grc[hw_info->dev_id]->PostControl!= NULL) 158 | ret = grc[hw_info->dev_id]->PostControl(hw_info->dev_data, hw_info->rc_data,IDR, skip_num, numFrameBits); 159 | return ret; 160 | } 161 | 162 | AMVEnc_Status AMRCInitFrameQP(amvenc_hw_t* hw_info,bool IDR,int bitrate, float frame_rate) 163 | { 164 | AMVEnc_Status ret = AMVENC_FAIL; 165 | if(!hw_info) 166 | return AMVENC_MEMORY_FAIL; 167 | 168 | if((hw_info->dev_id<=NO_DEFINE)||(hw_info->dev_id>=MAX_DEV)||(!hw_info->rc_data)) 169 | return AMVENC_FAIL; 170 | 171 | if(grc[hw_info->dev_id]->InitFrameQP!= NULL) 172 | ret = grc[hw_info->dev_id]->InitFrameQP(hw_info->dev_data, hw_info->rc_data, IDR, bitrate, frame_rate); 173 | return ret; 174 | } 175 | 176 | void AMCleanupRateControlModule(amvenc_hw_t* hw_info) 177 | { 178 | if(!hw_info) 179 | return; 180 | 181 | if((!hw_info->rc_data)&&(hw_info->dev_id>NO_DEFINE)&&(hw_info->dev_iddev_id]->Release(hw_info->rc_data); 183 | 184 | hw_info->rc_data = NULL; 185 | return; 186 | } 187 | 188 | AMVEnc_Status InitAMVEncode(amvenc_hw_t* hw_info, int force_mode) 189 | { 190 | char dev_info[16]; 191 | int iret = -1, fd = -1; 192 | 193 | if(!hw_info) 194 | return AMVENC_MEMORY_FAIL; 195 | 196 | hw_info->dev_fd = -1; 197 | hw_info->dev_data = NULL; 198 | 199 | fd = open(ENCODER_PATH, O_RDWR); 200 | if(fd<0){ 201 | return AMVENC_FAIL; 202 | } 203 | memset(dev_info,0,sizeof(dev_info)); 204 | 205 | hw_info->dev_id = (ENC_DEV_TYPE) 0; 206 | //iret = ioctl(fd, AMVENC_AVC_IOC_GET_DEVINFO,&dev_info[0]); 207 | //if((iret<0)||(dev_info[0] == 0)){ 208 | // //ALOGD("The old encoder driver, not support query the dev info. set as M8 type!"); 209 | // hw_info->dev_id = M8_FAST; 210 | //}else if((strcmp(dev_info, (char *)AMVENC_DEVINFO_M8) == 0) 211 | // ||(strcmp(dev_info, (char *)AMVENC_DEVINFO_G9) == 0)){ 212 | // hw_info->dev_id = M8_FAST; 213 | //}else if(strcmp(dev_info, (char *)AMVENC_DEVINFO_GXBB) == 0){ 214 | // hw_info->dev_id = GXBB; 215 | //}else if (strcmp(dev_info, (char *)AMVENC_DEVINFO_GXTVBB) == 0){ 216 | // hw_info->dev_id = GXBB; 217 | //}else{ 218 | // hw_info->dev_id = NO_DEFINE; 219 | //} 220 | 221 | ////ALOGI("hw_info->dev_id %d, %s", hw_info->dev_id, dev_info); 222 | //if (hw_info->dev_id == M8_FAST) { 223 | // if((hw_info->init_para.enc_width >= 1280) && (hw_info->init_para.enc_height >= 720)) 224 | // hw_info->dev_id = M8_FAST; 225 | // else 226 | // hw_info->dev_id = M8; 227 | // if(1 == force_mode){ 228 | // hw_info->dev_id = M8_FAST; 229 | // } else if(2 == force_mode){ 230 | // hw_info->dev_id = M8; 231 | // } 232 | // //char prop[PROPERTY_VALUE_MAX]; 233 | // int value = 0; 234 | // //memset(prop,0,sizeof(prop)); 235 | // //if(property_get("hw.encoder.forcemode", prop, "2") > 0){ 236 | // // sscanf(prop,"%d", &value); 237 | // //}else{ 238 | // // value = 0; 239 | // //} 240 | // if(1 == value){ 241 | // hw_info->dev_id = M8_FAST; 242 | // } else if(2 == value){ 243 | // hw_info->dev_id = M8; 244 | // } 245 | // //ALOGI("hw.encoder.forcemode = %d, dev_id=%d. fd:%d", value, hw_info->dev_id, fd); 246 | //} 247 | 248 | if((hw_info->dev_id<=NO_DEFINE)||(hw_info->dev_id>=MAX_DEV)){ 249 | //ALOGD("Not found available hw encoder device, fd:%d", fd); 250 | close(fd); 251 | return AMVENC_FAIL; 252 | } 253 | 254 | if(gdev[hw_info->dev_id]->Initialize != NULL) 255 | hw_info->dev_data = gdev[hw_info->dev_id]->Initialize(fd, &hw_info->init_para); 256 | 257 | if(!hw_info->dev_data){ 258 | //ALOGD("InitAMVEncode Fail, dev type:%d. fd:%d",hw_info->dev_id, fd); 259 | hw_info->dev_id = NO_DEFINE; 260 | close(fd); 261 | return AMVENC_FAIL; 262 | } 263 | hw_info->dev_fd = fd; 264 | return AMVENC_SUCCESS; 265 | } 266 | 267 | AMVEnc_Status AMVEncodeInitFrame(amvenc_hw_t* hw_info, ulong *yuv, AMVEncBufferType type, AMVEncFrameFmt fmt, bool IDRframe) 268 | { 269 | AMVEnc_Status ret = AMVENC_FAIL; 270 | if(!hw_info) 271 | return AMVENC_MEMORY_FAIL; 272 | 273 | if((hw_info->dev_id<=NO_DEFINE)||(hw_info->dev_id>=MAX_DEV)||(hw_info->dev_fd<0)||(!hw_info->dev_data)) 274 | return AMVENC_FAIL; 275 | 276 | if(gdev[hw_info->dev_id]->InitFrame!= NULL) 277 | ret = gdev[hw_info->dev_id]->InitFrame(hw_info->dev_data, yuv, type, fmt, IDRframe); 278 | return ret; 279 | } 280 | 281 | AMVEnc_Status AMVEncodeSPS_PPS(amvenc_hw_t* hw_info, unsigned char* outptr,int* datalen) 282 | { 283 | AMVEnc_Status ret = AMVENC_FAIL; 284 | if(!hw_info) 285 | return AMVENC_MEMORY_FAIL; 286 | 287 | if((hw_info->dev_id<=NO_DEFINE)||(hw_info->dev_id>=MAX_DEV)||(hw_info->dev_fd<0)||(!hw_info->dev_data)) 288 | return AMVENC_FAIL; 289 | 290 | if(gdev[hw_info->dev_id]->EncodeSPS_PPS!= NULL) 291 | ret = gdev[hw_info->dev_id]->EncodeSPS_PPS(hw_info->dev_data, outptr, datalen); 292 | return ret; 293 | } 294 | 295 | AMVEnc_Status AMVEncodeSlice(amvenc_hw_t* hw_info, unsigned char* outptr,int* datalen, bool re_encode) 296 | { 297 | AMVEnc_Status ret = AMVENC_FAIL; 298 | if(!hw_info) 299 | return AMVENC_MEMORY_FAIL; 300 | 301 | if((hw_info->dev_id<=NO_DEFINE)||(hw_info->dev_id>=MAX_DEV)||(hw_info->dev_fd<0)||(!hw_info->dev_data)) 302 | return AMVENC_FAIL; 303 | 304 | if(gdev[hw_info->dev_id]->EncodeSlice!= NULL) 305 | ret = gdev[hw_info->dev_id]->EncodeSlice(hw_info->dev_data, outptr, datalen, re_encode); 306 | return ret; 307 | } 308 | 309 | AMVEnc_Status AMVEncodeCommit(amvenc_hw_t* hw_info, bool IDR) 310 | { 311 | AMVEnc_Status ret = AMVENC_FAIL; 312 | if(!hw_info) 313 | return AMVENC_MEMORY_FAIL; 314 | 315 | if((hw_info->dev_id<=NO_DEFINE)||(hw_info->dev_id>=MAX_DEV)||(hw_info->dev_fd<0)||(!hw_info->dev_data)) 316 | return AMVENC_FAIL; 317 | 318 | if(gdev[hw_info->dev_id]->Commit!= NULL) 319 | ret = gdev[hw_info->dev_id]->Commit(hw_info->dev_data, IDR); 320 | 321 | return ret; 322 | } 323 | 324 | void UnInitAMVEncode(amvenc_hw_t* hw_info) 325 | { 326 | if(!hw_info) 327 | return; 328 | 329 | if((hw_info->dev_data)&&(hw_info->dev_id>NO_DEFINE)&&(hw_info->dev_iddev_id]->Release(hw_info->dev_data); 331 | hw_info->dev_data = NULL; 332 | if(hw_info->dev_fd>=0){ 333 | close(hw_info->dev_fd); 334 | } 335 | 336 | hw_info->dev_fd = -1; 337 | hw_info->dev_id = NO_DEFINE; 338 | return; 339 | } 340 | -------------------------------------------------------------------------------- /enc/gx_enc_fast/rate_control_gx_fast.cpp: -------------------------------------------------------------------------------- 1 | //#define LOG_NDEBUG 0 2 | #define LOG_TAG "FASTGX_RC" 3 | //#include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "enc_define.h" 11 | #include "gxvenclib_fast.h" 12 | #include "rate_control_gx_fast.h" 13 | //#include 14 | 15 | #define RC_MAX_QUANT 28 16 | #define RC_MIN_QUANT 1 //cap to 10 to prevent rate fluctuation 17 | 18 | #define NO_REENCODE 19 | 20 | #define INDENPENT_QP_INTERVAL // use this to set indenpent qp interval for P frame 21 | #ifdef INDENPENT_QP_INTERVAL 22 | #define P_RC_MAX_QUANT 26 23 | #define P_RC_MIN_QUANT 1 24 | #else 25 | #define P_RC_MAX_QUANT RC_MAX_QUANT 26 | #define P_RC_MIN_QUANT RC_MIN_QUANT 27 | #endif 28 | 29 | static double QP2Qstep(int QP) 30 | { 31 | int i; 32 | double Qstep; 33 | static const double QP2QSTEP[6] = { 0.625, 0.6875, 0.8125, 0.875, 1.0, 1.125 }; 34 | 35 | Qstep = QP2QSTEP[QP % 6]; 36 | for (i = 0; i < (QP / 6); i++) 37 | Qstep *= 2; 38 | 39 | return Qstep; 40 | } 41 | 42 | /* convert from step size to QP */ 43 | static int Qstep2QP(double Qstep) 44 | { 45 | int q_per = 0, q_rem = 0; 46 | 47 | if (Qstep < QP2Qstep(0)) 48 | return 0; 49 | else if (Qstep > QP2Qstep(51)) 50 | return 51; 51 | 52 | while (Qstep > QP2Qstep(5)){ 53 | Qstep /= 2; 54 | q_per += 1; 55 | } 56 | 57 | if (Qstep <= (0.625 + 0.6875) / 2) 58 | { 59 | Qstep = 0.625; 60 | q_rem = 0; 61 | } 62 | else if (Qstep <= (0.6875 + 0.8125) / 2) 63 | { 64 | Qstep = 0.6875; 65 | q_rem = 1; 66 | } 67 | else if (Qstep <= (0.8125 + 0.875) / 2) 68 | { 69 | Qstep = 0.8125; 70 | q_rem = 2; 71 | } 72 | else if (Qstep <= (0.875 + 1.0) / 2) 73 | { 74 | Qstep = 0.875; 75 | q_rem = 3; 76 | } 77 | else if (Qstep <= (1.0 + 1.125) / 2) 78 | { 79 | Qstep = 1.0; 80 | q_rem = 4; 81 | } 82 | else 83 | { 84 | Qstep = 1.125; 85 | q_rem = 5; 86 | } 87 | 88 | return (q_per * 6 + q_rem); 89 | } 90 | 91 | static void updateRC_PostProc(GxFastEncRateControl *rateCtrl, bool IDR) 92 | { 93 | int calculated_Qp; 94 | int Qp_diff; 95 | bool trap = false; 96 | int pframe_max_qp = rateCtrl->max_p_qp; 97 | calculated_Qp = Qstep2QP(rateCtrl->actual_Qstep); 98 | Qp_diff = calculated_Qp - rateCtrl->Qc; 99 | //ALOGV("Calculate qp:%d,rateCtrl->actual_Qstep:%f,diff:%d",calculated_Qp,rateCtrl->actual_Qstep,Qp_diff); 100 | if(rateCtrl->max_inc_qp_step>0){ 101 | if(Qp_diff > rateCtrl->max_inc_qp_step){ 102 | rateCtrl->Qc += rateCtrl->max_inc_qp_step; 103 | rateCtrl->actual_Qstep = QP2Qstep(rateCtrl->Qc); 104 | trap = true; 105 | } 106 | } 107 | if(rateCtrl->max_dec_qp_step>0){ 108 | if(Qp_diff < 0 - rateCtrl->max_dec_qp_step){ 109 | rateCtrl->Qc -= rateCtrl->max_dec_qp_step; 110 | rateCtrl->actual_Qstep = QP2Qstep(rateCtrl->Qc); 111 | trap = true; 112 | } 113 | } 114 | 115 | if(trap == false) { 116 | rateCtrl->Qc += Qp_diff; 117 | } 118 | calculated_Qp = rateCtrl->Qc; 119 | 120 | if(IDR){ 121 | if(calculated_Qp <= RC_MIN_QUANT){ 122 | rateCtrl->Qc = RC_MIN_QUANT; 123 | rateCtrl->actual_Qstep = QP2Qstep(RC_MIN_QUANT); 124 | } 125 | if(calculated_Qp >= rateCtrl->max_idr_qp){ 126 | rateCtrl->Qc = rateCtrl->max_idr_qp; 127 | rateCtrl->actual_Qstep = QP2Qstep(rateCtrl->max_idr_qp); 128 | } 129 | rateCtrl->last_IDR_qp_delta = rateCtrl->Qc - rateCtrl->max_p_qp; 130 | }else{ 131 | if(rateCtrl->last_IDR_qp_delta > 1){ 132 | pframe_max_qp = rateCtrl->max_p_qp + rateCtrl->last_IDR_qp_delta - 2; 133 | rateCtrl->last_IDR_qp_delta -= 2; 134 | } 135 | if(calculated_Qp <= P_RC_MIN_QUANT){ 136 | rateCtrl->Qc = P_RC_MIN_QUANT; 137 | rateCtrl->actual_Qstep = QP2Qstep(RC_MIN_QUANT); 138 | } 139 | if(calculated_Qp >= pframe_max_qp){ 140 | rateCtrl->Qc = pframe_max_qp; 141 | rateCtrl->actual_Qstep = QP2Qstep(rateCtrl->max_idr_qp); // if I frame qp != P frame qp, temp use I max qp. 142 | } 143 | } 144 | return; 145 | } 146 | 147 | static void targetBitCalculation(GxFastEncRateControl *rateCtrl, bool IDR) 148 | { 149 | /* some stuff about frame dropping remained here to be done because pMP cannot be inserted into updateRateControl()*/ 150 | updateRC_PostProc(rateCtrl, IDR); 151 | return; 152 | } 153 | 154 | void calculateQuantizer(gx_fast_enc_drv_t *p, GxFastEncRateControl *rateCtrl,bool IDR) 155 | { 156 | int median_quant; 157 | 158 | /* Mad based variable bit allocation */ 159 | targetBitCalculation(rateCtrl, IDR); 160 | 161 | median_quant = RC_MIN_QUANT + (rateCtrl->max_idr_qp- RC_MIN_QUANT) / 2; 162 | if (IDR == true){ 163 | if(rateCtrl->Qc < median_quant + 5){ //to avoid the qp for idr is too samll 164 | rateCtrl->Qc += 5; 165 | } 166 | rateCtrl->Qc = AVC_MIN(rateCtrl->Qc,rateCtrl->max_idr_qp); 167 | rateCtrl->actual_quant = (double)rateCtrl->Qc; 168 | } 169 | return; 170 | } 171 | 172 | 173 | static void updateRateControl(GxFastEncRateControl *rateCtrl, bool IDR) 174 | { 175 | int encode_frames; 176 | int64_t threshold; 177 | double rate,delta,decay; 178 | double target,current_target; 179 | int median_quant; 180 | rateCtrl->encoded_frames++; 181 | /**scene detact**/ 182 | rateCtrl->skip_next_frame = 0; 183 | median_quant = RC_MIN_QUANT + (rateCtrl->max_idr_qp - RC_MIN_QUANT) / 2; 184 | //ALOGV("rateCtrl->last_IDR_bits:%d,last_pframe_bits:%d,current:%d,QP:%d",rateCtrl->last_IDR_bits,rateCtrl->last_pframe_bits,rateCtrl->Rc,rateCtrl->Qc); 185 | if(rateCtrl->refresh == true){ 186 | float idr_ratio = 0.0; 187 | int old_bitsPerFrame = rateCtrl->bitsPerFrame; 188 | rateCtrl->bitsPerFrame = (int32)(rateCtrl->bitRate / rateCtrl->frame_rate); 189 | rateCtrl->T = rateCtrl->bitRate / rateCtrl->frame_rate; 190 | rateCtrl->average_rate = (double)rateCtrl->bitRate / rateCtrl->frame_rate; 191 | rateCtrl->reaction_rate = rateCtrl->average_rate; 192 | idr_ratio = (float)((float)rateCtrl->bitsPerFrame/(float)old_bitsPerFrame); 193 | rateCtrl->last_IDR_bits = (int)(rateCtrl->last_IDR_bits*idr_ratio); 194 | rateCtrl->refresh = false; 195 | } 196 | 197 | /** calculate average rate**/ 198 | //ALOGV("bitRate:%d,frame_rate:%f",rateCtrl->bitRate,rateCtrl->frame_rate); 199 | rate = rateCtrl->average_rate; 200 | delta = rateCtrl->average_delta; 201 | decay = 1 - delta; 202 | rate = rate * decay + ((double)rateCtrl->Rc) * delta; 203 | rateCtrl->average_rate = rate; 204 | 205 | /**calculate current target bits**/ 206 | target = (double)rateCtrl->bitsPerFrame; 207 | if(rate > target){ 208 | current_target = target - (rate - target); 209 | if(current_target < target * 0.75){ 210 | current_target = target * 0.75; 211 | } 212 | }else{ 213 | current_target = target; 214 | } 215 | 216 | if(IDR){ 217 | rateCtrl->last_IDR_bits = rateCtrl->Rc; 218 | rateCtrl->last_pframe_bits = 0x7fffffff; 219 | }else{ 220 | rateCtrl->last_pframe_bits = rateCtrl->Rc; 221 | } 222 | encode_frames = rateCtrl->encoded_frames; 223 | rateCtrl->buffer_fullness += rateCtrl->Rc - rateCtrl->bitsPerFrame; 224 | threshold = rateCtrl->bitsPerFrame * encode_frames * 0.05; 225 | //ALOGV("frame:%d :rateCtrl->bitsPerFrame:%d,current_bits:%d",encode_frames,rateCtrl->bitsPerFrame,rateCtrl->Rc); 226 | //ALOGV("bufferer_fullness:%lld,threshold:%lld",rateCtrl->buffer_fullness,threshold); 227 | 228 | /**calculate current reaction rate**/ 229 | rate = rateCtrl->reaction_rate; 230 | delta = rateCtrl->reaction_delta; 231 | decay = 1 - delta; 232 | rate = rate * decay + ((double)rateCtrl->Rc) * delta; 233 | rateCtrl->reaction_rate = rate; 234 | median_quant = RC_MIN_QUANT + (rateCtrl->max_idr_qp - RC_MIN_QUANT) / 2; 235 | 236 | //ALOGV("rate:%f,current_target:%f",rate,current_target); 237 | /**reduce quantizer when the reaction rate is low**/ 238 | if(rate < current_target && rateCtrl->buffer_fullness < threshold){ 239 | //if(rate < current_target){ 240 | rateCtrl->actual_Qstep = rateCtrl->actual_Qstep * (1 - rateCtrl->reaction_delta * ((current_target - rate) / current_target / 0.20)); 241 | } 242 | /**increase quantizer when the reaction rate is high**/ 243 | if(rate > current_target && rateCtrl->buffer_fullness > 0){ 244 | //if(rate > current_target){ 245 | /**slower increasement when the quant is higher than median*/ 246 | if(rateCtrl->Qc > median_quant){ 247 | rateCtrl->actual_Qstep = rateCtrl->actual_Qstep * (1 + rateCtrl->reaction_delta / rateCtrl->reaction_ratio); 248 | } else if(rate > current_target * 1.20){ 249 | rateCtrl->actual_Qstep = rateCtrl->actual_Qstep * (1 + rateCtrl->reaction_delta); 250 | } else{ 251 | rateCtrl->actual_Qstep = rateCtrl->actual_Qstep * (1 + rateCtrl->reaction_delta * ((rate - current_target) / current_target / 0.20)); 252 | } 253 | } 254 | 255 | return; 256 | } 257 | 258 | AMVEnc_Status GxFastRCUpdateFrame(void *dev, void *rc, bool IDR, int* skip_num, int numFrameBits) 259 | { 260 | gx_fast_enc_drv_t *p = (gx_fast_enc_drv_t *)dev; 261 | GxFastEncRateControl *rateCtrl = (GxFastEncRateControl *)rc; 262 | AMVEnc_Status status = AMVENC_SUCCESS; 263 | int diff_BTCounter; 264 | 265 | *skip_num = 0; 266 | 267 | if (rateCtrl->rcEnable == true){ 268 | 269 | //rateCtrl->Rc = rateCtrl->numFrameBits; /* Total Bits for current frame */ 270 | rateCtrl->Rc = numFrameBits; 271 | 272 | updateRateControl(rateCtrl, IDR); 273 | if (rateCtrl->skip_next_frame == -1){ // skip current frame 274 | status = AMVENC_SKIPPED_PICTURE; 275 | *skip_num = rateCtrl->skip_next_frame; 276 | } 277 | } 278 | //ALOGV("Qp:%d",p->quant); 279 | return status; 280 | } 281 | 282 | AMVEnc_Status GxFastRCInitFrameQP(void *dev, void *rc,bool IDR,int bitrate, float frame_rate) 283 | { 284 | gx_fast_enc_drv_t *p = (gx_fast_enc_drv_t *)dev; 285 | GxFastEncRateControl *rateCtrl = (GxFastEncRateControl *)rc; 286 | if (rateCtrl->rcEnable == true){ 287 | /* frame layer rate control */ 288 | if (rateCtrl->encoded_frames == 0){ 289 | p->quant= rateCtrl->Qc = rateCtrl->initQP; 290 | }else{ 291 | calculateQuantizer(p,rateCtrl,IDR); 292 | p->quant = rateCtrl->Qc; 293 | if(rateCtrl->frame_rate != frame_rate || rateCtrl->bitRate != bitrate || rateCtrl->force_IDR){ 294 | rateCtrl->refresh = true; 295 | //ALOGD("we got new config, frame_rate:%f, bitrate:%d, force_IDR:%d",frame_rate, bitrate, rateCtrl->force_IDR); 296 | }else{ 297 | rateCtrl->refresh = false; 298 | } 299 | rateCtrl->frame_rate = frame_rate; 300 | rateCtrl->bitRate = bitrate; 301 | } 302 | rateCtrl->numFrameBits = 0; // reset 303 | }else{// rcEnable 304 | p->quant = rateCtrl->initQP; 305 | } 306 | return AMVENC_SUCCESS; 307 | } 308 | 309 | AMVEnc_Status GxFastRCUpdateBuffer(void *dev, void *rc, int timecode, bool force_IDR) 310 | { 311 | gx_fast_enc_drv_t *p = (gx_fast_enc_drv_t *)dev; 312 | GxFastEncRateControl *rateCtrl = (GxFastEncRateControl *)rc; 313 | rateCtrl->force_IDR = force_IDR; 314 | return AMVENC_SUCCESS; 315 | } 316 | 317 | void GxFastCleanupRateControlModule(void *rc) 318 | { 319 | GxFastEncRateControl *rateCtrl = (GxFastEncRateControl *)rc; 320 | free(rateCtrl); 321 | return; 322 | } 323 | 324 | void* GxFastInitRateControlModule(amvenc_initpara_t* init_para) 325 | { 326 | GxFastEncRateControl *rateCtrl = NULL; 327 | 328 | if(!init_para) 329 | return NULL; 330 | 331 | rateCtrl = (GxFastEncRateControl*)calloc(1, sizeof(GxFastEncRateControl)); 332 | if(!rateCtrl) 333 | return NULL; 334 | 335 | memset(rateCtrl,0,sizeof(GxFastEncRateControl)); 336 | 337 | rateCtrl->rcEnable = init_para->rcEnable; 338 | rateCtrl->initQP = init_para->initQP; 339 | rateCtrl->frame_rate = (float)init_para->frame_rate; 340 | rateCtrl->bitRate = init_para->bitrate; 341 | rateCtrl->cpbSize = init_para->cpbSize; 342 | 343 | //char qp_str[PROPERTY_VALUE_MAX]; 344 | int qp = 0; 345 | //memset(qp_str,0,sizeof(qp_str)); 346 | //if(property_get("ro.amlenc.maxqp.I", qp_str, NULL) > 0){ 347 | // sscanf(qp_str,"%d",&qp); 348 | // if(qp<=51) 349 | // rateCtrl->max_idr_qp = qp; 350 | // else 351 | // rateCtrl->max_idr_qp = RC_MAX_QUANT; 352 | //}else{ 353 | rateCtrl->max_idr_qp = RC_MAX_QUANT; 354 | //} 355 | //qp = 0; 356 | //memset(qp_str,0,sizeof(qp_str)); 357 | //if(property_get("ro.amlenc.maxqp.P", qp_str, NULL) > 0){ 358 | // sscanf(qp_str,"%d",&qp); 359 | // if(qp<=51) 360 | // rateCtrl->max_p_qp = qp; 361 | // else 362 | // rateCtrl->max_p_qp = P_RC_MAX_QUANT; 363 | //}else{ 364 | rateCtrl->max_p_qp = P_RC_MAX_QUANT; 365 | //} 366 | //qp = 0; 367 | //memset(qp_str,0,sizeof(qp_str)); 368 | // not limit for increase qp step as default; 369 | //if(property_get("ro.amlenc.qpstep.MaxInc", qp_str, NULL) > 0){ 370 | // sscanf(qp_str,"%d",&qp); 371 | // if((qp<=0)||(qp>=51)) 372 | // rateCtrl->max_inc_qp_step = 0; 373 | // else 374 | // rateCtrl->max_inc_qp_step = qp; 375 | //}else{ 376 | rateCtrl->max_inc_qp_step = 0; 377 | //} 378 | //qp = 0; 379 | //memset(qp_str,0,sizeof(qp_str)); 380 | // limit 3 for decrease qp step as default; 381 | //if(property_get("ro.amlenc.qpstep.MaxDec", qp_str, NULL) > 0){ 382 | // sscanf(qp_str,"%d",&qp); 383 | // if((qp<0)||(qp>=51)) 384 | // rateCtrl->max_dec_qp_step = 3; 385 | // else 386 | // rateCtrl->max_dec_qp_step = qp; 387 | //}else{ 388 | rateCtrl->max_dec_qp_step = 3; 389 | //} 390 | 391 | //ALOGV("Max I frame qp: %d, Max P frame qp, %d, MaxInc qp step:%d, dec step:%d",rateCtrl->max_idr_qp,rateCtrl->max_p_qp,rateCtrl->max_inc_qp_step,rateCtrl->max_dec_qp_step); 392 | if (rateCtrl->rcEnable == true){ 393 | rateCtrl->bitsPerFrame = (int32)(rateCtrl->bitRate / rateCtrl->frame_rate); 394 | rateCtrl->skip_next_frame = 0; /* must be initialized */ 395 | rateCtrl->Bs = rateCtrl->cpbSize; 396 | rateCtrl->encoded_frames = 0; 397 | 398 | /* Setting the bitrate and framerate */ 399 | rateCtrl->Qc = rateCtrl->initQP; 400 | rateCtrl->T = rateCtrl->bitRate / rateCtrl->frame_rate; 401 | rateCtrl->average_rate = (double)rateCtrl->bitRate / rateCtrl->frame_rate; 402 | rateCtrl->average_delta = 1.0 / 200; // this value can change later 403 | rateCtrl->reaction_rate = rateCtrl->average_rate; 404 | rateCtrl->reaction_delta = 1.0 / 5; // this value can change later 405 | rateCtrl->reaction_ratio = 4;//according to paper,may change later; 406 | rateCtrl->actual_quant = (double)rateCtrl->Qc; 407 | rateCtrl->actual_Qstep = QP2Qstep(rateCtrl->Qc); 408 | rateCtrl->last_pframe_bits = 0x7fffffff; 409 | rateCtrl->buffer_fullness = 0; 410 | rateCtrl->last_IDR_qp_delta = rateCtrl->Qc - rateCtrl->max_p_qp; 411 | rateCtrl->refresh = false; 412 | rateCtrl->force_IDR = false; 413 | } 414 | return (void*)rateCtrl; 415 | 416 | CLEANUP_RC: 417 | GxFastCleanupRateControlModule((void*)rateCtrl); 418 | return NULL; 419 | } 420 | 421 | -------------------------------------------------------------------------------- /AML_HWEncoder.cpp: -------------------------------------------------------------------------------- 1 | 2 | //#define LOG_NDEBUG 0 3 | #define LOG_TAG "AMLVENC" 4 | //#include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "AML_HWEncoder.h" 15 | #include "enc_api.h" 16 | 17 | AMVEnc_Status DetermineFrameNum(AMVEncHandle *Handle, amvenc_info_t* info, uint32 modTime, uint *frameNum, uint32 new_frame_rate, bool force_IDR) 18 | { 19 | uint32 modTimeRef = info->modTimeRef; 20 | int32 currFrameNum ; 21 | int frameInc; 22 | int border = 200; 23 | bool no_skip = false; 24 | 25 | /* for now, the default is to encode every frame, To Be Changed */ 26 | if (info->first_frame){ 27 | info->modTimeRef = modTime; 28 | info->wrapModTime = 0; 29 | info->prevProcFrameNum = 0; 30 | info->prevProcFrameNumOffset = 0; 31 | info->lastTimeRef = 0; 32 | *frameNum = 0; 33 | 34 | /* set frame type to IDR-frame */ 35 | info->nal_unit_type = AVC_NALTYPE_IDR; 36 | info->slice_type = AVC_I_SLICE; 37 | info->late_frame_count = 0; 38 | info->frame_rate = new_frame_rate; 39 | return AMVENC_SUCCESS; 40 | }else{ 41 | if((info->freerun == true)||(force_IDR == true)) 42 | no_skip = true; 43 | 44 | if(info->frame_rate != new_frame_rate){ 45 | info->prevProcFrameNumOffset += info->prevProcFrameNum; 46 | info->late_frame_count = 0; 47 | info->prevProcFrameNum = 0; 48 | info->modTimeRef = info->lastTimeRef; 49 | modTimeRef = info->modTimeRef; 50 | info->wrapModTime = 0; 51 | info->frame_rate = new_frame_rate; 52 | no_skip = true; 53 | } 54 | 55 | if (modTime < modTimeRef){ 56 | /* modTime wrapped around */ 57 | info->wrapModTime += ((uint32)0xFFFFFFFF - modTimeRef) + 1; 58 | info->modTimeRef = modTimeRef = 0; 59 | } 60 | modTime += info->wrapModTime; /* wrapModTime is non zero after wrap-around */ 61 | 62 | currFrameNum = (int32)(((modTime - modTimeRef) * (float)info->frame_rate + border) / 1000); /* add small roundings */ 63 | 64 | if((currFrameNum <=(int32)(info->prevProcFrameNum - info->late_frame_count))&&(no_skip == false)){ 65 | return AMVENC_FAIL; /* this is a late frame do not encode it */ 66 | } 67 | 68 | frameInc = currFrameNum - info->prevProcFrameNum+info->late_frame_count; 69 | if((currFrameNum - info->prevProcFrameNum)>1) 70 | info->late_frame_count += (int)(currFrameNum - info->prevProcFrameNum -1); 71 | else if((info->late_frame_count>0)&&((currFrameNum - info->prevProcFrameNum) == 0)) 72 | info->late_frame_count--; 73 | 74 | if ((frameInc < info->skip_next_frame + 1)&&(no_skip == false)){ 75 | return AMVENC_FAIL; /* frame skip required to maintain the target bit rate. */ 76 | } 77 | 78 | //AMPreRateControl(&info->hw_info, frameInc, &IDR); 79 | AMPreRateControl(&info->hw_info, modTime, force_IDR);//frameInc is useless in m8 ratectrl,so use it to pass timecode; 80 | *frameNum = currFrameNum+info->prevProcFrameNumOffset; 81 | info->lastTimeRef = modTime; 82 | 83 | /* This part would be similar to DetermineVopType of m4venc */ 84 | if (*frameNum >= (uint)info->idrPeriod && info->idrPeriod > 0){ /* first frame or IDR*/ 85 | //info->modTimeRef += (uint32)(info->idrPeriod * 1000 / info->frame_rate); 86 | info->modTimeRef = modTime;//add this to avoid next modTime too small 87 | *frameNum -= info->idrPeriod; 88 | 89 | info->nal_unit_type = AVC_NALTYPE_IDR; 90 | info->slice_type = AVC_I_SLICE; 91 | info->prevProcFrameNum = *frameNum; 92 | info->prevProcFrameNumOffset = 0; 93 | }else{ 94 | if(force_IDR){ // todo: force_IDR only need one IDR or reset gop. 95 | //ALOGV("force next frame to idr :%d, handle: %p.",force_IDR, Handle); 96 | info->nal_unit_type = AVC_NALTYPE_IDR; 97 | info->slice_type = AVC_I_SLICE; 98 | *frameNum = 0; 99 | info->prevProcFrameNum = 0; 100 | info->modTimeRef = modTime; 101 | info->prevProcFrameNumOffset = 0; 102 | //ALOGV("refresh parameter, handle: %p.", Handle); 103 | }else{ 104 | info->nal_unit_type = AVC_NALTYPE_SLICE; 105 | info->slice_type = AVC_P_SLICE; 106 | info->prevProcFrameNum = currFrameNum; 107 | } 108 | } 109 | } 110 | //ALOGV("Get Nal Type: %s, handle: %p.", (info->nal_unit_type ==AVC_NALTYPE_IDR)?"IDR":"SLICE", Handle); 111 | return AMVENC_SUCCESS; 112 | } 113 | 114 | AMVEnc_Status AML_HWEncInitialize(AMVEncHandle *Handle, AMVEncParams *encParam, bool* has_mix, int force_mode) 115 | { 116 | AMVEnc_Status status = AMVENC_FAIL; 117 | amvenc_info_t* info = (amvenc_info_t*)calloc(1,sizeof(amvenc_info_t)); 118 | 119 | if((!info)||(!Handle)||(!encParam)){ 120 | status = AMVENC_MEMORY_FAIL; 121 | goto exit; 122 | } 123 | 124 | if (encParam->frame_rate == 0){ 125 | status = AMVENC_INVALID_FRAMERATE; 126 | goto exit; 127 | } 128 | 129 | memset(info,0,sizeof(amvenc_info_t)); 130 | info->hw_info.dev_fd = -1; 131 | info->hw_info.dev_id = NO_DEFINE; 132 | 133 | info->enc_width = encParam->width; 134 | info->enc_height = encParam->height; 135 | info->outOfBandParamSet = encParam->out_of_band_param_set; 136 | info->fullsearch_enable = encParam->fullsearch; 137 | 138 | /* now the rate control and performance related parameters */ 139 | info->scdEnable = encParam->auto_scd; 140 | info->idrPeriod = encParam->idr_period + 1; 141 | info->search_range = encParam->search_range; 142 | info->frame_rate = (float)(encParam->frame_rate * 1.0 / 1000); 143 | 144 | info->rcEnable = (encParam->rate_control == AVC_ON)?true:false; 145 | info->bitrate = encParam->bitrate; 146 | info->cpbSize = encParam->CPB_size; 147 | info->initDelayOffset = (info->bitrate * encParam->init_CBP_removal_delay / 1000); 148 | info->initQP = encParam->initQP; 149 | info->freerun = (encParam->FreeRun== AVC_ON)?true:false; 150 | info->nSliceHeaderSpacing = encParam->nSliceHeaderSpacing; 151 | info->MBsIntraRefresh = encParam->MBsIntraRefresh; 152 | info->MBsIntraOverlap = encParam->MBsIntraOverlap; 153 | 154 | if(info->initQP == 0){ 155 | #if 0 156 | double L1, L2, L3, bpp; 157 | bpp = 1.0 * info->bitrate /(info->frame_rate * (info->enc_width *info->enc_height)); 158 | if (info->enc_width <= 176){ 159 | L1 = 0.1; 160 | L2 = 0.3; 161 | L3 = 0.6; 162 | }else if (info->enc_width <= 352){ 163 | L1 = 0.2; 164 | L2 = 0.6; 165 | L3 = 1.2; 166 | }else{ 167 | L1 = 0.6; 168 | L2 = 1.4; 169 | L3 = 2.4; 170 | } 171 | 172 | if (bpp <= L1) 173 | info->initQP = 30; 174 | else if (bpp <= L2) 175 | info->initQP = 25; 176 | else if (bpp <= L3) 177 | info->initQP = 20; 178 | else 179 | info->initQP = 15; 180 | #else 181 | info->initQP = 26; 182 | #endif 183 | } 184 | 185 | info->hw_info.init_para.enc_width = info->enc_width; 186 | info->hw_info.init_para.enc_height = info->enc_height; 187 | info->hw_info.init_para.initQP = info->initQP; 188 | info->hw_info.init_para.nSliceHeaderSpacing = info->nSliceHeaderSpacing; 189 | info->hw_info.init_para.MBsIntraRefresh = info->MBsIntraRefresh; 190 | info->hw_info.init_para.MBsIntraOverlap = info->MBsIntraOverlap; 191 | info->hw_info.init_para.rcEnable = info->rcEnable; 192 | info->hw_info.init_para.bitrate= info->bitrate; 193 | info->hw_info.init_para.frame_rate= info->frame_rate; 194 | info->hw_info.init_para.cpbSize = info->cpbSize; 195 | info->hw_info.init_para.bitrate_scale = (encParam->BitrateScale== AVC_ON)?true:false; 196 | info->hw_info.init_para.encode_once = encParam->encode_once; 197 | status = InitAMVEncode(&info->hw_info,force_mode); 198 | if(status != AMVENC_SUCCESS){ 199 | goto exit; 200 | } 201 | 202 | encParam->dev_id = info->hw_info.dev_id; 203 | if(AMInitRateControlModule(&info->hw_info)!=AMVENC_SUCCESS){ 204 | status = AMVENC_MEMORY_FAIL; 205 | goto exit; 206 | } 207 | info->first_frame = true; /* set this flag for the first time */ 208 | 209 | info->modTimeRef = 0; /* ALWAYS ASSUME THAT TIMESTAMP START FROM 0 !!!*/ 210 | info->prevCodedFrameNum = 0; 211 | info->late_frame_count = 0; 212 | 213 | if (info->outOfBandParamSet) 214 | info->state= AMVEnc_Encoding_SPS; 215 | else 216 | info->state = AMVEnc_Analyzing_Frame; 217 | Handle->object = (void *)info; 218 | *has_mix = (info->hw_info.dev_id == M8)?true:false; 219 | //ALOGD("AML_HWEncInitialize success, handle: %p, fd:%d",Handle, info->hw_info.dev_fd); 220 | return AMVENC_SUCCESS; 221 | exit: 222 | if(info){ 223 | AMCleanupRateControlModule(&info->hw_info); 224 | UnInitAMVEncode(&info->hw_info); 225 | free(info); 226 | } 227 | //ALOGE("AML_HWEncInitialize Fail, error=%d. handle: %p",status,Handle); 228 | return status; 229 | } 230 | 231 | AMVEnc_Status AML_HWSetInput(AMVEncHandle *Handle, AMVEncFrameIO *input) 232 | { 233 | uint frameNum; 234 | amvenc_info_t* info = (amvenc_info_t*)Handle->object; 235 | AMVEnc_Status status = AMVENC_FAIL; 236 | ulong yuv[13]; 237 | 238 | if (info == NULL){ 239 | //ALOGE("AML_HWSetInput Fail: UNINITIALIZED. handle: %p", Handle); 240 | return AMVENC_UNINITIALIZED; 241 | } 242 | 243 | if (info->state== AMVEnc_WaitingForBuffer){ 244 | goto RECALL_INITFRAME; 245 | }else if (info->state != AMVEnc_Analyzing_Frame){ 246 | //ALOGE("AML_HWSetInput Wrong state: %d. handle: %p",info->state, Handle); 247 | return AMVENC_FAIL; 248 | } 249 | if (input->pitch > 0xFFFF){ 250 | //ALOGE("AML_HWSetInput Fail: NOT_SUPPORTED. handle: %p", Handle); 251 | return AMVENC_NOT_SUPPORTED; // we use 2-bytes for pitch 252 | } 253 | 254 | if (AMVENC_SUCCESS != DetermineFrameNum(Handle, info, input->coding_timestamp, &frameNum, (uint32)input->frame_rate, (input->op_flag & AMVEncFrameIO_FORCE_IDR_FLAG))){ 255 | //ALOGD("AML_HWSetInput SKIPPED_PICTURE, handle: %p", Handle); 256 | return AMVENC_SKIPPED_PICTURE; /* not time to encode, thus skipping */ 257 | } 258 | 259 | yuv[0]= input->YCbCr[0]; 260 | yuv[1]= input->YCbCr[1]; 261 | yuv[2]= input->YCbCr[2]; 262 | yuv[3]= input->canvas; 263 | yuv[4]= (input->op_flag & AMVEncFrameIO_FORCE_SKIP_FLAG)?1:0; 264 | yuv[5]= input->crop_top; 265 | yuv[6]= input->crop_bottom; 266 | yuv[7]= input->crop_left; 267 | yuv[8]= input->crop_right; 268 | yuv[9]= input->pitch; 269 | yuv[10]= input->height; 270 | yuv[11]= input->scale_width; 271 | yuv[12]= input->scale_height; 272 | info->coding_order = frameNum; 273 | 274 | RECALL_INITFRAME: 275 | /* initialize and analyze the frame */ 276 | status = AMVEncodeInitFrame(&info->hw_info, &yuv[0], input->type, input->fmt,(info->nal_unit_type == AVC_NALTYPE_IDR)); 277 | 278 | if((status == AMVENC_NEW_IDR)&&(info->nal_unit_type != AVC_NALTYPE_IDR)){ 279 | info->modTimeRef = input->coding_timestamp; 280 | info->coding_order = 0; 281 | info->nal_unit_type = AVC_NALTYPE_IDR; 282 | info->slice_type = AVC_I_SLICE; 283 | info->prevProcFrameNum = 0; 284 | } 285 | 286 | AMRCInitFrameQP(&info->hw_info,(info->nal_unit_type == AVC_NALTYPE_IDR), input->bitrate, input->frame_rate); 287 | 288 | if (status == AMVENC_SUCCESS){ 289 | info->state = AMVEnc_Encoding_Frame; 290 | }else if (status == AMVENC_NEW_IDR){ 291 | if (info->outOfBandParamSet) 292 | info->state = AMVEnc_Encoding_Frame; 293 | else // assuming that in-band paramset keeps sending new SPS and PPS. 294 | info->state = AMVEnc_Encoding_SPS; 295 | }else if (status == AMVENC_PICTURE_READY){ 296 | info->state = AMVEnc_WaitingForBuffer; // Input accepted but can't continue 297 | } 298 | //ALOGV("AML_HWSetInput status: %d. handle: %p",status,Handle); 299 | return status; 300 | } 301 | 302 | AMVEnc_Status AML_HWEncNAL(AMVEncHandle *Handle, unsigned char *buffer, unsigned int *buf_nal_size, int *nal_type) 303 | { 304 | AMVEnc_Status ret = AMVENC_FAIL; 305 | amvenc_info_t* info = (amvenc_info_t*)Handle->object; 306 | int datalen = 0; 307 | 308 | if (info == NULL){ 309 | //ALOGE("AML_HWEncNAL Fail: UNINITIALIZED. handle: %p", Handle); 310 | return AMVENC_UNINITIALIZED; 311 | } 312 | 313 | //ALOGV("AML_HWEncNAL state: %d. handle: %p",info->state, Handle); 314 | switch (info->state){ 315 | case AMVEnc_Initializing: 316 | return AMVENC_ALREADY_INITIALIZED; 317 | case AMVEnc_Encoding_SPS: 318 | /* encode SPS */ 319 | ret = AMVEncodeSPS_PPS(&info->hw_info, buffer,&datalen); 320 | if(ret!=AMVENC_SUCCESS){ 321 | //ALOGV("AML_HWEncNAL state: %d, err=%d, handle: %p",info->state,ret, Handle); 322 | return ret; 323 | } 324 | if (info->outOfBandParamSet) 325 | info->state = AMVEnc_Analyzing_Frame; 326 | else // SetInput has been called before SPS and PPS. 327 | info->state = AMVEnc_Encoding_Frame; 328 | 329 | *nal_type = AVC_NALTYPE_PPS; 330 | *buf_nal_size = datalen; 331 | break; 332 | case AMVEnc_Encoding_Frame: 333 | ret = AMVEncodeSlice(&info->hw_info,buffer,&datalen, false); 334 | if (ret == AMVENC_TIMEOUT){ 335 | //ALOGD("AML_HWEncNAL state: %d, err=%d. handle: %p",info->state,ret, Handle); 336 | //ret = AMVENC_SKIPPED_PICTURE; //need debug 337 | info->state = AMVEnc_Analyzing_Frame; // walk around to fix the poll timeout 338 | return ret; 339 | } 340 | 341 | if ((ret != AMVENC_PICTURE_READY)&&(ret != AMVENC_SUCCESS)&&(ret != AMVENC_NEW_IDR)){ 342 | //ALOGV("AML_HWEncNAL state: %d, err=%d. handle: %p",info->state,ret, Handle); 343 | return ret; 344 | } 345 | 346 | info->nal_unit_type = (ret == AMVENC_NEW_IDR)?AVC_NALTYPE_IDR:info->nal_unit_type; 347 | *nal_type = info->nal_unit_type; 348 | *buf_nal_size = datalen; 349 | 350 | if((ret == AMVENC_PICTURE_READY)||(ret == AMVENC_NEW_IDR)){ 351 | info->first_frame = false; 352 | ret = AMPostRateControl(&info->hw_info,(info->nal_unit_type == AVC_NALTYPE_IDR),&info->skip_next_frame,(datalen<<3)); 353 | if((ret == AMVENC_SKIPPED_PICTURE)&&(info->freerun ==false)){ 354 | info->state = AMVEnc_Analyzing_Frame; 355 | return ret; 356 | } 357 | /*we need to reencode the frame**/ 358 | if (ret == AMVENC_REENCODE_PICTURE) { 359 | //ALOGE("AML_HWEncNAL re-encode"); 360 | ret = AMVEncodeSlice(&info->hw_info,buffer,&datalen, true); 361 | if ((ret != AMVENC_PICTURE_READY)&&(ret != AMVENC_SUCCESS)&&(ret != AMVENC_NEW_IDR)){ 362 | //ALOGE("AML_HWEncNAL state: %d, err=%d. handle: %p",info->state,ret, Handle); 363 | return ret; 364 | } 365 | info->nal_unit_type = (ret == AMVENC_NEW_IDR)?AVC_NALTYPE_IDR:info->nal_unit_type; 366 | *nal_type = info->nal_unit_type; 367 | *buf_nal_size = datalen; 368 | if(ret == AMVENC_NEW_IDR){ 369 | info->first_frame = false; 370 | ret = AMPostRateControl(&info->hw_info,(info->nal_unit_type == AVC_NALTYPE_IDR)/*true*/,&info->skip_next_frame,(datalen<<3)); 371 | if ((ret == AMVENC_SKIPPED_PICTURE)&&(info->freerun ==false)){ 372 | info->state = AMVEnc_Analyzing_Frame; 373 | return ret; 374 | } 375 | }else{ 376 | //ALOGE("re-encode failed:%d. handle: %p",ret, Handle); 377 | } 378 | } 379 | if(AMVEncodeCommit(&info->hw_info,(info->nal_unit_type == AVC_NALTYPE_IDR))!=AMVENC_SUCCESS){ 380 | //ALOGE("Encode Commit failed:%d. handle: %p",ret, Handle); 381 | } 382 | info->prevCodedFrameNum = info->coding_order; 383 | info->state = AMVEnc_Analyzing_Frame; 384 | if(ret != AMVENC_FORCE_IDR_NEXT) 385 | ret = AMVENC_PICTURE_READY; 386 | }else{ 387 | ret = AMVENC_SUCCESS; 388 | } 389 | break; 390 | default: 391 | ret = AMVENC_WRONG_STATE; 392 | } 393 | //ALOGV("AML_HWEncNAL next state: %d, ret=%d. handle: %p",info->state, ret, Handle); 394 | return ret; 395 | } 396 | 397 | AMVEnc_Status AML_HWEncRelease(AMVEncHandle *Handle) 398 | { 399 | amvenc_info_t* info = (amvenc_info_t*)Handle->object; 400 | if(info){ 401 | AMCleanupRateControlModule(&info->hw_info); 402 | UnInitAMVEncode(&info->hw_info); 403 | free(info); 404 | } 405 | Handle->object = NULL; 406 | //ALOGV("AML_HWEncRelease Done, handle: %p", Handle); 407 | return AMVENC_SUCCESS; 408 | } 409 | 410 | -------------------------------------------------------------------------------- /enc/gx_enc_fast/gxvenclib_fast.cpp: -------------------------------------------------------------------------------- 1 | 2 | //#define LOG_NDEBUG 0 3 | #define LOG_TAG "GXFASTENCLIB" 4 | //#include 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | //#include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "gxvenclib_fast.h" 24 | #include "enc_define.h" 25 | #include "parser.h" 26 | //#include 27 | 28 | #define ENCODE_DONE_TIMEOUT 100 29 | 30 | #ifndef UCODE_MODE_FULL 31 | #define UCODE_MODE_FULL 0 32 | #endif 33 | 34 | static int encode_poll(int fd, int timeout) 35 | { 36 | struct pollfd poll_fd[1]; 37 | poll_fd[0].fd = fd; 38 | poll_fd[0].events = POLLIN |POLLERR; 39 | return poll(poll_fd, 1, timeout); 40 | } 41 | 42 | static void rgb32to24(const uint8_t *src, uint8_t *dst, int src_size) 43 | { 44 | int i; 45 | int num_pixels = src_size >> 2; 46 | for (i=0; isrc.pix_width*4; 61 | int canvas_w = (((p->src.pix_width*3)+31)>>5)<<5; 62 | int mb_h = p->src.mb_height<<4; 63 | int i; 64 | if(p->src.pix_height<(p->src.mb_height<<4)) 65 | crop_flag = true; 66 | src = (unsigned char*)p->src.plane[0]; 67 | dst = p->input_buf.addr; 68 | if(canvas_w != (p->src.pix_width*3)){ 69 | for(i =0; isrc.pix_height; i++){ 70 | rgb32to24(src, dst,bytes_per_line); 71 | dst+=canvas_w; 72 | src+=bytes_per_line; 73 | } 74 | }else{ 75 | rgb32to24(src, dst, bytes_per_line*p->src.pix_height); 76 | } 77 | offset = p->src.pix_height*canvas_w; 78 | 79 | if(crop_flag) 80 | memset(p->input_buf.addr+offset, 0, (mb_h -p->src.pix_height)*canvas_w); 81 | 82 | return canvas_w*mb_h; 83 | } 84 | 85 | static int RGB24_To_RGB24Canvas(gx_fast_enc_drv_t* p) 86 | { 87 | unsigned char* src = NULL; 88 | unsigned char* dst = NULL; 89 | bool crop_flag = false; 90 | uint32_t offset = 0; 91 | int bytes_per_line = p->src.pix_width*3; 92 | int canvas_w = ((bytes_per_line+31)>>5)<<5; 93 | int mb_h = p->src.mb_height<<4; 94 | int i; 95 | if(p->src.pix_height<(p->src.mb_height<<4)) 96 | crop_flag = true; 97 | src = (unsigned char*)p->src.plane[0]; 98 | dst = p->input_buf.addr; 99 | if(bytes_per_line !=canvas_w){ 100 | for(i =0; isrc.pix_height; i++){ 101 | memcpy(dst, src,bytes_per_line); 102 | dst+=canvas_w; 103 | src+=bytes_per_line; 104 | } 105 | }else{ 106 | memcpy(dst, src,bytes_per_line*p->src.pix_height); 107 | } 108 | offset = p->src.pix_height*canvas_w; 109 | 110 | if(crop_flag) 111 | memset(p->input_buf.addr+offset, 0, (mb_h -p->src.pix_height)*canvas_w); 112 | 113 | return canvas_w*mb_h; 114 | } 115 | 116 | static uint32_t copy_to_local(gx_fast_enc_drv_t* p) 117 | { 118 | bool crop_flag = false; 119 | uint32_t offset = 0; 120 | int canvas_w = 0; 121 | int i = 0; 122 | uint32_t total_size = 0; 123 | unsigned char* src = NULL; 124 | unsigned char* dst = NULL; 125 | if(p->src.pix_height<(p->src.mb_height<<4)) 126 | crop_flag = true; 127 | 128 | if(p->src.fmt != AMVENC_YUV420) 129 | canvas_w = ((p->src.pix_width+31)>>5)<<5; 130 | else 131 | canvas_w = ((p->src.pix_width+63)>>6)<<6; 132 | 133 | src = (unsigned char*)p->src.plane[0]; 134 | dst = p->input_buf.addr; 135 | if(p->src.pix_width !=canvas_w){ 136 | for(i =0; isrc.pix_height; i++){ 137 | memcpy(dst, src,p->src.pix_width); 138 | dst+=canvas_w; 139 | src+=p->src.pix_width; 140 | } 141 | }else{ 142 | memcpy(dst, src,p->src.pix_width*p->src.pix_height); 143 | } 144 | offset = p->src.pix_height*canvas_w; 145 | 146 | if(crop_flag){ 147 | memset(p->input_buf.addr+offset, 0, ((p->src.mb_height<<4) -p->src.pix_height)*canvas_w); 148 | offset = canvas_w*p->src.mb_height<<4; 149 | } 150 | 151 | src = (unsigned char*)p->src.plane[1]; 152 | dst = (unsigned char*)(p->input_buf.addr+offset); 153 | if((p->src.fmt == AMVENC_NV12)||(p->src.fmt == AMVENC_NV21)){ 154 | if(p->src.pix_width !=canvas_w){ 155 | for(i =0; isrc.pix_height/2;i++){ 156 | memcpy(dst, src,p->src.pix_width); 157 | dst+=canvas_w; 158 | src+=p->src.pix_width; 159 | } 160 | }else{ 161 | memcpy(dst, src,p->src.pix_width*p->src.pix_height/2); 162 | } 163 | offset += p->src.pix_height*canvas_w/2; 164 | if(crop_flag) 165 | memset(p->input_buf.addr+offset, 0x80, ((p->src.mb_height<<4) -p->src.pix_height)*canvas_w/2); 166 | }else if(p->src.fmt == AMVENC_YUV420){ 167 | if(p->src.pix_width !=canvas_w){ 168 | for(i =0;isrc.pix_height/2;i++){ 169 | memcpy(dst, src,p->src.pix_width/2); 170 | dst+=canvas_w/2; 171 | src+=p->src.pix_width/2; 172 | } 173 | }else{ 174 | memcpy(dst, src,p->src.pix_width*p->src.pix_height/4); 175 | } 176 | offset += p->src.pix_height*canvas_w/4; 177 | if(crop_flag){ 178 | memset(p->input_buf.addr+offset, 0x80, ((p->src.mb_height<<4) -p->src.pix_height)*canvas_w/4); 179 | offset = canvas_w*p->src.mb_height*5<<2; 180 | } 181 | src = (unsigned char*)p->src.plane[2]; 182 | dst = (unsigned char*)(p->input_buf.addr+offset); 183 | if(p->src.pix_width !=canvas_w){ 184 | for(i =0;isrc.pix_height/2;i++){ 185 | memcpy(dst, src,p->src.pix_width/2); 186 | dst+=canvas_w/2; 187 | src+=p->src.pix_width/2; 188 | } 189 | }else{ 190 | memcpy(dst, src,p->src.pix_width*p->src.pix_height/4); 191 | } 192 | offset += p->src.pix_height*canvas_w/4; 193 | if(crop_flag){ 194 | memset(p->input_buf.addr+offset, 0x80, ((p->src.mb_height<<4) -p->src.pix_height)*canvas_w/4); 195 | } 196 | } 197 | total_size = canvas_w*p->src.mb_height*3<<3; 198 | return total_size; 199 | } 200 | 201 | static int set_input(gx_fast_enc_drv_t* p, ulong *yuv, uint32_t enc_width, uint32_t enc_height, AMVEncBufferType type, AMVEncFrameFmt fmt) 202 | { 203 | int i; 204 | ulong y = yuv[0]; 205 | ulong u = yuv[1]; 206 | ulong v = yuv[2]; 207 | gx_fast_input_t *src = &p->src; 208 | 209 | if(!y) 210 | return -1; 211 | 212 | src->pix_width = enc_width; 213 | src->pix_height = enc_height; 214 | src->mb_width = (src->pix_width+15)>>4; 215 | src->mb_height = (src->pix_height+15)>>4; 216 | 217 | src->plane[1] = 0; 218 | src->plane[2] = 0; 219 | 220 | if(type == VMALLOC_BUFFER){ 221 | src->plane[0] = y; 222 | if((fmt == AMVENC_NV21)||(fmt == AMVENC_NV12)||(fmt == AMVENC_YUV420)) 223 | src->plane[1] = u; 224 | if(fmt == AMVENC_YUV420) 225 | src->plane[2] = v; 226 | }else{ 227 | src->canvas = (uint32_t)yuv[3]; 228 | } 229 | src->type = type; 230 | src->fmt = fmt; 231 | if(src->type == VMALLOC_BUFFER){ 232 | if((src->fmt != AMVENC_RGB888)&&(src->fmt != AMVENC_RGBA8888)){ 233 | src->framesize = copy_to_local(p); 234 | }else if(p->src.fmt == AMVENC_RGB888){ 235 | src->framesize = RGB24_To_RGB24Canvas(p); 236 | }else if(p->src.fmt == AMVENC_RGBA8888){ 237 | src->framesize = RGBA32_To_RGB24Canvas(p); 238 | src->fmt = AMVENC_RGB888; 239 | } 240 | }else{ 241 | src->framesize = src->mb_height*src->pix_width*24; 242 | } 243 | return 0; 244 | } 245 | 246 | static AMVEnc_Status start_ime(gx_fast_enc_drv_t* p, unsigned char* outptr,int* datalen) 247 | { 248 | AMVEnc_Status ret = AMVENC_FAIL; 249 | uint32_t status; 250 | uint32_t result[4]; 251 | uint32_t control_info[10]; 252 | uint32_t total_time = 0; 253 | 254 | if(p->logtime) 255 | gettimeofday(&p->start_test, NULL); 256 | 257 | control_info[0] = ENCODER_NON_IDR; 258 | control_info[1] = UCODE_MODE_FULL; 259 | control_info[2] = p->src.type; 260 | control_info[3] = p->src.fmt; 261 | control_info[4] = (p->src.type == VMALLOC_BUFFER)?0:p->src.canvas; 262 | control_info[5] = p->src.framesize; 263 | control_info[6] = (p->fix_qp >= 0)?p->fix_qp:p->quant; 264 | control_info[7] = AMVENC_FLUSH_FLAG_INPUT|AMVENC_FLUSH_FLAG_OUTPUT; // flush op; 265 | control_info[7] |= AMVENC_FLUSH_FLAG_INTER_INFO; 266 | control_info[8] = ENCODE_DONE_TIMEOUT; // timeout op; 267 | control_info[9] = p->nr_mode; // nr mode 0: disable 1: snr 2: tnr 2: 3dnr 268 | ioctl(p->fd, FASTGX_AVC_IOC_NEW_CMD, &control_info[0]); 269 | 270 | if(encode_poll(p->fd, -1)<=0){ 271 | //ALOGE("start_ime: poll fail, fd:%d", p->fd); 272 | return AMVENC_TIMEOUT; 273 | } 274 | 275 | ioctl(p->fd, FASTGX_AVC_IOC_GET_STAGE, &status); 276 | ret = AMVENC_FAIL; 277 | if(status == ENCODER_IDR_DONE){ 278 | ioctl(p->fd, FASTGX_AVC_IOC_GET_OUTPUT_SIZE, &result[0]); 279 | if((result[0] < p->output_buf.size)&&(result[0]>0)){ 280 | memcpy(outptr,p->output_buf.addr,result[0]); 281 | *datalen = result[0]; 282 | p->me_weight = result[1]; 283 | p->i4_weight = result[2]; 284 | p->i16_weight = result[3]; 285 | Parser_DumpInfo(p); 286 | ret = AMVENC_PICTURE_READY; 287 | //ALOGV("start_ime: done size: %d, fd:%d ", result[0], p->fd); 288 | } 289 | }else{ 290 | //ALOGE("start_ime: encode timeout, status:%d, fd:%d",status, p->fd); 291 | ret = AMVENC_TIMEOUT; 292 | } 293 | if(ret == AMVENC_PICTURE_READY){ 294 | p->total_encode_frame++; 295 | if(p->logtime){ 296 | gettimeofday(&p->end_test, NULL); 297 | total_time = p->end_test.tv_sec - p->start_test.tv_sec; 298 | total_time = total_time*1000000 + p->end_test.tv_usec -p->start_test.tv_usec; 299 | //ALOGD("start_ime: need time: %d us, frame num:%d, fd:%d",total_time, p->total_encode_frame, p->fd); 300 | p->total_encode_time +=total_time; 301 | } 302 | } 303 | return ret; 304 | } 305 | 306 | static AMVEnc_Status start_intra(gx_fast_enc_drv_t* p, unsigned char* outptr,int* datalen) 307 | { 308 | AMVEnc_Status ret = AMVENC_FAIL; 309 | uint32_t status; 310 | uint32_t result[4]; 311 | uint32_t control_info[10]; 312 | uint32_t total_time = 0; 313 | if(p->logtime) 314 | gettimeofday(&p->start_test, NULL); 315 | 316 | control_info[0] = ENCODER_IDR; 317 | control_info[1] = UCODE_MODE_FULL; 318 | control_info[2] = p->src.type; 319 | control_info[3] = p->src.fmt; 320 | control_info[4] = (p->src.type == VMALLOC_BUFFER)?0:p->src.canvas; 321 | control_info[5] = p->src.framesize; //(16X3/2) 322 | control_info[6] = (p->fix_qp >= 0)?p->fix_qp:p->quant; 323 | control_info[7] = AMVENC_FLUSH_FLAG_INPUT|AMVENC_FLUSH_FLAG_OUTPUT; // flush op; 324 | control_info[7] |= AMVENC_FLUSH_FLAG_INTRA_INFO; 325 | control_info[8] = ENCODE_DONE_TIMEOUT; // timeout op; 326 | if (p->total_encode_frame > 0) 327 | control_info[9] = p->nr_mode; // nr mode 0: disable 1: snr 2: tnr 2: 3dnr 328 | else 329 | control_info[9] = (p->nr_mode > 0)?1:0; 330 | ioctl(p->fd, FASTGX_AVC_IOC_NEW_CMD, &control_info[0]); 331 | 332 | if(encode_poll(p->fd, -1)<=0){ 333 | //ALOGE("start_intra: poll fail, fd:%d", p->fd); 334 | return AMVENC_TIMEOUT; 335 | } 336 | 337 | ioctl(p->fd, FASTGX_AVC_IOC_GET_STAGE, &status); 338 | ret = AMVENC_FAIL; 339 | if(status == ENCODER_IDR_DONE){ 340 | ioctl(p->fd, FASTGX_AVC_IOC_GET_OUTPUT_SIZE, &result[0]); 341 | if((result[0] < p->output_buf.size)&&(result[0]>0)){ 342 | memcpy(outptr,p->output_buf.addr,result[0]); 343 | *datalen = result[0]; 344 | p->me_weight = result[1]; 345 | p->i4_weight = result[2]; 346 | p->i16_weight = result[3]; 347 | Parser_DumpInfo(p); 348 | ret = AMVENC_NEW_IDR; 349 | //ALOGV("start_intra: done size: %d, fd:%d", result[0], p->fd); 350 | } 351 | }else{ 352 | //ALOGE("start_intra: encode timeout, status:%d, fd:%d",status, p->fd); 353 | ret = AMVENC_TIMEOUT; 354 | } 355 | 356 | if(ret == AMVENC_NEW_IDR){ 357 | p->total_encode_frame++; 358 | if(p->logtime){ 359 | gettimeofday(&p->end_test, NULL); 360 | total_time = (p->end_test.tv_sec - p->start_test.tv_sec)*1000000 + p->end_test.tv_usec -p->start_test.tv_usec; 361 | p->total_encode_time +=total_time; 362 | //ALOGD("start_intra: need time: %d us, frame num:%d, fd:%d",total_time, p->total_encode_frame, p->fd); 363 | } 364 | } 365 | return ret; 366 | } 367 | 368 | void* GxInitFastEncode(int fd, amvenc_initpara_t* init_para) 369 | { 370 | int addr_index = 0; 371 | int ret = 0; 372 | uint32_t buff_info[30]; 373 | uint32_t mode = UCODE_MODE_FULL; 374 | gx_fast_enc_drv_t* p = NULL; 375 | int i = 0; 376 | 377 | if(!init_para){ 378 | //ALOGE("InitFastEncode init para error. fd:%d", fd); 379 | return NULL; 380 | } 381 | 382 | p = (gx_fast_enc_drv_t*)calloc(1,sizeof(gx_fast_enc_drv_t)); 383 | if(!p){ 384 | //ALOGE("InitFastEncode calloc faill. fd:%d", fd); 385 | return NULL; 386 | } 387 | 388 | memset(p,0,sizeof(gx_fast_enc_drv_t)); 389 | p->fd = fd; 390 | if(p->fd < 0){ 391 | //ALOGE("InitFastEncode open encode device fail, fd:%d", p->fd); 392 | free(p); 393 | return NULL; 394 | } 395 | 396 | memset(buff_info,0,sizeof(buff_info)); 397 | ret = ioctl(p->fd, FASTGX_AVC_IOC_GET_BUFFINFO,&buff_info[0]); 398 | if((ret)||(buff_info[0]==0)){ 399 | //ALOGE("InitFastEncode -- old venc driver. no buffer information! fd:%d", p->fd); 400 | free(p); 401 | return NULL; 402 | } 403 | 404 | p->mmap_buff.addr = (unsigned char*)mmap(0,buff_info[0], PROT_READ|PROT_WRITE , MAP_SHARED ,p->fd, 0); 405 | if (p->mmap_buff.addr == MAP_FAILED) { 406 | //ALOGE("InitFastEncode mmap fail, fd:%d", p->fd); 407 | free(p); 408 | return NULL; 409 | } 410 | 411 | p->quant = init_para->initQP; 412 | p->enc_width = init_para->enc_width; 413 | p->enc_height = init_para->enc_height; 414 | p->mmap_buff.size = buff_info[0]; 415 | p->src.pix_width= init_para->enc_width; 416 | p->src.pix_height= init_para->enc_height; 417 | p->src.mb_width = (init_para->enc_width+15)>>4; 418 | p->src.mb_height= (init_para->enc_height+15)>>4; 419 | p->src.mbsize = p->src.mb_height*p->src.mb_width; 420 | p->sps_len = 0; 421 | p->gotSPS = false; 422 | p->pps_len = 0; 423 | p->gotPPS = false; 424 | p->fix_qp = -1; 425 | p->nr_mode = 3; 426 | 427 | buff_info[0] = mode; 428 | buff_info[1] = p->src.mb_height; 429 | buff_info[2] = p->enc_width; 430 | buff_info[3] = p->enc_height; 431 | ret = ioctl(p->fd, FASTGX_AVC_IOC_CONFIG_INIT,&buff_info[0]); 432 | if(ret){ 433 | //ALOGE("InitFastEncode config init fai, fd:%dl", p->fd); 434 | munmap(p->mmap_buff.addr ,p->mmap_buff.size); 435 | free(p); 436 | return NULL; 437 | } 438 | 439 | p->mb_info = (mb_t *)malloc(p->src.mbsize * sizeof(mb_t)); 440 | if(p->mb_info == NULL){ 441 | //ALOGE("ALLOC mb info memory failed. fd:%d",p->fd); 442 | munmap(p->mmap_buff.addr ,p->mmap_buff.size); 443 | free(p); 444 | return NULL; 445 | } 446 | 447 | p->input_buf.addr = p->mmap_buff.addr+buff_info[1]; 448 | p->input_buf.size = buff_info[3]-buff_info[1]; 449 | 450 | p->ref_buf_y[0].addr = p->mmap_buff.addr +buff_info[3]; 451 | p->ref_buf_y[0].size = buff_info[4]; 452 | p->ref_buf_uv[0].addr = p->mmap_buff.addr +buff_info[5]; 453 | p->ref_buf_uv[0].size = buff_info[6]; 454 | 455 | p->ref_buf_y[1].addr = p->mmap_buff.addr +buff_info[7]; 456 | p->ref_buf_y[1].size = buff_info[8]; 457 | p->ref_buf_uv[1].addr = p->mmap_buff.addr +buff_info[9]; 458 | p->ref_buf_uv[1].size = buff_info[10]; 459 | p->output_buf.addr = p->mmap_buff.addr +buff_info[11] ; 460 | p->output_buf.size = buff_info[12]; 461 | p->dump_buf.addr = p->mmap_buff.addr +buff_info[13] ; 462 | p->dump_buf.size = buff_info[14]; 463 | 464 | p->mCancel = false; 465 | p->total_encode_frame = 0; 466 | p->total_encode_time = 0; 467 | { 468 | //char prop[PROPERTY_VALUE_MAX]; 469 | //int value = 0; 470 | p->logtime = false; 471 | //memset(prop,0,sizeof(prop)); 472 | //if(property_get("hw.encoder.log.flag", prop, NULL) > 0){ 473 | // sscanf(prop,"%d",&value); 474 | //} 475 | //if(value&0x8){ 476 | // //ALOGD("Enable Debug Time Log, fd:%d", p->fd); 477 | // p->logtime = true; 478 | //} 479 | 480 | //value = -1; 481 | //memset(prop,0,sizeof(prop)); 482 | //if(property_get("hw.encoder.fix_qp", prop, NULL) > 0){ 483 | // sscanf(prop,"%d",&value); 484 | // if((value>=0)&&(value<51)){ 485 | // p->fix_qp = value; 486 | // //ALOGD("Enable fix qp mode: %d. fd:%d", p->fix_qp, p->fd); 487 | // } 488 | //} 489 | //value = -1; 490 | //memset(prop,0,sizeof(prop)); 491 | //if(property_get("hw.encoder.nr_mode", prop, NULL) > 0){ 492 | // sscanf(prop,"%d",&value); 493 | // if((value>=0)&&(value<=3)){ 494 | // p->nr_mode = value; 495 | // //ALOGD("Set Nr Mode as %d. fd:%d", p->nr_mode, p->fd); 496 | // } 497 | //} 498 | } 499 | return (void *)p; 500 | } 501 | 502 | AMVEnc_Status GxFastEncodeInitFrame(void *dev, ulong *yuv, AMVEncBufferType type, AMVEncFrameFmt fmt, bool IDRframe) 503 | { 504 | gx_fast_enc_drv_t* p = (gx_fast_enc_drv_t*)dev; 505 | AMVEnc_Status ret = AMVENC_FAIL; 506 | uint32_t total_time = 0; 507 | 508 | if((!p)||(!yuv)) 509 | return ret; 510 | 511 | if(p->logtime) 512 | gettimeofday(&p->start_test, NULL); 513 | 514 | set_input(p, yuv,p->enc_width, p->enc_height, type,fmt); 515 | 516 | p->IDRframe =IDRframe; 517 | if(p->IDRframe){ 518 | ret = AMVENC_NEW_IDR; 519 | }else{ 520 | ret = AMVENC_SUCCESS; 521 | } 522 | if(p->logtime){ 523 | gettimeofday(&p->end_test, NULL); 524 | total_time = (p->end_test.tv_sec - p->start_test.tv_sec)*1000000 + p->end_test.tv_usec -p->start_test.tv_usec; 525 | p->total_encode_time +=total_time; 526 | //ALOGD("GxVEncodeInitFrame: need time: %d us, ret:%d, fd:%d",total_time,ret, p->fd); 527 | } 528 | return ret; 529 | } 530 | 531 | AMVEnc_Status GxFastEncodeSPS_PPS(void* dev, unsigned char* outptr,int* datalen) 532 | { 533 | gx_fast_enc_drv_t* p = (gx_fast_enc_drv_t*)dev; 534 | AMVEnc_Status ret = AMVENC_FAIL; 535 | uint32_t status; 536 | uint32_t result[4]; 537 | uint32_t control_info[5]; 538 | 539 | control_info[0] = ENCODER_SEQUENCE; 540 | control_info[1] = UCODE_MODE_FULL; 541 | control_info[2] = 26; //init qp; 542 | control_info[3] = AMVENC_FLUSH_FLAG_OUTPUT; 543 | control_info[4] = 0; // never timeout 544 | ioctl(p->fd, FASTGX_AVC_IOC_NEW_CMD, &control_info[0]); 545 | 546 | if(encode_poll(p->fd, -1)<=0){ 547 | //ALOGE("sps pps: poll fail, fd:%d", p->fd); 548 | return AMVENC_TIMEOUT; 549 | } 550 | 551 | ioctl(p->fd, FASTGX_AVC_IOC_GET_STAGE, &status); 552 | 553 | //ALOGV("FastEncodeSPS_PPS status:%d, fd:%d", status, p->fd); 554 | ret = AMVENC_FAIL; 555 | if(status == ENCODER_PICTURE_DONE){ 556 | ioctl(p->fd, FASTGX_AVC_IOC_GET_OUTPUT_SIZE, &result[0]); 557 | p->sps_len = (result[0] >>16)&0xffff; 558 | p->pps_len = result[0] & 0xffff; 559 | if(((p->sps_len+ p->pps_len)< p->output_buf.size)&&(p->sps_len>0)&&(p->pps_len>0)){ 560 | p->gotSPS = true; 561 | p->gotPPS= true; 562 | memcpy(outptr,p->output_buf.addr,p->pps_len+p->sps_len); 563 | *datalen = p->pps_len+p->sps_len; 564 | ret = AMVENC_SUCCESS; 565 | } 566 | }else{ 567 | //ALOGE("sps pps timeout, status:%d, fd:%d",status, p->fd); 568 | ret = AMVENC_TIMEOUT; 569 | } 570 | return ret; 571 | } 572 | 573 | AMVEnc_Status GxFastEncodeSlice(void* dev, unsigned char* outptr,int* datalen, bool re_encode) 574 | { 575 | gx_fast_enc_drv_t* p = (gx_fast_enc_drv_t*)dev; 576 | AMVEnc_Status ret = AMVENC_FAIL; 577 | if((!p)||(!outptr)||(!datalen)) 578 | return ret; 579 | 580 | if(p->IDRframe){ 581 | ret = start_intra(p,outptr,datalen); 582 | }else{ 583 | ret = start_ime(p,outptr,datalen); 584 | } 585 | return ret; 586 | } 587 | 588 | AMVEnc_Status GxFastEncodeCommit(void* dev, bool IDR) 589 | { 590 | gx_fast_enc_drv_t* p = (gx_fast_enc_drv_t*)dev; 591 | AMVEnc_Status ret = AMVENC_FAIL; 592 | int status = 0; 593 | if(!p) 594 | return ret; 595 | status = (IDR == true)?ENCODER_IDR:ENCODER_NON_IDR; 596 | if(ioctl(p->fd, FASTGX_AVC_IOC_SUBMIT_ENCODE_DONE ,&status)== 0) 597 | ret = AMVENC_SUCCESS; 598 | return ret; 599 | } 600 | 601 | void GxUnInitFastEncode(void* dev) 602 | { 603 | gx_fast_enc_drv_t* p = (gx_fast_enc_drv_t*)dev; 604 | if(!p) 605 | return; 606 | 607 | p->mCancel = true; 608 | 609 | if(p->mb_info) 610 | free(p->mb_info); 611 | 612 | if(p->mmap_buff.addr) 613 | munmap(p->mmap_buff.addr ,p->mmap_buff.size); 614 | 615 | if(p->logtime) 616 | //ALOGD("total_encode_frame: %d, total_encode_time: %d ms, fd:%d", 617 | // p->total_encode_frame, p->total_encode_time/1000, p->fd); 618 | free(p); 619 | return; 620 | } 621 | 622 | --------------------------------------------------------------------------------