1 /*
2  * util.c --
3  *
4  *      Miscellaneous utility procedures.
5  *
6  */
7 
8 /*
9  * Copyright (c) 1995 The Regents of the University of California.
10  * All rights reserved.
11  *
12  * Permission to use, copy, modify, and distribute this software and its
13  * documentation for any purpose, without fee, and without written agreement is
14  * hereby granted, provided that the above copyright notice and the following
15  * two paragraphs appear in all copies of this software.
16  *
17  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
18  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
19  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
20  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21  *
22  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
23  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
24  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
25  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
26  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
27  */
28 
29 /*
30  * Portions of this software Copyright (c) 1995 Brown University.
31  * All rights reserved.
32  *
33  * Permission to use, copy, modify, and distribute this software and its
34  * documentation for any purpose, without fee, and without written agreement
35  * is hereby granted, provided that the above copyright notice and the
36  * following two paragraphs appear in all copies of this software.
37  *
38  * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR
39  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
40  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN
41  * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  *
43  * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
44  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
45  * PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS"
46  * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
47  * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
48  */
49 
50 #include <stdlib.h>
51 #include "video.h"
52 #include "proto.h"
53 #include "util.h"
54 #ifndef NOCONTROLS
55 #include "ctrlbar.h"
56 #endif
57 
58 /*
59    Changes to make the code reentrant:
60      de-globalized: totNumFrames, realTimeStart, vid_stream, sys_layer,
61         bitOffset, bitLength, bitBuffer, curVidStream
62      setjmp/longjmp replaced
63 
64    Additional changes:
65      only call DestroyVidStream up in mpegVidRsrc, not in correct_underflow
66 
67    -lsh@cs.brown.edu (Loring Holden)
68  */
69 
70 /* Bit masks used by bit i/o operations. */
71 
72 unsigned int nBitMask[] = { 0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
73 			    0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
74 			    0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
75 			    0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
76 			    0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
77 			    0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
78 			    0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
79 			    0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe};
80 
81 unsigned int bitMask[] = {  0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff,
82 			    0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff,
83 			    0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff,
84 			    0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff,
85 			    0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff,
86 			    0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff,
87 			    0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f,
88 			    0x0000000f, 0x00000007, 0x00000003, 0x00000001};
89 
90 unsigned int rBitMask[] = { 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8,
91 			    0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80,
92 			    0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800,
93 			    0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000,
94 			    0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000,
95 			    0xfff00000, 0xffe00000, 0xffc00000, 0xff800000,
96 			    0xff000000, 0xfe000000, 0xfc000000, 0xf8000000,
97 			    0xf0000000, 0xe0000000, 0xc0000000, 0x80000000};
98 
99 unsigned int bitTest[] = {  0x80000000, 0x40000000, 0x20000000, 0x10000000,
100 			    0x08000000, 0x04000000, 0x02000000, 0x01000000,
101 			    0x00800000, 0x00400000, 0x00200000, 0x00100000,
102 			    0x00080000, 0x00040000, 0x00020000, 0x00010000,
103 			    0x00008000, 0x00004000, 0x00002000, 0x00001000,
104 			    0x00000800, 0x00000400, 0x00000200, 0x00000100,
105 			    0x00000080, 0x00000040, 0x00000020, 0x00000010,
106 			    0x00000008, 0x00000004, 0x00000002, 0x00000001};
107 
108 
109 /*
110  *--------------------------------------------------------------
111  *
112  * correct_underflow --
113  *
114  *	Called when buffer does not have sufficient data to
115  *      satisfy request for bits.
116  *      Calls get_more_data, an application specific routine
117  *      required to fill the buffer with more data.
118  *
119  * Results:
120  *      None really.
121  *
122  * Side effects:
123  *	buf_length and buffer fields may be changed.
124  *
125  *--------------------------------------------------------------
126  */
127 
128 void
correct_underflow(vid_stream)129 correct_underflow(vid_stream)
130    VidStream *vid_stream;
131 {
132 
133   int status;
134 
135   status = get_more_data(vid_stream);
136 
137   if (status  < 0) {
138     if (!quietFlag) {
139       fprintf (stderr, "\n");
140       perror("Unexpected read error.");
141     }
142     exit(1);
143   }
144   else if ((status == 0) && (vid_stream->buf_length < 1)) {
145     if (!quietFlag) {
146       fprintf(stderr, "\nImproper or missing sequence end code.\n");
147     }
148 #ifdef ANALYSIS
149     PrintAllStats(vid_stream);
150 #endif
151     if (!quietFlag) {
152       PrintTimeInfo(vid_stream);
153     }
154 
155     vid_stream->film_has_ended=TRUE;
156 #ifndef NOCONTROLS
157     /* Hmm, don't really know if this works or not... */
158     clear_data_stream(vid_stream);
159     return;
160 #else
161     if (loopFlag) {
162       clear_data_stream(vid_stream);
163     } /* destroy stream up in mpegVidRsrc */
164     return;
165 #endif /* !NOCONTROLS */
166   }
167 #ifdef UTIL2
168   vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset;
169 #else
170   vid_stream->curBits = *vid_stream->buffer;
171 #endif
172 
173 }
174 
175 
176 /*
177  *--------------------------------------------------------------
178  *
179  * next_bits --
180  *
181  *	Compares next num bits to low order position in mask.
182  *      Buffer pointer is NOT advanced.
183  *
184  * Results:
185  *	TRUE, FALSE, or error code.
186  *
187  * Side effects:
188  *	None.
189  *
190  *--------------------------------------------------------------
191  */
192 
next_bits(num,mask,vid_stream)193 int next_bits(num, mask, vid_stream)
194 int num;
195 unsigned int mask;
196 VidStream *vid_stream;
197 {
198   unsigned int stream;
199   int ret_value;
200 
201   /* If no current stream, return error. */
202 
203   if (vid_stream == NULL)
204     return NO_VID_STREAM;
205 
206   /* Get next num bits, no buffer pointer advance. */
207 
208   show_bitsn(num, stream);
209 
210   /* Compare bit stream and mask. Set return value toTRUE if equal, FALSE if
211      differs.
212   */
213 
214   if (mask == stream) {
215     ret_value = TRUE;
216   } else ret_value = FALSE;
217 
218   /* Return return value. */
219   return ret_value;
220 }
221 
222 
223 /*
224  *--------------------------------------------------------------
225  *
226  * get_ext_data --
227  *
228  *	Assumes that bit stream is at begining of extension
229  *      data. Parses off extension data into dynamically
230  *      allocated space until start code is hit.
231  *
232  * Results:
233  *	Pointer to dynamically allocated memory containing
234  *      extension data.
235  *
236  * Side effects:
237  *	Bit stream irreversibly parsed.
238  *
239  *--------------------------------------------------------------
240  */
241 
get_ext_data(vid_stream)242 char *get_ext_data (vid_stream)
243    VidStream *vid_stream;
244 {
245   unsigned int size, marker;
246   char *dataPtr;
247   unsigned int data;
248 
249   /* Set initial ext data buffer size. */
250 
251   size = EXT_BUF_SIZE;
252 
253   /* Allocate ext data buffer. */
254 
255   dataPtr = (char *) malloc(size);
256 
257   /* Initialize marker to keep place in ext data buffer. */
258 
259   marker = 0;
260 
261   /* While next data is not start code... */
262   while (!next_bits(24, 0x000001, vid_stream)) {
263 
264     /* Get next byte of ext data. */
265 
266     get_bits8(data);
267 
268     /* Put ext data into ext data buffer. Advance marker. */
269 
270     dataPtr[marker] = (char) data;
271     marker++;
272 
273     /* If end of ext data buffer reached, resize data buffer. */
274 
275     if (marker == size) {
276       size += EXT_BUF_SIZE;
277       dataPtr = (char *) realloc(dataPtr, size);
278     }
279   }
280 
281   /* Realloc data buffer to free any extra space. */
282 
283   dataPtr = (char *) realloc(dataPtr, marker);
284 
285   /* Return pointer to ext data buffer. */
286   return dataPtr;
287 }
288 
289 
290 /*
291  *--------------------------------------------------------------
292  *
293  * next_start_code --
294  *
295  *	Parses off bitstream until start code reached. When done
296  *      next 4 bytes of bitstream will be start code. Bit offset
297  *      reset to 0.
298  *
299  * Results:
300  *	Status code.
301  *
302  * Side effects:
303  *	Bit stream irreversibly parsed.
304  *
305  *--------------------------------------------------------------
306  */
307 
next_start_code(vid_stream)308 int next_start_code(vid_stream)
309    VidStream *vid_stream;
310 {
311   int state;
312   int byteoff;
313   unsigned int data;
314 
315   /* If no current stream, return error. */
316 
317   if (vid_stream== NULL)
318     return NO_VID_STREAM;
319 
320   /* If insufficient buffer length, correct underflow. */
321 
322   if (vid_stream->buf_length < 4) {
323     correct_underflow(vid_stream);
324   }
325 
326   /* If bit offset not zero, reset and advance buffer pointer. */
327 
328   byteoff = vid_stream->bit_offset % 8;
329 
330   if (byteoff != 0) {
331     flush_bits((8-byteoff));
332   }
333 
334   /* Set state = 0. */
335 
336   state = 0;
337 
338   /* While buffer has data ... */
339 
340   while(vid_stream->buf_length > 0) {
341 
342     /* If insufficient data exists, correct underflow. */
343 
344 
345     if (vid_stream->buf_length < 4) {
346       correct_underflow(vid_stream);
347     }
348 
349     /* If next byte is zero... */
350 
351     get_bits8(data);
352 
353     if (data == 0) {
354 
355       /* If state < 2, advance state. */
356 
357       if (state < 2) state++;
358     }
359 
360     /* If next byte is one... */
361 
362     else if (data == 1) {
363 
364       /* If state == 2, advance state (i.e. start code found). */
365 
366       if (state == 2) state++;
367 
368       /* Otherwise, reset state to zero. */
369 
370       else state = 0;
371     }
372 
373     /* Otherwise byte is neither 1 or 0, reset state to 0. */
374 
375     else {
376       state = 0;
377     }
378 
379     /* If state == 3 (i.e. start code found)... */
380 
381     if (state == 3) {
382 
383       /* Set buffer pointer back and reset length & bit offsets so
384        * next bytes will be beginning of start code.
385        */
386 
387       vid_stream->bit_offset = vid_stream->bit_offset - 24;
388 
389 #ifdef ANALYSIS
390       bitCount -= 24;
391 #endif
392 
393       if (vid_stream->bit_offset < 0) {
394         vid_stream->bit_offset = 32 + vid_stream->bit_offset;
395         vid_stream->buf_length++;
396         vid_stream->buffer--;
397 #ifdef UTIL2
398         vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset;
399 #else
400         vid_stream->curBits = *vid_stream->buffer;
401 #endif
402       }
403       else {
404 #ifdef UTIL2
405         vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset;
406 #else
407         vid_stream->curBits = *vid_stream->buffer;
408 #endif
409       }
410 
411       /* Return success. */
412       return OK;
413     }
414   }
415 
416   /* Return underflow error. */
417   return STREAM_UNDERFLOW;
418 }
419 
420 
421 /*
422  *--------------------------------------------------------------
423  *
424  * get_extra_bit_info --
425  *
426  *	Parses off extra bit info stream into dynamically
427  *      allocated memory. Extra bit info is indicated by
428  *      a flag bit set to 1, followed by 8 bits of data.
429  *      This continues until the flag bit is zero. Assumes
430  *      that bit stream set to first flag bit in extra
431  *      bit info stream.
432  *
433  * Results:
434  *	Pointer to dynamically allocated memory with extra
435  *      bit info in it. Flag bits are NOT included.
436  *
437  * Side effects:
438  *	Bit stream irreversibly parsed.
439  *
440  *--------------------------------------------------------------
441  */
442 
get_extra_bit_info(vid_stream)443 char *get_extra_bit_info(vid_stream)
444 VidStream *vid_stream;
445 {
446   unsigned int size, marker;
447   char *dataPtr;
448   unsigned int data;
449 
450   /* Get first flag bit. */
451   get_bits1(data);
452 
453   /* If flag is false, return NULL pointer (i.e. no extra bit info). */
454 
455   if (!data) return NULL;
456 
457   /* Initialize size of extra bit info buffer and allocate. */
458 
459   size = EXT_BUF_SIZE;
460   dataPtr = (char *) malloc(size);
461 
462   /* Reset marker to hold place in buffer. */
463 
464   marker = 0;
465 
466   /* While flag bit is true. */
467 
468   while (data) {
469 
470     /* Get next 8 bits of data. */
471     get_bits8(data);
472 
473     /* Place in extra bit info buffer. */
474 
475     dataPtr[marker] = (char) data;
476     marker++;
477 
478     /* If buffer is full, reallocate. */
479 
480     if (marker == size) {
481       size += EXT_BUF_SIZE;
482       dataPtr = (char *) realloc(dataPtr, size);
483     }
484 
485     /* Get next flag bit. */
486     get_bits1(data);
487   }
488 
489   /* Reallocate buffer to free extra space. */
490 
491   dataPtr = (char *) realloc(dataPtr, marker);
492 
493   /* Return pointer to extra bit info buffer. */
494   return dataPtr;
495 }
496