📄 bitstream.c
字号:
/**********************************************************************
MPEG-4 Audio VM
Bit stream module
This software module was originally developed by
Heiko Purnhagen (University of Hannover / ACTS-MoMuSys)
and edited by
Ralph Sperschneider (Fraunhofer IIS)
Thomas Schaefer (Fraunhofer IIS)
in the course of development of the MPEG-2 NBC/MPEG-4 Audio standard
ISO/IEC 13818-7, 14496-1,2 and 3. This software module is an
implementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio tools
as specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC gives
users of the MPEG-2 NBC/MPEG-4 Audio standards free license to this
software module or modifications thereof for use in hardware or
software products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audio
standards. Those intending to use this software module in hardware or
software products are advised that this use may infringe existing
patents. The original developer of this software module and his/her
company, the subsequent editors and their companies, and ISO/IEC have
no liability for use of this software module or modifications thereof
in an implementation. Copyright is not released for non MPEG-2
NBC/MPEG-4 Audio conforming products. The original developer retains
full right to use the code for his/her own purpose, assign or donate
the code to a third party and to inhibit third party from using the
code for non MPEG-2 NBC/MPEG-4 Audio conforming products. This
copyright notice must be included in all copies or derivative works.
Copyright (c) 1996, 1997, 1998.
Source file: bitstream.c
$Id: bitstream.c,v 1.3 2002/07/08 15:04:15 mvillari Exp $
Required modules:
common.o common module
Authors:
HP Heiko Purnhagen, Uni Hannover <purnhage@tnt.uni-hannover.de>
BT Bodo Teichmann, FhG/IIS <tmn@iis.fhg.de>
Changes:
06-jun-96 HP added buffers, ASCII-header and BsGetBufferAhead()
07-jun-96 HP use CommonWarning(), CommonExit()
11-jun-96 HP ...
13-jun-96 HP changed BsGetBit(), BsPutBit(), BsGetBuffer(),
BsGetBufferAhead(), BsPutBuffer()
14-jun-96 HP fixed bug in BsOpenFileRead(), read header
18-jun-96 HP fixed bug in BsGetBuffer()
26-aug-96 HP CVS
23-oct-96 HP free for BsOpenFileRead() info string
07-nov-96 HP fixed BsBitStream info bug
15-nov-96 HP changed int to long where required
added BsGetBitChar(), BsGetBitShort(), BsGetBitInt()
improved file header handling
04-dec-96 HP fixed bug in BsGetBitXxx() for numBit==0
23-dec-96 HP renamed mode to write in BsBitStream
10-jan-97 HP added BsGetBitAhead(), BsGetSkip()
17-jan-97 HP fixed read file buffer bug
30-jan-97 HP minor bug fix in read bitstream file magic string
19-feb-97 HP made internal data structures invisible
04-apr-97 BT/HP added BsGetBufferAppend()
07-max-97 BT added BsGetBitBack()
14-mrz-98 sfr added CreateEpInfo(), BsReadInfoFile(), BsGetBitEP(),
BsGetBitEP()
20-jan-99 HP due to the nature of some of the modifications merged
into this code, I disclaim any responsibility for this
code and/or its readability -- sorry ...
21-jan-99 HP trying to clean up a bit ...
22-jan-99 HP added "-" stdin/stdout support
variable file buffer size for streaming
05-feb-99 HP added fflush() after fwrite()
12-feb-99 BT/HP updated ...
19-apr-99 HP cleaning up some header files again :-(
**********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bitstream.h" /* bit stream module */
#include "common_m4a.h" /* common module */
#include "buffersHandle.h" /* undesired, but ... */
/* ---------- declarations ---------- */
#include "bitstreamStruct.h" /* structs */
#define MIN_FILE_BUF_SIZE 1024 /* min num bytes in file buffer */
#define HEADER_BUF_SIZE 2048 /* max size of ASCII header */
#define COMMENT_LENGTH 1024 /* max nr of comment characters */
/* in predefinition file */
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) ((a) > (b) ? (a) : (b))
#endif
#define BYTE_NUMBIT 8 /* bits in byte (char) */
#define LONG_NUMBIT 32 /* bits in unsigned long */
#define bit2byte(a) (((a)+BYTE_NUMBIT-1)/BYTE_NUMBIT)
#define byte2bit(a) ((a)*BYTE_NUMBIT)
/* ---------- declarations (structures) ---------- */
/* ---------- variables ---------- */
static int BSdebugLevel = 0; /* debug level */
static int BSaacEOF = 0;
static long BSbufSizeByte = MIN_FILE_BUF_SIZE; /* num bytes file buf */
static long BSstreamId = 0; /* stream id counter */
/* ---------- internal functions ---------- */
/* BsReadFile() */
/* Read one buffer from file. */
static int BsReadFile (
BsBitStream *stream) /* in: stream */
/* returns: 0=OK 1=error */
{
long numByte;
long numByteRead;
long curBuf;
if (BSdebugLevel >= 3)
printf("BsReadFile: id=%ld streamNumByte=%ld curBit=%ld\n",
stream->streamId,stream->numByte,stream->currentBit);
if (feof(stream->file))
return 0;
numByte = bit2byte(stream->buffer[0]->size);
if (stream->numByte % numByte != 0) {
CommonWarning("BsReadFile: bit stream buffer error");
return 1;
}
curBuf = (stream->numByte / numByte) % 2;
numByteRead = fread(stream->buffer[curBuf]->data,sizeof(char),numByte,
stream->file);
if (ferror(stream->file)) {
CommonWarning("BsReadFile: error reading bit stream file");
return 1;
}
stream->numByte += numByteRead;
if (BSdebugLevel >= 3)
printf("BsReadFile: numByte=%ld numByteRead=%ld\n",numByte,numByteRead);
return 0;
}
/* BsWriteFile() */
/* Write one buffer to file. */
static int BsWriteFile (
BsBitStream *stream) /* in: stream */
/* returns: 0=OK 1=error */
{
long numByte;
long numByteWritten;
if (BSdebugLevel >= 3)
printf("BsWriteFile: id=%ld streamNumByte=%ld curBit=%ld\n",
stream->streamId,stream->numByte,stream->currentBit);
if (stream->numByte % bit2byte(stream->buffer[0]->size) != 0) {
CommonWarning("BsWriteFile: bit stream buffer error");
return 1;
}
numByte = bit2byte(stream->currentBit) - stream->numByte;
numByteWritten = fwrite(stream->buffer[0]->data,sizeof(char),numByte,
stream->file);
fflush(stream->file);
if (numByteWritten != numByte || ferror(stream->file)) {
CommonWarning("BsWriteFile: error writing bit stream file");
return 1;
}
stream->numByte += numByteWritten;
if (BSdebugLevel >= 3)
printf("BsWriteFile: numByteWritten=%ld\n",numByteWritten);
return 0;
}
/* BsReadAhead() */
/* If possible, ensure that the next numBit bits are available */
/* in read file buffer. */
static int BsReadAhead (
BsBitStream *stream, /* in: bit stream */
long numBit) /* in: number of bits */
/* returns: 0=OK 1=error */
{
if (stream->write==1 || stream->file==NULL)
return 0;
if (bit2byte(stream->currentBit+numBit) > stream->numByte)
if (BsReadFile(stream)) {
CommonWarning("BsReadAhead: error reading bit stream file");
return 1;
}
return 0;
}
/* BsCheckRead() */
/* Check if numBit bits could be read from stream. */
static int BsCheckRead (
BsBitStream *stream, /* in: bit stream */
long numBit) /* in: number of bits */
/* returns: */
/* 0=numBit bits could be read */
/* (or write mode) */
/* 1=numBit bits could not be read */
{
if (stream->write == 1)
return 0; /* write mode */
else
if (stream->file == NULL)
return (stream->currentBit+numBit > stream->buffer[0]->numBit) ? 1 : 0;
else
return (bit2byte(stream->currentBit+numBit) > stream->numByte) ? 1 : 0;
}
/* BsReadByte() */
/* Read byte from stream. */
static int BsReadByte (
BsBitStream *stream, /* in: stream */
unsigned long *data, /* out: data (max 8 bit, right justified) */
int numBit) /* in: num bits [1..8] */
/* returns: num bits read or 0 if error */
{
long numUsed;
long idx;
long buf;
if (stream->file!=NULL && stream->currentBit==stream->numByte*BYTE_NUMBIT)
if (BsReadFile(stream)) {
if ( ! BSaacEOF || BSdebugLevel > 0 )
CommonWarning("BsReadByte: error reading bit stream file");
return 0;
}
if (BsCheckRead(stream,numBit)) {
if ( ! BSaacEOF || BSdebugLevel > 0 )
CommonWarning("BsReadByte: not enough bits left in stream");
return 0;
}
idx = (stream->currentBit / BYTE_NUMBIT) % bit2byte(stream->buffer[0]->size);
buf = (stream->currentBit / BYTE_NUMBIT /
bit2byte(stream->buffer[0]->size)) % 2;
numUsed = stream->currentBit % BYTE_NUMBIT;
*data = (stream->buffer[buf]->data[idx] >> (BYTE_NUMBIT-numUsed-numBit)) &
((1<<numBit)-1);
stream->currentBit += numBit;
return numBit;
}
/* BsWriteByte() */
/* Write byte to stream. */
static int BsWriteByte (
BsBitStream *stream, /* in: stream */
unsigned long data, /* in: data (max 8 bit, right justified) */
int numBit) /* in: num bits [1..8] */
/* returns: 0=OK 1=error */
{
long numUsed,idx;
if (stream->file == NULL &&
stream->buffer[0]->numBit+numBit > stream->buffer[0]->size) {
CommonWarning("BsWriteByte: not enough bits left in buffer");
return 1;
}
idx = (stream->currentBit / BYTE_NUMBIT) % bit2byte(stream->buffer[0]->size);
numUsed = stream->currentBit % BYTE_NUMBIT;
if (numUsed == 0)
stream->buffer[0]->data[idx] = 0;
stream->buffer[0]->data[idx] |= (data & ((1<<numBit)-1)) <<
(BYTE_NUMBIT-numUsed-numBit);
stream->currentBit += numBit;
if (stream->file==NULL)
stream->buffer[0]->numBit = stream->currentBit;
if (stream->file!=NULL && stream->currentBit%stream->buffer[0]->size==0)
if (BsWriteFile(stream)) {
CommonWarning("BsWriteByte: error writing bit stream file");
return 1;
}
return 0;
}
/* ---------- functions ---------- */
/* BsInit() */
/* Init bit stream module. */
void BsInit (
long maxReadAhead, /* in: max num bits to be read ahead */
/* (determines file buffer size) */
/* (0 = default) */
int debugLevel, /* in: debug level */
/* 0=off 1=basic 2=medium 3=full */
int aacEOF) /* in: AAC eof detection (default = 0) */
{
if (maxReadAhead)
BSbufSizeByte = max(4,bit2byte(maxReadAhead));
else
BSbufSizeByte = MIN_FILE_BUF_SIZE;
BSdebugLevel = debugLevel;
BSaacEOF = aacEOF;
if (BSdebugLevel >= 1 )
printf("BsInit: debugLevel=%d aacEOF=%d bufSizeByte=%ld\n",
BSdebugLevel,BSaacEOF,BSbufSizeByte);
}
/* BsOpenFileRead() */
/* Open bit stream file for reading. */
BsBitStream *BsOpenFileRead (
char *fileName, /* in: file name */
/* "-": stdin */
char *magic, /* in: magic string */
/* or NULL (no ASCII header in file) */
char **info) /* out: info string */
/* or NULL (no info string in file) */
/* returns: */
/* bit stream (handle) */
/* or NULL if error */
{
BsBitStream *stream;
char header[HEADER_BUF_SIZE];
int tmp = 0;
long i,len;
if (BSdebugLevel >= 1) {
printf("BsOpenFileRead: fileName=\"%s\" id=%ld bufSize=%ld ",
fileName,BSstreamId,byte2bit(BSbufSizeByte));
if (magic != NULL)
printf("magic=\"%s\"\n",magic);
else
printf("no header\n");
}
if ((stream=(BsBitStream*)malloc(sizeof(BsBitStream))) == NULL)
CommonExit(1,"BsOpenFileRead: memory allocation error (stream)");
stream->buffer[0]=BsAllocBuffer(byte2bit(BSbufSizeByte));
stream->buffer[1]=BsAllocBuffer(byte2bit(BSbufSizeByte));
stream->write = 0;
stream->streamId = BSstreamId++;
stream->info = NULL;
if (strcmp(fileName,"-"))
stream->file = fopen(fileName,"rb");
else
stream->file = stdin;
if (stream->file == NULL) {
CommonWarning("BsOpenFileRead: error opening bit stream file %s",
fileName);
BsFreeBuffer(stream->buffer[0]);
BsFreeBuffer(stream->buffer[1]);
FREE(stream);
return NULL;
}
if (magic != NULL) {
/* read ASCII header */
/* read magic string */
len = strlen(magic);
if (len >= HEADER_BUF_SIZE) {
CommonWarning("BsOpenFileRead: magic string too long");
BsClose(stream);
return NULL;
}
for (i=0; i<len; i++)
header[i] = tmp = fgetc(stream->file);
if (tmp == EOF) { /* EOF requires int (not char) */
CommonWarning("BsOpenFileRead: "
"error reading bit stream file (header)");
BsClose(stream);
return NULL;
}
header[i] = '\0';
if (strcmp(header,magic) != 0) {
CommonWarning("BsOpenFileRead: magic string error "
"(found \"%s\", need \"%s\")",header,magic);
BsClose(stream);
return NULL;
}
if (info != NULL) {
/* read info string */
i = 0;
while ((header[i]=tmp=fgetc(stream->file)) != '\0') {
if (tmp == EOF) { /* EOF requires int (not char) */
CommonWarning("BsOpenFileRead: "
"error reading bit stream file (header)");
BsClose(stream);
return NULL;
}
i++;
if (i >= HEADER_BUF_SIZE) {
CommonWarning("BsOpenFileRead: info string too long");
BsClose(stream);
return NULL;
}
}
if (BSdebugLevel >= 1)
printf("BsOpenFileRead: info=\"%s\"\n",header);
if ((stream->info=(char*)malloc((strlen(header)+1)*sizeof(char)))
== NULL)
CommonExit(1,"BsOpenFileRead: memory allocation error (info)");
strcpy(stream->info,header);
*info = stream->info;
}
}
/* init buffer */
stream->currentBit = 0;
stream->numByte = 0;
return stream;
}
/* BsOpenFileWrite() */
/* Open bit stream file for writing. */
BsBitStream *BsOpenFileWrite (
char *fileName, /* in: file name */
/* "-": stdout */
char *magic, /* in: magic string */
/* or NULL (no ASCII header) */
char *info) /* in: info string */
/* or NULL (no info string) */
/* returns: */
/* bit stream (handle) */
/* or NULL if error */
{
BsBitStream *stream;
if (BSdebugLevel >= 1) {
printf("BsOpenFileWrite: fileName=\"%s\" id=%ld bufSize=%ld ",
fileName,BSstreamId,byte2bit(BSbufSizeByte));
if (magic != NULL) {
printf("magic=\"%s\"\n",magic);
if (info != NULL)
printf("BsOpenFileWrite: info=\"%s\"\n",info);
else
printf("BsOpenFileWrite: no info\n");
}
else
printf("no header\n");
}
if ((stream=(BsBitStream*)malloc(sizeof(BsBitStream))) == NULL)
CommonExit(1,"BsOpenFileWrite: memory allocation error (stream)");
stream->buffer[0]=BsAllocBuffer(byte2bit(BSbufSizeByte));
stream->write = 1;
stream->streamId = BSstreamId++;
stream->info = NULL;
if (strcmp(fileName,"-"))
stream->file = fopen(fileName,"wb");
else
stream->file = stdout;
if (stream->file == NULL) {
CommonWarning("BsOpenFileWrite: error opening bit stream file %s",
fileName);
BsFreeBuffer(stream->buffer[0]);
FREE(stream);
return NULL;
}
if (magic!=NULL) {
/* write ASCII header */
/* write magic string */
if (fputs(magic,stream->file) == EOF) {
CommonWarning("BsOpenFileWrite: error writing bit stream file (header)");
BsClose(stream);
return NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -