📄 bitstream.c
字号:
/**********************************************************************MPEG-4 Audio VMBit stream moduleThis software module was originally developed byHeiko Purnhagen (University of Hannover / ACTS-MoMuSys)and edited byRalph Sperschneider (Fraunhofer IIS)Thomas Schaefer (Fraunhofer IIS)in the course of development of the MPEG-2 NBC/MPEG-4 Audio standardISO/IEC 13818-7, 14496-1,2 and 3. This software module is animplementation of a part of one or more MPEG-2 NBC/MPEG-4 Audio toolsas specified by the MPEG-2 NBC/MPEG-4 Audio standard. ISO/IEC givesusers of the MPEG-2 NBC/MPEG-4 Audio standards free license to thissoftware module or modifications thereof for use in hardware orsoftware products claiming conformance to the MPEG-2 NBC/ MPEG-4 Audiostandards. Those intending to use this software module in hardware orsoftware products are advised that this use may infringe existingpatents. The original developer of this software module and his/hercompany, the subsequent editors and their companies, and ISO/IEC haveno liability for use of this software module or modifications thereofin an implementation. Copyright is not released for non MPEG-2NBC/MPEG-4 Audio conforming products. The original developer retainsfull right to use the code for his/her own purpose, assign or donatethe code to a third party and to inhibit third party from using thecode for non MPEG-2 NBC/MPEG-4 Audio conforming products. Thiscopyright notice must be included in all copies or derivative works.Copyright (c) 1996, 1997, 1998.Source file: bitstream.c$Id: bitstream.c,v 1.37 1999/07/26 13:17:56 purnhage Exp $Required modules:common.o common moduleAuthors: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 header18-jun-96 HP fixed bug in BsGetBuffer()26-aug-96 HP CVS23-oct-96 HP free for BsOpenFileRead() info string07-nov-96 HP fixed BsBitStream info bug15-nov-96 HP changed int to long where required added BsGetBitChar(), BsGetBitShort(), BsGetBitInt() improved file header handling04-dec-96 HP fixed bug in BsGetBitXxx() for numBit==023-dec-96 HP renamed mode to write in BsBitStream10-jan-97 HP added BsGetBitAhead(), BsGetSkip()17-jan-97 HP fixed read file buffer bug30-jan-97 HP minor bug fix in read bitstream file magic string19-feb-97 HP made internal data structures invisible04-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 streaming05-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 + -