ts_parser.cpp revision f84ff736ed4e9e3c52a6341f7f2f5f325d8b5bab
1/*--------------------------------------------------------------------------
2Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
3
4Redistribution and use in source and binary forms, with or without
5modification, 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
16THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19NON-INFRINGEMENT ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27--------------------------------------------------------------------------*/
28#include "ts_parser.h"
29
30#define DEBUG ALOGE
31void omx_time_stamp_reorder::set_timestamp_reorder_mode(bool mode)
32{
33    reorder_ts = mode;
34}
35
36void omx_time_stamp_reorder::enable_debug_print(bool flag)
37{
38    print_debug = flag;
39}
40
41omx_time_stamp_reorder::~omx_time_stamp_reorder()
42{
43    delete_list();
44}
45
46omx_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
54void 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
72bool 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
85bool 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
102bool 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
142bool 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
208bool 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
240void omx_time_stamp_reorder::flush_timestamp()
241{
242    delete_list();
243}
244
245bool 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