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