1 /**
2  * @copyright
3  *
4  *   Copyright (c) 2015-2017, 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("vendor.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             "vendor.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("vendor.omx_swvdec.dump.ip", property_value, NULL))
202     {
203         m_dump_ip = atoi(property_value);
204 
205         OMX_SWVDEC_LOG_HIGH("vendor.omx_swvdec.dump.ip: %d", m_dump_ip);
206     }
207 
208     if (property_get("vendor.omx_swvdec.dump.op", property_value, NULL))
209     {
210         m_dump_op = atoi(property_value);
211 
212         OMX_SWVDEC_LOG_HIGH("vendor.omx_swvdec.dump.op: %d", m_dump_op);
213     }
214 
215     if (m_dump_ip && property_get("vendor.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("vendor.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("vendor.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("vendor.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