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 #include "vidc_debug.h"
30
31 #define DEBUG DEBUG_PRINT_ERROR
32
set_timestamp_reorder_mode(bool mode)33 void omx_time_stamp_reorder::set_timestamp_reorder_mode(bool mode)
34 {
35 reorder_ts = mode;
36 }
37
enable_debug_print(bool flag)38 void omx_time_stamp_reorder::enable_debug_print(bool flag)
39 {
40 print_debug = flag;
41 }
42
~omx_time_stamp_reorder()43 omx_time_stamp_reorder::~omx_time_stamp_reorder()
44 {
45 delete_list();
46 }
47
omx_time_stamp_reorder()48 omx_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
delete_list()56 void 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
get_current_list()74 bool 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
update_head()87 bool 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
add_new_list()104 bool 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
insert_timestamp(OMX_BUFFERHEADERTYPE * header)144 bool 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
remove_time_stamp(OMX_TICKS ts,bool is_interlaced=false)210 bool 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
flush_timestamp()242 void omx_time_stamp_reorder::flush_timestamp()
243 {
244 delete_list();
245 }
246
get_next_timestamp(OMX_BUFFERHEADERTYPE * header,bool is_interlaced)247 bool 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