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