Subversion Repositories shark

Rev

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