1 /*-------------------------------------------------------------------------- 2 Copyright (c) 2010-2012, Code Aurora Forum. 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 Code Aurora 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 30 #define DEBUG ALOGE 31 void omx_time_stamp_reorder::set_timestamp_reorder_mode(bool mode) 32 { 33 reorder_ts = mode; 34 } 35 36 void omx_time_stamp_reorder::enable_debug_print(bool flag) 37 { 38 print_debug = flag; 39 } 40 41 omx_time_stamp_reorder::~omx_time_stamp_reorder() 42 { 43 delete_list(); 44 } 45 46 omx_time_stamp_reorder::omx_time_stamp_reorder() 47 { 48 reorder_ts = false; 49 phead = pcurrent = NULL; 50 error = false; 51 print_debug = false; 52 } 53 54 void omx_time_stamp_reorder::delete_list() 55 { 56 time_stamp_list *ptemp; 57 if (!phead) return; 58 while(phead->next != phead) { 59 ptemp = phead; 60 phead = phead->next; 61 phead->prev = ptemp->prev; 62 ptemp->prev->next = phead; 63 delete ptemp; 64 } 65 delete phead; 66 phead = NULL; 67 } 68 69 bool omx_time_stamp_reorder::get_current_list() 70 { 71 if (!phead) { 72 if(!add_new_list()) { 73 handle_error(); 74 return false; 75 } 76 } 77 pcurrent = phead->prev; 78 return true; 79 } 80 81 bool omx_time_stamp_reorder::update_head() 82 { 83 time_stamp_list *ptemp; 84 if(!phead) return false; 85 if (phead->next != phead) { 86 ptemp = phead; 87 phead = ptemp->next; 88 phead->prev = ptemp->prev; 89 ptemp->prev->next = phead; 90 delete ptemp; 91 } 92 return true; 93 } 94 95 bool omx_time_stamp_reorder::add_new_list() 96 { 97 bool status = true; 98 time_stamp_list *ptemp = NULL; 99 if (!phead) { 100 ptemp = phead = new time_stamp_list; 101 if (!phead) { 102 handle_error(); 103 status = false; 104 return status; 105 } 106 phead->prev = phead->next = phead; 107 } else { 108 ptemp = new time_stamp_list; 109 if (!ptemp) { 110 handle_error(); 111 status = false; 112 return status; 113 } 114 ptemp->prev = phead->prev; 115 ptemp->next = phead; 116 phead->prev->next = ptemp; 117 phead->prev = ptemp; 118 } 119 ptemp->entries_filled = 0; 120 for(int i=0; i < TIME_SZ; i++) { 121 ptemp->input_timestamps[i].in_use = false; 122 ptemp->input_timestamps[i].timestamps = -1; 123 } 124 return status; 125 } 126 127 bool omx_time_stamp_reorder::insert_timestamp(OMX_BUFFERHEADERTYPE *header) 128 { 129 OMX_TICKS *table_entry = NULL; 130 if (!reorder_ts || error || !header) { 131 if (error || !header) 132 DEBUG("\n Invalid condition in insert_timestamp %p", header); 133 return false; 134 } 135 if(!get_current_list()) { 136 handle_error(); 137 return false; 138 } 139 if (pcurrent->entries_filled > (TIME_SZ - 1)) { 140 DEBUG("\n Table full return error"); 141 handle_error(); 142 return false; 143 } 144 if (header->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { 145 return true; 146 } 147 if ((header->nFlags & OMX_BUFFERFLAG_EOS) && !header->nFilledLen) 148 { 149 DEBUG("\n EOS with zero length recieved"); 150 if (!add_new_list()) { 151 handle_error(); 152 return false; 153 } 154 return true; 155 } 156 for(int i = 0; i < TIME_SZ && !table_entry; i++) { 157 if (!pcurrent->input_timestamps[i].in_use) { 158 table_entry = &pcurrent->input_timestamps[i].timestamps; 159 pcurrent->input_timestamps[i].in_use = true; 160 pcurrent->entries_filled++; 161 } 162 } 163 if (!table_entry) { 164 DEBUG("\n All entries in use"); 165 handle_error(); 166 return false; 167 } 168 *table_entry = header->nTimeStamp; 169 if (print_debug) 170 DEBUG("Time stamp inserted %lld", header->nTimeStamp); 171 if (header->nFlags & OMX_BUFFERFLAG_EOS) { 172 if (!add_new_list()) { 173 handle_error(); 174 return false; 175 } 176 } 177 return true; 178 } 179 180 bool omx_time_stamp_reorder::remove_time_stamp(OMX_TICKS ts, bool is_interlaced = false) 181 { 182 unsigned int num_ent_remove = (is_interlaced)?2:1; 183 if (!reorder_ts || error) { 184 DEBUG("\n not in avi mode"); 185 return false; 186 } 187 if (!phead || !phead->entries_filled) return false; 188 for(int i=0; i < TIME_SZ && num_ent_remove; i++) { 189 if (phead->input_timestamps[i].in_use && phead->input_timestamps[i].timestamps == ts) { 190 phead->input_timestamps[i].in_use = false; 191 phead->entries_filled--; 192 num_ent_remove--; 193 if (print_debug) 194 DEBUG("Removed TS %lld", ts); 195 } 196 } 197 if (!phead->entries_filled) { 198 if (!update_head()) { 199 handle_error(); 200 return false; 201 } 202 } 203 return true; 204 } 205 206 void omx_time_stamp_reorder::flush_timestamp() 207 { 208 delete_list(); 209 } 210 211 bool omx_time_stamp_reorder::get_next_timestamp(OMX_BUFFERHEADERTYPE *header, bool is_interlaced) 212 { 213 timestamp *element = NULL,*duplicate = NULL; 214 bool status = false; 215 if (!reorder_ts || error || !header) { 216 if (error || !header) 217 DEBUG("\n Invalid condition in insert_timestamp %p", header); 218 return false; 219 } 220 if(!phead || !phead->entries_filled) return false; 221 for(int i=0; i < TIME_SZ; i++) { 222 if (phead->input_timestamps[i].in_use) { 223 status = true; 224 if (!element) 225 element = &phead->input_timestamps[i]; 226 else { 227 if (element->timestamps > phead->input_timestamps[i].timestamps){ 228 element = &phead->input_timestamps[i]; 229 duplicate = NULL; 230 } else if(element->timestamps == phead->input_timestamps[i].timestamps) 231 duplicate = &phead->input_timestamps[i]; 232 } 233 } 234 } 235 if (element) { 236 phead->entries_filled--; 237 header->nTimeStamp = element->timestamps; 238 if (print_debug) 239 DEBUG("Getnext Time stamp %lld", header->nTimeStamp); 240 element->in_use = false; 241 } 242 if(is_interlaced && duplicate) { 243 phead->entries_filled--; 244 duplicate->in_use = false; 245 } 246 else if(is_interlaced && status) 247 { 248 for(int i=0; i < TIME_SZ; i++) { 249 if (phead->input_timestamps[i].in_use) { 250 if (!duplicate) 251 duplicate = &phead->input_timestamps[i]; 252 else { 253 if (duplicate->timestamps > phead->input_timestamps[i].timestamps) 254 duplicate = &phead->input_timestamps[i]; 255 } 256 } 257 } 258 if (duplicate) { 259 phead->entries_filled--; 260 if (print_debug) 261 DEBUG("Getnext Duplicate Time stamp %lld", header->nTimeStamp); 262 duplicate->in_use = false; 263 } 264 } 265 266 if (!phead->entries_filled) { 267 if (!update_head()) { 268 handle_error(); 269 return false; 270 } 271 } 272 return status; 273 } 274