diff options
Diffstat (limited to 'mm-video/vidc/venc/src/video_encoder_device.cpp')
-rwxr-xr-x[-rw-r--r--] | mm-video/vidc/venc/src/video_encoder_device.cpp | 1608 |
1 files changed, 1330 insertions, 278 deletions
diff --git a/mm-video/vidc/venc/src/video_encoder_device.cpp b/mm-video/vidc/venc/src/video_encoder_device.cpp index 33d57174..6e9b63ce 100644..100755 --- a/mm-video/vidc/venc/src/video_encoder_device.cpp +++ b/mm-video/vidc/venc/src/video_encoder_device.cpp @@ -1,5 +1,5 @@ /*-------------------------------------------------------------------------- -Copyright (c) 2010, Code Aurora Forum. All rights reserved. +Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -27,40 +27,44 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------*/ #include<string.h> #include <sys/ioctl.h> +#include <sys/prctl.h> #include<unistd.h> #include <fcntl.h> #include "video_encoder_device.h" #include "omx_video_encoder.h" +#include <linux/android_pmem.h> +#ifdef USE_ION +#include <ion_msm.h> +#endif #define MPEG4_SP_START 0 #define MPEG4_ASP_START (MPEG4_SP_START + 8) #define MPEG4_720P_LEVEL 6 #define H263_BP_START 0 #define H264_BP_START 0 -#define H264_HP_START (H264_BP_START + 11) -#define H264_MP_START (H264_BP_START + 21) +#define H264_HP_START (H264_BP_START + 13) +#define H264_MP_START (H264_BP_START + 26) /* MPEG4 profile and level table*/ static const unsigned int mpeg4_profile_level_table[][5]= { /*max mb per frame, max mb per sec, max bitrate, level, profile*/ {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple}, - {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple}, + {99,1485,64000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple}, {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple}, {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple}, {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple}, {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, - {3600,108000,14000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, + {3600,108000,12000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, {0,0,0,0,0}, - {99,2970,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, - {99,2970,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {99,1485,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, + {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, - {3600,108000,14000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple}, - {0,0,0,0,0} + {0,0,0,0,0}, }; /* H264 profile and level table*/ @@ -77,6 +81,8 @@ static const unsigned int h264_profile_level_table[][5]= {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline}, {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline}, {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline}, + {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileBaseline}, + {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline}, {0,0,0,0,0}, {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh}, @@ -89,19 +95,24 @@ static const unsigned int h264_profile_level_table[][5]= {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh}, {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh}, {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh}, + {5120,216000,25000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileHigh}, + {8192,245760,25000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh}, {0,0,0,0,0}, {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileMain}, - {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain}, - {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain}, - {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain}, - {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain}, - {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain}, - {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain}, - {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain}, - {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain}, - {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain}, + {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain}, + {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain}, + {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain}, + {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain}, + {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain}, + {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain}, + {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain}, + {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain}, + {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain}, + {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileMain}, + {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain}, {0,0,0,0,0} + }; /* H263 profile and level table*/ @@ -119,16 +130,33 @@ static const unsigned int h263_profile_level_table[][5]= {0,0,0,0,0} }; +#define Log2(number, power) { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) && power < 16) { temp >>=0x1; power++; } } +#define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power); num = q >> power; den = 0x1 << (16 - power); } + +#ifdef INPUT_BUFFER_LOG +FILE *inputBufferFile1; +char inputfilename [] = "/data/input.yuv"; +#endif +#ifdef OUTPUT_BUFFER_LOG +FILE *outputBufferFile1; +char outputfilename [] = "/data/output-bitstream.\0\0\0\0"; +#endif //constructor -venc_dev::venc_dev() +venc_dev::venc_dev(class omx_venc *venc_class) { -//nothing to do - + m_max_allowed_bitrate_check = false; + m_eLevel = 0; + m_eProfile = 0; + pthread_mutex_init(&loaded_start_stop_mlock, NULL); + pthread_cond_init (&loaded_start_stop_cond, NULL); + DEBUG_PRINT_LOW("venc_dev constructor"); } venc_dev::~venc_dev() { - //nothing to do + pthread_cond_destroy(&loaded_start_stop_cond); + pthread_mutex_destroy(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("venc_dev distructor"); } void* async_venc_message_thread (void *input) @@ -136,28 +164,31 @@ void* async_venc_message_thread (void *input) struct venc_ioctl_msg ioctl_msg ={NULL,NULL}; struct venc_timeout timeout; struct venc_msg venc_msg; + int error_code = 0; omx_venc *omx = reinterpret_cast<omx_venc*>(input); + prctl(PR_SET_NAME, (unsigned long)"VideoEncCallBackThread", 0, 0, 0); timeout.millisec = VEN_TIMEOUT_INFINITE; while(1) { - ioctl_msg.inputparam = NULL; - ioctl_msg.outputparam = (void*)&venc_msg; + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&venc_msg; /*Wait for a message from the video decoder driver*/ - if(ioctl(omx->handle->m_nDriver_fd,VEN_IOCTL_CMD_READ_NEXT_MSG,(void *)&ioctl_msg) < 0) + error_code = ioctl(omx->handle->m_nDriver_fd,VEN_IOCTL_CMD_READ_NEXT_MSG,(void *)&ioctl_msg); + if (error_code == -512) // ERESTARTSYS { - DEBUG_PRINT_ERROR("\nioctl VEN_IOCTL_CMD_READ_NEXT_MSG failed/stopped"); - break; + DEBUG_PRINT_ERROR("\n ERESTARTSYS received in ioctl read next msg!"); } - else + else if (error_code <0) + { + DEBUG_PRINT_ERROR("\nioctl VEN_IOCTL_CMD_READ_NEXT_MSG failed"); + break; + } + else if(omx->async_message_process(input,&venc_msg) < 0) { - /*Call Instance specific process function*/ - if(omx->async_message_process(input,&venc_msg) < 0) - { DEBUG_PRINT_ERROR("\nERROR: Wrong ioctl message"); break; - } } } DEBUG_PRINT_HIGH("omx_venc: Async Thread exit\n"); @@ -184,6 +215,21 @@ bool venc_dev::venc_open(OMX_U32 codec) } DEBUG_PRINT_LOW("\nm_nDriver_fd = %d\n", m_nDriver_fd); +#ifdef SINGLE_ENCODER_INSTANCE + OMX_U32 num_instances = 0; + ioctl_msg.in = NULL; + ioctl_msg.out = &num_instances; + if(ioctl (m_nDriver_fd, VEN_IOCTL_GET_NUMBER_INSTANCES, (void*)&ioctl_msg) < 0 ) + { + DEBUG_PRINT_ERROR("\nERROR: Request number of encoder instances failed"); + } + else if (num_instances > 1) + { + DEBUG_PRINT_ERROR("\nSecond encoder instance rejected!"); + venc_close(); + return false; + } +#endif // set the basic configuration of the video encoder driver m_sVenc_cfg.input_width = OMX_CORE_QCIF_WIDTH; m_sVenc_cfg.input_height= OMX_CORE_QCIF_HEIGHT; @@ -192,43 +238,61 @@ bool venc_dev::venc_open(OMX_U32 codec) m_sVenc_cfg.fps_num = 30; m_sVenc_cfg.fps_den = 1; m_sVenc_cfg.targetbitrate = 64000; +#ifdef MAX_RES_1080P + m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12_16M2KA; +#else m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12; +#endif if(codec == OMX_VIDEO_CodingMPEG4) { m_sVenc_cfg.codectype = VEN_CODEC_MPEG4; codec_profile.profile = VEN_PROFILE_MPEG4_SP; profile_level.level = VEN_LEVEL_MPEG4_2; +#ifdef OUTPUT_BUFFER_LOG + strcat(outputfilename, "m4v"); +#endif } else if(codec == OMX_VIDEO_CodingH263) { m_sVenc_cfg.codectype = VEN_CODEC_H263; codec_profile.profile = VEN_PROFILE_H263_BASELINE; profile_level.level = VEN_LEVEL_H263_20; +#ifdef OUTPUT_BUFFER_LOG + strcat(outputfilename, "263"); +#endif } if(codec == OMX_VIDEO_CodingAVC) { m_sVenc_cfg.codectype = VEN_CODEC_H264; codec_profile.profile = VEN_PROFILE_H264_BASELINE; profile_level.level = VEN_LEVEL_H264_1p1; +#ifdef OUTPUT_BUFFER_LOG + strcat(outputfilename, "264"); +#endif } - ioctl_msg.inputparam = (void*)&m_sVenc_cfg; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&m_sVenc_cfg; + ioctl_msg.out = NULL; if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < 0 ) { DEBUG_PRINT_ERROR("\nERROR: Request for setting base configuration failed"); return false; } - +#ifdef INPUT_BUFFER_LOG + inputBufferFile1 = fopen (inputfilename, "ab"); +#endif +#ifdef OUTPUT_BUFFER_LOG + outputBufferFile1 = fopen (outputfilename, "ab"); +#endif // Get the I/P and O/P buffer requirements - ioctl_msg.inputparam = NULL; - ioctl_msg.outputparam = (void*)&m_sInput_buff_property; + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&m_sInput_buff_property; if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for getting i/p buffer requirement failed"); return false; } - ioctl_msg.inputparam = NULL; - ioctl_msg.outputparam = (void*)&m_sOutput_buff_property; + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&m_sOutput_buff_property; if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for getting o/p buffer requirement failed"); @@ -242,7 +306,7 @@ bool venc_dev::venc_open(OMX_U32 codec) DEBUG_PRINT_HIGH("\n %s(): Init Profile/Level setting success", __func__); } - + recon_buffers_count = MAX_RECON_BUFFERS; return true; } @@ -258,6 +322,12 @@ void venc_dev::venc_close() close(m_nDriver_fd); m_nDriver_fd = -1; } +#ifdef INPUT_BUFFER_LOG + fclose (inputBufferFile1); +#endif +#ifdef OUTPUT_BUFFER_LOG + fclose (outputBufferFile1); +#endif } bool venc_dev::venc_set_buf_req(unsigned long *min_buff_count, @@ -274,8 +344,8 @@ bool venc_dev::venc_set_buf_req(unsigned long *min_buff_count, { temp_count = m_sInput_buff_property.actualcount; m_sInput_buff_property.actualcount = *actual_buff_count; - ioctl_msg.inputparam = (void*)&m_sInput_buff_property; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&m_sInput_buff_property; + ioctl_msg.out = NULL; if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for setting i/p buffer requirement failed"); @@ -291,8 +361,8 @@ bool venc_dev::venc_set_buf_req(unsigned long *min_buff_count, { temp_count = m_sOutput_buff_property.actualcount; m_sOutput_buff_property.actualcount = *actual_buff_count; - ioctl_msg.inputparam = (void*)&m_sOutput_buff_property; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&m_sOutput_buff_property; + ioctl_msg.out = NULL; if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for setting o/p buffer requirement failed"); @@ -307,6 +377,125 @@ bool venc_dev::venc_set_buf_req(unsigned long *min_buff_count, } +bool venc_dev::venc_loaded_start() +{ + struct timespec ts; + int status = 0; + if(ioctl (m_nDriver_fd,VEN_IOCTL_CMD_START, NULL) < 0) + { + DEBUG_PRINT_ERROR("ERROR: VEN_IOCTL_CMD_START failed"); + return false; + } + if (clock_gettime(CLOCK_REALTIME, &ts) < 0) + { + DEBUG_PRINT_ERROR("%s: clock_gettime failed", __func__); + return false; + } + ts.tv_sec += 1; + pthread_mutex_lock(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("%s: wait on start done", __func__); + status = pthread_cond_timedwait(&loaded_start_stop_cond, + &loaded_start_stop_mlock, &ts); + if (status != 0) + { + DEBUG_PRINT_ERROR("%s: error status = %d, %s", __func__, + status, strerror(status)); + pthread_mutex_unlock(&loaded_start_stop_mlock); + return false; + } + DEBUG_PRINT_LOW("%s: wait over on start done", __func__); + pthread_mutex_unlock(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("%s: venc_loaded_start success", __func__); + return true; +} + +bool venc_dev::venc_loaded_stop() +{ + struct timespec ts; + int status = 0; + if(ioctl (m_nDriver_fd,VEN_IOCTL_CMD_STOP, NULL) < 0) + { + DEBUG_PRINT_ERROR("ERROR: VEN_IOCTL_CMD_STOP failed"); + return false; + } + if (clock_gettime(CLOCK_REALTIME, &ts) < 0) + { + DEBUG_PRINT_ERROR("%s: clock_gettime failed", __func__); + return false; + } + ts.tv_sec += 1; + pthread_mutex_lock(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("%s: wait on stop done", __func__); + status = pthread_cond_timedwait(&loaded_start_stop_cond, + &loaded_start_stop_mlock, &ts); + if (status != 0) + { + DEBUG_PRINT_ERROR("%s: error status = %d, %s", __func__, + status, strerror(status)); + pthread_mutex_unlock(&loaded_start_stop_mlock); + return false; + } + DEBUG_PRINT_LOW("%s: wait over on stop done", __func__); + pthread_mutex_unlock(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("%s: venc_loaded_stop success", __func__); + return true; +} + +bool venc_dev::venc_loaded_start_done() +{ + pthread_mutex_lock(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("%s: signal start done", __func__); + pthread_cond_signal(&loaded_start_stop_cond); + pthread_mutex_unlock(&loaded_start_stop_mlock); + return true; +} + +bool venc_dev::venc_loaded_stop_done() +{ + pthread_mutex_lock(&loaded_start_stop_mlock); + DEBUG_PRINT_LOW("%s: signal stop done", __func__); + pthread_cond_signal(&loaded_start_stop_cond); + pthread_mutex_unlock(&loaded_start_stop_mlock); + return true; +} + +bool venc_dev::venc_get_seq_hdr(void *buffer, + unsigned buffer_size, unsigned *header_len) +{ + struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; + int i = 0; + DEBUG_PRINT_HIGH("venc_dev::venc_get_seq_hdr"); + venc_seqheader seq_in, seq_out; + seq_in.hdrlen = 0; + seq_in.bufsize = buffer_size; + seq_in.hdrbufptr = (unsigned char*)buffer; + if (seq_in.hdrbufptr == NULL) { + DEBUG_PRINT_ERROR("ERROR: malloc for sequence header failed"); + return false; + } + DEBUG_PRINT_LOW("seq_in: buf=%x, sz=%d, hdrlen=%d", seq_in.hdrbufptr, + seq_in.bufsize, seq_in.hdrlen); + + ioctl_msg.in = (void*)&seq_in; + ioctl_msg.out = (void*)&seq_out; + if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_SEQUENCE_HDR,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("ERROR: Request for getting sequence header failed"); + return false; + } + if (seq_out.hdrlen == 0) { + DEBUG_PRINT_ERROR("ERROR: Seq header returned zero length header"); + DEBUG_PRINT_ERROR("seq_out: buf=%x, sz=%d, hdrlen=%d", seq_out.hdrbufptr, + seq_out.bufsize, seq_out.hdrlen); + return false; + } + *header_len = seq_out.hdrlen; + DEBUG_PRINT_LOW("seq_out: buf=%x, sz=%d, hdrlen=%d", seq_out.hdrbufptr, + seq_out.bufsize, seq_out.hdrlen); + + return true; +} + bool venc_dev::venc_get_buf_req(unsigned long *min_buff_count, unsigned long *actual_buff_count, unsigned long *buff_size, @@ -316,8 +505,8 @@ bool venc_dev::venc_get_buf_req(unsigned long *min_buff_count, if(port == 0) { - ioctl_msg.inputparam = NULL; - ioctl_msg.outputparam = (void*)&m_sInput_buff_property; + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&m_sInput_buff_property; if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for getting i/p buffer requirement failed"); @@ -325,13 +514,19 @@ bool venc_dev::venc_get_buf_req(unsigned long *min_buff_count, } *min_buff_count = m_sInput_buff_property.mincount; *actual_buff_count = m_sInput_buff_property.actualcount; - *buff_size = m_sInput_buff_property.datasize - + (m_sInput_buff_property.datasize % m_sInput_buff_property.alignment) ; +#ifdef USE_ION + // For ION memory allocations of the allocated buffer size + // must be 4k aligned, hence aligning the input buffer + // size to 4k. + m_sInput_buff_property.datasize = (m_sInput_buff_property.datasize + 4095) + & (~4095); +#endif + *buff_size = m_sInput_buff_property.datasize; } else { - ioctl_msg.inputparam = NULL; - ioctl_msg.outputparam = (void*)&m_sOutput_buff_property; + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&m_sOutput_buff_property; if(ioctl (m_nDriver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for getting o/p buffer requirement failed"); @@ -339,8 +534,7 @@ bool venc_dev::venc_get_buf_req(unsigned long *min_buff_count, } *min_buff_count = m_sOutput_buff_property.mincount; *actual_buff_count = m_sOutput_buff_property.actualcount; - *buff_size = m_sOutput_buff_property.datasize - + (m_sOutput_buff_property.datasize % m_sOutput_buff_property.alignment) ; + *buff_size = m_sOutput_buff_property.datasize; } return true; @@ -350,7 +544,6 @@ bool venc_dev::venc_get_buf_req(unsigned long *min_buff_count, bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) { venc_ioctl_msg ioctl_msg = {NULL,NULL}; - OMX_U32 temp_out_buf_count = 0; DEBUG_PRINT_LOW("venc_set_param:: venc-720p\n"); switch(index) { @@ -361,6 +554,12 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamPortDefinition\n"); if(portDefn->nPortIndex == PORT_INDEX_IN) { + + if(!venc_set_encode_framerate(portDefn->format.video.xFramerate, 0)) + { + return false; + } + if(!venc_set_color_format(portDefn->format.video.eColorFormat)) { return false; @@ -372,9 +571,8 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) m_sVenc_cfg.input_height = portDefn->format.video.nFrameHeight; m_sVenc_cfg.input_width = portDefn->format.video.nFrameWidth; - temp_out_buf_count = m_sOutput_buff_property.actualcount; - ioctl_msg.inputparam = (void*)&m_sVenc_cfg; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&m_sVenc_cfg; + ioctl_msg.out = NULL; if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for setting base config failed"); @@ -382,8 +580,8 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) } DEBUG_PRINT_LOW("\n Updating the buffer count/size for the new resolution"); - ioctl_msg.inputparam = NULL; - ioctl_msg.outputparam = (void*)&m_sInput_buff_property; + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&m_sInput_buff_property; if(ioctl (m_nDriver_fd, VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for getting i/p bufreq failed"); @@ -395,8 +593,8 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) m_sInput_buff_property.maxcount, m_sInput_buff_property.actualcount, m_sInput_buff_property.mincount); - ioctl_msg.inputparam = NULL; - ioctl_msg.outputparam = (void*)&m_sOutput_buff_property; + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&m_sOutput_buff_property; if(ioctl (m_nDriver_fd, VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for getting o/p bufreq failed"); @@ -408,12 +606,9 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) "mincount = %u", m_sOutput_buff_property.datasize, m_sOutput_buff_property.maxcount, m_sOutput_buff_property.actualcount, m_sOutput_buff_property.mincount); + ioctl_msg.in = (void*)&m_sOutput_buff_property; + ioctl_msg.out = NULL; - if(temp_out_buf_count < 7) - temp_out_buf_count = 7; - m_sOutput_buff_property.actualcount = temp_out_buf_count; - ioctl_msg.inputparam = (void*)&m_sOutput_buff_property; - ioctl_msg.outputparam = NULL; if(ioctl (m_nDriver_fd, VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for setting o/p bufreq failed"); @@ -424,8 +619,8 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) (portDefn->nBufferCountActual <= m_sInput_buff_property.maxcount)) { m_sInput_buff_property.actualcount = portDefn->nBufferCountActual; - ioctl_msg.inputparam = (void*)&m_sInput_buff_property; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&m_sInput_buff_property; + ioctl_msg.out = NULL; if(ioctl(m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for setting i/p buffer requirements failed"); @@ -441,19 +636,18 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) m_level_set = false; if(venc_set_profile_level(0, 0)) { - DEBUG_PRINT_HIGH("\n %s(): Dynamic Profile/Level setting success", - __func__); + DEBUG_PRINT_HIGH("\n %s(): Profile/Level setting success", __func__); } } else { if((portDefn->nBufferCountActual >= m_sInput_buff_property.mincount) && - (m_sInput_buff_property.actualcount <= portDefn->nBufferCountActual) && + (m_sInput_buff_property.maxcount >= portDefn->nBufferCountActual) && (m_sInput_buff_property.datasize == portDefn->nBufferSize)) { m_sInput_buff_property.actualcount = portDefn->nBufferCountActual; - ioctl_msg.inputparam = (void*)&m_sInput_buff_property; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&m_sInput_buff_property; + ioctl_msg.out = NULL; if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: ioctl VEN_IOCTL_SET_INPUT_BUFFER_REQ failed"); @@ -469,26 +663,21 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) } else if(portDefn->nPortIndex == PORT_INDEX_OUT) { - if(!venc_set_encode_framerate(portDefn->format.video.xFramerate)) - { - return false; - } - - if(!venc_set_target_bitrate(portDefn->format.video.nBitrate)) + if(!venc_set_target_bitrate(portDefn->format.video.nBitrate, 0)) { return false; } if( (portDefn->nBufferCountActual >= m_sOutput_buff_property.mincount) && - (m_sOutput_buff_property.actualcount <= portDefn->nBufferCountActual) + (m_sOutput_buff_property.maxcount >= portDefn->nBufferCountActual) && (m_sOutput_buff_property.datasize == portDefn->nBufferSize) ) { m_sOutput_buff_property.actualcount = portDefn->nBufferCountActual; - ioctl_msg.inputparam = (void*)&m_sOutput_buff_property; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&m_sOutput_buff_property; + ioctl_msg.out = NULL; if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: ioctl VEN_IOCTL_SET_OUTPUT_BUFFER_REQ failed"); @@ -522,7 +711,7 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) } else if(portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { - if(!venc_set_encode_framerate(portFmt->xFramerate)) + if(!venc_set_encode_framerate(portFmt->xFramerate, 0)) { return false; } @@ -541,7 +730,7 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { - if(!venc_set_target_bitrate(pParam->nTargetBitrate)) + if(!venc_set_target_bitrate(pParam->nTargetBitrate, 0)) { DEBUG_PRINT_ERROR("\nERROR: Target Bit Rate setting failed"); return false; @@ -561,21 +750,52 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) case OMX_IndexParamVideoMpeg4: { OMX_VIDEO_PARAM_MPEG4TYPE* pParam; + OMX_U32 bFrames = 0; + pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData; DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoMpeg4\n"); if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { - if(!venc_set_intra_period (pParam->nPFrames)) + if(!venc_set_voptiming_cfg(pParam->nTimeIncRes)) { - DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + DEBUG_PRINT_ERROR("\nERROR: Request for setting vop_timing failed"); return false; } - m_profile_set = false; m_level_set = false; if(!venc_set_profile_level (pParam->eProfile, pParam->eLevel)) { - DEBUG_PRINT_ERROR("\nWARNING: Unsuccessful in updating Profile and level"); + DEBUG_PRINT_ERROR("\nERROR: Unsuccessful in updating Profile and level"); + return false; + } +#ifdef MAX_RES_1080P + else { + if(pParam->eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) + { + if(pParam->nBFrames) + { + DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported"); + bFrames = 1; + } + } + else + { + if(pParam->nBFrames) + { + DEBUG_PRINT_ERROR("Warning: B frames not supported\n"); + bFrames = 0; + } + } + } +#endif + if(!venc_set_intra_period (pParam->nPFrames,bFrames)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + if(!venc_set_multislice_cfg(OMX_IndexParamVideoMpeg4,pParam->nSliceHeaderSpacing)) + { + DEBUG_PRINT_ERROR("\nERROR: Unsuccessful in updating slice_config"); return false; } } @@ -589,19 +809,22 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) { OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData; DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoH263\n"); + OMX_U32 bFrames = 0; if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { - if(venc_set_intra_period (pParam->nPFrames) == false) + m_profile_set = false; + m_level_set = false; + if(!venc_set_profile_level (pParam->eProfile, pParam->eLevel)) { - DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + DEBUG_PRINT_ERROR("\nERROR: Unsuccessful in updating Profile and level"); return false; } + if (pParam->nBFrames) + DEBUG_PRINT_ERROR("\nWARNING: B frame not supported for H.263"); - m_profile_set = false; - m_level_set = false; - if(!venc_set_profile_level (pParam->eProfile, pParam->eLevel)) + if(venc_set_intra_period (pParam->nPFrames, bFrames) == false) { - DEBUG_PRINT_ERROR("\nWARNING: Unsuccessful in updating Profile and level"); + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); return false; } } @@ -615,21 +838,60 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) { DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoAvc\n"); OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData; + OMX_U32 bFrames = 0; + if(pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { - if(venc_set_intra_period (pParam->nPFrames) == false) - { - DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); - return false; - } DEBUG_PRINT_LOW("pParam->eProfile :%d ,pParam->eLevel %d\n", pParam->eProfile,pParam->eLevel); m_profile_set = false; m_level_set = false; + if(!venc_set_profile_level (pParam->eProfile,pParam->eLevel)) { - DEBUG_PRINT_ERROR("\nWARNING: Unsuccessful in updating Profile and level"); + DEBUG_PRINT_ERROR("\nERROR: Unsuccessful in updating Profile and level %d, %d", + pParam->eProfile, pParam->eLevel); + return false; + } +#ifdef MAX_RES_1080P + else { + if(pParam->eProfile != OMX_VIDEO_AVCProfileBaseline) + { + if(pParam->nBFrames) + { + DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported"); + bFrames = 1; + } + } + else + { + if(pParam->nBFrames) + { + DEBUG_PRINT_ERROR("Warning: B frames not supported\n"); + bFrames = 0; + } + } + } +#endif + if(!venc_set_intra_period (pParam->nPFrames, bFrames)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + if(!venc_set_entropy_config (pParam->bEntropyCodingCABAC, pParam->nCabacInitIdc)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Entropy failed"); + return false; + } + if(!venc_set_inloop_filter (pParam->eLoopFilterMode)) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Inloop filter failed"); + return false; + } + if(!venc_set_multislice_cfg(OMX_IndexParamVideoAvc, pParam->nSliceHeaderSpacing)) + { + DEBUG_PRINT_ERROR("\nWARNING: Unsuccessful in updating slice_config"); return false; } } @@ -640,6 +902,44 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) //TBD, lot of other variables to be updated, yet to decide break; } + case OMX_IndexParamVideoIntraRefresh: + { + DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoIntraRefresh\n"); + OMX_VIDEO_PARAM_INTRAREFRESHTYPE *intra_refresh = + (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)paramData; + if(intra_refresh->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(venc_set_intra_refresh(intra_refresh->eRefreshMode, intra_refresh->nCirMBs) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Intra refresh failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoIntraRefresh"); + } + break; + } + case OMX_IndexParamVideoErrorCorrection: + { + DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoErrorCorrection\n"); + OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *error_resilience = + (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)paramData; + if(error_resilience->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(venc_set_error_resilience(error_resilience) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Setting Intra refresh failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for OMX_IndexParamVideoErrorCorrection"); + } + break; + } case OMX_IndexParamVideoProfileLevelCurrent: { DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoProfileLevelCurrent\n"); @@ -682,26 +982,39 @@ bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) } break; } - case OMX_IndexParamVideoSliceFMO: + case OMX_ExtraDataVideoEncoderSliceInfo: { - DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoSliceFMO\n"); - OMX_VIDEO_PARAM_AVCSLICEFMO *avc_slice_fmo = - (OMX_VIDEO_PARAM_AVCSLICEFMO*)paramData; - DEBUG_PRINT_LOW("\n portindex = %u", avc_slice_fmo->nPortIndex); - if(avc_slice_fmo->nPortIndex == (OMX_U32) PORT_INDEX_OUT) - { - if(venc_set_multislice_cfg(avc_slice_fmo->eSliceMode) == false) - { - DEBUG_PRINT_ERROR("\nERROR: Setting Multislice cfg failed"); - return false; - } - } - else + DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataVideoEncoderSliceInfo"); + OMX_U32 extra_data = *(OMX_U32 *)paramData; + if(venc_set_extradata(extra_data) == false) { - DEBUG_PRINT_ERROR("\nERROR: Invalid Port Index for Multislice cfg"); + DEBUG_PRINT_ERROR("ERROR: Setting " + "OMX_QcomIndexParamIndexExtraDataType failed"); + return false; } break; } + case OMX_QcomIndexEnableSliceDeliveryMode: + { + QOMX_EXTNINDEX_PARAMTYPE* pParam = + (QOMX_EXTNINDEX_PARAMTYPE*)paramData; + if(pParam->nPortIndex == PORT_INDEX_OUT) + { + if(venc_set_slice_delivery_mode(pParam->bEnable) == false) + { + DEBUG_PRINT_ERROR("Setting slice delivery mode failed"); + return OMX_ErrorUnsupportedSetting; + } + } + else + { + DEBUG_PRINT_ERROR("OMX_QcomIndexEnableSliceDeliveryMode " + "called on wrong port(%d)", pParam->nPortIndex); + return OMX_ErrorBadPortIndex; + } + break; + } + case OMX_IndexParamVideoSliceFMO: default: DEBUG_PRINT_ERROR("\nERROR: Unsupported parameter in venc_set_param: %u", index); @@ -723,10 +1036,16 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) { OMX_VIDEO_CONFIG_BITRATETYPE *bit_rate = (OMX_VIDEO_CONFIG_BITRATETYPE *) configData; + if(m_max_allowed_bitrate_check && + !venc_max_allowed_bitrate_check(bit_rate->nEncodeBitrate)) + { + DEBUG_PRINT_ERROR("Max Allowed Bitrate Check failed"); + return false; + } DEBUG_PRINT_LOW("\n venc_set_config: OMX_IndexConfigVideoBitrate"); if(bit_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) { - if(venc_set_target_bitrate(bit_rate->nEncodeBitrate) == false) + if(venc_set_target_bitrate(bit_rate->nEncodeBitrate, 1) == false) { DEBUG_PRINT_ERROR("\nERROR: Setting Target Bit rate failed"); return false; @@ -745,7 +1064,7 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) DEBUG_PRINT_LOW("\n venc_set_config: OMX_IndexConfigVideoFramerate"); if(frame_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) { - if(venc_set_encode_framerate(frame_rate->xEncodeFramerate) == false) + if(venc_set_encode_framerate(frame_rate->xEncodeFramerate, 1) == false) { DEBUG_PRINT_ERROR("\nERROR: Setting Encode Framerate failed"); return false; @@ -757,6 +1076,21 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) } break; } + case QOMX_IndexConfigVideoIntraperiod: + { + DEBUG_PRINT_LOW("venc_set_param:QOMX_IndexConfigVideoIntraperiod\n"); + QOMX_VIDEO_INTRAPERIODTYPE *intraperiod = + (QOMX_VIDEO_INTRAPERIODTYPE *)configData; + if(intraperiod->nPortIndex == (OMX_U32) PORT_INDEX_OUT) + { + if(venc_set_intra_period(intraperiod->nPFrames, intraperiod->nBFrames) == false) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); + return false; + } + } + break; + } case OMX_IndexConfigVideoIntraVOPRefresh: { OMX_CONFIG_INTRAREFRESHVOPTYPE *intra_vop_refresh = (OMX_CONFIG_INTRAREFRESHVOPTYPE *) @@ -776,6 +1110,25 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) } break; } + case OMX_IndexConfigCommonRotate: + { + OMX_CONFIG_ROTATIONTYPE *config_rotation = + reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData); + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + OMX_U32 nFrameWidth; + + DEBUG_PRINT_HIGH("\nvenc_set_config: updating the new Dims"); + nFrameWidth = m_sVenc_cfg.input_width; + m_sVenc_cfg.input_width = m_sVenc_cfg.input_height; + m_sVenc_cfg.input_height = nFrameWidth; + ioctl_msg.in = (void*)&m_sVenc_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < 0) { + DEBUG_PRINT_ERROR("\nERROR: Dimension Change for Rotation failed"); + return false; + } + break; + } default: DEBUG_PRINT_ERROR("\n Unsupported config index = %u", index); break; @@ -786,6 +1139,9 @@ bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) unsigned venc_dev::venc_stop( void) { +#ifdef MAX_RES_1080P + pmem_free(); +#endif return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_STOP,NULL); } @@ -799,6 +1155,16 @@ unsigned venc_dev::venc_resume(void) return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_RESUME,NULL) ; } +unsigned venc_dev::venc_start_done(void) +{ + return 0; +} + +unsigned venc_dev::venc_stop_done(void) +{ + return 0; +} + unsigned venc_dev::venc_start(void) { DEBUG_PRINT_HIGH("\n %s(): Check Profile/Level set in driver before start", @@ -814,7 +1180,254 @@ unsigned venc_dev::venc_start(void) __func__, codec_profile.profile, profile_level.level); } - return ioctl(m_nDriver_fd, VEN_IOCTL_CMD_START, NULL); + if(m_max_allowed_bitrate_check && + !venc_max_allowed_bitrate_check(bitrate.target_bitrate)) + { + DEBUG_PRINT_ERROR("Maximum Allowed Bitrate Check failed"); + return -1; + } + + venc_config_print(); + +#ifdef MAX_RES_1080P + if((codec_profile.profile == VEN_PROFILE_MPEG4_SP) || + (codec_profile.profile == VEN_PROFILE_H264_BASELINE) || + (codec_profile.profile == VEN_PROFILE_H263_BASELINE)) + recon_buffers_count = MAX_RECON_BUFFERS - 2; + else + recon_buffers_count = MAX_RECON_BUFFERS; + + if (!venc_allocate_recon_buffers()) + return ioctl(m_nDriver_fd, VEN_IOCTL_CMD_START, NULL); + else + { + DEBUG_PRINT_ERROR("Failed in creating Recon buffers\n"); + return -1; + } +#else + return ioctl(m_nDriver_fd, VEN_IOCTL_CMD_START, NULL); +#endif +} + +#ifdef MAX_RES_1080P +OMX_U32 venc_dev::venc_allocate_recon_buffers() +{ + OMX_U32 yuv_size; + struct venc_ioctl_msg ioctl_msg; + struct venc_recon_buff_size recon_buff_size; + + recon_buff_size.width = ((m_sVenc_cfg.input_width + 15) / 16) * 16; + recon_buff_size.height = ((m_sVenc_cfg.input_height + 15) / 16 ) * 16; + + DEBUG_PRINT_LOW("Width %d, Height %d, w_round %d, h_round %d\n", m_sVenc_cfg.input_width, + m_sVenc_cfg.input_height, recon_buff_size.width, recon_buff_size.height); + + ioctl_msg.in = NULL; + ioctl_msg.out = (void*)&recon_buff_size; + + if (ioctl (m_nDriver_fd,VEN_IOCTL_GET_RECON_BUFFER_SIZE, (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\n VEN_IOCTL_GET_RECON_BUFFER_SIZE Failed for width: %d, Height %d" , + recon_buff_size.width, recon_buff_size.height); + return OMX_ErrorInsufficientResources; + } + + DEBUG_PRINT_HIGH("Width %d, Height %d, w_round %d, h_round %d, yuv_size %d alignment %d count %d\n", + m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, recon_buff_size.width, + recon_buff_size.height, recon_buff_size.size, recon_buff_size.alignment, + recon_buffers_count); + + for(int i = 0; i < recon_buffers_count; i++) + { + if(pmem_allocate(recon_buff_size.size, recon_buff_size.alignment,i)) + { + DEBUG_PRINT_ERROR("Error returned in allocating recon buffers\n"); + return -1; + } + } + return 0; +} +OMX_U32 venc_dev::pmem_allocate(OMX_U32 size, OMX_U32 alignment, OMX_U32 count) +{ + OMX_U32 pmem_fd = -1; + OMX_U32 width, height; + void *buf_addr = NULL; + struct venc_ioctl_msg ioctl_msg; + struct venc_recon_addr recon_addr; + int rc = 0; + +#ifdef USE_ION + recon_buff[count].ion_device_fd = open (MEM_DEVICE,O_RDONLY); + if(recon_buff[count].ion_device_fd < 0) + { + DEBUG_PRINT_ERROR("\nERROR: ION Device open() Failed"); + return -1; + } + + recon_buff[count].alloc_data.len = size; + recon_buff[count].alloc_data.flags = (ION_HEAP(MEM_HEAP_ID) | + ION_HEAP(ION_IOMMU_HEAP_ID)); + recon_buff[count].alloc_data.align = clip2(alignment); + if (recon_buff[count].alloc_data.align != 8192) + recon_buff[count].alloc_data.align = 8192; + + rc = ioctl(recon_buff[count].ion_device_fd,ION_IOC_ALLOC,&recon_buff[count].alloc_data); + if(rc || !recon_buff[count].alloc_data.handle) { + DEBUG_PRINT_ERROR("\n ION ALLOC memory failed "); + recon_buff[count].alloc_data.handle=NULL; + return -1; + } + + recon_buff[count].ion_alloc_fd.handle = recon_buff[count].alloc_data.handle; + rc = ioctl(recon_buff[count].ion_device_fd,ION_IOC_MAP,&recon_buff[count].ion_alloc_fd); + if(rc) { + DEBUG_PRINT_ERROR("\n ION MAP failed "); + recon_buff[count].ion_alloc_fd.fd =-1; + recon_buff[count].ion_alloc_fd.fd =-1; + return -1; + } + pmem_fd = recon_buff[count].ion_alloc_fd.fd; +#else + struct pmem_allocation allocation; + pmem_fd = open(MEM_DEVICE, O_RDWR); + + if ((int)(pmem_fd) < 0) + { + DEBUG_PRINT_ERROR("\n Failed to get an pmem handle"); + return -1; + } + + allocation.size = size; + allocation.align = clip2(alignment); + + if (allocation.align != 8192) + allocation.align = 8192; + + if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) + { + DEBUG_PRINT_ERROR("\n Aligment(%u) failed with pmem driver Sz(%lu)", + allocation.align, allocation.size); + return -1; + } +#endif + buf_addr = mmap(NULL, size, + PROT_READ | PROT_WRITE, + MAP_SHARED, pmem_fd, 0); + + if (buf_addr == (void*) MAP_FAILED) + { + close(pmem_fd); + pmem_fd = -1; + DEBUG_PRINT_ERROR("Error returned in allocating recon buffers buf_addr: %p\n",buf_addr); +#ifdef USE_ION + if(ioctl(recon_buff[count].ion_device_fd,ION_IOC_FREE, + &recon_buff[count].alloc_data.handle)) { + DEBUG_PRINT_ERROR("ion recon buffer free failed"); + } + recon_buff[count].alloc_data.handle = NULL; + recon_buff[count].ion_alloc_fd.fd =-1; + close(recon_buff[count].ion_device_fd); + recon_buff[count].ion_device_fd =-1; +#endif + return -1; + } + + DEBUG_PRINT_HIGH("\n Allocated virt:%p, FD: %d of size %d \n", buf_addr, pmem_fd, size); + + recon_addr.buffer_size = size; + recon_addr.pmem_fd = pmem_fd; + recon_addr.offset = 0; + recon_addr.pbuffer = (unsigned char *)buf_addr; + + ioctl_msg.in = (void*)&recon_addr; + ioctl_msg.out = NULL; + + if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_RECON_BUFFER, (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("Failed to set the Recon_buffers\n"); + return -1; + } + + recon_buff[count].virtual_address = (unsigned char *) buf_addr; + recon_buff[count].size = size; + recon_buff[count].offset = 0; + recon_buff[count].pmem_fd = pmem_fd; + + DEBUG_PRINT_ERROR("\n Allocated virt:%p, FD: %d of size %d at index: %d\n", recon_buff[count].virtual_address, + recon_buff[count].pmem_fd, recon_buff[count].size, count); + return 0; +} + +OMX_U32 venc_dev::pmem_free() +{ + int cnt = 0; + struct venc_ioctl_msg ioctl_msg; + struct venc_recon_addr recon_addr; + for (cnt = 0; cnt < recon_buffers_count; cnt++) + { + if(recon_buff[cnt].pmem_fd) + { + recon_addr.pbuffer = recon_buff[cnt].virtual_address; + recon_addr.offset = recon_buff[cnt].offset; + recon_addr.pmem_fd = recon_buff[cnt].pmem_fd; + recon_addr.buffer_size = recon_buff[cnt].size; + ioctl_msg.in = (void*)&recon_addr; + ioctl_msg.out = NULL; + if(ioctl(m_nDriver_fd, VEN_IOCTL_FREE_RECON_BUFFER ,&ioctl_msg) < 0) + DEBUG_PRINT_ERROR("VEN_IOCTL_FREE_RECON_BUFFER failed"); + munmap(recon_buff[cnt].virtual_address, recon_buff[cnt].size); + close(recon_buff[cnt].pmem_fd); +#ifdef USE_ION + if(ioctl(recon_buff[cnt].ion_device_fd,ION_IOC_FREE, + &recon_buff[cnt].alloc_data.handle)) { + DEBUG_PRINT_ERROR("ion recon buffer free failed"); + } + recon_buff[cnt].alloc_data.handle = NULL; + recon_buff[cnt].ion_alloc_fd.fd =-1; + close(recon_buff[cnt].ion_device_fd); + recon_buff[cnt].ion_device_fd =-1; +#endif + DEBUG_PRINT_LOW("\n cleaning Index %d of size %d \n",cnt,recon_buff[cnt].size); + recon_buff[cnt].pmem_fd = -1; + recon_buff[cnt].virtual_address = NULL; + recon_buff[cnt].offset = 0; + recon_buff[cnt].alignment = 0; + recon_buff[cnt].size = 0; + } + } + return 0; +} +#endif + +void venc_dev::venc_config_print() +{ + + DEBUG_PRINT_HIGH("\nENC_CONFIG: Codec: %d, Profile %d, level : %d", + m_sVenc_cfg.codectype, codec_profile.profile, profile_level.level); + + DEBUG_PRINT_HIGH("\n ENC_CONFIG: Width: %d, Height:%d, Fps: %d", + m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, + m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: Bitrate: %d, RC: %d, I-Period: %d", + bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: qpI: %d, qpP: %d, qpb: 0", + session_qp.iframeqp, session_qp.pframqp); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: VOP_Resolution: %d, Slice-Mode: %d, Slize_Size: %d", + voptimecfg.voptime_resolution, multislice.mslice_mode, + multislice.mslice_size); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: EntropyMode: %d, CabacModel: %d", + entropy.longentropysel, entropy.cabacmodel); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: DB-Mode: %d, alpha: %d, Beta: %d\n", + dbkfilter.db_mode, dbkfilter.slicealpha_offset, + dbkfilter.slicebeta_offset); + + DEBUG_PRINT_HIGH("\nENC_CONFIG: IntraMB/Frame: %d, HEC: %d\n", + intra_refresh.mbcount, hec.header_extension); } unsigned venc_dev::venc_flush( unsigned port) @@ -824,17 +1437,19 @@ unsigned venc_dev::venc_flush( unsigned port) if(port == PORT_INDEX_IN) { + DEBUG_PRINT_HIGH("Calling Input Flush"); buffer_index.flush_mode = VEN_FLUSH_INPUT; - ioctl_msg.inputparam = (void*)&buffer_index; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&buffer_index; + ioctl_msg.out = NULL; return ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FLUSH,(void*)&ioctl_msg); } else if(port == PORT_INDEX_OUT) { + DEBUG_PRINT_HIGH("Calling Output Flush"); buffer_index.flush_mode = VEN_FLUSH_OUTPUT; - ioctl_msg.inputparam = (void*)&buffer_index; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&buffer_index; + ioctl_msg.out = NULL; return ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FLUSH,(void*)&ioctl_msg); } else @@ -846,7 +1461,7 @@ unsigned venc_dev::venc_flush( unsigned port) //allocating I/P memory from pmem and register with the device -bool venc_dev::venc_use_buf(void *buf_addr, unsigned port) +bool venc_dev::venc_use_buf(void *buf_addr, unsigned port,unsigned) { struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; struct pmem *pmem_tmp; @@ -861,10 +1476,10 @@ bool venc_dev::venc_use_buf(void *buf_addr, unsigned port) dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; dev_buffer.fd = pmem_tmp->fd; dev_buffer.maped_size = pmem_tmp->size; - dev_buffer.nsize = pmem_tmp->size; + dev_buffer.sz = pmem_tmp->size; dev_buffer.offset = pmem_tmp->offset; - ioctl_msg.inputparam = (void*)&dev_buffer; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&dev_buffer; + ioctl_msg.out = NULL; DEBUG_PRINT_LOW("\n venc_use_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ dev_buffer.pbuffer, \ @@ -882,11 +1497,11 @@ bool venc_dev::venc_use_buf(void *buf_addr, unsigned port) { dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; dev_buffer.fd = pmem_tmp->fd; - dev_buffer.nsize = pmem_tmp->size; + dev_buffer.sz = pmem_tmp->size; dev_buffer.maped_size = pmem_tmp->size; dev_buffer.offset = pmem_tmp->offset; - ioctl_msg.inputparam = (void*)&dev_buffer; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&dev_buffer; + ioctl_msg.out = NULL; DEBUG_PRINT_LOW("\n venc_use_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ dev_buffer.pbuffer, \ @@ -924,10 +1539,10 @@ bool venc_dev::venc_free_buf(void *buf_addr, unsigned port) dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; dev_buffer.fd = pmem_tmp->fd; dev_buffer.maped_size = pmem_tmp->size; - dev_buffer.nsize = pmem_tmp->size; + dev_buffer.sz = pmem_tmp->size; dev_buffer.offset = pmem_tmp->offset; - ioctl_msg.inputparam = (void*)&dev_buffer; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&dev_buffer; + ioctl_msg.out = NULL; DEBUG_PRINT_LOW("\n venc_free_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ dev_buffer.pbuffer, \ @@ -945,11 +1560,11 @@ bool venc_dev::venc_free_buf(void *buf_addr, unsigned port) { dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; dev_buffer.fd = pmem_tmp->fd; - dev_buffer.nsize = pmem_tmp->size; + dev_buffer.sz = pmem_tmp->size; dev_buffer.maped_size = pmem_tmp->size; dev_buffer.offset = pmem_tmp->offset; - ioctl_msg.inputparam = (void*)&dev_buffer; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&dev_buffer; + ioctl_msg.out = NULL; DEBUG_PRINT_LOW("\n venc_free_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ dev_buffer.pbuffer, \ @@ -972,7 +1587,7 @@ bool venc_dev::venc_free_buf(void *buf_addr, unsigned port) return true; } -bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf) +bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf,unsigned,unsigned) { struct venc_buffer frameinfo; struct pmem *temp_buffer; @@ -1000,14 +1615,14 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf) } frameinfo.clientdata = (void *) buffer; - frameinfo.size = bufhdr->nFilledLen; + frameinfo.sz = bufhdr->nFilledLen; frameinfo.len = bufhdr->nFilledLen; frameinfo.flags = bufhdr->nFlags; frameinfo.offset = bufhdr->nOffset; frameinfo.timestamp = bufhdr->nTimeStamp; DEBUG_PRINT_LOW("\n i/p TS = %u", (OMX_U32)frameinfo.timestamp); - ioctl_msg.inputparam = &frameinfo; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = &frameinfo; + ioctl_msg.out = NULL; DEBUG_PRINT_LOW("DBG: i/p frameinfo: bufhdr->pBuffer = %p, ptrbuffer = %p, offset = %u, len = %u", bufhdr->pBuffer, frameinfo.ptrbuffer, frameinfo.offset, frameinfo.len); @@ -1016,10 +1631,49 @@ bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf) /*Generate an async error and move to invalid state*/ return false; } +#ifdef INPUT_BUFFER_LOG +#ifdef MAX_RES_1080P + + int y_size = 0; + int c_offset = 0; + unsigned char *buf_addr = NULL; + + y_size = m_sVenc_cfg.input_width * m_sVenc_cfg.input_height; + //chroma offset is y_size aligned to the 2k boundary + c_offset= (y_size + 2047) & (~(2047)); + + if(pmem_data_buf) + { + DEBUG_PRINT_LOW("\n Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf); + buf_addr = (OMX_U8 *)pmem_data_buf; + } + else + { + DEBUG_PRINT_LOW("\n Shared PMEM addr for i/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer); + buf_addr = (unsigned char *)mmap(NULL, + ((encoder_media_buffer_type *)bufhdr->pBuffer)->meta_handle->data[2], + PROT_READ|PROT_WRITE, MAP_SHARED, + ((encoder_media_buffer_type *)bufhdr->pBuffer)->meta_handle->data[0], 0); + } + if(inputBufferFile1) + { + fwrite((const char *)buf_addr, y_size, 1,inputBufferFile1); + fwrite((const char *)(buf_addr + c_offset), (y_size>>1), 1,inputBufferFile1); + } + + munmap (buf_addr, ((encoder_media_buffer_type *)bufhdr->pBuffer)->meta_handle->data[2]); +#else + if(inputBufferFile1) + { + fwrite((const char *)frameinfo.ptrbuffer, frameinfo.len, 1,inputBufferFile1); + } +#endif + +#endif return true; } -bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf) +bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf,unsigned,unsigned) { struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; struct pmem *temp_buffer = NULL; @@ -1044,12 +1698,12 @@ bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf) } frameinfo.clientdata = buffer; - frameinfo.size = bufhdr->nAllocLen; + frameinfo.sz = bufhdr->nAllocLen; frameinfo.flags = bufhdr->nFlags; frameinfo.offset = bufhdr->nOffset; - ioctl_msg.inputparam = &frameinfo; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = &frameinfo; + ioctl_msg.out = NULL; DEBUG_PRINT_LOW("DBG: o/p frameinfo: bufhdr->pBuffer = %p, ptrbuffer = %p, offset = %u, len = %u", bufhdr->pBuffer, frameinfo.ptrbuffer, frameinfo.offset, frameinfo.len); if(ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) @@ -1061,6 +1715,41 @@ bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf) return true; } +bool venc_dev::venc_set_slice_delivery_mode(OMX_BOOL enable) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + DEBUG_PRINT_HIGH("Set slice_delivery_mode: %d", enable); + if(multislice.mslice_mode == VEN_MSLICE_CNT_MB) + { + if(ioctl(m_nDriver_fd, VEN_IOCTL_SET_SLICE_DELIVERY_MODE) < 0) + { + DEBUG_PRINT_ERROR("Request for setting slice delivery mode failed"); + return false; + } + } + else + { + DEBUG_PRINT_ERROR("WARNING: slice_mode[%d] is not VEN_MSLICE_CNT_MB to set " + "slice delivery mode to the driver.", multislice.mslice_mode); + } + return true; +} + +bool venc_dev::venc_set_extradata(OMX_U32 extra_data) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + DEBUG_PRINT_HIGH("venc_set_extradata:: %x", extra_data); + ioctl_msg.in = (void*)&extra_data; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd, VEN_IOCTL_SET_EXTRADATA, (void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("ERROR: Request for setting extradata failed"); + return false; + } + + return true; +} + bool venc_dev::venc_set_session_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp) { venc_ioctl_msg ioctl_msg = {NULL,NULL}; @@ -1071,8 +1760,8 @@ bool venc_dev::venc_set_session_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp) qp.iframeqp = i_frame_qp; qp.pframqp = p_frame_qp; - ioctl_msg.inputparam = (void*)&qp; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&qp; + ioctl_msg.out = NULL; if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_SESSION_QP,(void*)&ioctl_msg)< 0) { DEBUG_PRINT_ERROR("\nERROR: Request for setting session qp failed"); @@ -1094,13 +1783,22 @@ bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel) unsigned long mb_per_frame = 0, mb_per_sec = 0; DEBUG_PRINT_LOW("venc_set_profile_level:: eProfile = %d, Level = %d", eProfile, eLevel); - + mb_per_frame = ((m_sVenc_cfg.input_height + 15) >> 4)* + ((m_sVenc_cfg.input_width + 15) >> 4); if((eProfile == 0) && (eLevel == 0) && m_profile_set && m_level_set) { DEBUG_PRINT_LOW("\n Profile/Level setting complete before venc_start"); return true; } + if(eProfile && eLevel) + { + /* non-zero values will be set by user, saving the same*/ + m_eProfile = eProfile; + m_eLevel = eLevel; + DEBUG_PRINT_HIGH("Profile/Level set equal to %d/%d",m_eProfile, m_eLevel); + } + DEBUG_PRINT_LOW("\n Validating Profile/Level from table"); if(!venc_validate_profile_level(&eProfile, &eLevel)) { @@ -1139,44 +1837,51 @@ bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel) "OMX_VIDEO_MPEG4Level5 = %d", eLevel, OMX_VIDEO_MPEG4Level0, OMX_VIDEO_MPEG4Level1, OMX_VIDEO_MPEG4Level2, OMX_VIDEO_MPEG4Level3, OMX_VIDEO_MPEG4Level4, OMX_VIDEO_MPEG4Level5); - switch(eLevel) + if(mb_per_frame >= 3600) { - case OMX_VIDEO_MPEG4Level0: - requested_level.level = VEN_LEVEL_MPEG4_0; - break; - case OMX_VIDEO_MPEG4Level1: - requested_level.level = VEN_LEVEL_MPEG4_1; - break; - case OMX_VIDEO_MPEG4Level2: - requested_level.level = VEN_LEVEL_MPEG4_2; - break; - case OMX_VIDEO_MPEG4Level3: - requested_level.level = VEN_LEVEL_MPEG4_3; - break; - case OMX_VIDEO_MPEG4Level4a: - requested_level.level = VEN_LEVEL_MPEG4_4; - break; - case OMX_VIDEO_MPEG4Level5: - mb_per_frame = ((m_sVenc_cfg.input_height + 15) >> 4)* - ((m_sVenc_cfg.input_width + 15) >> 4); - mb_per_sec = mb_per_frame * (m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den); - - if((mb_per_frame >= profile_tbl[0]) && - (mb_per_sec >= profile_tbl[1])) - { - DEBUG_PRINT_LOW("\nMPEG4 Level 6 is set for 720p resolution"); + if(requested_profile.profile == VEN_PROFILE_MPEG4_ASP) + requested_level.level = VEN_LEVEL_MPEG4_5; + if(requested_profile.profile == VEN_PROFILE_MPEG4_SP) requested_level.level = VEN_LEVEL_MPEG4_6; - } - else + } + else + { + switch(eLevel) { - DEBUG_PRINT_LOW("\nMPEG4 Level 5 is set for non-720p resolution"); - requested_level.level = VEN_LEVEL_MPEG4_5; + case OMX_VIDEO_MPEG4Level0: + requested_level.level = VEN_LEVEL_MPEG4_0; + break; + case OMX_VIDEO_MPEG4Level1: + requested_level.level = VEN_LEVEL_MPEG4_1; + break; + case OMX_VIDEO_MPEG4Level2: + requested_level.level = VEN_LEVEL_MPEG4_2; + break; + case OMX_VIDEO_MPEG4Level3: + requested_level.level = VEN_LEVEL_MPEG4_3; + break; + case OMX_VIDEO_MPEG4Level4a: + requested_level.level = VEN_LEVEL_MPEG4_4; + break; + case OMX_VIDEO_MPEG4Level5: + mb_per_sec = mb_per_frame * (m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den); + if((requested_profile.profile == VEN_PROFILE_MPEG4_SP) && (mb_per_frame >= profile_tbl[0]) && + (mb_per_sec >= profile_tbl[1])) + { + DEBUG_PRINT_LOW("\nMPEG4 Level 6 is set for 720p resolution"); + requested_level.level = VEN_LEVEL_MPEG4_6; + } + else + { + DEBUG_PRINT_LOW("\nMPEG4 Level 5 is set for non-720p resolution"); + requested_level.level = VEN_LEVEL_MPEG4_5; + } + break; + default: + return false; + // TODO update corresponding levels for MPEG4_LEVEL_3b,MPEG4_LEVEL_6 + break; } - break; - default: - return false; - // TODO update corresponding levels for MPEG4_LEVEL_3b,MPEG4_LEVEL_6 - break; } } else if(m_sVenc_cfg.codectype == VEN_CODEC_H263) @@ -1276,19 +1981,26 @@ bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel) case OMX_VIDEO_AVCLevel31: requested_level.level = VEN_LEVEL_H264_3p1; break; + case OMX_VIDEO_AVCLevel32: + requested_level.level = VEN_LEVEL_H264_3p2; + break; + case OMX_VIDEO_AVCLevel4: + requested_level.level = VEN_LEVEL_H264_4; + break; default : + DEBUG_PRINT_ERROR("\nERROR: Unsupported H.264 level= %u", + requested_level.level); return false; break; } } - if(!m_profile_set) { - ioctl_msg.inputparam = (void*)&requested_profile; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&requested_profile; + ioctl_msg.out = NULL; if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_CODEC_PROFILE,(void*)&ioctl_msg)< 0) { - DEBUG_PRINT_LOW("\nERROR: Request for setting profile failed"); + DEBUG_PRINT_ERROR("\nERROR: Request for setting profile failed"); return false; } codec_profile.profile = requested_profile.profile; @@ -1297,11 +2009,11 @@ bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel) if(!m_level_set) { - ioctl_msg.inputparam = (void*)&requested_level; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&requested_level; + ioctl_msg.out = NULL; if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_PROFILE_LEVEL,(void*)&ioctl_msg)< 0) { - DEBUG_PRINT_LOW("\nERROR: Request for setting profile level failed"); + DEBUG_PRINT_ERROR("\nERROR: Request for setting profile level failed"); return false; } profile_level.level = requested_level.level; @@ -1311,78 +2023,338 @@ bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel) return true; } -bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames) +bool venc_dev::venc_set_voptiming_cfg( OMX_U32 TimeIncRes) { venc_ioctl_msg ioctl_msg = {NULL,NULL}; - struct venc_intraperiod intra_period; + struct venc_voptimingcfg vop_timing_cfg; + + DEBUG_PRINT_LOW("\n venc_set_voptiming_cfg: TimeRes = %u", + TimeIncRes); + + vop_timing_cfg.voptime_resolution = TimeIncRes; + + ioctl_msg.in = (void*)&vop_timing_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_VOP_TIMING_CFG,(void*)&ioctl_msg)< 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Vop Timing failed"); + return false; + } + + voptimecfg.voptime_resolution = vop_timing_cfg.voptime_resolution; + return true; +} + +bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_intraperiod intraperiod_cfg; DEBUG_PRINT_LOW("\n venc_set_intra_period: nPFrames = %u", nPFrames); - intra_period.num_pframes = nPFrames; - ioctl_msg.inputparam = (void*)&intra_period; - ioctl_msg.outputparam = NULL; + intraperiod_cfg.num_pframes = nPFrames; + if((codec_profile.profile == VEN_PROFILE_MPEG4_ASP) || + (codec_profile.profile == VEN_PROFILE_H264_MAIN) || + (codec_profile.profile == VEN_PROFILE_H264_HIGH)) + { +#ifdef MAX_RES_1080P + if (nBFrames) + { + DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported"); + intraperiod_cfg.num_bframes = 1; + } + else + intraperiod_cfg.num_bframes = 0; +#else + if(nBFrames) + { + DEBUG_PRINT_ERROR("B frames not supported"); + intraperiod_cfg.num_bframes = 0; + } + else + { + DEBUG_PRINT_ERROR("B frames not supported"); + intraperiod_cfg.num_bframes = 0; + } +#endif + } + else + intraperiod_cfg.num_bframes = 0; + + DEBUG_PRINT_ERROR("\n venc_set_intra_period: nPFrames = %u nBFrames = %u", + intraperiod_cfg.num_pframes, intraperiod_cfg.num_bframes); + ioctl_msg.in = (void*)&intraperiod_cfg; + ioctl_msg.out = NULL; if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_INTRA_PERIOD,(void*)&ioctl_msg)< 0) { DEBUG_PRINT_ERROR("\nERROR: Request for setting intra period failed"); return false; } + intra_period.num_pframes = intraperiod_cfg.num_pframes; + intra_period.num_bframes = intraperiod_cfg.num_bframes; return true; } -bool venc_dev::venc_set_target_bitrate(OMX_U32 nTargetBitrate) +bool venc_dev::venc_set_entropy_config(OMX_BOOL enable, OMX_U32 i_cabac_level) { - venc_ioctl_msg ioctl_msg = {NULL, NULL}; - struct venc_targetbitrate bit_rate; + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_entropycfg entropy_cfg; - DEBUG_PRINT_LOW("\n venc_set_target_bitrate: bitrate = %u", - nTargetBitrate); - bit_rate.target_bitrate = nTargetBitrate ; - ioctl_msg.inputparam = (void*)&bit_rate; - ioctl_msg.outputparam = NULL; - if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_TARGET_BITRATE,(void*)&ioctl_msg) < 0) - { - DEBUG_PRINT_ERROR("\nERROR: Request for setting bit rate failed"); + memset(&entropy_cfg,0,sizeof(entropy_cfg)); + DEBUG_PRINT_LOW("\n venc_set_entropy_config: CABAC = %u level: %u", enable, i_cabac_level); + + if(enable &&(codec_profile.profile != VEN_PROFILE_H264_BASELINE)){ + entropy_cfg.longentropysel = VEN_ENTROPY_MODEL_CABAC; + if (i_cabac_level == 0) { + entropy_cfg.cabacmodel = VEN_CABAC_MODEL_0; + } +#ifdef MAX_RES_1080P + else + { + DEBUG_PRINT_HIGH("Invalid model set (%d) defaulting to model 0",i_cabac_level); + entropy_cfg.cabacmodel = VEN_CABAC_MODEL_0; + } +#else + else if (i_cabac_level == 1) { + entropy_cfg.cabacmodel = VEN_CABAC_MODEL_1; + } + else if (i_cabac_level == 2) { + entropy_cfg.cabacmodel = VEN_CABAC_MODEL_2; + } +#endif + } + else if(!enable){ + entropy_cfg.longentropysel = VEN_ENTROPY_MODEL_CAVLC; + } + else{ + DEBUG_PRINT_ERROR("\nInvalid Entropy mode for Baseline Profile"); return false; } - m_sVenc_cfg.targetbitrate = nTargetBitrate; - m_level_set = false; - if(venc_set_profile_level(0, 0)) + + ioctl_msg.in = (void*)&entropy_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_ENTROPY_CFG,(void*)&ioctl_msg)< 0) { - DEBUG_PRINT_HIGH("\n %s(): Dynamic Profile/Level setting success", - __func__); + DEBUG_PRINT_ERROR("\nERROR: Request for setting entropy config failed"); + return false; } - + entropy.longentropysel = entropy_cfg.longentropysel; + entropy.cabacmodel = entropy_cfg.cabacmodel; return true; } -bool venc_dev::venc_set_encode_framerate(OMX_U32 encode_framerate) +bool venc_dev::venc_set_multislice_cfg(OMX_INDEXTYPE Codec, OMX_U32 nSlicesize) // MB { - venc_ioctl_msg ioctl_msg = {NULL, NULL}; - struct venc_framerate frame_rate; + venc_ioctl_msg ioctl_msg = {NULL, NULL}; + bool status = true; + struct venc_multiclicecfg multislice_cfg; - DEBUG_PRINT_LOW("\n venc_set_encode_framerate: framerate(Q16) = %u", - encode_framerate); - frame_rate.fps_numerator = 30; - if((encode_framerate >> 16)== 30) + if((Codec != OMX_IndexParamVideoH263) && (nSlicesize)){ + multislice_cfg.mslice_mode = VEN_MSLICE_CNT_MB; + multislice_cfg.mslice_size = nSlicesize; + } + else{ + multislice_cfg.mslice_mode = VEN_MSLICE_OFF; + multislice_cfg.mslice_size = 0; + } + + DEBUG_PRINT_LOW("\n %s(): mode = %u, size = %u", __func__, multislice_cfg.mslice_mode, + multislice_cfg.mslice_size); + + ioctl_msg.in = (void*)&multislice_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd, VEN_IOCTL_SET_MULTI_SLICE_CFG,(void*)&ioctl_msg) < 0) { - frame_rate.fps_denominator = 1; + DEBUG_PRINT_ERROR("\nERROR: Request for setting multi-slice cfg failed"); + status = false; } - else if((encode_framerate >>16) == 15) + else { - frame_rate.fps_denominator = 2; + multislice.mslice_mode = multislice_cfg.mslice_mode; + multislice.mslice_size = nSlicesize; } - else if((encode_framerate >> 16)== 7.5) + return status; +} + +bool venc_dev::venc_set_intra_refresh(OMX_VIDEO_INTRAREFRESHTYPE ir_mode, OMX_U32 irMBs) +{ + venc_ioctl_msg ioctl_msg = {NULL, NULL}; + bool status = true; + struct venc_intrarefresh intraRefresh_cfg; + + // There is no disabled mode. Disabled mode is indicated by a 0 count. + if (irMBs == 0 || ir_mode == OMX_VIDEO_IntraRefreshMax) { - frame_rate.fps_denominator = 4; + intraRefresh_cfg.irmode = VEN_IR_OFF; + intraRefresh_cfg.mbcount = 0; + } + else if ((ir_mode == OMX_VIDEO_IntraRefreshCyclic) && + (irMBs < ((m_sVenc_cfg.input_width * m_sVenc_cfg.input_height)>>8))) + { + intraRefresh_cfg.irmode = VEN_IR_CYCLIC; + intraRefresh_cfg.mbcount = irMBs; } else { - frame_rate.fps_denominator = 1; + DEBUG_PRINT_ERROR("\nERROR: Invalid IntraRefresh Parameters:" + "mb count: %d, mb mode:%d", irMBs, ir_mode); + return false; } - ioctl_msg.inputparam = (void*)&frame_rate; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&intraRefresh_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_INTRA_REFRESH,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting Intra Refresh failed"); + status = false; + } + else + { + intra_refresh.irmode = intraRefresh_cfg.irmode; + intra_refresh.mbcount = intraRefresh_cfg.mbcount; + } + return status; +} + +bool venc_dev::venc_set_error_resilience(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* error_resilience) +{ + venc_ioctl_msg ioctl_msg = {NULL, NULL}; + bool status = true; + struct venc_headerextension hec_cfg; + struct venc_multiclicecfg multislice_cfg; + + if (m_sVenc_cfg.codectype == OMX_VIDEO_CodingMPEG4) { + if (error_resilience->bEnableHEC) { + hec_cfg.header_extension = 1; + } + else { + hec_cfg.header_extension = 0; + } + + ioctl_msg.in = (void*)&hec_cfg; + ioctl_msg.out = NULL; + if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_HEC,(void*)&ioctl_msg) < 0) { + DEBUG_PRINT_ERROR("\nERROR: Request for setting HEader Error correction failed"); + return false; + } + hec.header_extension = error_resilience->bEnableHEC; + } + + if (error_resilience->bEnableRVLC) { + DEBUG_PRINT_ERROR("\n RVLC is not Supported"); + return false; + } + + if (( m_sVenc_cfg.codectype != OMX_VIDEO_CodingH263) && + (error_resilience->bEnableDataPartitioning)) { + DEBUG_PRINT_ERROR("\n DataPartioning are not Supported for MPEG4/H264"); + return false; + } + + if (( m_sVenc_cfg.codectype != OMX_VIDEO_CodingH263) && + (error_resilience->nResynchMarkerSpacing)) { + multislice_cfg.mslice_mode = VEN_MSLICE_CNT_BYTE; + multislice_cfg.mslice_size = error_resilience->nResynchMarkerSpacing; + } + else if (m_sVenc_cfg.codectype == OMX_VIDEO_CodingH263 && + error_resilience->bEnableDataPartitioning) { + multislice_cfg.mslice_mode = VEN_MSLICE_GOB; + multislice_cfg.mslice_size = 0; + } + else { + multislice_cfg.mslice_mode = VEN_MSLICE_OFF; + multislice_cfg.mslice_size = 0; + } + DEBUG_PRINT_LOW("\n %s(): mode = %u, size = %u", __func__, multislice_cfg.mslice_mode, + multislice_cfg.mslice_size); + ioctl_msg.in = (void*)&multislice_cfg; + ioctl_msg.out = NULL; + if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_MULTI_SLICE_CFG,(void*)&ioctl_msg) < 0) { + DEBUG_PRINT_ERROR("\nERROR: Request for setting multi-slice cfg failed"); + status = false; + } + else + { + multislice.mslice_mode = multislice_cfg.mslice_mode ; + multislice.mslice_size = multislice_cfg.mslice_size; + + } + return status; +} + +bool venc_dev::venc_set_inloop_filter(OMX_VIDEO_AVCLOOPFILTERTYPE loopfilter) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + struct venc_dbcfg filter_cfg; + + memset(&filter_cfg, 0, sizeof(filter_cfg)); + DEBUG_PRINT_LOW("\n venc_set_inloop_filter: %u",loopfilter); + + if (loopfilter == OMX_VIDEO_AVCLoopFilterEnable){ + filter_cfg.db_mode = VEN_DB_ALL_BLKG_BNDRY; + } + else if(loopfilter == OMX_VIDEO_AVCLoopFilterDisable){ + filter_cfg.db_mode = VEN_DB_DISABLE; + } + else if(loopfilter == OMX_VIDEO_AVCLoopFilterDisableSliceBoundary){ + filter_cfg.db_mode = VEN_DB_SKIP_SLICE_BNDRY; + } + filter_cfg.slicealpha_offset = filter_cfg.slicebeta_offset = 0; + + ioctl_msg.in = (void*)&filter_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_DEBLOCKING_CFG,(void*)&ioctl_msg)< 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting inloop filter failed"); + return false; + } + + dbkfilter.db_mode = filter_cfg.db_mode; + dbkfilter.slicealpha_offset = dbkfilter.slicebeta_offset = 0; + return true; +} + +bool venc_dev::venc_set_target_bitrate(OMX_U32 nTargetBitrate, OMX_U32 config) +{ + venc_ioctl_msg ioctl_msg = {NULL, NULL}; + struct venc_targetbitrate bitrate_cfg; + + DEBUG_PRINT_LOW("\n venc_set_target_bitrate: bitrate = %u", + nTargetBitrate); + bitrate_cfg.target_bitrate = nTargetBitrate ; + ioctl_msg.in = (void*)&bitrate_cfg; + ioctl_msg.out = NULL; + if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_TARGET_BITRATE,(void*)&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR("\nERROR: Request for setting bit rate failed"); + return false; + } + m_sVenc_cfg.targetbitrate = nTargetBitrate; + bitrate.target_bitrate = nTargetBitrate; + if(!config) + { + m_level_set = false; + if(venc_set_profile_level(0, 0)) + { + DEBUG_PRINT_LOW("Calling set level (Bitrate) with %d\n",profile_level.level); + } + } + return true; +} + +bool venc_dev::venc_set_encode_framerate(OMX_U32 encode_framerate, OMX_U32 config) +{ + venc_ioctl_msg ioctl_msg = {NULL, NULL}; + struct venc_framerate frame_rate_cfg; + + Q16ToFraction(encode_framerate,frame_rate_cfg.fps_numerator,frame_rate_cfg.fps_denominator); + + DEBUG_PRINT_LOW("\n venc_set_encode_framerate: framerate(Q16) = %u,NR: %d, DR: %d", + encode_framerate,frame_rate_cfg.fps_numerator,frame_rate_cfg.fps_denominator); + + ioctl_msg.in = (void*)&frame_rate_cfg; + ioctl_msg.out = NULL; if(ioctl(m_nDriver_fd, VEN_IOCTL_SET_FRAME_RATE, (void*)&ioctl_msg) < 0) { @@ -1390,15 +2362,16 @@ bool venc_dev::venc_set_encode_framerate(OMX_U32 encode_framerate) return false; } - m_sVenc_cfg.fps_den = frame_rate.fps_denominator; - m_sVenc_cfg.fps_num = frame_rate.fps_numerator; - m_level_set = false; - if(venc_set_profile_level(0, 0)) + m_sVenc_cfg.fps_den = frame_rate_cfg.fps_denominator; + m_sVenc_cfg.fps_num = frame_rate_cfg.fps_numerator; + if(!config) { - DEBUG_PRINT_HIGH("\n %s(): Dynamic Profile/Level setting success", - __func__); + m_level_set = false; + if(venc_set_profile_level(0, 0)) + { + DEBUG_PRINT_LOW("Calling set level (Framerate) with %d\n",profile_level.level); + } } - return true; } @@ -1409,16 +2382,24 @@ bool venc_dev::venc_set_color_format(OMX_COLOR_FORMATTYPE color_format) if(color_format == OMX_COLOR_FormatYUV420SemiPlanar) { +#ifdef MAX_RES_1080P + m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12_16M2KA; +#else m_sVenc_cfg.inputformat = VEN_INPUTFMT_NV12; +#endif } else { DEBUG_PRINT_ERROR("\nWARNING: Unsupported Color format [%d]", color_format); +#ifdef MAX_RES_1080P + m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12_16M2KA; +#else m_sVenc_cfg.inputformat = VEN_INPUTFMT_NV12; +#endif DEBUG_PRINT_HIGH("\n Default color format YUV420SemiPlanar is set"); } - ioctl_msg.inputparam = (void*)&m_sVenc_cfg; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&m_sVenc_cfg; + ioctl_msg.out = NULL; if (ioctl(m_nDriver_fd, VEN_IOCTL_SET_BASE_CFG, (void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for setting color format failed"); @@ -1449,21 +2430,25 @@ bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate) { venc_ioctl_msg ioctl_msg = {NULL,NULL}; bool status = true; + struct venc_ratectrlcfg ratectrl_cfg; //rate control switch(eControlRate) { case OMX_Video_ControlRateDisable: - rate_ctrl.rcmode = VEN_RC_OFF; + ratectrl_cfg.rcmode = VEN_RC_OFF; break; case OMX_Video_ControlRateVariableSkipFrames: - rate_ctrl.rcmode = VEN_RC_VBR_VFR; + ratectrl_cfg.rcmode = VEN_RC_VBR_VFR; break; case OMX_Video_ControlRateVariable: - rate_ctrl.rcmode = VEN_RC_VBR_CFR; + ratectrl_cfg.rcmode = VEN_RC_VBR_CFR; break; case OMX_Video_ControlRateConstantSkipFrames: - rate_ctrl.rcmode = VEN_RC_CBR_VFR; + ratectrl_cfg.rcmode = VEN_RC_CBR_VFR; + break; + case OMX_Video_ControlRateConstant: + ratectrl_cfg.rcmode = VEN_RC_CBR_CFR; break; default: status = false; @@ -1472,13 +2457,15 @@ bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate) if(status) { - ioctl_msg.inputparam = (void*)&rate_ctrl; - ioctl_msg.outputparam = NULL; + ioctl_msg.in = (void*)&ratectrl_cfg; + ioctl_msg.out = NULL; if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_RATE_CTRL_CFG,(void*)&ioctl_msg) < 0) { DEBUG_PRINT_ERROR("\nERROR: Request for setting rate control failed"); status = false; } + else + rate_ctrl.rcmode = ratectrl_cfg.rcmode; } return status; } @@ -1639,7 +2626,13 @@ bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel) case VEN_LEVEL_H264_3p1: *eLevel = OMX_VIDEO_AVCLevel31; break; - default : + case VEN_LEVEL_H264_3p2: + *eLevel = OMX_VIDEO_AVCLevel32; + break; + case VEN_LEVEL_H264_4: + *eLevel = OMX_VIDEO_AVCLevel4; + break; + default : *eLevel = OMX_VIDEO_AVCLevelMax; status = false; break; @@ -1801,6 +2794,19 @@ bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel) mb_per_frame = ((m_sVenc_cfg.input_height + 15) >> 4)* ((m_sVenc_cfg.input_width + 15)>> 4); + if((mb_per_frame >= 3600) && (m_sVenc_cfg.codectype == VEN_CODEC_MPEG4)) + { + if(codec_profile.profile == VEN_PROFILE_MPEG4_ASP) + profile_level.level = VEN_LEVEL_MPEG4_5; + if(codec_profile.profile == VEN_PROFILE_MPEG4_SP) + profile_level.level = VEN_LEVEL_MPEG4_6; + { + new_level = profile_level.level; + new_profile = codec_profile.profile; + return true; + } + } + mb_per_sec = mb_per_frame * m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den; do{ @@ -1810,10 +2816,10 @@ bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel) { if(m_sVenc_cfg.targetbitrate <= (int)profile_tbl[2]) { - DEBUG_PRINT_LOW("\n Appropriate profile/level found \n"); new_level = (int)profile_tbl[3]; new_profile = (int)profile_tbl[4]; profile_level_found = true; + DEBUG_PRINT_LOW("\n Appropriate profile/level found %d/%d\n", new_profile, new_level); break; } } @@ -1821,8 +2827,7 @@ bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel) profile_tbl = profile_tbl + 5; }while(profile_tbl[0] != 0); - if ((profile_level_found != true) || (new_profile != *eProfile) - || (new_level > *eLevel)) + if (profile_level_found != true) { DEBUG_PRINT_LOW("\n ERROR: Unsupported profile/level\n"); return false; @@ -1833,51 +2838,98 @@ bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel) { *eLevel = new_level; } - DEBUG_PRINT_HIGH("%s: Returning with eProfile = %lu" + DEBUG_PRINT_LOW("%s: Returning with eProfile = %lu" "Level = %lu", __func__, *eProfile, *eLevel); return true; } -bool venc_dev::venc_set_multislice_cfg(OMX_VIDEO_AVCSLICEMODETYPE eSliceMode) + +bool venc_dev::venc_max_allowed_bitrate_check(OMX_U32 nTargetBitrate) { - venc_ioctl_msg ioctl_msg = {NULL, NULL}; - bool status = true; - DEBUG_PRINT_LOW("\n %s(): eSliceMode = %u", __func__, eSliceMode); - switch(eSliceMode) + unsigned const int *profile_tbl = NULL; + + switch(m_sVenc_cfg.codectype) { - case OMX_VIDEO_SLICEMODE_AVCDefault: - DEBUG_PRINT_LOW("\n %s(): OMX_VIDEO_SLICEMODE_AVCDefault", __func__); - multislice_cfg.mslice_mode = VEN_MSLICE_OFF; - multislice_cfg.mslice_size = 0; - break; - case OMX_VIDEO_SLICEMODE_AVCMBSlice: - DEBUG_PRINT_LOW("\n %s(): OMX_VIDEO_SLICEMODE_AVCMBSlice", __func__); - multislice_cfg.mslice_mode = VEN_MSLICE_CNT_MB; - multislice_cfg.mslice_size = ((m_sVenc_cfg.input_width/16) * - (m_sVenc_cfg.input_height/16))/2; - break; - case OMX_VIDEO_SLICEMODE_AVCByteSlice: - DEBUG_PRINT_LOW("\n %s(): OMX_VIDEO_SLICEMODE_AVCByteSlice", __func__); - multislice_cfg.mslice_mode = VEN_MSLICE_CNT_BYTE; - multislice_cfg.mslice_size = 1920; - break; - default: - DEBUG_PRINT_ERROR("\n %s(): Unsupported SliceMode = %u",__func__, eSliceMode); - status = false; - break; - } - DEBUG_PRINT_LOW("\n %s(): mode = %u, size = %u", __func__, multislice_cfg.mslice_mode, - multislice_cfg.mslice_size); + case VEN_CODEC_MPEG4: + if(m_eProfile == OMX_VIDEO_MPEG4ProfileSimple) + { + profile_tbl = (unsigned int const *)mpeg4_profile_level_table; + } + else if(m_eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) + { + profile_tbl = (unsigned int const *) + (&mpeg4_profile_level_table[MPEG4_ASP_START]); + } + else + { + DEBUG_PRINT_ERROR("Unsupported MPEG4 profile type %lu", m_eProfile); + return false; + } + break; + case VEN_CODEC_H264: + if(m_eProfile == OMX_VIDEO_AVCProfileBaseline) + { + profile_tbl = (unsigned int const *)h264_profile_level_table; + } + else if(m_eProfile == OMX_VIDEO_AVCProfileHigh) + { + profile_tbl = (unsigned int const *) + (&h264_profile_level_table[H264_HP_START]); + } + else if(m_eProfile == OMX_VIDEO_AVCProfileMain) + { + profile_tbl = (unsigned int const *) + (&h264_profile_level_table[H264_MP_START]); + } + else + { + DEBUG_PRINT_ERROR("Unsupported AVC profile type %lu", m_eProfile); + return false; + } - if(status) + break; + case VEN_CODEC_H263: + if(m_eProfile == OMX_VIDEO_H263ProfileBaseline) + { + profile_tbl = (unsigned int const *)h263_profile_level_table; + } + else + { + DEBUG_PRINT_ERROR("Unsupported H.263 profile type %lu", m_eProfile); + return false; + } + break; + default: + DEBUG_PRINT_ERROR("%s: unknown codec type", __func__); + return false; + } + while(profile_tbl[0] != 0) { - ioctl_msg.inputparam = (void*)&multislice_cfg; - ioctl_msg.outputparam = NULL; - if(ioctl (m_nDriver_fd,VEN_IOCTL_SET_MULTI_SLICE_CFG,(void*)&ioctl_msg) < 0) + if(profile_tbl[3] == m_eLevel) { - DEBUG_PRINT_ERROR("\nERROR: Request for setting multi-slice cfg failed"); - status = false; + if(nTargetBitrate > profile_tbl[2]) + { + DEBUG_PRINT_ERROR("Max. supported bitrate for Profile[%d] & Level[%d]" + " is %u", m_eProfile, m_eLevel, profile_tbl[2]); + return false; + } } + profile_tbl += 5; } - return status; + return true; +} + +#ifdef _ANDROID_ICS_ +bool venc_dev::venc_set_meta_mode(bool mode) +{ + venc_ioctl_msg ioctl_msg = {NULL,NULL}; + ioctl_msg.in = &mode; + DEBUG_PRINT_HIGH("Set meta buffer mode: %d", mode); + if(ioctl(m_nDriver_fd,VEN_IOCTL_SET_METABUFFER_MODE,&ioctl_msg) < 0) + { + DEBUG_PRINT_ERROR(" Set meta buffer mode failed"); + return false; + } + return true; } +#endif |