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