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