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 45 #include <cutils/properties.h> 46 47 #include "omx_swvdec_utils.h" 48 49 #define OMX_SWVDEC_LOGLEVEL_DEFAULT 2 ///< default OMX SwVdec loglevel 50 51 unsigned int g_omx_swvdec_logmask = (1 << OMX_SWVDEC_LOGLEVEL_DEFAULT) - 1; 52 ///< global OMX SwVdec logmask variable definition 53 54 /** 55 * @brief Initialize OMX SwVdec log level & mask. 56 */ 57 void omx_swvdec_log_init() 58 { 59 int omx_swvdec_loglevel = OMX_SWVDEC_LOGLEVEL_DEFAULT; 60 61 char property_value[PROPERTY_VALUE_MAX] = {0}; 62 63 if (property_get("omx_swvdec.log.level", property_value, NULL)) 64 { 65 omx_swvdec_loglevel = atoi(property_value); 66 67 if (omx_swvdec_loglevel > 3) 68 { 69 omx_swvdec_loglevel = 3; 70 } 71 72 if (omx_swvdec_loglevel < 0) 73 { 74 omx_swvdec_loglevel = 0; 75 } 76 77 OMX_SWVDEC_LOG_HIGH( 78 "omx_swvdec.log.level: %d; %s", 79 omx_swvdec_loglevel, 80 (omx_swvdec_loglevel == 3) ? "error, high, & low logs" : 81 ((omx_swvdec_loglevel == 2) ? "error & high logs" : 82 ((omx_swvdec_loglevel == 1) ? "error logs" : 83 "no logs"))); 84 } 85 86 g_omx_swvdec_logmask = (unsigned int) ((1 << omx_swvdec_loglevel) - 1); 87 } 88 89 /** 90 * @brief OMX SwVdec queue constructor. 91 */ 92 omx_swvdec_queue::omx_swvdec_queue() 93 { 94 pthread_mutex_init(&m_mutex, NULL); 95 } 96 97 /** 98 * @brief OMX SwVdec queue destructor. 99 */ 100 omx_swvdec_queue::~omx_swvdec_queue() 101 { 102 pthread_mutex_destroy(&m_mutex); 103 } 104 105 /** 106 * @brief Push event to queue. 107 * 108 * @param[in] p_event_info: Pointer to event information structure. 109 */ 110 void omx_swvdec_queue::push(OMX_SWVDEC_EVENT_INFO *p_event_info) 111 { 112 pthread_mutex_lock(&m_mutex); 113 114 m_queue.push(*p_event_info); 115 116 pthread_mutex_unlock(&m_mutex); 117 } 118 119 /** 120 * @brief Pop event from queue. 121 * 122 * @param[in,out] p_event_info: Pointer to event information structure. 123 * 124 * @retval true if pop successful 125 * @retval false if pop unsuccessful 126 */ 127 bool omx_swvdec_queue::pop(OMX_SWVDEC_EVENT_INFO *p_event_info) 128 { 129 bool retval = true; 130 131 pthread_mutex_lock(&m_mutex); 132 133 if (m_queue.empty()) 134 { 135 retval = false; 136 } 137 else 138 { 139 *p_event_info = m_queue.front(); 140 141 m_queue.pop(); 142 } 143 144 pthread_mutex_unlock(&m_mutex); 145 146 return retval; 147 } 148 149 /** 150 * @brief OMX SwVdec diagnostics class constructor. 151 */ 152 omx_swvdec_diag::omx_swvdec_diag(): 153 m_dump_ip(0), 154 m_dump_op(0), 155 m_filename_ip(NULL), 156 m_filename_op(NULL), 157 m_file_ip(NULL), 158 m_file_op(NULL) 159 { 160 time_t time_raw; 161 162 struct tm *time_info; 163 164 char time_string[16]; 165 166 char filename_ip[PROPERTY_VALUE_MAX]; 167 char filename_op[PROPERTY_VALUE_MAX]; 168 169 char property_value[PROPERTY_VALUE_MAX] = {0}; 170 171 time_raw = time(NULL); 172 173 time_info = localtime(&time_raw); 174 175 if (time_info != NULL) 176 { 177 // time string: "YYYYmmddTHHMMSS" 178 strftime(time_string, sizeof(time_string), "%Y%m%dT%H%M%S", time_info); 179 } 180 else 181 { 182 // time string: "19700101T000000" 183 snprintf(time_string, sizeof(time_string), "19700101T000000"); 184 } 185 186 // default ip filename: "/data/misc/media/omx_swvdec_YYYYmmddTHHMMSS_ip.bin" 187 snprintf(filename_ip, 188 sizeof(filename_ip), 189 "%s/omx_swvdec_%s_ip.bin", 190 DIAG_FILE_PATH, 191 time_string); 192 193 // default op filename: "/data/misc/media/omx_swvdec_YYYYmmddTHHMMSS_op.yuv" 194 snprintf(filename_op, 195 sizeof(filename_op), 196 "%s/omx_swvdec_%s_op.yuv", 197 DIAG_FILE_PATH, 198 time_string); 199 200 if (property_get("omx_swvdec.dump.ip", property_value, NULL)) 201 { 202 m_dump_ip = atoi(property_value); 203 204 OMX_SWVDEC_LOG_HIGH("omx_swvdec.dump.ip: %d", m_dump_ip); 205 } 206 207 if (property_get("omx_swvdec.dump.op", property_value, NULL)) 208 { 209 m_dump_op = atoi(property_value); 210 211 OMX_SWVDEC_LOG_HIGH("omx_swvdec.dump.op: %d", m_dump_op); 212 } 213 214 if (m_dump_ip && property_get("omx_swvdec.filename.ip", 215 property_value, 216 filename_ip)) 217 { 218 m_filename_ip = 219 (char *) malloc((strlen(property_value) + 1) * sizeof(char)); 220 221 if (m_filename_ip == NULL) 222 { 223 OMX_SWVDEC_LOG_ERROR("failed to allocate %zu bytes for " 224 "input filename string", 225 (strlen(property_value) + 1) * sizeof(char)); 226 } 227 else 228 { 229 strlcpy(m_filename_ip, property_value, strlen(m_filename_ip)); 230 231 OMX_SWVDEC_LOG_HIGH("omx_swvdec.filename.ip: %s", m_filename_ip); 232 233 if ((m_file_ip = fopen(m_filename_ip, "wb")) == NULL) 234 { 235 OMX_SWVDEC_LOG_ERROR("cannot open input file '%s'", 236 m_filename_ip); 237 } 238 } 239 } 240 241 if (m_dump_op && property_get("omx_swvdec.filename.op", 242 property_value, 243 filename_op)) 244 { 245 m_filename_op = 246 (char *) malloc((strlen(property_value) + 1) * sizeof(char)); 247 248 if (m_filename_op == NULL) 249 { 250 OMX_SWVDEC_LOG_ERROR("failed to allocate %zu bytes for " 251 "output filename string", 252 (strlen(property_value) + 1) * sizeof(char)); 253 } 254 else 255 { 256 strlcpy(m_filename_op, property_value, strlen(m_filename_op)); 257 258 OMX_SWVDEC_LOG_HIGH("omx_swvdec.filename.op: %s", m_filename_op); 259 260 if ((m_file_op = fopen(m_filename_op, "wb")) == NULL) 261 { 262 OMX_SWVDEC_LOG_ERROR("cannot open output file '%s'", 263 m_filename_op); 264 } 265 } 266 } 267 } 268 269 /** 270 * @brief OMX SwVdec diagnostics class destructor. 271 */ 272 omx_swvdec_diag::~omx_swvdec_diag() 273 { 274 if (m_file_op) 275 { 276 fclose(m_file_op); 277 m_file_op = NULL; 278 } 279 280 if (m_file_ip) 281 { 282 fclose(m_file_ip); 283 m_file_ip = NULL; 284 } 285 286 if (m_filename_op) 287 { 288 free(m_filename_op); 289 m_filename_op = NULL; 290 } 291 292 if (m_filename_ip) 293 { 294 free(m_filename_ip); 295 m_filename_ip = NULL; 296 } 297 } 298 299 /** 300 * @brief Dump input bitstream to file. 301 * 302 * @param[in] p_buffer: Pointer to input bitstream buffer. 303 * @param[in] filled_length: Bitstream buffer's filled length. 304 */ 305 void omx_swvdec_diag::dump_ip(unsigned char *p_buffer, 306 unsigned int filled_length) 307 { 308 if (m_dump_ip && (m_file_ip != NULL)) 309 { 310 fwrite(p_buffer, sizeof(unsigned char), filled_length, m_file_ip); 311 } 312 } 313 314 /** 315 * @brief Dump output YUV to file. 316 * 317 * @param[in] p_buffer: Pointer to output YUV buffer. 318 * @param[in] width: Frame width. 319 * @param[in] height: Frame height. 320 * @param[in] stride: Frame stride. 321 * @param[in] scanlines: Frame scanlines. 322 */ 323 void omx_swvdec_diag::dump_op(unsigned char *p_buffer, 324 unsigned int width, 325 unsigned int height, 326 unsigned int stride, 327 unsigned int scanlines) 328 { 329 if (m_dump_op && (m_file_op != NULL)) 330 { 331 unsigned char *p_buffer_y; 332 unsigned char *p_buffer_uv; 333 334 unsigned int ii; 335 336 p_buffer_y = p_buffer; 337 p_buffer_uv = p_buffer + (stride * scanlines); 338 339 for (ii = 0; ii < height; ii++) 340 { 341 fwrite(p_buffer_y, sizeof(unsigned char), width, m_file_op); 342 343 p_buffer_y += stride; 344 } 345 346 for (ii = 0; ii < (height / 2); ii++) 347 { 348 fwrite(p_buffer_uv, sizeof(unsigned char), width, m_file_op); 349 350 p_buffer_uv += stride; 351 } 352 } 353 } 354