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
set_timestamp_reorder_mode(bool mode)31 void omx_time_stamp_reorder::set_timestamp_reorder_mode(bool mode)
32 {
33 	reorder_ts = mode;
34 }
35 
enable_debug_print(bool flag)36 void omx_time_stamp_reorder::enable_debug_print(bool flag)
37 {
38         print_debug = flag;
39 }
40 
~omx_time_stamp_reorder()41 omx_time_stamp_reorder::~omx_time_stamp_reorder()
42 {
43 	delete_list();
44 }
45 
omx_time_stamp_reorder()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 
delete_list()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 
get_current_list()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 
update_head()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 
add_new_list()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 
insert_timestamp(OMX_BUFFERHEADERTYPE * header)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 
remove_time_stamp(OMX_TICKS ts,bool is_interlaced=false)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 
flush_timestamp()206 void omx_time_stamp_reorder::flush_timestamp()
207 {
208 	delete_list();
209 }
210 
get_next_timestamp(OMX_BUFFERHEADERTYPE * header,bool is_interlaced)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