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 */
33WebRtc_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