/*-------------------------------------------------------------------------- | |
Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved. | |
Redistribution and use in source and binary forms, with or without | |
modification, are permitted provided that the following conditions are met: | |
* Redistributions of source code must retain the above copyright | |
notice, this list of conditions and the following disclaimer. | |
* Redistributions in binary form must reproduce the above copyright | |
notice, this list of conditions and the following disclaimer in the | |
documentation and/or other materials provided with the distribution. | |
* Neither the name of Code Aurora nor | |
the names of its contributors may be used to endorse or promote | |
products derived from this software without specific prior written | |
permission. | |
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; | |
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, | |
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR | |
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
--------------------------------------------------------------------------*/ | |
#include "ts_parser.h" | |
#define DEBUG ALOGE | |
void omx_time_stamp_reorder::set_timestamp_reorder_mode(bool mode) | |
{ | |
reorder_ts = mode; | |
} | |
void omx_time_stamp_reorder::enable_debug_print(bool flag) | |
{ | |
print_debug = flag; | |
} | |
omx_time_stamp_reorder::~omx_time_stamp_reorder() | |
{ | |
delete_list(); | |
} | |
omx_time_stamp_reorder::omx_time_stamp_reorder() | |
{ | |
reorder_ts = false; | |
phead = pcurrent = NULL; | |
error = false; | |
print_debug = false; | |
} | |
void omx_time_stamp_reorder::delete_list() | |
{ | |
time_stamp_list *ptemp; | |
if (!phead) return; | |
while(phead->next != phead) { | |
ptemp = phead; | |
phead = phead->next; | |
phead->prev = ptemp->prev; | |
ptemp->prev->next = phead; | |
delete ptemp; | |
} | |
delete phead; | |
phead = NULL; | |
} | |
bool omx_time_stamp_reorder::get_current_list() | |
{ | |
if (!phead) { | |
if(!add_new_list()) { | |
handle_error(); | |
return false; | |
} | |
} | |
pcurrent = phead->prev; | |
return true; | |
} | |
bool omx_time_stamp_reorder::update_head() | |
{ | |
time_stamp_list *ptemp; | |
if(!phead) return false; | |
if (phead->next != phead) { | |
ptemp = phead; | |
phead = ptemp->next; | |
phead->prev = ptemp->prev; | |
ptemp->prev->next = phead; | |
delete ptemp; | |
} | |
return true; | |
} | |
bool omx_time_stamp_reorder::add_new_list() | |
{ | |
bool status = true; | |
time_stamp_list *ptemp = NULL; | |
if (!phead) { | |
ptemp = phead = new time_stamp_list; | |
if (!phead) { | |
handle_error(); | |
status = false; | |
return status; | |
} | |
phead->prev = phead->next = phead; | |
} else { | |
ptemp = new time_stamp_list; | |
if (!ptemp) { | |
handle_error(); | |
status = false; | |
return status; | |
} | |
ptemp->prev = phead->prev; | |
ptemp->next = phead; | |
phead->prev->next = ptemp; | |
phead->prev = ptemp; | |
} | |
ptemp->entries_filled = 0; | |
for(int i=0; i < TIME_SZ; i++) { | |
ptemp->input_timestamps[i].in_use = false; | |
ptemp->input_timestamps[i].timestamps = -1; | |
} | |
return status; | |
} | |
bool omx_time_stamp_reorder::insert_timestamp(OMX_BUFFERHEADERTYPE *header) | |
{ | |
OMX_TICKS *table_entry = NULL; | |
if (!reorder_ts || error || !header) { | |
if (error || !header) | |
DEBUG("\n Invalid condition in insert_timestamp %p", header); | |
return false; | |
} | |
if(!get_current_list()) { | |
handle_error(); | |
return false; | |
} | |
if (pcurrent->entries_filled > (TIME_SZ - 1)) { | |
DEBUG("\n Table full return error"); | |
handle_error(); | |
return false; | |
} | |
if (header->nFlags & OMX_BUFFERFLAG_CODECCONFIG) { | |
return true; | |
} | |
if ((header->nFlags & OMX_BUFFERFLAG_EOS) && !header->nFilledLen) | |
{ | |
DEBUG("\n EOS with zero length recieved"); | |
if (!add_new_list()) { | |
handle_error(); | |
return false; | |
} | |
return true; | |
} | |
for(int i = 0; i < TIME_SZ && !table_entry; i++) { | |
if (!pcurrent->input_timestamps[i].in_use) { | |
table_entry = &pcurrent->input_timestamps[i].timestamps; | |
pcurrent->input_timestamps[i].in_use = true; | |
pcurrent->entries_filled++; | |
} | |
} | |
if (!table_entry) { | |
DEBUG("\n All entries in use"); | |
handle_error(); | |
return false; | |
} | |
*table_entry = header->nTimeStamp; | |
if (print_debug) | |
DEBUG("Time stamp inserted %lld", header->nTimeStamp); | |
if (header->nFlags & OMX_BUFFERFLAG_EOS) { | |
if (!add_new_list()) { | |
handle_error(); | |
return false; | |
} | |
} | |
return true; | |
} | |
bool omx_time_stamp_reorder::remove_time_stamp(OMX_TICKS ts, bool is_interlaced = false) | |
{ | |
unsigned int num_ent_remove = (is_interlaced)?2:1; | |
if (!reorder_ts || error) { | |
DEBUG("\n not in avi mode"); | |
return false; | |
} | |
if (!phead || !phead->entries_filled) return false; | |
for(int i=0; i < TIME_SZ && num_ent_remove; i++) { | |
if (phead->input_timestamps[i].in_use && phead->input_timestamps[i].timestamps == ts) { | |
phead->input_timestamps[i].in_use = false; | |
phead->entries_filled--; | |
num_ent_remove--; | |
if (print_debug) | |
DEBUG("Removed TS %lld", ts); | |
} | |
} | |
if (!phead->entries_filled) { | |
if (!update_head()) { | |
handle_error(); | |
return false; | |
} | |
} | |
return true; | |
} | |
void omx_time_stamp_reorder::flush_timestamp() | |
{ | |
delete_list(); | |
} | |
bool omx_time_stamp_reorder::get_next_timestamp(OMX_BUFFERHEADERTYPE *header, bool is_interlaced) | |
{ | |
timestamp *element = NULL,*duplicate = NULL; | |
bool status = false; | |
if (!reorder_ts || error || !header) { | |
if (error || !header) | |
DEBUG("\n Invalid condition in insert_timestamp %p", header); | |
return false; | |
} | |
if(!phead || !phead->entries_filled) return false; | |
for(int i=0; i < TIME_SZ; i++) { | |
if (phead->input_timestamps[i].in_use) { | |
status = true; | |
if (!element) | |
element = &phead->input_timestamps[i]; | |
else { | |
if (element->timestamps > phead->input_timestamps[i].timestamps){ | |
element = &phead->input_timestamps[i]; | |
duplicate = NULL; | |
} else if(element->timestamps == phead->input_timestamps[i].timestamps) | |
duplicate = &phead->input_timestamps[i]; | |
} | |
} | |
} | |
if (element) { | |
phead->entries_filled--; | |
header->nTimeStamp = element->timestamps; | |
if (print_debug) | |
DEBUG("Getnext Time stamp %lld", header->nTimeStamp); | |
element->in_use = false; | |
} | |
if(is_interlaced && duplicate) { | |
phead->entries_filled--; | |
duplicate->in_use = false; | |
} | |
else if(is_interlaced && status) | |
{ | |
for(int i=0; i < TIME_SZ; i++) { | |
if (phead->input_timestamps[i].in_use) { | |
if (!duplicate) | |
duplicate = &phead->input_timestamps[i]; | |
else { | |
if (duplicate->timestamps > phead->input_timestamps[i].timestamps) | |
duplicate = &phead->input_timestamps[i]; | |
} | |
} | |
} | |
if (duplicate) { | |
phead->entries_filled--; | |
if (print_debug) | |
DEBUG("Getnext Duplicate Time stamp %lld", header->nTimeStamp); | |
duplicate->in_use = false; | |
} | |
} | |
if (!phead->entries_filled) { | |
if (!update_head()) { | |
handle_error(); | |
return false; | |
} | |
} | |
return status; | |
} |