1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41 
42 #include "_highgui.h"
43 #include "bitstrm.h"
44 
45 #define  BS_DEF_BLOCK_SIZE   (1<<15)
46 
47 const ulong bs_bit_mask[] = {
48     0,
49     0x00000001, 0x00000003, 0x00000007, 0x0000000F,
50     0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,
51     0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,
52     0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,
53     0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,
54     0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,
55     0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,
56     0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF
57 };
58 
bsBSwapBlock(uchar * start,uchar * end)59 void bsBSwapBlock( uchar *start, uchar *end )
60 {
61     ulong* data = (ulong*)start;
62     int i, size = (int)(end - start+3)/4;
63 
64     for( i = 0; i < size; i++ )
65     {
66         ulong temp = data[i];
67         temp = BSWAP( temp );
68         data[i] = temp;
69     }
70 }
71 
bsIsBigEndian(void)72 bool  bsIsBigEndian( void )
73 {
74     return (((const int*)"\0\x1\x2\x3\x4\x5\x6\x7")[0] & 255) != 0;
75 }
76 
77 /////////////////////////  RBaseStream ////////////////////////////
78 
IsOpened()79 bool  RBaseStream::IsOpened()
80 {
81     return m_is_opened;
82 }
83 
Allocate()84 void  RBaseStream::Allocate()
85 {
86     if( !m_start )
87     {
88         m_start = new uchar[m_block_size + m_unGetsize];
89         m_start+= m_unGetsize;
90     }
91     m_end = m_start + m_block_size;
92     m_current = m_end;
93 }
94 
95 
RBaseStream()96 RBaseStream::RBaseStream()
97 {
98     m_start = m_end = m_current = 0;
99     m_file = 0;
100     m_block_size = BS_DEF_BLOCK_SIZE;
101     m_unGetsize = 4; // 32 bits
102     m_is_opened = false;
103     m_jmp_set = false;
104 }
105 
106 
~RBaseStream()107 RBaseStream::~RBaseStream()
108 {
109     Close();    // Close files
110     Release();  // free  buffers
111 }
112 
113 
ReadBlock()114 void  RBaseStream::ReadBlock()
115 {
116     size_t readed;
117     assert( m_file != 0 );
118 
119     // copy unget buffer
120     if( m_start )
121     {
122         memcpy( m_start - m_unGetsize, m_end - m_unGetsize, m_unGetsize );
123     }
124 
125     SetPos( GetPos() ); // normalize position
126 
127     fseek( m_file, m_block_pos, SEEK_SET );
128     readed = fread( m_start, 1, m_block_size, m_file );
129     m_end = m_start + readed;
130     m_current   -= m_block_size;
131     m_block_pos += m_block_size;
132 
133     if( readed == 0 || m_current >= m_end )
134     {
135         if( m_jmp_set )
136             longjmp( m_jmp_buf, RBS_THROW_EOS );
137     }
138 }
139 
140 
Open(const char * filename)141 bool  RBaseStream::Open( const char* filename )
142 {
143     Close();
144     Allocate();
145 
146     m_file = fopen( filename, "rb" );
147 
148     if( m_file )
149     {
150         m_is_opened = true;
151         SetPos(0);
152     }
153     return m_file != 0;
154 }
155 
Close()156 void  RBaseStream::Close()
157 {
158     if( m_file )
159     {
160         fclose( m_file );
161         m_file = 0;
162     }
163     m_is_opened = false;
164 }
165 
166 
Release()167 void  RBaseStream::Release()
168 {
169     if( m_start )
170     {
171         delete[] (m_start - m_unGetsize);
172     }
173     m_start = m_end = m_current = 0;
174 }
175 
176 
SetBlockSize(int block_size,int unGetsize)177 void  RBaseStream::SetBlockSize( int block_size, int unGetsize )
178 {
179     assert( unGetsize >= 0 && block_size > 0 &&
180            (block_size & (block_size-1)) == 0 );
181 
182     if( m_start && block_size == m_block_size && unGetsize == m_unGetsize ) return;
183     Release();
184     m_block_size = block_size;
185     m_unGetsize = unGetsize;
186     Allocate();
187 }
188 
189 
SetPos(int pos)190 void  RBaseStream::SetPos( int pos )
191 {
192     int offset = pos & (m_block_size - 1);
193     int block_pos = pos - offset;
194 
195     assert( IsOpened() && pos >= 0 );
196 
197     if( m_current < m_end && block_pos == m_block_pos - m_block_size )
198     {
199         m_current = m_start + offset;
200     }
201     else
202     {
203         m_block_pos = block_pos;
204         m_current = m_start + m_block_size + offset;
205     }
206 }
207 
208 
GetPos()209 int  RBaseStream::GetPos()
210 {
211     assert( IsOpened() );
212     return m_block_pos - m_block_size + (int)(m_current - m_start);
213 }
214 
Skip(int bytes)215 void  RBaseStream::Skip( int bytes )
216 {
217     assert( bytes >= 0 );
218     m_current += bytes;
219 }
220 
JmpBuf()221 jmp_buf& RBaseStream::JmpBuf()
222 {
223     m_jmp_set = true;
224     return m_jmp_buf;
225 }
226 
227 /////////////////////////  RLByteStream ////////////////////////////
228 
~RLByteStream()229 RLByteStream::~RLByteStream()
230 {
231 }
232 
GetByte()233 int  RLByteStream::GetByte()
234 {
235     uchar *current = m_current;
236     int   val;
237 
238     if( current >= m_end )
239     {
240         ReadBlock();
241         current = m_current;
242     }
243 
244     val = *((uchar*)current);
245     m_current = current + 1;
246     return val;
247 }
248 
249 
GetBytes(void * buffer,int count,int * readed)250 void  RLByteStream::GetBytes( void* buffer, int count, int* readed )
251 {
252     uchar*  data = (uchar*)buffer;
253     assert( count >= 0 );
254 
255     if( readed) *readed = 0;
256 
257     while( count > 0 )
258     {
259         int l;
260 
261         for(;;)
262         {
263             l = (int)(m_end - m_current);
264             if( l > count ) l = count;
265             if( l > 0 ) break;
266             ReadBlock();
267         }
268         memcpy( data, m_current, l );
269         m_current += l;
270         data += l;
271         count -= l;
272         if( readed ) *readed += l;
273     }
274 }
275 
276 
277 ////////////  RLByteStream & RMByteStream <Get[d]word>s ////////////////
278 
~RMByteStream()279 RMByteStream::~RMByteStream()
280 {
281 }
282 
283 
GetWord()284 int  RLByteStream::GetWord()
285 {
286     uchar *current = m_current;
287     int   val;
288 
289     if( current+1 < m_end )
290     {
291         val = current[0] + (current[1] << 8);
292         m_current = current + 2;
293     }
294     else
295     {
296         val = GetByte();
297         val|= GetByte() << 8;
298     }
299     return val;
300 }
301 
302 
GetDWord()303 int  RLByteStream::GetDWord()
304 {
305     uchar *current = m_current;
306     int   val;
307 
308     if( current+3 < m_end )
309     {
310         val = current[0] + (current[1] << 8) +
311               (current[2] << 16) + (current[3] << 24);
312         m_current = current + 4;
313     }
314     else
315     {
316         val = GetByte();
317         val |= GetByte() << 8;
318         val |= GetByte() << 16;
319         val |= GetByte() << 24;
320     }
321     return val;
322 }
323 
324 
GetWord()325 int  RMByteStream::GetWord()
326 {
327     uchar *current = m_current;
328     int   val;
329 
330     if( current+1 < m_end )
331     {
332         val = (current[0] << 8) + current[1];
333         m_current = current + 2;
334     }
335     else
336     {
337         val = GetByte() << 8;
338         val|= GetByte();
339     }
340     return val;
341 }
342 
343 
GetDWord()344 int  RMByteStream::GetDWord()
345 {
346     uchar *current = m_current;
347     int   val;
348 
349     if( current+3 < m_end )
350     {
351         val = (current[0] << 24) + (current[1] << 16) +
352               (current[2] << 8) + current[3];
353         m_current = current + 4;
354     }
355     else
356     {
357         val = GetByte() << 24;
358         val |= GetByte() << 16;
359         val |= GetByte() << 8;
360         val |= GetByte();
361     }
362     return val;
363 }
364 
365 
366 /////////////////////////  RLBitStream ////////////////////////////
367 
~RLBitStream()368 RLBitStream::~RLBitStream()
369 {
370 }
371 
372 
ReadBlock()373 void  RLBitStream::ReadBlock()
374 {
375     RBaseStream::ReadBlock();
376     if( bsIsBigEndian() )
377         bsBSwapBlock( m_start, m_end );
378 }
379 
380 
SetPos(int pos)381 void  RLBitStream::SetPos( int pos )
382 {
383     RBaseStream::SetPos(pos);
384     int offset = (int)(m_current - m_end);
385     m_current = m_end + (offset & -4);
386     m_bit_idx = (offset&3)*8;
387 }
388 
389 
GetPos()390 int  RLBitStream::GetPos()
391 {
392     return RBaseStream::GetPos() + (m_bit_idx >> 3);
393 }
394 
395 
Get(int bits)396 int  RLBitStream::Get( int bits )
397 {
398     int    bit_idx     = m_bit_idx;
399     int    new_bit_idx = bit_idx + bits;
400     int    mask    = new_bit_idx >= 32 ? -1 : 0;
401     ulong* current = (ulong*)m_current;
402 
403     assert( (unsigned)bits < 32 );
404 
405     if( (m_current = (uchar*)(current - mask)) >= m_end )
406     {
407         ReadBlock();
408         current = ((ulong*)m_current) + mask;
409     }
410     m_bit_idx = new_bit_idx & 31;
411     return ((current[0] >> bit_idx) |
412            ((current[1] <<-bit_idx) & mask)) & bs_bit_mask[bits];
413 }
414 
Show(int bits)415 int  RLBitStream::Show( int bits )
416 {
417     int    bit_idx = m_bit_idx;
418     int    new_bit_idx = bit_idx + bits;
419     int    mask    = new_bit_idx >= 32 ? -1 : 0;
420     ulong* current = (ulong*)m_current;
421 
422     assert( (unsigned)bits < 32 );
423 
424     if( (uchar*)(current - mask) >= m_end )
425     {
426         ReadBlock();
427         current = ((ulong*)m_current) + mask;
428         m_current = (uchar*)current;
429     }
430     return ((current[0] >> bit_idx) |
431            ((current[1] <<-bit_idx) & mask)) & bs_bit_mask[bits];
432 }
433 
434 
Move(int shift)435 void  RLBitStream::Move( int shift )
436 {
437     int new_bit_idx = m_bit_idx + shift;
438     m_current += (new_bit_idx >> 5) << 2;
439     m_bit_idx  = new_bit_idx & 31;
440 }
441 
442 
GetHuff(const short * table)443 int  RLBitStream::GetHuff( const short* table )
444 {
445     int  val;
446     int  code_bits;
447 
448     for(;;)
449     {
450         int table_bits = table[0];
451         val = table[Show(table_bits) + 2];
452         code_bits = val & 15;
453         val >>= 4;
454 
455         if( code_bits != 0 ) break;
456         table += val*2;
457         Move( table_bits );
458     }
459 
460     Move( code_bits );
461     if( val == RBS_HUFF_FORB )
462     {
463         if( m_jmp_set )
464             longjmp( m_jmp_buf, RBS_THROW_FORB );
465     }
466 
467     return val;
468 }
469 
Skip(int bytes)470 void  RLBitStream::Skip( int bytes )
471 {
472     Move( bytes*8 );
473 }
474 
475 /////////////////////////  RMBitStream ////////////////////////////
476 
477 
~RMBitStream()478 RMBitStream::~RMBitStream()
479 {
480 }
481 
482 
ReadBlock()483 void  RMBitStream::ReadBlock()
484 {
485     RBaseStream::ReadBlock();
486     if( !bsIsBigEndian() )
487         bsBSwapBlock( m_start, m_end );
488 }
489 
490 
SetPos(int pos)491 void  RMBitStream::SetPos( int pos )
492 {
493     RBaseStream::SetPos(pos);
494     int offset = (int)(m_current - m_end);
495     m_current = m_end + ((offset - 1) & -4);
496     m_bit_idx = (32 - (offset&3)*8) & 31;
497 }
498 
499 
GetPos()500 int  RMBitStream::GetPos()
501 {
502     return RBaseStream::GetPos() + ((32 - m_bit_idx) >> 3);
503 }
504 
505 
Get(int bits)506 int  RMBitStream::Get( int bits )
507 {
508     int    bit_idx = m_bit_idx - bits;
509     int    mask    = bit_idx >> 31;
510     ulong* current = ((ulong*)m_current) - mask;
511 
512     assert( (unsigned)bits < 32 );
513 
514     if( (m_current = (uchar*)current) >= m_end )
515     {
516         ReadBlock();
517         current = (ulong*)m_current;
518     }
519     m_bit_idx = bit_idx &= 31;
520     return (((current[-1] << -bit_idx) & mask)|
521              (current[0] >> bit_idx)) & bs_bit_mask[bits];
522 }
523 
524 
Show(int bits)525 int  RMBitStream::Show( int bits )
526 {
527     int    bit_idx = m_bit_idx - bits;
528     int    mask    = bit_idx >> 31;
529     ulong* current = ((ulong*)m_current) - mask;
530 
531     assert( (unsigned)bits < 32 );
532 
533     if( ((uchar*)current) >= m_end )
534     {
535         m_current = (uchar*)current;
536         ReadBlock();
537         current = (ulong*)m_current;
538         m_current -= 4;
539     }
540     return (((current[-1]<<-bit_idx) & mask)|
541              (current[0] >> bit_idx)) & bs_bit_mask[bits];
542 }
543 
544 
GetHuff(const short * table)545 int  RMBitStream::GetHuff( const short* table )
546 {
547     int  val;
548     int  code_bits;
549 
550     for(;;)
551     {
552         int table_bits = table[0];
553         val = table[Show(table_bits) + 1];
554         code_bits = val & 15;
555         val >>= 4;
556 
557         if( code_bits != 0 ) break;
558         table += val;
559         Move( table_bits );
560     }
561 
562     Move( code_bits );
563     if( val == RBS_HUFF_FORB )
564     {
565         if( m_jmp_set )
566             longjmp( m_jmp_buf, RBS_THROW_FORB );
567     }
568 
569     return val;
570 }
571 
572 
Move(int shift)573 void  RMBitStream::Move( int shift )
574 {
575     int new_bit_idx = m_bit_idx - shift;
576     m_current -= (new_bit_idx >> 5)<<2;
577     m_bit_idx  = new_bit_idx & 31;
578 }
579 
580 
Skip(int bytes)581 void  RMBitStream::Skip( int bytes )
582 {
583     Move( bytes*8 );
584 }
585 
586 
587 static const int huff_val_shift = 20, huff_code_mask = (1 << huff_val_shift) - 1;
588 
bsCreateDecodeHuffmanTable(const int * src,short * table,int max_size)589 bool bsCreateDecodeHuffmanTable( const int* src, short* table, int max_size )
590 {
591     const int forbidden_entry = (RBS_HUFF_FORB << 4)|1;
592     int       first_bits = src[0];
593     struct
594     {
595         int bits;
596         int offset;
597     }
598     sub_tables[1 << 11];
599     int  size = (1 << first_bits) + 1;
600     int  i, k;
601 
602     /* calc bit depths of sub tables */
603     memset( sub_tables, 0, ((size_t)1 << first_bits)*sizeof(sub_tables[0]) );
604     for( i = 1, k = 1; src[k] >= 0; i++ )
605     {
606         int code_count = src[k++];
607         int sb = i - first_bits;
608 
609         if( sb <= 0 )
610             k += code_count;
611         else
612             for( code_count += k; k < code_count; k++ )
613             {
614                 int  code = src[k] & huff_code_mask;
615                 sub_tables[code >> sb].bits = sb;
616             }
617     }
618 
619     /* calc offsets of sub tables and whole size of table */
620     for( i = 0; i < (1 << first_bits); i++ )
621     {
622         int b = sub_tables[i].bits;
623         if( b > 0 )
624         {
625             b = 1 << b;
626             sub_tables[i].offset = size;
627             size += b + 1;
628         }
629     }
630 
631     if( size > max_size )
632     {
633         assert(0);
634         return false;
635     }
636 
637     /* fill first table and subtables with forbidden values */
638     for( i = 0; i < size; i++ )
639     {
640         table[i] = (short)forbidden_entry;
641     }
642 
643     /* write header of first table */
644     table[0] = (short)first_bits;
645 
646     /* fill first table and sub tables */
647     for( i = 1, k = 1; src[k] >= 0; i++ )
648     {
649         int code_count = src[k++];
650         for( code_count += k; k < code_count; k++ )
651         {
652             int  table_bits= first_bits;
653             int  code_bits = i;
654             int  code = src[k] & huff_code_mask;
655             int  val  = src[k] >>huff_val_shift;
656             int  j, offset = 0;
657 
658             if( code_bits > table_bits )
659             {
660                 int idx = code >> (code_bits -= table_bits);
661                 code &= (1 << code_bits) - 1;
662                 offset   = sub_tables[idx].offset;
663                 table_bits= sub_tables[idx].bits;
664                 /* write header of subtable */
665                 table[offset]  = (short)table_bits;
666                 /* write jump to subtable */
667                 table[idx + 1]= (short)(offset << 4);
668             }
669 
670             table_bits -= code_bits;
671             assert( table_bits >= 0 );
672             val = (val << 4) | code_bits;
673             offset += (code << table_bits) + 1;
674 
675             for( j = 0; j < (1 << table_bits); j++ )
676             {
677                 assert( table[offset + j] == forbidden_entry );
678                 table[ offset + j ] = (short)val;
679             }
680         }
681     }
682     return true;
683 }
684 
685 
bsCreateSourceHuffmanTable(const uchar * src,int * dst,int max_bits,int first_bits)686 int*  bsCreateSourceHuffmanTable( const uchar* src, int* dst,
687                                   int max_bits, int first_bits )
688 {
689     int   i, val_idx, code = 0;
690     int*  table = dst;
691     *dst++ = first_bits;
692     for( i = 1, val_idx = max_bits; i <= max_bits; i++ )
693     {
694         int code_count = src[i - 1];
695         dst[0] = code_count;
696         code <<= 1;
697         for( int k = 0; k < code_count; k++ )
698         {
699             dst[k + 1] = (src[val_idx + k] << huff_val_shift)|(code + k);
700         }
701         code += code_count;
702         dst += code_count + 1;
703         val_idx += code_count;
704     }
705     dst[0] = -1;
706     return  table;
707 }
708 
709 
710 /////////////////////////// WBaseStream /////////////////////////////////
711 
712 // WBaseStream - base class for output streams
WBaseStream()713 WBaseStream::WBaseStream()
714 {
715     m_start = m_end = m_current = 0;
716     m_file = 0;
717     m_block_size = BS_DEF_BLOCK_SIZE;
718     m_is_opened = false;
719 }
720 
721 
~WBaseStream()722 WBaseStream::~WBaseStream()
723 {
724     Close();    // Close files
725     Release();  // free  buffers
726 }
727 
728 
IsOpened()729 bool  WBaseStream::IsOpened()
730 {
731     return m_is_opened;
732 }
733 
734 
Allocate()735 void  WBaseStream::Allocate()
736 {
737     if( !m_start )
738         m_start = new uchar[m_block_size];
739 
740     m_end = m_start + m_block_size;
741     m_current = m_start;
742 }
743 
744 
WriteBlock()745 void  WBaseStream::WriteBlock()
746 {
747     int size = (int)(m_current - m_start);
748     assert( m_file != 0 );
749 
750     //fseek( m_file, m_block_pos, SEEK_SET );
751     fwrite( m_start, 1, size, m_file );
752     m_current = m_start;
753 
754     /*if( written < size ) throw RBS_THROW_EOS;*/
755 
756     m_block_pos += size;
757 }
758 
759 
Open(const char * filename)760 bool  WBaseStream::Open( const char* filename )
761 {
762     Close();
763     Allocate();
764 
765     m_file = fopen( filename, "wb" );
766 
767     if( m_file )
768     {
769         m_is_opened = true;
770         m_block_pos = 0;
771         m_current = m_start;
772     }
773     return m_file != 0;
774 }
775 
776 
Close()777 void  WBaseStream::Close()
778 {
779     if( m_file )
780     {
781         WriteBlock();
782         fclose( m_file );
783         m_file = 0;
784     }
785     m_is_opened = false;
786 }
787 
788 
Release()789 void  WBaseStream::Release()
790 {
791     if( m_start )
792     {
793         delete[] m_start;
794     }
795     m_start = m_end = m_current = 0;
796 }
797 
798 
SetBlockSize(int block_size)799 void  WBaseStream::SetBlockSize( int block_size )
800 {
801     assert( block_size > 0 && (block_size & (block_size-1)) == 0 );
802 
803     if( m_start && block_size == m_block_size ) return;
804     Release();
805     m_block_size = block_size;
806     Allocate();
807 }
808 
809 
GetPos()810 int  WBaseStream::GetPos()
811 {
812     assert( IsOpened() );
813     return m_block_pos + (int)(m_current - m_start);
814 }
815 
816 
817 ///////////////////////////// WLByteStream ///////////////////////////////////
818 
~WLByteStream()819 WLByteStream::~WLByteStream()
820 {
821 }
822 
PutByte(int val)823 void WLByteStream::PutByte( int val )
824 {
825     *m_current++ = (uchar)val;
826     if( m_current >= m_end )
827         WriteBlock();
828 }
829 
830 
PutBytes(const void * buffer,int count)831 void WLByteStream::PutBytes( const void* buffer, int count )
832 {
833     uchar* data = (uchar*)buffer;
834 
835     assert( data && m_current && count >= 0 );
836 
837     while( count )
838     {
839         int l = (int)(m_end - m_current);
840 
841         if( l > count )
842             l = count;
843 
844         if( l > 0 )
845         {
846             memcpy( m_current, data, l );
847             m_current += l;
848             data += l;
849             count -= l;
850         }
851         if( m_current == m_end )
852             WriteBlock();
853     }
854 }
855 
856 
PutWord(int val)857 void WLByteStream::PutWord( int val )
858 {
859     uchar *current = m_current;
860 
861     if( current+1 < m_end )
862     {
863         current[0] = (uchar)val;
864         current[1] = (uchar)(val >> 8);
865         m_current = current + 2;
866         if( m_current == m_end )
867             WriteBlock();
868     }
869     else
870     {
871         PutByte(val);
872         PutByte(val >> 8);
873     }
874 }
875 
876 
PutDWord(int val)877 void WLByteStream::PutDWord( int val )
878 {
879     uchar *current = m_current;
880 
881     if( current+3 < m_end )
882     {
883         current[0] = (uchar)val;
884         current[1] = (uchar)(val >> 8);
885         current[2] = (uchar)(val >> 16);
886         current[3] = (uchar)(val >> 24);
887         m_current = current + 4;
888         if( m_current == m_end )
889             WriteBlock();
890     }
891     else
892     {
893         PutByte(val);
894         PutByte(val >> 8);
895         PutByte(val >> 16);
896         PutByte(val >> 24);
897     }
898 }
899 
900 
901 ///////////////////////////// WMByteStream ///////////////////////////////////
902 
~WMByteStream()903 WMByteStream::~WMByteStream()
904 {
905 }
906 
907 
PutWord(int val)908 void WMByteStream::PutWord( int val )
909 {
910     uchar *current = m_current;
911 
912     if( current+1 < m_end )
913     {
914         current[0] = (uchar)(val >> 8);
915         current[1] = (uchar)val;
916         m_current = current + 2;
917         if( m_current == m_end )
918             WriteBlock();
919     }
920     else
921     {
922         PutByte(val >> 8);
923         PutByte(val);
924     }
925 }
926 
927 
PutDWord(int val)928 void WMByteStream::PutDWord( int val )
929 {
930     uchar *current = m_current;
931 
932     if( current+3 < m_end )
933     {
934         current[0] = (uchar)(val >> 24);
935         current[1] = (uchar)(val >> 16);
936         current[2] = (uchar)(val >> 8);
937         current[3] = (uchar)val;
938         m_current = current + 4;
939         if( m_current == m_end )
940             WriteBlock();
941     }
942     else
943     {
944         PutByte(val >> 24);
945         PutByte(val >> 16);
946         PutByte(val >> 8);
947         PutByte(val);
948     }
949 }
950 
951 
952 
953 ///////////////////////////// WMBitStream ///////////////////////////////////
954 
WMBitStream()955 WMBitStream::WMBitStream()
956 {
957     m_pad_val = 0;
958     ResetBuffer();
959 }
960 
961 
~WMBitStream()962 WMBitStream::~WMBitStream()
963 {
964 }
965 
966 
Open(const char * filename)967 bool  WMBitStream::Open( const char* filename )
968 {
969     ResetBuffer();
970     return WBaseStream::Open( filename );
971 }
972 
973 
ResetBuffer()974 void  WMBitStream::ResetBuffer()
975 {
976     m_val = 0;
977     m_bit_idx = 32;
978     m_current = m_start;
979 }
980 
Flush()981 void  WMBitStream::Flush()
982 {
983     if( m_bit_idx < 32 )
984     {
985         Put( m_pad_val, m_bit_idx & 7 );
986         *((ulong*&)m_current)++ = m_val;
987     }
988 }
989 
990 
Close()991 void  WMBitStream::Close()
992 {
993     if( m_is_opened )
994     {
995         Flush();
996         WBaseStream::Close();
997     }
998 }
999 
1000 
WriteBlock()1001 void  WMBitStream::WriteBlock()
1002 {
1003     if( !bsIsBigEndian() )
1004         bsBSwapBlock( m_start, m_current );
1005     WBaseStream::WriteBlock();
1006 }
1007 
1008 
GetPos()1009 int  WMBitStream::GetPos()
1010 {
1011     return WBaseStream::GetPos() + ((32 - m_bit_idx) >> 3);
1012 }
1013 
1014 
Put(int val,int bits)1015 void  WMBitStream::Put( int val, int bits )
1016 {
1017     int  bit_idx = m_bit_idx - bits;
1018     ulong  curval = m_val;
1019 
1020     assert( 0 <= bits && bits < 32 );
1021 
1022     val &= bs_bit_mask[bits];
1023 
1024     if( bit_idx >= 0 )
1025     {
1026         curval |= val << bit_idx;
1027     }
1028     else
1029     {
1030         *((ulong*&)m_current)++ = curval | ((unsigned)val >> -bit_idx);
1031         if( m_current >= m_end )
1032         {
1033             WriteBlock();
1034         }
1035         bit_idx += 32;
1036         curval = val << bit_idx;
1037     }
1038 
1039     m_val = curval;
1040     m_bit_idx = bit_idx;
1041 }
1042 
1043 
PutHuff(int val,const ulong * table)1044 void  WMBitStream::PutHuff( int val, const ulong* table )
1045 {
1046     int min_val = (int)table[0];
1047     val -= min_val;
1048 
1049     assert( (unsigned)val < table[1] );
1050 
1051     ulong code = table[val + 2];
1052     assert( code != 0 );
1053 
1054     Put( code >> 8, code & 255 );
1055 }
1056 
1057 
bsCreateEncodeHuffmanTable(const int * src,ulong * table,int max_size)1058 bool bsCreateEncodeHuffmanTable( const int* src, ulong* table, int max_size )
1059 {
1060     int  i, k;
1061     int  min_val = INT_MAX, max_val = INT_MIN;
1062     int  size;
1063 
1064     /* calc min and max values in the table */
1065     for( i = 1, k = 1; src[k] >= 0; i++ )
1066     {
1067         int code_count = src[k++];
1068 
1069         for( code_count += k; k < code_count; k++ )
1070         {
1071             int  val = src[k] >> huff_val_shift;
1072             if( val < min_val )
1073                 min_val = val;
1074             if( val > max_val )
1075                 max_val = val;
1076         }
1077     }
1078 
1079     size = max_val - min_val + 3;
1080 
1081     if( size > max_size )
1082     {
1083         assert(0);
1084         return false;
1085     }
1086 
1087     memset( table, 0, size*sizeof(table[0]));
1088 
1089     table[0] = min_val;
1090     table[1] = size - 2;
1091 
1092     for( i = 1, k = 1; src[k] >= 0; i++ )
1093     {
1094         int code_count = src[k++];
1095 
1096         for( code_count += k; k < code_count; k++ )
1097         {
1098             int  val = src[k] >> huff_val_shift;
1099             int  code = src[k] & huff_code_mask;
1100 
1101             table[val - min_val + 2] = (code << 8) | i;
1102         }
1103     }
1104     return true;
1105 }
1106 
1107