1 /*
2 * Copyright (c) 2010, Texas Instruments Incorporated
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of Texas Instruments Incorporated nor the names of
17 * its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /**
34 * @file profile.c
35 * This file contains methods to profile DOMX
36 *
37 * @path ...\hardware\ti\domx\domx\profiling\inc
38 *
39 * @rev 1.0
40 */
41
42 /******************************************************************
43 * INCLUDE FILES
44 ******************************************************************/
45 /* ----- system and platform files ----------------------------*/
46 #include <stdlib.h>
47 #include <string.h>
48 #include <time.h>
49
50 #ifdef _Android
51 #include <cutils/properties.h>
52 #endif
53
54 #include <OMX_Types.h>
55 #include <OMX_Component.h>
56
57 /*-------program files ----------------------------------------*/
58 #include "omx_rpc_utils.h"
59 #include "omx_proxy_common.h"
60 #include "profile.h"
61
62
63 /******************************************************************
64 * DEFINES - CONSTANTS
65 ******************************************************************/
66 /* Events that can be dynamically enabled */
67 enum KPI_STATUS {
68 KPI_BUFFER_EVENTS = 1
69 };
70
71 /* OMX buffer events per component */
72 typedef struct {
73 OMX_HANDLETYPE hComponent;
74 OMX_U32 count_ftb;
75 OMX_U32 count_fbd;
76 OMX_U32 count_etb;
77 OMX_U32 count_ebd;
78 char name[50];
79 } kpi_omx_component;
80
81 /* we trace up to MAX_OMX_COMP components */
82 #define MAX_OMX_COMP 8
83
84
85 /***************************************************************
86 * kpi_omx_monitor
87 * -------------------------------------------------------------
88 * Contains up to 8 components data
89 *
90 ***************************************************************/
91 kpi_omx_component kpi_omx_monitor[MAX_OMX_COMP]; /* we trace up to MAX_OMX_COMP components */
92 OMX_U32 kpi_omx_monitor_cnt = 0; /* no component yet */
93 unsigned int kpi_status = 0;
94
95
96 /* ===========================================================================*/
97 /**
98 * @name KPI_GetTime()
99 * @brief Compute time since boot to timestamp events
100 * @param void
101 * @return OMX_U64 = time since boot in us
102 * @sa TBD
103 *
104 */
105 /* ===========================================================================*/
KPI_GetTime(void)106 OMX_U64 KPI_GetTime(void)
107 {
108 struct timespec tp;
109
110 clock_gettime(CLOCK_MONOTONIC, &tp);
111 return (tp.tv_sec * 1000000 + tp.tv_nsec / 1000);
112 }
113
114 /* ===========================================================================*/
115 /**
116 * @name KPI_OmxCompKpiUpdateStatus()
117 * @brief Update dynamic activation of traces
118 * @param void
119 * @return void
120 * @sa TBD
121 *
122 */
123 /* ===========================================================================*/
KPI_OmxCompKpiUpdateStatus(void)124 void KPI_OmxCompKpiUpdateStatus(void)
125 {
126 char *val = getenv("DEBUG_DOMX_KPI_STATUS");
127
128 if (val)
129 {
130 kpi_status = strtol(val, NULL, 0);
131 }
132 #ifdef _Android
133 else
134 {
135 char value[PROPERTY_VALUE_MAX];
136 int val;
137
138 property_get("debug.domx.kpi_status", value, "0");
139 val = atoi(value);
140 if (val >= 0)
141 kpi_status = val;
142 }
143 #endif
144 }
145
146 /* ===========================================================================*/
147 /**
148 * @name KPI_OmxCompInit()
149 * @brief Prepare monitoring structure for new component starting
150 * @param void
151 * @return void
152 * @sa TBD
153 *
154 */
155 /* ===========================================================================*/
KPI_OmxCompInit(OMX_HANDLETYPE hComponent)156 void KPI_OmxCompInit(OMX_HANDLETYPE hComponent)
157 {
158 OMX_VERSIONTYPE nVersionComp;
159 OMX_VERSIONTYPE nVersionSpec;
160 OMX_UUIDTYPE compUUID;
161 char compName[OMX_MAX_STRINGNAME_SIZE];
162 char* p;
163 OMX_U32 omx_cnt;
164 struct timespec tp;
165
166 /* Check if some profiling events have been enabled/disabled */
167 KPI_OmxCompKpiUpdateStatus();
168
169 if ( !(kpi_status & KPI_BUFFER_EVENTS) )
170 return;
171
172 /* First init: clear kpi_omx_monitor components */
173 if( kpi_omx_monitor_cnt == 0) {
174 for (omx_cnt = 0; omx_cnt < MAX_OMX_COMP; omx_cnt++) {
175 /*clear handler registry */
176 kpi_omx_monitor[omx_cnt].hComponent = 0;
177 }
178 }
179
180 /* find an empty monitoring structure */
181 for( omx_cnt = 0; omx_cnt < MAX_OMX_COMP; omx_cnt++ ) {
182 if( kpi_omx_monitor[omx_cnt].hComponent == 0 ) break;
183 }
184
185 /* too omany components started, do not monitor */
186 if( omx_cnt >= MAX_OMX_COMP) return;
187
188 /* current comp num and update */
189 kpi_omx_monitor_cnt++;
190
191 /* register the component handle */
192 kpi_omx_monitor[omx_cnt].hComponent = hComponent;
193
194 /* reset event counts */
195 kpi_omx_monitor[omx_cnt].count_ftb = 0;
196 kpi_omx_monitor[omx_cnt].count_fbd = 0;
197 kpi_omx_monitor[omx_cnt].count_etb = 0;
198 kpi_omx_monitor[omx_cnt].count_ebd = 0;
199
200 /* register the component name */
201 ((OMX_COMPONENTTYPE*) hComponent)->GetComponentVersion(hComponent, compName, &nVersionComp, &nVersionSpec, &compUUID);
202
203 /* get the end of the string compName... */
204 p = compName + strlen( compName ) - 1;
205 while( (*p != '.' ) && (p != compName) ) p--;
206 strncpy(kpi_omx_monitor[omx_cnt].name, p + 1, 6);
207
208 /* trace component init */
209 DOMX_PROF("<KPI> OMX %-6s Init %-8lld", kpi_omx_monitor[omx_cnt].name, KPI_GetTime());
210
211 return;
212 }
213
214 /* ===========================================================================*/
215 /**
216 * @name KPI_OmxCompDeinit()
217 * @brief Reset monitoring structure for component stopping
218 * @param void
219 * @return void
220 * @sa TBD
221 *
222 */
223 /* ===========================================================================*/
KPI_OmxCompDeinit(OMX_HANDLETYPE hComponent)224 void KPI_OmxCompDeinit( OMX_HANDLETYPE hComponent)
225 {
226 OMX_U32 omx_cnt;
227
228 if ( !(kpi_status & KPI_BUFFER_EVENTS) )
229 return;
230
231 if( kpi_omx_monitor_cnt == 0) return;
232
233 /* identify the component from the registry */
234 for( omx_cnt = 0; omx_cnt < MAX_OMX_COMP; omx_cnt++ ) {
235 if( kpi_omx_monitor[omx_cnt].hComponent == hComponent ) break;
236 }
237
238 /* trace component init */
239 DOMX_PROF( "<KPI> OMX %-6s Deinit %-8lld", kpi_omx_monitor[omx_cnt].name, KPI_GetTime());
240
241 /* unregister the component */
242 kpi_omx_monitor[omx_cnt].hComponent = 0;
243
244 kpi_omx_monitor_cnt--;
245
246 return;
247 }
248
249 /* ===========================================================================*/
250 /**
251 * @name KPI_OmxCompBufferEvent()
252 * @brief Trace FTB/ETB/FBD/EBD events
253 * @param void
254 * @return void
255 * @sa TBD
256 *
257 */
258 /* ===========================================================================*/
KPI_OmxCompBufferEvent(enum KPI_BUFFER_EVENT event,OMX_HANDLETYPE hComponent,PROXY_BUFFER_INFO * pBuffer)259 void KPI_OmxCompBufferEvent(enum KPI_BUFFER_EVENT event, OMX_HANDLETYPE hComponent, PROXY_BUFFER_INFO* pBuffer)
260 {
261 OMX_U32 omx_cnt;
262
263 if ( !(kpi_status & KPI_BUFFER_EVENTS) )
264 return;
265
266 if (kpi_omx_monitor_cnt == 0) return;
267
268 /* identify the component from the registry */
269 for (omx_cnt = 0; omx_cnt < MAX_OMX_COMP; omx_cnt++) {
270 if( kpi_omx_monitor[omx_cnt].hComponent == hComponent ) break;
271 }
272
273 /* Update counts and trace the event */
274 if( omx_cnt < MAX_OMX_COMP ) {
275 /* trace the event, we trace remote address to correlate to Ducati trace */
276 switch(event) {
277 case KPI_BUFFER_ETB:
278 DOMX_PROF("ETB %-6s %-4u %-8lld x%-8x", kpi_omx_monitor[omx_cnt].name, \
279 (unsigned int)++kpi_omx_monitor[omx_cnt].count_etb, KPI_GetTime(), (unsigned int)pBuffer->pBufHeaderRemote);
280 break;
281 case KPI_BUFFER_FTB:
282 DOMX_PROF("FTB %-6s %-4u %-8lld x%-8x", kpi_omx_monitor[omx_cnt].name, \
283 (unsigned int)++kpi_omx_monitor[omx_cnt].count_ftb, KPI_GetTime(), (unsigned int)pBuffer->pBufHeaderRemote);
284 break;
285 case KPI_BUFFER_EBD:
286 DOMX_PROF("EBD %-6s %-4u %-8lld x%-8x", kpi_omx_monitor[omx_cnt].name, \
287 (unsigned int)++kpi_omx_monitor[omx_cnt].count_ebd, KPI_GetTime(), (unsigned int)pBuffer->pBufHeaderRemote);
288 break;
289 /* we add timestamp metadata because this is a unique identifier of buffer among all SW layers */
290 case KPI_BUFFER_FBD:
291 DOMX_PROF("FBD %-6s %-4u %-8lld x%-8x %lld", kpi_omx_monitor[omx_cnt].name, \
292 (unsigned int)++kpi_omx_monitor[omx_cnt].count_fbd, KPI_GetTime(), (unsigned int)pBuffer->pBufHeaderRemote, pBuffer->pBufHeader->nTimeStamp);
293 break;
294
295 }
296 }
297
298 return;
299 }
300