1 /*****************************************************************************
2 * vlc_block_helper.h: Helper functions for data blocks management.
3 *****************************************************************************
4 * Copyright (C) 2003 the VideoLAN team
7 * Authors: Gildas Bazin <gbazin@netcourrier.com>
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.
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.
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 *****************************************************************************/
24 #ifndef VLC_BLOCK_HELPER_H
25 #define VLC_BLOCK_HELPER_H 1
27 #include <vlc_block.h>
29 typedef struct block_bytestream_t
37 /*****************************************************************************
38 * block_bytestream_t management
39 *****************************************************************************/
40 static inline block_bytestream_t
block_BytestreamInit( void )
42 block_bytestream_t bytestream
;
44 bytestream
.i_offset
= 0;
45 bytestream
.p_chain
= bytestream
.p_block
= NULL
;
50 static inline void block_BytestreamRelease( block_bytestream_t
*p_bytestream
)
52 while( p_bytestream
->p_chain
)
55 p_next
= p_bytestream
->p_chain
->p_next
;
56 p_bytestream
->p_chain
->pf_release( p_bytestream
->p_chain
);
57 p_bytestream
->p_chain
= p_next
;
59 p_bytestream
->i_offset
= 0;
60 p_bytestream
->p_chain
= p_bytestream
->p_block
= NULL
;
64 * It flush all data (read and unread) from a block_bytestream_t.
66 static inline void block_BytestreamEmpty( block_bytestream_t
*p_bytestream
)
68 block_BytestreamRelease( p_bytestream
);
70 *p_bytestream
= block_BytestreamInit();
74 * It flushes all already read data from a block_bytestream_t.
76 static inline void block_BytestreamFlush( block_bytestream_t
*p_bytestream
)
78 while( p_bytestream
->p_chain
!= p_bytestream
->p_block
)
81 p_next
= p_bytestream
->p_chain
->p_next
;
82 p_bytestream
->p_chain
->pf_release( p_bytestream
->p_chain
);
83 p_bytestream
->p_chain
= p_next
;
85 while( p_bytestream
->p_block
&&
86 (p_bytestream
->p_block
->i_buffer
- p_bytestream
->i_offset
) == 0 )
89 p_next
= p_bytestream
->p_chain
->p_next
;
90 p_bytestream
->p_chain
->pf_release( p_bytestream
->p_chain
);
91 p_bytestream
->p_chain
= p_bytestream
->p_block
= p_next
;
92 p_bytestream
->i_offset
= 0;
96 static inline void block_BytestreamPush( block_bytestream_t
*p_bytestream
,
99 block_ChainAppend( &p_bytestream
->p_chain
, p_block
);
100 if( !p_bytestream
->p_block
) p_bytestream
->p_block
= p_block
;
104 static inline block_t
*block_BytestreamPop( block_bytestream_t
*p_bytestream
)
108 block_BytestreamFlush( p_bytestream
);
110 p_block
= p_bytestream
->p_block
;
111 if( p_block
== NULL
)
115 else if( !p_block
->p_next
)
117 p_block
->p_buffer
+= p_bytestream
->i_offset
;
118 p_block
->i_buffer
-= p_bytestream
->i_offset
;
119 p_bytestream
->i_offset
= 0;
120 p_bytestream
->p_chain
= p_bytestream
->p_block
= NULL
;
124 while( p_block
->p_next
&& p_block
->p_next
->p_next
)
125 p_block
= p_block
->p_next
;
128 block_t
*p_block_old
= p_block
;
129 p_block
= p_block
->p_next
;
130 p_block_old
->p_next
= NULL
;
136 static inline int block_SkipByte( block_bytestream_t
*p_bytestream
)
138 /* Most common case first */
139 if( p_bytestream
->p_block
->i_buffer
- p_bytestream
->i_offset
)
141 p_bytestream
->i_offset
++;
148 /* Less common case which is also slower */
149 for( p_block
= p_bytestream
->p_block
->p_next
;
150 p_block
!= NULL
; p_block
= p_block
->p_next
)
152 if( p_block
->i_buffer
)
154 p_bytestream
->i_offset
= 1;
155 p_bytestream
->p_block
= p_block
;
161 /* Not enough data, bail out */
165 static inline int block_PeekByte( block_bytestream_t
*p_bytestream
,
168 /* Most common case first */
169 if( p_bytestream
->p_block
->i_buffer
- p_bytestream
->i_offset
)
171 *p_data
= p_bytestream
->p_block
->p_buffer
[p_bytestream
->i_offset
];
178 /* Less common case which is also slower */
179 for( p_block
= p_bytestream
->p_block
->p_next
;
180 p_block
!= NULL
; p_block
= p_block
->p_next
)
182 if( p_block
->i_buffer
)
184 *p_data
= p_block
->p_buffer
[0];
190 /* Not enough data, bail out */
194 static inline int block_GetByte( block_bytestream_t
*p_bytestream
,
197 /* Most common case first */
198 if( p_bytestream
->p_block
->i_buffer
- p_bytestream
->i_offset
)
200 *p_data
= p_bytestream
->p_block
->p_buffer
[p_bytestream
->i_offset
];
201 p_bytestream
->i_offset
++;
208 /* Less common case which is also slower */
209 for( p_block
= p_bytestream
->p_block
->p_next
;
210 p_block
!= NULL
; p_block
= p_block
->p_next
)
212 if( p_block
->i_buffer
)
214 *p_data
= p_block
->p_buffer
[0];
215 p_bytestream
->i_offset
= 1;
216 p_bytestream
->p_block
= p_block
;
222 /* Not enough data, bail out */
226 static inline int block_WaitBytes( block_bytestream_t
*p_bytestream
,
230 size_t i_offset
, i_copy
, i_size
;
232 /* Check we have that much data */
233 i_offset
= p_bytestream
->i_offset
;
236 for( p_block
= p_bytestream
->p_block
;
237 p_block
!= NULL
; p_block
= p_block
->p_next
)
239 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
248 /* Not enough data, bail out */
254 static inline int block_SkipBytes( block_bytestream_t
*p_bytestream
,
258 size_t i_offset
, i_copy
;
260 /* Check we have that much data */
261 i_offset
= p_bytestream
->i_offset
;
263 for( p_block
= p_bytestream
->p_block
;
264 p_block
!= NULL
; p_block
= p_block
->p_next
)
266 i_copy
= __MIN( i_data
, p_block
->i_buffer
- i_offset
);
276 /* Not enough data, bail out */
280 p_bytestream
->p_block
= p_block
;
281 p_bytestream
->i_offset
= i_offset
+ i_copy
;
285 static inline int block_PeekBytes( block_bytestream_t
*p_bytestream
,
286 uint8_t *p_data
, size_t i_data
)
289 size_t i_offset
, i_copy
, i_size
;
291 /* Check we have that much data */
292 i_offset
= p_bytestream
->i_offset
;
295 for( p_block
= p_bytestream
->p_block
;
296 p_block
!= NULL
; p_block
= p_block
->p_next
)
298 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
307 /* Not enough data, bail out */
312 i_offset
= p_bytestream
->i_offset
;
315 for( p_block
= p_bytestream
->p_block
;
316 p_block
!= NULL
; p_block
= p_block
->p_next
)
318 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
323 memcpy( p_data
, p_block
->p_buffer
+ i_offset
, i_copy
);
335 static inline int block_GetBytes( block_bytestream_t
*p_bytestream
,
336 uint8_t *p_data
, size_t i_data
)
339 size_t i_offset
, i_copy
, i_size
;
341 /* Check we have that much data */
342 i_offset
= p_bytestream
->i_offset
;
345 for( p_block
= p_bytestream
->p_block
;
346 p_block
!= NULL
; p_block
= p_block
->p_next
)
348 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
357 /* Not enough data, bail out */
362 i_offset
= p_bytestream
->i_offset
;
365 for( p_block
= p_bytestream
->p_block
;
366 p_block
!= NULL
; p_block
= p_block
->p_next
)
368 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
373 memcpy( p_data
, p_block
->p_buffer
+ i_offset
, i_copy
);
382 /* No buffer given, just skip the data */
383 p_bytestream
->p_block
= p_block
;
384 p_bytestream
->i_offset
= i_offset
+ i_copy
;
389 static inline int block_PeekOffsetBytes( block_bytestream_t
*p_bytestream
,
390 size_t i_peek_offset
, uint8_t *p_data
, size_t i_data
)
393 size_t i_offset
, i_copy
, i_size
;
395 /* Check we have that much data */
396 i_offset
= p_bytestream
->i_offset
;
397 i_size
= i_data
+ i_peek_offset
;
399 for( p_block
= p_bytestream
->p_block
;
400 p_block
!= NULL
; p_block
= p_block
->p_next
)
402 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
411 /* Not enough data, bail out */
415 /* Find the right place */
416 i_offset
= p_bytestream
->i_offset
;
417 i_size
= i_peek_offset
;
419 for( p_block
= p_bytestream
->p_block
;
420 p_block
!= NULL
; p_block
= p_block
->p_next
)
422 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
434 for( ; p_block
!= NULL
; p_block
= p_block
->p_next
)
436 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
441 memcpy( p_data
, p_block
->p_buffer
+ i_offset
, i_copy
);
453 static inline int block_FindStartcodeFromOffset(
454 block_bytestream_t
*p_bytestream
, size_t *pi_offset
,
455 const uint8_t *p_startcode
, int i_startcode_length
)
457 block_t
*p_block
, *p_block_backup
= 0;
459 size_t i_offset
, i_offset_backup
= 0;
460 int i_caller_offset_backup
= 0, i_match
;
462 /* Find the right place */
463 i_size
= *pi_offset
+ p_bytestream
->i_offset
;
464 for( p_block
= p_bytestream
->p_block
;
465 p_block
!= NULL
; p_block
= p_block
->p_next
)
467 i_size
-= p_block
->i_buffer
;
468 if( i_size
< 0 ) break;
473 /* Not enough data, bail out */
478 * We first look for an occurrence of the 1st startcode byte and
479 * if found, we do a more thorough check. */
480 i_size
+= p_block
->i_buffer
;
481 *pi_offset
-= i_size
;
483 for( ; p_block
!= NULL
; p_block
= p_block
->p_next
)
485 for( i_offset
= i_size
; i_offset
< p_block
->i_buffer
; i_offset
++ )
487 if( p_block
->p_buffer
[i_offset
] == p_startcode
[i_match
] )
491 p_block_backup
= p_block
;
492 i_offset_backup
= i_offset
;
493 i_caller_offset_backup
= *pi_offset
;
496 if( i_match
+ 1 == i_startcode_length
)
499 *pi_offset
+= i_offset
- i_match
;
508 p_block
= p_block_backup
;
509 i_offset
= i_offset_backup
;
510 *pi_offset
= i_caller_offset_backup
;
516 *pi_offset
+= i_offset
;
519 *pi_offset
-= i_match
;
523 #endif /* VLC_BLOCK_HELPER_H */