1 /*
2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 /*
12  * arith_routins.c
13  *
14  * This C file contains a function for finalizing the bitstream
15  * after arithmetic coding.
16  *
17  */
18 
19 #include "arith_routins.h"
20 
21 
22 /****************************************************************************
23  * WebRtcIsacfix_EncTerminate(...)
24  *
25  * Final call to the arithmetic coder for an encoder call. This function
26  * terminates and return byte stream.
27  *
28  * Input:
29  *      - streamData        : in-/output struct containing bitstream
30  *
31  * Return value             : number of bytes in the stream
32  */
WebRtcIsacfix_EncTerminate(Bitstr_enc * streamData)33 WebRtc_Word16 WebRtcIsacfix_EncTerminate(Bitstr_enc *streamData)
34 {
35   WebRtc_UWord16 *streamPtr;
36   WebRtc_UWord16 negCarry;
37 
38   /* point to the right place in the stream buffer */
39   streamPtr = streamData->stream + streamData->stream_index;
40 
41   /* find minimum length (determined by current interval width) */
42   if ( streamData->W_upper > 0x01FFFFFF )
43   {
44     streamData->streamval += 0x01000000;
45 
46     /* if result is less than the added value we must take care of the carry */
47     if (streamData->streamval < 0x01000000)
48     {
49       /* propagate carry */
50       if (streamData->full == 0) {
51         /* Add value to current value */
52         negCarry = *streamPtr;
53         negCarry += 0x0100;
54         *streamPtr = negCarry;
55 
56         /* if value is too big, propagate carry to next byte, and so on */
57         while (!(negCarry))
58         {
59           negCarry = *--streamPtr;
60           negCarry++;
61           *streamPtr = negCarry;
62         }
63       } else {
64         /* propagate carry by adding one to the previous byte in the
65          * stream if that byte is 0xFFFF we need to propagate the carry
66          * furhter back in the stream */
67         while ( !(++(*--streamPtr)) );
68       }
69 
70       /* put pointer back to the old value */
71       streamPtr = streamData->stream + streamData->stream_index;
72     }
73     /* write remaining data to bitstream, if "full == 0" first byte has data */
74     if (streamData->full == 0) {
75       *streamPtr++ += (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24);
76       streamData->full = 1;
77     } else {
78       *streamPtr = (WebRtc_UWord16) WEBRTC_SPL_LSHIFT_W32(
79           WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24), 8);
80       streamData->full = 0;
81     }
82   }
83   else
84   {
85     streamData->streamval += 0x00010000;
86 
87     /* if result is less than the added value we must take care of the carry */
88     if (streamData->streamval < 0x00010000)
89     {
90       /* propagate carry */
91       if (streamData->full == 0) {
92         /* Add value to current value */
93         negCarry = *streamPtr;
94         negCarry += 0x0100;
95         *streamPtr = negCarry;
96 
97         /* if value to big, propagate carry to next byte, and so on */
98         while (!(negCarry))
99         {
100           negCarry = *--streamPtr;
101           negCarry++;
102           *streamPtr = negCarry;
103         }
104       } else {
105         /* Add carry to previous byte */
106         while ( !(++(*--streamPtr)) );
107       }
108 
109       /* put pointer back to the old value */
110       streamPtr = streamData->stream + streamData->stream_index;
111     }
112     /* write remaining data (2 bytes) to bitstream */
113     if (streamData->full) {
114       *streamPtr++ = (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 16);
115     } else {
116       *streamPtr++ |= (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24);
117       *streamPtr = (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 8)
118           & 0xFF00;
119     }
120   }
121 
122   /* calculate stream length in bytes */
123   return (((streamPtr - streamData->stream)<<1) + !(streamData->full));
124 }
125