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 */
omx_swvdec_log_init()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 */
omx_swvdec_queue()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 */
~omx_swvdec_queue()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 */
push(OMX_SWVDEC_EVENT_INFO * p_event_info)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 */
pop(OMX_SWVDEC_EVENT_INFO * p_event_info)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 */
omx_swvdec_diag()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 */
~omx_swvdec_diag()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 */
dump_ip(unsigned char * p_buffer,unsigned int filled_length)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 */
dump_op(unsigned char * p_buffer,unsigned int width,unsigned int height,unsigned int stride,unsigned int scanlines)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