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