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