?? readfile.c
字號:
/* * readfile.c -- * * Procedures concerned with reading data and parsing * start codes from MPEG files. * *//* * Copyright (c) 1995 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. *//* * Portions of this software Copyright (c) 1995 Brown University. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement * is hereby granted, provided that the above copyright notice and the * following two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */#include "video.h"#include "proto.h"#include <sys/types.h>#include <signal.h>#ifndef MIPS#include <netinet/in.h>#else#include <bsd/netinet/in.h>#endif#include "util.h"#include "dither.h"#ifdef __STDC__#include <stdlib.h>#include <string.h>#endif/* Changes to make the code reentrant: deglobalized: totNumFrames, realTimeStart, stream id vars, Prase_done, swap, seekValue, input, EOF_flag, ReadPacket statics, sys_layer, bitOffset, bitLength, bitBuffer, curVidStream removed: [aud,sys,vid]Bytes Additional changes: get rid on ANSI C complaints about shifting -lsh@cs.brown.edu (Loring Holden) *//* Silly Constants.... */#define PACK_START_CODE ((unsigned int)0x000001ba)#define SYSTEM_HEADER_START_CODE ((unsigned int)0x000001bb)#define PACKET_START_CODE_MASK ((unsigned int)0xffffff00)#define PACKET_START_CODE_PREFIX ((unsigned int)0x00000100)#define ISO_11172_END_CODE ((unsigned int)0x000001b9) #define PACK_HEADER_SIZE 8 #define STD_AUDIO_STREAM_ID ((unsigned char) 0xb8)#define STD_VIDEO_STREAM_ID ((unsigned char) 0xb9)#define MIN_STREAM_ID_ID ((unsigned char) 0xbc)#define RESERVED_STREAM_ID ((unsigned char) 0xbc)#define PRIVATE_STREAM_1_ID ((unsigned char) 0xbd)#define PADDING_STREAM_ID ((unsigned char) 0xbe)#define PRIVATE_STREAM_2_ID ((unsigned char) 0xbf) #define STD_SYSTEM_CLOCK_FREQ (unsigned long)90000#define MUX_RATE_SCALE_FACTOR 50#define MAX_STREAMS 8#define NOT_PACKET_ID ((unsigned char) 0xff)#define KILL_BUFFER ((unsigned char) 0xfe) /* *-------------------------------------------------------------- * * get_more_data -- * * Called by get_more_data to read in more data from * video MPG files (non-system-layer) * * 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(vid_stream) VidStream *vid_stream;{ unsigned int **bs_ptr=&vid_stream->buf_start; int *max_length=&vid_stream->max_buf_length; int *length_ptr=&vid_stream->buf_length; unsigned int **buf_ptr=&vid_stream->buffer; int ioBytes, data, result; unsigned char byte; unsigned int *mark; int sys_layer= vid_stream->sys_layer; if (sys_layer == 0) { return pure_get_more_data(*bs_ptr, *max_length, length_ptr, buf_ptr, vid_stream); } if (sys_layer == -1) { /* Time to init ourselves */ vid_stream->swap = (htonl(1) != 1); mark = *bs_ptr; ioBytes = fread(&data, 1, 4, vid_stream->input); if (ioBytes != 4) { return 0; } data = ntohl(data); if ( (data == PACK_START_CODE) || (data == SYSTEM_HEADER_START_CODE) ) { got_sys: /* Yow, a System Layer Stream. Much harder to parse. Call in the specialist.... */ fprintf(stderr,"This is an MPEG System Layer Stream. "); fprintf(stderr,"Audio is not played.\n"); vid_stream->sys_layer = 1; result = read_sys(vid_stream,(unsigned int) data); return result; } else if (data == SEQ_START_CODE) { got_seq: /* No system Layer junk, just pretent we didn't peek, and hereafter just call pure_get_more_data */ vid_stream->sys_layer = 0; **bs_ptr = data; *length_ptr = 1; result = pure_get_more_data(*bs_ptr, *max_length, length_ptr, buf_ptr, vid_stream); *buf_ptr = *bs_ptr; return result; } else { int state; fprintf(stderr, "Junk at start of stream, searching for start code\n"); state = 0; while (TRUE) { if ((ioBytes = fread(&byte, 1, 1, vid_stream->input)) != 1) return 0; if (byte == 0) { if (state < 2) state++; } else if ((byte == 1) && (state == 2)) { state++; } else { state = 0; } if (state == 3) { if ((ioBytes = fread(&byte, 1, 1, vid_stream->input)) != 1) return 0; data = ((unsigned int) byte + 0x100); switch (data) { case SEQ_START_CODE: goto got_seq; case PACK_START_CODE: case SYSTEM_HEADER_START_CODE: goto got_sys; default: /* keep looking */ state=0; } } }} } /* A system layer stream (called after the 1st time), call the specialist */ result = read_sys(vid_stream,0); return result;}/* *------------------------------------------------------------- * * clear_data_stream * * Empties out internal buffers * *------------------------------------------------------------- */void clear_data_stream(vid_stream) VidStream *vid_stream;{ /* Only internal buffer is in ReadPacket */ if (vid_stream->sys_layer) { ReadPacket(KILL_BUFFER, vid_stream); }}/* *------------------------------------------------------------- * * SeekStream * * Goto an offset in the steam * *------------------------------------------------------------- */void SeekStream(vid_stream)VidStream *vid_stream;{ int errno; int code; if (vid_stream->seekValue < 0) return; /* done seeking */#ifdef SEEK_SET errno = fseek(vid_stream->input, vid_stream->seekValue, SEEK_SET);#else errno = fseek(vid_stream->input, vid_stream->seekValue, 0);#endif if (errno != 0) { fprintf(stderr,"Error in seek (%d)\n",errno); perror("mpeg_play"); } vid_stream->seekValue = 0-vid_stream->seekValue; vid_stream->totNumFrames = 0; /* clear that buffer */ vid_stream->buffer = vid_stream->buf_start; vid_stream->buf_length = 0; vid_stream->bit_offset = 0; /* Find a decent start code */ restart: NO_ZEROS: switch(fgetc(vid_stream->input)) { case 0: goto ONE_ZERO; case EOF: goto EOF_FOUND; default: goto NO_ZEROS; } ONE_ZERO: switch(fgetc(vid_stream->input)) { case 0: goto TWO_ZEROS; case EOF: goto EOF_FOUND; default: goto NO_ZEROS; } TWO_ZEROS: switch(fgetc(vid_stream->input)) { case 0x01: goto CODE_FOUND; case 0x00: goto TWO_ZEROS; case EOF: goto EOF_FOUND; default: goto NO_ZEROS; } CODE_FOUND: code = 0x00000100+fgetc(vid_stream->input); if (vid_stream->sys_layer) { clear_data_stream(vid_stream); if (((code & PACKET_START_CODE_MASK) == PACKET_START_CODE_PREFIX) && ((code & 0xff) >= 0xbc)) { read_sys(vid_stream, code); while (TRUE) { next_start_code(vid_stream); show_bits32(code); if ((code == SEQ_START_CODE) || (code == GOP_START_CODE)) return; flush_bits32; } } } else { if ((code == SEQ_START_CODE) || (code == GOP_START_CODE)) { *vid_stream->buffer = code; vid_stream->buf_length = 1; return; } } goto restart; EOF_FOUND: /* received EOF */ fprintf(stderr, "Hit EOF after seeking (offset %ld)\n", ftell(vid_stream->input)); exit(1);}/* *-------------------------------------------------------------- * * pure_get_more_data -- * (get_more_data from ver 2.0 with swap added) * * Called by get_more_data to read in more data from * video MPG files (non-system-layer) * * 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(buf_start, max_length, length_ptr, buf_ptr, vid_stream) unsigned int *buf_start; int max_length; int *length_ptr; unsigned int **buf_ptr; VidStream *vid_stream;{ int length, num_read, i; unsigned int request; unsigned char *buffer, *mark; unsigned int *lmark; BOOLEAN swap=vid_stream->swap; if (vid_stream->EOF_flag) return 0; length = *length_ptr; buffer = (unsigned char *) *buf_ptr; if (length > 0) { memcpy((unsigned char *) buf_start, buffer, (unsigned int) (length*4)); mark = ((unsigned char *) (buf_start + length)); } else { mark = (unsigned char *) buf_start; length = 0; } request = (max_length-length)*4; num_read = fread(mark, 1, request, vid_stream->input); /* Paulo Villegas - 26/1/1993: Correction for 4-byte alignment */ { int num_read_rounded; unsigned char *index; num_read_rounded = 4*(num_read/4); /* this can happen only if num_read<request; i.e. end of file reached */ if ( num_read_rounded < num_read ) { num_read_rounded = 4*( num_read/4+1 ); /* 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; vid_stream->EOF_flag = 1; return 0; } lmark = (unsigned int *) mark; num_read = num_read/4; if (swap) { for (i = 0; i < num_read; i++) { *lmark = htonl(*lmark); lmark++; } } *buf_ptr = buf_start; *length_ptr = length + num_read; return 1;}/* Here is the specialist.... Code is adapted from our program demux.... A bunch of this needs to be #ifdef ANALYSIS'ed define __SYSREAD_LOGGING_ON__ to get an output file for debugging *//* Brown - removed StreamID global variables */#ifdef ANALYSIS/* Statistics */static int gNumAudioPackets;static int gNumVideoPackets;static int gNumPaddingPackets;static int gNumReservedPackets;static int gNumPrivate_1_Packets;static int gNumPrivate_2_Packets;#endif/* *---------------------------------------------------------- * * 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(vid_stream, start) VidStream *vid_stream; unsigned int start; /* start is either a start code or 0 to indicate continued parsing */{ unsigned int **bs_ptr=&vid_stream->buf_start; int *max_length = &vid_stream->max_buf_length; int *length_ptr=&vid_stream->buf_length; unsigned int **buf_ptr=&vid_stream->buffer; unsigned int startCode; int errorCode, PacketReply; unsigned char packetID; double systemClockTime; unsigned long muxRate; /* Statistics */#ifdef ANALYSIS static int numPacks = 0; static int numPackets = 0; static int numSystemHeaders = 0;#endif BOOLEAN match; if (!start) { errorCode = ReadStartCode(&startCode,vid_stream); if (vid_stream->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) {#ifdef ANALYSIS ++numPacks; #endif match = TRUE; errorCode = ReadPackHeader( &systemClockTime, &muxRate, vid_stream); if (errorCode != 0) { fprintf(stderr, "Error in reading pack header\n"); return 0; } errorCode = ReadStartCode( &startCode, vid_stream ); if (errorCode != 0) { fprintf(stderr, "Error in reading start code\n"); return 0; } } if (startCode == SYSTEM_HEADER_START_CODE) {#ifdef ANALYSIS ++numSystemHeaders; #endif match = TRUE; errorCode = ReadSystemHeader(vid_stream); if (errorCode != 0) { fprintf(stderr, "Error in reading system header\n"); return 0; } errorCode = ReadStartCode( &startCode, vid_stream ); if (errorCode != 0) { fprintf(stderr,"Error in reading start code after system header\n"); return 0; } }
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -