• 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 
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