Home | History | Annotate | Download | only in src
      1 /**
      2  * @copyright
      3  *
      4  *   Copyright (c) 2015, 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 
     44 #include <cutils/properties.h>
     45 
     46 #include "omx_swvdec_utils.h"
     47 
     48 #define OMX_SWVDEC_LOGLEVEL_DEFAULT 2 ///< default OMX SwVdec loglevel
     49 
     50 unsigned int g_omx_swvdec_logmask = (1 << OMX_SWVDEC_LOGLEVEL_DEFAULT) - 1;
     51                               ///< global OMX SwVdec logmask variable definition
     52 
     53 /**
     54  * @brief Initialize OMX SwVdec log level & mask.
     55  */
     56 void omx_swvdec_log_init()
     57 {
     58     int omx_swvdec_loglevel = OMX_SWVDEC_LOGLEVEL_DEFAULT;
     59 
     60     char property_value[PROPERTY_VALUE_MAX] = {0};
     61 
     62     if (property_get("omx_swvdec.log.level", property_value, NULL))
     63     {
     64         omx_swvdec_loglevel = atoi(property_value);
     65 
     66         if (omx_swvdec_loglevel > 3)
     67             omx_swvdec_loglevel = 3;
     68         if (omx_swvdec_loglevel < 0)
     69             omx_swvdec_loglevel = 0;
     70 
     71         OMX_SWVDEC_LOG_LOW(
     72             "omx_swvdec.log.level: %d; %s",
     73             omx_swvdec_loglevel,
     74             (omx_swvdec_loglevel == 3) ? "error, high, & low logs" :
     75             ((omx_swvdec_loglevel == 2) ? "error & high logs" :
     76              ((omx_swvdec_loglevel == 1) ? "error logs" :
     77               "no logs")));
     78     }
     79 
     80     g_omx_swvdec_logmask = (unsigned int) ((1 << omx_swvdec_loglevel) - 1);
     81 }
     82 
     83 /**
     84  * @brief OMX SwVdec queue constructor.
     85  */
     86 omx_swvdec_queue::omx_swvdec_queue()
     87 {
     88     memset(m_queue, 0, sizeof(m_queue));
     89 
     90     m_count_total  = OMX_SWVDEC_QUEUE_ELEMENTS;
     91     m_count_filled = 0;
     92     m_index_write  = 0;
     93     m_index_read   = 0;
     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  * @retval  true if push successful
    112  * @retval false if push unsuccessful
    113  */
    114 bool omx_swvdec_queue::push(OMX_SWVDEC_EVENT_INFO *p_event_info)
    115 {
    116     bool retval = true;
    117 
    118     pthread_mutex_lock(&m_mutex);
    119 
    120     if (m_count_filled < m_count_total)
    121     {
    122         m_queue[m_index_write] = *p_event_info;
    123 
    124         m_index_write = (m_index_write + 1) % m_count_total;
    125         m_count_filled++;
    126     }
    127     else
    128     {
    129         retval = false;
    130     }
    131 
    132     pthread_mutex_unlock(&m_mutex);
    133 
    134     return retval;
    135 }
    136 
    137 /**
    138  * @brief Pop event from queue.
    139  *
    140  * @param[in,out] p_event_info: Pointer to event information structure.
    141  *
    142  * @retval  true if pop successful
    143  * @retval false if pop unsuccessful
    144  */
    145 bool omx_swvdec_queue::pop(OMX_SWVDEC_EVENT_INFO *p_event_info)
    146 {
    147     bool retval = true;
    148 
    149     pthread_mutex_lock(&m_mutex);
    150 
    151     if (m_count_filled > 0)
    152     {
    153         *p_event_info = m_queue[m_index_read];
    154 
    155         memset(&m_queue[m_index_read], 0, sizeof(OMX_SWVDEC_EVENT_INFO));
    156 
    157         m_index_read = (m_index_read + 1) % m_count_total;
    158         m_count_filled--;
    159     }
    160     else
    161     {
    162         retval = false;
    163     }
    164 
    165     pthread_mutex_unlock(&m_mutex);
    166 
    167     return retval;
    168 }
    169 
    170 /**
    171  * @brief OMX SwVdec timestamp list constructor.
    172  */
    173 omx_swvdec_ts_list::omx_swvdec_ts_list()
    174 {
    175     reset();
    176 
    177     pthread_mutex_init(&m_mutex, NULL);
    178 }
    179 
    180 /**
    181  * @brief OMX SwVdec timestamp list destructor.
    182  */
    183 omx_swvdec_ts_list::~omx_swvdec_ts_list()
    184 {
    185     pthread_mutex_destroy(&m_mutex);
    186 }
    187 
    188 /**
    189  * @brief Reset timestamp list.
    190  */
    191 void omx_swvdec_ts_list::reset()
    192 {
    193     memset(m_list, 0, sizeof(m_list));
    194     m_count_filled = 0;
    195 }
    196 
    197 /**
    198  * @brief Push timestamp to list, keeping lowest-valued timestamp at the end.
    199  *
    200  * @param[in] timestamp: Timestamp.
    201  *
    202  * @retval  true if push successful
    203  * @retval false if push unsuccessful
    204  */
    205 bool omx_swvdec_ts_list::push(long long timestamp)
    206 {
    207     bool retval = true;
    208 
    209     pthread_mutex_lock(&m_mutex);
    210 
    211     if (m_count_filled < OMX_SWVDEC_TS_LIST_ELEMENTS)
    212     {
    213         int index_curr, index_prev;
    214 
    215         long long timestamp_tmp;
    216 
    217         // insert timestamp into list
    218 
    219         m_list[m_count_filled].filled    = true;
    220         m_list[m_count_filled].timestamp = timestamp;
    221         m_count_filled++;
    222 
    223         // iterate backwards
    224 
    225         index_curr = m_count_filled - 1;
    226         index_prev = m_count_filled - 2;
    227 
    228         while ((index_curr > 0) &&
    229                (m_list[index_curr].timestamp > m_list[index_prev].timestamp))
    230         {
    231             // swap timestamps
    232 
    233             timestamp_tmp                = m_list[index_prev].timestamp;
    234             m_list[index_prev].timestamp = m_list[index_curr].timestamp;
    235             m_list[index_curr].timestamp = timestamp_tmp;
    236 
    237             index_curr--;
    238             index_prev--;
    239         }
    240     }
    241     else
    242     {
    243         retval = false;
    244     }
    245 
    246     pthread_mutex_unlock(&m_mutex);
    247 
    248     return retval;
    249 }
    250 
    251 /**
    252  * @brief Pop timestamp from list.
    253  *
    254  * @param[in,out] p_timestamp: Pointer to timestamp variable.
    255  *
    256  * @retval  true if pop successful
    257  * @retval false if pop unsuccessful
    258  */
    259 bool omx_swvdec_ts_list::pop(long long *p_timestamp)
    260 {
    261     bool retval;
    262 
    263     pthread_mutex_lock(&m_mutex);
    264 
    265     if (m_count_filled)
    266     {
    267         *p_timestamp = m_list[m_count_filled - 1].timestamp;
    268         m_list[m_count_filled - 1].filled = false;
    269         m_count_filled--;
    270 
    271         retval = true;
    272     }
    273     else
    274     {
    275         retval = false;
    276     }
    277 
    278     pthread_mutex_unlock(&m_mutex);
    279 
    280     return retval;
    281 }
    282 
    283 /**
    284  * @brief OMX SwVdec diagnostics class constructor.
    285  */
    286 omx_swvdec_diag::omx_swvdec_diag():
    287     m_dump_ip(0),
    288     m_dump_op(0),
    289     m_filename_ip(NULL),
    290     m_filename_op(NULL),
    291     m_file_ip(NULL),
    292     m_file_op(NULL)
    293 {
    294     char property_value[PROPERTY_VALUE_MAX] = {0};
    295 
    296     if (property_get("omx_swvdec.dump.ip", property_value, NULL))
    297     {
    298         m_dump_ip = atoi(property_value);
    299         OMX_SWVDEC_LOG_LOW("omx_swvdec.dump.ip: %d", m_dump_ip);
    300     }
    301 
    302     if (property_get("omx_swvdec.dump.op", property_value, NULL))
    303     {
    304         m_dump_op = atoi(property_value);
    305         OMX_SWVDEC_LOG_LOW("omx_swvdec.dump.op: %d", m_dump_op);
    306     }
    307 
    308     if (property_get("omx_swvdec.filename.ip",
    309                      property_value,
    310                      DIAG_FILENAME_IP))
    311     {
    312         OMX_SWVDEC_LOG_LOW("omx_swvdec.filename.ip: %s", m_filename_ip);
    313 
    314         m_filename_ip =
    315             (char *) malloc((strlen(property_value) + 1) * sizeof(char));
    316 
    317         if (m_filename_ip == NULL)
    318         {
    319             OMX_SWVDEC_LOG_ERROR("failed to allocate %d bytes for "
    320                                  "input filename string",
    321                                  (strlen(property_value) + 1) * sizeof(char));
    322         }
    323         else
    324         {
    325             strncpy(m_filename_ip, property_value, strlen(property_value) + 1);
    326         }
    327     }
    328 
    329     if (property_get("omx_swvdec.filename.op",
    330                      property_value,
    331                      DIAG_FILENAME_OP))
    332     {
    333         OMX_SWVDEC_LOG_LOW("omx_swvdec.filename.op: %s", m_filename_op);
    334 
    335         m_filename_op =
    336             (char *) malloc((strlen(property_value) + 1) * sizeof(char));
    337 
    338         if (m_filename_op == NULL)
    339         {
    340             OMX_SWVDEC_LOG_ERROR("failed to allocate %d bytes for "
    341                                  "output filename string",
    342                                  (strlen(property_value) + 1) * sizeof(char));
    343         }
    344         else
    345         {
    346             strncpy(m_filename_op, property_value, strlen(property_value) + 1);
    347         }
    348     }
    349 
    350     if (m_dump_ip && (m_filename_ip != NULL))
    351     {
    352         if ((m_file_ip = fopen(m_filename_ip, "rb")) == NULL)
    353         {
    354             OMX_SWVDEC_LOG_ERROR("cannot open input file '%s'", m_filename_ip);
    355             m_dump_ip = 0;
    356         }
    357     }
    358     else
    359     {
    360         m_dump_ip = 0;
    361     }
    362 
    363     if (m_dump_op && (m_filename_op != NULL))
    364     {
    365         if ((m_file_op = fopen(m_filename_op, "rb")) == NULL)
    366         {
    367             OMX_SWVDEC_LOG_ERROR("cannot open output file '%s'", m_filename_op);
    368             m_dump_op = 0;
    369         }
    370     }
    371     else
    372     {
    373         m_dump_op = 0;
    374     }
    375 }
    376 
    377 /**
    378  * @brief OMX SwVdec diagnostics class destructor.
    379  */
    380 omx_swvdec_diag::~omx_swvdec_diag()
    381 {
    382     if (m_file_op)
    383     {
    384         fclose(m_file_op);
    385         m_file_op = NULL;
    386     }
    387 
    388     if (m_file_ip)
    389     {
    390         fclose(m_file_ip);
    391         m_file_ip = NULL;
    392     }
    393 
    394     if (m_filename_op)
    395     {
    396         free(m_filename_op);
    397         m_filename_op = NULL;
    398     }
    399 
    400     if (m_filename_ip)
    401     {
    402         free(m_filename_ip);
    403         m_filename_ip = NULL;
    404     }
    405 }
    406 
    407 /**
    408  * @brief Dump input bitstream to file.
    409  *
    410  * @param[in] p_buffer:      Pointer to input bitstream buffer.
    411  * @param[in] filled_length: Bitstream buffer's filled length.
    412  */
    413 void omx_swvdec_diag::dump_ip(unsigned char *p_buffer,
    414                               unsigned int   filled_length)
    415 {
    416     if (m_dump_ip)
    417     {
    418         fwrite(p_buffer, sizeof(unsigned char), filled_length, m_file_ip);
    419     }
    420 }
    421 
    422 /**
    423  * @brief Dump output YUV to file.
    424  *
    425  * @param[in] p_buffer:  Pointer to output YUV buffer.
    426  * @param[in] width:     Frame width.
    427  * @param[in] height:    Frame height.
    428  * @param[in] stride:    Frame stride.
    429  * @param[in] scanlines: Frame scanlines.
    430  */
    431 void omx_swvdec_diag::dump_op(unsigned char *p_buffer,
    432                               unsigned int   width,
    433                               unsigned int   height,
    434                               unsigned int   stride,
    435                               unsigned int   scanlines)
    436 {
    437     if (m_dump_op)
    438     {
    439         unsigned char *p_buffer_y;
    440         unsigned char *p_buffer_uv;
    441 
    442         unsigned int ii;
    443 
    444         p_buffer_y  = p_buffer;
    445         p_buffer_uv = p_buffer + (stride * scanlines);
    446 
    447         for (ii = 0; ii < height; ii++)
    448         {
    449             fwrite(p_buffer_y, sizeof(unsigned char), width, m_file_op);
    450 
    451             p_buffer_y += stride;
    452         }
    453 
    454         for (ii = 0; ii < (height / 2); ii++)
    455         {
    456             fwrite(p_buffer_uv, sizeof(unsigned char), width, m_file_op);
    457 
    458             p_buffer_uv += stride;
    459         }
    460     }
    461 }
    462