www.pudn.com > bladeenc-0.90.0-src.zip > formatbitstream2.c
/* (c) Copyright 1998, 1999 - Tord Jansson ======================================= This file is part of the BladeEnc MP3 Encoder, based on ISO's reference code for MPEG Layer 3 compression. This file doesn't contain any of the ISO reference code and is copyright Tord Jansson (tord.jansson@swipnet.se). BladeEnc is free software; you can redistribute this file 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. */ #include#include #if !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(TARGET_OS_MAC) #include #endif #include "formatbitstream2.h" #include "common.h" extern char * pEncodedOutput; extern int outputBit; /*____ Structure Definitions _________________________________________________*/ typedef struct HeaderDef Header; struct HeaderDef { int size; int frameSize; char data[128]; Header * pNext; }; /*____ Function Prototypes ___________________________________________________*/ static int writeMainDataBits( BF_FrameData * psFrame, BitHolder *psBH ); static void putbits(unsigned int val, int n); static int generateHeader( BF_FrameData * psFrame ); /*____ Static Data ___________________________________________________________*/ static int BitsRemaining = 0; static Header * pHeaderChain; static Header * pFreeHeaderChain; /*____ initFormatBitstream() ________________________________________________*/ void initFormatBitstream( void ) { BitsRemaining = 0; pHeaderChain = NULL; pFreeHeaderChain = NULL; } /*____ exitFormatBitstream() _________________________________________________*/ void exitFormatBitstream( void ) { Header * psHeader; Header * psFree; /* Fill out the last frame with 0xFF */ while( BitsRemaining > 32 ) { putbits( 0xFFFFFFFF, 32 ); BitsRemaining -= 32; } if( BitsRemaining > 0 ) putbits( 0xFFFFFFFF, BitsRemaining ); /* Dealocate Headers */ psHeader = pHeaderChain; while( psHeader != NULL ) { psFree = psHeader; psHeader = psHeader->pNext; free( psFree ); } psHeader = pFreeHeaderChain; while( psHeader != NULL ) { psFree = psHeader; psHeader = psHeader->pNext; free( psFree ); } } /*____ initBitHolder() ______________________________________________________*/ BitHolder * initBitHolder( BitHolder * wp, int elements ) { wp->element = (BitHolderElement *) malloc( sizeof( BitHolderElement ) * elements ); wp->max_elements = elements; wp->nrEntries = 0; return wp; } /*____ exitBitHolder() ______________________________________________________*/ void exitBitHolder( BitHolder * wp ) { if( wp->element != NULL ) free( wp->element ); wp->element = NULL; } /*____ addBits() ____________________________________________________________*/ void addBits( BitHolder * wp, unsigned int value, int length ) { if( length != 0 ) { if( wp->nrEntries == wp->max_elements ) { printf( "ERROR: BitHolder overflow!\n" ); exit( -1 ); } value = value & ((0xFFFFFFFF)>>(32-length)); wp->element[wp->nrEntries].value = value; wp->element[wp->nrEntries].length = length; wp->nrEntries++; } } /*____ writeFrame() _________________________________________________________*/ void writeFrame( BF_FrameData *psFrame, BF_FrameResults *results ) { int bits; int ch, gr; int sizeRemainHeaders, sizeRemainFrames; Header * psHeader; /* Generate and save header, return size of SideInfo.*/ results->SILength = generateHeader( psFrame ); /* Put the bits and compute size of mainData */ bits = 0; for ( gr = 0; gr < psFrame->nGranules; gr++ ) for ( ch = 0; ch < psFrame->nChannels; ch++ ) { bits += writeMainDataBits( psFrame, &psFrame->scaleFactors[gr][ch] ); bits += writeMainDataBits( psFrame, &psFrame->codedData[gr][ch] ); bits += writeMainDataBits( psFrame, &psFrame->userSpectrum[gr][ch] ); } bits += writeMainDataBits( psFrame, &psFrame->userFrameData ); results->mainDataLength = bits; /* calculate nextBackPointer */ sizeRemainHeaders = 0; sizeRemainFrames = 0; for( psHeader = pHeaderChain ; psHeader != NULL ; psHeader = psHeader->pNext ) { sizeRemainHeaders += psHeader->size; sizeRemainFrames += psHeader->frameSize; } results->nextBackPtr = (BitsRemaining / 8) + sizeRemainFrames - sizeRemainHeaders; /* BitsRemaining must be dividable by 8 */ } /*============================================================================= >>> Static Functions <<< =============================================================================*/ /*____ writeBitHolder() _____________________________________________________*/ static void writeBitHolder( BitHolder * part ) { BitHolderElement * ep; int i; ep = part->element; for ( i = 0; i < part->nrEntries; i++, ep++ ) putbits( ep->value, ep->length ); } /*____ calcCRC() ____________________________________________________________*/ static int calcCRC( char * pData, int size ) { int i; int crc = 0xffff; int masking; int carry; int data; for( i = 2 ; i < size ; i++ ) { if( i != 4 && i != 5 ) { masking = 1 << 8; data = pData[i]; while( masking >>= 1 ) { carry = crc & 0x8000; crc <<= 1; if (!carry ^ !(data & masking)) crc ^= 0x8005; } } } crc &= 0xffff; return crc; } /*____ generateHeader() ____________________________________________________*/ static int generateHeader( BF_FrameData * psFrame ) { int ch, gr; int crc; Header * psHeader; Header **wpLink; char * pOldEncodedOutput; /* Get a Free Header structure */ if( pFreeHeaderChain == NULL ) psHeader = (Header *) malloc( sizeof( Header ) ); else { psHeader = pFreeHeaderChain; pFreeHeaderChain = psHeader->pNext; } psHeader->pNext = NULL; for( wpLink = &pHeaderChain ; * wpLink != NULL ; wpLink = &((*wpLink)->pNext) ); *wpLink = psHeader; /* Generate the Header */ pOldEncodedOutput = pEncodedOutput; pEncodedOutput = psHeader->data; writeBitHolder( &psFrame->header ); writeBitHolder( &psFrame->frameSI ); for ( ch = 0; ch < psFrame->nChannels; ch++ ) writeBitHolder( &psFrame->channelSI[ch] ); for ( gr = 0; gr < psFrame->nGranules; gr++ ) for ( ch = 0; ch < psFrame->nChannels; ch++ ) writeBitHolder( &psFrame->spectrumSI[gr][ch] ); /* Checksum generation (if CRC enabled).*/ if( !(psHeader->data[1] & 0x1) ) { crc = calcCRC( psHeader->data, pEncodedOutput - psHeader->data ); psHeader->data[4] = (char) (crc >> 8); psHeader->data[5] = (char) crc; } psHeader->size = pEncodedOutput - psHeader->data; psHeader->frameSize = psFrame->frameLength/8; pEncodedOutput = pOldEncodedOutput; return psHeader->size*8; } /*____ writeHeader() _______________________________________________________*/ static int writeHeader( void ) { Header * psHeader; psHeader = pHeaderChain; memcpy( pEncodedOutput, psHeader->data, psHeader->size ); pEncodedOutput += psHeader->size; * pEncodedOutput = 0; pHeaderChain = psHeader->pNext; psHeader->pNext = pFreeHeaderChain; pFreeHeaderChain = psHeader; return (psHeader->frameSize - psHeader->size)*8; } /*____ writeMainDataBits() __________________________________________________*/ static int writeMainDataBits( BF_FrameData * psFrame, BitHolder *psBH ) { BitHolderElement * psElem = psBH->element; int i, bits = 0; unsigned int val; int nBits; for ( i = 0; i < psBH->nrEntries; i++, psElem++ ) { val = psElem->value; nBits = psElem->length; if ( BitsRemaining == 0 ) BitsRemaining = writeHeader(); if ( nBits > BitsRemaining ) { nBits -= BitsRemaining; putbits( val >> nBits, BitsRemaining ); BitsRemaining = writeHeader(); putbits( val, nBits ); } else putbits( val, nBits ); BitsRemaining -= nBits; bits += psElem->length; } return bits; } /*____ putbits() _____________________________________________________________*/ /*write n bits into the bit stream */ static void putbits(unsigned int val, int n) { int x; while (n > 0) { x = MIN(n, outputBit); n -= x; outputBit -= x; * pEncodedOutput |= (val >> n) << outputBit; if (!outputBit) { outputBit = 8; pEncodedOutput++; * pEncodedOutput = 0; } } }