]> git.sesse.net Git - vlc/blob - include/vlc_block_helper.h
A bit of headers cleanup
[vlc] / include / vlc_block_helper.h
1 /*****************************************************************************
2  * vlc_block_helper.h: Helper functions for data blocks management.
3  *****************************************************************************
4  * Copyright (C) 2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Gildas Bazin <gbazin@netcourrier.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #ifndef _VLC_BLOCK_HELPER_H
25 #define _VLC_BLOCK_HELPER_H 1
26
27 #include <vlc_block.h>
28
29 typedef struct block_bytestream_t
30 {
31     block_t             *p_chain;
32     block_t             *p_block;
33     int                 i_offset;
34
35 } block_bytestream_t;
36
37 #define block_BytestreamInit( a ) __block_BytestreamInit( VLC_OBJECT(a) )
38
39 /*****************************************************************************
40  * block_bytestream_t management
41  *****************************************************************************/
42 static inline block_bytestream_t __block_BytestreamInit( vlc_object_t *p_obj )
43 {
44     block_bytestream_t bytestream;
45
46     bytestream.i_offset = 0;
47     bytestream.p_chain = bytestream.p_block = NULL;
48
49     return bytestream;
50 }
51
52 static inline void block_BytestreamRelease( block_bytestream_t *p_bytestream )
53 {
54     while( p_bytestream->p_chain )
55     {
56         block_t *p_next;
57         p_next = p_bytestream->p_chain->p_next;
58         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
59         p_bytestream->p_chain = p_next;
60     }
61     p_bytestream->i_offset = 0;
62     p_bytestream->p_chain = p_bytestream->p_block = NULL;
63 }
64
65 static inline void block_BytestreamFlush( block_bytestream_t *p_bytestream )
66 {
67     while( p_bytestream->p_chain != p_bytestream->p_block )
68     {
69         block_t *p_next;
70         p_next = p_bytestream->p_chain->p_next;
71         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
72         p_bytestream->p_chain = p_next;
73     }
74     while( p_bytestream->p_block &&
75            (p_bytestream->p_block->i_buffer - p_bytestream->i_offset) == 0 )
76     {
77         block_t *p_next;
78         p_next = p_bytestream->p_chain->p_next;
79         p_bytestream->p_chain->pf_release( p_bytestream->p_chain );
80         p_bytestream->p_chain = p_bytestream->p_block = p_next;
81         p_bytestream->i_offset = 0;
82     }
83 }
84
85 static inline void block_BytestreamPush( block_bytestream_t *p_bytestream,
86                                          block_t *p_block )
87 {
88     block_ChainAppend( &p_bytestream->p_chain, p_block );
89     if( !p_bytestream->p_block ) p_bytestream->p_block = p_block;
90 }
91
92 static inline block_t *block_BytestreamPop( block_bytestream_t *p_bytestream )
93 {
94     block_t *p_block;
95
96     block_BytestreamFlush( p_bytestream );
97
98     p_block = p_bytestream->p_block;
99     if( p_block == NULL )
100     {
101         return NULL;
102     }
103     else if( !p_block->p_next )
104     {
105         p_block->p_buffer += p_bytestream->i_offset;
106         p_block->i_buffer -= p_bytestream->i_offset;
107         p_bytestream->i_offset = 0;
108         p_bytestream->p_chain = p_bytestream->p_block = NULL;
109         return p_block;
110     }
111
112     while( p_block->p_next && p_block->p_next->p_next )
113         p_block = p_block->p_next;
114
115     {
116         block_t *p_block_old = p_block;
117         p_block = p_block->p_next;
118         p_block_old->p_next = NULL;
119     }
120
121     return p_block;
122 }
123
124 static inline int block_SkipByte( block_bytestream_t *p_bytestream )
125 {
126     /* Most common case first */
127     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
128     {
129         p_bytestream->i_offset++;
130         return VLC_SUCCESS;
131     }
132     else
133     {
134         block_t *p_block;
135
136         /* Less common case which is also slower */
137         for( p_block = p_bytestream->p_block->p_next;
138              p_block != NULL; p_block = p_block->p_next )
139         {
140             if( p_block->i_buffer )
141             {
142                 p_bytestream->i_offset = 1;
143                 p_bytestream->p_block = p_block;
144                 return VLC_SUCCESS;
145             }
146         }
147     }
148
149     /* Not enough data, bail out */
150     return VLC_EGENERIC;
151 }
152
153 static inline int block_PeekByte( block_bytestream_t *p_bytestream,
154                                   uint8_t *p_data )
155 {
156     /* Most common case first */
157     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
158     {
159         *p_data = p_bytestream->p_block->p_buffer[p_bytestream->i_offset];
160         return VLC_SUCCESS;
161     }
162     else
163     {
164         block_t *p_block;
165
166         /* Less common case which is also slower */
167         for( p_block = p_bytestream->p_block->p_next;
168              p_block != NULL; p_block = p_block->p_next )
169         {
170             if( p_block->i_buffer )
171             {
172                 *p_data = p_block->p_buffer[0];
173                 return VLC_SUCCESS;
174             }
175         }
176     }
177
178     /* Not enough data, bail out */
179     return VLC_EGENERIC;
180 }
181
182 static inline int block_GetByte( block_bytestream_t *p_bytestream,
183                                  uint8_t *p_data )
184 {
185     /* Most common case first */
186     if( p_bytestream->p_block->i_buffer - p_bytestream->i_offset )
187     {
188         *p_data = p_bytestream->p_block->p_buffer[p_bytestream->i_offset];
189         p_bytestream->i_offset++;
190         return VLC_SUCCESS;
191     }
192     else
193     {
194         block_t *p_block;
195
196         /* Less common case which is also slower */
197         for( p_block = p_bytestream->p_block->p_next;
198              p_block != NULL; p_block = p_block->p_next )
199         {
200             if( p_block->i_buffer )
201             {
202                 *p_data = p_block->p_buffer[0];
203                 p_bytestream->i_offset = 1;
204                 p_bytestream->p_block = p_block;
205                 return VLC_SUCCESS;
206             }
207         }
208     }
209
210     /* Not enough data, bail out */
211     return VLC_EGENERIC;
212 }
213
214 static inline int block_WaitBytes( block_bytestream_t *p_bytestream,
215                                    int i_data )
216 {
217     block_t *p_block;
218     int i_offset, i_copy, i_size;
219
220     /* Check we have that much data */
221     i_offset = p_bytestream->i_offset;
222     i_size = i_data;
223     i_copy = 0;
224     for( p_block = p_bytestream->p_block;
225          p_block != NULL; p_block = p_block->p_next )
226     {
227         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
228         i_size -= i_copy;
229         i_offset = 0;
230
231         if( !i_size ) break;
232     }
233
234     if( i_size )
235     {
236         /* Not enough data, bail out */
237         return VLC_EGENERIC;
238     }
239     return VLC_SUCCESS;
240 }
241
242 static inline int block_SkipBytes( block_bytestream_t *p_bytestream,
243                                    int i_data )
244 {
245     block_t *p_block;
246     int i_offset, i_copy;
247
248     /* Check we have that much data */
249     i_offset = p_bytestream->i_offset;
250     i_copy = 0;
251     for( p_block = p_bytestream->p_block;
252          p_block != NULL; p_block = p_block->p_next )
253     {
254         i_copy = __MIN( i_data, p_block->i_buffer - i_offset );
255         i_data -= i_copy;
256
257         if( !i_data ) break;
258
259         i_offset = 0;
260     }
261
262     if( i_data )
263     {
264         /* Not enough data, bail out */
265         return VLC_EGENERIC;
266     }
267
268     p_bytestream->p_block = p_block;
269     p_bytestream->i_offset = i_offset + i_copy;
270     return VLC_SUCCESS;
271 }
272
273 static inline int block_PeekBytes( block_bytestream_t *p_bytestream,
274                                    uint8_t *p_data, int i_data )
275 {
276     block_t *p_block;
277     int i_offset, i_copy, i_size;
278
279     /* Check we have that much data */
280     i_offset = p_bytestream->i_offset;
281     i_size = i_data;
282     i_copy = 0;
283     for( p_block = p_bytestream->p_block;
284          p_block != NULL; p_block = p_block->p_next )
285     {
286         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
287         i_size -= i_copy;
288         i_offset = 0;
289
290         if( !i_size ) break;
291     }
292
293     if( i_size )
294     {
295         /* Not enough data, bail out */
296         return VLC_EGENERIC;
297     }
298
299     /* Copy the data */
300     i_offset = p_bytestream->i_offset;
301     i_size = i_data;
302     i_copy = 0;
303     for( p_block = p_bytestream->p_block;
304          p_block != NULL; p_block = p_block->p_next )
305     {
306         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
307         i_size -= i_copy;
308
309         if( i_copy )
310         {
311             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
312             p_data += i_copy;
313         }
314
315         i_offset = 0;
316
317         if( !i_size ) break;
318     }
319
320     return VLC_SUCCESS;
321 }
322
323 static inline int block_GetBytes( block_bytestream_t *p_bytestream,
324                                   uint8_t *p_data, int i_data )
325 {
326     block_t *p_block;
327     int i_offset, i_copy, i_size;
328
329     /* Check we have that much data */
330     i_offset = p_bytestream->i_offset;
331     i_size = i_data;
332     i_copy = 0;
333     for( p_block = p_bytestream->p_block;
334          p_block != NULL; p_block = p_block->p_next )
335     {
336         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
337         i_size -= i_copy;
338         i_offset = 0;
339
340         if( !i_size ) break;
341     }
342
343     if( i_size )
344     {
345         /* Not enough data, bail out */
346         return VLC_EGENERIC;
347     }
348
349     /* Copy the data */
350     i_offset = p_bytestream->i_offset;
351     i_size = i_data;
352     i_copy = 0;
353     for( p_block = p_bytestream->p_block;
354          p_block != NULL; p_block = p_block->p_next )
355     {
356         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
357         i_size -= i_copy;
358
359         if( i_copy )
360         {
361             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
362             p_data += i_copy;
363         }
364
365         if( !i_size ) break;
366
367         i_offset = 0;
368     }
369
370     /* No buffer given, just skip the data */
371     p_bytestream->p_block = p_block;
372     p_bytestream->i_offset = i_offset + i_copy;
373
374     return VLC_SUCCESS;
375 }
376
377 static inline int block_PeekOffsetBytes( block_bytestream_t *p_bytestream,
378     int i_peek_offset, uint8_t *p_data, int i_data )
379 {
380     block_t *p_block;
381     int i_offset, i_copy, i_size;
382
383     /* Check we have that much data */
384     i_offset = p_bytestream->i_offset;
385     i_size = i_data + i_peek_offset;
386     i_copy = 0;
387     for( p_block = p_bytestream->p_block;
388          p_block != NULL; p_block = p_block->p_next )
389     {
390         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
391         i_size -= i_copy;
392         i_offset = 0;
393
394         if( !i_size ) break;
395     }
396
397     if( i_size )
398     {
399         /* Not enough data, bail out */
400         return VLC_EGENERIC;
401     }
402
403     /* Find the right place */
404     i_offset = p_bytestream->i_offset;
405     i_size = i_peek_offset;
406     i_copy = 0;
407     for( p_block = p_bytestream->p_block;
408          p_block != NULL; p_block = p_block->p_next )
409     {
410         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
411         i_size -= i_copy;
412
413         if( !i_size ) break;
414
415         i_offset = 0;
416     }
417
418     /* Copy the data */
419     i_offset += i_copy;
420     i_size = i_data;
421     i_copy = 0;
422     for( ; p_block != NULL; p_block = p_block->p_next )
423     {
424         i_copy = __MIN( i_size, p_block->i_buffer - i_offset );
425         i_size -= i_copy;
426
427         if( i_copy )
428         {
429             memcpy( p_data, p_block->p_buffer + i_offset, i_copy );
430             p_data += i_copy;
431         }
432
433         i_offset = 0;
434
435         if( !i_size ) break;
436     }
437
438     return VLC_SUCCESS;
439 }
440
441 static inline int block_FindStartcodeFromOffset(
442     block_bytestream_t *p_bytestream, int *pi_offset,
443     uint8_t *p_startcode, int i_startcode_length )
444 {
445     block_t *p_block, *p_block_backup = 0;
446     int i_size, i_offset, i_offset_backup = 0;
447     int i_caller_offset_backup = 0, i_match;
448
449     /* Find the right place */
450     i_size = *pi_offset + p_bytestream->i_offset;
451     for( p_block = p_bytestream->p_block;
452          p_block != NULL; p_block = p_block->p_next )
453     {
454         i_size -= p_block->i_buffer;
455         if( i_size < 0 ) break;
456     }
457
458     if( i_size >= 0 )
459     {
460         /* Not enough data, bail out */
461         return VLC_EGENERIC;
462     }
463
464     /* Begin the search.
465      * We first look for an occurrence of the 1st startcode byte and
466      * if found, we do a more thorough check. */
467     i_size = p_block->i_buffer + i_size;
468     *pi_offset -= i_size;
469     i_match = 0;
470     for( ; p_block != NULL; p_block = p_block->p_next )
471     {
472         for( i_offset = i_size; i_offset < p_block->i_buffer; i_offset++ )
473         {
474             if( p_block->p_buffer[i_offset] == p_startcode[i_match] )
475             {
476                 if( !i_match )
477                 {
478                     p_block_backup = p_block;
479                     i_offset_backup = i_offset;
480                     i_caller_offset_backup = *pi_offset;
481                 }
482
483                 if( i_match + 1 == i_startcode_length )
484                 {
485                     /* We have it */
486                     *pi_offset += i_offset - i_match;
487                     return VLC_SUCCESS;
488                 }
489
490                 i_match++;
491             }
492             else if ( i_match )
493             {
494                 /* False positive */
495                 p_block = p_block_backup;
496                 i_offset = i_offset_backup;
497                 *pi_offset = i_caller_offset_backup;
498                 i_match = 0;
499             }
500
501         }
502         i_size = 0;
503         *pi_offset += i_offset;
504     }
505
506     *pi_offset -= i_match;
507     return VLC_EGENERIC;
508 }
509
510 #endif /* VLC_BLOCK_HELPER_H */