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 */
67enum KPI_STATUS {
68	KPI_BUFFER_EVENTS = 1
69};
70
71/* OMX buffer events per component */
72typedef 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 ***************************************************************/
91kpi_omx_component kpi_omx_monitor[MAX_OMX_COMP]; /* we trace up to MAX_OMX_COMP components */
92OMX_U32 kpi_omx_monitor_cnt = 0; /* no component yet */
93unsigned 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/* ===========================================================================*/
106OMX_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/* ===========================================================================*/
124void 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/* ===========================================================================*/
156void 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/* ===========================================================================*/
224void 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/* ===========================================================================*/
259void 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