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/*============================================================================
29                    V E N C _ T E S T. C P P
30
31DESCRIPTION
32
33 This is the OMX test app .
34
35REFERENCES
36
37============================================================================*/
38
39//usage
40// FILE QVGA MP4 24 384000 100 enc_qvga.yuv QVGA_24.m4v
41// FILE QCIF MP4 15 96000 0 foreman.qcif.yuv output_qcif.m4v
42// FILE VGA MP4 24 1200000 218 enc_vga.yuv vga_output.m4v
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <string.h>
46#include <unistd.h>
47#include <stdlib.h>
48#include <stdio.h>
49#include <pthread.h>
50#include <fcntl.h>
51#include <sys/mman.h>
52//#include <sys/time.h>
53#include <time.h>
54#include <sys/ioctl.h>
55#include <limits.h>
56#include <string.h>
57//#include <sys/stat.h>
58#include "OMX_QCOMExtns.h"
59#include "OMX_Core.h"
60
61#define QCOM_EXT 1
62
63#include "OMX_Core.h"
64#include "OMX_Video.h"
65#include "OMX_Component.h"
66#include "camera_test.h"
67#include "fb_test.h"
68#include "venc_util.h"
69#include "extra_data_handler.h"
70#ifdef USE_ION
71#include <linux/msm_ion.h>
72#endif
73#ifdef _MSM8974_
74#include <media/msm_media_info.h>
75#endif
76
77//////////////////////////
78// MACROS
79//////////////////////////
80
81#define CHK(result) if ((result != OMX_ErrorNone) && (result != OMX_ErrorNoMore)) { E("*************** error *************"); exit(0); }
82#define TEST_LOG
83#ifdef VENC_SYSLOG
84#include <cutils/log.h>
85/// Debug message macro
86#define D(fmt, ...) ALOGE("venc_test Debug %s::%d "fmt,              \
87        __FUNCTION__, __LINE__,                        \
88## __VA_ARGS__)
89
90/// Error message macro
91#define E(fmt, ...) ALOGE("venc_test Error %s::%d "fmt,            \
92        __FUNCTION__, __LINE__,                      \
93## __VA_ARGS__)
94
95#else
96#ifdef TEST_LOG
97#define D(fmt, ...) fprintf(stderr, "venc_test Debug %s::%d "fmt"\n",   \
98        __FUNCTION__, __LINE__,                     \
99## __VA_ARGS__)
100
101/// Error message macro
102#define E(fmt, ...) fprintf(stderr, "venc_test Error %s::%d "fmt"\n", \
103        __FUNCTION__, __LINE__,                   \
104## __VA_ARGS__)
105#else
106#define D(fmt, ...)
107#define E(fmt, ...)
108#endif
109
110#endif
111
112//////////////////////////
113// CONSTANTS
114//////////////////////////
115static const int MAX_MSG = 100;
116//#warning do not hardcode these use port definition
117static const int PORT_INDEX_IN = 0;
118static const int PORT_INDEX_OUT = 1;
119
120static const int NUM_IN_BUFFERS = 10;
121static const int NUM_OUT_BUFFERS = 10;
122
123unsigned int num_in_buffers = 0;
124unsigned int num_out_buffers = 0;
125
126//////////////////////////
127/* MPEG4 profile and level table*/
128static const unsigned int mpeg4_profile_level_table[][5]= {
129    /*max mb per frame, max mb per sec, max bitrate, level, profile*/
130    {99,1485,64000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileSimple},
131    {99,1485,64000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileSimple},
132    {396,5940,128000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileSimple},
133    {396,11880,384000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileSimple},
134    {1200,36000,4000000,OMX_VIDEO_MPEG4Level4a,OMX_VIDEO_MPEG4ProfileSimple},
135    {1620,40500,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
136    {3600,108000,12000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
137#ifdef _MSM8974_
138    {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
139    {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileSimple},
140#endif
141    {0,0,0,0,0},
142
143    {99,1485,128000,OMX_VIDEO_MPEG4Level0,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
144    {99,1485,128000,OMX_VIDEO_MPEG4Level1,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
145    {396,5940,384000,OMX_VIDEO_MPEG4Level2,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
146    {396,11880,768000,OMX_VIDEO_MPEG4Level3,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
147    {792,23760,3000000,OMX_VIDEO_MPEG4Level4,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
148    {1620,48600,8000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
149#ifdef _MSM8974_
150    {32400,972000,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
151    {34560,1036800,20000000,OMX_VIDEO_MPEG4Level5,OMX_VIDEO_MPEG4ProfileAdvancedSimple},
152#endif
153    {0,0,0,0,0},
154};
155
156/* H264 profile and level table*/
157static const unsigned int h264_profile_level_table[][5]= {
158    /*max mb per frame, max mb per sec, max bitrate, level, profile*/
159    {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileBaseline},
160    {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileBaseline},
161    {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileBaseline},
162    {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileBaseline},
163    {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileBaseline},
164    {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileBaseline},
165    {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileBaseline},
166    {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileBaseline},
167    {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileBaseline},
168    {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileBaseline},
169    {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileBaseline},
170    {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline},
171#ifdef _MSM8974_
172    {32400,972000,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline},
173    {34560,1036800,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileBaseline},
174#endif
175    {0,0,0,0,0},
176
177    {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileHigh},
178    {99,1485,160000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileHigh},
179    {396,3000,240000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileHigh},
180    {396,6000,480000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileHigh},
181    {396,11880,960000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileHigh},
182    {396,11880,2500000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileHigh},
183    {792,19800,5000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileHigh},
184    {1620,20250,5000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileHigh},
185    {1620,40500,12500000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileHigh},
186    {3600,108000,17500000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileHigh},
187    {5120,216000,25000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileHigh},
188    {8192,245760,25000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh},
189#ifdef _MSM8974_
190    {32400,972000,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh},
191    {34560,1036800,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileHigh},
192#endif
193    {0,0,0,0,0},
194
195    {99,1485,64000,OMX_VIDEO_AVCLevel1,OMX_VIDEO_AVCProfileMain},
196    {99,1485,128000,OMX_VIDEO_AVCLevel1b,OMX_VIDEO_AVCProfileMain},
197    {396,3000,192000,OMX_VIDEO_AVCLevel11,OMX_VIDEO_AVCProfileMain},
198    {396,6000,384000,OMX_VIDEO_AVCLevel12,OMX_VIDEO_AVCProfileMain},
199    {396,11880,768000,OMX_VIDEO_AVCLevel13,OMX_VIDEO_AVCProfileMain},
200    {396,11880,2000000,OMX_VIDEO_AVCLevel2,OMX_VIDEO_AVCProfileMain},
201    {792,19800,4000000,OMX_VIDEO_AVCLevel21,OMX_VIDEO_AVCProfileMain},
202    {1620,20250,4000000,OMX_VIDEO_AVCLevel22,OMX_VIDEO_AVCProfileMain},
203    {1620,40500,10000000,OMX_VIDEO_AVCLevel3,OMX_VIDEO_AVCProfileMain},
204    {3600,108000,14000000,OMX_VIDEO_AVCLevel31,OMX_VIDEO_AVCProfileMain},
205    {5120,216000,20000000,OMX_VIDEO_AVCLevel32,OMX_VIDEO_AVCProfileMain},
206    {8192,245760,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain},
207#ifdef _MSM8974_
208    {32400,972000,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain},
209    {34560,1036800,20000000,OMX_VIDEO_AVCLevel4,OMX_VIDEO_AVCProfileMain},
210#endif
211    {0,0,0,0,0}
212
213};
214
215/* H263 profile and level table*/
216static const unsigned int h263_profile_level_table[][5]= {
217    /*max mb per frame, max mb per sec, max bitrate, level, profile*/
218    {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline},
219    {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline},
220    {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline},
221    {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline},
222    {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline},
223    {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline},
224    {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline},
225    {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline},
226#ifdef _MSM8974_
227    {32400,972000,20000000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline},
228    {34560,1036800,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline},
229#endif
230    {0,0,0,0,0}
231};
232#ifdef _MSM8974_
233static const unsigned int VP8_profile_level_table[][5]= {
234    /*max mb per frame, max mb per sec, max bitrate, level, profile*/
235    {99,1485,64000,OMX_VIDEO_H263Level10,OMX_VIDEO_H263ProfileBaseline},
236    {396,5940,128000,OMX_VIDEO_H263Level20,OMX_VIDEO_H263ProfileBaseline},
237    {396,11880,384000,OMX_VIDEO_H263Level30,OMX_VIDEO_H263ProfileBaseline},
238    {396,11880,2048000,OMX_VIDEO_H263Level40,OMX_VIDEO_H263ProfileBaseline},
239    {99,1485,128000,OMX_VIDEO_H263Level45,OMX_VIDEO_H263ProfileBaseline},
240    {396,19800,4096000,OMX_VIDEO_H263Level50,OMX_VIDEO_H263ProfileBaseline},
241    {810,40500,8192000,OMX_VIDEO_H263Level60,OMX_VIDEO_H263ProfileBaseline},
242    {1620,81000,16384000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline},
243    {32400,972000,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline},
244    {34560,1036800,20000000,OMX_VIDEO_H263Level70,OMX_VIDEO_H263ProfileBaseline},
245    {0,0,0,0,0}
246};
247#endif
248
249#define Log2(number, power)  { OMX_U32 temp = number; power = 0; while( (0 == (temp & 0x1)) &&  power < 16) { temp >>=0x1; power++; } }
250#define FractionToQ16(q,num,den) { OMX_U32 power; Log2(den,power); q = num << (16 - power); }
251
252//////////////////////////
253// TYPES
254//////////////////////////
255struct ProfileType {
256    OMX_VIDEO_CODINGTYPE eCodec;
257    OMX_VIDEO_MPEG4LEVELTYPE eLevel;
258    OMX_VIDEO_CONTROLRATETYPE eControlRate;
259    OMX_VIDEO_AVCSLICEMODETYPE eSliceMode;
260    OMX_U32 nFrameWidth;
261    OMX_U32 nFrameHeight;
262    OMX_U32 nFrameBytes;
263#ifdef _MSM8974_
264    OMX_U32 nFramestride;
265    OMX_U32 nFrameScanlines;
266    OMX_U32 nFrameRead;
267#endif
268    OMX_U32 nBitrate;
269    float nFramerate;
270    char* cInFileName;
271    char* cOutFileName;
272    OMX_U32 nUserProfile;
273};
274
275enum MsgId {
276    MSG_ID_OUTPUT_FRAME_DONE,
277    MSG_ID_INPUT_FRAME_DONE,
278    MSG_ID_MAX
279};
280union MsgData {
281    struct {
282        OMX_BUFFERHEADERTYPE* pBuffer;
283    } sBitstreamData;
284};
285struct Msg {
286    MsgId id;
287    MsgData data;
288};
289struct MsgQ {
290    Msg q[MAX_MSG];
291    int head;
292    int size;
293};
294
295enum Mode {
296    MODE_PREVIEW,
297    MODE_DISPLAY,
298    MODE_PROFILE,
299    MODE_FILE_ENCODE,
300    MODE_LIVE_ENCODE
301};
302
303enum ResyncMarkerType {
304    RESYNC_MARKER_NONE,     ///< No resync marker
305    RESYNC_MARKER_BYTE,     ///< BYTE Resync marker for MPEG4, H.264
306    RESYNC_MARKER_MB,       ///< MB resync marker for MPEG4, H.264
307    RESYNC_MARKER_GOB       ///< GOB resync marker for H.263
308};
309
310union DynamicConfigData {
311    OMX_VIDEO_CONFIG_BITRATETYPE bitrate;
312    OMX_CONFIG_FRAMERATETYPE framerate;
313    QOMX_VIDEO_INTRAPERIODTYPE intraperiod;
314    OMX_CONFIG_INTRAREFRESHVOPTYPE intravoprefresh;
315    OMX_CONFIG_ROTATIONTYPE rotation;
316    float f_framerate;
317};
318
319struct DynamicConfig {
320    bool pending;
321    unsigned frame_num;
322    OMX_INDEXTYPE config_param;
323    union DynamicConfigData config_data;
324};
325
326#ifdef USE_ION
327struct enc_ion {
328    int ion_device_fd;
329    struct ion_allocation_data alloc_data;
330    struct ion_fd_data ion_alloc_fd;
331};
332#endif
333
334//////////////////////////
335// MODULE VARS
336//////////////////////////
337static pthread_mutex_t m_mutex;
338static pthread_cond_t m_signal;
339static MsgQ m_sMsgQ;
340
341//#warning determine how many buffers we really have
342OMX_STATETYPE m_eState = OMX_StateInvalid;
343OMX_COMPONENTTYPE m_sComponent;
344OMX_HANDLETYPE m_hHandle = NULL;
345OMX_BUFFERHEADERTYPE* m_pOutBuffers[NUM_OUT_BUFFERS] = {NULL};
346OMX_BUFFERHEADERTYPE* m_pInBuffers[NUM_IN_BUFFERS] = {NULL};
347OMX_BOOL m_bInFrameFree[NUM_IN_BUFFERS];
348
349ProfileType m_sProfile;
350
351static int m_nFramePlay = 0;
352static int m_eMode = MODE_PREVIEW;
353static int m_nInFd = -1;
354static int m_nOutFd = -1;
355static int m_nTimeStamp = 0;
356static int m_nFrameIn = 0; // frames pushed to encoder
357static int m_nFrameOut = 0; // frames returned by encoder
358static int m_nAVCSliceMode = 0;
359static bool m_bWatchDogKicked = false;
360FILE  *m_pDynConfFile = NULL;
361static struct DynamicConfig dynamic_config;
362
363/* Statistics Logging */
364static long long tot_bufsize = 0;
365int ebd_cnt=0, fbd_cnt=0;
366
367#ifdef USE_ION
368static const char* PMEM_DEVICE = "/dev/ion";
369#elif MAX_RES_720P
370static const char* PMEM_DEVICE = "/dev/pmem_adsp";
371#elif MAX_RES_1080P_EBI
372static const char* PMEM_DEVICE  = "/dev/pmem_adsp";
373#elif MAX_RES_1080P
374static const char* PMEM_DEVICE = "/dev/pmem_smipool";
375#else
376#error PMEM_DEVICE cannot be determined.
377#endif
378
379#ifdef USE_ION
380struct enc_ion ion_data;
381#endif
382//////////////////////////
383// MODULE FUNCTIONS
384//////////////////////////
385
386void* PmemMalloc(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem, int nSize)
387{
388    void *pvirt = NULL;
389    int rc = 0;
390
391    if (!pMem)
392        return NULL;
393
394#ifdef USE_ION
395    ion_data.ion_device_fd = open (PMEM_DEVICE, O_RDONLY);
396
397    if (ion_data.ion_device_fd < 0) {
398        E("\nERROR: ION Device open() Failed");
399        return NULL;
400    }
401
402    nSize = (nSize + 4095) & (~4095);
403    ion_data.alloc_data.len = nSize;
404    ion_data.alloc_data.heap_id_mask = 0x1 << ION_CP_MM_HEAP_ID;
405    ion_data.alloc_data.align = 4096;
406    ion_data.alloc_data.flags = ION_SECURE;
407
408    rc = ioctl(ion_data.ion_device_fd,ION_IOC_ALLOC,&ion_data.alloc_data);
409
410    if (rc || !ion_data.alloc_data.handle) {
411        E("\n ION ALLOC memory failed rc: %d, handle: %p", rc, ion_data.alloc_data.handle);
412        ion_data.alloc_data.handle=NULL;
413        return NULL;
414    }
415
416    ion_data.ion_alloc_fd.handle = ion_data.alloc_data.handle;
417    rc = ioctl(ion_data.ion_device_fd,ION_IOC_MAP,&ion_data.ion_alloc_fd);
418
419    if (rc) {
420        E("\n ION MAP failed ");
421        ion_data.ion_alloc_fd.fd =-1;
422        ion_data.ion_alloc_fd.fd =-1;
423        return NULL;
424    }
425
426    pMem->pmem_fd = ion_data.ion_alloc_fd.fd;
427#else
428    pMem->pmem_fd = open(PMEM_DEVICE, O_RDWR);
429
430    if ((int)(pMem->pmem_fd) < 0)
431        return NULL;
432
433    nSize = (nSize + 4095) & (~4095);
434#endif
435    pMem->offset = 0;
436    pvirt = mmap(NULL, nSize,
437            PROT_READ | PROT_WRITE,
438            MAP_SHARED, pMem->pmem_fd, pMem->offset);
439
440    if (pvirt == (void*) MAP_FAILED) {
441        close(pMem->pmem_fd);
442        pMem->pmem_fd = -1;
443#ifdef USE_ION
444
445        if (ioctl(ion_data.ion_device_fd,ION_IOC_FREE,
446                    &ion_data.alloc_data.handle)) {
447            E("ion recon buffer free failed");
448        }
449
450        ion_data.alloc_data.handle = NULL;
451        ion_data.ion_alloc_fd.fd =-1;
452        close(ion_data.ion_device_fd);
453        ion_data.ion_device_fd =-1;
454#endif
455        return NULL;
456    }
457
458    D("allocated pMem->fd = %lu pvirt=0x%p, pMem->phys=0x%lx, size = %d", pMem->pmem_fd,
459            pvirt, pMem->offset, nSize);
460    return pvirt;
461}
462
463int PmemFree(OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem, void* pvirt, int nSize)
464{
465    if (!pMem || !pvirt)
466        return -1;
467
468    nSize = (nSize + 4095) & (~4095);
469    munmap(pvirt, nSize);
470    close(pMem->pmem_fd);
471    pMem->pmem_fd = -1;
472#ifdef USE_ION
473
474    if (ioctl(ion_data.ion_device_fd,ION_IOC_FREE,
475                &ion_data.alloc_data.handle)) {
476        E("ion recon buffer free failed");
477    }
478
479    ion_data.alloc_data.handle = NULL;
480    ion_data.ion_alloc_fd.fd =-1;
481    close(ion_data.ion_device_fd);
482    ion_data.ion_device_fd =-1;
483#endif
484    return 0;
485}
486void PrintFramePackArrangement(OMX_QCOM_FRAME_PACK_ARRANGEMENT framePackingArrangement)
487{
488    printf("id (%lu)\n",
489            framePackingArrangement.id);
490    printf("cancel_flag (%lu)\n",
491            framePackingArrangement.cancel_flag);
492    printf("type (%lu)\n",
493            framePackingArrangement.type);
494    printf("quincunx_sampling_flag (%lu)\n",
495            framePackingArrangement.quincunx_sampling_flag);
496    printf("content_interpretation_type (%lu)\n",
497            framePackingArrangement.content_interpretation_type);
498    printf("spatial_flipping_flag (%lu)\n",
499            framePackingArrangement.spatial_flipping_flag);
500    printf("frame0_flipped_flag (%lu)\n",
501            framePackingArrangement.frame0_flipped_flag);
502    printf("field_views_flag (%lu)\n",
503            framePackingArrangement.field_views_flag);
504    printf("current_frame_is_frame0_flag (%lu)\n",
505            framePackingArrangement.current_frame_is_frame0_flag);
506    printf("frame0_self_contained_flag (%lu)\n",
507            framePackingArrangement.frame0_self_contained_flag);
508    printf("frame1_self_contained_flag (%lu)\n",
509            framePackingArrangement.frame1_self_contained_flag);
510    printf("frame0_grid_position_x (%lu)\n",
511            framePackingArrangement.frame0_grid_position_x);
512    printf("frame0_grid_position_y (%lu)\n",
513            framePackingArrangement.frame0_grid_position_y);
514    printf("frame1_grid_position_x (%lu)\n",
515            framePackingArrangement.frame1_grid_position_x);
516    printf("frame1_grid_position_y (%lu)\n",
517            framePackingArrangement.frame1_grid_position_y);
518    printf("reserved_byte (%lu)\n",
519            framePackingArrangement.reserved_byte);
520    printf("repetition_period (%lu)\n",
521            framePackingArrangement.repetition_period);
522    printf("extension_flag (%lu)\n",
523            framePackingArrangement.extension_flag);
524}
525void SetState(OMX_STATETYPE eState)
526{
527#define GOTO_STATE(eState)                      \
528    case eState:                                 \
529                             {                                         \
530                                 D("Going to state " # eState"...");            \
531                                 OMX_SendCommand(m_hHandle,                     \
532                                         OMX_CommandStateSet,           \
533                                         (OMX_U32) eState,              \
534                                         NULL);                         \
535                                 while (m_eState != eState)                     \
536                                 {                                              \
537                                     sleep(1);                               \
538                                 }                                              \
539                                 D("Now in state " # eState);                   \
540                                 break;                                         \
541                             }
542
543    switch (eState) {
544        GOTO_STATE(OMX_StateLoaded);
545        GOTO_STATE(OMX_StateIdle);
546        GOTO_STATE(OMX_StateExecuting);
547        GOTO_STATE(OMX_StateInvalid);
548        GOTO_STATE(OMX_StateWaitForResources);
549        GOTO_STATE(OMX_StatePause);
550    }
551}
552////////////////////////////////////////////////////////////////////////////////
553OMX_ERRORTYPE ConfigureEncoder()
554{
555    OMX_ERRORTYPE result = OMX_ErrorNone;
556    unsigned const int *profile_tbl = (unsigned int const *)mpeg4_profile_level_table;
557    OMX_U32 mb_per_sec, mb_per_frame;
558    bool profile_level_found = false;
559    OMX_U32 eProfile,eLevel;
560
561    OMX_PARAM_PORTDEFINITIONTYPE portdef; // OMX_IndexParamPortDefinition
562#ifdef QCOM_EXT
563    OMX_QCOM_PARAM_PORTDEFINITIONTYPE qPortDefnType;
564#endif
565    portdef.nPortIndex = (OMX_U32) 0; // input
566    result = OMX_GetParameter(m_hHandle,
567            OMX_IndexParamPortDefinition,
568            &portdef);
569    E("\n OMX_IndexParamPortDefinition Get Paramter on input port");
570    CHK(result);
571    portdef.format.video.nFrameWidth = m_sProfile.nFrameWidth;
572    portdef.format.video.nFrameHeight = m_sProfile.nFrameHeight;
573
574    E ("\n Height %lu width %lu bit rate %lu",portdef.format.video.nFrameHeight
575            ,portdef.format.video.nFrameWidth,portdef.format.video.nBitrate);
576    result = OMX_SetParameter(m_hHandle,
577            OMX_IndexParamPortDefinition,
578            &portdef);
579    E("\n OMX_IndexParamPortDefinition Set Paramter on input port");
580    CHK(result);
581    // once more to get proper buffer size
582    result = OMX_GetParameter(m_hHandle,
583            OMX_IndexParamPortDefinition,
584            &portdef);
585    E("\n OMX_IndexParamPortDefinition Get Paramter on input port, 2nd pass");
586    CHK(result);
587    // update size accordingly
588    m_sProfile.nFrameBytes = portdef.nBufferSize;
589    portdef.nPortIndex = (OMX_U32) 1; // output
590    result = OMX_GetParameter(m_hHandle,
591            OMX_IndexParamPortDefinition,
592            &portdef);
593    E("\n OMX_IndexParamPortDefinition Get Paramter on output port");
594    CHK(result);
595    portdef.format.video.nFrameWidth = m_sProfile.nFrameWidth;
596    portdef.format.video.nFrameHeight = m_sProfile.nFrameHeight;
597    portdef.format.video.nBitrate = m_sProfile.nBitrate;
598    FractionToQ16(portdef.format.video.xFramerate,(int) (m_sProfile.nFramerate * 2),2);
599    result = OMX_SetParameter(m_hHandle,
600            OMX_IndexParamPortDefinition,
601            &portdef);
602    E("\n OMX_IndexParamPortDefinition Set Paramter on output port");
603    CHK(result);
604
605#ifdef QCOM_EXT
606
607    qPortDefnType.nPortIndex = PORT_INDEX_IN;
608    qPortDefnType.nMemRegion = OMX_QCOM_MemRegionEBI1;
609    qPortDefnType.nSize = sizeof(OMX_QCOM_PARAM_PORTDEFINITIONTYPE);
610
611    result = OMX_SetParameter(m_hHandle,
612            (OMX_INDEXTYPE)OMX_QcomIndexPortDefn,
613            &qPortDefnType);
614
615#endif
616
617    if (!m_sProfile.nUserProfile) { // profile not set by user, go ahead with table calculation
618        //validate the ht,width,fps,bitrate and set the appropriate profile and level
619        if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) {
620            profile_tbl = (unsigned int const *)mpeg4_profile_level_table;
621        } else if (m_sProfile.eCodec == OMX_VIDEO_CodingAVC) {
622            profile_tbl = (unsigned int const *)h264_profile_level_table;
623        } else if (m_sProfile.eCodec == OMX_VIDEO_CodingH263) {
624            profile_tbl = (unsigned int const *)h263_profile_level_table;
625        }
626
627#ifdef _MSM8974_
628        else if (m_sProfile.eCodec == OMX_VIDEO_CodingVPX) {
629            profile_tbl = (unsigned int const *)VP8_profile_level_table;
630        }
631
632#endif
633        mb_per_frame = ((m_sProfile.nFrameHeight+15)>>4)*
634            ((m_sProfile.nFrameWidth+15)>>4);
635
636        mb_per_sec = mb_per_frame*(m_sProfile.nFramerate);
637
638        do {
639            if (mb_per_frame <= (unsigned int)profile_tbl[0]) {
640                if (mb_per_sec <= (unsigned int)profile_tbl[1]) {
641                    if (m_sProfile.nBitrate <= (unsigned int)profile_tbl[2]) {
642                        eLevel = (int)profile_tbl[3];
643                        eProfile = (int)profile_tbl[4];
644                        E("\n profile/level found: %lu/%lu\n",eProfile, eLevel);
645                        profile_level_found = true;
646                        break;
647                    }
648                }
649            }
650
651            profile_tbl = profile_tbl + 5;
652        } while (profile_tbl[0] != 0);
653
654        if ( profile_level_found != true ) {
655            E("\n Error: Unsupported profile/level\n");
656            return OMX_ErrorNone;
657        }
658    } else { // Profile set by user!
659        eProfile = m_sProfile.nUserProfile;
660        eLevel = 0;
661    }
662
663    if (m_sProfile.eCodec == OMX_VIDEO_CodingH263) {
664        D("Configuring H263...");
665
666        OMX_VIDEO_PARAM_H263TYPE h263;
667        result = OMX_GetParameter(m_hHandle,
668                OMX_IndexParamVideoH263,
669                &h263);
670        CHK(result);
671        h263.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
672        h263.nPFrames = m_sProfile.nFramerate * 2 - 1; // intra period
673        h263.nBFrames = 0;
674        h263.eProfile = (OMX_VIDEO_H263PROFILETYPE)eProfile;
675        h263.eLevel = (OMX_VIDEO_H263LEVELTYPE)eLevel;
676        h263.bPLUSPTYPEAllowed = OMX_FALSE;
677        h263.nAllowedPictureTypes = 2;
678        h263.bForceRoundingTypeToZero = OMX_TRUE;
679        h263.nPictureHeaderRepetition = 0;
680        h263.nGOBHeaderInterval = 1;
681        result = OMX_SetParameter(m_hHandle,
682                OMX_IndexParamVideoH263,
683                &h263);
684    } else {
685        D("Configuring MP4/H264...");
686
687        OMX_VIDEO_PARAM_PROFILELEVELTYPE profileLevel; // OMX_IndexParamVideoProfileLevelCurrent
688        profileLevel.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
689        profileLevel.eProfile = eProfile;
690        profileLevel.eLevel =  eLevel;
691        result = OMX_SetParameter(m_hHandle,
692                OMX_IndexParamVideoProfileLevelCurrent,
693                &profileLevel);
694        E("\n OMX_IndexParamVideoProfileLevelCurrent Set Paramter port");
695        CHK(result);
696        //profileLevel.eLevel = (OMX_U32) m_sProfile.eLevel;
697        result = OMX_GetParameter(m_hHandle,
698                OMX_IndexParamVideoProfileLevelCurrent,
699                &profileLevel);
700        E("\n OMX_IndexParamVideoProfileLevelCurrent Get Paramter port");
701        D ("\n Profile = %lu level = %lu",profileLevel.eProfile,profileLevel.eLevel);
702        CHK(result);
703
704        if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) {
705            OMX_VIDEO_PARAM_MPEG4TYPE mp4; // OMX_IndexParamVideoMpeg4
706            result = OMX_GetParameter(m_hHandle,
707                    OMX_IndexParamVideoMpeg4,
708                    &mp4);
709            CHK(result);
710            mp4.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
711            mp4.nTimeIncRes = 1000;
712            result = OMX_SetParameter(m_hHandle,
713                    OMX_IndexParamVideoMpeg4,
714                    &mp4);
715            CHK(result);
716        }
717    }
718
719    if (m_sProfile.eCodec == OMX_VIDEO_CodingAVC) {
720#if 1
721        /////////////C A B A C ///A N D/////D E B L O C K I N G /////////////////
722
723        OMX_VIDEO_PARAM_AVCTYPE avcdata;
724        avcdata.nPortIndex = (OMX_U32)PORT_INDEX_OUT;
725        result = OMX_GetParameter(m_hHandle,
726                OMX_IndexParamVideoAvc,
727                &avcdata);
728        CHK(result);
729        // TEST VALUES (CHANGE FOR DIFF CONFIG's)
730        avcdata.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterEnable;
731        //      avcdata.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterDisable;
732        //    avcdata.eLoopFilterMode = OMX_VIDEO_AVCLoopFilterDisableSliceBoundary;
733        avcdata.bEntropyCodingCABAC = OMX_FALSE;
734        //   avcdata.bEntropyCodingCABAC = OMX_TRUE;
735        avcdata.nCabacInitIdc = 1;
736        ///////////////////////////////////////////////
737
738        result = OMX_SetParameter(m_hHandle,
739                OMX_IndexParamVideoAvc,
740                &avcdata);
741        CHK(result);
742
743        /////////////C A B A C ///A N D/////D E B L O C K I N G /////////////////
744#endif
745    }
746
747    OMX_VIDEO_PARAM_BITRATETYPE bitrate; // OMX_IndexParamVideoBitrate
748    bitrate.nPortIndex = (OMX_U32)PORT_INDEX_OUT;
749    result = OMX_GetParameter(m_hHandle,
750            OMX_IndexParamVideoBitrate,
751            &bitrate);
752    E("\n OMX_IndexParamVideoBitrate Get Paramter port");
753    CHK(result);
754    bitrate.eControlRate = m_sProfile.eControlRate;
755    bitrate.nTargetBitrate = m_sProfile.nBitrate;
756    result = OMX_SetParameter(m_hHandle,
757            OMX_IndexParamVideoBitrate,
758            &bitrate);
759    E("\n OMX_IndexParamVideoBitrate Set Paramter port");
760    CHK(result);
761
762    OMX_VIDEO_PARAM_PORTFORMATTYPE framerate; // OMX_IndexParamVidePortFormat
763    framerate.nPortIndex = 0;
764    result = OMX_GetParameter(m_hHandle,
765            OMX_IndexParamVideoPortFormat,
766            &framerate);
767    E("\n OMX_IndexParamVideoPortFormat Get Paramter port");
768    CHK(result);
769    FractionToQ16(framerate.xFramerate,(int) (m_sProfile.nFramerate * 2),2);
770    result = OMX_SetParameter(m_hHandle,
771            OMX_IndexParamVideoPortFormat,
772            &framerate);
773    E("\n OMX_IndexParamVideoPortFormat Set Paramter port");
774    CHK(result);
775
776#if 1
777    ///////////////////I N T R A P E R I O D ///////////////////
778
779    QOMX_VIDEO_INTRAPERIODTYPE intra;
780
781    intra.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
782    result = OMX_GetConfig(m_hHandle,
783            (OMX_INDEXTYPE) QOMX_IndexConfigVideoIntraperiod,
784            (OMX_PTR) &intra);
785
786    if (result == OMX_ErrorNone) {
787        intra.nPFrames = (OMX_U32) (2 * m_sProfile.nFramerate - 1); //setting I
788        //frame interval to
789        //2 x framerate
790        intra.nIDRPeriod = 1; //every I frame is an IDR
791        intra.nPortIndex = (OMX_U32) PORT_INDEX_OUT;
792        result = OMX_SetConfig(m_hHandle,
793                (OMX_INDEXTYPE) QOMX_IndexConfigVideoIntraperiod,
794                (OMX_PTR) &intra);
795    } else {
796        E("failed to get state", 0, 0, 0);
797    }
798
799
800    ///////////////////I N T R A P E R I O D ///////////////////
801#endif
802
803#if 1
804    ///////////////////E R R O R C O R R E C T I O N ///////////////////
805
806    ResyncMarkerType eResyncMarkerType = RESYNC_MARKER_NONE;
807    unsigned long int nResyncMarkerSpacing = 0;
808    OMX_BOOL enableHEC = OMX_FALSE;
809
810    //For Testing ONLY
811    if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) {
812        // MPEG4
813        //      eResyncMarkerType = RESYNC_MARKER_BYTE;
814        //      nResyncMarkerSpacing = 1920;
815        eResyncMarkerType = RESYNC_MARKER_MB;
816        nResyncMarkerSpacing = 50;
817        enableHEC = OMX_TRUE;
818    } else if (m_sProfile.eCodec == OMX_VIDEO_CodingH263) {
819        //H263
820        //eResyncMarkerType = RESYNC_MARKER_GOB;
821        eResyncMarkerType = RESYNC_MARKER_NONE;
822        nResyncMarkerSpacing = 0;
823    } else if (m_sProfile.eCodec == OMX_VIDEO_CodingAVC) {
824        //H264
825        //      eResyncMarkerType = RESYNC_MARKER_BYTE;
826        //      nResyncMarkerSpacing = 1920;
827
828        //nResyncMarkerSpacing sets the slice size in venc_set_multislice_cfg
829        //
830        //As of 9/24/10, it is known that the firmware has a bitstream
831        //corruption issue when RateControl and multislice are enabled for 720P
832        //So, disabling multislice for 720P when ratecontrol is enabled until
833        //the firmware issue is resolved.
834
835        if ( ( (m_sProfile.nFrameWidth == 1280) && (m_sProfile.nFrameHeight = 720) ) &&
836                (m_sProfile.eControlRate  != OMX_Video_ControlRateDisable) ) {
837            eResyncMarkerType = RESYNC_MARKER_NONE;
838            nResyncMarkerSpacing = 0;
839        } else {
840            eResyncMarkerType = RESYNC_MARKER_NONE;
841            nResyncMarkerSpacing = 0;
842        }
843    }
844
845    OMX_VIDEO_PARAM_ERRORCORRECTIONTYPE errorCorrection; //OMX_IndexParamVideoErrorCorrection
846    errorCorrection.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
847    result = OMX_GetParameter(m_hHandle,
848            (OMX_INDEXTYPE) OMX_IndexParamVideoErrorCorrection,
849            (OMX_PTR) &errorCorrection);
850
851    errorCorrection.bEnableRVLC = OMX_FALSE;
852    errorCorrection.bEnableDataPartitioning = OMX_FALSE;
853
854    if ((eResyncMarkerType == RESYNC_MARKER_BYTE) &&
855            (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4)) {
856        errorCorrection.bEnableResync = OMX_TRUE;
857        errorCorrection.nResynchMarkerSpacing = nResyncMarkerSpacing;
858        errorCorrection.bEnableHEC = enableHEC;
859    } else if ((eResyncMarkerType == RESYNC_MARKER_BYTE) &&
860            (m_sProfile.eCodec == OMX_VIDEO_CodingAVC)) {
861        errorCorrection.bEnableResync = OMX_TRUE;
862        errorCorrection.nResynchMarkerSpacing = nResyncMarkerSpacing;
863    } else if ((eResyncMarkerType == RESYNC_MARKER_GOB) &&
864            (m_sProfile.eCodec == OMX_VIDEO_CodingH263)) {
865        errorCorrection.bEnableResync = OMX_FALSE;
866        errorCorrection.nResynchMarkerSpacing = nResyncMarkerSpacing;
867        errorCorrection.bEnableDataPartitioning = OMX_TRUE;
868    }
869
870    result = OMX_SetParameter(m_hHandle,
871            (OMX_INDEXTYPE) OMX_IndexParamVideoErrorCorrection,
872            (OMX_PTR) &errorCorrection);
873    CHK(result);
874
875    if (eResyncMarkerType == RESYNC_MARKER_MB) {
876        if (m_sProfile.eCodec == OMX_VIDEO_CodingAVC) {
877            OMX_VIDEO_PARAM_AVCTYPE avcdata;
878            avcdata.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
879            result = OMX_GetParameter(m_hHandle,
880                    OMX_IndexParamVideoAvc,
881                    (OMX_PTR) &avcdata);
882            CHK(result);
883
884            if (result == OMX_ErrorNone) {
885                avcdata.nSliceHeaderSpacing = nResyncMarkerSpacing;
886                result = OMX_SetParameter(m_hHandle,
887                        OMX_IndexParamVideoAvc,
888                        (OMX_PTR) &avcdata);
889                CHK(result);
890
891            }
892        } else if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) {
893            OMX_VIDEO_PARAM_MPEG4TYPE mp4;
894            mp4.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
895            result = OMX_GetParameter(m_hHandle,
896                    OMX_IndexParamVideoMpeg4,
897                    (OMX_PTR) &mp4);
898            CHK(result);
899
900            if (result == OMX_ErrorNone) {
901                mp4.nSliceHeaderSpacing = nResyncMarkerSpacing;
902                result = OMX_SetParameter(m_hHandle,
903                        OMX_IndexParamVideoMpeg4,
904                        (OMX_PTR) &mp4);
905                CHK(result);
906            }
907        }
908    }
909
910    ///////////////////E R R O R C O R R E C T I O N ///////////////////
911#endif
912
913#if 1
914    ///////////////////I N T R A R E F R E S H///////////////////
915    bool bEnableIntraRefresh = OMX_TRUE;
916
917    if (result == OMX_ErrorNone) {
918        OMX_VIDEO_PARAM_INTRAREFRESHTYPE ir; // OMX_IndexParamVideoIntraRefresh
919        ir.nPortIndex = (OMX_U32) PORT_INDEX_OUT; // output
920        result = OMX_GetParameter(m_hHandle,
921                OMX_IndexParamVideoIntraRefresh,
922                (OMX_PTR) &ir);
923
924        if (result == OMX_ErrorNone) {
925            if (bEnableIntraRefresh) {
926                ir.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
927                ir.nCirMBs = 5;
928                result = OMX_SetParameter(m_hHandle,
929                        OMX_IndexParamVideoIntraRefresh,
930                        (OMX_PTR) &ir);
931                CHK(result);
932            }
933        }
934    }
935
936#endif
937#if 1
938    ///////////////////FRAMEPACKING DATA///////////////////
939    OMX_QCOM_FRAME_PACK_ARRANGEMENT framePackingArrangement;
940    FILE *m_pConfigFile;
941    char m_configFilename [128] = "/data/configFile.cfg";
942    memset(&framePackingArrangement, 0, sizeof(framePackingArrangement));
943    m_pConfigFile = fopen(m_configFilename, "r");
944
945    if (m_pConfigFile != NULL) {
946        //read all frame packing data
947        framePackingArrangement.nPortIndex = (OMX_U32)PORT_INDEX_OUT;
948        int totalSizeToRead = FRAME_PACK_SIZE * sizeof(OMX_U32);
949        char *pFramePack = (char *) &(framePackingArrangement.id);
950
951        while ( ( (fscanf(m_pConfigFile, "%d", pFramePack)) != EOF ) &&
952                (totalSizeToRead != 0) ) {
953            //printf("Addr = %p, Value read = %d, sizeToRead remaining=%d\n",
954            //       pFramePack, *pFramePack, totalSizeToRead);
955            pFramePack += sizeof(OMX_U32);
956            totalSizeToRead -= sizeof(OMX_U32);
957        }
958
959        //close the file.
960        fclose(m_pConfigFile);
961
962        printf("Frame Packing data from config file:\n");
963        PrintFramePackArrangement(framePackingArrangement);
964    } else {
965        D("\n Config file does not exist or could not be opened.");
966        //set the default values
967        framePackingArrangement.nPortIndex = (OMX_U32)PORT_INDEX_OUT;
968        framePackingArrangement.id = 123;
969        framePackingArrangement.cancel_flag = false;
970        framePackingArrangement.type = 3;
971        framePackingArrangement.quincunx_sampling_flag = false;
972        framePackingArrangement.content_interpretation_type = 0;
973        framePackingArrangement.spatial_flipping_flag = true;
974        framePackingArrangement.frame0_flipped_flag = false;
975        framePackingArrangement.field_views_flag = false;
976        framePackingArrangement.current_frame_is_frame0_flag = false;
977        framePackingArrangement.frame0_self_contained_flag = true;
978        framePackingArrangement.frame1_self_contained_flag = false;
979        framePackingArrangement.frame0_grid_position_x = 3;
980        framePackingArrangement.frame0_grid_position_y = 15;
981        framePackingArrangement.frame1_grid_position_x = 11;
982        framePackingArrangement.frame1_grid_position_y = 7;
983        framePackingArrangement.reserved_byte = 0;
984        framePackingArrangement.repetition_period = 16381;
985        framePackingArrangement.extension_flag = false;
986
987        printf("Frame Packing Defaults :\n");
988        PrintFramePackArrangement(framePackingArrangement);
989    }
990
991    result = OMX_SetConfig(m_hHandle,
992            (OMX_INDEXTYPE)OMX_QcomIndexConfigVideoFramePackingArrangement,
993            (OMX_PTR) &framePackingArrangement);
994    CHK(result);
995
996    //////////////////////OMX_VIDEO_PARAM_INTRAREFRESHTYPE///////////////////
997#endif
998
999    OMX_CONFIG_FRAMERATETYPE enc_framerate; // OMX_IndexConfigVideoFramerate
1000    enc_framerate.nPortIndex = (OMX_U32)PORT_INDEX_OUT;
1001    result = OMX_GetConfig(m_hHandle,
1002            OMX_IndexConfigVideoFramerate,
1003            &enc_framerate);
1004    CHK(result);
1005    FractionToQ16(enc_framerate.xEncodeFramerate,(int) (m_sProfile.nFramerate * 2),2);
1006    result = OMX_SetConfig(m_hHandle,
1007            OMX_IndexConfigVideoFramerate,
1008            &enc_framerate);
1009    CHK(result);
1010    return OMX_ErrorNone;
1011}
1012////////////////////////////////////////////////////////////////////////////////
1013void SendMessage(MsgId id, MsgData* data)
1014{
1015    pthread_mutex_lock(&m_mutex);
1016
1017    if (m_sMsgQ.size >= MAX_MSG) {
1018        E("main msg m_sMsgQ is full");
1019        return;
1020    }
1021
1022    m_sMsgQ.q[(m_sMsgQ.head + m_sMsgQ.size) % MAX_MSG].id = id;
1023
1024    if (data)
1025        m_sMsgQ.q[(m_sMsgQ.head + m_sMsgQ.size) % MAX_MSG].data = *data;
1026
1027    ++m_sMsgQ.size;
1028    pthread_cond_signal(&m_signal);
1029    pthread_mutex_unlock(&m_mutex);
1030}
1031////////////////////////////////////////////////////////////////////////////////
1032void PopMessage(Msg* msg)
1033{
1034    pthread_mutex_lock(&m_mutex);
1035
1036    while (m_sMsgQ.size == 0) {
1037        pthread_cond_wait(&m_signal, &m_mutex);
1038    }
1039
1040    *msg = m_sMsgQ.q[m_sMsgQ.head];
1041    --m_sMsgQ.size;
1042    m_sMsgQ.head = (m_sMsgQ.head + 1) % MAX_MSG;
1043    pthread_mutex_unlock(&m_mutex);
1044}
1045////////////////////////////////////////////////////////////////////////////////
1046OMX_ERRORTYPE EVT_CB(OMX_IN OMX_HANDLETYPE hComponent,
1047        OMX_IN OMX_PTR pAppData,
1048        OMX_IN OMX_EVENTTYPE eEvent,
1049        OMX_IN OMX_U32 nData1,
1050        OMX_IN OMX_U32 nData2,
1051        OMX_IN OMX_PTR pEventData)
1052{
1053#define SET_STATE(eState)                                   \
1054    case eState:                                             \
1055                                 {                                                     \
1056                                     D("" # eState " complete");                        \
1057                                     m_eState = eState;                                 \
1058                                     break;                                             \
1059                                 }
1060
1061    if (eEvent == OMX_EventCmdComplete) {
1062        if ((OMX_COMMANDTYPE) nData1 == OMX_CommandStateSet) {
1063            switch ((OMX_STATETYPE) nData2) {
1064                SET_STATE(OMX_StateLoaded);
1065                SET_STATE(OMX_StateIdle);
1066                SET_STATE(OMX_StateExecuting);
1067                SET_STATE(OMX_StateInvalid);
1068                SET_STATE(OMX_StateWaitForResources);
1069                SET_STATE(OMX_StatePause);
1070                default:
1071                E("invalid state %d", (int) nData2);
1072            }
1073        }
1074    }
1075
1076    else if (eEvent == OMX_EventError) {
1077        E("OMX_EventError");
1078    }
1079
1080    else {
1081        E("unexpected event %d", (int) eEvent);
1082    }
1083
1084    return OMX_ErrorNone;
1085}
1086////////////////////////////////////////////////////////////////////////////////
1087OMX_ERRORTYPE EBD_CB(OMX_IN OMX_HANDLETYPE hComponent,
1088        OMX_IN OMX_PTR pAppData,
1089        OMX_IN OMX_BUFFERHEADERTYPE* pBuffer)
1090{
1091    D("Got EBD callback ts=%lld", pBuffer->nTimeStamp);
1092
1093    for (int i = 0; i < num_in_buffers; i++) {
1094        // mark this buffer ready for use again
1095        if (m_pInBuffers[i] == pBuffer) {
1096
1097            D("Marked input buffer idx %d as free, buf %p", i, pBuffer->pBuffer);
1098            m_bInFrameFree[i] = OMX_TRUE;
1099            break;
1100        }
1101    }
1102
1103    if (m_eMode == MODE_LIVE_ENCODE) {
1104        CameraTest_ReleaseFrame(pBuffer->pBuffer,
1105                ((OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*)pBuffer->pAppPrivate));
1106    } else {
1107        // wake up main thread and tell it to send next frame
1108        MsgData data;
1109        data.sBitstreamData.pBuffer = pBuffer;
1110        SendMessage(MSG_ID_INPUT_FRAME_DONE,
1111                &data);
1112
1113    }
1114
1115    return OMX_ErrorNone;
1116}
1117////////////////////////////////////////////////////////////////////////////////
1118OMX_ERRORTYPE FBD_CB(OMX_OUT OMX_HANDLETYPE hComponent,
1119        OMX_OUT OMX_PTR pAppData,
1120        OMX_OUT OMX_BUFFERHEADERTYPE* pBuffer)
1121{
1122    D("Got FBD callback ts=%lld", pBuffer->nTimeStamp);
1123
1124    static long long prevTime = 0;
1125    long long currTime = GetTimeStamp();
1126
1127    m_bWatchDogKicked = true;
1128
1129    /* Empty Buffers should not be counted */
1130    if (pBuffer->nFilledLen !=0) {
1131        /* Counting Buffers supplied from OpneMax Encoder */
1132        fbd_cnt++;
1133        tot_bufsize += pBuffer->nFilledLen;
1134    }
1135
1136    if (prevTime != 0) {
1137        long long currTime = GetTimeStamp();
1138        D("FBD_DELTA = %lld\n", currTime - prevTime);
1139    }
1140
1141    prevTime = currTime;
1142
1143    if (m_eMode == MODE_PROFILE) {
1144        // if we are profiling we are not doing file I/O
1145        // so just give back to encoder
1146        if (OMX_FillThisBuffer(m_hHandle, pBuffer) != OMX_ErrorNone) {
1147            E("empty buffer failed for profiling");
1148        }
1149    } else {
1150        // wake up main thread and tell it to write to file
1151        MsgData data;
1152        data.sBitstreamData.pBuffer = pBuffer;
1153        SendMessage(MSG_ID_OUTPUT_FRAME_DONE,
1154                &data);
1155    }
1156
1157    return OMX_ErrorNone;
1158}
1159////////////////////////////////////////////////////////////////////////////////
1160OMX_ERRORTYPE VencTest_Initialize()
1161{
1162    OMX_ERRORTYPE result = OMX_ErrorNone;
1163    static OMX_CALLBACKTYPE sCallbacks = {EVT_CB, EBD_CB, FBD_CB};
1164    int i;
1165
1166    for (i = 0; i < num_in_buffers; i++) {
1167        m_pInBuffers[i] = NULL;
1168    }
1169
1170    result = OMX_Init();
1171    CHK(result);
1172
1173    if (m_sProfile.eCodec == OMX_VIDEO_CodingMPEG4) {
1174        result = OMX_GetHandle(&m_hHandle,
1175                "OMX.qcom.video.encoder.mpeg4",
1176                NULL,
1177                &sCallbacks);
1178        // CHK(result);
1179    } else if (m_sProfile.eCodec == OMX_VIDEO_CodingH263) {
1180        result = OMX_GetHandle(&m_hHandle,
1181                "OMX.qcom.video.encoder.h263",
1182                NULL,
1183                &sCallbacks);
1184        CHK(result);
1185    }
1186
1187#ifdef _MSM8974_
1188    else if (m_sProfile.eCodec == OMX_VIDEO_CodingVPX) {
1189        result = OMX_GetHandle(&m_hHandle,
1190                "OMX.qcom.video.encoder.vp8",
1191                NULL,
1192                &sCallbacks);
1193        CHK(result);
1194    }
1195
1196#endif
1197    else {
1198        result = OMX_GetHandle(&m_hHandle,
1199                "OMX.qcom.video.encoder.avc",
1200                NULL,
1201                &sCallbacks);
1202        CHK(result);
1203    }
1204
1205
1206    result = ConfigureEncoder();
1207    CHK(result);
1208
1209    return result;
1210}
1211
1212////////////////////////////////////////////////////////////////////////////////
1213OMX_ERRORTYPE VencTest_RegisterYUVBuffer(OMX_BUFFERHEADERTYPE** ppBufferHeader,
1214        OMX_U8 *pBuffer,
1215        OMX_PTR pAppPrivate)
1216{
1217    OMX_ERRORTYPE result = OMX_ErrorNone;
1218#if 0
1219    D("register buffer");
1220
1221    if ((result = OMX_AllocateBuffer(m_hHandle,
1222                    ppBufferHeader,
1223                    (OMX_U32) PORT_INDEX_IN,
1224                    pAppPrivate,
1225                    m_sProfile.nFrameBytes
1226                    )) != OMX_ErrorNone) {
1227        E("use buffer failed");
1228    } else {
1229        E("Allocate Buffer Success %x", (*ppBufferHeader)->pBuffer);
1230    }
1231
1232#endif
1233    D("register buffer");
1234    D("Calling UseBuffer for Input port");
1235
1236    if ((result = OMX_UseBuffer(m_hHandle,
1237                    ppBufferHeader,
1238                    (OMX_U32) PORT_INDEX_IN,
1239                    pAppPrivate,
1240                    m_sProfile.nFrameBytes,
1241                    pBuffer)) != OMX_ErrorNone) {
1242        E("use buffer failed");
1243    }
1244
1245    return result;
1246}
1247////////////////////////////////////////////////////////////////////////////////
1248OMX_ERRORTYPE VencTest_EncodeFrame(void* pYUVBuff,
1249        long long nTimeStamp)
1250{
1251    OMX_ERRORTYPE result = OMX_ErrorUndefined;
1252    D("calling OMX empty this buffer");
1253
1254    for (int i = 0; i < num_in_buffers; i++) {
1255        if (pYUVBuff == m_pInBuffers[i]->pBuffer) {
1256            m_pInBuffers[i]->nTimeStamp = nTimeStamp;
1257            D("Sending Buffer - %x", m_pInBuffers[i]->pBuffer);
1258            result = OMX_EmptyThisBuffer(m_hHandle,
1259                    m_pInBuffers[i]);
1260
1261            /* Counting Buffers supplied to OpenMax Encoder */
1262            if (OMX_ErrorNone == result)
1263                ebd_cnt++;
1264
1265            CHK(result);
1266            break;
1267        }
1268    }
1269
1270    return result;
1271}
1272////////////////////////////////////////////////////////////////////////////////
1273OMX_ERRORTYPE VencTest_Exit(void)
1274{
1275    int i;
1276    OMX_ERRORTYPE result = OMX_ErrorNone;
1277    D("trying to exit venc");
1278
1279    D("going to idle state");
1280    SetState(OMX_StateIdle);
1281
1282
1283    D("going to loaded state");
1284    //SetState(OMX_StateLoaded);
1285    OMX_SendCommand(m_hHandle,
1286            OMX_CommandStateSet,
1287            (OMX_U32) OMX_StateLoaded,
1288            NULL);
1289
1290    for (i = 0; i < num_in_buffers; i++) {
1291        D("free buffer");
1292
1293        if (m_pInBuffers[i]->pBuffer) {
1294            // free(m_pInBuffers[i]->pBuffer);
1295            result = OMX_FreeBuffer(m_hHandle,
1296                    PORT_INDEX_IN,
1297                    m_pInBuffers[i]);
1298            CHK(result);
1299        } else {
1300            E("buffer %d is null", i);
1301            result = OMX_ErrorUndefined;
1302            CHK(result);
1303        }
1304    }
1305
1306    for (i = 0; i < num_out_buffers; i++) {
1307        D("free buffer");
1308
1309        if (m_pOutBuffers[i]->pBuffer) {
1310            free(m_pOutBuffers[i]->pBuffer);
1311            result = OMX_FreeBuffer(m_hHandle,
1312                    PORT_INDEX_OUT,
1313                    m_pOutBuffers[i]);
1314            CHK(result);
1315
1316        } else {
1317            E("buffer %d is null", i);
1318            result = OMX_ErrorUndefined;
1319            CHK(result);
1320        }
1321    }
1322
1323    while (m_eState != OMX_StateLoaded) {
1324        sleep(1);
1325    }
1326
1327    D("component_deinit...");
1328    result = OMX_Deinit();
1329    CHK(result);
1330
1331    D("venc is exiting...");
1332    return result;
1333}
1334////////////////////////////////////////////////////////////////////////////////
1335
1336void VencTest_ReadDynamicConfigMsg()
1337{
1338    char frame_n[8], config[16], param[8];
1339    char *dest = frame_n;
1340    bool end = false;
1341    int cntr, nparam = 0;
1342    memset(&dynamic_config, 0, sizeof(struct DynamicConfig));
1343
1344    do {
1345        cntr = -1;
1346
1347        do {
1348            dest[++cntr] = fgetc(m_pDynConfFile);
1349        } while (dest[cntr] != ' ' && dest[cntr] != '\t' && dest[cntr] != '\n' && dest[cntr] != '\r' && !feof(m_pDynConfFile));
1350
1351        if (dest[cntr] == '\n' || dest[cntr] == '\r')
1352            end = true;
1353
1354        dest[cntr] = NULL;
1355
1356        if (dest == frame_n)
1357            dest = config;
1358        else if (dest == config)
1359            dest = param;
1360        else
1361            end = true;
1362
1363        nparam++;
1364    } while (!end && !feof(m_pDynConfFile));
1365
1366    if (nparam > 1) {
1367        dynamic_config.pending = true;
1368        dynamic_config.frame_num = atoi(frame_n);
1369
1370        if (!strcmp(config, "bitrate")) {
1371            dynamic_config.config_param = OMX_IndexConfigVideoBitrate;
1372            dynamic_config.config_data.bitrate.nPortIndex = PORT_INDEX_OUT;
1373            dynamic_config.config_data.bitrate.nEncodeBitrate = strtoul(param, NULL, 10);
1374        } else if (!strcmp(config, "framerate")) {
1375            dynamic_config.config_param = OMX_IndexConfigVideoFramerate;
1376            dynamic_config.config_data.framerate.nPortIndex = PORT_INDEX_OUT;
1377            dynamic_config.config_data.f_framerate = atof(param);
1378        } else if (!strcmp(config, "iperiod")) {
1379            dynamic_config.config_param = (OMX_INDEXTYPE)QOMX_IndexConfigVideoIntraperiod;
1380            dynamic_config.config_data.intraperiod.nPortIndex = PORT_INDEX_OUT;
1381            dynamic_config.config_data.intraperiod.nPFrames = strtoul(param, NULL, 10) - 1;
1382            dynamic_config.config_data.intraperiod.nIDRPeriod = 1; // This value is ignored in OMX component
1383        } else if (!strcmp(config, "ivoprefresh")) {
1384            dynamic_config.config_param = OMX_IndexConfigVideoIntraVOPRefresh;
1385            dynamic_config.config_data.intravoprefresh.nPortIndex = PORT_INDEX_OUT;
1386            dynamic_config.config_data.intravoprefresh.IntraRefreshVOP = OMX_TRUE;
1387        } else if (!strcmp(config, "rotation")) {
1388            dynamic_config.config_param = OMX_IndexConfigCommonRotate;
1389            dynamic_config.config_data.rotation.nPortIndex = PORT_INDEX_OUT;
1390            dynamic_config.config_data.rotation.nRotation = strtoul(param, NULL, 10);
1391        } else {
1392            E("UNKNOWN CONFIG PARAMETER: %s!", config);
1393            dynamic_config.pending = false;
1394        }
1395    } else if (feof(m_pDynConfFile)) {
1396        fclose(m_pDynConfFile);
1397        m_pDynConfFile = NULL;
1398    }
1399}
1400
1401void VencTest_ProcessDynamicConfigurationFile()
1402{
1403    do {
1404        if (dynamic_config.pending) {
1405            if (m_nFrameIn == dynamic_config.frame_num) {
1406                if (dynamic_config.config_param == OMX_IndexConfigVideoFramerate) {
1407                    m_sProfile.nFramerate = dynamic_config.config_data.f_framerate;
1408                    FractionToQ16(dynamic_config.config_data.framerate.xEncodeFramerate,
1409                            (int)(m_sProfile.nFramerate * 2), 2);
1410                }
1411
1412                if (OMX_SetConfig(m_hHandle, dynamic_config.config_param,
1413                            &dynamic_config.config_data) != OMX_ErrorNone)
1414                    E("ERROR: Setting dynamic config to OMX param[0x%x]", dynamic_config.config_param);
1415
1416                dynamic_config.pending = false;
1417            } else if (m_nFrameIn > dynamic_config.frame_num) {
1418                E("WARNING: Config change requested in passed frame(%d)", dynamic_config.frame_num);
1419                dynamic_config.pending = false;
1420            }
1421        }
1422
1423        if (!dynamic_config.pending)
1424            VencTest_ReadDynamicConfigMsg();
1425    } while (!dynamic_config.pending && m_pDynConfFile);
1426}
1427
1428////////////////////////////////////////////////////////////////////////////////
1429OMX_ERRORTYPE VencTest_ReadAndEmpty(OMX_BUFFERHEADERTYPE* pYUVBuffer)
1430{
1431    OMX_ERRORTYPE result = OMX_ErrorNone;
1432#ifdef T_ARM
1433#if defined(MAX_RES_720P) && !defined(_MSM8974_)
1434
1435    if (read(m_nInFd,
1436                pYUVBuffer->pBuffer,
1437                m_sProfile.nFrameBytes) != m_sProfile.nFrameBytes) {
1438        return OMX_ErrorUndefined;
1439    }
1440
1441#elif _MSM8974_
1442    int i, lscanl, lstride, cscanl, cstride, height, width;
1443    int bytes = 0, read_bytes = 0;
1444    OMX_U8 *yuv = pYUVBuffer->pBuffer;
1445    height = m_sProfile.nFrameHeight;
1446    width = m_sProfile.nFrameWidth;
1447    lstride = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
1448    lscanl = VENUS_Y_SCANLINES(COLOR_FMT_NV12, height);
1449    cstride = VENUS_UV_STRIDE(COLOR_FMT_NV12, width);
1450    cscanl = VENUS_UV_SCANLINES(COLOR_FMT_NV12, height);
1451
1452    for (i = 0; i < height; i++) {
1453        bytes = read(m_nInFd, yuv, width);
1454
1455        if (bytes != width) {
1456            E("read failed: %d != %d\n", read, width);
1457            return OMX_ErrorUndefined;
1458        }
1459
1460        read_bytes += bytes;
1461        yuv += lstride;
1462    }
1463
1464    yuv = pYUVBuffer->pBuffer + (lscanl * lstride);
1465
1466    for (i = 0; i < ((height + 1) >> 1); i++) {
1467        bytes = read(m_nInFd, yuv, width);
1468
1469        if (bytes != width) {
1470            E("read failed: %d != %d\n", read, width);
1471            return OMX_ErrorUndefined;
1472        }
1473
1474        read_bytes += bytes;
1475        yuv += cstride;
1476    }
1477
1478    m_sProfile.nFrameRead = VENUS_BUFFER_SIZE(COLOR_FMT_NV12, width, height);
1479    E("\n\nActual read bytes: %d, NV12 buffer size: %d\n\n\n", read_bytes, m_sProfile.nFrameRead);
1480#else
1481    OMX_U32 bytestoread = m_sProfile.nFrameWidth*m_sProfile.nFrameHeight;
1482
1483    // read Y first
1484    if (read(m_nInFd,
1485                pYUVBuffer->pBuffer,
1486                bytestoread) != bytestoread)
1487        return OMX_ErrorUndefined;
1488
1489    // check alignment for offset to C
1490    OMX_U32 offset_to_c = m_sProfile.nFrameWidth * m_sProfile.nFrameHeight;
1491
1492    const OMX_U32 C_2K = (1024*2),
1493          MASK_2K = C_2K-1,
1494          IMASK_2K = ~MASK_2K;
1495
1496    if (offset_to_c & MASK_2K) {
1497        // offset to C is not 2k aligned, adjustment is required
1498        offset_to_c = (offset_to_c & IMASK_2K) + C_2K;
1499    }
1500
1501    bytestoread = m_sProfile.nFrameWidth*m_sProfile.nFrameHeight/2;
1502
1503    // read C
1504    if (read(m_nInFd,
1505                pYUVBuffer->pBuffer + offset_to_c,
1506                bytestoread)!= bytestoread)
1507        return OMX_ErrorUndefined;
1508
1509#endif
1510#else
1511    {
1512        char * pInputbuf = (char *)(pYUVBuffer->pBuffer) ;
1513        read(m_nInFd,pInputbuf,m_sProfile.nFrameBytes) ;
1514
1515    }
1516#endif
1517
1518    if (m_pDynConfFile)
1519        VencTest_ProcessDynamicConfigurationFile();
1520
1521    D("about to call VencTest_EncodeFrame...");
1522    pthread_mutex_lock(&m_mutex);
1523    ++m_nFrameIn;
1524#ifdef _MSM8974_
1525    pYUVBuffer->nFilledLen = m_sProfile.nFrameRead;
1526#else
1527    pYUVBuffer->nFilledLen = m_sProfile.nFrameBytes;
1528#endif
1529    D("Called Buffer with Data filled length %d",pYUVBuffer->nFilledLen);
1530
1531    result = VencTest_EncodeFrame(pYUVBuffer->pBuffer,
1532            m_nTimeStamp);
1533
1534    m_nTimeStamp += (1000000) / m_sProfile.nFramerate;
1535    CHK(result);
1536    pthread_mutex_unlock(&m_mutex);
1537    return result;
1538}
1539////////////////////////////////////////////////////////////////////////////////
1540void PreviewCallback(int nFD,
1541        int nOffset,
1542        void* pPhys,
1543        void* pVirt,
1544        long long nTimeStamp)
1545{
1546
1547    D("================= preview frame %d, phys=0x%x, nTimeStamp(millis)=%lld",
1548            m_nFrameIn+1, pPhys, (nTimeStamp / 1000));
1549
1550    if (m_nFrameIn == m_nFramePlay &&
1551            m_nFramePlay != 0) {
1552        // we will stop camera after last frame is encoded.
1553        // for now just ignore input frames
1554
1555        CameraTest_ReleaseFrame(pPhys, pVirt);
1556        return;
1557    }
1558
1559    // see if we should stop
1560    pthread_mutex_lock(&m_mutex);
1561    ++m_nFrameIn;
1562    pthread_mutex_unlock(&m_mutex);
1563
1564
1565    if (m_eMode == MODE_LIVE_ENCODE) {
1566
1567        OMX_ERRORTYPE result;
1568
1569        // register new camera buffers with encoder
1570        int i;
1571
1572        for (i = 0; i < num_in_buffers; i++) {
1573            if (m_pInBuffers[i] != NULL &&
1574                    m_pInBuffers[i]->pBuffer == pPhys) {
1575                break;
1576            } else if (m_pInBuffers[i] == NULL) {
1577                D("registering buffer...");
1578                result = VencTest_RegisterYUVBuffer(&m_pInBuffers[i],
1579                        (OMX_U8*) pPhys,
1580                        (OMX_PTR) pVirt); // store virt in app private field
1581                D("register done");
1582                CHK(result);
1583                break;
1584            }
1585        }
1586
1587        if (i == num_in_buffers) {
1588            E("There are more camera buffers than we thought");
1589            CHK(1);
1590        }
1591
1592        // encode the yuv frame
1593
1594        D("StartEncodeTime=%lld", GetTimeStamp());
1595        result = VencTest_EncodeFrame(pPhys,
1596                nTimeStamp);
1597        CHK(result);
1598        // FBTest_DisplayImage(nFD, nOffset);
1599    } else {
1600        // FBTest_DisplayImage(nFD, nOffset);
1601        CameraTest_ReleaseFrame(pPhys, pVirt);
1602    }
1603}
1604////////////////////////////////////////////////////////////////////////////////
1605void usage(char* filename)
1606{
1607    char* fname = strrchr(filename, (int) '/');
1608    fname = (fname == NULL) ? filename : fname;
1609
1610    fprintf(stderr, "usage: %s LIVE <QCIF|QVGA> <MP4|H263> <FPS> <BITRATE> <NFRAMES> <OUTFILE>\n", fname);
1611    fprintf(stderr, "usage: %s FILE <QCIF|QVGA> <MP4|H263 <FPS> <BITRATE> <NFRAMES> <INFILE> <OUTFILE> ", fname);
1612    fprintf(stderr, "<Dynamic config file - opt> <Rate Control - opt> <AVC Slice Mode - opt>\n", fname);
1613    fprintf(stderr, "usage: %s PROFILE <QCIF|QVGA> <MP4|H263 <FPS> <BITRATE> <NFRAMES> <INFILE>\n", fname);
1614    fprintf(stderr, "usage: %s PREVIEW <QCIF|QVGA> <FPS> <NFRAMES>\n", fname);
1615    fprintf(stderr, "usage: %s DISPLAY <QCIF|QVGA> <FPS> <NFRAMES> <INFILE>\n", fname);
1616    fprintf(stderr, "\n       BITRATE - bitrate in kbps\n");
1617    fprintf(stderr, "       FPS - frames per second\n");
1618    fprintf(stderr, "       NFRAMES - number of frames to play, 0 for infinite\n");
1619    fprintf(stderr, "       RateControl (Values 0 - 4 for RC_OFF, RC_CBR_CFR, RC_CBR_VFR, RC_VBR_CFR, RC_VBR_VFR\n");
1620    exit(1);
1621}
1622
1623bool parseWxH(char *str, OMX_U32 *width, OMX_U32 *height)
1624{
1625    bool parseOK = false;
1626    const char delimiters[] = " x*,";
1627    char *token, *dupstr, *temp;
1628    OMX_U32 w, h;
1629
1630    dupstr = strdup(str);
1631    token = strtok_r(dupstr, delimiters, &temp);
1632
1633    if (token) {
1634        w = strtoul(token, NULL, 10);
1635        token = strtok_r(NULL, delimiters, &temp);
1636
1637        if (token) {
1638            h = strtoul(token, NULL, 10);
1639
1640            if (w != ULONG_MAX && h != ULONG_MAX) {
1641#ifdef MAX_RES_720P
1642
1643                if ((w * h >> 8) <= 3600) {
1644                    parseOK = true;
1645                    *width = w;
1646                    *height = h;
1647                }
1648
1649#else
1650
1651                if ((w * h >> 8) <= 8160) {
1652                    parseOK = true;
1653                    *width = w;
1654                    *height = h;
1655                }
1656
1657#endif
1658                else
1659                    E("\nInvalid dimensions %dx%d",w,h);
1660            }
1661        }
1662    }
1663
1664    free(dupstr);
1665    return parseOK;
1666}
1667
1668////////////////////////////////////////////////////////////////////////////////
1669void parseArgs(int argc, char** argv)
1670{
1671    int dyn_file_arg = argc;
1672
1673    if (argc == 1) {
1674        usage(argv[0]);
1675    } else if (strcmp("PREVIEW", argv[1]) == 0 ||
1676            strcmp("preview", argv[1]) == 0) {
1677        m_eMode = MODE_PREVIEW;
1678
1679        if (argc != 5) {
1680            usage(argv[0]);
1681        }
1682    } else if (strcmp("DISPLAY", argv[1]) == 0 ||
1683            strcmp("display", argv[1]) == 0) {
1684        m_eMode = MODE_DISPLAY;
1685
1686        if (argc != 6) {
1687            usage(argv[0]);
1688        }
1689
1690        m_sProfile.cInFileName = argv[5];
1691        m_sProfile.cOutFileName = NULL;
1692    } else if (strcmp("LIVE", argv[1]) == 0 ||
1693            strcmp("live", argv[1]) == 0) {//263
1694        m_eMode = MODE_LIVE_ENCODE;
1695
1696        if (argc != 8) {
1697            usage(argv[0]);
1698        }
1699
1700        m_sProfile.cInFileName = NULL;
1701        m_sProfile.cOutFileName = argv[7];
1702    } else if (strcmp("FILE", argv[1]) == 0 ||
1703            strcmp("file", argv[1]) == 0) {//263
1704        m_eMode = MODE_FILE_ENCODE;
1705
1706        if (argc < 9 || argc > 13) {
1707            usage(argv[0]);
1708        } else {
1709            if (argc > 9)
1710                dyn_file_arg = 9;
1711
1712            if (argc > 10) {
1713                m_sProfile.eControlRate = OMX_Video_ControlRateVariable;
1714                int RC = atoi(argv[10]);
1715
1716                switch (RC) {
1717                    case 0:
1718                        m_sProfile.eControlRate  = OMX_Video_ControlRateDisable ;//VENC_RC_NONE
1719                        break;
1720                    case 1:
1721                        m_sProfile.eControlRate  = OMX_Video_ControlRateConstant;//VENC_RC_CBR_CFR
1722                        break;
1723
1724                    case 2:
1725                        m_sProfile.eControlRate  = OMX_Video_ControlRateConstantSkipFrames;//VENC_RC_CBR_VFR
1726                        break;
1727
1728                    case 3:
1729                        m_sProfile.eControlRate  =OMX_Video_ControlRateVariable ;//VENC_RC_VBR_CFR
1730                        break;
1731
1732                    case 4:
1733                        m_sProfile.eControlRate  = OMX_Video_ControlRateVariableSkipFrames;//VENC_RC_VBR_VFR
1734                        break;
1735
1736                    default:
1737                        E("invalid rate control selection");
1738                        m_sProfile.eControlRate = OMX_Video_ControlRateVariable; //VENC_RC_VBR_CFR
1739                        break;
1740                }
1741            }
1742
1743            if (argc > 11) {
1744                int profile_argi = 11;
1745
1746                if (!strcmp(argv[3], "H264") || !strcmp(argv[3], "h264")) {
1747                    profile_argi = 12;
1748                    D("\nSetting AVCSliceMode ... ");
1749                    int AVCSliceMode = atoi(argv[11]);
1750
1751                    switch (AVCSliceMode) {
1752                        case 0:
1753                            m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault;
1754                            break;
1755
1756                        case 1:
1757                            m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCMBSlice;
1758                            break;
1759
1760                        case 2:
1761                            m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCByteSlice;
1762                            break;
1763
1764                        default:
1765                            E("invalid Slice Mode");
1766                            m_sProfile.eSliceMode = OMX_VIDEO_SLICEMODE_AVCDefault;
1767                            break;
1768                    }
1769                }
1770
1771                if (profile_argi < argc) {
1772                    if (!strncmp(argv[profile_argi], "0x", 2) || !strncmp(argv[profile_argi], "0x", 2)) {
1773                        m_sProfile.nUserProfile = strtoul(argv[profile_argi], NULL, 16);
1774                    } else {
1775                        m_sProfile.nUserProfile = strtoul(argv[profile_argi], NULL, 10);
1776                    }
1777
1778                    if (!m_sProfile.nUserProfile || m_sProfile.nUserProfile == ULONG_MAX) {
1779                        E("invalid specified Profile %s, using default", argv[profile_argi]);
1780                        m_sProfile.nUserProfile = 0;
1781                    }
1782                }
1783            }
1784        }
1785
1786        m_sProfile.cInFileName = argv[7];
1787        m_sProfile.cOutFileName = argv[8];
1788    } else if (strcmp("PROFILE", argv[1]) == 0 ||
1789            strcmp("profile", argv[1]) == 0) {//263
1790        m_eMode = MODE_PROFILE;
1791
1792        if (argc != 8) {
1793            usage(argv[0]);
1794        }
1795
1796        m_sProfile.cInFileName = argv[7];
1797        m_sProfile.cOutFileName = NULL;
1798    } else {
1799        usage(argv[0]);
1800    }
1801
1802
1803    if (strcmp("QCIF", argv[2]) == 0 ||
1804            strcmp("qcif", argv[2]) == 0) {
1805        m_sProfile.nFrameWidth = 176;
1806        m_sProfile.nFrameHeight = 144;
1807        m_sProfile.nFrameBytes = 176*144*3/2;
1808        m_sProfile.eLevel = OMX_VIDEO_MPEG4Level0;
1809    } else if (strcmp("QVGA", argv[2]) == 0 ||
1810            strcmp("qvga", argv[2]) == 0) {
1811        m_sProfile.nFrameWidth = 320;
1812        m_sProfile.nFrameHeight = 240;
1813        m_sProfile.nFrameBytes = 320*240*3/2;
1814        m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
1815    }
1816
1817
1818    else if (strcmp("VGA", argv[2]) == 0 ||
1819            strcmp("vga", argv[2]) == 0) {
1820        m_sProfile.nFrameWidth = 640;
1821        m_sProfile.nFrameHeight = 480;
1822        m_sProfile.nFrameBytes = 640*480*3/2;
1823        m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
1824    }
1825
1826    else if (strcmp("WVGA", argv[2]) == 0 ||
1827            strcmp("wvga", argv[2]) == 0) {
1828        m_sProfile.nFrameWidth = 800;
1829        m_sProfile.nFrameHeight = 480;
1830        m_sProfile.nFrameBytes = 800*480*3/2;
1831        m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
1832    } else if (strcmp("CIF", argv[2]) == 0 ||
1833            strcmp("cif", argv[2]) == 0) {
1834        m_sProfile.nFrameWidth = 352;
1835        m_sProfile.nFrameHeight = 288;
1836        m_sProfile.nFrameBytes = 352*288*3/2;
1837        m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
1838    } else if (strcmp("720", argv[2]) == 0) {
1839        m_sProfile.nFrameWidth = 1280;
1840        m_sProfile.nFrameHeight = 720;
1841        m_sProfile.nFrameBytes = 720*1280*3/2;
1842        m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
1843    } else if (strcmp("1080", argv[2]) == 0) {
1844        m_sProfile.nFrameWidth = 1920;
1845        m_sProfile.nFrameHeight = 1080;
1846        m_sProfile.nFrameBytes = 1920*1080*3/2;
1847        m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
1848    }
1849
1850#ifdef _MSM8974_
1851    else if (strcmp("4K2K", argv[2]) == 0) {
1852        m_sProfile.nFrameWidth = 4096;
1853        m_sProfile.nFrameHeight = 2160;
1854        m_sProfile.nFrameBytes = 4096*2160*3/2;
1855        m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
1856    } else if (strcmp("2160P", argv[2]) == 0) {
1857        m_sProfile.nFrameWidth = 3840;
1858        m_sProfile.nFrameHeight = 2160;
1859        m_sProfile.nFrameBytes = 3840*2160*3/2;
1860        m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
1861    }
1862
1863#endif
1864    else if (parseWxH(argv[2], &m_sProfile.nFrameWidth, &m_sProfile.nFrameHeight)) {
1865        m_sProfile.nFrameBytes = m_sProfile.nFrameWidth*m_sProfile.nFrameHeight*3/2;
1866        m_sProfile.eLevel = OMX_VIDEO_MPEG4Level1;
1867    } else {
1868        usage(argv[0]);
1869    }
1870
1871#ifdef _MSM8974_
1872    m_sProfile.nFramestride =  (m_sProfile.nFrameWidth + 31) & (~31);
1873    m_sProfile.nFrameScanlines = (m_sProfile.nFrameHeight + 31) & (~31);
1874    m_sProfile.nFrameBytes = ((m_sProfile.nFramestride * m_sProfile.nFrameScanlines * 3/2) + 4095) & (~4095);
1875    m_sProfile.nFrameRead = m_sProfile.nFramestride * m_sProfile.nFrameScanlines * 3/2;
1876#endif
1877
1878    if (m_eMode == MODE_DISPLAY ||
1879            m_eMode == MODE_PREVIEW) {
1880        m_sProfile.nFramerate = atof(argv[3]);
1881        m_nFramePlay = atoi(argv[4]);
1882
1883    } else if (m_eMode == MODE_LIVE_ENCODE ||
1884            m_eMode == MODE_FILE_ENCODE ||
1885            m_eMode == MODE_PROFILE) {
1886        if ((!strcmp(argv[3], "MP4")) || (!strcmp(argv[3], "mp4"))) {
1887            m_sProfile.eCodec = OMX_VIDEO_CodingMPEG4;
1888        } else if ((!strcmp(argv[3], "H263")) || (!strcmp(argv[3], "h263"))) {
1889            m_sProfile.eCodec = OMX_VIDEO_CodingH263;
1890        } else if ((!strcmp(argv[3], "H264")) || (!strcmp(argv[3], "h264"))) {
1891            m_sProfile.eCodec = OMX_VIDEO_CodingAVC;
1892        }
1893
1894#ifdef _MSM8974_
1895        else if ((!strcmp(argv[3], "VP8")) || (!strcmp(argv[3], "vp8"))) {
1896            m_sProfile.eCodec = OMX_VIDEO_CodingVPX;
1897        }
1898
1899#endif
1900        else {
1901            usage(argv[0]);
1902        }
1903
1904        m_sProfile.nFramerate = atof(argv[4]);
1905        m_sProfile.nBitrate = atoi(argv[5]);
1906        //      m_sProfile.eControlRate = OMX_Video_ControlRateVariable;
1907        m_nFramePlay = atoi(argv[6]);
1908
1909        if (dyn_file_arg < argc) {
1910            m_pDynConfFile = fopen(argv[dyn_file_arg], "r");
1911
1912            if (!m_pDynConfFile)
1913                E("ERROR: Cannot open dynamic config file: %s", argv[dyn_file_arg]);
1914            else {
1915                memset(&dynamic_config, 0, sizeof(struct DynamicConfig));
1916            }
1917        }
1918    }
1919}
1920
1921void* Watchdog(void* data)
1922{
1923    while (1) {
1924        sleep(1000);
1925
1926        if (m_bWatchDogKicked == true)
1927            m_bWatchDogKicked = false;
1928        else
1929            E("watchdog has not been kicked. we may have a deadlock");
1930    }
1931
1932    return NULL;
1933}
1934
1935int main(int argc, char** argv)
1936{
1937    OMX_U8* pvirt = NULL;
1938    int result;
1939    float enc_time_sec=0.0,enc_time_usec=0.0;
1940
1941    m_nInFd = -1;
1942    m_nOutFd = -1;
1943    m_nTimeStamp = 0;
1944    m_nFrameIn = 0;
1945    m_nFrameOut = 0;
1946
1947    memset(&m_sMsgQ, 0, sizeof(MsgQ));
1948    memset(&m_sProfile, 0, sizeof(m_sProfile));
1949    parseArgs(argc, argv);
1950
1951    D("fps=%f, bitrate=%u, width=%u, height=%u, frame bytes=%u",
1952            m_sProfile.nFramerate,
1953            m_sProfile.nBitrate,
1954            m_sProfile.nFrameWidth,
1955            m_sProfile.nFrameHeight,
1956            m_sProfile.nFrameBytes);
1957#ifdef _MSM8974_
1958    D("Frame stride=%u, scanlines=%u, read=%u",
1959            m_sProfile.nFramestride,
1960            m_sProfile.nFrameScanlines,
1961            m_sProfile.nFrameRead);
1962#endif
1963
1964
1965    //if (m_eMode != MODE_PREVIEW && m_eMode != MODE_DISPLAY)
1966    //{
1967    // pthread_t wd;
1968    // pthread_create(&wd, NULL, Watchdog, NULL);
1969    //}
1970
1971    for (int x = 0; x < num_in_buffers; x++) {
1972        // mark all buffers as ready to use
1973        m_bInFrameFree[x] = OMX_TRUE;
1974    }
1975
1976
1977    if (m_eMode != MODE_PROFILE) {
1978#if T_ARM
1979        m_nOutFd = open(m_sProfile.cOutFileName, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
1980#else
1981        m_nOutFd = open(m_sProfile.cOutFileName,0);
1982#endif
1983
1984        if (m_nOutFd < 0) {
1985            E("could not open output file %s", m_sProfile.cOutFileName);
1986            CHK(1);
1987        }
1988    }
1989
1990    pthread_mutex_init(&m_mutex, NULL);
1991    pthread_cond_init(&m_signal, NULL);
1992
1993    if (m_eMode != MODE_PREVIEW) {
1994        VencTest_Initialize();
1995    }
1996
1997    ////////////////////////////////////////
1998    // Camera + Encode
1999    ////////////////////////////////////////
2000    if (m_eMode == MODE_LIVE_ENCODE) {
2001        CameraTest_Initialize(m_sProfile.nFramerate,
2002                m_sProfile.nFrameWidth,
2003                m_sProfile.nFrameHeight,
2004                PreviewCallback);
2005        CameraTest_Run();
2006    }
2007
2008    if (m_eMode == MODE_FILE_ENCODE ||
2009            m_eMode == MODE_PROFILE) {
2010        int i;
2011#if T_ARM
2012        m_nInFd = open(m_sProfile.cInFileName, O_RDONLY);
2013#else
2014        m_nInFd = open(m_sProfile.cInFileName,1);
2015#endif
2016
2017        if (m_nInFd < 0) {
2018            E("could not open input file");
2019            CHK(1);
2020
2021        }
2022
2023        D("going to idle state");
2024        //SetState(OMX_StateIdle);
2025        OMX_SendCommand(m_hHandle,
2026                OMX_CommandStateSet,
2027                (OMX_U32) OMX_StateIdle,
2028                NULL);
2029
2030        OMX_PARAM_PORTDEFINITIONTYPE portDef;
2031
2032        portDef.nPortIndex = 0;
2033        result = OMX_GetParameter(m_hHandle, OMX_IndexParamPortDefinition, &portDef);
2034        CHK(result);
2035
2036        D("allocating Input buffers");
2037        num_in_buffers = portDef.nBufferCountActual;
2038
2039        for (i = 0; i < portDef.nBufferCountActual; i++) {
2040            OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO* pMem = new OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO;
2041            pvirt = (OMX_U8*)PmemMalloc(pMem, m_sProfile.nFrameBytes);
2042
2043            if (pvirt == NULL) {
2044                CHK(1);
2045            }
2046
2047            result = VencTest_RegisterYUVBuffer(&m_pInBuffers[i],
2048                    (OMX_U8*) pvirt,
2049                    (OMX_PTR) pMem);
2050            CHK(result);
2051        }
2052    } else if (m_eMode == MODE_LIVE_ENCODE) {
2053        D("going to idle state");
2054        //SetState(OMX_StateIdle);
2055        OMX_SendCommand(m_hHandle,
2056                OMX_CommandStateSet,
2057                (OMX_U32) OMX_StateIdle,
2058                NULL);
2059    }
2060
2061    int i;
2062    OMX_PARAM_PORTDEFINITIONTYPE portDef;
2063
2064    portDef.nPortIndex = 1;
2065    result = OMX_GetParameter(m_hHandle, OMX_IndexParamPortDefinition, &portDef);
2066    CHK(result);
2067
2068    D("allocating & calling usebuffer for Output port");
2069    num_out_buffers = portDef.nBufferCountActual;
2070
2071    for (i = 0; i < portDef.nBufferCountActual; i++) {
2072        void* pBuff;
2073
2074        pBuff = malloc(portDef.nBufferSize);
2075        D("portDef.nBufferSize = %d ",portDef.nBufferSize);
2076        result = OMX_UseBuffer(m_hHandle,
2077                &m_pOutBuffers[i],
2078                (OMX_U32) PORT_INDEX_OUT,
2079                NULL,
2080                portDef.nBufferSize,
2081                (OMX_U8*) pBuff);
2082        CHK(result);
2083    }
2084
2085    D("allocate done");
2086
2087    // D("Going to state " # eState"...");
2088
2089    while (m_eState != OMX_StateIdle) {
2090        sleep(1);
2091    }
2092
2093    //D("Now in state " # eState);
2094
2095
2096    D("going to executing state");
2097    SetState(OMX_StateExecuting);
2098
2099    for (i = 0; i < num_out_buffers; i++) {
2100        D("filling buffer %d", i);
2101        result = OMX_FillThisBuffer(m_hHandle, m_pOutBuffers[i]);
2102        //sleep(1000);
2103        CHK(result);
2104    }
2105
2106    if (m_eMode == MODE_FILE_ENCODE) {
2107        // encode the first frame to kick off the whole process
2108        VencTest_ReadAndEmpty(m_pInBuffers[0]);
2109        //  FBTest_DisplayImage(((PmemBuffer*) m_pInBuffers[0]->pAppPrivate)->fd,0);
2110    }
2111
2112    if (m_eMode == MODE_PROFILE) {
2113        int i;
2114
2115        // read several frames into memory
2116        D("reading frames into memory");
2117
2118        for (i = 0; i < num_in_buffers; i++) {
2119            D("[%d] address 0x%x",i, m_pInBuffers[i]->pBuffer);
2120#ifdef MAX_RES_720P
2121            read(m_nInFd,
2122                    m_pInBuffers[i]->pBuffer,
2123                    m_sProfile.nFrameBytes);
2124#else
2125            // read Y first
2126            read(m_nInFd,
2127                    m_pInBuffers[i]->pBuffer,
2128                    m_sProfile.nFrameWidth*m_sProfile.nFrameHeight);
2129
2130            // check alignment for offset to C
2131            OMX_U32 offset_to_c = m_sProfile.nFrameWidth * m_sProfile.nFrameHeight;
2132
2133            const OMX_U32 C_2K = (1024*2),
2134                  MASK_2K = C_2K-1,
2135                  IMASK_2K = ~MASK_2K;
2136
2137            if (offset_to_c & MASK_2K) {
2138                // offset to C is not 2k aligned, adjustment is required
2139                offset_to_c = (offset_to_c & IMASK_2K) + C_2K;
2140            }
2141
2142            // read C
2143            read(m_nInFd,
2144                    m_pInBuffers[i]->pBuffer + offset_to_c,
2145                    m_sProfile.nFrameWidth*m_sProfile.nFrameHeight/2);
2146#endif
2147
2148        }
2149
2150        // FBTest_Initialize(m_sProfile.nFrameWidth, m_sProfile.nFrameHeight);
2151
2152        // loop over the mem-resident frames and encode them
2153        D("beging playing mem-resident frames...");
2154
2155        for (i = 0; m_nFramePlay == 0 || i < m_nFramePlay; i++) {
2156            int idx = i % num_in_buffers;
2157
2158            if (m_bInFrameFree[idx] == OMX_FALSE) {
2159                int j;
2160                E("the expected buffer is not free, but lets find another");
2161
2162                idx = -1;
2163
2164                // lets see if we can find another free buffer
2165                for (j = 0; j < num_in_buffers; j++) {
2166                    if (m_bInFrameFree[j]) {
2167                        idx = j;
2168                        break;
2169                    }
2170                }
2171            }
2172
2173            // if we have a free buffer let's encode it
2174            if (idx >= 0) {
2175                D("encode frame %d...m_pInBuffers[idx]->pBuffer=0x%x", i,m_pInBuffers[idx]->pBuffer);
2176                m_bInFrameFree[idx] = OMX_FALSE;
2177                VencTest_EncodeFrame(m_pInBuffers[idx]->pBuffer,
2178                        m_nTimeStamp);
2179                D("display frame %d...", i);
2180                //    FBTest_DisplayImage(((PmemBuffer*) m_pInBuffers[idx]->pAppPrivate)->fd,0);
2181                m_nTimeStamp += 1000000 / m_sProfile.nFramerate;
2182            } else {
2183                E("wow, no buffers are free, performance "
2184                        "is not so good. lets just sleep some more");
2185
2186            }
2187
2188            D("sleep for %d microsec", 1000000/m_sProfile.nFramerate);
2189            sleep (1000000 / m_sProfile.nFramerate);
2190        }
2191
2192        // FBTest_Exit();
2193    }
2194
2195    Msg msg;
2196    bool bQuit = false;
2197
2198    while ((m_eMode == MODE_FILE_ENCODE || m_eMode == MODE_LIVE_ENCODE) &&
2199            !bQuit) {
2200        PopMessage(&msg);
2201
2202        switch (msg.id) {
2203            //////////////////////////////////
2204            // FRAME IS ENCODED
2205            //////////////////////////////////
2206            case MSG_ID_INPUT_FRAME_DONE:
2207                /*pthread_mutex_lock(&m_mutex);
2208                  ++m_nFrameOut;
2209                  if (m_nFrameOut == m_nFramePlay && m_nFramePlay != 0)
2210                  {
2211                  bQuit = true;
2212                  }
2213                  pthread_mutex_unlock(&m_mutex);*/
2214
2215                if (!bQuit && m_eMode == MODE_FILE_ENCODE) {
2216                    D("pushing another frame down to encoder");
2217
2218                    if (VencTest_ReadAndEmpty(msg.data.sBitstreamData.pBuffer)) {
2219                        // we have read the last frame
2220                        D("main is exiting...");
2221                        bQuit = true;
2222                    }
2223                }
2224
2225                break;
2226            case MSG_ID_OUTPUT_FRAME_DONE:
2227                D("================ writing frame %d = %d bytes to output file",
2228                        m_nFrameOut+1,
2229                        msg.data.sBitstreamData.pBuffer->nFilledLen);
2230                D("StopEncodeTime=%lld", GetTimeStamp());
2231
2232
2233                write(m_nOutFd,
2234                        msg.data.sBitstreamData.pBuffer->pBuffer,
2235                        msg.data.sBitstreamData.pBuffer->nFilledLen);
2236
2237
2238                result = OMX_FillThisBuffer(m_hHandle,
2239                        msg.data.sBitstreamData.pBuffer);
2240
2241                if (result != OMX_ErrorNone) {
2242                    CHK(result);
2243                }
2244
2245                pthread_mutex_lock(&m_mutex);
2246                ++m_nFrameOut;
2247
2248                if (m_nFrameOut == m_nFramePlay && m_nFramePlay != 0) {
2249                    bQuit = true;
2250                }
2251
2252                pthread_mutex_unlock(&m_mutex);
2253                break;
2254
2255            default:
2256                E("invalid msg id %d", (int) msg.id);
2257        } // end switch (msg.id)
2258
2259        /*  // TO UNCOMMENT FOR PAUSE TESTINGS
2260            if(m_nFrameOut == 10)
2261            {
2262            E("\nGoing to Pause state\n");
2263            SetState(OMX_StatePause);
2264            sleep(3);
2265        //REQUEST AN I FRAME AFTER PAUSE
2266        OMX_CONFIG_INTRAREFRESHVOPTYPE voprefresh;
2267        voprefresh.nPortIndex = (OMX_U32)PORT_INDEX_OUT;
2268        voprefresh.IntraRefreshVOP = OMX_TRUE;
2269        result = OMX_SetConfig(m_hHandle,
2270        OMX_IndexConfigVideoIntraVOPRefresh,
2271        &voprefresh);
2272        E("\n OMX_IndexConfigVideoIntraVOPRefresh Set Paramter port");
2273        CHK(result);
2274        E("\nGoing to executing state\n");
2275        SetState(OMX_StateExecuting);
2276        }
2277         */
2278    } // end while (!bQuit)
2279
2280
2281    if (m_eMode == MODE_LIVE_ENCODE) {
2282        CameraTest_Exit();
2283        close(m_nOutFd);
2284    } else if (m_eMode == MODE_FILE_ENCODE ||
2285            m_eMode == MODE_PROFILE) {
2286        // deallocate pmem buffers
2287        for (int i = 0; i < num_in_buffers; i++) {
2288            PmemFree((OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*)m_pInBuffers[i]->pAppPrivate,
2289                    m_pInBuffers[i]->pBuffer,
2290                    m_sProfile.nFrameBytes);
2291            delete (OMX_QCOM_PLATFORM_PRIVATE_PMEM_INFO*) m_pInBuffers[i]->pAppPrivate;
2292        }
2293
2294        close(m_nInFd);
2295
2296        if (m_eMode == MODE_FILE_ENCODE) {
2297            close(m_nOutFd);
2298        }
2299
2300        if (m_pDynConfFile) {
2301            fclose(m_pDynConfFile);
2302            m_pDynConfFile = NULL;
2303        }
2304    }
2305
2306    if (m_eMode != MODE_PREVIEW) {
2307        D("exit encoder test");
2308        VencTest_Exit();
2309    }
2310
2311    pthread_mutex_destroy(&m_mutex);
2312    pthread_cond_destroy(&m_signal);
2313
2314    /* Time Statistics Logging */
2315    if (0 != m_sProfile.nFramerate) {
2316        enc_time_usec = m_nTimeStamp - (1000000 / m_sProfile.nFramerate);
2317        enc_time_sec =enc_time_usec/1000000;
2318
2319        if (0 != enc_time_sec) {
2320            printf("Total Frame Rate: %f",ebd_cnt/enc_time_sec);
2321            printf("\nEncoder Bitrate :%lf Kbps",(tot_bufsize*8)/(enc_time_sec*1000));
2322        }
2323    } else {
2324        printf("\n\n Encode Time is zero");
2325    }
2326
2327    printf("\nTotal Number of Frames :%d",ebd_cnt);
2328    printf("\nNumber of dropped frames during encoding:%d\n",ebd_cnt-fbd_cnt);
2329    /* End of Time Statistics Logging */
2330
2331    D("main has exited");
2332    return 0;
2333}
2334