📄 bitstream.c
字号:
/*
* FAAC - Freeware Advanced Audio Coder
* Copyright (C) 2001 Menno Bakker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: bitstream.c,v 1.7 2002/02/25 22:26:43 dmackie Exp $
*/
#include <stdlib.h>
#include <assert.h>
#include "coder.h"
#include "channels.h"
#include "huffman.h"
#include "bitstream.h"
#include "ltp.h"
#include "util.h"
int WriteBitstream(faacEncHandle hEncoder,
CoderInfo *coderInfo,
ChannelInfo *channelInfo,
BitStream *bitStream,
int numChannel)
{
int channel;
int bits = 0;
int bitsLeftAfterFill, numFillBits;
CountBitstream(hEncoder, coderInfo, channelInfo, bitStream, numChannel);
bits += WriteADTSHeader(hEncoder, bitStream, 1);
for (channel = 0; channel < numChannel; channel++) {
if (channelInfo[channel].present) {
/* Write out a single_channel_element */
if (!channelInfo[channel].cpe) {
if (channelInfo[channel].lfe) {
/* Write out lfe */
bits += WriteLFE(&coderInfo[channel],
&channelInfo[channel],
bitStream,
hEncoder->config.aacObjectType,
1);
} else {
/* Write out sce */
bits += WriteSCE(&coderInfo[channel],
&channelInfo[channel],
bitStream,
hEncoder->config.aacObjectType,
1);
}
} else {
if (channelInfo[channel].ch_is_left) {
/* Write out cpe */
bits += WriteCPE(&coderInfo[channel],
&coderInfo[channelInfo[channel].paired_ch],
&channelInfo[channel],
bitStream,
hEncoder->config.aacObjectType,
1);
}
}
}
}
/* Compute how many fill bits are needed to avoid overflowing bit reservoir */
/* Save room for ID_END terminator */
if (bits < (8 - LEN_SE_ID) ) {
numFillBits = 8 - LEN_SE_ID - bits;
} else {
numFillBits = 0;
}
/* Write AAC fill_elements, smallest fill element is 7 bits. */
/* Function may leave up to 6 bits left after fill, so tell it to fill a few extra */
numFillBits += 6;
bitsLeftAfterFill = WriteAACFillBits(bitStream, numFillBits, 1);
bits += (numFillBits - bitsLeftAfterFill);
/* Write ID_END terminator */
bits += LEN_SE_ID;
PutBit(bitStream, ID_END, LEN_SE_ID);
/* Now byte align the bitstream */
/*
* This byte_alignment() is correct for both MPEG2 and MPEG4, although
* in MPEG4 the byte_alignment() is officially done before the new frame
* instead of at the end. But this is basically the same.
*/
assert(bitStream->numBit==bits);
bitStream->numBit=bits;
#if 0
if (hEncoder->config.mpegVersion == 0)
bits += ByteAlign(bitStream, 1,2);
#endif
bits += ByteAlign(bitStream, 1,0);
return bits;
}
static int CountBitstream(faacEncHandle hEncoder,
CoderInfo *coderInfo,
ChannelInfo *channelInfo,
BitStream *bitStream,
int numChannel)
{
int channel;
int bits = 0;
int bitsLeftAfterFill, numFillBits;
bits += WriteADTSHeader(hEncoder, bitStream, 0);
for (channel = 0; channel < numChannel; channel++) {
if (channelInfo[channel].present) {
/* Write out a single_channel_element */
if (!channelInfo[channel].cpe) {
if (channelInfo[channel].lfe) {
/* Write out lfe */
bits += WriteLFE(&coderInfo[channel],
&channelInfo[channel],
bitStream,
hEncoder->config.aacObjectType,
0);
} else {
/* Write out sce */
bits += WriteSCE(&coderInfo[channel],
&channelInfo[channel],
bitStream,
hEncoder->config.aacObjectType,
0);
}
} else {
if (channelInfo[channel].ch_is_left) {
/* Write out cpe */
bits += WriteCPE(&coderInfo[channel],
&coderInfo[channelInfo[channel].paired_ch],
&channelInfo[channel],
bitStream,
hEncoder->config.aacObjectType,
0);
}
}
}
}
/* Compute how many fill bits are needed to avoid overflowing bit reservoir */
/* Save room for ID_END terminator */
if (bits < (8 - LEN_SE_ID) ) {
numFillBits = 8 - LEN_SE_ID - bits;
} else {
numFillBits = 0;
}
/* Write AAC fill_elements, smallest fill element is 7 bits. */
/* Function may leave up to 6 bits left after fill, so tell it to fill a few extra */
numFillBits += 6;
bitsLeftAfterFill = WriteAACFillBits(bitStream, numFillBits, 0);
bits += (numFillBits - bitsLeftAfterFill);
/* Write ID_END terminator */
bits += LEN_SE_ID;
/* Now byte align the bitstream */
bitStream->numBit=bits;
#if 0
if (hEncoder->config.mpegVersion == 0)
bits += ByteAlign(bitStream, 0,2);
#endif
bits += ByteAlign(bitStream, 0,0);
hEncoder->usedBytes = bit2byte(bits);
return bits;
}
static int WriteADTSHeader(faacEncHandle hEncoder,
BitStream *bitStream,
int writeFlag)
{
int bits = 56;
#ifdef MPEG4IP
if (hEncoder->config.useAdts == 0) {
return 0;
}
#endif
if (writeFlag) {
/* Fixed ADTS header */
PutBit(bitStream, 0xFFFF, 12); /* 12 bit Syncword */
PutBit(bitStream, hEncoder->config.mpegVersion, 1); /* ID == 0 for MPEG4 AAC, 1 for MPEG2 AAC */
PutBit(bitStream, 0, 2); /* layer == 0 */
PutBit(bitStream, 1, 1); /* protection absent */
PutBit(bitStream, hEncoder->config.aacObjectType, 2); /* profile */
PutBit(bitStream, hEncoder->sampleRateIdx, 4); /* sampling rate */
PutBit(bitStream, 0, 1); /* private bit */
PutBit(bitStream, hEncoder->numChannels, 3); /* ch. config (must be > 0) */
/* simply using numChannels only works for
6 channels or less, else a channel
configuration should be written */
PutBit(bitStream, 0, 1); /* original/copy */
PutBit(bitStream, 0, 1); /* home */
if (hEncoder->config.mpegVersion == 0)
PutBit(bitStream, 0, 2); /* emphasis */
/* Variable ADTS header */
PutBit(bitStream, 0, 1); /* copyr. id. bit */
PutBit(bitStream, 0, 1); /* copyr. id. start */
PutBit(bitStream, hEncoder->usedBytes, 13);
PutBit(bitStream, 0x7FF, 11); /* buffer fullness (0x7FF for VBR) */
PutBit(bitStream, 0, 2); /* raw data blocks (0+1=1) */
}
/*
* MPEG2 says byte_aligment() here, but ADTS always is multiple of 8 bits
* MPEG4 has no byte_alignment() here
*/
/*
if (hEncoder->config.mpegVersion == 1)
bits += ByteAlign(bitStream, writeFlag);
*/
if (hEncoder->config.mpegVersion == 0)
bits += 2; /* emphasis */
return bits;
}
static int WriteCPE(CoderInfo *coderInfoL,
CoderInfo *coderInfoR,
ChannelInfo *channelInfo,
BitStream* bitStream,
int objectType,
int writeFlag)
{
int bits = 0;
if (writeFlag) {
/* write ID_CPE, single_element_channel() identifier */
PutBit(bitStream, ID_CPE, LEN_SE_ID);
/* write the element_identifier_tag */
PutBit(bitStream, channelInfo->tag, LEN_TAG);
/* common_window? */
PutBit(bitStream, channelInfo->common_window, LEN_COM_WIN);
}
bits += LEN_SE_ID;
bits += LEN_TAG;
bits += LEN_COM_WIN;
/* if common_window, write ics_info */
if (channelInfo->common_window) {
int numWindows, maxSfb;
bits += WriteICSInfo(coderInfoL, bitStream, objectType, writeFlag);
numWindows = coderInfoL->num_window_groups;
maxSfb = coderInfoL->max_sfb;
if (writeFlag) {
PutBit(bitStream, channelInfo->msInfo.is_present, LEN_MASK_PRES);
if (channelInfo->msInfo.is_present == 1) {
int g;
int b;
for (g=0;g<numWindows;g++) {
for (b=0;b<maxSfb;b++) {
PutBit(bitStream, channelInfo->msInfo.ms_used[g*maxSfb+b], LEN_MASK);
}
}
}
}
bits += LEN_MASK_PRES;
if (channelInfo->msInfo.is_present == 1)
bits += (numWindows*maxSfb*LEN_MASK);
}
/* Write individual_channel_stream elements */
bits += WriteICS(coderInfoL, bitStream, channelInfo->common_window, objectType, writeFlag);
bits += WriteICS(coderInfoR, bitStream, channelInfo->common_window, objectType, writeFlag);
return bits;
}
static int WriteSCE(CoderInfo *coderInfo,
ChannelInfo *channelInfo,
BitStream *bitStream,
int objectType,
int writeFlag)
{
int bits = 0;
if (writeFlag) {
/* write Single Element Channel (SCE) identifier */
PutBit(bitStream, ID_SCE, LEN_SE_ID);
/* write the element identifier tag */
PutBit(bitStream, channelInfo->tag, LEN_TAG);
}
bits += LEN_SE_ID;
bits += LEN_TAG;
/* Write an Individual Channel Stream element */
bits += WriteICS(coderInfo, bitStream, 0, objectType, writeFlag);
return bits;
}
static int WriteLFE(CoderInfo *coderInfo,
ChannelInfo *channelInfo,
BitStream *bitStream,
int objectType,
int writeFlag)
{
int bits = 0;
if (writeFlag) {
/* write ID_LFE, lfe_element_channel() identifier */
PutBit(bitStream, ID_LFE, LEN_SE_ID);
/* write the element_identifier_tag */
PutBit(bitStream, channelInfo->tag, LEN_TAG);
}
bits += LEN_SE_ID;
bits += LEN_TAG;
/* Write an individual_channel_stream element */
bits += WriteICS(coderInfo, bitStream, 0, objectType, writeFlag);
return bits;
}
static int WriteICSInfo(CoderInfo *coderInfo,
BitStream *bitStream,
int objectType,
int writeFlag)
{
int grouping_bits;
int bits = 0;
if (writeFlag) {
/* write out ics_info() information */
PutBit(bitStream, 0, LEN_ICS_RESERV); /* reserved Bit*/
/* Write out window sequence */
PutBit(bitStream, coderInfo->block_type, LEN_WIN_SEQ); /* block type */
/* Write out window shape */
PutBit(bitStream, coderInfo->window_shape, LEN_WIN_SH); /* window shape */
}
bits += LEN_ICS_RESERV;
bits += LEN_WIN_SEQ;
bits += LEN_WIN_SH;
/* For short windows, write out max_sfb and scale_factor_grouping */
if (coderInfo->block_type == ONLY_SHORT_WINDOW){
if (writeFlag) {
PutBit(bitStream, coderInfo->max_sfb, LEN_MAX_SFBS);
grouping_bits = FindGroupingBits(coderInfo);
PutBit(bitStream, grouping_bits, MAX_SHORT_WINDOWS - 1); /* the grouping bits */
}
bits += LEN_MAX_SFBS;
bits += MAX_SHORT_WINDOWS - 1;
} else { /* Otherwise, write out max_sfb and predictor data */
if (writeFlag) {
PutBit(bitStream, coderInfo->max_sfb, LEN_MAX_SFBL);
}
bits += LEN_MAX_SFBL;
if (objectType == LTP)
bits += WriteLTPPredictorData(coderInfo, bitStream, writeFlag);
else
bits += WritePredictorData(coderInfo, bitStream, writeFlag);
}
return bits;
}
static int WriteICS(CoderInfo *coderInfo,
BitStream *bitStream,
int commonWindow,
int objectType,
int writeFlag)
{
/* this function writes out an individual_channel_stream to the bitstream and */
/* returns the number of bits written to the bitstream */
int bits = 0;
/* Write the 8-bit global_gain */
if (writeFlag)
PutBit(bitStream, coderInfo->global_gain, LEN_GLOB_GAIN);
bits += LEN_GLOB_GAIN;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -