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 #if !defined( __LIBVLC__ )
25 #error You are not libvlc or one of its plugins. You cannot include this file
28 #ifndef _VLC_BLOCK_HELPER_H
29 #define _VLC_BLOCK_HELPER_H 1
31 #include <vlc_block.h>
33 typedef struct block_bytestream_t
41 #define block_BytestreamInit( a ) __block_BytestreamInit( VLC_OBJECT(a) )
43 /*****************************************************************************
44 * block_bytestream_t management
45 *****************************************************************************/
46 static inline block_bytestream_t
__block_BytestreamInit( vlc_object_t
*p_obj
)
48 block_bytestream_t bytestream
;
50 bytestream
.i_offset
= 0;
51 bytestream
.p_chain
= bytestream
.p_block
= NULL
;
56 static inline void block_BytestreamRelease( block_bytestream_t
*p_bytestream
)
58 while( p_bytestream
->p_chain
)
61 p_next
= p_bytestream
->p_chain
->p_next
;
62 p_bytestream
->p_chain
->pf_release( p_bytestream
->p_chain
);
63 p_bytestream
->p_chain
= p_next
;
65 p_bytestream
->i_offset
= 0;
66 p_bytestream
->p_chain
= p_bytestream
->p_block
= NULL
;
69 static inline void block_BytestreamFlush( block_bytestream_t
*p_bytestream
)
71 while( p_bytestream
->p_chain
!= p_bytestream
->p_block
)
74 p_next
= p_bytestream
->p_chain
->p_next
;
75 p_bytestream
->p_chain
->pf_release( p_bytestream
->p_chain
);
76 p_bytestream
->p_chain
= p_next
;
78 while( p_bytestream
->p_block
&&
79 (p_bytestream
->p_block
->i_buffer
- p_bytestream
->i_offset
) == 0 )
82 p_next
= p_bytestream
->p_chain
->p_next
;
83 p_bytestream
->p_chain
->pf_release( p_bytestream
->p_chain
);
84 p_bytestream
->p_chain
= p_bytestream
->p_block
= p_next
;
85 p_bytestream
->i_offset
= 0;
89 static inline void block_BytestreamPush( block_bytestream_t
*p_bytestream
,
92 block_ChainAppend( &p_bytestream
->p_chain
, p_block
);
93 if( !p_bytestream
->p_block
) p_bytestream
->p_block
= p_block
;
96 static inline block_t
*block_BytestreamPop( block_bytestream_t
*p_bytestream
)
100 block_BytestreamFlush( p_bytestream
);
102 p_block
= p_bytestream
->p_block
;
103 if( p_block
== NULL
)
107 else if( !p_block
->p_next
)
109 p_block
->p_buffer
+= p_bytestream
->i_offset
;
110 p_block
->i_buffer
-= p_bytestream
->i_offset
;
111 p_bytestream
->i_offset
= 0;
112 p_bytestream
->p_chain
= p_bytestream
->p_block
= NULL
;
116 while( p_block
->p_next
&& p_block
->p_next
->p_next
)
117 p_block
= p_block
->p_next
;
120 block_t
*p_block_old
= p_block
;
121 p_block
= p_block
->p_next
;
122 p_block_old
->p_next
= NULL
;
128 static inline int block_SkipByte( block_bytestream_t
*p_bytestream
)
130 /* Most common case first */
131 if( p_bytestream
->p_block
->i_buffer
- p_bytestream
->i_offset
)
133 p_bytestream
->i_offset
++;
140 /* Less common case which is also slower */
141 for( p_block
= p_bytestream
->p_block
->p_next
;
142 p_block
!= NULL
; p_block
= p_block
->p_next
)
144 if( p_block
->i_buffer
)
146 p_bytestream
->i_offset
= 1;
147 p_bytestream
->p_block
= p_block
;
153 /* Not enough data, bail out */
157 static inline int block_PeekByte( block_bytestream_t
*p_bytestream
,
160 /* Most common case first */
161 if( p_bytestream
->p_block
->i_buffer
- p_bytestream
->i_offset
)
163 *p_data
= p_bytestream
->p_block
->p_buffer
[p_bytestream
->i_offset
];
170 /* Less common case which is also slower */
171 for( p_block
= p_bytestream
->p_block
->p_next
;
172 p_block
!= NULL
; p_block
= p_block
->p_next
)
174 if( p_block
->i_buffer
)
176 *p_data
= p_block
->p_buffer
[0];
182 /* Not enough data, bail out */
186 static inline int block_GetByte( block_bytestream_t
*p_bytestream
,
189 /* Most common case first */
190 if( p_bytestream
->p_block
->i_buffer
- p_bytestream
->i_offset
)
192 *p_data
= p_bytestream
->p_block
->p_buffer
[p_bytestream
->i_offset
];
193 p_bytestream
->i_offset
++;
200 /* Less common case which is also slower */
201 for( p_block
= p_bytestream
->p_block
->p_next
;
202 p_block
!= NULL
; p_block
= p_block
->p_next
)
204 if( p_block
->i_buffer
)
206 *p_data
= p_block
->p_buffer
[0];
207 p_bytestream
->i_offset
= 1;
208 p_bytestream
->p_block
= p_block
;
214 /* Not enough data, bail out */
218 static inline int block_WaitBytes( block_bytestream_t
*p_bytestream
,
222 int i_offset
, i_copy
, i_size
;
224 /* Check we have that much data */
225 i_offset
= p_bytestream
->i_offset
;
228 for( p_block
= p_bytestream
->p_block
;
229 p_block
!= NULL
; p_block
= p_block
->p_next
)
231 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
240 /* Not enough data, bail out */
246 static inline int block_SkipBytes( block_bytestream_t
*p_bytestream
,
250 int i_offset
, i_copy
;
252 /* Check we have that much data */
253 i_offset
= p_bytestream
->i_offset
;
255 for( p_block
= p_bytestream
->p_block
;
256 p_block
!= NULL
; p_block
= p_block
->p_next
)
258 i_copy
= __MIN( i_data
, p_block
->i_buffer
- i_offset
);
268 /* Not enough data, bail out */
272 p_bytestream
->p_block
= p_block
;
273 p_bytestream
->i_offset
= i_offset
+ i_copy
;
277 static inline int block_PeekBytes( block_bytestream_t
*p_bytestream
,
278 uint8_t *p_data
, int i_data
)
281 int i_offset
, i_copy
, i_size
;
283 /* Check we have that much data */
284 i_offset
= p_bytestream
->i_offset
;
287 for( p_block
= p_bytestream
->p_block
;
288 p_block
!= NULL
; p_block
= p_block
->p_next
)
290 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
299 /* Not enough data, bail out */
304 i_offset
= p_bytestream
->i_offset
;
307 for( p_block
= p_bytestream
->p_block
;
308 p_block
!= NULL
; p_block
= p_block
->p_next
)
310 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
315 memcpy( p_data
, p_block
->p_buffer
+ i_offset
, i_copy
);
327 static inline int block_GetBytes( block_bytestream_t
*p_bytestream
,
328 uint8_t *p_data
, int i_data
)
331 int i_offset
, i_copy
, i_size
;
333 /* Check we have that much data */
334 i_offset
= p_bytestream
->i_offset
;
337 for( p_block
= p_bytestream
->p_block
;
338 p_block
!= NULL
; p_block
= p_block
->p_next
)
340 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
349 /* Not enough data, bail out */
354 i_offset
= p_bytestream
->i_offset
;
357 for( p_block
= p_bytestream
->p_block
;
358 p_block
!= NULL
; p_block
= p_block
->p_next
)
360 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
365 memcpy( p_data
, p_block
->p_buffer
+ i_offset
, i_copy
);
374 /* No buffer given, just skip the data */
375 p_bytestream
->p_block
= p_block
;
376 p_bytestream
->i_offset
= i_offset
+ i_copy
;
381 static inline int block_PeekOffsetBytes( block_bytestream_t
*p_bytestream
,
382 int i_peek_offset
, uint8_t *p_data
, int i_data
)
385 int i_offset
, i_copy
, i_size
;
387 /* Check we have that much data */
388 i_offset
= p_bytestream
->i_offset
;
389 i_size
= i_data
+ i_peek_offset
;
391 for( p_block
= p_bytestream
->p_block
;
392 p_block
!= NULL
; p_block
= p_block
->p_next
)
394 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
403 /* Not enough data, bail out */
407 /* Find the right place */
408 i_offset
= p_bytestream
->i_offset
;
409 i_size
= i_peek_offset
;
411 for( p_block
= p_bytestream
->p_block
;
412 p_block
!= NULL
; p_block
= p_block
->p_next
)
414 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
426 for( ; p_block
!= NULL
; p_block
= p_block
->p_next
)
428 i_copy
= __MIN( i_size
, p_block
->i_buffer
- i_offset
);
433 memcpy( p_data
, p_block
->p_buffer
+ i_offset
, i_copy
);
445 static inline int block_FindStartcodeFromOffset(
446 block_bytestream_t
*p_bytestream
, int *pi_offset
,
447 uint8_t *p_startcode
, int i_startcode_length
)
449 block_t
*p_block
, *p_block_backup
= 0;
450 int i_size
, i_offset
, i_offset_backup
= 0;
451 int i_caller_offset_backup
= 0, i_match
;
453 /* Find the right place */
454 i_size
= *pi_offset
+ p_bytestream
->i_offset
;
455 for( p_block
= p_bytestream
->p_block
;
456 p_block
!= NULL
; p_block
= p_block
->p_next
)
458 i_size
-= p_block
->i_buffer
;
459 if( i_size
< 0 ) break;
464 /* Not enough data, bail out */
469 * We first look for an occurrence of the 1st startcode byte and
470 * if found, we do a more thorough check. */
471 i_size
= p_block
->i_buffer
+ i_size
;
472 *pi_offset
-= i_size
;
474 for( ; p_block
!= NULL
; p_block
= p_block
->p_next
)
476 for( i_offset
= i_size
; i_offset
< p_block
->i_buffer
; i_offset
++ )
478 if( p_block
->p_buffer
[i_offset
] == p_startcode
[i_match
] )
482 p_block_backup
= p_block
;
483 i_offset_backup
= i_offset
;
484 i_caller_offset_backup
= *pi_offset
;
487 if( i_match
+ 1 == i_startcode_length
)
490 *pi_offset
+= i_offset
- i_match
;
499 p_block
= p_block_backup
;
500 i_offset
= i_offset_backup
;
501 *pi_offset
= i_caller_offset_backup
;
507 *pi_offset
+= i_offset
;
510 *pi_offset
-= i_match
;
514 #endif /* VLC_BLOCK_HELPER_H */