/*
(c) Copyright 1998-2001 - 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 ([email protected]).
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.
------------ Changes ------------
2000-12-05 Andre Piotrowski
- reformatted, slightly optimized
2001-01-12 ap
- use some explicit type casting to avoid compiler warnings
*/
#include <stdio.h>
#include <stdlib.h>
#if defined(_MSC)
#include <malloc.h>
#endif
#include "common.h"
#include "formatbitstream2.h"
extern char *pEncodedOutput;
extern int outputBit;
/*____ Structure Definitions _________________________________________________*/
typedef struct HeaderDef
{
int size;
int frameSize;
char data[128];
struct HeaderDef *pNext;
} Header;
/*____ 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 = NULL;
static Header *pFreeHeaderChain = NULL;
/*____ initFormatBitstream() ________________________________________________*/
void initFormatBitstream (void)
{
BitsRemaining = 0;
pHeaderChain = NULL;
pFreeHeaderChain = NULL;
}
/*____ exitFormatBitstream() _________________________________________________*/
void exitFormatBitstream (void)
{
Header *psFree;
/* Fill out the last frame with 0xFF */
flushFrame ();
/* Dealocate Headers */
while (pHeaderChain != NULL)
{
psFree = pHeaderChain;
pHeaderChain = psFree->pNext;
free (psFree);
}
while (pFreeHeaderChain != NULL)
{
psFree = pFreeHeaderChain;
pFreeHeaderChain = psFree->pNext;
free (psFree);
}
}
/*____ flushFrame() _________________________________________________________*/
void flushFrame (void)
{
/* Fill out the last frame with 0xFF */
while (BitsRemaining > 32)
{
putbits (0xFFFFFFFF, 32);
BitsRemaining -= 32;
}
if (BitsRemaining > 0)
putbits (0xFFFFFFFF, BitsRemaining);
BitsRemaining = 0;
}
/*____ 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)
{
mem_free ((void **)&wp->element);
/*
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 &= 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 gr, ch;
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 == 0) != ((data & masking) == 0) )
*/
if (!carry ^ !(data & masking))
crc ^= 0x8005;
}
}
}
crc &= 0xffff;
return crc;
}
/*____ generateHeader() ____________________________________________________*/
static int generateHeader (BF_FrameData *psFrame)
{
int gr, ch;
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) )
{} /* avoid compiler warning */
*wpLink = psHeader;
/* Generate the Header */
pOldEncodedOutput = pEncodedOutput;
pEncodedOutput = psHeader->data;
pEncodedOutput[0] = 0; /* Need to be cleared since we OR in 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, /* avoid compiler warning */
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);
BitsRemaining -= nBits;
bits += psElem->length;
}
return bits;
}
/*____ putbits() _____________________________________________________________*/
/*write n bits into the bit stream */
static void putbits
(
unsigned int val,
int n
)
{
if (n == 0)
return;
while (n >= outputBit)
{
n -= outputBit;
*pEncodedOutput |= val >> n;
outputBit = 8;
pEncodedOutput++;
*pEncodedOutput = 0;
}
if (n > 0) /* n < outputBit */
{
outputBit -= n;
*pEncodedOutput |= val << outputBit;
}
}
|