Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 pj 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>	TO FIX!!! */
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
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
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
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
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
 */
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
 */
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
 */
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
 */
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
 */
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__
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
 
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
 */
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
 
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
 
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__
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
}