ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/freemol/trunk/src/mpeg_encode/src/bitio.c
Revision: 22
Committed: Mon Jul 7 22:16:37 2008 UTC (11 years ago) by wdelano
File size: 14046 byte(s)
Log Message:
initial checkin of mpeg_encode source
Line File contents
1 /*===========================================================================*
2 * bitio.c *
3 * *
4 * Procedures concerned with the bit-wise I/O *
5 * *
6 * EXPORTED PROCEDURES: *
7 * Bitio_New *
8 * Bitio_Free *
9 * Bitio_Write *
10 * Bitio_Flush *
11 * Bitio_WriteToSocket *
12 * Bitio_BytePad *
13 * *
14 *===========================================================================*/
15
16 /*
17 * Copyright (c) 1995 The Regents of the University of California.
18 * All rights reserved.
19 *
20 * Permission to use, copy, modify, and distribute this software and its
21 * documentation for any purpose, without fee, and without written agreement is
22 * hereby granted, provided that the above copyright notice and the following
23 * two paragraphs appear in all copies of this software.
24 *
25 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
26 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
27 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
28 * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
32 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
33 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
34 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
35 */
36
37 /*
38 * $Header: /n/picasso/project/mm/mpeg/mpeg_dist/mpeg_encode/RCS/bitio.c,v 1.13 1995/06/21 18:36:06 smoot Exp $
39 * $Log: bitio.c,v $
40 * Revision 1.13 1995/06/21 18:36:06 smoot
41 * added a flush when done with file
42 *
43 * Revision 1.12 1995/01/19 23:07:15 eyhung
44 * Changed copyrights
45 *
46 * Revision 1.11 1994/11/12 02:11:43 keving
47 * nothing
48 *
49 * Revision 1.10 1993/12/22 19:19:01 keving
50 * nothing
51 *
52 * Revision 1.10 1993/12/22 19:19:01 keving
53 * nothing
54 *
55 * Revision 1.9 1993/07/22 22:23:43 keving
56 * nothing
57 *
58 * Revision 1.8 1993/06/30 20:06:09 keving
59 * nothing
60 *
61 * Revision 1.7 1993/06/03 21:08:08 keving
62 * nothing
63 *
64 * Revision 1.6 1993/02/17 23:21:41 dwallach
65 * checkin prior to keving's joining the project
66 *
67 * Revision 1.5 1993/01/18 10:20:02 dwallach
68 * *** empty log message ***
69 *
70 * Revision 1.4 1993/01/18 10:17:29 dwallach
71 * RCS headers installed, code indented uniformly
72 *
73 * Revision 1.4 1993/01/18 10:17:29 dwallach
74 * RCS headers installed, code indented uniformly
75 *
76 */
77
78 /*==============*
79 * HEADER FILES *
80 *==============*/
81
82 #include <assert.h>
83 #include "all.h"
84 #include "byteorder.h"
85 #include "bitio.h"
86 #include "mtypes.h"
87
88
89 /*===============================*
90 * INTERNAL PROCEDURE prototypes *
91 *===============================*/
92
93 static void Dump _ANSI_ARGS_((BitBucket *bbPtr));
94
95
96 /*==================*
97 * STATIC VARIABLES *
98 *==================*/
99
100 static uint32 lower_mask[33] = {
101 0,
102 0x1, 0x3, 0x7, 0xf,
103 0x1f, 0x3f, 0x7f, 0xff,
104 0x1ff, 0x3ff, 0x7ff, 0xfff,
105 0x1fff, 0x3fff, 0x7fff, 0xffff,
106 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff,
107 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff,
108 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff,
109 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff
110 };
111
112
113 extern time_t IOtime;
114
115
116 /*=====================*
117 * EXPORTED PROCEDURES *
118 *=====================*/
119
120
121 /*===========================================================================*
122 *
123 * Bitio_New
124 *
125 * Create a new bit bucket; filePtr is a pointer to the open file the
126 * bits should ultimately be written to.
127 *
128 * RETURNS: pointer to the resulting bit bucket
129 *
130 * SIDE EFFECTS: none
131 *
132 *===========================================================================*/
133 BitBucket *
134 Bitio_New(filePtr)
135 FILE *filePtr;
136 {
137 BitBucket *bbPtr;
138
139 bbPtr = (BitBucket *) malloc(sizeof(BitBucket));
140 ERRCHK(bbPtr, "malloc");
141
142 bbPtr->firstPtr = bbPtr->lastPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));
143 ERRCHK(bbPtr->firstPtr, "malloc");
144
145 bbPtr->totalbits = 0;
146 bbPtr->cumulativeBits = 0;
147 bbPtr->bitsWritten = 0;
148 bbPtr->filePtr = filePtr;
149
150 bbPtr->firstPtr->nextPtr = NULL;
151 bbPtr->firstPtr->bitsleft = MAXBITS_PER_BUCKET;
152 bbPtr->firstPtr->bitsleftcur = 32;
153 bbPtr->firstPtr->currword = 0;
154 memset((char *)bbPtr->firstPtr->bits, 0, sizeof(uint32) * WORDS_PER_BUCKET);
155
156 return bbPtr;
157 }
158
159
160 /*===========================================================================*
161 *
162 * Bitio_Free
163 *
164 * Frees the memory associated with the given bit bucket
165 *
166 * RETURNS: nothing
167 *
168 * SIDE EFFECTS: none
169 *
170 *===========================================================================*/
171 void
172 Bitio_Free(bbPtr)
173 BitBucket *bbPtr;
174 {
175 struct bitBucket *tmpPtr, *nextPtr;
176
177 for (tmpPtr = bbPtr->firstPtr; tmpPtr != NULL; tmpPtr = nextPtr) {
178 nextPtr = tmpPtr->nextPtr;
179 free(tmpPtr);
180 }
181 free(bbPtr);
182 }
183
184
185 /*===========================================================================*
186 *
187 * Bitio_Write
188 *
189 * Writes 'nbits' bits from 'bits' into the given bit bucket
190 * 'nbits' must be between 0 and 32
191 *
192 * RETURNS: nothing
193 *
194 * SIDE EFFECTS: if the number of bits in the bit bucket surpasses
195 * MAX_BITS, then that many bits are flushed to the
196 * appropriate output file
197 *
198 *===========================================================================*/
199 void
200 Bitio_Write(bbPtr, bits, nbits)
201 BitBucket *bbPtr;
202 uint32 bits;
203 int nbits;
204 {
205 register struct bitBucket *lastPtr, *newPtr;
206 register int delta;
207
208 assert(nbits <= 32 && nbits >= 0);
209
210 /*
211 * Clear top bits if not part of data, necessary due to down and
212 * dirty calls of Bitio_Write with unecessary top bits set.
213 */
214
215 bits = bits & lower_mask[nbits];
216
217 bbPtr->totalbits += nbits;
218 bbPtr->cumulativeBits += nbits;
219 lastPtr = bbPtr->lastPtr;
220
221 delta = nbits - lastPtr->bitsleft;
222 if (delta >= 0) {
223 /*
224 * there's not enough room in the current bucket, so we're
225 * going to have to allocate another bucket
226 */
227 newPtr = lastPtr->nextPtr = (struct bitBucket *) malloc(sizeof(struct bitBucket));
228 ERRCHK(newPtr, "malloc");
229 newPtr->nextPtr = NULL;
230 newPtr->bitsleft = MAXBITS_PER_BUCKET;
231 newPtr->bitsleftcur = 32;
232 newPtr->currword = 0;
233 memset((char *)newPtr->bits, 0, sizeof(uint32) * WORDS_PER_BUCKET);
234 bbPtr->lastPtr = newPtr;
235
236 assert(lastPtr->currword == WORDS_PER_BUCKET - 1);
237 lastPtr->bits[WORDS_PER_BUCKET - 1] |= (bits >> delta);
238 lastPtr->bitsleft = 0;
239 lastPtr->bitsleftcur = 0;
240 /* lastPtr->currword++; */
241
242 if (!delta) {
243 if ( bbPtr->totalbits > MAX_BITS ) {
244 Dump(bbPtr);
245 }
246 }
247
248 assert(delta <= 32);
249 newPtr->bits[0] = (bits & lower_mask[delta]) << (32 - delta);
250 newPtr->bitsleft -= delta;
251 newPtr->bitsleftcur -= delta;
252 } else {
253 /*
254 * the current bucket will be sufficient
255 */
256 delta = nbits - lastPtr->bitsleftcur;
257 lastPtr->bitsleftcur -= nbits;
258 lastPtr->bitsleft -= nbits;
259
260 if (delta >= 0)
261 {
262 /*
263 * these bits will span more than one word
264 */
265 lastPtr->bits[lastPtr->currword] |= (bits >> delta);
266 lastPtr->currword++;
267 lastPtr->bits[lastPtr->currword] = (bits & lower_mask[delta]) << (32 - delta);
268 lastPtr->bitsleftcur = 32 - delta;
269 } else {
270 /*
271 * these bits will fit, whole
272 */
273 lastPtr->bits[lastPtr->currword] |= (bits << (-delta));
274 }
275 }
276
277 if ( bbPtr->totalbits > MAX_BITS ) /* flush bits */
278 Dump(bbPtr);
279 }
280
281
282 /*===========================================================================*
283 *
284 * Bitio_Flush
285 *
286 * Flushes all of the remaining bits in the given bit bucket to the
287 * appropriate output file. It will generate up to the nearest 8-bit
288 * unit of bits, which means that up to 7 extra 0 bits will be appended
289 * to the end of the file.
290 *
291 * RETURNS: nothing
292 *
293 * SIDE EFFECTS: frees the bit bucket
294 *
295 *===========================================================================*/
296 void
297 Bitio_Flush(bbPtr)
298 BitBucket *bbPtr;
299 {
300 struct bitBucket *ptr, *tempPtr;
301 uint32 buffer[WORDS_PER_BUCKET];
302 uint32 lastWord;
303 int i, nitems;
304 int bitsWritten = 0;
305 int bitsLeft;
306 int numWords;
307 uint8 charBuf[4];
308 boolean flushHere = FALSE;
309 time_t tempTimeStart, tempTimeEnd;
310
311 time(&tempTimeStart);
312
313 bitsLeft = bbPtr->totalbits;
314
315 for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {
316 if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
317 continue; /* empty */
318 }
319
320 if ( bitsLeft >= 32 ) {
321 if ( ((ptr->currword + 1) * 32) > bitsLeft ) {
322 numWords = ptr->currword;
323 flushHere = TRUE;
324 } else {
325 numWords = ptr->currword+1;
326 }
327
328 for (i = 0; i < numWords; i++) {
329 buffer[i] = htonl(ptr->bits[i]);
330 }
331
332 nitems = fwrite(buffer, sizeof(uint32), numWords, bbPtr->filePtr);
333 if (nitems != numWords) {
334 fprintf(stderr, "Whoa! Trouble writing %d bytes (got %d items)! Game over, dude!\n",
335 (int)(numWords), nitems);
336 exit(1);
337 }
338
339 bitsWritten += (numWords * 32);
340 bitsLeft -= (numWords * 32);
341 } else {
342 flushHere = TRUE;
343 }
344
345 if ( (bitsLeft < 32) && flushHere ) {
346 lastWord = ptr->bits[ptr->currword];
347
348 /* output the lastPtr word in big-endian order (network) */
349
350 /* now write out lastPtr bits */
351 while ( bitsLeft > 0 ) {
352 charBuf[0] = (lastWord >> 24);
353 charBuf[0] &= lower_mask[8];
354 fwrite(charBuf, 1, sizeof(uint8), bbPtr->filePtr);
355 lastWord = (lastWord << 8);
356 bitsLeft -= 8;
357 bitsWritten += 8;
358 }
359 }
360 }
361 fflush(bbPtr->filePtr);
362 while ( bbPtr->firstPtr != ptr ) {
363 tempPtr = bbPtr->firstPtr;
364 bbPtr->firstPtr = tempPtr->nextPtr;
365 free(tempPtr);
366 }
367
368 free(bbPtr);
369
370 time(&tempTimeEnd);
371 IOtime += (tempTimeEnd-tempTimeStart);
372 }
373
374
375 /*===========================================================================*
376 *
377 * Bitio_WriteToSocket
378 *
379 * Writes all of the remaining bits in the given bit bucket to the
380 * given socket. May pad the end of the socket stream with extra 0
381 * bits as does Bitio_Flush.
382 *
383 * RETURNS: nothing
384 *
385 * SIDE EFFECTS: frees the bit bucket
386 *
387 *===========================================================================*/
388 void
389 Bitio_WriteToSocket(bbPtr, socket)
390 BitBucket *bbPtr;
391 int socket;
392 {
393 struct bitBucket *ptr, *tempPtr;
394 uint32 buffer[WORDS_PER_BUCKET];
395 uint32 lastWord;
396 int i, nitems;
397 int bitsWritten = 0;
398 int bitsLeft;
399 int numWords;
400 uint8 charBuf[4];
401 boolean flushHere = FALSE;
402
403 bitsLeft = bbPtr->totalbits;
404
405 for (ptr = bbPtr->firstPtr; ptr; ptr = ptr->nextPtr) {
406 if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
407 continue; /* empty */
408 }
409
410 if ( bitsLeft >= 32 ) {
411 if ( ((ptr->currword + 1) * 32) > bitsLeft ) {
412 numWords = ptr->currword;
413 flushHere = TRUE;
414 } else {
415 numWords = ptr->currword+1;
416 }
417
418 for (i = 0; i < numWords; i++) {
419 buffer[i] = htonl(ptr->bits[i]);
420 }
421
422 nitems = write(socket, buffer, numWords * sizeof(uint32));
423 if (nitems != numWords*sizeof(uint32)) {
424 fprintf(stderr, "Whoa! Trouble writing %d bytes (got %d bytes)! Game over, dude!\n",
425 (int)(numWords*sizeof(uint32)), nitems);
426 exit(1);
427 }
428
429 bitsWritten += (numWords * 32);
430 bitsLeft -= (numWords * 32);
431 } else {
432 flushHere = TRUE;
433 }
434
435 if ( (bitsLeft < 32) && flushHere ) {
436 lastWord = ptr->bits[ptr->currword];
437
438 /* output the lastPtr word in big-endian order (network) */
439
440 /* now write out lastPtr bits */
441 while ( bitsLeft > 0 ) {
442 charBuf[0] = (lastWord >> 24);
443 charBuf[0] &= lower_mask[8];
444 if ( write(socket, charBuf, 1) != 1 ) {
445 fprintf(stderr, "ERROR: write of lastPtr bits\n");
446 exit(1);
447 }
448 lastWord = (lastWord << 8);
449 bitsLeft -= 8;
450 bitsWritten += 8;
451 }
452 }
453 }
454
455 while ( bbPtr->firstPtr != ptr ) {
456 tempPtr = bbPtr->firstPtr;
457 bbPtr->firstPtr = tempPtr->nextPtr;
458 free(tempPtr);
459 }
460
461 free(bbPtr);
462 }
463
464
465 /*===========================================================================*
466 *
467 * Bitio_BytePad
468 *
469 * Pads the end of the bit bucket to the nearest byte with 0 bits
470 *
471 * RETURNS: nothing
472 *
473 *===========================================================================*/
474 void
475 Bitio_BytePad(bbPtr)
476 BitBucket *bbPtr;
477 {
478 struct bitBucket *lastPtrPtr = bbPtr->lastPtr;
479
480 if (lastPtrPtr->bitsleftcur % 8) {
481 Bitio_Write(bbPtr, 0, lastPtrPtr->bitsleftcur % 8);
482 }
483 }
484
485
486 /*=====================*
487 * INTERNAL PROCEDURES *
488 *=====================*/
489
490
491 /*===========================================================================*
492 *
493 * Dump
494 *
495 * Writes out the first MAX_BITS bits of the bit bucket to the
496 * appropriate output file
497 *
498 * RETURNS: nothing
499 *
500 * SIDE EFFECTS: none
501 *
502 *===========================================================================*/
503 static void
504 Dump(bbPtr)
505 BitBucket *bbPtr;
506 {
507 struct bitBucket *ptr, *tempPtr;
508 uint32 buffer[WORDS_PER_BUCKET];
509 int i, nitems;
510 int bitsWritten = 0;
511 time_t tempTimeStart, tempTimeEnd;
512
513 time(&tempTimeStart);
514
515 for (ptr = bbPtr->firstPtr; ptr && (bitsWritten < MAX_BITS);
516 ptr = ptr->nextPtr) {
517 if (ptr->bitsleftcur == 32 && ptr->currword == 0) {
518 continue; /* empty */
519 }
520
521 for (i = 0; i <= ptr->currword; i++) {
522 buffer[i] = htonl(ptr->bits[i]);
523 }
524
525 nitems = fwrite((uint8 *)buffer, sizeof(uint32), (ptr->currword + 1), bbPtr->filePtr);
526 if (nitems != (ptr->currword+1)) {
527 fprintf(stderr, "Whoa! Trouble writing %d bytes (got %d items)! Game over, dude!\n",
528 (int)((ptr->currword+1)), nitems);
529 assert(0);
530 exit(1);
531 }
532
533 bitsWritten += ((ptr->currword + 1) * 32);
534 }
535
536 while ( bbPtr->firstPtr != ptr ) {
537 tempPtr = bbPtr->firstPtr;
538 bbPtr->firstPtr = tempPtr->nextPtr;
539 free(tempPtr);
540 }
541
542 bbPtr->totalbits -= bitsWritten;
543 bbPtr->bitsWritten += bitsWritten;
544
545 time(&tempTimeEnd);
546 IOtime += (tempTimeEnd-tempTimeStart);
547 }