1 /** 2 * @copyright 3 * 4 * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * * Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * * Neither the name of The Linux Foundation nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 19 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 28 * DAMAGE. 29 * 30 * @file 31 * 32 * omx_swvdec_utils.cpp 33 * 34 * @brief 35 * 36 * OMX software video decoder utility functions source. 37 */ 38 39 #include <stdlib.h> 40 #include <string.h> 41 #include <assert.h> 42 #include <pthread.h> 43 #include <time.h> 44 #include <errno.h> 45 46 #include <cutils/properties.h> 47 48 #include "omx_swvdec_utils.h" 49 50 #define OMX_SWVDEC_LOGLEVEL_DEFAULT 2 ///< default OMX SwVdec loglevel 51 52 unsigned int g_omx_swvdec_logmask = (1 << OMX_SWVDEC_LOGLEVEL_DEFAULT) - 1; 53 ///< global OMX SwVdec logmask variable definition 54 55 /** 56 * @brief Initialize OMX SwVdec log level & mask. 57 */ 58 void omx_swvdec_log_init() 59 { 60 int omx_swvdec_loglevel = OMX_SWVDEC_LOGLEVEL_DEFAULT; 61 62 char property_value[PROPERTY_VALUE_MAX] = {0}; 63 64 if (property_get("omx_swvdec.log.level", property_value, NULL)) 65 { 66 omx_swvdec_loglevel = atoi(property_value); 67 68 if (omx_swvdec_loglevel > 3) 69 { 70 omx_swvdec_loglevel = 3; 71 } 72 73 if (omx_swvdec_loglevel < 0) 74 { 75 omx_swvdec_loglevel = 0; 76 } 77 78 OMX_SWVDEC_LOG_HIGH( 79 "omx_swvdec.log.level: %d; %s", 80 omx_swvdec_loglevel, 81 (omx_swvdec_loglevel == 3) ? "error, high, & low logs" : 82 ((omx_swvdec_loglevel == 2) ? "error & high logs" : 83 ((omx_swvdec_loglevel == 1) ? "error logs" : 84 "no logs"))); 85 } 86 87 g_omx_swvdec_logmask = (unsigned int) ((1 << omx_swvdec_loglevel) - 1); 88 } 89 90 /** 91 * @brief OMX SwVdec queue constructor. 92 */ 93 omx_swvdec_queue::omx_swvdec_queue() 94 { 95 pthread_mutex_init(&m_mutex, NULL); 96 } 97 98 /** 99 * @brief OMX SwVdec queue destructor. 100 */ 101 omx_swvdec_queue::~omx_swvdec_queue() 102 { 103 pthread_mutex_destroy(&m_mutex); 104 } 105 106 /** 107 * @brief Push event to queue. 108 * 109 * @param[in] p_event_info: Pointer to event information structure. 110 */ 111 void omx_swvdec_queue::push(OMX_SWVDEC_EVENT_INFO *p_event_info) 112 { 113 pthread_mutex_lock(&m_mutex); 114 115 m_queue.push(*p_event_info); 116 117 pthread_mutex_unlock(&m_mutex); 118 } 119 120 /** 121 * @brief Pop event from queue. 122 * 123 * @param[in,out] p_event_info: Pointer to event information structure. 124 * 125 * @retval true if pop successful 126 * @retval false if pop unsuccessful 127 */ 128 bool omx_swvdec_queue::pop(OMX_SWVDEC_EVENT_INFO *p_event_info) 129 { 130 bool retval = true; 131 132 pthread_mutex_lock(&m_mutex); 133 134 if (m_queue.empty()) 135 { 136 retval = false; 137 } 138 else 139 { 140 *p_event_info = m_queue.front(); 141 142 m_queue.pop(); 143 } 144 145 pthread_mutex_unlock(&m_mutex); 146 147 return retval; 148 } 149 150 /** 151 * @brief OMX SwVdec diagnostics class constructor. 152 */ 153 omx_swvdec_diag::omx_swvdec_diag(): 154 m_dump_ip(0), 155 m_dump_op(0), 156 m_filename_ip(NULL), 157 m_filename_op(NULL), 158 m_file_ip(NULL), 159 m_file_op(NULL) 160 { 161 time_t time_raw; 162 163 struct tm *time_info; 164 165 char time_string[16]; 166 167 char filename_ip[PROPERTY_VALUE_MAX]; 168 char filename_op[PROPERTY_VALUE_MAX]; 169 170 char property_value[PROPERTY_VALUE_MAX] = {0}; 171 172 time_raw = time(NULL); 173 174 time_info = localtime(&time_raw); 175 176 if (time_info != NULL) 177 { 178 // time string: "YYYYmmddTHHMMSS" 179 strftime(time_string, sizeof(time_string), "%Y%m%dT%H%M%S", time_info); 180 } 181 else 182 { 183 // time string: "19700101T000000" 184 snprintf(time_string, sizeof(time_string), "19700101T000000"); 185 } 186 187 // default ip filename: "/data/misc/media/omx_swvdec_YYYYmmddTHHMMSS_ip.bin" 188 snprintf(filename_ip, 189 sizeof(filename_ip), 190 "%s/omx_swvdec_%s_ip.bin", 191 DIAG_FILE_PATH, 192 time_string); 193 194 // default op filename: "/data/misc/media/omx_swvdec_YYYYmmddTHHMMSS_op.yuv" 195 snprintf(filename_op, 196 sizeof(filename_op), 197 "%s/omx_swvdec_%s_op.yuv", 198 DIAG_FILE_PATH, 199 time_string); 200 201 if (property_get("omx_swvdec.dump.ip", property_value, NULL)) 202 { 203 m_dump_ip = atoi(property_value); 204 205 OMX_SWVDEC_LOG_HIGH("omx_swvdec.dump.ip: %d", m_dump_ip); 206 } 207 208 if (property_get("omx_swvdec.dump.op", property_value, NULL)) 209 { 210 m_dump_op = atoi(property_value); 211 212 OMX_SWVDEC_LOG_HIGH("omx_swvdec.dump.op: %d", m_dump_op); 213 } 214 215 if (m_dump_ip && property_get("omx_swvdec.filename.ip", 216 property_value, 217 filename_ip) && (strlen(property_value) > 0 ) ) 218 { 219 size_t m_filename_ip_size = (strlen(property_value) + 1)*sizeof(char); 220 m_filename_ip = 221 (char *) malloc(m_filename_ip_size); 222 if (m_filename_ip == NULL) 223 { 224 OMX_SWVDEC_LOG_ERROR("failed to allocate %zu bytes for " 225 "input filename string", 226 m_filename_ip_size); 227 } 228 else 229 { 230 strlcpy(m_filename_ip, property_value,m_filename_ip_size); 231 OMX_SWVDEC_LOG_HIGH("omx_swvdec.filename.ip: %s", m_filename_ip); 232 if ((m_file_ip = fopen(m_filename_ip, "wb")) == NULL) 233 { 234 OMX_SWVDEC_LOG_ERROR("cannot open input file '%s' logging erro is : %d", 235 m_filename_ip,errno); 236 } 237 } 238 } 239 240 if (m_dump_op && property_get("omx_swvdec.filename.op", 241 property_value, 242 filename_op) && (strlen(property_value) > 0 )) 243 { 244 size_t m_filename_op_size = (strlen(property_value) + 1)*sizeof(char); 245 m_filename_op = 246 (char *) malloc(m_filename_op_size); 247 if (m_filename_op == NULL) 248 { 249 OMX_SWVDEC_LOG_ERROR("failed to allocate %zu bytes for " 250 "output filename string", 251 m_filename_op_size); 252 } 253 else 254 { 255 strlcpy(m_filename_op, property_value,m_filename_op_size); 256 OMX_SWVDEC_LOG_HIGH("omx_swvdec.filename.op: %s", m_filename_op); 257 if ((m_file_op = fopen(m_filename_op, "wb")) == NULL) 258 { 259 OMX_SWVDEC_LOG_ERROR("cannot open output file '%s' logging error : %d", 260 m_filename_op,errno); 261 } 262 } 263 } 264 } 265 266 /** 267 * @brief OMX SwVdec diagnostics class destructor. 268 */ 269 omx_swvdec_diag::~omx_swvdec_diag() 270 { 271 if (m_file_op) 272 { 273 fclose(m_file_op); 274 m_file_op = NULL; 275 } 276 277 if (m_file_ip) 278 { 279 fclose(m_file_ip); 280 m_file_ip = NULL; 281 } 282 283 if (m_filename_op) 284 { 285 free(m_filename_op); 286 m_filename_op = NULL; 287 } 288 289 if (m_filename_ip) 290 { 291 free(m_filename_ip); 292 m_filename_ip = NULL; 293 } 294 } 295 296 /** 297 * @brief Dump input bitstream to file. 298 * 299 * @param[in] p_buffer: Pointer to input bitstream buffer. 300 * @param[in] filled_length: Bitstream buffer's filled length. 301 */ 302 void omx_swvdec_diag::dump_ip(unsigned char *p_buffer, 303 unsigned int filled_length) 304 { 305 if (m_dump_ip && (m_file_ip != NULL)) 306 { 307 fwrite(p_buffer, sizeof(unsigned char), filled_length, m_file_ip); 308 } 309 } 310 311 /** 312 * @brief Dump output YUV to file. 313 * 314 * @param[in] p_buffer: Pointer to output YUV buffer. 315 * @param[in] width: Frame width. 316 * @param[in] height: Frame height. 317 * @param[in] stride: Frame stride. 318 * @param[in] scanlines: Frame scanlines. 319 */ 320 void omx_swvdec_diag::dump_op(unsigned char *p_buffer, 321 unsigned int width, 322 unsigned int height, 323 unsigned int stride, 324 unsigned int scanlines) 325 { 326 if (m_dump_op && (m_file_op != NULL)) 327 { 328 unsigned char *p_buffer_y; 329 unsigned char *p_buffer_uv; 330 331 unsigned int ii; 332 333 p_buffer_y = p_buffer; 334 p_buffer_uv = p_buffer + (stride * scanlines); 335 336 for (ii = 0; ii < height; ii++) 337 { 338 fwrite(p_buffer_y, sizeof(unsigned char), width, m_file_op); 339 340 p_buffer_y += stride; 341 } 342 343 for (ii = 0; ii < (height / 2); ii++) 344 { 345 fwrite(p_buffer_uv, sizeof(unsigned char), width, m_file_op); 346 347 p_buffer_uv += stride; 348 } 349 } 350 } 351