1
1
use crate :: fatal;
2
2
use crate :: util:: log:: ExitCause ;
3
+ use crate :: util:: log:: { debug, DebugMessageFlag } ;
3
4
use thiserror:: Error ;
4
5
5
6
#[ derive( Debug , Error ) ]
@@ -23,7 +24,12 @@ pub struct BitStreamRust<'a> {
23
24
pub _i_pos : usize ,
24
25
pub _i_bpos : u8 ,
25
26
}
26
-
27
+ #[ macro_export]
28
+ macro_rules! dbg_es {
29
+ ( $( $args: expr) ,* ) => {
30
+ debug!( msg_type = DebugMessageFlag :: VERBOSE ; "{}" , format!( $( $args) ,* ) )
31
+ } ;
32
+ }
27
33
impl < ' a > BitStreamRust < ' a > {
28
34
/// Create a new bitstream. Empty data is allowed (bits_left = 0).
29
35
pub fn new ( data : & ' a [ u8 ] ) -> Result < Self , BitstreamError > {
@@ -333,6 +339,129 @@ impl<'a> BitStreamRust<'a> {
333
339
334
340
res
335
341
}
342
+ // Return the next startcode or sequence_error_code if not enough
343
+ // data was left in the bitstream. Also set esstream->bitsleft.
344
+ // The bitstream pointer shall be moved to the begin of the start
345
+ // code if found, or to the position where a search would continue
346
+ // would more data be made available.
347
+ // This function discards all data until the start code is
348
+ // found
349
+ pub fn search_start_code ( & mut self ) -> Result < u8 , BitstreamError > {
350
+ self . make_byte_aligned ( ) ?;
351
+
352
+ // Keep a negative esstream->bitsleft, but correct it.
353
+ if self . bits_left <= 0 {
354
+ dbg_es ! ( "search_start_code: bitsleft <= 0" ) ;
355
+ self . bits_left -= 8 * 4 ;
356
+ return Ok ( 0xB4 ) ;
357
+ }
358
+
359
+ let mut tpos = self . pos ;
360
+
361
+ // Scan for 0x000001xx in header
362
+ loop {
363
+ // Find next 0x00 byte
364
+ let remaining_data = & self . data [ tpos..] ;
365
+ if let Some ( zero_offset) = remaining_data. iter ( ) . position ( |& b| b == 0x00 ) {
366
+ tpos += zero_offset;
367
+ } else {
368
+ // We don't even have the starting 0x00
369
+ tpos = self . data . len ( ) ;
370
+ self . bits_left = -8 * 4 ;
371
+ break ;
372
+ }
373
+
374
+ if tpos + 3 >= self . data . len ( ) {
375
+ // Not enough bytes left to check for 0x000001??
376
+ self . bits_left = 8 * ( self . data . len ( ) as i64 - ( tpos + 4 ) as i64 ) ;
377
+ break ;
378
+ } else if self . data [ tpos + 1 ] == 0x00 && self . data [ tpos + 2 ] == 0x01 {
379
+ // Found 0x000001??
380
+ self . bits_left = 8 * ( self . data . len ( ) as i64 - ( tpos + 4 ) as i64 ) ;
381
+ break ;
382
+ }
383
+ // Keep searching
384
+ tpos += 1 ;
385
+ }
386
+
387
+ self . pos = tpos;
388
+ if self . bits_left < 0 {
389
+ dbg_es ! ( "search_start_code: bitsleft <= 0" ) ;
390
+ Ok ( 0xB4 )
391
+ } else {
392
+ dbg_es ! ( "search_start_code: Found {:02X}" , self . data[ tpos + 3 ] ) ;
393
+ Ok ( self . data [ tpos + 3 ] )
394
+ }
395
+ }
396
+
397
+ // Return the next startcode or sequence_error_code if not enough
398
+ // data was left in the bitstream. Also set esstream->bitsleft.
399
+ // The bitstream pointer shall be moved to the begin of the start
400
+ // code if found, or to the position where a search would continue
401
+ // would more data be made available.
402
+ // Only NULL bytes before the start code are discarded, if a non
403
+ // NULL byte is encountered esstream->error is set to TRUE and the
404
+ // function returns sequence_error_code with the pointer set after
405
+ // that byte.
406
+ pub fn next_start_code ( & mut self ) -> Result < u8 , BitstreamError > {
407
+ if self . error || self . bits_left < 0 {
408
+ return Ok ( 0xB4 ) ;
409
+ }
410
+
411
+ self . make_byte_aligned ( ) ?;
412
+
413
+ // Only start looking if there is enough data. Adjust bitsleft.
414
+ if self . bits_left < 4 * 8 {
415
+ dbg_es ! ( "next_start_code: bitsleft {} < 32" , self . bits_left) ;
416
+ self . bits_left -= 8 * 4 ;
417
+ return Ok ( 0xB4 ) ;
418
+ }
419
+
420
+ let mut tmp: u8 ;
421
+ while ( self . bitstream_get_num ( 4 , false ) ? & 0x00FFFFFF ) != 0x00010000 // LSB 0x000001??
422
+ && self . bits_left > 0
423
+ {
424
+ tmp = self . bitstream_get_num ( 1 , true ) ? as u8 ;
425
+ if tmp != 0 {
426
+ dbg_es ! ( "next_start_code: Non zero stuffing" ) ;
427
+ self . error = true ;
428
+ return Ok ( 0xB4 ) ;
429
+ }
430
+ }
431
+
432
+ if self . bits_left < 8 {
433
+ self . bits_left -= 8 ;
434
+ dbg_es ! ( "next_start_code: bitsleft <= 0" ) ;
435
+ Ok ( 0xB4 )
436
+ } else {
437
+ dbg_es ! ( "next_start_code: Found {:02X}" , self . data[ self . pos + 3 ] ) ;
438
+
439
+ if self . data [ self . pos + 3 ] == 0xB4 {
440
+ dbg_es ! ( "B4: assume bitstream syntax error!" ) ;
441
+ self . error = true ;
442
+ }
443
+
444
+ Ok ( self . data [ self . pos + 3 ] )
445
+ }
446
+ }
447
+ pub fn init_bitstream ( & mut self , start : usize , end : usize ) -> Result < ( ) , BitstreamError > {
448
+ if start > end || end > self . data . len ( ) {
449
+ return Err ( BitstreamError :: InsufficientData ) ;
450
+ }
451
+
452
+ self . pos = start;
453
+ self . bpos = 8 ;
454
+ self . bits_left = ( end - start) as i64 * 8 ;
455
+ self . error = false ;
456
+ self . _i_pos = 0 ;
457
+ self . _i_bpos = 0 ;
458
+
459
+ if self . bits_left < 0 {
460
+ return Err ( BitstreamError :: NegativeLength ) ;
461
+ }
462
+
463
+ Ok ( ( ) )
464
+ }
336
465
}
337
466
#[ cfg( test) ]
338
467
mod tests {
0 commit comments