/* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* * arith_routins.c * * This C file contains a function for finalizing the bitstream * after arithmetic coding. * */ #include "arith_routins.h" /**************************************************************************** * WebRtcIsacfix_EncTerminate(...) * * Final call to the arithmetic coder for an encoder call. This function * terminates and return byte stream. * * Input: * - streamData : in-/output struct containing bitstream * * Return value : number of bytes in the stream */ WebRtc_Word16 WebRtcIsacfix_EncTerminate(Bitstr_enc *streamData) { WebRtc_UWord16 *streamPtr; WebRtc_UWord16 negCarry; /* point to the right place in the stream buffer */ streamPtr = streamData->stream + streamData->stream_index; /* find minimum length (determined by current interval width) */ if ( streamData->W_upper > 0x01FFFFFF ) { streamData->streamval += 0x01000000; /* if result is less than the added value we must take care of the carry */ if (streamData->streamval < 0x01000000) { /* propagate carry */ if (streamData->full == 0) { /* Add value to current value */ negCarry = *streamPtr; negCarry += 0x0100; *streamPtr = negCarry; /* if value is too big, propagate carry to next byte, and so on */ while (!(negCarry)) { negCarry = *--streamPtr; negCarry++; *streamPtr = negCarry; } } else { /* propagate carry by adding one to the previous byte in the * stream if that byte is 0xFFFF we need to propagate the carry * furhter back in the stream */ while ( !(++(*--streamPtr)) ); } /* put pointer back to the old value */ streamPtr = streamData->stream + streamData->stream_index; } /* write remaining data to bitstream, if "full == 0" first byte has data */ if (streamData->full == 0) { *streamPtr++ += (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24); streamData->full = 1; } else { *streamPtr = (WebRtc_UWord16) WEBRTC_SPL_LSHIFT_W32( WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24), 8); streamData->full = 0; } } else { streamData->streamval += 0x00010000; /* if result is less than the added value we must take care of the carry */ if (streamData->streamval < 0x00010000) { /* propagate carry */ if (streamData->full == 0) { /* Add value to current value */ negCarry = *streamPtr; negCarry += 0x0100; *streamPtr = negCarry; /* if value to big, propagate carry to next byte, and so on */ while (!(negCarry)) { negCarry = *--streamPtr; negCarry++; *streamPtr = negCarry; } } else { /* Add carry to previous byte */ while ( !(++(*--streamPtr)) ); } /* put pointer back to the old value */ streamPtr = streamData->stream + streamData->stream_index; } /* write remaining data (2 bytes) to bitstream */ if (streamData->full) { *streamPtr++ = (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 16); } else { *streamPtr++ |= (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 24); *streamPtr = (WebRtc_UWord16) WEBRTC_SPL_RSHIFT_W32(streamData->streamval, 8) & 0xFF00; } } /* calculate stream length in bytes */ return (((streamPtr - streamData->stream)<<1) + !(streamData->full)); }