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