1 /*--------------------------------------------------------------------------
2 Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are met:
6     * Redistributions of source code must retain the above copyright
7       notice, this list of conditions and the following disclaimer.
8     * Redistributions in binary form must reproduce the above copyright
9       notice, this list of conditions and the following disclaimer in the
10       documentation and/or other materials provided with the distribution.
11     * Neither the name of The Linux Foundation nor
12       the names of its contributors may be used to endorse or promote
13       products derived from this software without specific prior written
14       permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 --------------------------------------------------------------------------*/
28 #include<string.h>
29 #include <sys/ioctl.h>
30 #include <sys/prctl.h>
31 #include<unistd.h>
32 #include <fcntl.h>
33 #include "video_encoder_device.h"
34 #include "omx_video_encoder.h"
35 #include <linux/android_pmem.h>
36 #ifdef USE_ION
37 #include <linux/msm_ion.h>
38 #endif
39 
40 #define MPEG4_SP_START 0
41 #define MPEG4_ASP_START (MPEG4_SP_START + 8)
42 #define MPEG4_720P_LEVEL 6
43 #define H263_BP_START 0
44 #define H264_BP_START 0
45 #define H264_HP_START (H264_BP_START + 13)
46 #define H264_MP_START (H264_BP_START + 26)
47 
48 /* MPEG4 profile and level table*/
49 static const unsigned int mpeg4_profile_level_table[][5]= {
50     /*max mb per frame, max mb per sec, max bitrate, level, profile*/
51     {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple},
52     {99,1485,64000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple},
53     {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple},
54     {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple},
55     {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple},
56     {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
57     {3600,108000,12000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
58     {0,0,0,0,0},
59 
60     {99,1485,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
61     {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
62     {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
63     {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
64     {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
65     {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
66     {0,0,0,0,0},
67 };
68 
69 /* H264 profile and level table*/
70 static const unsigned int h264_profile_level_table[][5]= {
71     /*max mb per frame, max mb per sec, max bitrate, level, profile*/
72     {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline},
73     {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline},
74     {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline},
75     {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline},
76     {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline},
77     {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline},
78     {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline},
79     {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline},
80     {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline},
81     {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline},
82     {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileBaseline},
83     {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline},
84     {0,0,0,0,0},
85 
86     {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh},
87     {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh},
88     {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh},
89     {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh},
90     {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh},
91     {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh},
92     {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh},
93     {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh},
94     {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh},
95     {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh},
96     {5120,216000,25000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileHigh},
97     {8192,245760,25000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh},
98     {0,0,0,0,0},
99 
100     {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileMain},
101     {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain},
102     {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain},
103     {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain},
104     {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain},
105     {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain},
106     {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain},
107     {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain},
108     {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain},
109     {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain},
110     {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileMain},
111     {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain},
112     {0,0,0,0,0}
113 
114 };
115 
116 /* H263 profile and level table*/
117 static const unsigned int h263_profile_level_table[][5]= {
118     /*max mb per frame, max mb per sec, max bitrate, level, profile*/
119     {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline},
120     {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline},
121     {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline},
122     {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline},
123     {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline},
124     {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline},
125     {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline},
126     {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline},
127     {0,0,0,0,0}
128 };
129 
130 #define Log2(number, power)  { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) &&  power < 16) { temp >>=0x1; power++; } }
131 #define Q16ToFraction(q,num,den) { OMX_U32 power; Log2(q,power);  num = q >> power; den = 0x1 << (16 - power); }
132 
133 #define BUFFER_LOG_LOC "/data/misc/media"
134 
135 //constructor
venc_dev(class omx_venc * venc_class)136 venc_dev::venc_dev(class omx_venc *venc_class)
137 {
138     m_max_allowed_bitrate_check = false;
139     m_eLevel = 0;
140     m_eProfile = 0;
141     pthread_mutex_init(&loaded_start_stop_mlock, NULL);
142     pthread_cond_init (&loaded_start_stop_cond, NULL);
143     memset(&m_debug,0,sizeof(m_debug));
144 
145     char property_value[PROPERTY_VALUE_MAX] = {0};
146     property_value[0] = '\0';
147     property_get("vidc.enc.log.in", property_value, "0");
148     m_debug.in_buffer_log = atoi(property_value);
149 
150     property_value[0] = '\0';
151     property_get("vidc.enc.log.out", property_value, "0");
152     m_debug.out_buffer_log = atoi(property_value);
153     snprintf(m_debug.log_loc, PROPERTY_VAL_MAX,
154              "%s", BUFFER_LOG_LOC);
155 
156     DEBUG_PRINT_LOW("venc_dev constructor");
157 }
158 
~venc_dev()159 venc_dev::~venc_dev()
160 {
161     pthread_cond_destroy(&loaded_start_stop_cond);
162     pthread_mutex_destroy(&loaded_start_stop_mlock);
163     DEBUG_PRINT_LOW("venc_dev distructor");
164 }
165 
async_venc_message_thread(void * input)166 void* async_venc_message_thread (void *input)
167 {
168     struct venc_ioctl_msg ioctl_msg ={NULL,NULL};
169     struct venc_timeout timeout;
170     struct venc_msg venc_msg;
171     int error_code = 0;
172     omx_venc *omx = reinterpret_cast<omx_venc*>(input);
173 
174     prctl(PR_SET_NAME, (unsigned long)"VideoEncCallBackThread", 0, 0, 0);
175     timeout.millisec = VEN_TIMEOUT_INFINITE;
176 
177     while (1) {
178         ioctl_msg.in = NULL;
179         ioctl_msg.out = (void*)&venc_msg;
180 
181         /*Wait for a message from the video decoder driver*/
182         error_code = ioctl(omx->handle->m_nDriver_fd,VEN_IOCTL_CMD_READ_NEXT_MSG,(void *)&ioctl_msg);
183 
184         if (error_code == -512) { // ERESTARTSYS
185             DEBUG_PRINT_ERROR("ERESTARTSYS received in ioctl read next msg!");
186         } else if (error_code <0) {
187             DEBUG_PRINT_LOW("ioctl VEN_IOCTL_CMD_READ_NEXT_MSG failed");
188             break;
189         } else if (omx->async_message_process(input,&venc_msg) < 0) {
190             DEBUG_PRINT_ERROR("ERROR: Wrong ioctl message");
191             break;
192         }
193     }
194     DEBUG_PRINT_HIGH("omx_venc: Async Thread exit");
195     return NULL;
196 }
197 
venc_extradata_log_buffers(char * buffer_addr)198 int venc_dev::venc_extradata_log_buffers(char *buffer_addr)
199 {
200     return OMX_ErrorUnsupportedSetting;
201 }
202 
venc_output_log_buffers(const char * buffer_addr,int buffer_len)203 int venc_dev::venc_output_log_buffers(const char *buffer_addr, int buffer_len)
204 {
205     if (m_debug.out_buffer_log && !m_debug.outfile) {
206         int size = 0;
207         if(m_sVenc_cfg.codectype == VEN_CODEC_MPEG4) {
208            size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%d_%d_%p.m4v",
209                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
210         } else if(m_sVenc_cfg.codectype == VEN_CODEC_H264) {
211            size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%d_%d_%p.264",
212                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
213         } else if(m_sVenc_cfg.codectype == VENC_CODEC_H263) {
214            size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%d_%d_%p.263",
215                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
216         } else if(m_sVenc_cfg.codectype == VENC_CODEC_VP8) {
217            size = snprintf(m_debug.outfile_name, PROPERTY_VALUE_MAX, "%s/output_enc_%d_%d_%p.ivf",
218                            m_debug.log_loc, m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, this);
219         }
220         if ((size > PROPERTY_VALUE_MAX) || (size < 0)) {
221             DEBUG_PRINT_ERROR("Failed to open output file: %s for logging as size:%d",
222                                m_debug.outfile_name, size);
223             return -1;
224         }
225         m_debug.outfile = fopen(m_debug.outfile_name, "ab");
226         if (!m_debug.outfile) {
227             DEBUG_PRINT_ERROR("Failed to open output file: %s for logging errno:%d",
228                               m_debug.outfile_name, errno);
229             m_debug.outfile_name[0] = '\0';
230             return -1;
231         }
232     }
233     if (m_debug.outfile && buffer_len) {
234         DEBUG_PRINT_LOW("%s buffer_len:%d", __func__, buffer_len);
235         fwrite(buffer_addr, buffer_len, 1, m_debug.outfile);
236     }
237     return 0;
238 }
239 
venc_get_output_log_flag()240 bool venc_dev::venc_get_output_log_flag()
241 {
242     return (m_debug.out_buffer_log == 1);
243 }
244 
venc_input_log_buffers(OMX_BUFFERHEADERTYPE * pbuffer,void * pmem_data_buf,int framelen)245 int venc_dev::venc_input_log_buffers(OMX_BUFFERHEADERTYPE *pbuffer, void *pmem_data_buf, int framelen) {
246     if (!m_debug.infile) {
247         int size = snprintf(m_debug.infile_name, PROPERTY_VALUE_MAX, "%s/input_enc_%d_%d_%p.yuv",
248                            m_debug.log_loc, m_sVenc_cfg.input_width,
249                            m_sVenc_cfg.input_height, this);
250         if ((size > PROPERTY_VALUE_MAX) || (size < 0)) {
251             DEBUG_PRINT_ERROR("Failed to open input file: %s for logging size:%d",
252                                m_debug.infile_name, size);
253             return -1;
254         }
255         m_debug.infile = fopen (m_debug.infile_name, "ab");
256         if (!m_debug.infile) {
257             DEBUG_PRINT_HIGH("Failed to open input file: %s for logging", m_debug.infile);
258             m_debug.infile_name[0] = '\0';
259             return -1;
260         }
261     }
262     if (m_debug.infile && pbuffer && pbuffer->nFilledLen) {
263 #ifdef MAX_RES_1080P
264        int y_size = 0;
265        int c_offset = 0;
266        unsigned char *buf_addr = NULL;
267 
268        y_size = m_sVenc_cfg.input_width * m_sVenc_cfg.input_height;
269        //chroma offset is y_size aligned to the 2k boundary
270        c_offset= (y_size + 2047) & (~(2047));
271 
272        if (pmem_data_buf) {
273            DEBUG_PRINT_LOW("Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf);
274            buf_addr = (OMX_U8 *)pmem_data_buf;
275        } else {
276            DEBUG_PRINT_LOW("Shared PMEM addr for i/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer);
277            buf_addr = (unsigned char *)mmap(NULL,
278                       ((encoder_media_buffer_type *)pbuffer->pBuffer)->meta_handle->data[2],
279                       PROT_READ|PROT_WRITE, MAP_SHARED,
280                       ((encoder_media_buffer_type *)pbuffer->pBuffer)->meta_handle->data[0], 0);
281        }
282 
283        if (m_debug.infile) {
284            fwrite((const char *)buf_addr, y_size, 1, m_debug.infile);
285            fwrite((const char *)(buf_addr + c_offset), (y_size>>1), 1, m_debug.infile);
286        }
287 
288        if (!pmem_data_buf) {
289            munmap (buf_addr, ((encoder_media_buffer_type *)pbuffer->pBuffer)->meta_handle->data[2]);
290        }
291 #else
292        if (m_debug.infile) {
293            OMX_U8* ptrbuffer = NULL;
294            if (pmem_data_buf) {
295                DEBUG_PRINT_LOW("Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf);
296                ptrbuffer = (OMX_U8 *)pmem_data_buf;
297            } else {
298                DEBUG_PRINT_LOW("Shared PMEM addr for i/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer);
299                ptrbuffer = (OMX_U8 *)bufhdr->pBuffer;
300            }
301            fwrite((const char *)ptrbuffer, framelen, 1, m_debug.infile);
302        }
303 
304 #endif
305     }
306     return 0;
307 }
308 
venc_open(OMX_U32 codec)309 bool venc_dev::venc_open(OMX_U32 codec)
310 {
311     struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
312     int r;
313     unsigned int   alignment = 0,buffer_size = 0, temp =0;
314 
315     m_nDriver_fd = open ("/dev/msm_vidc_enc",O_RDWR|O_NONBLOCK);
316 
317     if (m_nDriver_fd == 0) {
318         DEBUG_PRINT_ERROR("ERROR: Got fd as 0 for msm_vidc_enc, Opening again");
319         m_nDriver_fd = open ("/dev/msm_vidc_enc",O_RDWR|O_NONBLOCK);
320     }
321 
322     if ((int)m_nDriver_fd < 0) {
323         DEBUG_PRINT_ERROR("ERROR: Omx_venc::Comp Init Returning failure");
324         return false;
325     }
326 
327     DEBUG_PRINT_LOW("m_nDriver_fd = %d", m_nDriver_fd);
328 #ifdef SINGLE_ENCODER_INSTANCE
329     OMX_U32 num_instances = 0;
330     ioctl_msg.in = NULL;
331     ioctl_msg.out = &num_instances;
332 
333     if (ioctl (m_nDriver_fd, VEN_IOCTL_GET_NUMBER_INSTANCES, (void*)&ioctl_msg) < 0 ) {
334         DEBUG_PRINT_ERROR("ERROR: Request number of encoder instances failed");
335     } else if (num_instances > 1) {
336         DEBUG_PRINT_ERROR("Second encoder instance rejected!");
337         venc_close();
338         return false;
339     }
340 
341 #endif
342     // set the basic configuration of the video encoder driver
343     m_sVenc_cfg.input_width = OMX_CORE_QCIF_WIDTH;
344     m_sVenc_cfg.input_height= OMX_CORE_QCIF_HEIGHT;
345     m_sVenc_cfg.dvs_width = OMX_CORE_QCIF_WIDTH;
346     m_sVenc_cfg.dvs_height = OMX_CORE_QCIF_HEIGHT;
347     m_sVenc_cfg.fps_num = 30;
348     m_sVenc_cfg.fps_den = 1;
349     m_sVenc_cfg.targetbitrate = 64000;
350 #ifdef MAX_RES_1080P
351     m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12_16M2KA;
352 #else
353     m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12;
354 #endif
355     // initializing QP range parameters
356     qp_range.minqp = 2;
357 
358     if (codec == OMX_VIDEO_CodingAVC)
359         qp_range.maxqp = 51;
360     else
361         qp_range.maxqp = 31;
362 
363     if (codec == OMX_VIDEO_CodingMPEG4) {
364         m_sVenc_cfg.codectype = VEN_CODEC_MPEG4;
365         codec_profile.profile = VEN_PROFILE_MPEG4_SP;
366         profile_level.level = VEN_LEVEL_MPEG4_2;
367     } else if (codec == OMX_VIDEO_CodingH263) {
368         m_sVenc_cfg.codectype = VEN_CODEC_H263;
369         codec_profile.profile = VEN_PROFILE_H263_BASELINE;
370         profile_level.level = VEN_LEVEL_H263_20;
371     }
372 
373     if (codec == OMX_VIDEO_CodingAVC) {
374         m_sVenc_cfg.codectype = VEN_CODEC_H264;
375         codec_profile.profile = VEN_PROFILE_H264_BASELINE;
376         profile_level.level = VEN_LEVEL_H264_1p1;
377     }
378 
379     ioctl_msg.in = (void*)&m_sVenc_cfg;
380     ioctl_msg.out = NULL;
381 
382     if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < 0 ) {
383         DEBUG_PRINT_ERROR("ERROR: Request for setting base configuration failed");
384         return false;
385     }
386 
387     // Get the I/P and O/P buffer requirements
388     ioctl_msg.in = NULL;
389     ioctl_msg.out = (void*)&m_sInput_buff_property;
390 
391     if (ioctl (m_nDriver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) {
392         DEBUG_PRINT_ERROR("ERROR: Request for getting i/p buffer requirement failed");
393         return false;
394     }
395 
396     ioctl_msg.in = NULL;
397     ioctl_msg.out = (void*)&m_sOutput_buff_property;
398 
399     if (ioctl (m_nDriver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) {
400         DEBUG_PRINT_ERROR("ERROR: Request for getting o/p buffer requirement failed");
401         return false;
402     }
403 
404     m_profile_set = false;
405     m_level_set = false;
406 
407     if (venc_set_profile_level(0, 0)) {
408         DEBUG_PRINT_HIGH("%s(): Init Profile/Level setting success",
409                 __func__);
410     }
411 
412     recon_buffers_count = MAX_RECON_BUFFERS;
413     ltrmode.ltr_mode = 0;
414     ltrcount.ltr_count = 0;
415     ltrperiod.ltr_period = 0;
416 
417     return true;
418 }
419 
venc_close()420 void venc_dev::venc_close()
421 {
422     DEBUG_PRINT_LOW("venc_close: fd = %d", m_nDriver_fd);
423 
424     if ((int)m_nDriver_fd >= 0) {
425         DEBUG_PRINT_HIGH("venc_close(): Calling VEN_IOCTL_CMD_STOP_READ_MSG");
426         (void)ioctl(m_nDriver_fd, VEN_IOCTL_CMD_STOP_READ_MSG,
427                 NULL);
428         DEBUG_PRINT_LOW("Calling close()");
429         close(m_nDriver_fd);
430         m_nDriver_fd = -1;
431     }
432 
433     if (m_debug.infile) {
434         fclose(m_debug.infile);
435         m_debug.infile = NULL;
436     }
437     if (m_debug.outfile) {
438         fclose(m_debug.outfile);
439         m_debug.outfile = NULL;
440     }
441 
442 }
443 
venc_set_buf_req(unsigned long * min_buff_count,unsigned long * actual_buff_count,unsigned long * buff_size,unsigned long port)444 bool venc_dev::venc_set_buf_req(unsigned long *min_buff_count,
445         unsigned long *actual_buff_count,
446         unsigned long *buff_size,
447         unsigned long port)
448 {
449     struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
450     unsigned long temp_count = 0;
451 
452     if (port == 0) {
453         if (*actual_buff_count > m_sInput_buff_property.mincount) {
454             temp_count = m_sInput_buff_property.actualcount;
455             m_sInput_buff_property.actualcount = *actual_buff_count;
456             ioctl_msg.in = (void*)&m_sInput_buff_property;
457             ioctl_msg.out = NULL;
458 
459             if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) {
460                 DEBUG_PRINT_ERROR("ERROR: Request for setting i/p buffer requirement failed");
461                 m_sInput_buff_property.actualcount = temp_count;
462                 return false;
463             }
464 
465             DEBUG_PRINT_LOW("I/P Count set to %lu", *actual_buff_count);
466         }
467     } else {
468         if (*actual_buff_count > m_sOutput_buff_property.mincount) {
469             temp_count = m_sOutput_buff_property.actualcount;
470             m_sOutput_buff_property.actualcount = *actual_buff_count;
471             ioctl_msg.in = (void*)&m_sOutput_buff_property;
472             ioctl_msg.out = NULL;
473 
474             if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) {
475                 DEBUG_PRINT_ERROR("ERROR: Request for setting o/p buffer requirement failed");
476                 m_sOutput_buff_property.actualcount = temp_count;
477                 return false;
478             }
479 
480             DEBUG_PRINT_LOW("O/P Count set to %lu", *actual_buff_count);
481         }
482     }
483 
484     return true;
485 
486 }
487 
venc_loaded_start()488 bool venc_dev::venc_loaded_start()
489 {
490     struct timespec ts;
491     int status = 0;
492 
493     if (ioctl (m_nDriver_fd,VEN_IOCTL_CMD_START, NULL) < 0) {
494         DEBUG_PRINT_ERROR("ERROR: VEN_IOCTL_CMD_START failed");
495         return false;
496     }
497 
498     if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
499         DEBUG_PRINT_ERROR("%s: clock_gettime failed", __func__);
500         return false;
501     }
502 
503     ts.tv_sec += 1;
504     pthread_mutex_lock(&loaded_start_stop_mlock);
505     DEBUG_PRINT_LOW("%s: wait on start done", __func__);
506     status = pthread_cond_timedwait(&loaded_start_stop_cond,
507             &loaded_start_stop_mlock, &ts);
508 
509     if (status != 0) {
510         DEBUG_PRINT_ERROR("%s: error status = %d, %s", __func__,
511                 status, strerror(status));
512         pthread_mutex_unlock(&loaded_start_stop_mlock);
513         return false;
514     }
515 
516     DEBUG_PRINT_LOW("%s: wait over on start done", __func__);
517     pthread_mutex_unlock(&loaded_start_stop_mlock);
518     DEBUG_PRINT_LOW("%s: venc_loaded_start success", __func__);
519     return true;
520 }
521 
venc_loaded_stop()522 bool venc_dev::venc_loaded_stop()
523 {
524     struct timespec ts;
525     int status = 0;
526 
527     if (ioctl (m_nDriver_fd,VEN_IOCTL_CMD_STOP, NULL) < 0) {
528         DEBUG_PRINT_ERROR("ERROR: VEN_IOCTL_CMD_STOP failed");
529         return false;
530     }
531 
532     if (clock_gettime(CLOCK_REALTIME, &ts) < 0) {
533         DEBUG_PRINT_ERROR("%s: clock_gettime failed", __func__);
534         return false;
535     }
536 
537     ts.tv_sec += 1;
538     pthread_mutex_lock(&loaded_start_stop_mlock);
539     DEBUG_PRINT_LOW("%s: wait on stop done", __func__);
540     status = pthread_cond_timedwait(&loaded_start_stop_cond,
541             &loaded_start_stop_mlock, &ts);
542 
543     if (status != 0) {
544         DEBUG_PRINT_ERROR("%s: error status = %d, %s", __func__,
545                 status, strerror(status));
546         pthread_mutex_unlock(&loaded_start_stop_mlock);
547         return false;
548     }
549 
550     DEBUG_PRINT_LOW("%s: wait over on stop done", __func__);
551     pthread_mutex_unlock(&loaded_start_stop_mlock);
552     DEBUG_PRINT_LOW("%s: venc_loaded_stop success", __func__);
553     return true;
554 }
555 
venc_loaded_start_done()556 bool venc_dev::venc_loaded_start_done()
557 {
558     pthread_mutex_lock(&loaded_start_stop_mlock);
559     DEBUG_PRINT_LOW("%s: signal start done", __func__);
560     pthread_cond_signal(&loaded_start_stop_cond);
561     pthread_mutex_unlock(&loaded_start_stop_mlock);
562     return true;
563 }
564 
venc_loaded_stop_done()565 bool venc_dev::venc_loaded_stop_done()
566 {
567     pthread_mutex_lock(&loaded_start_stop_mlock);
568     DEBUG_PRINT_LOW("%s: signal stop done", __func__);
569     pthread_cond_signal(&loaded_start_stop_cond);
570     pthread_mutex_unlock(&loaded_start_stop_mlock);
571     return true;
572 }
573 
venc_get_seq_hdr(void * buffer,unsigned buffer_size,unsigned * header_len)574 bool venc_dev::venc_get_seq_hdr(void *buffer,
575         unsigned buffer_size, unsigned *header_len)
576 {
577     struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
578     int i = 0;
579     DEBUG_PRINT_HIGH("venc_dev::venc_get_seq_hdr");
580     venc_seqheader seq_in, seq_out;
581     seq_in.hdrlen = 0;
582     seq_in.bufsize = buffer_size;
583     seq_in.hdrbufptr = (unsigned char*)buffer;
584 
585     if (seq_in.hdrbufptr == NULL) {
586         DEBUG_PRINT_ERROR("ERROR: malloc for sequence header failed");
587         return false;
588     }
589 
590     DEBUG_PRINT_LOW("seq_in: buf=%x, sz=%d, hdrlen=%d", seq_in.hdrbufptr,
591             seq_in.bufsize, seq_in.hdrlen);
592 
593     ioctl_msg.in = (void*)&seq_in;
594     ioctl_msg.out = (void*)&seq_out;
595 
596     if (ioctl (m_nDriver_fd,VEN_IOCTL_GET_SEQUENCE_HDR,(void*)&ioctl_msg) < 0) {
597         DEBUG_PRINT_ERROR("ERROR: Request for getting sequence header failed");
598         return false;
599     }
600 
601     if (seq_out.hdrlen == 0) {
602         DEBUG_PRINT_ERROR("ERROR: Seq header returned zero length header");
603         DEBUG_PRINT_ERROR("seq_out: buf=%x, sz=%d, hdrlen=%d", seq_out.hdrbufptr,
604                 seq_out.bufsize, seq_out.hdrlen);
605         return false;
606     }
607 
608     *header_len = seq_out.hdrlen;
609     DEBUG_PRINT_LOW("seq_out: buf=%x, sz=%d, hdrlen=%d", seq_out.hdrbufptr,
610             seq_out.bufsize, seq_out.hdrlen);
611 
612     return true;
613 }
614 
venc_get_capability_ltrcount(unsigned long * min,unsigned long * max,unsigned long * step_size)615 bool venc_dev::venc_get_capability_ltrcount(unsigned long *min,
616         unsigned long *max, unsigned long *step_size)
617 {
618     struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
619     venc_range  cap_ltr_count;
620     ioctl_msg.in = NULL;
621     ioctl_msg.out = (void*)&cap_ltr_count;
622 
623     if (ioctl (m_nDriver_fd, VEN_IOCTL_GET_CAPABILITY_LTRCOUNT,
624                 (void*)&ioctl_msg) < 0) {
625         DEBUG_PRINT_ERROR("ERROR: Get LTR Capability failed");
626         return false;
627     } else {
628         *min = cap_ltr_count.min;
629         *max = cap_ltr_count.max;
630         *step_size = cap_ltr_count.step_size;
631         DEBUG_PRINT_HIGH("LTR Capability: min=%x, max=%d, step_size=%d",
632                 *min, *max, *step_size);
633     }
634 
635     return true;
636 }
637 
venc_get_buf_req(unsigned long * min_buff_count,unsigned long * actual_buff_count,unsigned long * buff_size,unsigned long port)638 bool venc_dev::venc_get_buf_req(unsigned long *min_buff_count,
639         unsigned long *actual_buff_count,
640         unsigned long *buff_size,
641         unsigned long port)
642 {
643     struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
644 
645     if (port == 0) {
646         ioctl_msg.in = NULL;
647         ioctl_msg.out = (void*)&m_sInput_buff_property;
648 
649         if (ioctl (m_nDriver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) {
650             DEBUG_PRINT_ERROR("ERROR: Request for getting i/p buffer requirement failed");
651             return false;
652         }
653 
654         *min_buff_count = m_sInput_buff_property.mincount;
655         *actual_buff_count = m_sInput_buff_property.actualcount;
656 #ifdef USE_ION
657         // For ION memory allocations of the allocated buffer size
658         // must be 4k aligned, hence aligning the input buffer
659         // size to 4k.
660         m_sInput_buff_property.datasize = (m_sInput_buff_property.datasize + 4095)
661             & (~4095);
662 #endif
663         *buff_size = m_sInput_buff_property.datasize;
664     } else {
665         ioctl_msg.in = NULL;
666         ioctl_msg.out = (void*)&m_sOutput_buff_property;
667 
668         if (ioctl (m_nDriver_fd,VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) {
669             DEBUG_PRINT_ERROR("ERROR: Request for getting o/p buffer requirement failed");
670             return false;
671         }
672 
673         *min_buff_count = m_sOutput_buff_property.mincount;
674         *actual_buff_count = m_sOutput_buff_property.actualcount;
675         *buff_size = m_sOutput_buff_property.datasize;
676     }
677 
678     return true;
679 
680 }
681 
venc_set_param(void * paramData,OMX_INDEXTYPE index)682 bool venc_dev::venc_set_param(void *paramData,OMX_INDEXTYPE index )
683 {
684     venc_ioctl_msg ioctl_msg = {NULL,NULL};
685     DEBUG_PRINT_LOW("venc_set_param:: venc-720p");
686 
687     switch (index) {
688         case OMX_IndexParamPortDefinition:
689             {
690                 OMX_PARAM_PORTDEFINITIONTYPE *portDefn;
691                 portDefn = (OMX_PARAM_PORTDEFINITIONTYPE *) paramData;
692                 DEBUG_PRINT_HIGH("venc_set_param: OMX_IndexParamPortDefinition");
693 
694                 if (portDefn->nPortIndex == PORT_INDEX_IN) {
695 
696                     if (!venc_set_encode_framerate(portDefn->format.video.xFramerate, 0)) {
697                         return false;
698                     }
699 
700                     if (!venc_set_color_format(portDefn->format.video.eColorFormat)) {
701                         return false;
702                     }
703 
704                     DEBUG_PRINT_LOW("Basic parameter has changed");
705                     m_sVenc_cfg.input_height = portDefn->format.video.nFrameHeight;
706                     m_sVenc_cfg.input_width = portDefn->format.video.nFrameWidth;
707 
708                     ioctl_msg.in = (void*)&m_sVenc_cfg;
709                     ioctl_msg.out = NULL;
710 
711                     if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < 0) {
712                         DEBUG_PRINT_ERROR("ERROR: Request for setting base config failed");
713                         return false;
714                     }
715 
716                     DEBUG_PRINT_HIGH("WxH (%dx%d), codec (%d), fps(nr/dr) (%d/%d), bitrate (%d), "
717                             "color_format (%d)", m_sVenc_cfg.input_width, m_sVenc_cfg.input_height,
718                             m_sVenc_cfg.codectype, m_sVenc_cfg.fps_num, m_sVenc_cfg.fps_den,
719                             m_sVenc_cfg.targetbitrate, m_sVenc_cfg.inputformat);
720 
721                     DEBUG_PRINT_LOW("Updating the buffer count/size for the new resolution");
722                     ioctl_msg.in = NULL;
723                     ioctl_msg.out = (void*)&m_sInput_buff_property;
724 
725                     if (ioctl (m_nDriver_fd, VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) {
726                         DEBUG_PRINT_ERROR("ERROR: Request for getting i/p bufreq failed");
727                         return false;
728                     }
729 
730                     DEBUG_PRINT_HIGH("Got updated m_sInput_buff_property values: "
731                             "datasize = %u, maxcount = %u, actualcnt = %u, "
732                             "mincount = %u", m_sInput_buff_property.datasize,
733                             m_sInput_buff_property.maxcount, m_sInput_buff_property.actualcount,
734                             m_sInput_buff_property.mincount);
735 
736                     ioctl_msg.in = NULL;
737                     ioctl_msg.out = (void*)&m_sOutput_buff_property;
738 
739                     if (ioctl (m_nDriver_fd, VEN_IOCTL_GET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) {
740                         DEBUG_PRINT_ERROR("ERROR: Request for getting o/p bufreq failed");
741                         return false;
742                     }
743 
744                     DEBUG_PRINT_HIGH("Got updated m_sOutput_buff_property values: "
745                             "datasize = %u, maxcount = %u, actualcnt = %u, "
746                             "mincount = %u", m_sOutput_buff_property.datasize,
747                             m_sOutput_buff_property.maxcount, m_sOutput_buff_property.actualcount,
748                             m_sOutput_buff_property.mincount);
749                     ioctl_msg.in = (void*)&m_sOutput_buff_property;
750                     ioctl_msg.out = NULL;
751 
752                     if (ioctl (m_nDriver_fd, VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) {
753                         DEBUG_PRINT_ERROR("ERROR: Request for setting o/p bufreq failed");
754                         return false;
755                     }
756 
757                     if ((portDefn->nBufferCountActual >= m_sInput_buff_property.mincount) &&
758                             (portDefn->nBufferCountActual <= m_sInput_buff_property.maxcount)) {
759                         m_sInput_buff_property.actualcount = portDefn->nBufferCountActual;
760                         ioctl_msg.in = (void*)&m_sInput_buff_property;
761                         ioctl_msg.out = NULL;
762 
763                         if (ioctl(m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) {
764                             DEBUG_PRINT_ERROR("ERROR: Request for setting i/p buffer requirements failed");
765                             return false;
766                         }
767                     }
768 
769                     if (m_sInput_buff_property.datasize != portDefn->nBufferSize) {
770                         DEBUG_PRINT_ERROR("WARNING: Requested i/p bufsize[%u],"
771                                 "Driver's updated i/p bufsize = %u", portDefn->nBufferSize,
772                                 m_sInput_buff_property.datasize);
773                     }
774 
775                     m_level_set = false;
776 
777                     if (venc_set_profile_level(0, 0)) {
778                         DEBUG_PRINT_LOW("%s(): Profile/Level setting success", __func__);
779                     }
780                 } else if (portDefn->nPortIndex == PORT_INDEX_OUT) {
781                     if (!venc_set_target_bitrate(portDefn->format.video.nBitrate, 0)) {
782                         return false;
783                     }
784 
785                     if ( (portDefn->nBufferCountActual >= m_sOutput_buff_property.mincount)
786                             &&
787                             (m_sOutput_buff_property.maxcount >= portDefn->nBufferCountActual)
788                             &&
789                             (m_sOutput_buff_property.datasize == portDefn->nBufferSize)
790                        ) {
791                         m_sOutput_buff_property.actualcount = portDefn->nBufferCountActual;
792                         ioctl_msg.in = (void*)&m_sOutput_buff_property;
793                         ioctl_msg.out = NULL;
794 
795                         if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) {
796                             DEBUG_PRINT_ERROR("ERROR: ioctl VEN_IOCTL_SET_OUTPUT_BUFFER_REQ failed");
797                             return false;
798                         }
799                     } else {
800                         DEBUG_PRINT_ERROR("ERROR: Setting Output buffer requirements failed");
801                         return false;
802                     }
803                 } else {
804                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamPortDefinition");
805                 }
806 
807                 break;
808             }
809         case OMX_IndexParamVideoPortFormat:
810             {
811                 OMX_VIDEO_PARAM_PORTFORMATTYPE *portFmt;
812                 portFmt =(OMX_VIDEO_PARAM_PORTFORMATTYPE *)paramData;
813                 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoPortFormat");
814 
815                 if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_IN) {
816                     if (!venc_set_color_format(portFmt->eColorFormat)) {
817                         return false;
818                     }
819                 } else if (portFmt->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
820                     if (!venc_set_encode_framerate(portFmt->xFramerate, 0)) {
821                         return false;
822                     }
823                 } else {
824                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoPortFormat");
825                 }
826 
827                 break;
828             }
829         case OMX_IndexParamVideoBitrate:
830             {
831                 OMX_VIDEO_PARAM_BITRATETYPE* pParam;
832                 pParam = (OMX_VIDEO_PARAM_BITRATETYPE*)paramData;
833                 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoBitrate");
834 
835                 if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
836                     if (!venc_set_target_bitrate(pParam->nTargetBitrate, 0)) {
837                         DEBUG_PRINT_ERROR("ERROR: Target Bit Rate setting failed");
838                         return false;
839                     }
840 
841                     if (!venc_set_ratectrl_cfg(pParam->eControlRate)) {
842                         DEBUG_PRINT_ERROR("ERROR: Rate Control setting failed");
843                         return false;
844                     }
845                 } else {
846                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoBitrate");
847                 }
848 
849                 break;
850             }
851         case OMX_IndexParamVideoMpeg4:
852             {
853                 OMX_VIDEO_PARAM_MPEG4TYPE* pParam;
854                 OMX_U32 bFrames = 0;
855 
856                 pParam = (OMX_VIDEO_PARAM_MPEG4TYPE*)paramData;
857                 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoMpeg4");
858 
859                 if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
860                     if (!venc_set_voptiming_cfg(pParam->nTimeIncRes)) {
861                         DEBUG_PRINT_ERROR("ERROR: Request for setting vop_timing failed");
862                         return false;
863                     }
864 
865                     m_profile_set = false;
866                     m_level_set = false;
867 
868                     if (!venc_set_profile_level (pParam->eProfile, pParam->eLevel)) {
869                         DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile and level");
870                         return false;
871                     }
872 
873 #ifdef MAX_RES_1080P
874                     else {
875                         if (pParam->eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) {
876                             if (pParam->nBFrames) {
877                                 DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported");
878                                 bFrames = 1;
879                             }
880                         } else {
881                             if (pParam->nBFrames) {
882                                 DEBUG_PRINT_ERROR("Warning: B frames not supported");
883                                 bFrames = 0;
884                             }
885                         }
886                     }
887 
888 #endif
889 
890                     if (!venc_set_intra_period (pParam->nPFrames,bFrames)) {
891                         DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
892                         return false;
893                     }
894 
895                     if (!venc_set_multislice_cfg(OMX_IndexParamVideoMpeg4,pParam->nSliceHeaderSpacing)) {
896                         DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating slice_config");
897                         return false;
898                     }
899                 } else {
900                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoMpeg4");
901                 }
902 
903                 break;
904             }
905         case OMX_IndexParamVideoH263:
906             {
907                 OMX_VIDEO_PARAM_H263TYPE* pParam = (OMX_VIDEO_PARAM_H263TYPE*)paramData;
908                 DEBUG_PRINT_LOW("venc_set_param: OMX_IndexParamVideoH263");
909                 OMX_U32 bFrames = 0;
910 
911                 if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
912                     m_profile_set = false;
913                     m_level_set = false;
914 
915                     if (!venc_set_profile_level (pParam->eProfile, pParam->eLevel)) {
916                         DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile and level");
917                         return false;
918                     }
919 
920                     if (pParam->nBFrames)
921                         DEBUG_PRINT_ERROR("WARNING: B frame not supported for H.263");
922 
923                     if (venc_set_intra_period (pParam->nPFrames, bFrames) == false) {
924                         DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
925                         return false;
926                     }
927                 } else {
928                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoH263");
929                 }
930 
931                 break;
932             }
933         case OMX_IndexParamVideoAvc:
934             {
935                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoAvc");
936                 OMX_VIDEO_PARAM_AVCTYPE* pParam = (OMX_VIDEO_PARAM_AVCTYPE*)paramData;
937                 OMX_U32 bFrames = 0;
938 
939                 if (pParam->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
940                     DEBUG_PRINT_LOW("pParam->eProfile :%d ,pParam->eLevel %d",
941                             pParam->eProfile,pParam->eLevel);
942 
943                     m_profile_set = false;
944                     m_level_set = false;
945 
946                     if (!venc_set_profile_level (pParam->eProfile,pParam->eLevel)) {
947                         DEBUG_PRINT_ERROR("ERROR: Unsuccessful in updating Profile and level %d, %d",
948                                 pParam->eProfile, pParam->eLevel);
949                         return false;
950                     }
951 
952 #ifdef MAX_RES_1080P
953                     else {
954                         if (pParam->eProfile != OMX_VIDEO_AVCProfileBaseline) {
955                             if (pParam->nBFrames) {
956                                 DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported");
957                                 bFrames = 1;
958                             }
959                         } else {
960                             if (pParam->nBFrames) {
961                                 DEBUG_PRINT_ERROR("Warning: B frames not supported");
962                                 bFrames = 0;
963                             }
964                         }
965                     }
966 
967 #endif
968 
969                     if (!venc_set_intra_period (pParam->nPFrames, bFrames)) {
970                         DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
971                         return false;
972                     }
973 
974                     if (!venc_set_entropy_config (pParam->bEntropyCodingCABAC, pParam->nCabacInitIdc)) {
975                         DEBUG_PRINT_ERROR("ERROR: Request for setting Entropy failed");
976                         return false;
977                     }
978 
979                     if (!venc_set_inloop_filter (pParam->eLoopFilterMode)) {
980                         DEBUG_PRINT_ERROR("ERROR: Request for setting Inloop filter failed");
981                         return false;
982                     }
983 
984                     if (!venc_set_multislice_cfg(OMX_IndexParamVideoAvc, pParam->nSliceHeaderSpacing)) {
985                         DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating slice_config");
986                         return false;
987                     }
988                 } else {
989                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoAvc");
990                 }
991 
992                 //TBD, lot of other variables to be updated, yet to decide
993                 break;
994             }
995         case OMX_IndexParamVideoIntraRefresh:
996             {
997                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoIntraRefresh");
998                 OMX_VIDEO_PARAM_INTRAREFRESHTYPE *intra_refresh =
999                     (OMX_VIDEO_PARAM_INTRAREFRESHTYPE *)paramData;
1000 
1001                 if (intra_refresh->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
1002                     if (venc_set_intra_refresh(intra_refresh->eRefreshMode, intra_refresh->nCirMBs) == false) {
1003                         DEBUG_PRINT_ERROR("ERROR: Setting Intra refresh failed");
1004                         return false;
1005                     }
1006                 } else {
1007                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoIntraRefresh");
1008                 }
1009 
1010                 break;
1011             }
1012         case OMX_IndexParamVideoErrorCorrection:
1013             {
1014                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoErrorCorrection");
1015                 OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *error_resilience =
1016                     (OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE *)paramData;
1017 
1018                 if (error_resilience->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
1019                     if (venc_set_error_resilience(error_resilience) == false) {
1020                         DEBUG_PRINT_ERROR("ERROR: Setting Intra refresh failed");
1021                         return false;
1022                     }
1023                 } else {
1024                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoErrorCorrection");
1025                 }
1026 
1027                 break;
1028             }
1029         case OMX_IndexParamVideoProfileLevelCurrent:
1030             {
1031                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoProfileLevelCurrent");
1032                 OMX_VIDEO_PARAM_PROFILELEVELTYPE *profile_level =
1033                     (OMX_VIDEO_PARAM_PROFILELEVELTYPE *)paramData;
1034 
1035                 if (profile_level->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
1036                     m_profile_set = false;
1037                     m_level_set = false;
1038 
1039                     if (!venc_set_profile_level (profile_level->eProfile,
1040                                 profile_level->eLevel)) {
1041                         DEBUG_PRINT_ERROR("WARNING: Unsuccessful in updating Profile and level");
1042                         return false;
1043                     }
1044                 } else {
1045                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoProfileLevelCurrent");
1046                 }
1047 
1048                 break;
1049             }
1050         case OMX_IndexParamVideoQuantization:
1051             {
1052                 DEBUG_PRINT_LOW("venc_set_param:OMX_IndexParamVideoQuantization");
1053                 OMX_VIDEO_PARAM_QUANTIZATIONTYPE *session_qp =
1054                     (OMX_VIDEO_PARAM_QUANTIZATIONTYPE *)paramData;
1055 
1056                 if (session_qp->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
1057                     if (venc_set_session_qp (session_qp->nQpI,
1058                                 session_qp->nQpP) == false) {
1059                         DEBUG_PRINT_ERROR("ERROR: Setting Session QP failed");
1060                         return false;
1061                     }
1062                 } else {
1063                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexParamVideoQuantization");
1064                 }
1065 
1066                 break;
1067             }
1068 
1069         case OMX_QcomIndexParamVideoQPRange:
1070             {
1071                 DEBUG_PRINT_LOW("venc_set_param:OMX_QcomIndexParamVideoQPRange");
1072                 OMX_QCOM_VIDEO_PARAM_QPRANGETYPE *qp_range =
1073                     (OMX_QCOM_VIDEO_PARAM_QPRANGETYPE *)paramData;
1074 
1075                 if (qp_range->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
1076                     if (venc_set_qp_range (qp_range->minQP,
1077                                 qp_range->maxQP) == false) {
1078                         DEBUG_PRINT_ERROR("ERROR: Setting QP Range failed");
1079                         return false;
1080                     }
1081                 } else {
1082                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_QcomIndexParamVideoQPRange");
1083                 }
1084 
1085                 break;
1086             }
1087 
1088         case OMX_ExtraDataVideoEncoderSliceInfo:
1089             {
1090                 DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataVideoEncoderSliceInfo");
1091                 OMX_U32 extra_data = *(OMX_U32 *)paramData;
1092 
1093                 if (venc_set_extradata(extra_data) == false) {
1094                     DEBUG_PRINT_ERROR("ERROR: Setting "
1095                             "OMX_ExtraDataVideoEncoderSliceInfo failed");
1096                     return false;
1097                 }
1098 
1099                 break;
1100             }
1101         case OMX_ExtraDataVideoLTRInfo:
1102             {
1103                 DEBUG_PRINT_LOW("venc_set_param: OMX_ExtraDataVideoLTRInfo");
1104                 OMX_U32 extra_data = *(OMX_U32 *)paramData;
1105 
1106                 if (venc_set_extradata(extra_data) == false) {
1107                     DEBUG_PRINT_ERROR("ERROR: Setting "
1108                             "OMX_ExtraDataVideoLTRInfo failed");
1109                     return false;
1110                 }
1111 
1112                 break;
1113             }
1114         case OMX_QcomIndexEnableSliceDeliveryMode:
1115             {
1116                 QOMX_EXTNINDEX_PARAMTYPE* pParam =
1117                     (QOMX_EXTNINDEX_PARAMTYPE*)paramData;
1118 
1119                 if (pParam->nPortIndex == PORT_INDEX_OUT) {
1120                     if (venc_set_slice_delivery_mode(pParam->bEnable) == false) {
1121                         DEBUG_PRINT_ERROR("Setting slice delivery mode failed");
1122                         return OMX_ErrorUnsupportedSetting;
1123                     }
1124                 } else {
1125                     DEBUG_PRINT_ERROR("OMX_QcomIndexEnableSliceDeliveryMode "
1126                             "called on wrong port(%d)", pParam->nPortIndex);
1127                     return OMX_ErrorBadPortIndex;
1128                 }
1129 
1130                 break;
1131             }
1132         case OMX_QcomIndexEnableH263PlusPType:
1133             {
1134                 QOMX_EXTNINDEX_PARAMTYPE* pParam =
1135                     (QOMX_EXTNINDEX_PARAMTYPE*)paramData;
1136                 DEBUG_PRINT_LOW("OMX_QcomIndexEnableH263PlusPType");
1137 
1138                 if (pParam->nPortIndex == PORT_INDEX_OUT) {
1139                     if (venc_set_plusptype(pParam->bEnable) == false) {
1140                         DEBUG_PRINT_ERROR("Setting PlusPType failed for H263");
1141                         return OMX_ErrorUnsupportedSetting;
1142                     }
1143                 } else {
1144                     DEBUG_PRINT_ERROR("OMX_QcomIndexEnableH263PlusPType "
1145                             "called on wrong port(%d)", pParam->nPortIndex);
1146                     return OMX_ErrorBadPortIndex;
1147                 }
1148 
1149                 break;
1150             }
1151         case QOMX_IndexParamVideoLTRMode:
1152             {
1153                 QOMX_VIDEO_PARAM_LTRMODE_TYPE* pParam =
1154                     (QOMX_VIDEO_PARAM_LTRMODE_TYPE*)paramData;
1155 
1156                 if (pParam->nPortIndex == PORT_INDEX_OUT) {
1157                     if (!venc_set_ltrmode(pParam->eLTRMode)) {
1158                         DEBUG_PRINT_ERROR("Setting ltr mode failed");
1159                         return OMX_ErrorUnsupportedSetting;
1160                     }
1161                 } else {
1162                     DEBUG_PRINT_ERROR("QOMX_IndexParamVideoLTRMode "
1163                             "called on wrong port(%d)", pParam->nPortIndex);
1164                     return OMX_ErrorBadPortIndex;
1165                 }
1166 
1167                 break;
1168             }
1169         case QOMX_IndexParamVideoLTRCount:
1170             {
1171                 QOMX_VIDEO_PARAM_LTRCOUNT_TYPE* pParam =
1172                     (QOMX_VIDEO_PARAM_LTRCOUNT_TYPE*)paramData;
1173 
1174                 if (pParam->nPortIndex == PORT_INDEX_OUT) {
1175                     if (!venc_set_ltrcount(pParam->nCount)) {
1176                         DEBUG_PRINT_ERROR("Setting ltr count failed");
1177                         return OMX_ErrorUnsupportedSetting;
1178                     }
1179                 } else {
1180                     DEBUG_PRINT_ERROR("QOMX_IndexParamVideoLTRCount "
1181                             "called on wrong port(%d)", pParam->nPortIndex);
1182                     return OMX_ErrorBadPortIndex;
1183                 }
1184 
1185                 break;
1186             }
1187         case OMX_IndexParamVideoSliceFMO:
1188         default:
1189             DEBUG_PRINT_ERROR("venc_set_param: Unsupported index 0x%x", index);
1190             break;
1191     }
1192 
1193     return true;
1194 }
1195 
venc_set_config(void * configData,OMX_INDEXTYPE index)1196 bool venc_dev::venc_set_config(void *configData, OMX_INDEXTYPE index)
1197 {
1198     venc_ioctl_msg ioctl_msg = {NULL,NULL};
1199     DEBUG_PRINT_LOW("Inside venc_set_config");
1200 
1201     switch (index) {
1202         case OMX_IndexConfigVideoBitrate:
1203             {
1204                 OMX_VIDEO_CONFIG_BITRATETYPE *bit_rate = (OMX_VIDEO_CONFIG_BITRATETYPE *)
1205                     configData;
1206 
1207                 if (m_max_allowed_bitrate_check &&
1208                         !venc_max_allowed_bitrate_check(bit_rate->nEncodeBitrate)) {
1209                     DEBUG_PRINT_ERROR("Max Allowed Bitrate Check failed");
1210                     return false;
1211                 }
1212 
1213                 DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoBitrate");
1214 
1215                 if (bit_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
1216                     if (venc_set_target_bitrate(bit_rate->nEncodeBitrate, 1) == false) {
1217                         DEBUG_PRINT_ERROR("ERROR: Setting Target Bit rate failed");
1218                         return false;
1219                     }
1220                 } else {
1221                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoBitrate");
1222                 }
1223 
1224                 break;
1225             }
1226         case OMX_IndexConfigVideoFramerate:
1227             {
1228                 OMX_CONFIG_FRAMERATETYPE *frame_rate = (OMX_CONFIG_FRAMERATETYPE *)
1229                     configData;
1230                 DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoFramerate");
1231 
1232                 if (frame_rate->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
1233                     if (venc_set_encode_framerate(frame_rate->xEncodeFramerate, 1) == false) {
1234                         DEBUG_PRINT_ERROR("ERROR: Setting Encode Framerate failed");
1235                         return false;
1236                     }
1237                 } else {
1238                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate");
1239                 }
1240 
1241                 break;
1242             }
1243         case QOMX_IndexConfigVideoIntraperiod:
1244             {
1245                 DEBUG_PRINT_LOW("venc_set_param:QOMX_IndexConfigVideoIntraperiod");
1246                 QOMX_VIDEO_INTRAPERIODTYPE *intraperiod =
1247                     (QOMX_VIDEO_INTRAPERIODTYPE *)configData;
1248 
1249                 if (intraperiod->nPortIndex == (OMX_U32) PORT_INDEX_OUT) {
1250                     if (venc_set_intra_period(intraperiod->nPFrames, intraperiod->nBFrames) == false) {
1251                         DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
1252                         return false;
1253                     }
1254                 }
1255 
1256                 break;
1257             }
1258         case OMX_IndexConfigVideoIntraVOPRefresh:
1259             {
1260                 OMX_CONFIG_INTRAREFRESHVOPTYPE *intra_vop_refresh = (OMX_CONFIG_INTRAREFRESHVOPTYPE *)
1261                     configData;
1262                 DEBUG_PRINT_LOW("venc_set_config: OMX_IndexConfigVideoIntraVOPRefresh");
1263 
1264                 if (intra_vop_refresh->nPortIndex == (OMX_U32)PORT_INDEX_OUT) {
1265                     if (venc_set_intra_vop_refresh(intra_vop_refresh->IntraRefreshVOP) == false) {
1266                         DEBUG_PRINT_ERROR("ERROR: Setting Encode Framerate failed");
1267                         return false;
1268                     }
1269                 } else {
1270                     DEBUG_PRINT_ERROR("ERROR: Invalid Port Index for OMX_IndexConfigVideoFramerate");
1271                 }
1272 
1273                 break;
1274             }
1275         case OMX_IndexConfigCommonRotate:
1276             {
1277                 OMX_CONFIG_ROTATIONTYPE *config_rotation =
1278                     reinterpret_cast<OMX_CONFIG_ROTATIONTYPE*>(configData);
1279                 venc_ioctl_msg ioctl_msg = {NULL,NULL};
1280                 OMX_U32 nFrameWidth;
1281 
1282                 DEBUG_PRINT_HIGH("venc_set_config: updating the new Dims");
1283                 nFrameWidth = m_sVenc_cfg.input_width;
1284                 m_sVenc_cfg.input_width  = m_sVenc_cfg.input_height;
1285                 m_sVenc_cfg.input_height = nFrameWidth;
1286                 ioctl_msg.in = (void*)&m_sVenc_cfg;
1287                 ioctl_msg.out = NULL;
1288 
1289                 if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_BASE_CFG,(void*)&ioctl_msg) < 0) {
1290                     DEBUG_PRINT_ERROR("ERROR: Dimension Change for Rotation failed");
1291                     return false;
1292                 }
1293 
1294                 break;
1295             }
1296         case QOMX_IndexConfigVideoLTRPeriod:
1297             {
1298                 QOMX_VIDEO_CONFIG_LTRPERIOD_TYPE* pParam =
1299                     (QOMX_VIDEO_CONFIG_LTRPERIOD_TYPE*)configData;
1300 
1301                 if (pParam->nPortIndex == PORT_INDEX_OUT) {
1302                     if (!venc_set_ltrperiod(pParam->nFrames)) {
1303                         DEBUG_PRINT_ERROR("Setting ltr period failed");
1304                         return OMX_ErrorUnsupportedSetting;
1305                     }
1306                 } else {
1307                     DEBUG_PRINT_ERROR("QOMX_IndexConfigVideoLTRPeriod "
1308                             "called on wrong port(%d)", pParam->nPortIndex);
1309                     return OMX_ErrorBadPortIndex;
1310                 }
1311 
1312                 break;
1313             }
1314         case QOMX_IndexConfigVideoLTRUse:
1315             {
1316                 QOMX_VIDEO_CONFIG_LTRUSE_TYPE* pParam =
1317                     (QOMX_VIDEO_CONFIG_LTRUSE_TYPE*)configData;
1318 
1319                 if (pParam->nPortIndex == PORT_INDEX_OUT) {
1320                     if (!venc_set_ltruse(pParam->nID, pParam->nFrames)) {
1321                         DEBUG_PRINT_ERROR("Setting ltr use failed");
1322                         return OMX_ErrorUnsupportedSetting;
1323                     }
1324                 } else {
1325                     DEBUG_PRINT_ERROR("QOMX_IndexConfigVideoLTRUse "
1326                             "called on wrong port(%d)", pParam->nPortIndex);
1327                     return OMX_ErrorBadPortIndex;
1328                 }
1329 
1330                 break;
1331             }
1332         default:
1333             DEBUG_PRINT_ERROR("venc_set_config: Unsupported index = 0x%x", index);
1334             break;
1335     }
1336 
1337     return true;
1338 }
1339 
venc_stop(void)1340 unsigned venc_dev::venc_stop( void)
1341 {
1342 #ifdef MAX_RES_1080P
1343     pmem_free();
1344 #endif
1345     return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_STOP,NULL);
1346 }
1347 
venc_pause(void)1348 unsigned venc_dev::venc_pause(void)
1349 {
1350     return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_PAUSE,NULL);
1351 }
1352 
venc_resume(void)1353 unsigned venc_dev::venc_resume(void)
1354 {
1355     return ioctl(m_nDriver_fd,VEN_IOCTL_CMD_RESUME,NULL) ;
1356 }
1357 
venc_start_done(void)1358 unsigned venc_dev::venc_start_done(void)
1359 {
1360     return 0;
1361 }
1362 
venc_set_message_thread_id(pthread_t)1363 unsigned venc_dev::venc_set_message_thread_id(pthread_t)
1364 {
1365     return 0;
1366 }
1367 
venc_start(void)1368 unsigned venc_dev::venc_start(void)
1369 {
1370     DEBUG_PRINT_HIGH("%s(): Check Profile/Level set in driver before start",
1371             __func__);
1372 
1373     if (!venc_set_profile_level(0, 0)) {
1374         DEBUG_PRINT_ERROR("ERROR: %s(): Driver Profile/Level is NOT SET",
1375                 __func__);
1376     } else {
1377         DEBUG_PRINT_HIGH("%s(): Driver Profile[%lu]/Level[%lu] successfully SET",
1378                 __func__, codec_profile.profile, profile_level.level);
1379     }
1380 
1381     if (m_max_allowed_bitrate_check &&
1382             !venc_max_allowed_bitrate_check(bitrate.target_bitrate)) {
1383         DEBUG_PRINT_ERROR("Maximum Allowed Bitrate Check failed");
1384         return -1;
1385     }
1386 
1387     venc_config_print();
1388 
1389 #ifdef MAX_RES_1080P
1390 
1391     if ((codec_profile.profile == VEN_PROFILE_MPEG4_SP) ||
1392             (codec_profile.profile == VEN_PROFILE_H264_BASELINE) ||
1393             (codec_profile.profile == VEN_PROFILE_H263_BASELINE))
1394         recon_buffers_count = MAX_RECON_BUFFERS - 2;
1395     else
1396         recon_buffers_count = MAX_RECON_BUFFERS;
1397 
1398     if (ltrmode.ltr_mode == (unsigned long)QOMX_VIDEO_LTRMode_Auto) {
1399         recon_buffers_count = MAX_RECON_BUFFERS;
1400         DEBUG_PRINT_HIGH("ltr mode enabled, so set recon buffers "
1401                 "count to %d", recon_buffers_count);
1402     }
1403 
1404     if (!venc_allocate_recon_buffers())
1405         return ioctl(m_nDriver_fd, VEN_IOCTL_CMD_START, NULL);
1406     else {
1407         DEBUG_PRINT_ERROR("Failed in creating Recon buffers");
1408         return -1;
1409     }
1410 
1411 #else
1412     return ioctl(m_nDriver_fd, VEN_IOCTL_CMD_START, NULL);
1413 #endif
1414 }
1415 
1416 #ifdef MAX_RES_1080P
venc_allocate_recon_buffers()1417 OMX_U32 venc_dev::venc_allocate_recon_buffers()
1418 {
1419     OMX_U32 yuv_size;
1420     struct venc_ioctl_msg ioctl_msg;
1421     struct venc_recon_buff_size recon_buff_size;
1422 
1423     recon_buff_size.width =  ((m_sVenc_cfg.input_width + 15) / 16) * 16;
1424     recon_buff_size.height = ((m_sVenc_cfg.input_height + 15) / 16 ) * 16;
1425 
1426     DEBUG_PRINT_LOW("Width %d, Height %d, w_round %d, h_round %d", m_sVenc_cfg.input_width,
1427             m_sVenc_cfg.input_height, recon_buff_size.width, recon_buff_size.height);
1428 
1429     ioctl_msg.in = NULL;
1430     ioctl_msg.out = (void*)&recon_buff_size;
1431 
1432     if (ioctl (m_nDriver_fd,VEN_IOCTL_GET_RECON_BUFFER_SIZE, (void*)&ioctl_msg) < 0) {
1433         DEBUG_PRINT_ERROR("VEN_IOCTL_GET_RECON_BUFFER_SIZE Failed for width: %d, Height %d" ,
1434                 recon_buff_size.width, recon_buff_size.height);
1435         return OMX_ErrorInsufficientResources;
1436     }
1437 
1438     DEBUG_PRINT_HIGH("Width %d, Height %d, w_round %d, h_round %d, yuv_size %d alignment %d count %d",
1439             m_sVenc_cfg.input_width, m_sVenc_cfg.input_height, recon_buff_size.width,
1440             recon_buff_size.height, recon_buff_size.size, recon_buff_size.alignment,
1441             recon_buffers_count);
1442 
1443     for (int i = 0; i < recon_buffers_count; i++) {
1444         if (pmem_allocate(recon_buff_size.size, recon_buff_size.alignment,i)) {
1445             DEBUG_PRINT_ERROR("Error returned in allocating recon buffers");
1446             return -1;
1447         }
1448     }
1449 
1450     return 0;
1451 }
pmem_allocate(OMX_U32 size,OMX_U32 alignment,OMX_U32 count)1452 OMX_U32 venc_dev::pmem_allocate(OMX_U32 size, OMX_U32 alignment, OMX_U32 count)
1453 {
1454     OMX_U32 pmem_fd = -1;
1455     OMX_U32 width, height;
1456     void *buf_addr = NULL;
1457     struct venc_ioctl_msg ioctl_msg;
1458     struct venc_recon_addr recon_addr;
1459     int rc = 0;
1460 
1461 #ifdef USE_ION
1462     recon_buff[count].ion_device_fd = open (MEM_DEVICE,O_RDONLY);
1463 
1464     if (recon_buff[count].ion_device_fd < 0) {
1465         DEBUG_PRINT_ERROR("ERROR: ION Device open() Failed");
1466         return -1;
1467     }
1468 
1469     recon_buff[count].alloc_data.len = size;
1470 #ifdef MAX_RES_720P
1471     recon_buff[count].alloc_data.heap_id_mask = ION_HEAP(MEM_HEAP_ID);
1472 #else
1473     recon_buff[count].alloc_data.heap_id_mask = (ION_HEAP(MEM_HEAP_ID) |
1474             ION_HEAP(ION_IOMMU_HEAP_ID));
1475 #endif
1476     recon_buff[count].alloc_data.flags = ION_FLAG_CACHED;
1477     recon_buff[count].alloc_data.align = clip2(alignment);
1478 
1479     if (recon_buff[count].alloc_data.align != 8192)
1480         recon_buff[count].alloc_data.align = 8192;
1481 
1482     rc = ioctl(recon_buff[count].ion_device_fd,ION_IOC_ALLOC,&recon_buff[count].alloc_data);
1483 
1484     if (rc || !recon_buff[count].alloc_data.handle) {
1485         DEBUG_PRINT_ERROR("ION ALLOC memory failed ");
1486         recon_buff[count].alloc_data.handle=NULL;
1487         return -1;
1488     }
1489 
1490     recon_buff[count].ion_alloc_fd.handle = recon_buff[count].alloc_data.handle;
1491     rc = ioctl(recon_buff[count].ion_device_fd,ION_IOC_MAP,&recon_buff[count].ion_alloc_fd);
1492 
1493     if (rc) {
1494         DEBUG_PRINT_ERROR("ION MAP failed ");
1495         recon_buff[count].ion_alloc_fd.fd =-1;
1496         recon_buff[count].ion_alloc_fd.fd =-1;
1497         return -1;
1498     }
1499 
1500     pmem_fd = recon_buff[count].ion_alloc_fd.fd;
1501 #else
1502     struct pmem_allocation allocation;
1503     pmem_fd = open(MEM_DEVICE, O_RDWR);
1504 
1505     if ((int)(pmem_fd) < 0) {
1506         DEBUG_PRINT_ERROR("Failed to get an pmem handle");
1507         return -1;
1508     }
1509 
1510     allocation.size = size;
1511     allocation.align = clip2(alignment);
1512 
1513     if (allocation.align != 8192)
1514         allocation.align = 8192;
1515 
1516     if (ioctl(pmem_fd, PMEM_ALLOCATE_ALIGNED, &allocation) < 0) {
1517         DEBUG_PRINT_ERROR("Aligment(%u) failed with pmem driver Sz(%lu)",
1518                 allocation.align, allocation.size);
1519         return -1;
1520     }
1521 
1522 #endif
1523     buf_addr = mmap(NULL, size,
1524             PROT_READ | PROT_WRITE,
1525             MAP_SHARED, pmem_fd, 0);
1526 
1527     if (buf_addr == (void*) MAP_FAILED) {
1528         close(pmem_fd);
1529         pmem_fd = -1;
1530         DEBUG_PRINT_ERROR("Error returned in allocating recon buffers buf_addr: %p",buf_addr);
1531 #ifdef USE_ION
1532 
1533         if (ioctl(recon_buff[count].ion_device_fd,ION_IOC_FREE,
1534                     &recon_buff[count].alloc_data.handle)) {
1535             DEBUG_PRINT_LOW("ion recon buffer free failed");
1536         }
1537 
1538         recon_buff[count].alloc_data.handle = NULL;
1539         recon_buff[count].ion_alloc_fd.fd =-1;
1540         close(recon_buff[count].ion_device_fd);
1541         recon_buff[count].ion_device_fd =-1;
1542 #endif
1543         return -1;
1544     }
1545 
1546     DEBUG_PRINT_HIGH("Allocated virt:%p, FD: %d of size %d", buf_addr, pmem_fd, size);
1547 
1548     recon_addr.buffer_size = size;
1549     recon_addr.pmem_fd = pmem_fd;
1550     recon_addr.offset = 0;
1551     recon_addr.pbuffer = (unsigned char *)buf_addr;
1552 
1553     ioctl_msg.in = (void*)&recon_addr;
1554     ioctl_msg.out = NULL;
1555 
1556     if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_RECON_BUFFER, (void*)&ioctl_msg) < 0) {
1557         DEBUG_PRINT_ERROR("Failed to set the Recon_buffers");
1558         return -1;
1559     }
1560 
1561     recon_buff[count].virtual_address = (unsigned char *) buf_addr;
1562     recon_buff[count].size = size;
1563     recon_buff[count].offset = 0;
1564     recon_buff[count].pmem_fd = pmem_fd;
1565 
1566     DEBUG_PRINT_ERROR("Allocated virt:%p, FD: %d of size %d at index: %d", recon_buff[count].virtual_address,
1567             recon_buff[count].pmem_fd, recon_buff[count].size, count);
1568     return 0;
1569 }
1570 
pmem_free()1571 OMX_U32 venc_dev::pmem_free()
1572 {
1573     int cnt = 0;
1574     struct venc_ioctl_msg ioctl_msg;
1575     struct venc_recon_addr recon_addr;
1576 
1577     for (cnt = 0; cnt < recon_buffers_count; cnt++) {
1578         if (recon_buff[cnt].pmem_fd) {
1579             recon_addr.pbuffer = recon_buff[cnt].virtual_address;
1580             recon_addr.offset = recon_buff[cnt].offset;
1581             recon_addr.pmem_fd = recon_buff[cnt].pmem_fd;
1582             recon_addr.buffer_size = recon_buff[cnt].size;
1583             ioctl_msg.in = (void*)&recon_addr;
1584             ioctl_msg.out = NULL;
1585 
1586             if (ioctl(m_nDriver_fd, VEN_IOCTL_FREE_RECON_BUFFER ,&ioctl_msg) < 0)
1587                 DEBUG_PRINT_ERROR("VEN_IOCTL_FREE_RECON_BUFFER failed");
1588 
1589             munmap(recon_buff[cnt].virtual_address, recon_buff[cnt].size);
1590             close(recon_buff[cnt].pmem_fd);
1591 #ifdef USE_ION
1592 
1593             if (ioctl(recon_buff[cnt].ion_device_fd,ION_IOC_FREE,
1594                         &recon_buff[cnt].alloc_data.handle)) {
1595                 DEBUG_PRINT_LOW("ion recon buffer free failed");
1596             }
1597 
1598             recon_buff[cnt].alloc_data.handle = NULL;
1599             recon_buff[cnt].ion_alloc_fd.fd =-1;
1600             close(recon_buff[cnt].ion_device_fd);
1601             recon_buff[cnt].ion_device_fd =-1;
1602 #endif
1603             DEBUG_PRINT_LOW("cleaning Index %d of size %d",cnt,recon_buff[cnt].size);
1604             recon_buff[cnt].pmem_fd = -1;
1605             recon_buff[cnt].virtual_address = NULL;
1606             recon_buff[cnt].offset = 0;
1607             recon_buff[cnt].alignment = 0;
1608             recon_buff[cnt].size = 0;
1609         }
1610     }
1611 
1612     return 0;
1613 }
1614 #endif
1615 
venc_config_print()1616 void venc_dev::venc_config_print()
1617 {
1618 
1619     DEBUG_PRINT_HIGH("ENC_CONFIG: Codec: %d, Profile %d, level : %d",
1620             m_sVenc_cfg.codectype, codec_profile.profile, profile_level.level);
1621 
1622     DEBUG_PRINT_HIGH("ENC_CONFIG: Width: %d, Height:%d, Fps: %d",
1623             m_sVenc_cfg.input_width, m_sVenc_cfg.input_height,
1624             m_sVenc_cfg.fps_num/m_sVenc_cfg.fps_den);
1625 
1626     DEBUG_PRINT_HIGH("ENC_CONFIG: Bitrate: %d, RC: %d, I-Period: %d",
1627             bitrate.target_bitrate, rate_ctrl.rcmode, intra_period.num_pframes);
1628 
1629     DEBUG_PRINT_HIGH("ENC_CONFIG: qpI: %d, qpP: %d, qpb: 0",
1630             session_qp.iframeqp, session_qp.pframqp);
1631 
1632     DEBUG_PRINT_HIGH("ENC_CONFIG: minQP: %d, maxQP: %d",
1633             qp_range.minqp, qp_range.maxqp);
1634 
1635     DEBUG_PRINT_HIGH("ENC_CONFIG: VOP_Resolution: %d, Slice-Mode: %d, Slize_Size: %d",
1636             voptimecfg.voptime_resolution, multislice.mslice_mode,
1637             multislice.mslice_size);
1638 
1639     DEBUG_PRINT_HIGH("ENC_CONFIG: EntropyMode: %d, CabacModel: %d",
1640             entropy.longentropysel, entropy.cabacmodel);
1641 
1642     DEBUG_PRINT_HIGH("ENC_CONFIG: DB-Mode: %d, alpha: %d, Beta: %d",
1643             dbkfilter.db_mode, dbkfilter.slicealpha_offset,
1644             dbkfilter.slicebeta_offset);
1645 
1646     DEBUG_PRINT_HIGH("ENC_CONFIG: IntraMB/Frame: %d, HEC: %d",
1647             intra_refresh.mbcount, hec.header_extension);
1648 }
1649 
venc_flush(unsigned port)1650 unsigned venc_dev::venc_flush( unsigned port)
1651 {
1652     struct venc_ioctl_msg ioctl_msg;
1653     struct venc_bufferflush buffer_index;
1654 
1655     if (port == PORT_INDEX_IN) {
1656         DEBUG_PRINT_HIGH("Calling Input Flush");
1657         buffer_index.flush_mode = VEN_FLUSH_INPUT;
1658         ioctl_msg.in = (void*)&buffer_index;
1659         ioctl_msg.out = NULL;
1660 
1661         return ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FLUSH,(void*)&ioctl_msg);
1662     } else if (port == PORT_INDEX_OUT) {
1663         DEBUG_PRINT_HIGH("Calling Output Flush");
1664         buffer_index.flush_mode = VEN_FLUSH_OUTPUT;
1665         ioctl_msg.in = (void*)&buffer_index;
1666         ioctl_msg.out = NULL;
1667         return ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FLUSH,(void*)&ioctl_msg);
1668     } else {
1669         return -1;
1670     }
1671 }
1672 
1673 //allocating I/P memory from pmem and register with the device
1674 
1675 
venc_use_buf(void * buf_addr,unsigned port,unsigned)1676 bool venc_dev::venc_use_buf(void *buf_addr, unsigned port,unsigned)
1677 {
1678     struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
1679     struct pmem *pmem_tmp;
1680     struct venc_bufferpayload dev_buffer = {0};
1681     struct venc_allocatorproperty buff_alloc_property = {0};
1682 
1683     pmem_tmp = (struct pmem *)buf_addr;
1684 
1685     DEBUG_PRINT_LOW("venc_use_buf:: pmem_tmp = %p", pmem_tmp);
1686 
1687     if (port == PORT_INDEX_IN) {
1688         dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
1689         dev_buffer.fd  = pmem_tmp->fd;
1690         dev_buffer.maped_size = pmem_tmp->size;
1691         dev_buffer.sz = pmem_tmp->size;
1692         dev_buffer.offset = pmem_tmp->offset;
1693 
1694         if ((m_sVenc_cfg.input_height %16 !=0) || (m_sVenc_cfg.input_width%16 != 0)) {
1695             unsigned long ht = m_sVenc_cfg.input_height;
1696             unsigned long wd = m_sVenc_cfg.input_width;
1697             unsigned int luma_size, luma_size_2k;
1698 
1699             ht = (ht + 15) & ~15;
1700             wd = (wd + 15) & ~15;
1701 
1702             luma_size = ht * wd;
1703             luma_size_2k = (luma_size + 2047) & ~2047;
1704 
1705             dev_buffer.sz = luma_size_2k + ((luma_size/2 + 2047) & ~2047);
1706 #ifdef USE_ION
1707             ioctl_msg.in = NULL;
1708             ioctl_msg.out = (void*)&buff_alloc_property;
1709 
1710             if (ioctl (m_nDriver_fd,VEN_IOCTL_GET_INPUT_BUFFER_REQ,(void*)&ioctl_msg) < 0) {
1711                 DEBUG_PRINT_ERROR("ERROR: venc_use_buf:get input buffer failed ");
1712                 return false;
1713             }
1714 
1715             if (buff_alloc_property.alignment < 4096) {
1716                 dev_buffer.sz = ((dev_buffer.sz + 4095) & ~4095);
1717             } else {
1718                 dev_buffer.sz = ((dev_buffer.sz + (buff_alloc_property.alignment - 1)) &
1719                         ~(buff_alloc_property.alignment - 1));
1720             }
1721 
1722 #endif
1723             dev_buffer.maped_size = dev_buffer.sz;
1724         }
1725 
1726         ioctl_msg.in  = (void*)&dev_buffer;
1727         ioctl_msg.out = NULL;
1728 
1729         DEBUG_PRINT_LOW("venc_use_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \
1730                 dev_buffer.pbuffer, \
1731                 dev_buffer.fd, \
1732                 dev_buffer.offset, \
1733                 dev_buffer.maped_size);
1734 
1735         if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_INPUT_BUFFER,&ioctl_msg) < 0) {
1736             DEBUG_PRINT_ERROR("ERROR: venc_use_buf:set input buffer failed ");
1737             return false;
1738         }
1739     } else if (port == PORT_INDEX_OUT) {
1740         dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
1741         dev_buffer.fd  = pmem_tmp->fd;
1742         dev_buffer.sz = pmem_tmp->size;
1743         dev_buffer.maped_size = pmem_tmp->size;
1744         dev_buffer.offset = pmem_tmp->offset;
1745         ioctl_msg.in  = (void*)&dev_buffer;
1746         ioctl_msg.out = NULL;
1747 
1748         DEBUG_PRINT_LOW("venc_use_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \
1749                 dev_buffer.pbuffer, \
1750                 dev_buffer.fd, \
1751                 dev_buffer.offset, \
1752                 dev_buffer.maped_size);
1753 
1754         if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_OUTPUT_BUFFER,&ioctl_msg) < 0) {
1755             DEBUG_PRINT_ERROR("ERROR: venc_use_buf:set output buffer failed ");
1756             return false;
1757         }
1758     } else {
1759         DEBUG_PRINT_ERROR("ERROR: venc_use_buf:Invalid Port Index ");
1760         return false;
1761     }
1762 
1763     return true;
1764 }
1765 
venc_free_buf(void * buf_addr,unsigned port)1766 bool venc_dev::venc_free_buf(void *buf_addr, unsigned port)
1767 {
1768     struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
1769     struct pmem *pmem_tmp;
1770     struct venc_bufferpayload dev_buffer = {0};
1771 
1772     pmem_tmp = (struct pmem *)buf_addr;
1773 
1774     DEBUG_PRINT_LOW("venc_use_buf:: pmem_tmp = %p", pmem_tmp);
1775 
1776     if (port == PORT_INDEX_IN) {
1777         dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
1778         dev_buffer.fd  = pmem_tmp->fd;
1779         dev_buffer.maped_size = pmem_tmp->size;
1780         dev_buffer.sz = pmem_tmp->size;
1781         dev_buffer.offset = pmem_tmp->offset;
1782         ioctl_msg.in  = (void*)&dev_buffer;
1783         ioctl_msg.out = NULL;
1784 
1785         DEBUG_PRINT_LOW("venc_free_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \
1786                 dev_buffer.pbuffer, \
1787                 dev_buffer.fd, \
1788                 dev_buffer.offset, \
1789                 dev_buffer.maped_size);
1790 
1791         if (ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FREE_INPUT_BUFFER,&ioctl_msg) < 0) {
1792             DEBUG_PRINT_ERROR("ERROR: venc_free_buf: free input buffer failed ");
1793             return false;
1794         }
1795     } else if (port == PORT_INDEX_OUT) {
1796         dev_buffer.pbuffer = (OMX_U8 *)pmem_tmp->buffer;
1797         dev_buffer.fd  = pmem_tmp->fd;
1798         dev_buffer.sz = pmem_tmp->size;
1799         dev_buffer.maped_size = pmem_tmp->size;
1800         dev_buffer.offset = pmem_tmp->offset;
1801         ioctl_msg.in  = (void*)&dev_buffer;
1802         ioctl_msg.out = NULL;
1803 
1804         DEBUG_PRINT_LOW("venc_free_buf:pbuffer = %x,fd = %x, offset = %d, maped_size = %d", \
1805                 dev_buffer.pbuffer, \
1806                 dev_buffer.fd, \
1807                 dev_buffer.offset, \
1808                 dev_buffer.maped_size);
1809 
1810         if (ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FREE_OUTPUT_BUFFER,&ioctl_msg) < 0) {
1811             DEBUG_PRINT_ERROR("ERROR: venc_free_buf: free output buffer failed ");
1812             return false;
1813         }
1814     } else {
1815         DEBUG_PRINT_ERROR("ERROR: venc_free_buf:Invalid Port Index ");
1816         return false;
1817     }
1818 
1819     return true;
1820 }
1821 
venc_color_align(OMX_BUFFERHEADERTYPE * buffer,OMX_U32 width,OMX_U32 height)1822 bool venc_dev::venc_color_align(OMX_BUFFERHEADERTYPE *buffer,
1823                 OMX_U32 width, OMX_U32 height)
1824 {
1825     DEBUG_PRINT_ERROR("%s not implemented!", __func__);
1826     return OMX_ErrorUnsupportedSetting;
1827 }
1828 
venc_empty_buf(void * buffer,void * pmem_data_buf,unsigned,unsigned)1829 bool venc_dev::venc_empty_buf(void *buffer, void *pmem_data_buf,unsigned,unsigned)
1830 {
1831     struct venc_buffer frameinfo;
1832     struct pmem *temp_buffer;
1833     struct venc_ioctl_msg ioctl_msg;
1834     struct OMX_BUFFERHEADERTYPE *bufhdr;
1835 
1836     if (buffer == NULL) {
1837         DEBUG_PRINT_ERROR("ERROR: venc_etb: buffer is NULL");
1838         return false;
1839     }
1840 
1841     bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
1842 
1843     DEBUG_PRINT_LOW("Input buffer length %d",bufhdr->nFilledLen);
1844 
1845     if (pmem_data_buf) {
1846         DEBUG_PRINT_LOW("Internal PMEM addr for i/p Heap UseBuf: %p", pmem_data_buf);
1847         frameinfo.ptrbuffer = (OMX_U8 *)pmem_data_buf;
1848     } else {
1849         DEBUG_PRINT_LOW("Shared PMEM addr for i/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer);
1850         frameinfo.ptrbuffer = (OMX_U8 *)bufhdr->pBuffer;
1851     }
1852 
1853     frameinfo.clientdata = (void *) buffer;
1854     frameinfo.sz = bufhdr->nFilledLen;
1855     frameinfo.len = bufhdr->nFilledLen;
1856     frameinfo.flags = bufhdr->nFlags;
1857     frameinfo.offset = bufhdr->nOffset;
1858     frameinfo.timestamp = bufhdr->nTimeStamp;
1859     DEBUG_PRINT_LOW("i/p TS = %u", (OMX_U32)frameinfo.timestamp);
1860     ioctl_msg.in = &frameinfo;
1861     ioctl_msg.out = NULL;
1862 
1863     DEBUG_PRINT_LOW("DBG: i/p frameinfo: bufhdr->pBuffer = %p, ptrbuffer = %p, offset = %u, len = %u",
1864             bufhdr->pBuffer, frameinfo.ptrbuffer, frameinfo.offset, frameinfo.len);
1865 
1866     if (ioctl(m_nDriver_fd,VEN_IOCTL_CMD_ENCODE_FRAME,&ioctl_msg) < 0) {
1867         /*Generate an async error and move to invalid state*/
1868         return false;
1869     }
1870 
1871     if (m_debug.in_buffer_log) {
1872         venc_input_log_buffers(bufhdr, pmem_data_bufr, frameinfo.len);
1873     }
1874 
1875     return true;
1876 }
venc_fill_buf(void * buffer,void * pmem_data_buf,unsigned,unsigned)1877 bool venc_dev::venc_fill_buf(void *buffer, void *pmem_data_buf,unsigned,unsigned)
1878 {
1879     struct venc_ioctl_msg ioctl_msg = {NULL,NULL};
1880     struct pmem *temp_buffer = NULL;
1881     struct venc_buffer  frameinfo;
1882     struct OMX_BUFFERHEADERTYPE *bufhdr;
1883 
1884     if (buffer == NULL) {
1885         return false;
1886     }
1887 
1888     bufhdr = (OMX_BUFFERHEADERTYPE *)buffer;
1889 
1890     if (pmem_data_buf) {
1891         DEBUG_PRINT_LOW("Internal PMEM addr for o/p Heap UseBuf: %p", pmem_data_buf);
1892         frameinfo.ptrbuffer = (OMX_U8 *)pmem_data_buf;
1893     } else {
1894         DEBUG_PRINT_LOW("Shared PMEM addr for o/p PMEM UseBuf/AllocateBuf: %p", bufhdr->pBuffer);
1895         frameinfo.ptrbuffer = (OMX_U8 *)bufhdr->pBuffer;
1896     }
1897 
1898     frameinfo.clientdata = buffer;
1899     frameinfo.sz = bufhdr->nAllocLen;
1900     frameinfo.flags = bufhdr->nFlags;
1901     frameinfo.offset = bufhdr->nOffset;
1902 
1903     ioctl_msg.in = &frameinfo;
1904     ioctl_msg.out = NULL;
1905     DEBUG_PRINT_LOW("DBG: o/p frameinfo: bufhdr->pBuffer = %p, ptrbuffer = %p, offset = %u, len = %u",
1906             bufhdr->pBuffer, frameinfo.ptrbuffer, frameinfo.offset, frameinfo.len);
1907 
1908     if (ioctl (m_nDriver_fd,VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER,&ioctl_msg) < 0) {
1909         DEBUG_PRINT_ERROR("ERROR: ioctl VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER failed");
1910         return false;
1911     }
1912 
1913     return true;
1914 }
1915 
venc_set_slice_delivery_mode(OMX_BOOL enable)1916 bool venc_dev::venc_set_slice_delivery_mode(OMX_BOOL enable)
1917 {
1918     venc_ioctl_msg ioctl_msg = {NULL,NULL};
1919     DEBUG_PRINT_HIGH("Set slice_delivery_mode: %d", enable);
1920 
1921     if (multislice.mslice_mode == VEN_MSLICE_CNT_MB) {
1922         if (ioctl(m_nDriver_fd, VEN_IOCTL_SET_SLICE_DELIVERY_MODE) < 0) {
1923             DEBUG_PRINT_ERROR("Request for setting slice delivery mode failed");
1924             return false;
1925         }
1926     } else {
1927         DEBUG_PRINT_ERROR("WARNING: slice_mode[%d] is not VEN_MSLICE_CNT_MB to set "
1928                 "slice delivery mode to the driver.", multislice.mslice_mode);
1929     }
1930 
1931     return true;
1932 }
1933 
venc_set_plusptype(OMX_BOOL enable)1934 bool venc_dev::venc_set_plusptype(OMX_BOOL enable)
1935 {
1936     venc_ioctl_msg ioctl_msg = {NULL,NULL};
1937     struct venc_plusptype plusptype = {0};
1938     DEBUG_PRINT_LOW("Set plusptype: %d", enable);
1939     plusptype.plusptype_enable = enable;
1940     ioctl_msg.in = (void*)&plusptype;
1941     ioctl_msg.out = NULL;
1942 
1943     if (ioctl(m_nDriver_fd, VEN_IOCTL_SET_H263_PLUSPTYPE,(void*)&ioctl_msg) < 0) {
1944         DEBUG_PRINT_ERROR("Request for setting plusptype for h263 failed");
1945         return false;
1946     }
1947 
1948     return true;
1949 }
1950 
venc_set_ltrmode(QOMX_VIDEO_LTRMODETYPE mode)1951 bool venc_dev::venc_set_ltrmode(QOMX_VIDEO_LTRMODETYPE mode)
1952 {
1953     venc_ioctl_msg ioctl_msg = {NULL,NULL};
1954     venc_ltrmode ltr_mode;
1955     ltr_mode.ltr_mode = (unsigned long)mode;
1956     DEBUG_PRINT_HIGH("Set ltr mode: %d", mode);
1957     ioctl_msg.in = (void*)&ltr_mode;
1958     ioctl_msg.out = NULL;
1959 
1960     if (ioctl (m_nDriver_fd, VEN_IOCTL_SET_LTRMODE, (void*)&ioctl_msg) < 0) {
1961         DEBUG_PRINT_ERROR("ERROR: Setting ltrmode failed");
1962         return false;
1963     }
1964 
1965     ltrmode.ltr_mode = (unsigned long)mode;
1966     return true;
1967 }
1968 
venc_set_ltrcount(OMX_U32 count)1969 bool venc_dev::venc_set_ltrcount(OMX_U32 count)
1970 {
1971     venc_ioctl_msg ioctl_msg = {NULL,NULL};
1972     venc_ltrcount ltr_count;
1973     ltr_count.ltr_count = (unsigned long)count;
1974     DEBUG_PRINT_HIGH("Set ltr count: %d", count);
1975     ioctl_msg.in = (void*)&ltr_count;
1976     ioctl_msg.out = NULL;
1977 
1978     if (ioctl (m_nDriver_fd, VEN_IOCTL_SET_LTRCOUNT, (void*)&ioctl_msg) < 0) {
1979         DEBUG_PRINT_ERROR("ERROR: Setting ltrcount failed");
1980         return false;
1981     }
1982 
1983     ltrcount.ltr_count = (unsigned long)count;
1984     return true;
1985 }
1986 
venc_set_ltrperiod(OMX_U32 period)1987 bool venc_dev::venc_set_ltrperiod(OMX_U32 period)
1988 {
1989     venc_ioctl_msg ioctl_msg = {NULL,NULL};
1990     venc_ltrperiod ltr_period;
1991     ltr_period.ltr_period = (unsigned long)period;
1992     DEBUG_PRINT_HIGH("Set ltr period: %d", period);
1993     ioctl_msg.in = (void*)&ltr_period;
1994     ioctl_msg.out = NULL;
1995 
1996     if (ioctl (m_nDriver_fd, VEN_IOCTL_SET_LTRPERIOD, (void*)&ioctl_msg) < 0) {
1997         DEBUG_PRINT_ERROR("ERROR: Setting ltrperiod failed");
1998         return false;
1999     }
2000 
2001     ltrperiod.ltr_period = (unsigned long)period;
2002     return true;
2003 }
2004 
venc_set_ltruse(OMX_U32 id,OMX_U32 frames)2005 bool venc_dev::venc_set_ltruse(OMX_U32 id, OMX_U32 frames)
2006 {
2007     venc_ioctl_msg ioctl_msg = {NULL,NULL};
2008     venc_ltruse ltr_use;
2009     ltr_use.ltr_id = (unsigned long)id;
2010     ltr_use.ltr_frames = (unsigned long)frames;
2011     DEBUG_PRINT_HIGH("Set ltr use: id = %d, ltr_frames = %d", id, frames);
2012     ioctl_msg.in = (void*)&ltr_use;
2013     ioctl_msg.out = NULL;
2014 
2015     if (ioctl (m_nDriver_fd, VEN_IOCTL_SET_LTRUSE, (void*)&ioctl_msg) < 0) {
2016         DEBUG_PRINT_ERROR("ERROR: Setting ltruse failed");
2017         return false;
2018     }
2019 
2020     return true;
2021 }
2022 
venc_set_extradata(OMX_U32 extra_data)2023 bool venc_dev::venc_set_extradata(OMX_U32 extra_data)
2024 {
2025     venc_ioctl_msg ioctl_msg = {NULL,NULL};
2026     DEBUG_PRINT_HIGH("venc_set_extradata:: %x", extra_data);
2027     ioctl_msg.in = (void*)&extra_data;
2028     ioctl_msg.out = NULL;
2029 
2030     if (ioctl (m_nDriver_fd, VEN_IOCTL_SET_EXTRADATA, (void*)&ioctl_msg) < 0) {
2031         DEBUG_PRINT_ERROR("ERROR: Request for setting extradata failed");
2032         return false;
2033     }
2034 
2035     return true;
2036 }
2037 
venc_set_session_qp(OMX_U32 i_frame_qp,OMX_U32 p_frame_qp)2038 bool venc_dev::venc_set_session_qp(OMX_U32 i_frame_qp, OMX_U32 p_frame_qp)
2039 {
2040     venc_ioctl_msg ioctl_msg = {NULL,NULL};
2041     struct venc_sessionqp qp = {0, 0};
2042     DEBUG_PRINT_HIGH("venc_set_session_qp:: i_frame_qp = %d, p_frame_qp = %d", i_frame_qp,
2043             p_frame_qp);
2044 
2045     qp.iframeqp = i_frame_qp;
2046     qp.pframqp = p_frame_qp;
2047 
2048     ioctl_msg.in = (void*)&qp;
2049     ioctl_msg.out = NULL;
2050 
2051     if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_SESSION_QP,(void*)&ioctl_msg)< 0) {
2052         DEBUG_PRINT_ERROR("ERROR: Request for setting session qp failed");
2053         return false;
2054     }
2055 
2056     session_qp.iframeqp = i_frame_qp;
2057     session_qp.pframqp = p_frame_qp;
2058 
2059     return true;
2060 }
2061 
venc_set_qp_range(OMX_U32 min_qp,OMX_U32 max_qp)2062 bool venc_dev::venc_set_qp_range(OMX_U32 min_qp, OMX_U32 max_qp)
2063 {
2064     venc_ioctl_msg ioctl_msg = {NULL,NULL};
2065     struct venc_qprange qp = {0, 0};
2066     DEBUG_PRINT_LOW("venc_set_qp_range:: min_qp = %d, max_qp = %d", min_qp,
2067             max_qp);
2068 
2069     qp.minqp = min_qp;
2070     qp.maxqp = max_qp;
2071 
2072     ioctl_msg.in = (void*)&qp;
2073     ioctl_msg.out = NULL;
2074 
2075     if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_QP_RANGE,(void*)&ioctl_msg)< 0) {
2076         DEBUG_PRINT_ERROR("ERROR: Request for setting qp range failed");
2077         return false;
2078     }
2079 
2080     qp_range.minqp= min_qp;
2081     qp_range.maxqp= max_qp;
2082 
2083     return true;
2084 }
2085 
venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel)2086 bool venc_dev::venc_set_profile_level(OMX_U32 eProfile,OMX_U32 eLevel)
2087 {
2088     venc_ioctl_msg ioctl_msg = {NULL,NULL};
2089     struct venc_profile requested_profile;
2090     struct ven_profilelevel requested_level;
2091     unsigned const int *profile_tbl = NULL;
2092     unsigned long mb_per_frame = 0, mb_per_sec = 0;
2093     DEBUG_PRINT_HIGH("venc_set_profile_level:: eProfile = %d, Level = %d",
2094             eProfile, eLevel);
2095     mb_per_frame = ((m_sVenc_cfg.input_height + 15) >> 4)*
2096         ((m_sVenc_cfg.input_width + 15) >> 4);
2097 
2098     if ((eProfile == 0) && (eLevel == 0) && m_profile_set && m_level_set) {
2099         DEBUG_PRINT_HIGH("Set profile/level was done already");
2100         return true;
2101     }
2102 
2103     if (eProfile && eLevel) {
2104         /* non-zero values will be set by user, saving the same*/
2105         m_eProfile = eProfile;
2106         m_eLevel = eLevel;
2107         DEBUG_PRINT_HIGH("Save profile/level (%d/%d) for max allowed bitrate check",
2108                 m_eProfile, m_eLevel);
2109     }
2110 
2111     DEBUG_PRINT_LOW("Validating Profile/Level from table");
2112 
2113     if (!venc_validate_profile_level(&eProfile, &eLevel)) {
2114         DEBUG_PRINT_LOW("ERROR: Profile/Level validation failed");
2115         return false;
2116     }
2117 
2118     if (m_sVenc_cfg.codectype == VEN_CODEC_MPEG4) {
2119         DEBUG_PRINT_LOW("eProfile = %d, OMX_VIDEO_MPEG4ProfileSimple = %d and "
2120                 "OMX_VIDEO_MPEG4ProfileAdvancedSimple = %d", eProfile,
2121                 OMX_VIDEO_MPEG4ProfileSimple, OMX_VIDEO_MPEG4ProfileAdvancedSimple);
2122 
2123         if (eProfile == OMX_VIDEO_MPEG4ProfileSimple) {
2124             requested_profile.profile = VEN_PROFILE_MPEG4_SP;
2125             profile_tbl = (unsigned int const *)
2126                 (&mpeg4_profile_level_table[MPEG4_SP_START]);
2127             profile_tbl += MPEG4_720P_LEVEL*5;
2128         } else if (eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) {
2129             requested_profile.profile = VEN_PROFILE_MPEG4_ASP;
2130             profile_tbl = (unsigned int const *)
2131                 (&mpeg4_profile_level_table[MPEG4_ASP_START]);
2132             profile_tbl += MPEG4_720P_LEVEL*5;
2133         } else {
2134             DEBUG_PRINT_LOW("ERROR: Unsupported MPEG4 profile = %u",
2135                     eProfile);
2136             return false;
2137         }
2138 
2139         DEBUG_PRINT_LOW("eLevel = %d, OMX_VIDEO_MPEG4Level0 = %d, OMX_VIDEO_MPEG4Level1 = %d,"
2140                 "OMX_VIDEO_MPEG4Level2 = %d, OMX_VIDEO_MPEG4Level3 = %d, OMX_VIDEO_MPEG4Level4 = %d,"
2141                 "OMX_VIDEO_MPEG4Level5 = %d", eLevel, OMX_VIDEO_MPEG4Level0, OMX_VIDEO_MPEG4Level1,
2142                 OMX_VIDEO_MPEG4Level2, OMX_VIDEO_MPEG4Level3, OMX_VIDEO_MPEG4Level4, OMX_VIDEO_MPEG4Level5);
2143 
2144         if (mb_per_frame >= 3600) {
2145             if (requested_profile.profile == VEN_PROFILE_MPEG4_ASP)
2146                 requested_level.level = VEN_LEVEL_MPEG4_5;
2147 
2148             if (requested_profile.profile == VEN_PROFILE_MPEG4_SP)
2149                 requested_level.level = VEN_LEVEL_MPEG4_6;
2150         } else {
2151             switch (eLevel) {
2152                 case OMX_VIDEO_MPEG4Level0:
2153                     requested_level.level = VEN_LEVEL_MPEG4_0;
2154                     break;
2155                 case OMX_VIDEO_MPEG4Level1:
2156                     requested_level.level = VEN_LEVEL_MPEG4_1;
2157                     break;
2158                 case OMX_VIDEO_MPEG4Level2:
2159                     requested_level.level = VEN_LEVEL_MPEG4_2;
2160                     break;
2161                 case OMX_VIDEO_MPEG4Level3:
2162                     requested_level.level = VEN_LEVEL_MPEG4_3;
2163                     break;
2164                 case OMX_VIDEO_MPEG4Level4a:
2165                     requested_level.level = VEN_LEVEL_MPEG4_4;
2166                     break;
2167                 case OMX_VIDEO_MPEG4Level5:
2168                     mb_per_sec = mb_per_frame * (m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den);
2169 
2170                     if ((requested_profile.profile == VEN_PROFILE_MPEG4_SP) && (mb_per_frame >= profile_tbl[0]) &&
2171                             (mb_per_sec >= profile_tbl[1])) {
2172                         DEBUG_PRINT_LOW("MPEG4 Level 6 is set for 720p resolution");
2173                         requested_level.level = VEN_LEVEL_MPEG4_6;
2174                     } else {
2175                         DEBUG_PRINT_LOW("MPEG4 Level 5 is set for non-720p resolution");
2176                         requested_level.level = VEN_LEVEL_MPEG4_5;
2177                     }
2178 
2179                     break;
2180                 default:
2181                     return false;
2182                     // TODO update corresponding levels for MPEG4_LEVEL_3b,MPEG4_LEVEL_6
2183                     break;
2184             }
2185         }
2186     } else if (m_sVenc_cfg.codectype == VEN_CODEC_H263) {
2187         if (eProfile == OMX_VIDEO_H263ProfileBaseline) {
2188             requested_profile.profile = VEN_PROFILE_H263_BASELINE;
2189         } else {
2190             DEBUG_PRINT_LOW("ERROR: Unsupported H.263 profile = %u",
2191                     requested_profile.profile);
2192             return false;
2193         }
2194 
2195         //profile level
2196         switch (eLevel) {
2197             case OMX_VIDEO_H263Level10:
2198                 requested_level.level = VEN_LEVEL_H263_10;
2199                 break;
2200             case OMX_VIDEO_H263Level20:
2201                 requested_level.level = VEN_LEVEL_H263_20;
2202                 break;
2203             case OMX_VIDEO_H263Level30:
2204                 requested_level.level = VEN_LEVEL_H263_30;
2205                 break;
2206             case OMX_VIDEO_H263Level40:
2207                 requested_level.level = VEN_LEVEL_H263_40;
2208                 break;
2209             case OMX_VIDEO_H263Level45:
2210                 requested_level.level = VEN_LEVEL_H263_45;
2211                 break;
2212             case OMX_VIDEO_H263Level50:
2213                 requested_level.level = VEN_LEVEL_H263_50;
2214                 break;
2215             case OMX_VIDEO_H263Level60:
2216                 requested_level.level = VEN_LEVEL_H263_60;
2217                 break;
2218             case OMX_VIDEO_H263Level70:
2219                 requested_level.level = VEN_LEVEL_H263_70;
2220                 break;
2221             default:
2222                 return false;
2223                 break;
2224         }
2225     } else if (m_sVenc_cfg.codectype == VEN_CODEC_H264) {
2226         if (eProfile == OMX_VIDEO_AVCProfileBaseline) {
2227             requested_profile.profile = VEN_PROFILE_H264_BASELINE;
2228         } else if (eProfile == OMX_VIDEO_AVCProfileMain) {
2229             requested_profile.profile = VEN_PROFILE_H264_MAIN;
2230         } else if (eProfile == OMX_VIDEO_AVCProfileHigh) {
2231             requested_profile.profile = VEN_PROFILE_H264_HIGH;
2232         } else {
2233             DEBUG_PRINT_LOW("ERROR: Unsupported H.264 profile = %u",
2234                     requested_profile.profile);
2235             return false;
2236         }
2237 
2238         //profile level
2239         switch (eLevel) {
2240             case OMX_VIDEO_AVCLevel1:
2241                 requested_level.level = VEN_LEVEL_H264_1;
2242                 break;
2243             case OMX_VIDEO_AVCLevel1b:
2244                 requested_level.level = VEN_LEVEL_H264_1b;
2245                 break;
2246             case OMX_VIDEO_AVCLevel11:
2247                 requested_level.level = VEN_LEVEL_H264_1p1;
2248                 break;
2249             case OMX_VIDEO_AVCLevel12:
2250                 requested_level.level = VEN_LEVEL_H264_1p2;
2251                 break;
2252             case OMX_VIDEO_AVCLevel13:
2253                 requested_level.level = VEN_LEVEL_H264_1p3;
2254                 break;
2255             case OMX_VIDEO_AVCLevel2:
2256                 requested_level.level = VEN_LEVEL_H264_2;
2257                 break;
2258             case OMX_VIDEO_AVCLevel21:
2259                 requested_level.level = VEN_LEVEL_H264_2p1;
2260                 break;
2261             case OMX_VIDEO_AVCLevel22:
2262                 requested_level.level = VEN_LEVEL_H264_2p2;
2263                 break;
2264             case OMX_VIDEO_AVCLevel3:
2265                 requested_level.level = VEN_LEVEL_H264_3;
2266                 break;
2267             case OMX_VIDEO_AVCLevel31:
2268                 requested_level.level = VEN_LEVEL_H264_3p1;
2269                 break;
2270             case OMX_VIDEO_AVCLevel32:
2271                 requested_level.level = VEN_LEVEL_H264_3p2;
2272                 break;
2273             case OMX_VIDEO_AVCLevel4:
2274                 requested_level.level = VEN_LEVEL_H264_4;
2275                 break;
2276             default :
2277                 DEBUG_PRINT_ERROR("ERROR: Unsupported H.264 level= %u",
2278                         requested_level.level);
2279                 return false;
2280                 break;
2281         }
2282     }
2283 
2284     if (!m_profile_set) {
2285         ioctl_msg.in = (void*)&requested_profile;
2286         ioctl_msg.out = NULL;
2287 
2288         if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_CODEC_PROFILE,(void*)&ioctl_msg)< 0) {
2289             DEBUG_PRINT_ERROR("ERROR: Request for setting profile failed");
2290             return false;
2291         }
2292 
2293         codec_profile.profile = requested_profile.profile;
2294         m_profile_set = true;
2295         DEBUG_PRINT_HIGH("Set codec profile = 0x%x", codec_profile.profile);
2296     }
2297 
2298     if (!m_level_set) {
2299         ioctl_msg.in = (void*)&requested_level;
2300         ioctl_msg.out = NULL;
2301 
2302         if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_PROFILE_LEVEL,(void*)&ioctl_msg)< 0) {
2303             DEBUG_PRINT_ERROR("ERROR: Request for setting profile level failed");
2304             return false;
2305         }
2306 
2307         profile_level.level = requested_level.level;
2308         m_level_set = true;
2309         DEBUG_PRINT_HIGH("Set codec level = 0x%x", profile_level.level);
2310     }
2311 
2312     return true;
2313 }
2314 
venc_set_voptiming_cfg(OMX_U32 TimeIncRes)2315 bool venc_dev::venc_set_voptiming_cfg( OMX_U32 TimeIncRes)
2316 {
2317     venc_ioctl_msg ioctl_msg = {NULL,NULL};
2318     struct venc_voptimingcfg vop_timing_cfg;
2319 
2320     DEBUG_PRINT_HIGH("venc_set_voptiming_cfg: TimeRes = %u",
2321             TimeIncRes);
2322 
2323     vop_timing_cfg.voptime_resolution = TimeIncRes;
2324 
2325     ioctl_msg.in = (void*)&vop_timing_cfg;
2326     ioctl_msg.out = NULL;
2327 
2328     if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_VOP_TIMING_CFG,(void*)&ioctl_msg)< 0) {
2329         DEBUG_PRINT_ERROR("ERROR: Request for setting Vop Timing failed");
2330         return false;
2331     }
2332 
2333     voptimecfg.voptime_resolution = vop_timing_cfg.voptime_resolution;
2334     return true;
2335 }
2336 
venc_set_intra_period(OMX_U32 nPFrames,OMX_U32 nBFrames)2337 bool venc_dev::venc_set_intra_period(OMX_U32 nPFrames, OMX_U32 nBFrames)
2338 {
2339     venc_ioctl_msg ioctl_msg = {NULL,NULL};
2340     struct venc_intraperiod intraperiod_cfg;
2341 
2342     DEBUG_PRINT_LOW("venc_set_intra_period: nPFrames = %u",
2343             nPFrames);
2344     intraperiod_cfg.num_pframes = nPFrames;
2345 
2346     if ((codec_profile.profile == VEN_PROFILE_MPEG4_ASP) ||
2347             (codec_profile.profile == VEN_PROFILE_H264_MAIN) ||
2348             (codec_profile.profile == VEN_PROFILE_H264_HIGH)) {
2349 #ifdef MAX_RES_1080P
2350 
2351         if (nBFrames) {
2352             DEBUG_PRINT_HIGH("INFO: Only 1 Bframe is supported");
2353             intraperiod_cfg.num_bframes = 1;
2354         } else
2355             intraperiod_cfg.num_bframes = 0;
2356 
2357 #else
2358 
2359         if (nBFrames) {
2360             DEBUG_PRINT_ERROR("B frames not supported");
2361             intraperiod_cfg.num_bframes = 0;
2362         } else {
2363             DEBUG_PRINT_ERROR("B frames not supported");
2364             intraperiod_cfg.num_bframes = 0;
2365         }
2366 
2367 #endif
2368     } else
2369         intraperiod_cfg.num_bframes = 0;
2370 
2371     DEBUG_PRINT_HIGH("venc_set_intra_period: nPFrames = %u nBFrames = %u",
2372             intraperiod_cfg.num_pframes, intraperiod_cfg.num_bframes);
2373     ioctl_msg.in = (void*)&intraperiod_cfg;
2374     ioctl_msg.out = NULL;
2375 
2376     if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_INTRA_PERIOD,(void*)&ioctl_msg)< 0) {
2377         DEBUG_PRINT_ERROR("ERROR: Request for setting intra period failed");
2378         return false;
2379     }
2380 
2381     intra_period.num_pframes = intraperiod_cfg.num_pframes;
2382     intra_period.num_bframes = intraperiod_cfg.num_bframes;
2383     return true;
2384 }
2385 
venc_set_entropy_config(OMX_BOOL enable,OMX_U32 i_cabac_level)2386 bool venc_dev::venc_set_entropy_config(OMX_BOOL enable, OMX_U32 i_cabac_level)
2387 {
2388     venc_ioctl_msg ioctl_msg = {NULL,NULL};
2389     struct venc_entropycfg entropy_cfg;
2390 
2391     memset(&entropy_cfg,0,sizeof(entropy_cfg));
2392     DEBUG_PRINT_LOW("venc_set_entropy_config: CABAC = %u level: %u", enable, i_cabac_level);
2393 
2394     if (enable &&(codec_profile.profile != VEN_PROFILE_H264_BASELINE)) {
2395         entropy_cfg.longentropysel = VEN_ENTROPY_MODEL_CABAC;
2396 
2397         if (i_cabac_level == 0) {
2398             entropy_cfg.cabacmodel = VEN_CABAC_MODEL_0;
2399         }
2400 
2401 #ifdef MAX_RES_1080P
2402         else {
2403             DEBUG_PRINT_HIGH("Invalid model set (%d) defaulting to  model 0",i_cabac_level);
2404             entropy_cfg.cabacmodel = VEN_CABAC_MODEL_0;
2405         }
2406 
2407 #else
2408         else if (i_cabac_level == 1) {
2409             entropy_cfg.cabacmodel = VEN_CABAC_MODEL_1;
2410         } else if (i_cabac_level == 2) {
2411             entropy_cfg.cabacmodel = VEN_CABAC_MODEL_2;
2412         }
2413 
2414 #endif
2415     } else if (!enable) {
2416         entropy_cfg.longentropysel = VEN_ENTROPY_MODEL_CAVLC;
2417     } else {
2418         DEBUG_PRINT_ERROR("Invalid Entropy mode for Baseline Profile");
2419         return false;
2420     }
2421 
2422     ioctl_msg.in = (void*)&entropy_cfg;
2423     ioctl_msg.out = NULL;
2424 
2425     if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_ENTROPY_CFG,(void*)&ioctl_msg)< 0) {
2426         DEBUG_PRINT_ERROR("ERROR: Request for setting entropy config failed");
2427         return false;
2428     }
2429 
2430     entropy.longentropysel = entropy_cfg.longentropysel;
2431     entropy.cabacmodel  = entropy_cfg.cabacmodel;
2432     return true;
2433 }
2434 
venc_set_multislice_cfg(OMX_INDEXTYPE Codec,OMX_U32 nSlicesize)2435 bool venc_dev::venc_set_multislice_cfg(OMX_INDEXTYPE Codec, OMX_U32 nSlicesize) // MB
2436 {
2437     venc_ioctl_msg ioctl_msg = {NULL, NULL};
2438     bool status = true;
2439     struct venc_multiclicecfg multislice_cfg;
2440 
2441     if ((Codec != OMX_IndexParamVideoH263)  && (nSlicesize)) {
2442         multislice_cfg.mslice_mode = VEN_MSLICE_CNT_MB;
2443         multislice_cfg.mslice_size = nSlicesize;
2444     } else {
2445         multislice_cfg.mslice_mode = VEN_MSLICE_OFF;
2446         multislice_cfg.mslice_size = 0;
2447     }
2448 
2449     DEBUG_PRINT_LOW("%s(): mode = %u, size = %u", __func__, multislice_cfg.mslice_mode,
2450             multislice_cfg.mslice_size);
2451 
2452     ioctl_msg.in = (void*)&multislice_cfg;
2453     ioctl_msg.out = NULL;
2454 
2455     if (ioctl (m_nDriver_fd, VEN_IOCTL_SET_MULTI_SLICE_CFG,(void*)&ioctl_msg) < 0) {
2456         DEBUG_PRINT_ERROR("ERROR: Request for setting multi-slice cfg failed");
2457         status = false;
2458     } else {
2459         multislice.mslice_mode = multislice_cfg.mslice_mode;
2460         multislice.mslice_size = nSlicesize;
2461     }
2462 
2463     return status;
2464 }
2465 
venc_set_intra_refresh(OMX_VIDEO_INTRAREFRESHTYPE ir_mode,OMX_U32 irMBs)2466 bool venc_dev::venc_set_intra_refresh(OMX_VIDEO_INTRAREFRESHTYPE ir_mode, OMX_U32 irMBs)
2467 {
2468     venc_ioctl_msg ioctl_msg = {NULL, NULL};
2469     bool status = true;
2470     struct venc_intrarefresh intraRefresh_cfg;
2471 
2472     // There is no disabled mode.  Disabled mode is indicated by a 0 count.
2473     if (irMBs == 0 || ir_mode == OMX_VIDEO_IntraRefreshMax) {
2474         intraRefresh_cfg.irmode = VEN_IR_OFF;
2475         intraRefresh_cfg.mbcount = 0;
2476     } else if ((ir_mode == OMX_VIDEO_IntraRefreshCyclic) &&
2477             (irMBs < ((m_sVenc_cfg.input_width * m_sVenc_cfg.input_height)>>8))) {
2478         intraRefresh_cfg.irmode = VEN_IR_CYCLIC;
2479         intraRefresh_cfg.mbcount = irMBs;
2480     } else {
2481         DEBUG_PRINT_ERROR("ERROR: Invalid IntraRefresh Parameters:"
2482                 "mb count: %d, mb mode:%d", irMBs, ir_mode);
2483         return false;
2484     }
2485 
2486     ioctl_msg.in = (void*)&intraRefresh_cfg;
2487     ioctl_msg.out = NULL;
2488 
2489     if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_INTRA_REFRESH,(void*)&ioctl_msg) < 0) {
2490         DEBUG_PRINT_ERROR("ERROR: Request for setting Intra Refresh failed");
2491         status = false;
2492     } else {
2493         intra_refresh.irmode = intraRefresh_cfg.irmode;
2494         intra_refresh.mbcount = intraRefresh_cfg.mbcount;
2495     }
2496 
2497     return status;
2498 }
2499 
venc_set_error_resilience(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE * error_resilience)2500 bool venc_dev::venc_set_error_resilience(OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE* error_resilience)
2501 {
2502     venc_ioctl_msg ioctl_msg = {NULL, NULL};
2503     bool status = true;
2504     struct venc_headerextension hec_cfg;
2505     struct venc_multiclicecfg multislice_cfg;
2506 
2507     if (m_sVenc_cfg.codectype == OMX_VIDEO_CodingMPEG4) {
2508         if (error_resilience->bEnableHEC) {
2509             hec_cfg.header_extension = 1;
2510         } else {
2511             hec_cfg.header_extension = 0;
2512         }
2513 
2514         ioctl_msg.in = (void*)&hec_cfg;
2515         ioctl_msg.out = NULL;
2516 
2517         if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_HEC,(void*)&ioctl_msg) < 0) {
2518             DEBUG_PRINT_ERROR("ERROR: Request for setting HEader Error correction failed");
2519             return false;
2520         }
2521 
2522         hec.header_extension = error_resilience->bEnableHEC;
2523     }
2524 
2525     if (error_resilience->bEnableRVLC) {
2526         DEBUG_PRINT_ERROR("RVLC is not Supported");
2527         return false;
2528     }
2529 
2530     if (( m_sVenc_cfg.codectype != OMX_VIDEO_CodingH263) &&
2531             (error_resilience->bEnableDataPartitioning)) {
2532         DEBUG_PRINT_ERROR("DataPartioning are not Supported for MPEG4/H264");
2533         return false;
2534     }
2535 
2536     if (( m_sVenc_cfg.codectype != OMX_VIDEO_CodingH263) &&
2537             (error_resilience->nResynchMarkerSpacing)) {
2538         multislice_cfg.mslice_mode = VEN_MSLICE_CNT_BYTE;
2539         multislice_cfg.mslice_size = error_resilience->nResynchMarkerSpacing;
2540     } else if (m_sVenc_cfg.codectype == OMX_VIDEO_CodingH263 &&
2541             error_resilience->bEnableDataPartitioning) {
2542         multislice_cfg.mslice_mode = VEN_MSLICE_GOB;
2543         multislice_cfg.mslice_size = 0;
2544     } else {
2545         multislice_cfg.mslice_mode = VEN_MSLICE_OFF;
2546         multislice_cfg.mslice_size = 0;
2547     }
2548 
2549     DEBUG_PRINT_LOW("%s(): mode = %u, size = %u", __func__, multislice_cfg.mslice_mode,
2550             multislice_cfg.mslice_size);
2551     ioctl_msg.in = (void*)&multislice_cfg;
2552     ioctl_msg.out = NULL;
2553 
2554     if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_MULTI_SLICE_CFG,(void*)&ioctl_msg) < 0) {
2555         DEBUG_PRINT_ERROR("ERROR: Request for setting multi-slice cfg failed");
2556         status = false;
2557     } else {
2558         multislice.mslice_mode = multislice_cfg.mslice_mode ;
2559         multislice.mslice_size = multislice_cfg.mslice_size;
2560 
2561     }
2562 
2563     return status;
2564 }
2565 
venc_set_inloop_filter(OMX_VIDEO_AVCLOOPFILTERTYPE loopfilter)2566 bool venc_dev::venc_set_inloop_filter(OMX_VIDEO_AVCLOOPFILTERTYPE loopfilter)
2567 {
2568     venc_ioctl_msg ioctl_msg = {NULL,NULL};
2569     struct venc_dbcfg filter_cfg;
2570 
2571     memset(&filter_cfg, 0, sizeof(filter_cfg));
2572     DEBUG_PRINT_LOW("venc_set_inloop_filter: %u",loopfilter);
2573 
2574     if (loopfilter == OMX_VIDEO_AVCLoopFilterEnable) {
2575         filter_cfg.db_mode = VEN_DB_ALL_BLKG_BNDRY;
2576     } else if (loopfilter == OMX_VIDEO_AVCLoopFilterDisable) {
2577         filter_cfg.db_mode = VEN_DB_DISABLE;
2578     } else if (loopfilter == OMX_VIDEO_AVCLoopFilterDisableSliceBoundary) {
2579         filter_cfg.db_mode = VEN_DB_SKIP_SLICE_BNDRY;
2580     }
2581 
2582     filter_cfg.slicealpha_offset = filter_cfg.slicebeta_offset = 0;
2583 
2584     ioctl_msg.in = (void*)&filter_cfg;
2585     ioctl_msg.out = NULL;
2586 
2587     if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_DEBLOCKING_CFG,(void*)&ioctl_msg)< 0) {
2588         DEBUG_PRINT_ERROR("ERROR: Request for setting inloop filter failed");
2589         return false;
2590     }
2591 
2592     dbkfilter.db_mode = filter_cfg.db_mode;
2593     dbkfilter.slicealpha_offset = dbkfilter.slicebeta_offset = 0;
2594     return true;
2595 }
2596 
venc_set_target_bitrate(OMX_U32 nTargetBitrate,OMX_U32 config)2597 bool venc_dev::venc_set_target_bitrate(OMX_U32 nTargetBitrate, OMX_U32 config)
2598 {
2599     venc_ioctl_msg ioctl_msg = {NULL, NULL};
2600     struct venc_targetbitrate bitrate_cfg;
2601 
2602     DEBUG_PRINT_HIGH("venc_set_target_bitrate: bitrate = %u",
2603             nTargetBitrate);
2604     bitrate_cfg.target_bitrate = nTargetBitrate ;
2605     ioctl_msg.in = (void*)&bitrate_cfg;
2606     ioctl_msg.out = NULL;
2607 
2608     if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_TARGET_BITRATE,(void*)&ioctl_msg) < 0) {
2609         DEBUG_PRINT_ERROR("ERROR: Request for setting bit rate failed");
2610         return false;
2611     }
2612 
2613     m_sVenc_cfg.targetbitrate = nTargetBitrate;
2614     bitrate.target_bitrate = nTargetBitrate;
2615 
2616     if (!config) {
2617         m_level_set = false;
2618 
2619         if (venc_set_profile_level(0, 0)) {
2620             DEBUG_PRINT_LOW("Calling set level (Bitrate) with %d",profile_level.level);
2621         }
2622     }
2623 
2624     return true;
2625 }
2626 
venc_set_encode_framerate(OMX_U32 encode_framerate,OMX_U32 config)2627 bool venc_dev::venc_set_encode_framerate(OMX_U32 encode_framerate, OMX_U32 config)
2628 {
2629     venc_ioctl_msg ioctl_msg = {NULL, NULL};
2630     struct venc_framerate frame_rate_cfg;
2631 
2632     Q16ToFraction(encode_framerate,frame_rate_cfg.fps_numerator,frame_rate_cfg.fps_denominator);
2633 
2634     DEBUG_PRINT_HIGH("venc_set_encode_framerate: framerate(Q16) = %u, NR: %d, DR: %d",
2635             encode_framerate,frame_rate_cfg.fps_numerator,frame_rate_cfg.fps_denominator);
2636 
2637     ioctl_msg.in = (void*)&frame_rate_cfg;
2638     ioctl_msg.out = NULL;
2639 
2640     if (ioctl(m_nDriver_fd, VEN_IOCTL_SET_FRAME_RATE,
2641                 (void*)&ioctl_msg) < 0) {
2642         DEBUG_PRINT_ERROR("ERROR: Request for setting framerate failed");
2643         return false;
2644     }
2645 
2646     m_sVenc_cfg.fps_den = frame_rate_cfg.fps_denominator;
2647     m_sVenc_cfg.fps_num = frame_rate_cfg.fps_numerator;
2648 
2649     if (!config) {
2650         m_level_set = false;
2651 
2652         if (venc_set_profile_level(0, 0)) {
2653             DEBUG_PRINT_LOW("Calling set level (Framerate) with %d",profile_level.level);
2654         }
2655     }
2656 
2657     return true;
2658 }
2659 
venc_set_color_format(OMX_COLOR_FORMATTYPE color_format)2660 bool venc_dev::venc_set_color_format(OMX_COLOR_FORMATTYPE color_format)
2661 {
2662     venc_ioctl_msg ioctl_msg = {NULL, NULL};
2663 
2664     if (color_format == OMX_COLOR_FormatYUV420SemiPlanar) {
2665 #ifdef MAX_RES_1080P
2666         m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12_16M2KA;
2667 #else
2668         m_sVenc_cfg.inputformat = VEN_INPUTFMT_NV12;
2669 #endif
2670     } else {
2671         DEBUG_PRINT_ERROR("WARNING: Unsupported Color format [%d]", color_format);
2672 #ifdef MAX_RES_1080P
2673         m_sVenc_cfg.inputformat= VEN_INPUTFMT_NV12_16M2KA;
2674 #else
2675         m_sVenc_cfg.inputformat = VEN_INPUTFMT_NV12;
2676 #endif
2677         DEBUG_PRINT_HIGH("Default color format YUV420SemiPlanar is set");
2678     }
2679 
2680     ioctl_msg.in = (void*)&m_sVenc_cfg;
2681     ioctl_msg.out = NULL;
2682 
2683     if (ioctl(m_nDriver_fd, VEN_IOCTL_SET_BASE_CFG, (void*)&ioctl_msg) < 0) {
2684         DEBUG_PRINT_ERROR("ERROR: Request for setting color format failed");
2685         return false;
2686     }
2687 
2688     return true;
2689 }
2690 
venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh)2691 bool venc_dev::venc_set_intra_vop_refresh(OMX_BOOL intra_vop_refresh)
2692 {
2693     DEBUG_PRINT_LOW("venc_set_intra_vop_refresh: intra_vop = %uc", intra_vop_refresh);
2694 
2695     if (intra_vop_refresh == OMX_TRUE) {
2696         if (ioctl(m_nDriver_fd, VEN_IOCTL_CMD_REQUEST_IFRAME, NULL) < 0) {
2697             DEBUG_PRINT_ERROR("ERROR: Request for setting Intra VOP Refresh failed");
2698             return false;
2699         }
2700     } else {
2701         DEBUG_PRINT_ERROR("ERROR: VOP Refresh is False, no effect");
2702     }
2703 
2704     return true;
2705 }
2706 
venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate)2707 bool venc_dev::venc_set_ratectrl_cfg(OMX_VIDEO_CONTROLRATETYPE eControlRate)
2708 {
2709     venc_ioctl_msg ioctl_msg = {NULL,NULL};
2710     bool status = true;
2711     struct venc_ratectrlcfg ratectrl_cfg;
2712 
2713     //rate control
2714     switch (eControlRate) {
2715         case OMX_Video_ControlRateDisable:
2716             ratectrl_cfg.rcmode = VEN_RC_OFF;
2717             break;
2718         case OMX_Video_ControlRateVariableSkipFrames:
2719             ratectrl_cfg.rcmode = VEN_RC_VBR_VFR;
2720             break;
2721         case OMX_Video_ControlRateVariable:
2722             ratectrl_cfg.rcmode = VEN_RC_VBR_CFR;
2723             break;
2724         case OMX_Video_ControlRateConstantSkipFrames:
2725             ratectrl_cfg.rcmode = VEN_RC_CBR_VFR;
2726             break;
2727         case OMX_Video_ControlRateConstant:
2728             ratectrl_cfg.rcmode = VEN_RC_CBR_CFR;
2729             break;
2730         default:
2731             status = false;
2732             break;
2733     }
2734 
2735     if (status) {
2736         ioctl_msg.in = (void*)&ratectrl_cfg;
2737         ioctl_msg.out = NULL;
2738 
2739         if (ioctl (m_nDriver_fd,VEN_IOCTL_SET_RATE_CTRL_CFG,(void*)&ioctl_msg) < 0) {
2740             DEBUG_PRINT_ERROR("ERROR: Request for setting rate control failed");
2741             status = false;
2742         } else
2743             rate_ctrl.rcmode = ratectrl_cfg.rcmode;
2744     }
2745 
2746     return status;
2747 }
2748 
venc_get_profile_level(OMX_U32 * eProfile,OMX_U32 * eLevel)2749 bool venc_dev::venc_get_profile_level(OMX_U32 *eProfile,OMX_U32 *eLevel)
2750 {
2751     bool status = true;
2752 
2753     if (eProfile == NULL || eLevel == NULL) {
2754         return false;
2755     }
2756 
2757     if (m_sVenc_cfg.codectype == VEN_CODEC_MPEG4) {
2758         switch (codec_profile.profile) {
2759             case VEN_PROFILE_MPEG4_SP:
2760                 *eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2761                 break;
2762             case VEN_PROFILE_MPEG4_ASP:
2763                 *eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
2764                 break;
2765             default:
2766                 *eProfile = OMX_VIDEO_MPEG4ProfileMax;
2767                 status = false;
2768                 break;
2769         }
2770 
2771         if (!status) {
2772             return status;
2773         }
2774 
2775         //profile level
2776         switch (profile_level.level) {
2777             case VEN_LEVEL_MPEG4_0:
2778                 *eLevel = OMX_VIDEO_MPEG4Level0;
2779                 break;
2780             case VEN_LEVEL_MPEG4_1:
2781                 *eLevel = OMX_VIDEO_MPEG4Level1;
2782                 break;
2783             case VEN_LEVEL_MPEG4_2:
2784                 *eLevel = OMX_VIDEO_MPEG4Level2;
2785                 break;
2786             case VEN_LEVEL_MPEG4_3:
2787                 *eLevel = OMX_VIDEO_MPEG4Level3;
2788                 break;
2789             case VEN_LEVEL_MPEG4_4:
2790                 *eLevel = OMX_VIDEO_MPEG4Level4a;
2791                 break;
2792             case VEN_LEVEL_MPEG4_5:
2793             case VEN_LEVEL_MPEG4_6:
2794                 *eLevel = OMX_VIDEO_MPEG4Level5;
2795                 break;
2796             default:
2797                 *eLevel = OMX_VIDEO_MPEG4LevelMax;
2798                 status =  false;
2799                 break;
2800         }
2801     } else if (m_sVenc_cfg.codectype == VEN_CODEC_H263) {
2802         if (codec_profile.profile == VEN_PROFILE_H263_BASELINE) {
2803             *eProfile = OMX_VIDEO_H263ProfileBaseline;
2804         } else {
2805             *eProfile = OMX_VIDEO_H263ProfileMax;
2806             return false;
2807         }
2808 
2809         switch (profile_level.level) {
2810             case VEN_LEVEL_H263_10:
2811                 *eLevel = OMX_VIDEO_H263Level10;
2812                 break;
2813             case VEN_LEVEL_H263_20:
2814                 *eLevel = OMX_VIDEO_H263Level20;
2815                 break;
2816             case VEN_LEVEL_H263_30:
2817                 *eLevel = OMX_VIDEO_H263Level30;
2818                 break;
2819             case VEN_LEVEL_H263_40:
2820                 *eLevel = OMX_VIDEO_H263Level40;
2821                 break;
2822             case VEN_LEVEL_H263_45:
2823                 *eLevel = OMX_VIDEO_H263Level45;
2824                 break;
2825             case VEN_LEVEL_H263_50:
2826                 *eLevel = OMX_VIDEO_H263Level50;
2827                 break;
2828             case VEN_LEVEL_H263_60:
2829                 *eLevel = OMX_VIDEO_H263Level60;
2830                 break;
2831             case VEN_LEVEL_H263_70:
2832                 *eLevel = OMX_VIDEO_H263Level70;
2833                 break;
2834             default:
2835                 *eLevel = OMX_VIDEO_H263LevelMax;
2836                 status = false;
2837                 break;
2838         }
2839     } else if (m_sVenc_cfg.codectype == VEN_CODEC_H264) {
2840         switch (codec_profile.profile) {
2841             case VEN_PROFILE_H264_BASELINE:
2842                 *eProfile = OMX_VIDEO_AVCProfileBaseline;
2843                 break;
2844             case VEN_PROFILE_H264_MAIN:
2845                 *eProfile = OMX_VIDEO_AVCProfileMain;
2846                 break;
2847             case VEN_PROFILE_H264_HIGH:
2848                 *eProfile = OMX_VIDEO_AVCProfileHigh;
2849                 break;
2850             default:
2851                 *eProfile = OMX_VIDEO_AVCProfileMax;
2852                 status = false;
2853                 break;
2854         }
2855 
2856         if (!status) {
2857             return status;
2858         }
2859 
2860         switch (profile_level.level) {
2861             case VEN_LEVEL_H264_1:
2862                 *eLevel = OMX_VIDEO_AVCLevel1;
2863                 break;
2864             case VEN_LEVEL_H264_1b:
2865                 *eLevel = OMX_VIDEO_AVCLevel1b;
2866                 break;
2867             case VEN_LEVEL_H264_1p1:
2868                 *eLevel = OMX_VIDEO_AVCLevel11;
2869                 break;
2870             case VEN_LEVEL_H264_1p2:
2871                 *eLevel = OMX_VIDEO_AVCLevel12;
2872                 break;
2873             case VEN_LEVEL_H264_1p3:
2874                 *eLevel = OMX_VIDEO_AVCLevel13;
2875                 break;
2876             case VEN_LEVEL_H264_2:
2877                 *eLevel = OMX_VIDEO_AVCLevel2;
2878                 break;
2879             case VEN_LEVEL_H264_2p1:
2880                 *eLevel = OMX_VIDEO_AVCLevel21;
2881                 break;
2882             case VEN_LEVEL_H264_2p2:
2883                 *eLevel = OMX_VIDEO_AVCLevel22;
2884                 break;
2885             case VEN_LEVEL_H264_3:
2886                 *eLevel = OMX_VIDEO_AVCLevel3;
2887                 break;
2888             case VEN_LEVEL_H264_3p1:
2889                 *eLevel = OMX_VIDEO_AVCLevel31;
2890                 break;
2891             case VEN_LEVEL_H264_3p2:
2892                 *eLevel = OMX_VIDEO_AVCLevel32;
2893                 break;
2894             case VEN_LEVEL_H264_4:
2895                 *eLevel = OMX_VIDEO_AVCLevel4;
2896                 break;
2897             default :
2898                 *eLevel = OMX_VIDEO_AVCLevelMax;
2899                 status = false;
2900                 break;
2901         }
2902     }
2903 
2904     return status;
2905 }
2906 
venc_validate_profile_level(OMX_U32 * eProfile,OMX_U32 * eLevel)2907 bool venc_dev::venc_validate_profile_level(OMX_U32 *eProfile, OMX_U32 *eLevel)
2908 {
2909     OMX_U32 new_profile = 0, new_level = 0;
2910     unsigned const int *profile_tbl = NULL;
2911     OMX_U32 mb_per_frame, mb_per_sec;
2912     bool profile_level_found = false;
2913 
2914     DEBUG_PRINT_LOW("Init profile table for respective codec");
2915 
2916     //validate the ht,width,fps,bitrate and set the appropriate profile and level
2917     if (m_sVenc_cfg.codectype == VEN_CODEC_MPEG4) {
2918         if (*eProfile == 0) {
2919             if (!m_profile_set) {
2920                 *eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2921             } else {
2922                 switch (codec_profile.profile) {
2923                     case VEN_PROFILE_MPEG4_ASP:
2924                         *eProfile = OMX_VIDEO_MPEG4ProfileAdvancedSimple;
2925                         break;
2926                     case VEN_PROFILE_MPEG4_SP:
2927                         *eProfile = OMX_VIDEO_MPEG4ProfileSimple;
2928                         break;
2929                     default:
2930                         DEBUG_PRINT_LOW("%s(): Unknown Error", __func__);
2931                         return false;
2932                 }
2933             }
2934         }
2935 
2936         if (*eLevel == 0 && !m_level_set) {
2937             *eLevel = OMX_VIDEO_MPEG4LevelMax;
2938         }
2939 
2940         if (*eProfile == OMX_VIDEO_MPEG4ProfileSimple) {
2941             profile_tbl = (unsigned int const *)mpeg4_profile_level_table;
2942         } else if (*eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) {
2943             profile_tbl = (unsigned int const *)
2944                 (&mpeg4_profile_level_table[MPEG4_ASP_START]);
2945         } else {
2946             DEBUG_PRINT_LOW("Unsupported MPEG4 profile type %lu", *eProfile);
2947             return false;
2948         }
2949     } else if (m_sVenc_cfg.codectype == VEN_CODEC_H264) {
2950         if (*eProfile == 0) {
2951             if (!m_profile_set) {
2952                 *eProfile = OMX_VIDEO_AVCProfileBaseline;
2953             } else {
2954                 switch (codec_profile.profile) {
2955                     case VEN_PROFILE_H264_BASELINE:
2956                         *eProfile = OMX_VIDEO_AVCProfileBaseline;
2957                         break;
2958 #ifndef _MSM8610_
2959                     case VEN_PROFILE_H264_MAIN:
2960                         *eProfile = OMX_VIDEO_AVCProfileMain;
2961                         break;
2962                     case VEN_PROFILE_H264_HIGH:
2963                         *eProfile = OMX_VIDEO_AVCProfileHigh;
2964                         break;
2965 #endif
2966                     default:
2967                         DEBUG_PRINT_LOW("%s(): Unsupported profile %x", __func__, codec_profile.profile);
2968                         return false;
2969                 }
2970             }
2971         }
2972 
2973         if (*eLevel == 0 && !m_level_set) {
2974             *eLevel = OMX_VIDEO_AVCLevelMax;
2975         }
2976 
2977         if (*eProfile == OMX_VIDEO_AVCProfileBaseline) {
2978             profile_tbl = (unsigned int const *)h264_profile_level_table;
2979         } else if (*eProfile == OMX_VIDEO_AVCProfileHigh) {
2980             profile_tbl = (unsigned int const *)
2981                 (&h264_profile_level_table[H264_HP_START]);
2982         } else if (*eProfile == OMX_VIDEO_AVCProfileMain) {
2983             profile_tbl = (unsigned int const *)
2984                 (&h264_profile_level_table[H264_MP_START]);
2985         } else {
2986             DEBUG_PRINT_LOW("Unsupported AVC profile type %lu", *eProfile);
2987             return false;
2988         }
2989     } else if (m_sVenc_cfg.codectype == VEN_CODEC_H263) {
2990         if (*eProfile == 0) {
2991             if (!m_profile_set) {
2992                 *eProfile = OMX_VIDEO_H263ProfileBaseline;
2993             } else {
2994                 switch (codec_profile.profile) {
2995                     case VEN_PROFILE_H263_BASELINE:
2996                         *eProfile = OMX_VIDEO_H263ProfileBaseline;
2997                         break;
2998                     default:
2999                         DEBUG_PRINT_LOW("%s(): Unknown Error", __func__);
3000                         return false;
3001                 }
3002             }
3003         }
3004 
3005         if (*eLevel == 0 && !m_level_set) {
3006             *eLevel = OMX_VIDEO_H263LevelMax;
3007         }
3008 
3009         if (*eProfile == OMX_VIDEO_H263ProfileBaseline) {
3010             profile_tbl = (unsigned int const *)h263_profile_level_table;
3011         } else {
3012             DEBUG_PRINT_LOW("Unsupported H.263 profile type %lu", *eProfile);
3013             return false;
3014         }
3015     } else {
3016         DEBUG_PRINT_LOW("Invalid codec type");
3017         return false;
3018     }
3019 
3020     mb_per_frame = ((m_sVenc_cfg.input_height + 15) >> 4)*
3021         ((m_sVenc_cfg.input_width + 15)>> 4);
3022 
3023     if ((mb_per_frame >= 3600) && (m_sVenc_cfg.codectype == VEN_CODEC_MPEG4)) {
3024         if (codec_profile.profile == VEN_PROFILE_MPEG4_ASP)
3025             profile_level.level = VEN_LEVEL_MPEG4_5;
3026 
3027         if (codec_profile.profile == VEN_PROFILE_MPEG4_SP)
3028             profile_level.level = VEN_LEVEL_MPEG4_6;
3029 
3030         {
3031             new_level = profile_level.level;
3032             new_profile = codec_profile.profile;
3033             return true;
3034         }
3035     }
3036 
3037     mb_per_sec = mb_per_frame * m_sVenc_cfg.fps_num / m_sVenc_cfg.fps_den;
3038 
3039     do {
3040         if (mb_per_frame <= (int)profile_tbl[0]) {
3041             if (mb_per_sec <= (int)profile_tbl[1]) {
3042                 if (m_sVenc_cfg.targetbitrate <= (int)profile_tbl[2]) {
3043                     new_level = (int)profile_tbl[3];
3044                     new_profile = (int)profile_tbl[4];
3045                     profile_level_found = true;
3046                     DEBUG_PRINT_LOW("Appropriate profile/level found %d/%d", new_profile, new_level);
3047                     break;
3048                 }
3049             }
3050         }
3051 
3052         profile_tbl = profile_tbl + 5;
3053     } while (profile_tbl[0] != 0);
3054 
3055     if (profile_level_found != true) {
3056         DEBUG_PRINT_LOW("ERROR: Unsupported profile/level");
3057         return false;
3058     }
3059 
3060     if ((*eLevel == OMX_VIDEO_MPEG4LevelMax) || (*eLevel == OMX_VIDEO_AVCLevelMax)
3061             || (*eLevel == OMX_VIDEO_H263LevelMax)) {
3062         *eLevel = new_level;
3063     }
3064 
3065     DEBUG_PRINT_LOW("%s: Returning with eProfile = %lu"
3066             "Level = %lu", __func__, *eProfile, *eLevel);
3067 
3068     return true;
3069 }
3070 
venc_max_allowed_bitrate_check(OMX_U32 nTargetBitrate)3071 bool venc_dev::venc_max_allowed_bitrate_check(OMX_U32 nTargetBitrate)
3072 {
3073     unsigned const int *profile_tbl = NULL;
3074 
3075     switch (m_sVenc_cfg.codectype) {
3076         case VEN_CODEC_MPEG4:
3077 
3078             if (m_eProfile == OMX_VIDEO_MPEG4ProfileSimple) {
3079                 profile_tbl = (unsigned int const *)mpeg4_profile_level_table;
3080             } else if (m_eProfile == OMX_VIDEO_MPEG4ProfileAdvancedSimple) {
3081                 profile_tbl = (unsigned int const *)
3082                     (&mpeg4_profile_level_table[MPEG4_ASP_START]);
3083             } else {
3084                 DEBUG_PRINT_ERROR("Unsupported MPEG4 profile type %lu", m_eProfile);
3085                 return false;
3086             }
3087 
3088             break;
3089         case VEN_CODEC_H264:
3090 
3091             if (m_eProfile == OMX_VIDEO_AVCProfileBaseline) {
3092                 profile_tbl = (unsigned int const *)h264_profile_level_table;
3093             } else if (m_eProfile == OMX_VIDEO_AVCProfileHigh) {
3094                 profile_tbl = (unsigned int const *)
3095                     (&h264_profile_level_table[H264_HP_START]);
3096             } else if (m_eProfile == OMX_VIDEO_AVCProfileMain) {
3097                 profile_tbl = (unsigned int const *)
3098                     (&h264_profile_level_table[H264_MP_START]);
3099             } else {
3100                 DEBUG_PRINT_ERROR("Unsupported AVC profile type %lu", m_eProfile);
3101                 return false;
3102             }
3103 
3104             break;
3105         case VEN_CODEC_H263:
3106 
3107             if (m_eProfile == OMX_VIDEO_H263ProfileBaseline) {
3108                 profile_tbl = (unsigned int const *)h263_profile_level_table;
3109             } else {
3110                 DEBUG_PRINT_ERROR("Unsupported H.263 profile type %lu", m_eProfile);
3111                 return false;
3112             }
3113 
3114             break;
3115         default:
3116             DEBUG_PRINT_ERROR("%s: unknown codec type", __func__);
3117             return false;
3118     }
3119 
3120     while (profile_tbl[0] != 0) {
3121         if (profile_tbl[3] == m_eLevel) {
3122             if (nTargetBitrate > profile_tbl[2]) {
3123                 DEBUG_PRINT_ERROR("Max. supported bitrate for Profile[%d] & Level[%d]"
3124                         " is %u", m_eProfile, m_eLevel, profile_tbl[2]);
3125                 return false;
3126             }
3127         }
3128 
3129         profile_tbl += 5;
3130     }
3131 
3132     return true;
3133 }
3134 
3135 #ifdef _ANDROID_ICS_
venc_set_meta_mode(bool mode)3136 bool venc_dev::venc_set_meta_mode(bool mode)
3137 {
3138     venc_ioctl_msg ioctl_msg = {NULL,NULL};
3139     ioctl_msg.in = &mode;
3140     DEBUG_PRINT_HIGH("Set meta buffer mode: %d", mode);
3141 
3142     if (ioctl(m_nDriver_fd,VEN_IOCTL_SET_METABUFFER_MODE,&ioctl_msg) < 0) {
3143         DEBUG_PRINT_ERROR(" Set meta buffer mode failed");
3144         return false;
3145     }
3146 
3147     return true;
3148 }
3149 #endif
3150