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