1 /*
2  * readfile.c --
3  *
4  *       Procedures concerned with reading data and parsing
5  *       start codes from MPEG files.
6  *
7  */
8 
9 /*
10  * Copyright (c) 1995 The Regents of the University of California.
11  * All rights reserved.
12  *
13  * Permission to use, copy, modify, and distribute this software and its
14  * documentation for any purpose, without fee, and without written agreement is
15  * hereby granted, provided that the above copyright notice and the following
16  * two paragraphs appear in all copies of this software.
17  *
18  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
19  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
20  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
21  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22  *
23  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
24  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
25  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
26  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
27  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
28  */
29 
30 /*
31  * Portions of this software Copyright (c) 1995 Brown University.
32  * All rights reserved.
33  *
34  * Permission to use, copy, modify, and distribute this software and its
35  * documentation for any purpose, without fee, and without written agreement
36  * is hereby granted, provided that the above copyright notice and the
37  * following two paragraphs appear in all copies of this software.
38  *
39  * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
40  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
41  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
42  * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43  *
44  * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
45  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
46  * PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
47  * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
48  * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
49  */
50 
51 #include "video.h"
52 #include "proto.h"
53 #include <sys/types.h>
54 #include <signal.h>
55 #ifndef MIPS
56 #include <netinet/in.h>
57 #else
58 #include <bsd/netinet/in.h>
59 #endif
60 
61 #include "util.h"
62 #include "dither.h"
63 
64 #ifdef __STDC__
65 #include <stdlib.h>
66 #include <string.h>
67 #endif
68 
69 /*
70    Changes to make the code reentrant:
71       deglobalized: totNumFrames, realTimeStart, stream id vars, Prase_done,
72          swap, seekValue, input, EOF_flag, ReadPacket statics, sys_layer,
73 	 bitOffset, bitLength, bitBuffer, curVidStream
74    removed: [aud,sys,vid]Bytes
75    Additional changes:
76       get rid on ANSI C complaints about shifting
77    -lsh@cs.brown.edu (Loring Holden)
78  */
79 
80 /* Silly Constants.... */
81 #define PACK_START_CODE             ((unsigned int)0x000001ba)
82 #define SYSTEM_HEADER_START_CODE    ((unsigned int)0x000001bb)
83 #define PACKET_START_CODE_MASK      ((unsigned int)0xffffff00)
84 #define PACKET_START_CODE_PREFIX    ((unsigned int)0x00000100)
85 #define ISO_11172_END_CODE          ((unsigned int)0x000001b9)
86 
87 #define PACK_HEADER_SIZE 8
88 
89 #define STD_AUDIO_STREAM_ID ((unsigned char) 0xb8)
90 #define STD_VIDEO_STREAM_ID ((unsigned char) 0xb9)
91 #define MIN_STREAM_ID_ID    ((unsigned char) 0xbc)
92 #define RESERVED_STREAM_ID  ((unsigned char) 0xbc)
93 #define PRIVATE_STREAM_1_ID ((unsigned char) 0xbd)
94 #define PADDING_STREAM_ID   ((unsigned char) 0xbe)
95 #define PRIVATE_STREAM_2_ID ((unsigned char) 0xbf)
96 
97 #define STD_SYSTEM_CLOCK_FREQ (unsigned long)90000
98 #define MUX_RATE_SCALE_FACTOR 50
99 #define MAX_STREAMS 8
100 #define NOT_PACKET_ID       ((unsigned char) 0xff)
101 #define KILL_BUFFER         ((unsigned char) 0xfe)
102 
103 
104 /*
105  *--------------------------------------------------------------
106  *
107  * get_more_data --
108  *
109  *	Called by get_more_data to read in more data from
110  *      video MPG files (non-system-layer)
111  *
112  * Results:
113  *	Input buffer updated, buffer length updated.
114  *      Returns 1 if data read, 0 if EOF, -1 if error.
115  *
116  * Side effects:
117  *      None.
118  *
119  *--------------------------------------------------------------
120  */
121 int
get_more_data(vid_stream)122 get_more_data(vid_stream)
123       VidStream *vid_stream;
124 {
125   unsigned int **bs_ptr=&vid_stream->buf_start;
126   int *max_length=&vid_stream->max_buf_length;
127   int *length_ptr=&vid_stream->buf_length;
128   unsigned int **buf_ptr=&vid_stream->buffer;
129   int ioBytes, data, result;
130   unsigned char byte;
131   unsigned int *mark;
132   int sys_layer= vid_stream->sys_layer;
133 
134   if (sys_layer == 0) {
135     return pure_get_more_data(*bs_ptr,
136 			      *max_length,
137 			       length_ptr,
138 			       buf_ptr,
139 			       vid_stream);
140   }
141 
142   if (sys_layer == -1) {
143     /* Time to init ourselves */
144     vid_stream->swap = (htonl(1) != 1);
145     mark = *bs_ptr;
146     ioBytes = fread(&data, 1, 4, vid_stream->input);
147 
148     if (ioBytes != 4) {
149 	  return 0;
150     }
151 
152     data = ntohl(data);
153     if ( (data == PACK_START_CODE) || (data == SYSTEM_HEADER_START_CODE) ) {
154     got_sys:
155       /* Yow, a System Layer Stream.  Much harder to parse.  Call in the
156 	     specialist.... */
157       fprintf(stderr,"This is an MPEG System Layer Stream.  ");
158       fprintf(stderr,"Audio is not played.\n");
159       vid_stream->sys_layer = 1;
160       result = read_sys(vid_stream,(unsigned int) data);
161       return result;
162     } else if (data ==  SEQ_START_CODE) {
163     got_seq:
164       /* No system Layer junk, just pretent we didn't peek,
165 	     and hereafter just call pure_get_more_data */
166       vid_stream->sys_layer = 0;
167       **bs_ptr = data;
168       *length_ptr = 1;
169       result = pure_get_more_data(*bs_ptr, *max_length,
170 				 length_ptr, buf_ptr, vid_stream);
171       *buf_ptr = *bs_ptr;
172       return result;
173     } else {
174       int state;
175 
176       fprintf(stderr, "Junk at start of stream, searching for start code\n");
177       state = 0;
178       while (TRUE) {
179 	if ((ioBytes = fread(&byte, 1, 1, vid_stream->input)) != 1) return 0;
180 	if (byte == 0) {
181 	  if (state < 2) state++;
182 	} else if ((byte == 1) && (state == 2)) {
183 	  state++;
184 	} else {
185 	  state = 0;
186 	}
187 	if (state == 3) {
188 	  if ((ioBytes = fread(&byte, 1, 1, vid_stream->input)) != 1) return 0;
189 	  data = ((unsigned int) byte + 0x100);
190 	  switch (data) {
191 	  case SEQ_START_CODE:
192 	    goto got_seq;
193 	  case PACK_START_CODE:
194 	  case SYSTEM_HEADER_START_CODE:
195 	    goto got_sys;
196 	  default:
197 	    /* keep looking */
198 	    state=0;
199 	  }
200 	}
201       }}
202   }
203 
204   /* A system layer stream (called after the 1st time), call the specialist */
205   result = read_sys(vid_stream,0);
206   return result;
207 }
208 
209 
210 /*
211  *-------------------------------------------------------------
212  *
213  * clear_data_stream
214  *
215  * Empties out internal buffers
216  *
217  *-------------------------------------------------------------
218  */
219 void
clear_data_stream(vid_stream)220   clear_data_stream(vid_stream)
221      VidStream *vid_stream;
222 {
223   /* Only internal buffer is in ReadPacket */
224   if (vid_stream->sys_layer) {
225     ReadPacket(KILL_BUFFER, vid_stream);
226   }
227 }
228 
229 /*
230  *-------------------------------------------------------------
231  *
232  * SeekStream
233  *
234  * Goto an offset in the steam
235  *
236  *-------------------------------------------------------------
237  */
238 void
SeekStream(vid_stream)239   SeekStream(vid_stream)
240 VidStream *vid_stream;
241 {
242   int errno;
243   int code;
244 
245   if (vid_stream->seekValue < 0) return; /* done seeking */
246 #ifdef SEEK_SET
247   errno = fseek(vid_stream->input, vid_stream->seekValue, SEEK_SET);
248 #else
249   errno = fseek(vid_stream->input, vid_stream->seekValue, 0);
250 #endif
251   if (errno != 0) {
252     fprintf(stderr,"Error in seek (%d)\n",errno);
253     perror("mpeg_play");
254   }
255   vid_stream->seekValue = 0-vid_stream->seekValue;
256   vid_stream->totNumFrames = 0;
257 
258   /* clear that buffer */
259   vid_stream->buffer = vid_stream->buf_start;
260   vid_stream->buf_length = 0;
261   vid_stream->bit_offset = 0;
262 
263   /* Find a decent start code */
264  restart:
265  NO_ZEROS:
266   switch(fgetc(vid_stream->input)) {
267   case 0:    goto ONE_ZERO;
268   case EOF:  goto EOF_FOUND;
269   default:   goto NO_ZEROS;
270   }
271 
272  ONE_ZERO:
273   switch(fgetc(vid_stream->input)) {
274   case 0:    goto TWO_ZEROS;
275   case EOF:  goto EOF_FOUND;
276   default:   goto NO_ZEROS;
277   }
278 
279  TWO_ZEROS:
280   switch(fgetc(vid_stream->input)) {
281   case 0x01:  goto CODE_FOUND;
282   case 0x00:  goto TWO_ZEROS;
283   case EOF:   goto EOF_FOUND;
284   default:    goto NO_ZEROS;
285   }
286 
287  CODE_FOUND:
288   code = 0x00000100+fgetc(vid_stream->input);
289   if (vid_stream->sys_layer) {
290     clear_data_stream(vid_stream);
291     if (((code & PACKET_START_CODE_MASK) == PACKET_START_CODE_PREFIX) &&
292 	((code & 0xff) >= 0xbc)) {
293       read_sys(vid_stream, code);
294       while (TRUE) {
295 	next_start_code(vid_stream);
296 	show_bits32(code);
297 	if ((code == SEQ_START_CODE) ||
298 	    (code == GOP_START_CODE)) return;
299 	flush_bits32;
300       }
301     }
302   } else {
303     if ((code == SEQ_START_CODE) ||
304 	(code == GOP_START_CODE)) {
305       *vid_stream->buffer = code;
306       vid_stream->buf_length = 1;
307       return;
308     }
309   }
310   goto restart;
311 
312  EOF_FOUND:   /* received EOF */
313   fprintf(stderr, "Hit EOF after seeking (offset %ld)\n",
314      ftell(vid_stream->input));
315   exit(1);
316 
317 }
318 
319 
320 /*
321  *--------------------------------------------------------------
322  *
323  * pure_get_more_data --
324  *      (get_more_data from ver 2.0 with swap added)
325  *
326  *	Called by get_more_data to read in more data from
327  *      video MPG files (non-system-layer)
328  *
329  * Results:
330  *	Input buffer updated, buffer length updated.
331  *      Returns 1 if data read, 0 if EOF, -1 if error.
332  *
333  * Side effects:
334  *      None.
335  *
336  *--------------------------------------------------------------
337  */
338 
339 int
pure_get_more_data(buf_start,max_length,length_ptr,buf_ptr,vid_stream)340 pure_get_more_data(buf_start, max_length, length_ptr, buf_ptr, vid_stream)
341      unsigned int *buf_start;
342      int max_length;
343      int *length_ptr;
344      unsigned int **buf_ptr;
345      VidStream *vid_stream;
346 {
347 
348   int length, num_read, i;
349   unsigned int request;
350   unsigned char *buffer, *mark;
351   unsigned int *lmark;
352   BOOLEAN swap=vid_stream->swap;
353 
354   if (vid_stream->EOF_flag) return 0;
355 
356   length = *length_ptr;
357   buffer = (unsigned char *) *buf_ptr;
358 
359   if (length > 0) {
360     memcpy((unsigned char *) buf_start, buffer, (unsigned int) (length*4));
361     mark = ((unsigned char *) (buf_start + length));
362   }
363   else {
364     mark = (unsigned char *) buf_start;
365     length = 0;
366   }
367 
368   request = (max_length-length)*4;
369 
370 
371   num_read = fread(mark, 1, request, vid_stream->input);
372 
373   /* Paulo Villegas - 26/1/1993: Correction for 4-byte alignment */
374   {
375     int num_read_rounded;
376     unsigned char *index;
377 
378     num_read_rounded = 4*(num_read/4);
379 
380     /* this can happen only if num_read<request; i.e. end of file reached */
381     if ( num_read_rounded < num_read ) {
382  	  num_read_rounded = 4*( num_read/4+1 );
383 
384  	    /* fill in with zeros */
385  	  for( index=mark+num_read; index<mark+num_read_rounded; *(index++)=0 );
386 
387  	  /* advance to the next 4-byte boundary */
388  	  num_read = num_read_rounded;
389     }
390   }
391 
392   if (num_read < 0) {
393     return -1;
394   } else if (num_read == 0) {
395     *buf_ptr = buf_start;
396 
397     /* Make 32 bits after end equal to 0 and 32
398      * bits after that equal to seq end code
399      * in order to prevent messy data from infinite
400      * recursion.
401      */
402 
403     *(buf_start + length) = 0x0;
404     *(buf_start + length+1) = SEQ_END_CODE;
405 
406     vid_stream->EOF_flag = 1;
407     return 0;
408   }
409 
410   lmark = (unsigned int *) mark;
411 
412   num_read = num_read/4;
413 
414   if (swap) {
415     for (i = 0; i < num_read; i++) {
416       *lmark = htonl(*lmark);
417       lmark++;
418     }
419   }
420 
421   *buf_ptr = buf_start;
422   *length_ptr = length + num_read;
423 
424   return 1;
425 }
426 
427 
428 
429 
430 /*
431   Here is the specialist....
432   Code is adapted from our program demux....
433   A bunch of this needs to be #ifdef ANALYSIS'ed
434   define __SYSREAD_LOGGING_ON__ to get  an output file for debugging
435   */
436 
437 /* Brown - removed StreamID global variables */
438 #ifdef ANALYSIS
439 /* Statistics */
440 static int gNumAudioPackets;
441 static int gNumVideoPackets;
442 static int gNumPaddingPackets;
443 static int gNumReservedPackets;
444 static int gNumPrivate_1_Packets;
445 static int gNumPrivate_2_Packets;
446 #endif
447 
448 /*
449  *----------------------------------------------------------
450  *
451  *  read_sys
452  *
453  *      Parse out a packet of the system layer MPEG file.
454  *
455  *  Results:  Returns 0 if error or EOF
456  *            Returns 1 if more data read (could be just one int)
457  *
458  *  Side Effects:  ReadPacket can change *bs_ptr to be a new buffer
459  *                 buf_ptr will remain pointing at *length_ptr (at input)
460  *                         into the buffer
461  *                 *length_ptr will be changed to the new size
462  *                 *max_length can be changed if a new buffer is alloc'd
463  *
464  *----------------------------------------------------------
465  */
read_sys(vid_stream,start)466 int read_sys(vid_stream, start)
467      VidStream *vid_stream;
468      unsigned int start;
469      /* start is either a start code or 0 to indicate continued parsing */
470 {
471   unsigned int **bs_ptr=&vid_stream->buf_start;
472   int *max_length = &vid_stream->max_buf_length;
473   int *length_ptr=&vid_stream->buf_length;
474   unsigned int **buf_ptr=&vid_stream->buffer;
475   unsigned int startCode;
476   int errorCode, PacketReply;
477   unsigned char packetID;
478   double systemClockTime;
479   unsigned long muxRate;
480   /* Statistics */
481 #ifdef ANALYSIS
482   static int numPacks = 0;
483   static int numPackets = 0;
484   static int numSystemHeaders = 0;
485 #endif
486   BOOLEAN match;
487 
488   if (!start) {
489     errorCode = ReadStartCode(&startCode,vid_stream);
490     if (vid_stream->EOF_flag) return 0;
491     if (errorCode != 0) {
492       fprintf(stderr, "Unable to read initial pack start code\n");
493       return 0;
494     }}
495   else {
496     errorCode = 0;
497     startCode = start;
498   }
499 
500   while (1) {
501     match=FALSE;
502     if (startCode == PACK_START_CODE) {
503 #ifdef ANALYSIS
504       ++numPacks;
505 #endif
506       match = TRUE;
507       errorCode = ReadPackHeader( &systemClockTime, &muxRate, vid_stream);
508       if (errorCode != 0) {
509         fprintf(stderr, "Error in reading pack header\n");
510         return 0;
511       }
512       errorCode = ReadStartCode( &startCode, vid_stream );
513       if (errorCode != 0) {
514         fprintf(stderr, "Error in reading start code\n");
515         return 0;
516       }
517     }
518     if (startCode == SYSTEM_HEADER_START_CODE) {
519 #ifdef ANALYSIS
520       ++numSystemHeaders;
521 #endif
522       match = TRUE;
523       errorCode = ReadSystemHeader(vid_stream);
524       if (errorCode != 0) {
525         fprintf(stderr, "Error in reading system header\n");
526         return 0;
527       }
528       errorCode = ReadStartCode( &startCode, vid_stream );
529       if (errorCode != 0) {
530         fprintf(stderr,"Error in reading start code after system header\n");
531         return 0;
532       }
533     }
534     packetID = startCode & 0xff;
535     while (((startCode & PACKET_START_CODE_MASK) == PACKET_START_CODE_PREFIX) &&
536 	   (packetID >= 0xbc)) {
537 #ifdef ANALYSIS
538       ++numPackets;
539 #endif
540       match = TRUE;
541       packetID = startCode & 0xff;
542       PacketReply = ReadPacket(packetID, vid_stream);
543       switch (PacketReply) {
544       case 2:
545         return 1;
546       case 1:
547         return 0;
548       default: /* do nothing */
549         break;
550       }
551       errorCode = ReadStartCode( &startCode, vid_stream );
552       if (errorCode != 0) {
553         fprintf(stderr,"Error in start code after packet\n");
554         return 0;
555       }
556       if (startCode == PACK_START_CODE || startCode == ISO_11172_END_CODE) {
557         break;
558       }
559     }
560 
561     if (startCode == ISO_11172_END_CODE) {
562       match = TRUE;
563       if (vid_stream->Parse_done) {
564 	return 1;
565       }
566 #ifdef ANALYSIS
567       fprintf(stderr, "Successful parse of MPEG system level\n");
568       fprintf(stderr, "%d system headers, %d packs, %d packets\n",
569 	      numSystemHeaders, numPacks, numPackets);
570       fprintf(stderr, "%d audio packets, %d video packets, %d padding packets\n",
571 	      gNumAudioPackets, gNumVideoPackets, gNumPaddingPackets);
572       fprintf(stderr, "%d reserved packets, %d/%d private type 1/2 packets\n",
573 	      gNumReservedPackets, gNumPrivate_1_Packets, gNumPrivate_2_Packets);
574 #endif
575       ReadPacket(NOT_PACKET_ID, vid_stream);
576       vid_stream->Parse_done = TRUE;
577       return 1;
578     }
579     if (errorCode != 0)
580       return 1;
581     if (! match) {
582       fprintf(stderr,"\nNo match found for start code %08x in system layer, skipping\n",startCode);
583       startCode = find_start_code(vid_stream->input);
584       if (startCode == EOF) {
585         vid_stream->EOF_flag = 1;
586         return 0;
587       }
588     }
589   }
590 }
591 
592 
593 /*
594  *-----------------------------------------------------------
595  *
596  *  ReadStartCode
597  *
598  *      Parses a start code out of the stream
599  *
600  *  Results/Side Effects:  Sets *startCode to the code, returns
601  *     1 on error, 0 on success
602  *
603  *-----------------------------------------------------------
604  */
ReadStartCode(startCode,vid_stream)605 int ReadStartCode(startCode, vid_stream)
606      unsigned int *startCode;
607      VidStream *vid_stream;
608 {
609   int numRead;
610 
611   numRead = fread((unsigned char *)startCode, 1, 4, vid_stream->input);
612   *startCode = htonl(*startCode);
613 
614   if (numRead < 4) {
615     vid_stream->EOF_flag = 1;
616     return 1;
617   }
618 
619   if ((*startCode&0xfffffe00) != 0) {
620     fprintf(stderr,"Problem with system layer parse, skipping to start code\n");
621     *startCode = find_start_code(vid_stream->input);
622     if (*startCode == EOF) {
623        vid_stream->EOF_flag = TRUE;
624       return 0;
625     }
626   }
627 
628   return 0;
629 }
630 
631 
632 /*
633  *-----------------------------------------------------------
634  *
635  *  find_start_code
636  *
637  *      Parses a start code out of the stream by tossing bytes until it gets one
638  *
639  *  Results/Side Effects:  Parses bytes of the stream, returns code
640  *                         Returns EOF in case of end of file
641  *
642  *-----------------------------------------------------------
643  */
find_start_code(input)644 int find_start_code(input)
645     FILE *input;
646 {
647  NO_ZEROS:
648   switch(fgetc(input)) {
649   case 0:    goto ONE_ZERO;
650   case EOF:  goto EOF_FOUND;
651   default:   goto NO_ZEROS;
652   }
653 
654  ONE_ZERO:
655   switch(fgetc(input)) {
656   case 0:    goto TWO_ZEROS;
657   case EOF:  goto EOF_FOUND;
658   default:   goto NO_ZEROS;
659   }
660 
661  TWO_ZEROS:
662   switch(fgetc(input)) {
663   case 0x01:  goto CODE_FOUND;
664   case 0x00:  goto TWO_ZEROS;
665   case EOF:  goto EOF_FOUND;
666   default:    goto NO_ZEROS;
667   }
668 
669  CODE_FOUND:
670   return 0x00000100+fgetc(input);
671 
672  EOF_FOUND:   /* received EOF */
673   return EOF;
674 }
675 
676 
677 
678 
679 /*
680  *-----------------------------------------------------------------
681  *
682  *  ReadPackHeader
683  *
684  *      Parses out the PACK header
685  *
686  *  Returns: 1 on error, 0 on success
687  *
688  *-------------------------------------------------------------------
689  */
ReadPackHeader(systemClockTime,muxRate,vid_stream)690 int ReadPackHeader(systemClockTime,muxRate, vid_stream)
691      double *systemClockTime;
692      unsigned long *muxRate;
693      VidStream *vid_stream;
694 {
695   int numRead;
696   unsigned char inputBuffer[PACK_HEADER_SIZE];
697   unsigned long systemClockRef;
698   unsigned char systemClockRefHiBit;
699   int errorCode;
700 
701   numRead = fread(inputBuffer, 1, PACK_HEADER_SIZE, vid_stream->input);
702   if (numRead < PACK_HEADER_SIZE) {
703     vid_stream->EOF_flag = 1;
704     return 1;
705   }
706   ReadTimeStamp(inputBuffer, &systemClockRefHiBit, &systemClockRef);
707   errorCode = MakeFloatClockTime(systemClockRefHiBit, systemClockRef,
708 				 systemClockTime);
709   ReadRate(&inputBuffer[5], muxRate);
710   *muxRate *= MUX_RATE_SCALE_FACTOR;
711   return 0;
712 }
713 
714 
715 /*
716  *------------------------------------------------------------------
717  *
718  *   ReadSystemHeader
719  *
720  *      Parse out the system header, setup out stream IDs for parsing packets
721  *
722  *   Results:  Returns 1 on error, 0 on success.
723  *             Sets gAudioStreamID and gVideoStreamID
724  *
725  *------------------------------------------------------------------
726  */
ReadSystemHeader(vid_stream)727 int ReadSystemHeader(vid_stream)
728    VidStream *vid_stream;
729 {
730   unsigned char *inputBuffer = NULL;
731   int numRead;
732   int pos;
733   unsigned short headerSize;
734   unsigned char streamID;
735 
736   numRead = fread((char *)&headerSize, 1, 2, vid_stream->input);
737   headerSize = ntohs(headerSize);
738   if (numRead != 2) {
739     vid_stream->EOF_flag = 1;
740     return 1;
741   }
742   inputBuffer = (unsigned char *) malloc((unsigned int) headerSize+1);
743   if (inputBuffer == NULL) {
744     return 1;
745   }
746   inputBuffer[headerSize]=0;
747   numRead = fread(inputBuffer, 1, headerSize, vid_stream->input);
748   /* Brown - get rid of Ansi C complaints */
749   if (numRead < (int) headerSize) {
750     vid_stream->EOF_flag = 1;
751     return 1;
752   }
753 
754   pos = 6;
755   while ((inputBuffer[pos] & 0x80) == 0x80) {
756     streamID = inputBuffer[pos];
757     switch (streamID) {
758     case STD_VIDEO_STREAM_ID:
759       break;
760     case STD_AUDIO_STREAM_ID:
761       break;
762     case RESERVED_STREAM_ID:
763       break;
764     case PADDING_STREAM_ID:
765       break;
766     case PRIVATE_STREAM_1_ID:
767       break;
768     case PRIVATE_STREAM_2_ID:
769       break;
770     default:
771       if (streamID < MIN_STREAM_ID_ID) {
772 	return 1;
773       }
774       switch (streamID >> 4) {
775       case 0xc:
776       case 0xd:
777 	vid_stream->gAudioStreamID = streamID;
778 	break;
779       case 0xe:
780 	if ((vid_stream->gVideoStreamID != 0) &&
781 	    (vid_stream->gVideoStreamID!=streamID)) {
782 	  break;
783 	}
784 	vid_stream->gVideoStreamID = streamID;
785 	break;
786       case 0xf:
787 /*Brown - deglobalized gReservedStreamID */
788 	vid_stream->gReservedStreamID = streamID;
789 	break;
790       }
791       break;
792     }
793     pos += 3;
794   }
795   if (inputBuffer != NULL)
796     free(inputBuffer);
797   return 0;
798 }
799 
800 
801 /*
802  *-----------------------------------------------------------------
803  *
804  *  ReadPacket
805  *
806  *      Reads a single packet out of the stream, and puts it in the
807  *      buffer if it is video.
808  *
809  *  Results:
810  *      Changes the value of *length_ptr to be the new length (plus old)
811  *      If the buffer is too small, can change *bs_ptr, *max_length, and
812  *      buf_ptr to be correct for a newly allocated buffer.
813  *
814  *  State:
815  *      The buffer is in ints, but the packets can be an arbitrary number
816  *      of bytes, so leftover bytes are kept in the VidStream variable and
817  *      are added on the next call.
818  *
819  *-----------------------------------------------------------------
820  */
821 #ifdef __STDC__
ReadPacket(unsigned char packetID,VidStream * vid_stream)822 int ReadPacket(unsigned char packetID, VidStream *vid_stream)
823 #else
824 int ReadPacket(packetID, vid_stream)
825      unsigned char packetID;
826      VidStream *vid_stream;
827 #endif
828 
829      /* Returns:
830 	0 - no error, but not video packet we want
831 	1 - error
832 	2 - got video packet into buffer
833 	*/
834 {
835   unsigned int **bs_ptr=&vid_stream->buf_start;
836   int *max_length = &vid_stream->max_buf_length;
837   int *length_ptr=&vid_stream->buf_length;
838   unsigned int **buf_ptr=&vid_stream->buffer;
839   int ioBytes;
840   unsigned char nextByte;
841   unsigned short packetLength;
842   unsigned char *packetBuffer = NULL;
843   int pos;
844   int numStuffBytes = 0;
845   unsigned int packetDataLength;
846   int byte_length;
847   unsigned char scratch[10];
848   /* Leftovers from previous video packets */
849 
850   if (packetID == NOT_PACKET_ID) {
851     /* Gross hack to handle unread bytes before end of stream */
852     if (vid_stream->num_left != 0) {
853       /* Sigh, deal with previous leftovers */
854       *(*buf_ptr+*length_ptr) = vid_stream->leftover_bytes;
855       *(*buf_ptr+*length_ptr+1) = ISO_11172_END_CODE;
856       *length_ptr += 2;
857     } else {
858       *(*buf_ptr+*length_ptr) = ISO_11172_END_CODE;
859       *length_ptr += 1;
860     }
861     return 1;
862   } else if (packetID==KILL_BUFFER) {
863     vid_stream->num_left=0;
864     vid_stream->leftover_bytes=0;
865     return 0;
866   }
867 
868   ioBytes = fread(&packetLength, 1, 2, vid_stream->input);
869   packetLength = htons(packetLength);
870   if (ioBytes < 2) {
871     return 1;
872   }
873   if (packetID == vid_stream->gAudioStreamID) {
874 #ifdef ANALYSIS
875     ++gNumAudioPackets;
876 #endif
877   }
878   else if (packetID == vid_stream->gVideoStreamID) {
879 #ifdef ANALYSIS
880     ++gNumVideoPackets;
881 #endif
882   }
883   else {
884     switch (packetID) {
885     case PADDING_STREAM_ID:
886 #ifdef ANALYSIS
887       ++gNumPaddingPackets;
888 #endif
889       break;
890     case RESERVED_STREAM_ID:
891 #ifdef ANALYSIS
892       ++gNumReservedPackets;
893 #endif
894       break;
895     case PRIVATE_STREAM_1_ID:
896 #ifdef ANALYSIS
897       ++gNumPrivate_1_Packets;
898 #endif
899       break;
900     case PRIVATE_STREAM_2_ID:
901 #ifdef ANALYSIS
902       ++gNumPrivate_2_Packets;
903 #endif
904       break;
905     default:
906       fprintf(stderr, "\nUnknown packet type encountered. P'bly audio? (%x) at %d\n",
907 	      packetID,(int) ftell(vid_stream->input));
908     }
909     if (packetID != vid_stream->gVideoStreamID) {/* changed by jim */
910       fseek(vid_stream->input, packetLength, 1);
911       return 0;
912     }
913   }
914 
915   fread(&nextByte,1,1,vid_stream->input);
916   pos = 0;
917   while (nextByte & 0x80) {
918     ++numStuffBytes;
919     ++pos;
920     fread(&nextByte,1,1,vid_stream->input);
921   }
922   if ((nextByte >> 6) == 0x01) {
923     pos += 2;
924     fread(&nextByte,1,1,vid_stream->input);
925     fread(&nextByte,1,1,vid_stream->input);
926   }
927   if ((nextByte >> 4) == 0x02) {
928     scratch[0] = nextByte;                      /* jim */
929     fread(&scratch[1],1,4,vid_stream->input);   /* jim */
930     fread(&nextByte,1,1,vid_stream->input);
931     pos += 5;
932   }
933   else if ((nextByte >> 4) == 0x03) {
934     scratch[0] = nextByte;                      /* jim */
935     fread(&scratch[1],1,9,vid_stream->input);   /* jim */
936     fread(&nextByte,1,1,vid_stream->input);
937     pos += 10;
938   }
939   else {
940     fread(&nextByte,1,1,vid_stream->input);
941     pos += 1;
942   }
943   /* Read all the headers, now make room for packet */
944   if (*bs_ptr + *max_length < *buf_ptr+ packetLength/4 + *length_ptr) {
945      /* Brown - get rid of Ansi C complaints */
946     if (*max_length - *length_ptr < (int) packetLength/4) {
947       /* Buffer too small for a packet (plus whats there),
948 	   * time to enlarge it!
949 	   */
950       unsigned int *old = *bs_ptr;
951       *max_length = *length_ptr + packetLength/2;
952       *bs_ptr=(unsigned int *)malloc(*max_length*4);
953       if (*bs_ptr == NULL) {
954         return 1;
955       }
956       memcpy((unsigned char *)*bs_ptr, *buf_ptr, (unsigned int) *length_ptr*4);
957       free(old);
958       *buf_ptr = *bs_ptr;
959     } else {
960       memcpy((unsigned char *)*bs_ptr, *buf_ptr, (unsigned int) *length_ptr*4);
961       *buf_ptr = *bs_ptr;
962     }}
963   byte_length = *length_ptr*4;
964   if (vid_stream->num_left != 0) {
965     /* Sigh, deal with previous leftovers */
966     byte_length += vid_stream->num_left;
967     *(*buf_ptr+*length_ptr) = vid_stream->leftover_bytes;
968   }
969   packetBuffer=((unsigned char *)*buf_ptr)+byte_length;
970   packetDataLength = packetLength - pos;
971   *packetBuffer++ = nextByte;
972 /* Brown - deglobalize gVideoStreamID */
973   if (packetID == vid_stream->gVideoStreamID) {
974     ioBytes = fread(packetBuffer, 1, packetDataLength-1, vid_stream->input);
975     if (ioBytes != packetDataLength-1) {
976       vid_stream->EOF_flag = 1;
977       return 1;
978     }
979     if (1 != ntohl(1)) {
980       unsigned int *mark = *buf_ptr+*length_ptr;
981       int i;
982 
983       for (i=0; i < ((packetDataLength+
984 			 vid_stream->num_left)&0xfffffffc); i+=4) {
985         *mark=ntohl(*mark);
986         mark++;
987       }
988     }
989     byte_length = byte_length + packetDataLength;
990     vid_stream->num_left = byte_length % 4;
991     *length_ptr = byte_length / 4;
992     vid_stream->leftover_bytes = *(*buf_ptr + *length_ptr);
993     return 2;
994   }
995   else if (packetID == vid_stream->gAudioStreamID) {
996     packetBuffer = (unsigned char *)(*buf_ptr + *length_ptr + 1);
997     fread(packetBuffer, 1, packetDataLength - 1, vid_stream->input);
998   }
999   else /* Donno what it is, just nuke it */ {
1000     /* This code should be unreachable */
1001     packetBuffer = (unsigned char *)(*buf_ptr + *length_ptr + 1);
1002     fread(packetBuffer, 1, packetDataLength - 1, vid_stream->input);
1003   }
1004   return 0;
1005 }
1006 
1007 
1008 /*
1009  * The remaining procedures are formatting utility procedures.
1010  */
ReadTimeStamp(inputBuffer,hiBit,low4Bytes)1011 void ReadTimeStamp(inputBuffer,hiBit,low4Bytes)
1012      unsigned char *inputBuffer, *hiBit;
1013      unsigned long *low4Bytes;
1014 {
1015   *hiBit = ((unsigned long)inputBuffer[0] >> 3) & 0x01;
1016   *low4Bytes = (((unsigned long)inputBuffer[0] >> 1) & 0x03) << 30;
1017   *low4Bytes |= (unsigned long)inputBuffer[1] << 22;
1018   *low4Bytes |= ((unsigned long)inputBuffer[2] >> 1) << 15;
1019   *low4Bytes |= (unsigned long)inputBuffer[3] << 7;
1020   *low4Bytes |= ((unsigned long)inputBuffer[4]) >> 1;
1021 }
1022 
ReadSTD(inputBuffer,stdBufferScale,stdBufferSize)1023 void ReadSTD(inputBuffer,stdBufferScale,stdBufferSize)
1024 unsigned char *inputBuffer;
1025 unsigned char *stdBufferScale;
1026 unsigned long *stdBufferSize;
1027 {
1028   /* Brown - get rid of ANSI C complaints */
1029   *stdBufferScale = ((int)(inputBuffer[0] & 0x20) >> 5);
1030   *stdBufferSize = ((unsigned long)inputBuffer[0] & 0x1f) << 8;
1031   *stdBufferSize |= (unsigned long)inputBuffer[1];
1032 }
1033 
1034 
ReadRate(inputBuffer,rate)1035 void ReadRate(inputBuffer,rate)
1036      unsigned char *inputBuffer;
1037      unsigned long *rate;
1038 {
1039   *rate = (inputBuffer[0] & 0x7f) << 15;
1040   *rate |= inputBuffer[1] << 7;
1041   /* Brown - get rid of ANSI C complaints */
1042   *rate |= (int) (inputBuffer[2] & 0xfe) >> 1;
1043 }
1044 
1045 #define FLOAT_0x10000 (double)((unsigned long)1 << 16)
1046 
1047 #ifdef __STDC__
MakeFloatClockTime(unsigned char hiBit,unsigned long low4Bytes,double * floatClockTime)1048 int MakeFloatClockTime(unsigned char hiBit, unsigned long low4Bytes,
1049 		       double * floatClockTime)
1050 #else
1051 int MakeFloatClockTime(hiBit,low4Bytes,floatClockTime)
1052      unsigned char hiBit;
1053      unsigned long low4Bytes;
1054      double *floatClockTime;
1055 #endif
1056 {
1057   if (hiBit != 0 && hiBit != 1) {
1058     *floatClockTime = 0.0;
1059     return 1;
1060   }
1061   *floatClockTime
1062     = (double)hiBit*FLOAT_0x10000*FLOAT_0x10000 + (double)low4Bytes;
1063   *floatClockTime /= (double)STD_SYSTEM_CLOCK_FREQ;
1064   return 0;
1065 }
1066