home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 106
/
EnigmaAmiga106CD.iso
/
indispensabili
/
grafica
/
amipeg_1.1
/
src
/
readfile.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-15
|
19KB
|
754 lines
/* readfile.c */
#include "video.h"
#include "proto.h"
#include <proto/asyncio.h>
/* Stream IDs */
int gAudioStreamID=0;
int gVideoStreamID=0;
int gReservedStreamID=0;
#ifdef ANALYSIS
int gNumAudioPackets=0;
int gNumVideoPackets=0;
int gNumPaddingPackets=0;
int gNumReservedPackets=0;
int gNumPrivate_1_Packets=0;
int gNumPrivate_2_Packets=0;
#endif
extern int sys_layer=-1;
extern int EOF_flag;
extern int quietFlag;
// static FILE *hack;
FILE *out;
/*
*--------------------------------------------------------------
*
* get_more_data --
*
* Called by correct_underflow in bit parsing utilities to
* read in more data. Checks if System Layer etc.
*
* Results:
* Input buffer updated, buffer length updated.
* Returns 1 if data read, 0 if EOF, -1 if error.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
int get_more_data(bs_ptr, max_length, length_ptr, buf_ptr)
unsigned int **bs_ptr;
int *max_length, *length_ptr;
unsigned int **buf_ptr;
{
int ioBytes, data, result;
if (sys_layer == 0) {
return pure_get_more_data(*bs_ptr, *max_length, length_ptr, buf_ptr);
}
if (sys_layer == -1) {
// hack=fopen("hack.dat", "w");
/* Time to init ourselves */
ioBytes = ReadAsync(input, &data, 4);
if (ioBytes!=4) return 0;
if ((data==PACK_START_CODE) || (data==SYSTEM_HEADER_START_CODE)) {
/* Yow, a System Layer Stream. Much harder to parse. Call in the
specialist.... */
if(!quietFlag) {
fprintf(stderr,"This is an MPEG System Layer Stream. ");
fprintf(stderr,"Audio is not processed.\n");
}
sys_layer=1;
result= read_sys(bs_ptr, max_length, length_ptr, buf_ptr, data);
// fwrite((unsigned char *)(*buf_ptr),1,*length_ptr*4,hack);
return result;
} else {
/* No system Layer junk, just pretend we didn't peek,
and hereafter just call pure_get_more_data */
sys_layer=0;
**bs_ptr=data;
*length_ptr=1;
result= pure_get_more_data(*bs_ptr, *max_length,
length_ptr, buf_ptr);
*buf_ptr= *bs_ptr;
return result;
}
}
/* A system layer stream (called after the 1st time), call the specialist */
// data= *length_ptr;
result=read_sys(bs_ptr, max_length, length_ptr, buf_ptr, 0);
// fwrite((unsigned char *) ((*buf_ptr)+data),1,4*((*length_ptr)-data),hack);
return result;
}
/*
*--------------------------------------------------------------
*
* pure_get_more_data --
*
* Called by get_more_data to
* read in more data in normal case streams.
*
* Results:
* Input buffer updated, buffer length updated.
* Returns 1 if data read, 0 if EOF, -1 if error.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
int pure_get_more_data(unsigned int *buf_start, int max_length, int *length_ptr, unsigned int **buf_ptr)
{
int length, num_read, request;
unsigned char *buffer, *mark;
if (EOF_flag) return 0;
length = *length_ptr;
buffer = (unsigned char *) *buf_ptr;
if (length > 0) {
memcpy((unsigned char *) buf_start, buffer, (length*4));
mark = ((unsigned char *) (buf_start + length));
}
else {
mark = (unsigned char *) buf_start;
length = 0;
}
request = (max_length-length)*4;
num_read = ReadAsync(input, mark, request);
/* Paulo Villegas - 26/1/1993: Correction for 4-byte alignment */
{
int num_read_rounded;
unsigned char *index;
num_read_rounded = num_read & 0xfffffffc;
/* this can happen only if num_read<request; i.e. end of file reached */
if( num_read_rounded < num_read )
{
num_read_rounded+=4;
/* fill in with zeros */
for( index=mark+num_read; index<mark+num_read_rounded; *(index++)=0 );
/* advance to the next 4-byte boundary */
num_read = num_read_rounded;
}
}
if (num_read < 0) {
return -1;
}
else if (num_read == 0) {
*buf_ptr = buf_start;
/* Make 32 bits after end equal to 0 and 32
bits after that equal to seq end code
in order to prevent messy data from infinite
recursion.
*/
*(buf_start + length) = 0x0;
*(buf_start + length+1) = SEQ_END_CODE;
EOF_flag = 1;
return 0;
}
num_read >>= 2;
*buf_ptr = buf_start;
*length_ptr = length + num_read;
return 1;
}
/*
*----------------------------------------------------------
*
* read_sys
*
* Parse out a packet of the system layer MPEG file.
*
* Results: Returns 0 if error or EOF
* Returns 1 if more data read (could be just one int)
*
* Side Effects: ReadPacket can change *bs_ptr to be a new buffer
* buf_ptr will remain pointing at *length_ptr (at input)
* into the buffer
* *length_ptr will be changed to the new size
* *max_length can be changed if a new buffer is alloc'd
*
*----------------------------------------------------------
*/
int read_sys(bs_ptr, max_length, length_ptr, buf_ptr, start)
unsigned int **bs_ptr;
int *max_length, *length_ptr;
unsigned int **buf_ptr, start;
/* start is either a start code or 0 to indicate continued parsing */
{
unsigned int startCode;
int errorCode, PacketReply;
unsigned char packetID;
double systemClockTime;
unsigned long muxRate;
/* Statistics */
static int numPacks = 0;
static int numPackets = 0;
static int numSystemHeaders = 0;
static BOOLEAN Parse_done=FALSE;
BOOLEAN match;
if (!start) {
errorCode = ReadStartCode(&startCode);
if (EOF_flag) return 0;
if (errorCode != 0) {
fprintf(stderr, "Unable to read initial pack start code\n");
return 0;
}
}
else {
errorCode = 0;
startCode = start;
}
while (1) {
match=FALSE;
if (startCode == PACK_START_CODE) {
++numPacks; match=TRUE;
errorCode = ReadPackHeader( &systemClockTime, &muxRate);
if (errorCode != 0) {
fprintf(stderr, "Error in reading pack header\n");
return 0;
}
errorCode = ReadStartCode( &startCode);
if (errorCode != 0) {
fprintf(stderr, "Error in reading start code\n");
return 0;
}
}
if (startCode == SYSTEM_HEADER_START_CODE) {
++numSystemHeaders; match=TRUE;
errorCode = ReadSystemHeader();
if (errorCode != 0) {
fprintf(stderr, "Error in reading system header\n");
return 0;
}
errorCode = ReadStartCode( &startCode);
if (errorCode != 0) {
fprintf(stderr,"Error in reading start code after system header\n");
return 0;
}
}
packetID = startCode & 0xff;
while (((startCode & PACKET_START_CODE_MASK) == PACKET_START_CODE_PREFIX) &&
(packetID>=0xbc)) {
++numPackets; match=TRUE;
packetID = startCode & 0xff;
PacketReply = ReadPacket(packetID, bs_ptr, max_length, length_ptr, buf_ptr);
switch (PacketReply) {
case 2:
return 1;
case 1:
return 0;
default: /* do nothing */
break;
}
errorCode = ReadStartCode( &startCode);
if (errorCode != 0) {
fprintf(stderr,"Error in start code after packet\n");
/*printf("startCode: %08lx\n", startCode);*/
return 0;
}
if (startCode == PACK_START_CODE || startCode == ISO_11172_END_CODE)
break;
}
if (startCode == ISO_11172_END_CODE) {
if (Parse_done) return 1;
#ifdef ANALYSIS
fprintf(stderr, "Successful parse of MPEG system level\n");
fprintf(stderr, "%d system headers, %d packs, %d packets\n",
numSystemHeaders, numPacks, numPackets);
fprintf(stderr, "%d audio packets, %d video packets, %d padding packets\n",
gNumAudioPackets, gNumVideoPackets, gNumPaddingPackets);
fprintf(stderr, "%d reserved packets, %d/%d private type 1/2 packets\n",
gNumReservedPackets, gNumPrivate_1_Packets, gNumPrivate_2_Packets);
#endif
ReadPacket(NOT_PACKET_ID, bs_ptr, max_length, length_ptr, buf_ptr);
Parse_done=TRUE;
return 1;
}
if (errorCode != 0)
return 1;
if (!match) {
fprintf(stderr,"\nNo match found for start code %08x in system layer, skipping\n",startCode);
startCode=(int) find_start_code();
if (startCode==EOF) {
EOF_flag=1;
return 0;
}
}
}
return 0; /* shouldnt get here */
}
/*
*-----------------------------------------------------------
*
* ReadStartCode
*
* Parses a start code out of the stream
*
* Results/Side Effects: Sets *startCode to the code, returns
* 1 on error, 0 on success
*
*-----------------------------------------------------------
*/
int ReadStartCode(startCode)
unsigned int *startCode;
{
int numRead;
numRead = ReadAsync(input, (unsigned char *)startCode, 4);
if (numRead < 4) {
EOF_flag=1;
return 1;
}
if ((*startCode&0xfffffe00) != 0) {
fprintf(stderr,"Problem with system layer parse, skipping to start code\n");
*startCode=(int) find_start_code();
if (*startCode==EOF) {
EOF_flag=TRUE;
return 0;
}
}
return 0;
}
/*
*-----------------------------------------------------------
*
* find_start_code
*
* Parses a start code out of the stream by tossing bytes until it gets one
*
* Results/Side Effects: Parses bytes of the stream, returns code
* Returns EOF in case of end of file
*
*-----------------------------------------------------------
*/
int find_start_code(void)
{
NO_ZEROS:
switch(ReadCharAsync(input)) {
case 0: goto ONE_ZERO;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
ONE_ZERO:
switch(ReadCharAsync(input)) {
case 0: goto TWO_ZEROS;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
TWO_ZEROS:
switch(ReadCharAsync(input)) {
case 0x01: goto CODE_FOUND;
case 0x00: goto TWO_ZEROS;
case EOF: goto EOF_FOUND;
default: goto NO_ZEROS;
}
CODE_FOUND:
return 0x00000100+ReadCharAsync(input);
EOF_FOUND: /* received EOF */
return EOF;
}
/*
*-----------------------------------------------------------------
*
* ReadPackHeader
*
* Parses out the PACK header
*
* Returns: 1 on error, 0 on success
*
*-------------------------------------------------------------------
*/
int ReadPackHeader(systemClockTime,muxRate)
double *systemClockTime;
unsigned long *muxRate;
{
int numRead;
unsigned char inputBuffer[PACK_HEADER_SIZE];
unsigned long systemClockRef;
unsigned char systemClockRefHiBit;
numRead = ReadAsync(input, inputBuffer, PACK_HEADER_SIZE);
if (numRead < PACK_HEADER_SIZE) {
EOF_flag=1;
return 1;
}
ReadTimeStamp(inputBuffer, &systemClockRefHiBit, &systemClockRef);
MakeFloatClockTime(systemClockRefHiBit, systemClockRef, systemClockTime);
ReadRate(&inputBuffer[5], muxRate);
*muxRate *= MUX_RATE_SCALE_FACTOR;
return 0;
}
/*
*------------------------------------------------------------------
*
* ReadSystemHeader
*
* Parse out the system header, setup out dtream IDs for parsing packets
*
* Results: Returns 1 on error, 0 on success.
* Sets gAudioStreamID and gVideoStreamID
*
*------------------------------------------------------------------
*/
int ReadSystemHeader()
{
unsigned char *inputBuffer;
int numRead;
int pos;
unsigned short headerSize;
unsigned char streamID;
/* Only needed for system log file */
numRead = ReadAsync(input, (char *)&headerSize, 2);
if (numRead != 2) {
EOF_flag=1;
return 1;
}
inputBuffer = (unsigned char *) malloc(headerSize+1);
if (inputBuffer == NULL) {
return 1;
}
inputBuffer[headerSize]=0;
numRead = ReadAsync(input, inputBuffer, headerSize);
if (numRead < headerSize) {
EOF_flag=1;
return 1;
}
pos = 6;
while ((inputBuffer[pos] & 0x80) == 0x80) {
streamID = inputBuffer[pos];
switch (streamID) {
case STD_VIDEO_STREAM_ID:
break;
case STD_AUDIO_STREAM_ID:
break;
case RESERVED_STREAM_ID:
break;
case PADDING_STREAM_ID:
break;
case PRIVATE_STREAM_1_ID:
break;
case PRIVATE_STREAM_2_ID:
break;
case 0xb1:
if (streamID < MIN_STREAM_ID_ID) {
return 1;
}
default:
if (streamID < MIN_STREAM_ID_ID) {
return 1;
}
switch (streamID >> 4) {
case 0xc:
case 0xd:
gAudioStreamID = streamID;
break;
case 0xe:
if ((gVideoStreamID != 0) && (gVideoStreamID!=streamID)) {
break;
}
gVideoStreamID = streamID;
break;
case 0xf:
gReservedStreamID = streamID;
break;
}
break;
}
pos += 3;
}
if (inputBuffer)
free(inputBuffer);
return 0;
}
/*
*-----------------------------------------------------------------
*
* ReadPacket
*
* Reads a single packet out of the stream, and puts it in the
* buffer if it is video.
*
* Results:
* Changes the value of *length_ptr to be the new length (plus old)
* If the buffer is too small, can change *bs_ptr, *max_length, and *buf_ptr
* to be correct for a newly allocated buffer.
*
* State: The buffer is in ints, but the packets can be an arbitrary number
* of bytes, so leftover bytes are kept in static vars and added in on the
* next call.
*
*-----------------------------------------------------------------
*/
int ReadPacket(packetID, bs_ptr, max_length, length_ptr, buf_ptr)
unsigned char packetID;
unsigned int **bs_ptr;
int *max_length;
int *length_ptr;
unsigned int **buf_ptr;
/* Returns:
0 - no error, but not video packet we want
1 - error
2 - got video packet into buffer
*/
{
int ioBytes;
unsigned char nextByte;
unsigned short packetLength;
unsigned char *packetBuffer;
int pos;
int packetDataLength;
int byte_length;
/* Leftovers from previous video packets */
static unsigned int num_left=0, leftover_bytes=0;
if (packetID==NOT_PACKET_ID) {
/* Gross hack to handle unread bytes before end of stream */
if (num_left!=0) {
/* Sigh, deal with previous leftovers */
*(*buf_ptr+*length_ptr)=leftover_bytes;
*(*buf_ptr+*length_ptr+1)=ISO_11172_END_CODE;
*length_ptr+=2;
} else {
*(*buf_ptr+*length_ptr)=ISO_11172_END_CODE;
*length_ptr+=1;
}
return 1;
}
ioBytes = ReadAsync(input, &packetLength, 2);
if (ioBytes < 2) {
return 1;
}
if (packetID == gAudioStreamID) {
#ifdef ANALYSIS
++gNumAudioPackets;
#endif
}
else if (packetID == gVideoStreamID) {
#ifdef ANALYSIS
++gNumVideoPackets;
#endif
}
else {
switch (packetID) {
case PADDING_STREAM_ID:
#ifdef ANALYSIS
++gNumPaddingPackets;
#endif
break;
case RESERVED_STREAM_ID:
#ifdef ANALYSIS
++gNumReservedPackets;
#endif
break;
case PRIVATE_STREAM_1_ID:
#ifdef ANALYSIS
++gNumPrivate_1_Packets;
#endif
break;
case PRIVATE_STREAM_2_ID:
#ifdef ANALYSIS
++gNumPrivate_2_Packets;
#endif
break;
default:
if (packetID < MIN_STREAM_ID_ID){
return 1;
}
switch(packetID >> 4){
case 0xc:
case 0xd:
packetID = gAudioStreamID;
break;
case 0xe:
if ((gVideoStreamID != 0)&&(gVideoStreamID != packetID)){
break;
}
gVideoStreamID = packetID;
break;
}
break;
/* fprintf(stderr, "\nUnknown packet type encountered. P'bly audio? (%x) at %d\n", <---- obsolete
packetID,(int) SeekAsync(input, 0, MODE_CURRENT)); <---- " */
} /* switch */
} /* else */
if (packetID != gVideoStreamID) {
SeekAsync(input, packetLength, MODE_CURRENT);
return 0;
}
nextByte=ReadCharAsync(input);
pos = 0;
while (nextByte & 0x80) {
++pos;
nextByte=ReadCharAsync(input);
}
if ((nextByte >> 6) == 0x01) {
pos += 2;
ReadCharAsync(input);
nextByte=ReadCharAsync(input);
}
if ((nextByte >> 4) == 0x02) {
SeekAsync(input, 4, MODE_CURRENT);
nextByte=ReadCharAsync(input);
pos+=5;
}
else if ((nextByte >> 4) == 0x03) {
SeekAsync(input, 9, MODE_CURRENT);
nextByte=ReadCharAsync(input);
pos += 10;
}
else {
nextByte=ReadCharAsync(input);
pos += 1;
}
/* Read all the headers, now make room for packet */
if (*bs_ptr+*max_length<*buf_ptr+packetLength/4+*length_ptr) {
if (*max_length-*length_ptr<packetLength/4) {
/* Buffer too small for a packet (plus whats there),
time to enlarge it! */
unsigned int *old= *bs_ptr;
*max_length = *length_ptr + packetLength/2;
*bs_ptr=(unsigned int *)malloc(*max_length*4);
if (*bs_ptr == NULL) {
return 1;
}
memcpy((unsigned char *)*bs_ptr,*buf_ptr,*length_ptr*4);
free(old);
*buf_ptr= *bs_ptr;
} else {
memcpy((unsigned char *)*bs_ptr,*buf_ptr,*length_ptr*4);
*buf_ptr = *bs_ptr;
}
}
byte_length= (*length_ptr)*4;
if (num_left!=0) {
/* Sigh, deal with previous leftovers */
byte_length += num_left;
*(*buf_ptr+*length_ptr)=leftover_bytes;
}
packetBuffer=((unsigned char *)*buf_ptr)+byte_length;
packetDataLength = packetLength - pos;
*packetBuffer++=nextByte;
if (packetID == gVideoStreamID) {
ioBytes=ReadAsync(input, packetBuffer, packetDataLength-1);
if (ioBytes!=packetDataLength-1) {
EOF_flag=1;
return 1;
}
byte_length = byte_length+packetDataLength;
num_left = byte_length%4;
*length_ptr = byte_length/4;
leftover_bytes = *(*buf_ptr+*length_ptr);
return 2;
}
else if (packetID == gAudioStreamID) {
packetBuffer = (unsigned char *)(*buf_ptr+*length_ptr+1);
ReadAsync(input, packetBuffer, packetDataLength-1);
/* if(!out)
out = fopen("ram:out", "w");
fwrite(packetBuffer, 1, packetDataLength-1, out);*/
}
else /* Donno what it is, just nuke it */ {
/* This code should be unreachable */
packetBuffer=(unsigned char *)(*buf_ptr+*length_ptr+1);
ReadAsync(input, packetBuffer, packetDataLength-1);
}
return 0;
}
/*
* A formatting utility procedure.
*/
void ReadTimeStamp(inputBuffer,hiBit,low4Bytes)
unsigned char *inputBuffer, *hiBit;
unsigned long *low4Bytes;
{
*hiBit = ((unsigned long)inputBuffer[0] >> 3) & 0x01;
*low4Bytes = (((unsigned long)inputBuffer[0] >> 1) & 0x03) << 30;
*low4Bytes |= (unsigned long)inputBuffer[1] << 22;
*low4Bytes |= ((unsigned long)inputBuffer[2] >> 1) << 15;
*low4Bytes |= (unsigned long)inputBuffer[3] << 7;
*low4Bytes |= ((unsigned long)inputBuffer[4]) >> 1;
}
void ReadRate(inputBuffer,rate)
unsigned char *inputBuffer;
unsigned long *rate;
{
*rate = (inputBuffer[0] & 0x7f) << 15;
*rate |= inputBuffer[1] << 7;
*rate |= (inputBuffer[2] & 0xfe) >> 1;
}
#define FLOAT_0x10000 (double)((unsigned long)1 << 16)
int MakeFloatClockTime(hiBit,low4Bytes,floatClockTime)
unsigned char hiBit;
unsigned long low4Bytes;
double *floatClockTime;
{
if (hiBit != 0 && hiBit != 1) {
*floatClockTime = 0.0;
return 1;
}
*floatClockTime
= (double)hiBit*FLOAT_0x10000*FLOAT_0x10000 + (double)low4Bytes;
*floatClockTime /= (double)90000;
return 0;
}