📄 formatbitstream.c
字号:
/*********************************************************************
Copyright (c) 1995 ISO/IEC JTC1 SC29 WG1, All Rights Reserved
formatBitstream.c
**********************************************************************/
/*
* $Header: /MP3Stego/MP3Stego Encoder/formatBitstream.c 4 30/11/00 15:57 Fabienpe $
*/
/*
Revision History:
Date Programmer Comment
========== ========================= ===============================
1995/09/06 mc@fivebats.com created
1995/09/18 mc@fivebats.com bugfix: WriteMainDataBits
1995/09/20 mc@fivebats.com bugfix: store_side_info
*/
#include "formatBitstream.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
/* globals */
static int BitCount = 0;
static int ThisFrameSize = 0;
static int BitsRemaining = 0;
static BitsFcnPtr PutBits = NULL;
/* forward declarations */
static int store_side_info( BF_FrameData *frameInfo );
static int main_data( BF_FrameData *frameInfo, BF_FrameResults *results );
static int side_queue_elements( int *forwardFrameLength, int *forwardSILength );
static void free_side_queues();
static void WriteMainDataBits( unsigned val,
unsigned nbits,
BF_FrameResults *results );
/*
BitStreamFrame is the public interface to the bitstream
formatting package. It writes one frame of main data per call.
Assumptions:
- The back pointer is zero on the first call
- An integral number of bytes is written each frame
You should be able to change the frame length, side info
length, #channels, #granules on a frame-by-frame basis.
See formatBitstream.h for more information about the data
structures and the bitstream syntax.
*/
void
BF_BitstreamFrame( BF_FrameData *frameInfo, BF_FrameResults *results )
{
int elements, forwardFrameLength, forwardSILength;
assert( frameInfo->nGranules <= MAX_GRANULES );
assert( frameInfo->nChannels <= MAX_CHANNELS );
/* get ptr to bit writing function */
PutBits = frameInfo->putbits;
assert( PutBits );
/* save SI and compute its length */
results->SILength = store_side_info( frameInfo );
/* write the main data, inserting SI to maintain framing */
results->mainDataLength = main_data( frameInfo, results );
/*
Caller must ensure that back SI and main data are
an integral number of bytes, since the back pointer
can only point to a byte boundary and this code
does not add stuffing bits
*/
assert( (BitsRemaining % 8) == 0 );
/* calculate nextBackPointer */
elements = side_queue_elements( &forwardFrameLength, &forwardSILength );
results->nextBackPtr = (BitsRemaining / 8) + (forwardFrameLength / 8) - (forwardSILength / 8);
}
/*
FlushBitstream writes zeros into main data
until all queued headers are written. The
queue data buffers are also freed.
*/
void
BF_FlushBitstream( BF_FrameData *frameInfo, BF_FrameResults *results )
{
int elements, forwardFrameLength, forwardSILength;
/* get ptr to bit writing function */
PutBits = frameInfo->putbits;
assert( PutBits );
elements = side_queue_elements( &forwardFrameLength, &forwardSILength );
if ( elements )
{
int bitsRemaining = forwardFrameLength - forwardSILength;
int wordsRemaining = bitsRemaining / 32;
while ( wordsRemaining-- )
WriteMainDataBits( 0, 32, results );
WriteMainDataBits( 0, (bitsRemaining % 32), results );
}
results->mainDataLength = forwardFrameLength - forwardSILength;
results->SILength = forwardSILength;
results->nextBackPtr = 0;
/* reclaim queue space */
free_side_queues();
/* reinitialize globals */
BitCount = 0;
ThisFrameSize = 0;
BitsRemaining = 0;
PutBits = NULL;
return;
}
int
BF_PartLength( BF_BitstreamPart *part )
{
BF_BitstreamElement *ep = part->element;
int i, bits;
bits = 0;
for ( i = 0; i < part->nrEntries; i++, ep++ )
bits += ep->length;
return bits;
}
/*
The following is all private to this file
*/
typedef struct
{
int frameLength;
int SILength;
int nGranules;
int nChannels;
BF_PartHolder *headerPH;
BF_PartHolder *frameSIPH;
BF_PartHolder *channelSIPH[MAX_CHANNELS];
BF_PartHolder *spectrumSIPH[MAX_GRANULES][MAX_CHANNELS];
} MYSideInfo;
static MYSideInfo *get_side_info();
static int write_side_info();
typedef int (*PartWriteFcnPtr)( BF_BitstreamPart *part, BF_FrameResults *results );
static int
writePartMainData( BF_BitstreamPart *part, BF_FrameResults *results )
{
BF_BitstreamElement *ep;
int i, bits;
assert( results );
assert( part );
bits = 0;
ep = part->element;
for ( i = 0; i < part->nrEntries; i++, ep++ )
{
WriteMainDataBits( ep->value, ep->length, results );
bits += ep->length;
}
return bits;
}
static int
writePartSideInfo( BF_BitstreamPart *part, BF_FrameResults *results )
{
BF_BitstreamElement *ep;
int i, bits;
assert( part );
bits = 0;
ep = part->element;
for ( i = 0; i < part->nrEntries; i++, ep++ )
{
(*PutBits)( ep->value, ep->length );
bits += ep->length;
}
return bits;
}
static int
main_data( BF_FrameData *fi, BF_FrameResults *results )
{
int gr, ch, bits;
PartWriteFcnPtr wp = writePartMainData;
bits = 0;
results->mainDataLength = 0;
for ( gr = 0; gr < fi->nGranules; gr++ )
for ( ch = 0; ch < fi->nChannels; ch++ )
{
bits += (*wp)( fi->scaleFactors[gr][ch], results );
bits += (*wp)( fi->codedData[gr][ch], results );
bits += (*wp)( fi->userSpectrum[gr][ch], results );
}
bits += (*wp)( fi->userFrameData, results );
return bits;
}
/*
This is a wrapper around PutBits() that makes sure that the
framing header and side info are inserted at the proper
locations
*/
static void
WriteMainDataBits( unsigned val,
unsigned nbits,
BF_FrameResults *results )
{
assert( nbits <= 32 );
if ( BitCount == ThisFrameSize )
{
BitCount = write_side_info();
BitsRemaining = ThisFrameSize - BitCount;
}
if ( nbits == 0 )
return;
if ( nbits > BitsRemaining )
{
unsigned extra = val >> (nbits - BitsRemaining);
nbits -= BitsRemaining;
(*PutBits)( extra, BitsRemaining );
BitCount = write_side_info();
BitsRemaining = ThisFrameSize - BitCount;
(*PutBits)( val, nbits );
}
else
(*PutBits)( val, nbits );
BitCount += nbits;
BitsRemaining -= nbits;
assert( BitCount <= ThisFrameSize );
assert( BitsRemaining >= 0 );
assert( (BitCount + BitsRemaining) == ThisFrameSize );
}
static int
write_side_info()
{
MYSideInfo *si;
int bits, ch, gr;
PartWriteFcnPtr wp = writePartSideInfo;
bits = 0;
si = get_side_info();
ThisFrameSize = si->frameLength;
bits += (*wp)( si->headerPH->part, NULL );
bits += (*wp)( si->frameSIPH->part, NULL );
for ( ch = 0; ch < si->nChannels; ch++ )
bits += (*wp)( si->channelSIPH[ch]->part, NULL );
for ( gr = 0; gr < si->nGranules; gr++ )
for ( ch = 0; ch < si->nChannels; ch++ )
bits += (*wp)( si->spectrumSIPH[gr][ch]->part, NULL );
return bits;
}
typedef struct side_info_link
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -