Home | History | Annotate | Download | only in src
      1 /*--------------------------------------------------------------------------
      2 Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
      3 
      4 Redistribution and use in source and binary forms, with or without
      5 modification, are permitted provided that the following conditions are met:
      6     * Redistributions of source code must retain the above copyright
      7       notice, this list of conditions and the following disclaimer.
      8     * Redistributions in binary form must reproduce the above copyright
      9       notice, this list of conditions and the following disclaimer in the
     10       documentation and/or other materials provided with the distribution.
     11     * Neither the name of The Linux Foundation nor
     12       the names of its contributors may be used to endorse or promote
     13       products derived from this software without specific prior written
     14       permission.
     15 
     16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18 IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     19 NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     20 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     21 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     22 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     23 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     25 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     26 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 --------------------------------------------------------------------------*/
     28 #include "ts_parser.h"
     29 #include "vidc_debug.h"
     30 
     31 #define DEBUG DEBUG_PRINT_ERROR
     32 
     33 void omx_time_stamp_reorder::set_timestamp_reorder_mode(bool mode)
     34 {
     35     auto_lock l(&m_lock);
     36     reorder_ts = mode;
     37 }
     38 
     39 void omx_time_stamp_reorder::enable_debug_print(bool flag)
     40 {
     41     auto_lock l(&m_lock);
     42     print_debug = flag;
     43 }
     44 
     45 omx_time_stamp_reorder::~omx_time_stamp_reorder()
     46 {
     47     delete_list();
     48     pthread_mutex_destroy(&m_lock);
     49 }
     50 
     51 omx_time_stamp_reorder::omx_time_stamp_reorder()
     52 {
     53     reorder_ts = false;
     54     phead = pcurrent = NULL;
     55     error = false;
     56     print_debug = false;
     57     pthread_mutex_init(&m_lock, NULL);
     58 }
     59 
     60 void omx_time_stamp_reorder::delete_list()
     61 {
     62     time_stamp_list *ptemp;
     63 
     64     if (!phead) return;
     65 
     66     while (phead->next != phead) {
     67         ptemp = phead;
     68         phead = phead->next;
     69         phead->prev = ptemp->prev;
     70         ptemp->prev->next = phead;
     71         delete ptemp;
     72     }
     73 
     74     delete phead;
     75     phead = NULL;
     76 }
     77 
     78 bool omx_time_stamp_reorder::get_current_list()
     79 {
     80     if (!phead) {
     81         if (!add_new_list()) {
     82             handle_error();
     83             return false;
     84         }
     85     }
     86 
     87     pcurrent = phead->prev;
     88     return true;
     89 }
     90 
     91 bool omx_time_stamp_reorder::update_head()
     92 {
     93     time_stamp_list *ptemp;
     94 
     95     if (!phead) return false;
     96 
     97     if (phead->next != phead) {
     98         ptemp = phead;
     99         phead = ptemp->next;
    100         phead->prev = ptemp->prev;
    101         ptemp->prev->next = phead;
    102         delete ptemp;
    103     }
    104 
    105     return true;
    106 }
    107 
    108 bool omx_time_stamp_reorder::add_new_list()
    109 {
    110     bool status = true;
    111     time_stamp_list *ptemp = NULL;
    112 
    113     if (!phead) {
    114         ptemp = phead = new time_stamp_list;
    115 
    116         if (!phead) {
    117             handle_error();
    118             status = false;
    119             return status;
    120         }
    121 
    122         phead->prev = phead->next = phead;
    123     } else {
    124         ptemp = new time_stamp_list;
    125 
    126         if (!ptemp) {
    127             handle_error();
    128             status = false;
    129             return status;
    130         }
    131 
    132         ptemp->prev = phead->prev;
    133         ptemp->next = phead;
    134         phead->prev->next = ptemp;
    135         phead->prev = ptemp;
    136     }
    137 
    138     ptemp->entries_filled = 0;
    139 
    140     for (int i=0; i < TIME_SZ; i++) {
    141         ptemp->input_timestamps[i].in_use = false;
    142         ptemp->input_timestamps[i].timestamps = -1;
    143     }
    144 
    145     return status;
    146 }
    147 
    148 bool omx_time_stamp_reorder::insert_timestamp(OMX_BUFFERHEADERTYPE *header)
    149 {
    150     auto_lock l(&m_lock);
    151     OMX_TICKS *table_entry = NULL;
    152 
    153     if (!reorder_ts || error || !header) {
    154         if (error || !header)
    155             DEBUG("Invalid condition in insert_timestamp %p", header);
    156 
    157         return false;
    158     }
    159 
    160     if (!get_current_list()) {
    161         handle_error();
    162         return false;
    163     }
    164 
    165     if (pcurrent->entries_filled > (TIME_SZ - 1)) {
    166         DEBUG("Table full return error");
    167         handle_error();
    168         return false;
    169     }
    170 
    171     if (header->nFlags & OMX_BUFFERFLAG_CODECCONFIG) {
    172         return true;
    173     }
    174 
    175     if ((header->nFlags & OMX_BUFFERFLAG_EOS) && !header->nFilledLen) {
    176         DEBUG("EOS with zero length recieved");
    177 
    178         if (!add_new_list()) {
    179             handle_error();
    180             return false;
    181         }
    182 
    183         return true;
    184     }
    185 
    186     for (int i = 0; i < TIME_SZ && !table_entry; i++) {
    187         if (!pcurrent->input_timestamps[i].in_use) {
    188             table_entry = &pcurrent->input_timestamps[i].timestamps;
    189             pcurrent->input_timestamps[i].in_use = true;
    190             pcurrent->entries_filled++;
    191         }
    192     }
    193 
    194     if (!table_entry) {
    195         DEBUG("All entries in use");
    196         handle_error();
    197         return false;
    198     }
    199 
    200     *table_entry = header->nTimeStamp;
    201 
    202     if (print_debug)
    203         DEBUG("Time stamp inserted %lld", header->nTimeStamp);
    204 
    205     if (header->nFlags & OMX_BUFFERFLAG_EOS) {
    206         if (!add_new_list()) {
    207             handle_error();
    208             return false;
    209         }
    210     }
    211 
    212     return true;
    213 }
    214 
    215 bool omx_time_stamp_reorder::remove_time_stamp(OMX_TICKS ts, bool is_interlaced = false)
    216 {
    217     auto_lock l(&m_lock);
    218     unsigned int num_ent_remove = (is_interlaced)?2:1;
    219 
    220     if (!reorder_ts || error) {
    221         DEBUG("not in avi mode");
    222         return false;
    223     }
    224 
    225     if (!phead || !phead->entries_filled) return false;
    226 
    227     for (int i=0; i < TIME_SZ && num_ent_remove; i++) {
    228         if (phead->input_timestamps[i].in_use && phead->input_timestamps[i].timestamps == ts) {
    229             phead->input_timestamps[i].in_use = false;
    230             phead->entries_filled--;
    231             num_ent_remove--;
    232 
    233             if (print_debug)
    234                 DEBUG("Removed TS %lld", ts);
    235         }
    236     }
    237 
    238     if (!phead->entries_filled) {
    239         if (!update_head()) {
    240             handle_error();
    241             return false;
    242         }
    243     }
    244 
    245     return true;
    246 }
    247 
    248 void omx_time_stamp_reorder::flush_timestamp()
    249 {
    250     auto_lock l(&m_lock);
    251     delete_list();
    252 }
    253 
    254 bool omx_time_stamp_reorder::get_next_timestamp(OMX_BUFFERHEADERTYPE *header, bool is_interlaced)
    255 {
    256     auto_lock l(&m_lock);
    257     timestamp *element = NULL,*duplicate = NULL;
    258     bool status = false;
    259 
    260     if (!reorder_ts || error || !header) {
    261         if (error || !header)
    262             DEBUG("Invalid condition in insert_timestamp %p", header);
    263 
    264         return false;
    265     }
    266 
    267     if (!phead || !phead->entries_filled) return false;
    268 
    269     for (int i=0; i < TIME_SZ; i++) {
    270         if (phead->input_timestamps[i].in_use) {
    271             status = true;
    272 
    273             if (!element)
    274                 element = &phead->input_timestamps[i];
    275             else {
    276                 if (element->timestamps > phead->input_timestamps[i].timestamps) {
    277                     element = &phead->input_timestamps[i];
    278                     duplicate = NULL;
    279                 } else if (element->timestamps == phead->input_timestamps[i].timestamps)
    280                     duplicate = &phead->input_timestamps[i];
    281             }
    282         }
    283     }
    284 
    285     if (element) {
    286         phead->entries_filled--;
    287         header->nTimeStamp = element->timestamps;
    288 
    289         if (print_debug)
    290             DEBUG("Getnext Time stamp %lld", header->nTimeStamp);
    291 
    292         element->in_use = false;
    293     }
    294 
    295     if (is_interlaced && duplicate) {
    296         phead->entries_filled--;
    297         duplicate->in_use = false;
    298     } else if (is_interlaced && !duplicate) {
    299         element = NULL;
    300 
    301         for (int i=0; i < TIME_SZ; i++) {
    302             if (phead->input_timestamps[i].in_use) {
    303                 if (!element)
    304                     element = &phead->input_timestamps[i];
    305                 else if (element->timestamps > phead->input_timestamps[i].timestamps)
    306                     element = &phead->input_timestamps[i];
    307             }
    308         }
    309 
    310         if (element) {
    311             phead->entries_filled--;
    312             header->nTimeStamp = element->timestamps;
    313             element->in_use = false;
    314         }
    315     }
    316 
    317     if (!phead->entries_filled) {
    318         if (!update_head()) {
    319             handle_error();
    320             return false;
    321         }
    322     }
    323 
    324     return status;
    325 }
    326