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