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