• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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