| /*-------------------------------------------------------------------------- |
| Copyright (c) 2010-2013, The Linux Foundation. All rights reserved. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions are met: |
| * Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| * Redistributions in binary form must reproduce the above copyright |
| notice, this list of conditions and the following disclaimer in the |
| documentation and/or other materials provided with the distribution. |
| * Neither the name of The Linux Foundation nor |
| the names of its contributors may be used to endorse or promote |
| products derived from this software without specific prior written |
| permission. |
| |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| --------------------------------------------------------------------------*/ |
| #include<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" |
| #ifdef USE_ION |
| #include <linux/msm_ion.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 + 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,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,12000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple}, |
| {0,0,0,0,0}, |
| |
| {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}, |
| {0,0,0,0,0}, |
| }; |
| |
| /* H264 profile and level table*/ |
| static const unsigned int h264_profile_level_table[][5]= { |
| /*max mb per frame, max mb per sec, max bitrate, level, profile*/ |
| {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline}, |
| {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline}, |
| {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline}, |
| {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline}, |
| {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline}, |
| {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline}, |
| {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline}, |
| {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}, |
| {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh}, |
| {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh}, |
| {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh}, |
| {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh}, |
| {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh}, |
| {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh}, |
| {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,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*/ |
| static const unsigned int h263_profile_level_table[][5]= { |
| /*max mb per frame, max mb per sec, max bitrate, level, profile*/ |
| {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline}, |
| {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline}, |
| {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline}, |
| {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline}, |
| {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline}, |
| {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline}, |
| {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline}, |
| {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline}, |
| {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); } |
| |
| #define BUFFER_LOG_LOC "/data/misc/media" |
| |
| //constructor |
| venc_dev::venc_dev(class omx_venc *venc_class) |
| { |
| 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); |
| memset(&m_debug,0,sizeof(m_debug)); |
| |
| char property_value[PROPERTY_VALUE_MAX] = {0}; |
| property_value[0] = '\0'; |
| property_get("vidc.enc.log.in", property_value, "0"); |
| m_debug.in_buffer_log = atoi(property_value); |
| |
| property_value[0] = '\0'; |
| property_get("vidc.enc.log.out", property_value, "0"); |
| m_debug.out_buffer_log = atoi(property_value); |
| snprintf(m_debug.log_loc, PROPERTY_VAL_MAX, |
| "%s", BUFFER_LOG_LOC); |
| |
| DEBUG_PRINT_LOW("venc_dev constructor"); |
| } |
| |
| venc_dev::~venc_dev() |
| { |
| 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) |
| { |
| 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.in = NULL; |
| ioctl_msg.out = (void*)&venc_msg; |
| |
| /*Wait for a message from the video decoder driver*/ |
| 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("ERESTARTSYS received in ioctl read next msg!"); |
| } else if (error_code <0) { |
| DEBUG_PRINT_LOW("ioctl VEN_IOCTL_CMD_READ_NEXT_MSG failed"); |
| break; |
| } else if (omx->async_message_process(input,&venc_msg) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message"); |
| break; |
| } |
| } |
| DEBUG_PRINT_HIGH("omx_venc: Async Thread exit"); |
| return NULL; |
| } |
| |
| int venc_dev::venc_extradata_log_buffers(char *buffer_addr) |
| { |
| return OMX_ErrorUnsupportedSetting; |
| } |
| |
| int venc_dev::venc_output_log_buffers(const char *buffer_addr, int buffer_len) |
| { |
| if (m_debug.out_buffer_log && !m_debug.outfile) { |
| int size = 0; |
| if(m_sVenc_cfg.codectype == VEN_CODEC_MPEG4) { |
| size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%d_%d_%p.m4v", |
| m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this); |
| } else if(m_sVenc_cfg.codectype == VEN_CODEC_H264) { |
| size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%d_%d_%p.264", |
| m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this); |
| } else if(m_sVenc_cfg.codectype == VENC_CODEC_H263) { |
| size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%d_%d_%p.263", |
| m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this); |
| } else if(m_sVenc_cfg.codectype == VENC_CODEC_VP8) { |
| size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%d_%d_%p.ivf", |
| m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this); |
| } |
| if ((size > PROPERTY_VALUE_MAX) || (size < 0)) { |
| DEBUG_PRINT_ERROR("Failed to open output file: %s for logging as size:%d", |
| m_debug.outfile_name, size); |
| return -1; |
| } |
| m_debug.outfile = fopen(m_debug.outfile_name, "ab"); |
| if (!m_debug.outfile) { |
| DEBUG_PRINT_ERROR("Failed to open output file: %s for logging errno:%d", |
| m_debug.outfile_name, errno); |
| m_debug.outfile_name[0] = '\0'; |
| return -1; |
| } |
| } |
| if (m_debug.outfile && buffer_len) { |
| DEBUG_PRINT_LOW("%s buffer_len:%d", __func__, buffer_len); |
| fwrite(buffer_addr, buffer_len, 1, m_debug.outfile); |
| } |
| return 0; |
| } |
| |
| bool venc_dev::venc_get_output_log_flag() |
| { |
| return (m_debug.out_buffer_log == 1); |
| } |
| |
| int venc_dev::venc_input_log_buffers(OMX_BUFFERHEADERTYPE *pbuffer, void *pmem_data_buf, int framelen) { |
| if (!m_debug.infile) { |
| int size = snprintf(m_debug.infile_name, PROPERTY_VALUE_MAX, "%s/input_enc_%d_%d_%p.yuv", |
| m_debug.log_loc, m_sVenc_cfg.input_width, |
| m_sVenc_cfg.input_height, this); |
| if ((size > PROPERTY_VALUE_MAX) || (size < 0)) { |
| DEBUG_PRINT_ERROR("Failed to open input file: %s for logging size:%d", |
| m_debug.infile_name, size); |
| return -1; |
| } |
| m_debug.infile = fopen (m_debug.infile_name, "ab"); |
| if (!m_debug.infile) { |
| DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile); |
| m_debug.infile_name[0] = '\0'; |
| return -1; |
| } |
| } |
| if (m_debug.infile && pbuffer && pbuffer->nFilledLen) { |
| #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("Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf); |
| buf_addr = (OMX_U8 *)pmem_data_buf; |
| } else { |
| DEBUG_PRINT_LOW("Shared PMEM addr for i/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer); |
| buf_addr = (unsigned char *)mmap(NULL, |
| ((encoder_media_buffer_type *)pbuffer->pBuffer)->meta_handle->data[2], |
| PROT_READ|PROT_WRITE, MAP_SHARED, |
| ((encoder_media_buffer_type *)pbuffer->pBuffer)->meta_handle->data[0], 0); |
| } |
| |
| if (m_debug.infile) { |
| fwrite((const char *)buf_addr, y_size, 1, m_debug.infile); |
| fwrite((const char *)(buf_addr + c_offset), (y_size>>1), 1, m_debug.infile); |
| } |
| |
| if (!pmem_data_buf) { |
| munmap (buf_addr, ((encoder_media_buffer_type *)pbuffer->pBuffer)->meta_handle->data[2]); |
| } |
| #else |
| if (m_debug.infile) { |
| OMX_U8* ptrbuffer = NULL; |
| if (pmem_data_buf) { |
| DEBUG_PRINT_LOW("Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf); |
| ptrbuffer = (OMX_U8 *)pmem_data_buf; |
| } else { |
| DEBUG_PRINT_LOW("Shared PMEM addr for i/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer); |
| ptrbuffer = (OMX_U8 *)bufhdr->pBuffer; |
| } |
| fwrite((const char *)ptrbuffer, framelen, 1, m_debug.infile); |
| } |
| |
| #endif |
| } |
| return 0; |
| } |
| |
| bool venc_dev::venc_open(OMX_U32 codec) |
| { |
| struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| int r; |
| unsigned int alignment = 0,buffer_size = 0, temp =0; |
| |
| m_nDriver_fd = open ("/dev/msm_vidc_enc",O_RDWR|O_NONBLOCK); |
| |
| if (m_nDriver_fd == 0) { |
| DEBUG_PRINT_ERROR("ERROR: Got fd as 0 for msm_vidc_enc, Opening again"); |
| m_nDriver_fd = open ("/dev/msm_vidc_enc",O_RDWR|O_NONBLOCK); |
| } |
| |
| if ((int)m_nDriver_fd < 0) { |
| DEBUG_PRINT_ERROR("ERROR: Omx_venc::Comp Init Returning failure"); |
| return false; |
| } |
| |
| DEBUG_PRINT_LOW("m_nDriver_fd = %d", 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("ERROR: Request number of encoder instances failed"); |
| } else if (num_instances > 1) { |
| DEBUG_PRINT_ERROR("Second 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; |
| m_sVenc_cfg.dvs_width = OMX_CORE_QCIF_WIDTH; |
| m_sVenc_cfg.dvs_height = OMX_CORE_QCIF_HEIGHT; |
| 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 |
| // initializing QP range parameters |
| qp_range.minqp = 2; |
| |
| if (codec == OMX_VIDEO_CodingAVC) |
| qp_range.maxqp = 51; |
| else |
| qp_range.maxqp = 31; |
| |
| 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; |
| } 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; |
| } |
| |
| 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; |
| } |
| |
| 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("ERROR: Request for setting base configuration failed"); |
| return false; |
| } |
| |
| // Get the I/P and O/P buffer requirements |
| 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("ERROR: Request for getting i/p buffer requirement failed"); |
| return false; |
| } |
| |
| 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("ERROR: Request for getting o/p buffer requirement failed"); |
| return false; |
| } |
| |
| m_profile_set = false; |
| m_level_set = false; |
| |
| if (venc_set_profile_level(0, 0)) { |
| DEBUG_PRINT_HIGH("%s(): Init Profile/Level setting success", |
| __func__); |
| } |
| |
| recon_buffers_count = MAX_RECON_BUFFERS; |
| ltrmode.ltr_mode = 0; |
| ltrcount.ltr_count = 0; |
| ltrperiod.ltr_period = 0; |
| |
| return true; |
| } |
| |
| void venc_dev::venc_close() |
| { |
| DEBUG_PRINT_LOW("venc_close: fd = %d", m_nDriver_fd); |
| |
| if ((int)m_nDriver_fd >= 0) { |
| DEBUG_PRINT_HIGH("venc_close(): Calling VEN_IOCTL_CMD_STOP_READ_MSG"); |
| (void)ioctl(m_nDriver_fd, VEN_IOCTL_CMD_STOP_READ_MSG, |
| NULL); |
| DEBUG_PRINT_LOW("Calling close()"); |
| close(m_nDriver_fd); |
| m_nDriver_fd = -1; |
| } |
| |
| if (m_debug.infile) { |
| fclose(m_debug.infile); |
| m_debug.infile = NULL; |
| } |
| if (m_debug.outfile) { |
| fclose(m_debug.outfile); |
| m_debug.outfile = NULL; |
| } |
| |
| } |
| |
| bool venc_dev::venc_set_buf_req(unsigned long *min_buff_count, |
| unsigned long *actual_buff_count, |
| unsigned long *buff_size, |
| unsigned long port) |
| { |
| struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| unsigned long temp_count = 0; |
| |
| if (port == 0) { |
| if (*actual_buff_count > m_sInput_buff_property.mincount) { |
| temp_count = m_sInput_buff_property.actualcount; |
| m_sInput_buff_property.actualcount = *actual_buff_count; |
| 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("ERROR: Request for setting i/p buffer requirement failed"); |
| m_sInput_buff_property.actualcount = temp_count; |
| return false; |
| } |
| |
| DEBUG_PRINT_LOW("I/P Count set to %lu", *actual_buff_count); |
| } |
| } else { |
| if (*actual_buff_count > m_sOutput_buff_property.mincount) { |
| temp_count = m_sOutput_buff_property.actualcount; |
| m_sOutput_buff_property.actualcount = *actual_buff_count; |
| 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("ERROR: Request for setting o/p buffer requirement failed"); |
| m_sOutput_buff_property.actualcount = temp_count; |
| return false; |
| } |
| |
| DEBUG_PRINT_LOW("O/P Count set to %lu", *actual_buff_count); |
| } |
| } |
| |
| return true; |
| |
| } |
| |
| 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, OMX_U32 *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_capability_ltrcount(unsigned long *min, |
| unsigned long *max, unsigned long *step_size) |
| { |
| struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| venc_range cap_ltr_count; |
| ioctl_msg.in = NULL; |
| ioctl_msg.out = (void*)&cap_ltr_count; |
| |
| if (ioctl (m_nDriver_fd, VEN_IOCTL_GET_CAPABILITY_LTRCOUNT, |
| (void*)&ioctl_msg) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: Get LTR Capability failed"); |
| return false; |
| } else { |
| *min = cap_ltr_count.min; |
| *max = cap_ltr_count.max; |
| *step_size = cap_ltr_count.step_size; |
| DEBUG_PRINT_HIGH("LTR Capability: min=%x, max=%d, step_size=%d", |
| *min, *max, *step_size); |
| } |
| |
| return true; |
| } |
| |
| bool venc_dev::venc_get_buf_req(unsigned long *min_buff_count, |
| unsigned long *actual_buff_count, |
| unsigned long *buff_size, |
| unsigned long port) |
| { |
| struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| |
| if (port == 0) { |
| 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("ERROR: Request for getting i/p buffer requirement failed"); |
| return false; |
| } |
| |
| *min_buff_count = m_sInput_buff_property.mincount; |
| *actual_buff_count = m_sInput_buff_property.actualcount; |
| #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.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("ERROR: Request for getting o/p buffer requirement failed"); |
| return false; |
| } |
| |
| *min_buff_count = m_sOutput_buff_property.mincount; |
| *actual_buff_count = m_sOutput_buff_property.actualcount; |
| *buff_size = m_sOutput_buff_property.datasize; |
| } |
| |
| return true; |
| |
| } |
| |
| bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index ) |
| { |
| venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| DEBUG_PRINT_LOW("venc_set_param:: venc-720p"); |
| |
| switch (index) { |
| case OMX_IndexParamPortDefinition: |
| { |
| OMX_PARAM_PORTDEFINITIONTYPE *portDefn; |
| portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData; |
| DEBUG_PRINT_HIGH("venc_set_param: OMX_IndexParamPortDefinition"); |
| |
| 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; |
| } |
| |
| DEBUG_PRINT_LOW("Basic parameter has changed"); |
| m_sVenc_cfg.input_height = portDefn->format.video.nFrameHeight; |
| m_sVenc_cfg.input_width = portDefn->format.video.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("ERROR: Request for setting base config failed"); |
| return false; |
| } |
| |
| DEBUG_PRINT_HIGH("WxH (%dx%d), codec (%d), fps(nr/dr) (%d/%d), bitrate (%d), " |
| "color_format (%d)", m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, |
| m_sVenc_cfg.codectype, m_sVenc_cfg.fps_num, m_sVenc_cfg.fps_den, |
| m_sVenc_cfg.targetbitrate, m_sVenc_cfg.inputformat); |
| |
| DEBUG_PRINT_LOW("Updating the buffer count/size for the new resolution"); |
| 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("ERROR: Request for getting i/p bufreq failed"); |
| return false; |
| } |
| |
| DEBUG_PRINT_HIGH("Got updated m_sInput_buff_property values: " |
| "datasize = %u, maxcount = %u, actualcnt = %u, " |
| "mincount = %u", m_sInput_buff_property.datasize, |
| m_sInput_buff_property.maxcount, m_sInput_buff_property.actualcount, |
| m_sInput_buff_property.mincount); |
| |
| 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("ERROR: Request for getting o/p bufreq failed"); |
| return false; |
| } |
| |
| DEBUG_PRINT_HIGH("Got updated m_sOutput_buff_property values: " |
| "datasize = %u, maxcount = %u, actualcnt = %u, " |
| "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 (ioctl (m_nDriver_fd, VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: Request for setting o/p bufreq failed"); |
| return false; |
| } |
| |
| if ((portDefn->nBufferCountActual >= m_sInput_buff_property.mincount) && |
| (portDefn->nBufferCountActual <= m_sInput_buff_property.maxcount)) { |
| m_sInput_buff_property.actualcount = portDefn->nBufferCountActual; |
| 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("ERROR: Request for setting i/p buffer requirements failed"); |
| return false; |
| } |
| } |
| |
| if (m_sInput_buff_property.datasize != portDefn->nBufferSize) { |
| DEBUG_PRINT_ERROR("WARNING: Requested i/p bufsize[%u]," |
| "Driver's updated i/p bufsize = %u", portDefn->nBufferSize, |
| m_sInput_buff_property.datasize); |
| } |
| |
| m_level_set = false; |
| |
| if (venc_set_profile_level(0, 0)) { |
| DEBUG_PRINT_LOW("%s(): Profile/Level setting success", __func__); |
| } |
| } else if (portDefn->nPortIndex == PORT_INDEX_OUT) { |
| if (!venc_set_target_bitrate(portDefn->format.video.nBitrate, 0)) { |
| return false; |
| } |
| |
| if ( (portDefn->nBufferCountActual >= m_sOutput_buff_property.mincount) |
| && |
| (m_sOutput_buff_property.maxcount >= portDefn->nBufferCountActual) |
| && |
| (m_sOutput_buff_property.datasize == portDefn->nBufferSize) |
| ) { |
| m_sOutput_buff_property.actualcount = portDefn->nBufferCountActual; |
| 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("ERROR: ioctl VEN_IOCTL_SET_OUTPUT_BUFFER_REQ failed"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Setting Output buffer requirements failed"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamPortDefinition"); |
| } |
| |
| break; |
| } |
| case OMX_IndexParamVideoPortFormat: |
| { |
| OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt; |
| portFmt =(OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData; |
| DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoPortFormat"); |
| |
| if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) { |
| if (!venc_set_color_format(portFmt->eColorFormat)) { |
| return false; |
| } |
| } else if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { |
| if (!venc_set_encode_framerate(portFmt->xFramerate, 0)) { |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoPortFormat"); |
| } |
| |
| break; |
| } |
| case OMX_IndexParamVideoBitrate: |
| { |
| OMX_VIDEO_PARAM_BITRATETYPE* pParam; |
| pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData; |
| DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoBitrate"); |
| |
| if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { |
| if (!venc_set_target_bitrate(pParam->nTargetBitrate, 0)) { |
| DEBUG_PRINT_ERROR("ERROR: Target Bit Rate setting failed"); |
| return false; |
| } |
| |
| if (!venc_set_ratectrl_cfg(pParam->eControlRate)) { |
| DEBUG_PRINT_ERROR("ERROR: Rate Control setting failed"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoBitrate"); |
| } |
| |
| break; |
| } |
| 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"); |
| |
| if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { |
| if (!venc_set_voptiming_cfg(pParam->nTimeIncRes)) { |
| DEBUG_PRINT_ERROR("ERROR: 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("ERROR: 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"); |
| bFrames = 0; |
| } |
| } |
| } |
| |
| #endif |
| |
| if (!venc_set_intra_period (pParam->nPFrames,bFrames)) { |
| DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed"); |
| return false; |
| } |
| |
| if (!venc_set_multislice_cfg(OMX_IndexParamVideoMpeg4,pParam->nSliceHeaderSpacing)) { |
| DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating slice_config"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoMpeg4"); |
| } |
| |
| break; |
| } |
| case OMX_IndexParamVideoH263: |
| { |
| OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData; |
| DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoH263"); |
| OMX_U32 bFrames = 0; |
| |
| if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { |
| m_profile_set = false; |
| m_level_set = false; |
| |
| if (!venc_set_profile_level (pParam->eProfile, pParam->eLevel)) { |
| DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile and level"); |
| return false; |
| } |
| |
| if (pParam->nBFrames) |
| DEBUG_PRINT_ERROR("WARNING: B frame not supported for H.263"); |
| |
| if (venc_set_intra_period (pParam->nPFrames, bFrames) == false) { |
| DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoH263"); |
| } |
| |
| break; |
| } |
| case OMX_IndexParamVideoAvc: |
| { |
| DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoAvc"); |
| OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData; |
| OMX_U32 bFrames = 0; |
| |
| if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { |
| DEBUG_PRINT_LOW("pParam->eProfile :%d ,pParam->eLevel %d", |
| pParam->eProfile,pParam->eLevel); |
| |
| m_profile_set = false; |
| m_level_set = false; |
| |
| if (!venc_set_profile_level (pParam->eProfile,pParam->eLevel)) { |
| DEBUG_PRINT_ERROR("ERROR: 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"); |
| bFrames = 0; |
| } |
| } |
| } |
| |
| #endif |
| |
| if (!venc_set_intra_period (pParam->nPFrames, bFrames)) { |
| DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed"); |
| return false; |
| } |
| |
| if (!venc_set_entropy_config (pParam->bEntropyCodingCABAC, pParam->nCabacInitIdc)) { |
| DEBUG_PRINT_ERROR("ERROR: Request for setting Entropy failed"); |
| return false; |
| } |
| |
| if (!venc_set_inloop_filter (pParam->eLoopFilterMode)) { |
| DEBUG_PRINT_ERROR("ERROR: Request for setting Inloop filter failed"); |
| return false; |
| } |
| |
| if (!venc_set_multislice_cfg(OMX_IndexParamVideoAvc, pParam->nSliceHeaderSpacing)) { |
| DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating slice_config"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoAvc"); |
| } |
| |
| //TBD, lot of other variables to be updated, yet to decide |
| break; |
| } |
| case OMX_IndexParamVideoIntraRefresh: |
| { |
| DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoIntraRefresh"); |
| 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("ERROR: Setting Intra refresh failed"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoIntraRefresh"); |
| } |
| |
| break; |
| } |
| case OMX_IndexParamVideoErrorCorrection: |
| { |
| DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoErrorCorrection"); |
| 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("ERROR: Setting Intra refresh failed"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoErrorCorrection"); |
| } |
| |
| break; |
| } |
| case OMX_IndexParamVideoProfileLevelCurrent: |
| { |
| DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoProfileLevelCurrent"); |
| OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level = |
| (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData; |
| |
| if (profile_level->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { |
| m_profile_set = false; |
| m_level_set = false; |
| |
| if (!venc_set_profile_level (profile_level->eProfile, |
| profile_level->eLevel)) { |
| DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating Profile and level"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoProfileLevelCurrent"); |
| } |
| |
| break; |
| } |
| case OMX_IndexParamVideoQuantization: |
| { |
| DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoQuantization"); |
| OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp = |
| (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)paramData; |
| |
| if (session_qp->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { |
| if (venc_set_session_qp (session_qp->nQpI, |
| session_qp->nQpP) == false) { |
| DEBUG_PRINT_ERROR("ERROR: Setting Session QP failed"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoQuantization"); |
| } |
| |
| break; |
| } |
| |
| case OMX_QcomIndexParamVideoQPRange: |
| { |
| DEBUG_PRINT_LOW("venc_set_param:OMX_QcomIndexParamVideoQPRange"); |
| OMX_QCOM_VIDEO_PARAM_QPRANGETYPE *qp_range = |
| (OMX_QCOM_VIDEO_PARAM_QPRANGETYPE *)paramData; |
| |
| if (qp_range->nPortIndex == (OMX_U32) PORT_INDEX_OUT) { |
| if (venc_set_qp_range (qp_range->minQP, |
| qp_range->maxQP) == false) { |
| DEBUG_PRINT_ERROR("ERROR: Setting QP Range failed"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexParamVideoQPRange"); |
| } |
| |
| break; |
| } |
| |
| case OMX_ExtraDataVideoEncoderSliceInfo: |
| { |
| 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("ERROR: Setting " |
| "OMX_ExtraDataVideoEncoderSliceInfo failed"); |
| return false; |
| } |
| |
| break; |
| } |
| case OMX_ExtraDataVideoLTRInfo: |
| { |
| DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataVideoLTRInfo"); |
| OMX_U32 extra_data = *(OMX_U32 *)paramData; |
| |
| if (venc_set_extradata(extra_data) == false) { |
| DEBUG_PRINT_ERROR("ERROR: Setting " |
| "OMX_ExtraDataVideoLTRInfo 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_QcomIndexEnableH263PlusPType: |
| { |
| QOMX_EXTNINDEX_PARAMTYPE* pParam = |
| (QOMX_EXTNINDEX_PARAMTYPE*)paramData; |
| DEBUG_PRINT_LOW("OMX_QcomIndexEnableH263PlusPType"); |
| |
| if (pParam->nPortIndex == PORT_INDEX_OUT) { |
| if (venc_set_plusptype(pParam->bEnable) == false) { |
| DEBUG_PRINT_ERROR("Setting PlusPType failed for H263"); |
| return OMX_ErrorUnsupportedSetting; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("OMX_QcomIndexEnableH263PlusPType " |
| "called on wrong port(%d)", pParam->nPortIndex); |
| return OMX_ErrorBadPortIndex; |
| } |
| |
| break; |
| } |
| case QOMX_IndexParamVideoLTRMode: |
| { |
| QOMX_VIDEO_PARAM_LTRMODE_TYPE* pParam = |
| (QOMX_VIDEO_PARAM_LTRMODE_TYPE*)paramData; |
| |
| if (pParam->nPortIndex == PORT_INDEX_OUT) { |
| if (!venc_set_ltrmode(pParam->eLTRMode)) { |
| DEBUG_PRINT_ERROR("Setting ltr mode failed"); |
| return OMX_ErrorUnsupportedSetting; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("QOMX_IndexParamVideoLTRMode " |
| "called on wrong port(%d)", pParam->nPortIndex); |
| return OMX_ErrorBadPortIndex; |
| } |
| |
| break; |
| } |
| case QOMX_IndexParamVideoLTRCount: |
| { |
| QOMX_VIDEO_PARAM_LTRCOUNT_TYPE* pParam = |
| (QOMX_VIDEO_PARAM_LTRCOUNT_TYPE*)paramData; |
| |
| if (pParam->nPortIndex == PORT_INDEX_OUT) { |
| if (!venc_set_ltrcount(pParam->nCount)) { |
| DEBUG_PRINT_ERROR("Setting ltr count failed"); |
| return OMX_ErrorUnsupportedSetting; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("QOMX_IndexParamVideoLTRCount " |
| "called on wrong port(%d)", pParam->nPortIndex); |
| return OMX_ErrorBadPortIndex; |
| } |
| |
| break; |
| } |
| case OMX_IndexParamVideoSliceFMO: |
| default: |
| DEBUG_PRINT_ERROR("venc_set_param: Unsupported index 0x%x", index); |
| break; |
| } |
| |
| return true; |
| } |
| |
| bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index) |
| { |
| venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| DEBUG_PRINT_LOW("Inside venc_set_config"); |
| |
| switch (index) { |
| case OMX_IndexConfigVideoBitrate: |
| { |
| 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("venc_set_config: OMX_IndexConfigVideoBitrate"); |
| |
| if (bit_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) { |
| if (venc_set_target_bitrate(bit_rate->nEncodeBitrate, 1) == false) { |
| DEBUG_PRINT_ERROR("ERROR: Setting Target Bit rate failed"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoBitrate"); |
| } |
| |
| break; |
| } |
| case OMX_IndexConfigVideoFramerate: |
| { |
| OMX_CONFIG_FRAMERATETYPE *frame_rate = (OMX_CONFIG_FRAMERATETYPE *) |
| configData; |
| DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoFramerate"); |
| |
| if (frame_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) { |
| if (venc_set_encode_framerate(frame_rate->xEncodeFramerate, 1) == false) { |
| DEBUG_PRINT_ERROR("ERROR: Setting Encode Framerate failed"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate"); |
| } |
| |
| break; |
| } |
| case QOMX_IndexConfigVideoIntraperiod: |
| { |
| DEBUG_PRINT_LOW("venc_set_param:QOMX_IndexConfigVideoIntraperiod"); |
| 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("ERROR: Request for setting intra period failed"); |
| return false; |
| } |
| } |
| |
| break; |
| } |
| case OMX_IndexConfigVideoIntraVOPRefresh: |
| { |
| OMX_CONFIG_INTRAREFRESHVOPTYPE *intra_vop_refresh = (OMX_CONFIG_INTRAREFRESHVOPTYPE *) |
| configData; |
| DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoIntraVOPRefresh"); |
| |
| if (intra_vop_refresh->nPortIndex == (OMX_U32)PORT_INDEX_OUT) { |
| if (venc_set_intra_vop_refresh(intra_vop_refresh->IntraRefreshVOP) == false) { |
| DEBUG_PRINT_ERROR("ERROR: Setting Encode Framerate failed"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate"); |
| } |
| |
| 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("venc_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("ERROR: Dimension Change for Rotation failed"); |
| return false; |
| } |
| |
| break; |
| } |
| case QOMX_IndexConfigVideoLTRPeriod: |
| { |
| QOMX_VIDEO_CONFIG_LTRPERIOD_TYPE* pParam = |
| (QOMX_VIDEO_CONFIG_LTRPERIOD_TYPE*)configData; |
| |
| if (pParam->nPortIndex == PORT_INDEX_OUT) { |
| if (!venc_set_ltrperiod(pParam->nFrames)) { |
| DEBUG_PRINT_ERROR("Setting ltr period failed"); |
| return OMX_ErrorUnsupportedSetting; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("QOMX_IndexConfigVideoLTRPeriod " |
| "called on wrong port(%d)", pParam->nPortIndex); |
| return OMX_ErrorBadPortIndex; |
| } |
| |
| break; |
| } |
| case QOMX_IndexConfigVideoLTRUse: |
| { |
| QOMX_VIDEO_CONFIG_LTRUSE_TYPE* pParam = |
| (QOMX_VIDEO_CONFIG_LTRUSE_TYPE*)configData; |
| |
| if (pParam->nPortIndex == PORT_INDEX_OUT) { |
| if (!venc_set_ltruse(pParam->nID, pParam->nFrames)) { |
| DEBUG_PRINT_ERROR("Setting ltr use failed"); |
| return OMX_ErrorUnsupportedSetting; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("QOMX_IndexConfigVideoLTRUse " |
| "called on wrong port(%d)", pParam->nPortIndex); |
| return OMX_ErrorBadPortIndex; |
| } |
| |
| break; |
| } |
| default: |
| DEBUG_PRINT_ERROR("venc_set_config: Unsupported index = 0x%x", index); |
| break; |
| } |
| |
| return true; |
| } |
| |
| unsigned venc_dev::venc_stop( void) |
| { |
| #ifdef MAX_RES_1080P |
| pmem_free(); |
| #endif |
| return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_STOP,NULL); |
| } |
| |
| unsigned venc_dev::venc_pause(void) |
| { |
| return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_PAUSE,NULL); |
| } |
| |
| 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_set_message_thread_id(pthread_t) |
| { |
| return 0; |
| } |
| |
| unsigned venc_dev::venc_start(void) |
| { |
| DEBUG_PRINT_HIGH("%s(): Check Profile/Level set in driver before start", |
| __func__); |
| |
| if (!venc_set_profile_level(0, 0)) { |
| DEBUG_PRINT_ERROR("ERROR: %s(): Driver Profile/Level is NOT SET", |
| __func__); |
| } else { |
| DEBUG_PRINT_HIGH("%s(): Driver Profile[%lu]/Level[%lu] successfully SET", |
| __func__, codec_profile.profile, profile_level.level); |
| } |
| |
| 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 (ltrmode.ltr_mode == (unsigned long)QOMX_VIDEO_LTRMode_Auto) { |
| recon_buffers_count = MAX_RECON_BUFFERS; |
| DEBUG_PRINT_HIGH("ltr mode enabled, so set recon buffers " |
| "count to %d", recon_buffers_count); |
| } |
| |
| if (!venc_allocate_recon_buffers()) |
| return ioctl(m_nDriver_fd, VEN_IOCTL_CMD_START, NULL); |
| else { |
| DEBUG_PRINT_ERROR("Failed in creating Recon buffers"); |
| 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", 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("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", |
| 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"); |
| 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("ERROR: ION Device open() Failed"); |
| return -1; |
| } |
| |
| recon_buff[count].alloc_data.len = size; |
| #ifdef MAX_RES_720P |
| recon_buff[count].alloc_data.ION_HEAP_MASK = ION_HEAP(MEM_HEAP_ID); |
| #else |
| recon_buff[count].alloc_data.ION_HEAP_MASK = (ION_HEAP(MEM_HEAP_ID) | |
| ION_HEAP(ION_IOMMU_HEAP_ID)); |
| #endif |
| recon_buff[count].alloc_data.flags = ION_FLAG_CACHED; |
| 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("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("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("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("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",buf_addr); |
| #ifdef USE_ION |
| |
| if (ioctl(recon_buff[count].ion_device_fd,ION_IOC_FREE, |
| &recon_buff[count].alloc_data.handle)) { |
| DEBUG_PRINT_LOW("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("Allocated virt:%p, FD: %d of size %d", 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"); |
| 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("Allocated virt:%p, FD: %d of size %d at index: %d", 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_LOW("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("cleaning Index %d of size %d",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("ENC_CONFIG: Codec: %d, Profile %d, level : %d", |
| m_sVenc_cfg.codectype, codec_profile.profile, profile_level.level); |
| |
| DEBUG_PRINT_HIGH("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("ENC_CONFIG: Bitrate: %d, RC: %d, I-Period: %d", |
| bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes); |
| |
| DEBUG_PRINT_HIGH("ENC_CONFIG: qpI: %d, qpP: %d, qpb: 0", |
| session_qp.iframeqp, session_qp.pframqp); |
| |
| DEBUG_PRINT_HIGH("ENC_CONFIG: minQP: %d, maxQP: %d", |
| qp_range.minqp, qp_range.maxqp); |
| |
| DEBUG_PRINT_HIGH("ENC_CONFIG: VOP_Resolution: %d, Slice-Mode: %d, Slize_Size: %d", |
| voptimecfg.voptime_resolution, multislice.mslice_mode, |
| multislice.mslice_size); |
| |
| DEBUG_PRINT_HIGH("ENC_CONFIG: EntropyMode: %d, CabacModel: %d", |
| entropy.longentropysel, entropy.cabacmodel); |
| |
| DEBUG_PRINT_HIGH("ENC_CONFIG: DB-Mode: %d, alpha: %d, Beta: %d", |
| dbkfilter.db_mode, dbkfilter.slicealpha_offset, |
| dbkfilter.slicebeta_offset); |
| |
| DEBUG_PRINT_HIGH("ENC_CONFIG: IntraMB/Frame: %d, HEC: %d", |
| intra_refresh.mbcount, hec.header_extension); |
| } |
| |
| unsigned venc_dev::venc_flush( unsigned port) |
| { |
| struct venc_ioctl_msg ioctl_msg; |
| struct venc_bufferflush buffer_index; |
| |
| if (port == PORT_INDEX_IN) { |
| DEBUG_PRINT_HIGH("Calling Input Flush"); |
| buffer_index.flush_mode = VEN_FLUSH_INPUT; |
| 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.in = (void*)&buffer_index; |
| ioctl_msg.out = NULL; |
| return ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FLUSH,(void*)&ioctl_msg); |
| } else { |
| return -1; |
| } |
| } |
| |
| //allocating I/P memory from pmem and register with the device |
| |
| |
| bool venc_dev::venc_use_buf(void *buf_addr, unsigned port,unsigned) |
| { |
| struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| struct pmem *pmem_tmp; |
| struct venc_bufferpayload dev_buffer = {0}; |
| struct venc_allocatorproperty buff_alloc_property = {0}; |
| |
| pmem_tmp = (struct pmem *)buf_addr; |
| |
| DEBUG_PRINT_LOW("venc_use_buf:: pmem_tmp = %p", pmem_tmp); |
| |
| if (port == PORT_INDEX_IN) { |
| dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; |
| dev_buffer.fd = pmem_tmp->fd; |
| dev_buffer.maped_size = pmem_tmp->size; |
| dev_buffer.sz = pmem_tmp->size; |
| dev_buffer.offset = pmem_tmp->offset; |
| |
| if ((m_sVenc_cfg.input_height %16 !=0) || (m_sVenc_cfg.input_width%16 != 0)) { |
| unsigned long ht = m_sVenc_cfg.input_height; |
| unsigned long wd = m_sVenc_cfg.input_width; |
| unsigned int luma_size, luma_size_2k; |
| |
| ht = (ht + 15) & ~15; |
| wd = (wd + 15) & ~15; |
| |
| luma_size = ht * wd; |
| luma_size_2k = (luma_size + 2047) & ~2047; |
| |
| dev_buffer.sz = luma_size_2k + ((luma_size/2 + 2047) & ~2047); |
| #ifdef USE_ION |
| ioctl_msg.in = NULL; |
| ioctl_msg.out = (void*)&buff_alloc_property; |
| |
| if (ioctl (m_nDriver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: venc_use_buf:get input buffer failed "); |
| return false; |
| } |
| |
| if (buff_alloc_property.alignment < 4096) { |
| dev_buffer.sz = ((dev_buffer.sz + 4095) & ~4095); |
| } else { |
| dev_buffer.sz = ((dev_buffer.sz + (buff_alloc_property.alignment - 1)) & |
| ~(buff_alloc_property.alignment - 1)); |
| } |
| |
| #endif |
| dev_buffer.maped_size = dev_buffer.sz; |
| } |
| |
| ioctl_msg.in = (void*)&dev_buffer; |
| ioctl_msg.out = NULL; |
| |
| DEBUG_PRINT_LOW("venc_use_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ |
| dev_buffer.pbuffer, \ |
| dev_buffer.fd, \ |
| dev_buffer.offset, \ |
| dev_buffer.maped_size); |
| |
| if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER,&ioctl_msg) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: venc_use_buf:set input buffer failed "); |
| return false; |
| } |
| } else if (port == PORT_INDEX_OUT) { |
| dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; |
| dev_buffer.fd = pmem_tmp->fd; |
| dev_buffer.sz = pmem_tmp->size; |
| dev_buffer.maped_size = pmem_tmp->size; |
| dev_buffer.offset = pmem_tmp->offset; |
| ioctl_msg.in = (void*)&dev_buffer; |
| ioctl_msg.out = NULL; |
| |
| DEBUG_PRINT_LOW("venc_use_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ |
| dev_buffer.pbuffer, \ |
| dev_buffer.fd, \ |
| dev_buffer.offset, \ |
| dev_buffer.maped_size); |
| |
| if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER,&ioctl_msg) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: venc_use_buf:set output buffer failed "); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: venc_use_buf:Invalid Port Index "); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool venc_dev::venc_free_buf(void *buf_addr, unsigned port) |
| { |
| struct venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| struct pmem *pmem_tmp; |
| struct venc_bufferpayload dev_buffer = {0}; |
| |
| pmem_tmp = (struct pmem *)buf_addr; |
| |
| DEBUG_PRINT_LOW("venc_use_buf:: pmem_tmp = %p", pmem_tmp); |
| |
| if (port == PORT_INDEX_IN) { |
| dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; |
| dev_buffer.fd = pmem_tmp->fd; |
| dev_buffer.maped_size = pmem_tmp->size; |
| dev_buffer.sz = pmem_tmp->size; |
| dev_buffer.offset = pmem_tmp->offset; |
| ioctl_msg.in = (void*)&dev_buffer; |
| ioctl_msg.out = NULL; |
| |
| DEBUG_PRINT_LOW("venc_free_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ |
| dev_buffer.pbuffer, \ |
| dev_buffer.fd, \ |
| dev_buffer.offset, \ |
| dev_buffer.maped_size); |
| |
| if (ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FREE_INPUT_BUFFER,&ioctl_msg) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: venc_free_buf: free input buffer failed "); |
| return false; |
| } |
| } else if (port == PORT_INDEX_OUT) { |
| dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer; |
| dev_buffer.fd = pmem_tmp->fd; |
| dev_buffer.sz = pmem_tmp->size; |
| dev_buffer.maped_size = pmem_tmp->size; |
| dev_buffer.offset = pmem_tmp->offset; |
| ioctl_msg.in = (void*)&dev_buffer; |
| ioctl_msg.out = NULL; |
| |
| DEBUG_PRINT_LOW("venc_free_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \ |
| dev_buffer.pbuffer, \ |
| dev_buffer.fd, \ |
| dev_buffer.offset, \ |
| dev_buffer.maped_size); |
| |
| if (ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FREE_OUTPUT_BUFFER,&ioctl_msg) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: venc_free_buf: free output buffer failed "); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: venc_free_buf:Invalid Port Index "); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool venc_dev::venc_color_align(OMX_BUFFERHEADERTYPE *buffer, |
| OMX_U32 width, OMX_U32 height) |
| { |
| DEBUG_PRINT_ERROR("%s not implemented!", __func__); |
| return OMX_ErrorUnsupportedSetting; |
| } |
| |
| bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf,unsigned,unsigned) |
| { |
| struct venc_buffer frameinfo; |
| struct pmem *temp_buffer; |
| struct venc_ioctl_msg ioctl_msg; |
| struct OMX_BUFFERHEADERTYPE *bufhdr; |
| |
| if (buffer == NULL) { |
| DEBUG_PRINT_ERROR("ERROR: venc_etb: buffer is NULL"); |
| return false; |
| } |
| |
| bufhdr = (OMX_BUFFERHEADERTYPE *)buffer; |
| |
| DEBUG_PRINT_LOW("Input buffer length %d",bufhdr->nFilledLen); |
| |
| if (pmem_data_buf) { |
| DEBUG_PRINT_LOW("Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf); |
| frameinfo.ptrbuffer = (OMX_U8 *)pmem_data_buf; |
| } else { |
| DEBUG_PRINT_LOW("Shared PMEM addr for i/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer); |
| frameinfo.ptrbuffer = (OMX_U8 *)bufhdr->pBuffer; |
| } |
| |
| frameinfo.clientdata = (void *) buffer; |
| frameinfo.sz = bufhdr->nFilledLen; |
| frameinfo.len = bufhdr->nFilledLen; |
| frameinfo.flags = bufhdr->nFlags; |
| frameinfo.offset = bufhdr->nOffset; |
| frameinfo.timestamp = bufhdr->nTimeStamp; |
| DEBUG_PRINT_LOW("i/p TS = %u", (OMX_U32)frameinfo.timestamp); |
| 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); |
| |
| if (ioctl(m_nDriver_fd,VEN_IOCTL_CMD_ENCODE_FRAME,&ioctl_msg) < 0) { |
| /*Generate an async error and move to invalid state*/ |
| return false; |
| } |
| |
| if (m_debug.in_buffer_log) { |
| venc_input_log_buffers(bufhdr, pmem_data_bufr, frameinfo.len); |
| } |
| |
| return true; |
| } |
| 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; |
| struct venc_buffer frameinfo; |
| struct OMX_BUFFERHEADERTYPE *bufhdr; |
| |
| if (buffer == NULL) { |
| return false; |
| } |
| |
| bufhdr = (OMX_BUFFERHEADERTYPE *)buffer; |
| |
| if (pmem_data_buf) { |
| DEBUG_PRINT_LOW("Internal PMEM addr for o/p Heap UseBuf: %p", pmem_data_buf); |
| frameinfo.ptrbuffer = (OMX_U8 *)pmem_data_buf; |
| } else { |
| DEBUG_PRINT_LOW("Shared PMEM addr for o/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer); |
| frameinfo.ptrbuffer = (OMX_U8 *)bufhdr->pBuffer; |
| } |
| |
| frameinfo.clientdata = buffer; |
| frameinfo.sz = bufhdr->nAllocLen; |
| frameinfo.flags = bufhdr->nFlags; |
| frameinfo.offset = bufhdr->nOffset; |
| |
| 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) { |
| DEBUG_PRINT_ERROR("ERROR: ioctl VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER failed"); |
| return false; |
| } |
| |
| 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_plusptype(OMX_BOOL enable) |
| { |
| venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| struct venc_plusptype plusptype = {0}; |
| DEBUG_PRINT_LOW("Set plusptype: %d", enable); |
| plusptype.plusptype_enable = enable; |
| ioctl_msg.in = (void*)&plusptype; |
| ioctl_msg.out = NULL; |
| |
| if (ioctl(m_nDriver_fd, VEN_IOCTL_SET_H263_PLUSPTYPE,(void*)&ioctl_msg) < 0) { |
| DEBUG_PRINT_ERROR("Request for setting plusptype for h263 failed"); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool venc_dev::venc_set_ltrmode(QOMX_VIDEO_LTRMODETYPE mode) |
| { |
| venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| venc_ltrmode ltr_mode; |
| ltr_mode.ltr_mode = (unsigned long)mode; |
| DEBUG_PRINT_HIGH("Set ltr mode: %d", mode); |
| ioctl_msg.in = (void*)<r_mode; |
| ioctl_msg.out = NULL; |
| |
| if (ioctl (m_nDriver_fd, VEN_IOCTL_SET_LTRMODE, (void*)&ioctl_msg) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: Setting ltrmode failed"); |
| return false; |
| } |
| |
| ltrmode.ltr_mode = (unsigned long)mode; |
| return true; |
| } |
| |
| bool venc_dev::venc_set_ltrcount(OMX_U32 count) |
| { |
| venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| venc_ltrcount ltr_count; |
| ltr_count.ltr_count = (unsigned long)count; |
| DEBUG_PRINT_HIGH("Set ltr count: %d", count); |
| ioctl_msg.in = (void*)<r_count; |
| ioctl_msg.out = NULL; |
| |
| if (ioctl (m_nDriver_fd, VEN_IOCTL_SET_LTRCOUNT, (void*)&ioctl_msg) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: Setting ltrcount failed"); |
| return false; |
| } |
| |
| ltrcount.ltr_count = (unsigned long)count; |
| return true; |
| } |
| |
| bool venc_dev::venc_set_ltrperiod(OMX_U32 period) |
| { |
| venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| venc_ltrperiod ltr_period; |
| ltr_period.ltr_period = (unsigned long)period; |
| DEBUG_PRINT_HIGH("Set ltr period: %d", period); |
| ioctl_msg.in = (void*)<r_period; |
| ioctl_msg.out = NULL; |
| |
| if (ioctl (m_nDriver_fd, VEN_IOCTL_SET_LTRPERIOD, (void*)&ioctl_msg) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: Setting ltrperiod failed"); |
| return false; |
| } |
| |
| ltrperiod.ltr_period = (unsigned long)period; |
| return true; |
| } |
| |
| bool venc_dev::venc_set_ltruse(OMX_U32 id, OMX_U32 frames) |
| { |
| venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| venc_ltruse ltr_use; |
| ltr_use.ltr_id = (unsigned long)id; |
| ltr_use.ltr_frames = (unsigned long)frames; |
| DEBUG_PRINT_HIGH("Set ltr use: id = %d, ltr_frames = %d", id, frames); |
| ioctl_msg.in = (void*)<r_use; |
| ioctl_msg.out = NULL; |
| |
| if (ioctl (m_nDriver_fd, VEN_IOCTL_SET_LTRUSE, (void*)&ioctl_msg) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: Setting ltruse failed"); |
| return false; |
| } |
| |
| 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}; |
| struct venc_sessionqp qp = {0, 0}; |
| DEBUG_PRINT_HIGH("venc_set_session_qp:: i_frame_qp = %d, p_frame_qp = %d", i_frame_qp, |
| p_frame_qp); |
| |
| qp.iframeqp = i_frame_qp; |
| qp.pframqp = p_frame_qp; |
| |
| 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("ERROR: Request for setting session qp failed"); |
| return false; |
| } |
| |
| session_qp.iframeqp = i_frame_qp; |
| session_qp.pframqp = p_frame_qp; |
| |
| return true; |
| } |
| |
| bool venc_dev::venc_set_qp_range(OMX_U32 min_qp, OMX_U32 max_qp) |
| { |
| venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| struct venc_qprange qp = {0, 0}; |
| DEBUG_PRINT_LOW("venc_set_qp_range:: min_qp = %d, max_qp = %d", min_qp, |
| max_qp); |
| |
| qp.minqp = min_qp; |
| qp.maxqp = max_qp; |
| |
| ioctl_msg.in = (void*)&qp; |
| ioctl_msg.out = NULL; |
| |
| if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_QP_RANGE,(void*)&ioctl_msg)< 0) { |
| DEBUG_PRINT_ERROR("ERROR: Request for setting qp range failed"); |
| return false; |
| } |
| |
| qp_range.minqp= min_qp; |
| qp_range.maxqp= max_qp; |
| |
| return true; |
| } |
| |
| bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel) |
| { |
| venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| struct venc_profile requested_profile; |
| struct ven_profilelevel requested_level; |
| unsigned const int *profile_tbl = NULL; |
| unsigned long mb_per_frame = 0, mb_per_sec = 0; |
| DEBUG_PRINT_HIGH("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_HIGH("Set profile/level was done already"); |
| 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("Save profile/level (%d/%d) for max allowed bitrate check", |
| m_eProfile, m_eLevel); |
| } |
| |
| DEBUG_PRINT_LOW("Validating Profile/Level from table"); |
| |
| if (!venc_validate_profile_level(&eProfile, &eLevel)) { |
| DEBUG_PRINT_LOW("ERROR: Profile/Level validation failed"); |
| return false; |
| } |
| |
| if (m_sVenc_cfg.codectype == VEN_CODEC_MPEG4) { |
| DEBUG_PRINT_LOW("eProfile = %d, OMX_VIDEO_MPEG4ProfileSimple = %d and " |
| "OMX_VIDEO_MPEG4ProfileAdvancedSimple = %d", eProfile, |
| OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4ProfileAdvancedSimple); |
| |
| if (eProfile == OMX_VIDEO_MPEG4ProfileSimple) { |
| requested_profile.profile = VEN_PROFILE_MPEG4_SP; |
| profile_tbl = (unsigned int const *) |
| (&mpeg4_profile_level_table[MPEG4_SP_START]); |
| profile_tbl += MPEG4_720P_LEVEL*5; |
| } else if (eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) { |
| requested_profile.profile = VEN_PROFILE_MPEG4_ASP; |
| profile_tbl = (unsigned int const *) |
| (&mpeg4_profile_level_table[MPEG4_ASP_START]); |
| profile_tbl += MPEG4_720P_LEVEL*5; |
| } else { |
| DEBUG_PRINT_LOW("ERROR: Unsupported MPEG4 profile = %u", |
| eProfile); |
| return false; |
| } |
| |
| DEBUG_PRINT_LOW("eLevel = %d, OMX_VIDEO_MPEG4Level0 = %d, OMX_VIDEO_MPEG4Level1 = %d," |
| "OMX_VIDEO_MPEG4Level2 = %d, OMX_VIDEO_MPEG4Level3 = %d, OMX_VIDEO_MPEG4Level4 = %d," |
| "OMX_VIDEO_MPEG4Level5 = %d", eLevel, OMX_VIDEO_MPEG4Level0, OMX_VIDEO_MPEG4Level1, |
| OMX_VIDEO_MPEG4Level2, OMX_VIDEO_MPEG4Level3, OMX_VIDEO_MPEG4Level4, OMX_VIDEO_MPEG4Level5); |
| |
| if (mb_per_frame >= 3600) { |
| 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 { |
| switch (eLevel) { |
| 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("MPEG4 Level 6 is set for 720p resolution"); |
| requested_level.level = VEN_LEVEL_MPEG4_6; |
| } else { |
| DEBUG_PRINT_LOW("MPEG4 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; |
| } |
| } |
| } else if (m_sVenc_cfg.codectype == VEN_CODEC_H263) { |
| if (eProfile == OMX_VIDEO_H263ProfileBaseline) { |
| requested_profile.profile = VEN_PROFILE_H263_BASELINE; |
| } else { |
| DEBUG_PRINT_LOW("ERROR: Unsupported H.263 profile = %u", |
| requested_profile.profile); |
| return false; |
| } |
| |
| //profile level |
| switch (eLevel) { |
| case OMX_VIDEO_H263Level10: |
| requested_level.level = VEN_LEVEL_H263_10; |
| break; |
| case OMX_VIDEO_H263Level20: |
| requested_level.level = VEN_LEVEL_H263_20; |
| break; |
| case OMX_VIDEO_H263Level30: |
| requested_level.level = VEN_LEVEL_H263_30; |
| break; |
| case OMX_VIDEO_H263Level40: |
| requested_level.level = VEN_LEVEL_H263_40; |
| break; |
| case OMX_VIDEO_H263Level45: |
| requested_level.level = VEN_LEVEL_H263_45; |
| break; |
| case OMX_VIDEO_H263Level50: |
| requested_level.level = VEN_LEVEL_H263_50; |
| break; |
| case OMX_VIDEO_H263Level60: |
| requested_level.level = VEN_LEVEL_H263_60; |
| break; |
| case OMX_VIDEO_H263Level70: |
| requested_level.level = VEN_LEVEL_H263_70; |
| break; |
| default: |
| return false; |
| break; |
| } |
| } else if (m_sVenc_cfg.codectype == VEN_CODEC_H264) { |
| if (eProfile == OMX_VIDEO_AVCProfileBaseline) { |
| requested_profile.profile = VEN_PROFILE_H264_BASELINE; |
| } else if (eProfile == OMX_VIDEO_AVCProfileMain) { |
| requested_profile.profile = VEN_PROFILE_H264_MAIN; |
| } else if (eProfile == OMX_VIDEO_AVCProfileHigh) { |
| requested_profile.profile = VEN_PROFILE_H264_HIGH; |
| } else { |
| DEBUG_PRINT_LOW("ERROR: Unsupported H.264 profile = %u", |
| requested_profile.profile); |
| return false; |
| } |
| |
| //profile level |
| switch (eLevel) { |
| case OMX_VIDEO_AVCLevel1: |
| requested_level.level = VEN_LEVEL_H264_1; |
| break; |
| case OMX_VIDEO_AVCLevel1b: |
| requested_level.level = VEN_LEVEL_H264_1b; |
| break; |
| case OMX_VIDEO_AVCLevel11: |
| requested_level.level = VEN_LEVEL_H264_1p1; |
| break; |
| case OMX_VIDEO_AVCLevel12: |
| requested_level.level = VEN_LEVEL_H264_1p2; |
| break; |
| case OMX_VIDEO_AVCLevel13: |
| requested_level.level = VEN_LEVEL_H264_1p3; |
| break; |
| case OMX_VIDEO_AVCLevel2: |
| requested_level.level = VEN_LEVEL_H264_2; |
| break; |
| case OMX_VIDEO_AVCLevel21: |
| requested_level.level = VEN_LEVEL_H264_2p1; |
| break; |
| case OMX_VIDEO_AVCLevel22: |
| requested_level.level = VEN_LEVEL_H264_2p2; |
| break; |
| case OMX_VIDEO_AVCLevel3: |
| requested_level.level = VEN_LEVEL_H264_3; |
| break; |
| 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("ERROR: Unsupported H.264 level= %u", |
| requested_level.level); |
| return false; |
| break; |
| } |
| } |
| |
| if (!m_profile_set) { |
| 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_ERROR("ERROR: Request for setting profile failed"); |
| return false; |
| } |
| |
| codec_profile.profile = requested_profile.profile; |
| m_profile_set = true; |
| DEBUG_PRINT_HIGH("Set codec profile = 0x%x", codec_profile.profile); |
| } |
| |
| if (!m_level_set) { |
| 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_ERROR("ERROR: Request for setting profile level failed"); |
| return false; |
| } |
| |
| profile_level.level = requested_level.level; |
| m_level_set = true; |
| DEBUG_PRINT_HIGH("Set codec level = 0x%x", profile_level.level); |
| } |
| |
| return true; |
| } |
| |
| bool venc_dev::venc_set_voptiming_cfg( OMX_U32 TimeIncRes) |
| { |
| venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| struct venc_voptimingcfg vop_timing_cfg; |
| |
| DEBUG_PRINT_HIGH("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("ERROR: 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("venc_set_intra_period: nPFrames = %u", |
| nPFrames); |
| 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_HIGH("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("ERROR: 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_entropy_config(OMX_BOOL enable, OMX_U32 i_cabac_level) |
| { |
| venc_ioctl_msg ioctl_msg = {NULL,NULL}; |
| struct venc_entropycfg entropy_cfg; |
| |
| memset(&entropy_cfg,0,sizeof(entropy_cfg)); |
| DEBUG_PRINT_LOW("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("Invalid Entropy mode for Baseline Profile"); |
| return false; |
| } |
| |
| 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_ERROR("ERROR: 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_multislice_cfg(OMX_INDEXTYPE Codec, OMX_U32 nSlicesize) // MB |
| { |
| venc_ioctl_msg ioctl_msg = {NULL, NULL}; |
| bool status = true; |
| struct venc_multiclicecfg multislice_cfg; |
| |
| 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("%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("ERROR: Request for setting multi-slice cfg failed"); |
| status = false; |
| } else { |
| multislice.mslice_mode = multislice_cfg.mslice_mode; |
| multislice.mslice_size = nSlicesize; |
| } |
| |
| 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) { |
| 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 { |
| DEBUG_PRINT_ERROR("ERROR: Invalid IntraRefresh Parameters:" |
| "mb count: %d, mb mode:%d", irMBs, ir_mode); |
| return false; |
| } |
| |
| 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("ERROR: 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("ERROR: Request for setting HEader Error correction failed"); |
| return false; |
| } |
| |
| hec.header_extension = error_resilience->bEnableHEC; |
| } |
| |
| if (error_resilience->bEnableRVLC) { |
| DEBUG_PRINT_ERROR("RVLC is not Supported"); |
| return false; |
| } |
| |
| if (( m_sVenc_cfg.codectype != OMX_VIDEO_CodingH263) && |
| (error_resilience->bEnableDataPartitioning)) { |
| DEBUG_PRINT_ERROR("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("%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("ERROR: 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("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("ERROR: 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_HIGH("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("ERROR: 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",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_HIGH("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) { |
| DEBUG_PRINT_ERROR("ERROR: Request for setting framerate failed"); |
| return false; |
| } |
| |
| m_sVenc_cfg.fps_den = frame_rate_cfg.fps_denominator; |
| m_sVenc_cfg.fps_num = frame_rate_cfg.fps_numerator; |
| |
| if (!config) { |
| m_level_set = false; |
| |
| if (venc_set_profile_level(0, 0)) { |
| DEBUG_PRINT_LOW("Calling set level (Framerate) with %d",profile_level.level); |
| } |
| } |
| |
| return true; |
| } |
| |
| bool venc_dev::venc_set_color_format(OMX_COLOR_FORMATTYPE color_format) |
| { |
| venc_ioctl_msg ioctl_msg = {NULL, NULL}; |
| |
| 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("WARNING: 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("Default color format YUV420SemiPlanar is set"); |
| } |
| |
| 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("ERROR: Request for setting color format failed"); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool venc_dev::venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh) |
| { |
| DEBUG_PRINT_LOW("venc_set_intra_vop_refresh: intra_vop = %uc", intra_vop_refresh); |
| |
| if (intra_vop_refresh == OMX_TRUE) { |
| if (ioctl(m_nDriver_fd, VEN_IOCTL_CMD_REQUEST_IFRAME, NULL) < 0) { |
| DEBUG_PRINT_ERROR("ERROR: Request for setting Intra VOP Refresh failed"); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_ERROR("ERROR: VOP Refresh is False, no effect"); |
| } |
| |
| return true; |
| } |
| |
| 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: |
| ratectrl_cfg.rcmode = VEN_RC_OFF; |
| break; |
| case OMX_Video_ControlRateVariableSkipFrames: |
| ratectrl_cfg.rcmode = VEN_RC_VBR_VFR; |
| break; |
| case OMX_Video_ControlRateVariable: |
| ratectrl_cfg.rcmode = VEN_RC_VBR_CFR; |
| break; |
| case OMX_Video_ControlRateConstantSkipFrames: |
| ratectrl_cfg.rcmode = VEN_RC_CBR_VFR; |
| break; |
| case OMX_Video_ControlRateConstant: |
| ratectrl_cfg.rcmode = VEN_RC_CBR_CFR; |
| break; |
| default: |
| status = false; |
| break; |
| } |
| |
| if (status) { |
| 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("ERROR: Request for setting rate control failed"); |
| status = false; |
| } else |
| rate_ctrl.rcmode = ratectrl_cfg.rcmode; |
| } |
| |
| return status; |
| } |
| |
| bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel) |
| { |
| bool status = true; |
| |
| if (eProfile == NULL || eLevel == NULL) { |
| return false; |
| } |
| |
| if (m_sVenc_cfg.codectype == VEN_CODEC_MPEG4) { |
| switch (codec_profile.profile) { |
| case VEN_PROFILE_MPEG4_SP: |
| *eProfile = OMX_VIDEO_MPEG4ProfileSimple; |
| break; |
| case VEN_PROFILE_MPEG4_ASP: |
| *eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; |
| break; |
| default: |
| *eProfile = OMX_VIDEO_MPEG4ProfileMax; |
| status = false; |
| break; |
| } |
| |
| if (!status) { |
| return status; |
| } |
| |
| //profile level |
| switch (profile_level.level) { |
| case VEN_LEVEL_MPEG4_0: |
| *eLevel = OMX_VIDEO_MPEG4Level0; |
| break; |
| case VEN_LEVEL_MPEG4_1: |
| *eLevel = OMX_VIDEO_MPEG4Level1; |
| break; |
| case VEN_LEVEL_MPEG4_2: |
| *eLevel = OMX_VIDEO_MPEG4Level2; |
| break; |
| case VEN_LEVEL_MPEG4_3: |
| *eLevel = OMX_VIDEO_MPEG4Level3; |
| break; |
| case VEN_LEVEL_MPEG4_4: |
| *eLevel = OMX_VIDEO_MPEG4Level4a; |
| break; |
| case VEN_LEVEL_MPEG4_5: |
| case VEN_LEVEL_MPEG4_6: |
| *eLevel = OMX_VIDEO_MPEG4Level5; |
| break; |
| default: |
| *eLevel = OMX_VIDEO_MPEG4LevelMax; |
| status = false; |
| break; |
| } |
| } else if (m_sVenc_cfg.codectype == VEN_CODEC_H263) { |
| if (codec_profile.profile == VEN_PROFILE_H263_BASELINE) { |
| *eProfile = OMX_VIDEO_H263ProfileBaseline; |
| } else { |
| *eProfile = OMX_VIDEO_H263ProfileMax; |
| return false; |
| } |
| |
| switch (profile_level.level) { |
| case VEN_LEVEL_H263_10: |
| *eLevel = OMX_VIDEO_H263Level10; |
| break; |
| case VEN_LEVEL_H263_20: |
| *eLevel = OMX_VIDEO_H263Level20; |
| break; |
| case VEN_LEVEL_H263_30: |
| *eLevel = OMX_VIDEO_H263Level30; |
| break; |
| case VEN_LEVEL_H263_40: |
| *eLevel = OMX_VIDEO_H263Level40; |
| break; |
| case VEN_LEVEL_H263_45: |
| *eLevel = OMX_VIDEO_H263Level45; |
| break; |
| case VEN_LEVEL_H263_50: |
| *eLevel = OMX_VIDEO_H263Level50; |
| break; |
| case VEN_LEVEL_H263_60: |
| *eLevel = OMX_VIDEO_H263Level60; |
| break; |
| case VEN_LEVEL_H263_70: |
| *eLevel = OMX_VIDEO_H263Level70; |
| break; |
| default: |
| *eLevel = OMX_VIDEO_H263LevelMax; |
| status = false; |
| break; |
| } |
| } else if (m_sVenc_cfg.codectype == VEN_CODEC_H264) { |
| switch (codec_profile.profile) { |
| case VEN_PROFILE_H264_BASELINE: |
| *eProfile = OMX_VIDEO_AVCProfileBaseline; |
| break; |
| case VEN_PROFILE_H264_MAIN: |
| *eProfile = OMX_VIDEO_AVCProfileMain; |
| break; |
| case VEN_PROFILE_H264_HIGH: |
| *eProfile = OMX_VIDEO_AVCProfileHigh; |
| break; |
| default: |
| *eProfile = OMX_VIDEO_AVCProfileMax; |
| status = false; |
| break; |
| } |
| |
| if (!status) { |
| return status; |
| } |
| |
| switch (profile_level.level) { |
| case VEN_LEVEL_H264_1: |
| *eLevel = OMX_VIDEO_AVCLevel1; |
| break; |
| case VEN_LEVEL_H264_1b: |
| *eLevel = OMX_VIDEO_AVCLevel1b; |
| break; |
| case VEN_LEVEL_H264_1p1: |
| *eLevel = OMX_VIDEO_AVCLevel11; |
| break; |
| case VEN_LEVEL_H264_1p2: |
| *eLevel = OMX_VIDEO_AVCLevel12; |
| break; |
| case VEN_LEVEL_H264_1p3: |
| *eLevel = OMX_VIDEO_AVCLevel13; |
| break; |
| case VEN_LEVEL_H264_2: |
| *eLevel = OMX_VIDEO_AVCLevel2; |
| break; |
| case VEN_LEVEL_H264_2p1: |
| *eLevel = OMX_VIDEO_AVCLevel21; |
| break; |
| case VEN_LEVEL_H264_2p2: |
| *eLevel = OMX_VIDEO_AVCLevel22; |
| break; |
| case VEN_LEVEL_H264_3: |
| *eLevel = OMX_VIDEO_AVCLevel3; |
| break; |
| case VEN_LEVEL_H264_3p1: |
| *eLevel = OMX_VIDEO_AVCLevel31; |
| break; |
| 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; |
| } |
| } |
| |
| return status; |
| } |
| |
| bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel) |
| { |
| OMX_U32 new_profile = 0, new_level = 0; |
| unsigned const int *profile_tbl = NULL; |
| OMX_U32 mb_per_frame, mb_per_sec; |
| bool profile_level_found = false; |
| |
| DEBUG_PRINT_LOW("Init profile table for respective codec"); |
| |
| //validate the ht,width,fps,bitrate and set the appropriate profile and level |
| if (m_sVenc_cfg.codectype == VEN_CODEC_MPEG4) { |
| if (*eProfile == 0) { |
| if (!m_profile_set) { |
| *eProfile = OMX_VIDEO_MPEG4ProfileSimple; |
| } else { |
| switch (codec_profile.profile) { |
| case VEN_PROFILE_MPEG4_ASP: |
| *eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple; |
| break; |
| case VEN_PROFILE_MPEG4_SP: |
| *eProfile = OMX_VIDEO_MPEG4ProfileSimple; |
| break; |
| default: |
| DEBUG_PRINT_LOW("%s(): Unknown Error", __func__); |
| return false; |
| } |
| } |
| } |
| |
| if (*eLevel == 0 && !m_level_set) { |
| *eLevel = OMX_VIDEO_MPEG4LevelMax; |
| } |
| |
| if (*eProfile == OMX_VIDEO_MPEG4ProfileSimple) { |
| profile_tbl = (unsigned int const *)mpeg4_profile_level_table; |
| } else if (*eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) { |
| profile_tbl = (unsigned int const *) |
| (&mpeg4_profile_level_table[MPEG4_ASP_START]); |
| } else { |
| DEBUG_PRINT_LOW("Unsupported MPEG4 profile type %lu", *eProfile); |
| return false; |
| } |
| } else if (m_sVenc_cfg.codectype == VEN_CODEC_H264) { |
| if (*eProfile == 0) { |
| if (!m_profile_set) { |
| *eProfile = OMX_VIDEO_AVCProfileBaseline; |
| } else { |
| switch (codec_profile.profile) { |
| case VEN_PROFILE_H264_BASELINE: |
| *eProfile = OMX_VIDEO_AVCProfileBaseline; |
| break; |
| case VEN_PROFILE_H264_MAIN: |
| *eProfile = OMX_VIDEO_AVCProfileMain; |
| break; |
| case VEN_PROFILE_H264_HIGH: |
| *eProfile = OMX_VIDEO_AVCProfileHigh; |
| break; |
| default: |
| DEBUG_PRINT_LOW("%s(): Unknown Error", __func__); |
| return false; |
| } |
| } |
| } |
| |
| if (*eLevel == 0 && !m_level_set) { |
| *eLevel = OMX_VIDEO_AVCLevelMax; |
| } |
| |
| if (*eProfile == OMX_VIDEO_AVCProfileBaseline) { |
| profile_tbl = (unsigned int const *)h264_profile_level_table; |
| } else if (*eProfile == OMX_VIDEO_AVCProfileHigh) { |
| profile_tbl = (unsigned int const *) |
| (&h264_profile_level_table[H264_HP_START]); |
| } else if (*eProfile == OMX_VIDEO_AVCProfileMain) { |
| profile_tbl = (unsigned int const *) |
| (&h264_profile_level_table[H264_MP_START]); |
| } else { |
| DEBUG_PRINT_LOW("Unsupported AVC profile type %lu", *eProfile); |
| return false; |
| } |
| } else if (m_sVenc_cfg.codectype == VEN_CODEC_H263) { |
| if (*eProfile == 0) { |
| if (!m_profile_set) { |
| *eProfile = OMX_VIDEO_H263ProfileBaseline; |
| } else { |
| switch (codec_profile.profile) { |
| case VEN_PROFILE_H263_BASELINE: |
| *eProfile = OMX_VIDEO_H263ProfileBaseline; |
| break; |
| default: |
| DEBUG_PRINT_LOW("%s(): Unknown Error", __func__); |
| return false; |
| } |
| } |
| } |
| |
| if (*eLevel == 0 && !m_level_set) { |
| *eLevel = OMX_VIDEO_H263LevelMax; |
| } |
| |
| if (*eProfile == OMX_VIDEO_H263ProfileBaseline) { |
| profile_tbl = (unsigned int const *)h263_profile_level_table; |
| } else { |
| DEBUG_PRINT_LOW("Unsupported H.263 profile type %lu", *eProfile); |
| return false; |
| } |
| } else { |
| DEBUG_PRINT_LOW("Invalid codec type"); |
| return false; |
| } |
| |
| 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 { |
| if (mb_per_frame <= (int)profile_tbl[0]) { |
| if (mb_per_sec <= (int)profile_tbl[1]) { |
| if (m_sVenc_cfg.targetbitrate <= (int)profile_tbl[2]) { |
| new_level = (int)profile_tbl[3]; |
| new_profile = (int)profile_tbl[4]; |
| profile_level_found = true; |
| DEBUG_PRINT_LOW("Appropriate profile/level found %d/%d", new_profile, new_level); |
| break; |
| } |
| } |
| } |
| |
| profile_tbl = profile_tbl + 5; |
| } while (profile_tbl[0] != 0); |
| |
| if (profile_level_found != true) { |
| DEBUG_PRINT_LOW("ERROR: Unsupported profile/level"); |
| return false; |
| } |
| |
| if ((*eLevel == OMX_VIDEO_MPEG4LevelMax) || (*eLevel == OMX_VIDEO_AVCLevelMax) |
| || (*eLevel == OMX_VIDEO_H263LevelMax)) { |
| *eLevel = new_level; |
| } |
| |
| DEBUG_PRINT_LOW("%s: Returning with eProfile = %lu" |
| "Level = %lu", __func__, *eProfile, *eLevel); |
| |
| return true; |
| } |
| |
| bool venc_dev::venc_max_allowed_bitrate_check(OMX_U32 nTargetBitrate) |
| { |
| unsigned const int *profile_tbl = NULL; |
| |
| switch (m_sVenc_cfg.codectype) { |
| 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; |
| } |
| |
| 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) { |
| if (profile_tbl[3] == m_eLevel) { |
| 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 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 |