1 /*************************************************************
2 Copyright (C) 1990, 1991, 1993 Andy C. Hung, all rights reserved.
3 PUBLIC DOMAIN LICENSE: Stanford University Portable Video Research
4 Group. If you use this software, you agree to the following: This
5 program package is purely experimental, and is licensed "as is".
6 Permission is granted to use, modify, and distribute this program
7 without charge for any purpose, provided this license/ disclaimer
8 notice appears in the copies. No warranty or maintenance is given,
9 either expressed or implied. In no event shall the author(s) be
10 liable to you or a third party for any special, incidental,
11 consequential, or other damages, arising out of the use or inability
12 to use the program for any purpose (or the loss of data), even if we
13 have been advised of such possibilities. Any public reference or
14 advertisement of this source code should refer to it as the Portable
15 Video Research Group (PVRG) code, and not by any author(s) (or
16 Stanford University) name.
17 *************************************************************/
18
19 /*
20 ************************************************************
21 stream.c
22
23 This file is used for management of bit-aligned files.
24
25 ************************************************************
26 */
27
28 /*LABEL stream.c */
29
30 /* Include files */
31
32 #include "globals.h"
33 #include "marker.h"
34 #include "stream.h"
35 #include <stdlib.h> /* exit */
36
37 /*PUBLIC*/
38
39 extern void initstream();
40 extern void pushstream();
41 extern void popstream();
42 extern void bpushc();
43 extern int bgetc();
44 extern void bputc();
45 extern void mropen();
46 extern void mrclose();
47 extern void mwopen();
48 extern void swbytealign();
49 extern void mwclose();
50 extern long mwtell();
51 extern long mrtell();
52 extern void mwseek();
53 extern void mrseek();
54 extern int megetb();
55 extern void meputv();
56 extern int megetv();
57 extern int DoMarker();
58 extern int ScreenMarker();
59 extern void Resync();
60 extern void WriteResync();
61 extern int ReadResync();
62 extern int ScreenAllMarker();
63 extern int DoAllMarker();
64
65 static int pgetc();
66
67 /*PRIVATE*/
68
69 /* External values */
70
71 extern int ErrorValue;
72 extern IMAGE *CImage;
73 extern int Robust; /* Whether to ignore scan markers and such */
74
75 /* Masks */
76 int bit_set_mask[] = { /* This is 2^i at ith position */
77 0x00000001,0x00000002,0x00000004,0x00000008,
78 0x00000010,0x00000020,0x00000040,0x00000080,
79 0x00000100,0x00000200,0x00000400,0x00000800,
80 0x00001000,0x00002000,0x00004000,0x00008000,
81 0x00010000,0x00020000,0x00040000,0x00080000,
82 0x00100000,0x00200000,0x00400000,0x00800000,
83 0x01000000,0x02000000,0x04000000,0x08000000,
84 0x10000000,0x20000000,0x40000000,0x80000000};
85 int lmask[] = { /* This is 2^{i+1}-1 */
86 0x00000001,0x00000003,0x00000007,0x0000000f,
87 0x0000001f,0x0000003f,0x0000007f,0x000000ff,
88 0x000001ff,0x000003ff,0x000007ff,0x00000fff,
89 0x00001fff,0x00003fff,0x00007fff,0x0000ffff,
90 0x0001ffff,0x0003ffff,0x0007ffff,0x000fffff,
91 0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
92 0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,
93 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff};
94
95 #ifdef __OLD
96 int umask[] = { /* This is -1 XOR 2^{i+1}-1 */
97 0xfffffffe,0xfffffffc,0xfffffff8,0xfffffff0,
98 0xffffffe0,0xffffffc0,0xffffff80,0xffffff00,
99 0xfffffe00,0xfffffc00,0xfffff800,0xfffff000,
100 0xffffe000,0xffffc000,0xffff8000,0xffff0000,
101 0xfffe0000,0xfffc0000,0xfff80000,0xfff00000,
102 0xffe00000,0xffc00000,0xff800000,0xff000000,
103 0xfe000000,0xfc000000,0xf8000000,0xf0000000,
104 0xe0000000,0xc0000000,0x80000000,0x00000000};
105 #endif
106
107 /* Internally kept variables for global flag communication */
108
109 int CleartoResync=0; /* Return black blocks until last Resync reached*/
110 int ResyncEnable=0; /* This enables the resync feature */
111 int ResyncCount=0; /* This is the resync marker count */
112 int LastKnownResync=0; /* This is the index of the next Resync */
113 int EndofFile=0; /* End of file means read stream exhausted */
114 int EndofImage=0; /* End of image means EOI image marker found */
115
116 /* Static variables that keep internal state. */
117
118 static FILE *swout;
119 static FILE *srin;
120 static unsigned int current_write_byte;
121 static unsigned int current_read_byte;
122 static unsigned int marker_read_byte;
123 static int read_position;
124 static int write_position;
125 static int InResync=0;
126
127 /* Stack of variables to handle multiple streams. */
128
129 static int Stack_Stream_Current= -1;
130 static int Stack_Stream_Active[NUMBER_OF_STREAMS];
131 static int Stack_Stream_CleartoResync[NUMBER_OF_STREAMS];
132 static int Stack_Stream_ResyncEnable[NUMBER_OF_STREAMS];
133 static int Stack_Stream_ResyncCount[NUMBER_OF_STREAMS];
134 static int Stack_Stream_LastKnownResync[NUMBER_OF_STREAMS];
135 static int Stack_Stream_EndofFile[NUMBER_OF_STREAMS];
136 static int Stack_Stream_EndofImage[NUMBER_OF_STREAMS];
137 static FILE * Stack_Stream_swout[NUMBER_OF_STREAMS];
138 static FILE * Stack_Stream_srin[NUMBER_OF_STREAMS];
139 static unsigned int Stack_Stream_current_write_byte[NUMBER_OF_STREAMS];
140 static unsigned int Stack_Stream_current_read_byte[NUMBER_OF_STREAMS];
141 static unsigned int Stack_Stream_marker_read_byte[NUMBER_OF_STREAMS];
142 static int Stack_Stream_read_position[NUMBER_OF_STREAMS];
143 static int Stack_Stream_write_position[NUMBER_OF_STREAMS];
144
145 /*START*/
146
147 /* STACK STREAM LIBRARY */
148
149 /*BFUNC
150
151 initstream() initializes all of the stream variables-- especially the
152 stack. Not necessary to call unless you wish to use more than one
153 stream variable.
154
155 EFUNC*/
156
initstream()157 void initstream()
158 {
159 BEGIN("initstream")
160 int i;
161
162 Stack_Stream_Current= -1;
163 for(i=0;i<NUMBER_OF_STREAMS;i++)
164 {
165 Stack_Stream_Active[i]=0;
166 Stack_Stream_swout[i]=NULL;
167 Stack_Stream_srin[i]=NULL;
168 }
169 }
170
171 /*BFUNC
172
173 pushstream() pushes the currently active stream into its predefined
174 location.
175
176 EFUNC*/
177
pushstream()178 void pushstream()
179 {
180 BEGIN("pushstream")
181
182 if (Stack_Stream_Current < 0) return;
183 Stack_Stream_CleartoResync[Stack_Stream_Current]=CleartoResync;
184 Stack_Stream_ResyncEnable[Stack_Stream_Current]=ResyncEnable;
185 Stack_Stream_ResyncCount[Stack_Stream_Current]=ResyncCount;
186 Stack_Stream_LastKnownResync[Stack_Stream_Current]=LastKnownResync;
187 Stack_Stream_EndofFile[Stack_Stream_Current]=EndofFile;
188 Stack_Stream_EndofImage[Stack_Stream_Current]=EndofImage;
189 Stack_Stream_swout[Stack_Stream_Current]=swout;
190 Stack_Stream_srin[Stack_Stream_Current]=srin;
191 Stack_Stream_current_write_byte[Stack_Stream_Current]=current_write_byte;
192 Stack_Stream_current_read_byte[Stack_Stream_Current]=current_read_byte;
193 Stack_Stream_marker_read_byte[Stack_Stream_Current]=marker_read_byte;
194 Stack_Stream_read_position[Stack_Stream_Current]=read_position;
195 Stack_Stream_write_position[Stack_Stream_Current]=write_position;
196 }
197
198 /*BFUNC
199
200 popstream() gets the specified stream from the location. If there
201 is already a current active stream, it removes it.
202
203 EFUNC*/
204
popstream(index)205 void popstream(index)
206 int index;
207 {
208 BEGIN("popstream")
209
210 if ((index < 0)||(!Stack_Stream_Active[index]))
211 {
212 WHEREAMI();
213 printf("Cannot pop non-existent stream.\n");
214 exit(ERROR_BOUNDS);
215 }
216 if (Stack_Stream_Current >=0) pushstream();
217 CleartoResync=Stack_Stream_CleartoResync[index];
218 ResyncEnable=Stack_Stream_ResyncEnable[index];
219 ResyncCount=Stack_Stream_ResyncCount[index];
220 LastKnownResync=Stack_Stream_LastKnownResync[index];
221 EndofFile=Stack_Stream_EndofFile[index];
222 EndofImage=Stack_Stream_EndofImage[index];
223 swout=Stack_Stream_swout[index];
224 srin=Stack_Stream_srin[index];
225 current_write_byte=Stack_Stream_current_write_byte[index];
226 current_read_byte=Stack_Stream_current_read_byte[index];
227 marker_read_byte=Stack_Stream_marker_read_byte[index];
228 read_position=Stack_Stream_read_position[index];
229 write_position=Stack_Stream_write_position[index];
230 }
231
232 /* THAT'S ALL FOR THE STACK STREAM LIBRARY! */
233
234 /* BUFFER LIBRARY */
235
236 /*BFUNC
237
238 brtell() is used to find the location in the read stream.
239
240 EFUNC*/
241
brtell()242 int brtell()
243 {BEGIN("brtell") return(ftell(srin));}
244
245 /*BFUNC
246
247 brseek() is used to find the location in the read stream.
248
249 EFUNC*/
250
brseek(offset,ptr)251 int brseek(offset,ptr)
252 int offset;
253 int ptr;
254 {BEGIN("brseek") return(fseek(srin,offset,ptr));}
255
256 /*BFUNC
257
258 bpushc() is used to unget a character value from the current stream.
259
260 EFUNC*/
261
bpushc(value)262 void bpushc(value)
263 int value;
264 {BEGIN("bpushc") ungetc(value,srin);}
265
266 /*BFUNC
267
268 bgetc() gets a character from the stream. It is byte aligned and
269 bypasses bit buffering.
270
271 EFUNC*/
272
bgetc()273 int bgetc()
274 {BEGIN("bgetc") return(getc(srin));}
275
276 /*BFUNC
277
278 bgetw() gets a msb word from the stream.
279
280 EFUNC*/
281
bgetw()282 int bgetw()
283 {BEGIN("bgetw") int fu; fu=getc(srin); return ((fu << 8)| getc(srin));}
284
285 /*BFUNC
286
287 bputc() puts a character into the stream. It is byte aligned and
288 bypasses the bit buffering.
289
290 EFUNC*/
291
bputc(c)292 void bputc(c)
293 int c;
294 {BEGIN("bputc") putc(c,swout);}
295
296 /* PROTECTED MARKER GETS AND FETCHES */
297
298 /*BFUNC
299
300 pgetc() gets a character onto the stream but it checks to see
301 if there are any marker conflicts.
302
303 EFUNC*/
304
pgetc()305 static int pgetc()
306 {
307 BEGIN("pgetc")
308 int temp;
309
310 if (CleartoResync) /* If cleartoresync do not read from stream */
311 {
312 return(0);
313 }
314 if ((temp = bgetc())==MARKER_MARKER) /* If MARKER then */
315 {
316 if ((temp = bgetc())) /* if next is not 0xff, then marker */
317 {
318 WHEREAMI();
319 printf("Unanticipated marker detected.\n");
320 if (!ResyncEnable) DoAllMarker(); /* If no resync enabled */
321 } /* could be marker */
322 else
323 {
324 return(MARKER_MARKER); /* else truly 0xff */
325 }
326 }
327 return(temp);
328 }
329
330 /*BMACRO
331
332 pputc(stream,)
333 ) puts a value onto the stream; puts a value onto the stream, appending an extra '0' if it
334 matches the marker code.
335
336 EMACRO*/
337
338 #define pputc(val) {bputc(val); if (val==MARKER_MARKER) bputc(0);}
339
340 /* MAIN ROUTINES */
341
342 /*BFUNC
343
344 mropen() opens a given filename as the input read stream.
345
346 EFUNC*/
347
mropen(filename,index)348 void mropen(filename,index)
349 char *filename;
350 int index;
351 {
352 BEGIN("mropen")
353
354 if (Stack_Stream_Active[index])
355 {
356 WHEREAMI();
357 printf("%s cannot be opened because %d stream slot filled.\n",
358 filename,index);
359 exit(ERROR_BOUNDS);
360 }
361 if (Stack_Stream_Current!=index) pushstream();
362 current_read_byte=0;
363 read_position = -1;
364 if ((srin = fopen(filename,"rb"))==NULL)
365 {
366 WHEREAMI();
367 printf("Cannot read input file %s.\n",
368 filename);
369 exit(ERROR_INIT_FILE);
370 }
371 CleartoResync=0;
372 ResyncEnable=0;
373 ResyncCount=0;
374 LastKnownResync=0;
375 EndofFile=0;
376 EndofImage=1; /* We start after "virtual" end of previous image */
377 Stack_Stream_Current= index;
378 Stack_Stream_Active[index]=1;
379 }
380
381 /*BFUNC
382
383 mrclose() closes the input read stream.
384
385 EFUNC*/
386
mrclose()387 void mrclose()
388 {
389 BEGIN("mrclose")
390 fclose(srin);
391 srin=NULL;
392 if (swout==NULL)
393 {
394 Stack_Stream_Active[Stack_Stream_Current]=0;
395 Stack_Stream_Current= -1;
396 }
397 }
398
399 /*BFUNC
400
401 mwopen() opens the stream for writing. Note that reading and
402 writing can occur simultaneously because the read and write
403 routines are independently buffered.
404
405 EFUNC*/
406
mwopen(filename,index)407 void mwopen(filename,index)
408 char *filename;
409 int index;
410 {
411 BEGIN("mwopen")
412
413 if (Stack_Stream_Active[index])
414 {
415 WHEREAMI();
416 printf("%s cannot be opened because %d stream slot filled.\n",
417 filename,index);
418 exit(ERROR_BOUNDS);
419 }
420 if ((Stack_Stream_Current!=index)) pushstream();
421 current_write_byte=0;
422 write_position=7;
423 if ((swout = fopen(filename,"wb+"))==NULL)
424 {
425 WHEREAMI();
426 printf("Cannot open output file %s.\n",filename);
427 exit(ERROR_INIT_FILE);
428 }
429 Stack_Stream_Current= index;
430 Stack_Stream_Active[index]=1;
431 }
432
433 /*BFUNC
434
435 swbytealign() flushes the current bit-buffered byte out to the stream.
436 This is used before marker codes.
437
438 EFUNC*/
439
swbytealign()440 void swbytealign()
441 {
442 BEGIN("swbytealign")
443
444 if (write_position !=7)
445 {
446 current_write_byte |= lmask[write_position];
447 pputc(current_write_byte);
448 write_position=7;
449 current_write_byte=0;
450 }
451 }
452
453 /*BFUNC
454
455 mwclose() closes the stream that has been opened for writing.
456
457 EFUNC*/
458
mwclose()459 void mwclose()
460 {
461 BEGIN("mwclose")
462
463 swbytealign();
464 fclose(swout);
465 swout=NULL;
466 if (srin==NULL)
467 {
468 Stack_Stream_Active[Stack_Stream_Current]=0;
469 Stack_Stream_Current= -1;
470 }
471 }
472
473 /*BFUNC
474
475 mwtell() returns the bit position on the write stream.
476
477 EFUNC*/
478
mwtell()479 long mwtell()
480 {
481 BEGIN("mwtell")
482
483 return((ftell(swout)<<3) + (7 - write_position));
484 }
485
486 /*BFUNC
487
488 mrtell() returns the bit position on the read stream.
489
490 EFUNC*/
491
mrtell()492 long mrtell()
493 {
494 BEGIN("mrtell")
495
496 return((ftell(srin)<<3) - (read_position+1));
497 }
498
499 /*BFUNC
500
501 mwseek returns the bit position on the write stream.
502
503 EFUNC*/
504
mwseek(distance)505 void mwseek(distance)
506 long distance;
507 {
508 BEGIN("mwseek")
509 int length;
510
511 if (write_position!=7) /* Must flush out current byte */
512 {
513 putc(current_write_byte,swout);
514 }
515 fseek(swout,0,2L); /* Find end */
516 length = ftell(swout);
517 fseek(swout,((distance+7)>>3),0L);
518 if ((length<<3) <= distance) /* Make sure we read clean stuff */
519 {
520 current_write_byte = 0;
521 write_position = 7 - (distance & 0x7);
522 }
523 else
524 {
525 current_write_byte = getc(swout); /* if within bounds, then read byte */
526 write_position = 7 - (distance & 0x7);
527 fseek(swout,((distance+7)>>3),0L); /* Reset seek pointer for write */
528 }
529 }
530
531
532 /*BFUNC
533
534 mrseek() jumps to a bit position on the read stream.
535
536 EFUNC*/
537
mrseek(distance)538 void mrseek(distance)
539 long distance;
540 {
541 BEGIN("mrseek")
542
543 fseek(srin,(distance>>3),0L); /* Go to location */
544 current_read_byte = bgetc(); /* read byte in */
545 read_position = 7 - (distance % 8);
546 }
547
548
549 /*BFUNC
550
551 megetb() gets a bit from the read stream.
552
553 EFUNC*/
554
megetb()555 int megetb()
556 {
557 BEGIN("megetb")
558
559 if (read_position < 0)
560 {
561 current_read_byte = pgetc();
562 read_position=7;
563 }
564 if (current_read_byte&bit_set_mask[read_position--])
565 {
566 return(1);
567 }
568 return(0);
569 }
570
571 /*BFUNC
572
573 meputv() puts n bits from b onto the writer stream.
574
575 EFUNC*/
576
meputv(n,b)577 void meputv(n,b)
578 int n;
579 int b;
580 {
581 BEGIN("meputv")
582 int p;
583
584 n--;
585 b &= lmask[n];
586 p = n - write_position;
587 if (!p) /* Can do parallel save immediately */
588 {
589 current_write_byte |= b;
590 pputc(current_write_byte);
591 current_write_byte = 0;
592 write_position = 7;
593 return;
594 }
595 else if (p < 0) /* if can fit, we have to shift byte */
596 {
597 p = -p;
598 current_write_byte |= (b << p);
599 write_position = p-1;
600 return;
601 }
602 current_write_byte |= (b >> p); /* cannot fit. we must do putc's */
603 pputc(current_write_byte); /* Save off remainder */
604 while(p > 7) /* Save off bytes while remaining > 7 */
605 {
606 p -= 8;
607 current_write_byte = (b >> p) & lmask[7];
608 pputc(current_write_byte);
609 }
610 if (!p) /* If zero then reset position */
611 {
612 write_position = 7;
613 current_write_byte = 0;
614 }
615 else /* Otherwise reset write byte buffer */
616 {
617 write_position = 8-p;
618 current_write_byte = (b << write_position) & lmask[7];
619 write_position--;
620 }
621 }
622
623 /*BFUNC
624
625 megetv() gets n bits from the read stream and returns it.
626
627 EFUNC*/
628
megetv(n)629 int megetv(n)
630 int n;
631 {
632 BEGIN("megetv")
633 int p,rv;
634
635 n--;
636 p = n-read_position;
637 while(p > 0)
638 {
639 if (read_position>23) /* If byte buffer contains almost entire word */
640 {
641 rv = (current_read_byte << p); /* Manipulate buffer */
642 current_read_byte = pgetc(); /* Change read bytes */
643 rv |= (current_read_byte >> (8-p));
644 read_position = 7-p;
645 return(rv & lmask[n]); /* Can return pending residual val */
646 }
647 current_read_byte = (current_read_byte << 8) | pgetc();
648 read_position += 8; /* else shift in new information */
649 p -= 8;
650 }
651 if (!p) /* If position is zero */
652 {
653 read_position = -1; /* Can return current byte */
654 return(current_read_byte & lmask[n]);
655 }
656 p = -p; /* Else reverse position and shift */
657 read_position = p-1;
658 return((current_read_byte >> p) & lmask[n]);
659 }
660
661
662 /*BFUNC
663
664 DoMarker() performs marker analysis. We assume that the Current Marker
665 head has been read (0xFF) plus top information is at
666 marker\_read\_byte.
667
668 EFUNC*/
669
DoMarker()670 int DoMarker()
671 {
672 BEGIN("DoMarker")
673 int i,hin,lon,marker,length;
674
675 current_read_byte = 0;
676 read_position= -1; /* Make sure we are byte-flush. */
677 while(marker_read_byte==MARKER_FIL) /* Get rid of FIL markers */
678 {
679 #ifdef VERSION_1_0
680 if ((marker_read_byte = bgetc())!=MARKER_MARKER)
681 {
682 WHEREAMI();
683 printf("Unknown FIL marker. Bypassing.\n");
684 ErrorValue = ERROR_MARKER;
685 return(0);
686 }
687 #endif
688 marker_read_byte = bgetc();
689 }
690 lon = marker_read_byte & 0x0f; /* Segregate between hi and lo */
691 hin = (marker_read_byte>>4) & 0x0f; /* nybbles for the marker read byte */
692 marker = marker_read_byte;
693
694 if (InResync)
695 {
696 if ((marker <0xd0)||(marker>0xd7))
697 {
698 WHEREAMI();
699 printf("Illegal resync marker found.\n");
700 return(0);
701 }
702 }
703 switch(hin) /* Pretty much self explanatory */
704 {
705 case 0x0c: /* Frame Style Marker */
706 switch(lon)
707 {
708 case 0x04:
709 ReadDht();
710 break;
711 case 0x00:
712 case 0x01:
713 case 0x03:
714 ReadSof(lon);
715 break;
716 case 0x08:
717 case 0x09:
718 case 0x0a:
719 case 0x0b:
720 case 0x0c:
721 case 0x0d:
722 case 0x0e:
723 case 0x0f:
724 WHEREAMI();
725 printf("Arithmetic coding not supported.\n");
726 length = bgetw();
727 for(i=2;i<length;i++) /* Length adds 2 bytes itself */
728 bgetc();
729 break;
730 case 0x02:
731 case 0x05:
732 case 0x06:
733 case 0x07:
734 default:
735 WHEREAMI();
736 printf("Frame type %x not supported.\n",lon);
737 length = bgetw();
738 for(i=2;i<length;i++) /* Length adds 2 bytes itself */
739 bgetc();
740 break;
741 }
742 break;
743 case 0x0d: /* Resync Marker */
744 if (lon > 7)
745 {
746 switch(lon)
747 {
748 case 0x08: /* Start of Image */
749 EndofImage=0; /* If End of Image occurs */
750 CImage->ImageSequence++; /* reset, and increment sequence */
751 break;
752 case 0x09: /* End of Image */
753 EndofImage=1;
754 break;
755 case 0x0a:
756 ResyncCount=0; /* SOS clears the resync count */
757 ReadSos();
758 break;
759 case 0x0b:
760 ReadDqt();
761 break;
762 case 0x0c:
763 ReadDnl();
764 break;
765 case 0x0d:
766 ReadDri();
767 break;
768 default:
769 WHEREAMI();
770 printf("Hierarchical markers found.\n");
771 length = bgetw();
772 for(i=2;i<length;i++) /* Length adds 2 bytes itself */
773 {
774 bgetc();
775 }
776 break;
777 }
778 }
779 break;
780 case 0x0e: /* Application Specific */
781 length = bgetw();
782 for(i=2;i<length;i++) /* Length adds 2 bytes itself */
783 bgetc();
784 break;
785 case 0x0f: /* JPEG Specific */
786 length = bgetw();
787 for(i=2;i<length;i++) /* Length adds 2 bytes itself */
788 bgetc();
789 break;
790 default:
791 WHEREAMI();
792 printf("Bad marker byte %d.\n",marker);
793 Resync();
794 ErrorValue = ERROR_MARKER;
795 return(-1);
796 break;
797 }
798 return(marker);
799 }
800
801 /*BFUNC
802
803 ScreenMarker() looks to see what marker is present on the stream. It
804 returns with the marker value read.
805
806 EFUNC*/
807
ScreenMarker()808 int ScreenMarker()
809 {
810 BEGIN("ScreenMarker")
811
812 if (read_position!=7) /* Already read byte */
813 {
814 current_read_byte = 0;
815 read_position= -1; /* Consume byte to be flush */
816 if ((marker_read_byte=bgetc())==(unsigned int)EOF)
817 {
818 EndofFile=2;
819 return(EOF);
820 }
821 }
822 else /* If flush, then marker byte is current read byte */
823 {
824 marker_read_byte = current_read_byte;
825 }
826 if (marker_read_byte!=MARKER_MARKER) /* Not a marker, return -1. */
827 {
828 current_read_byte = marker_read_byte;
829 read_position=7;
830 return(-1);
831 }
832 while((marker_read_byte = bgetc())==MARKER_FIL)
833 { /* Get rid of FIL markers */
834 if ((marker_read_byte = bgetc())!=MARKER_MARKER)
835 {
836 WHEREAMI();
837 printf("Unattached FIL marker.\n");
838 ErrorValue = ERROR_MARKER;
839 return(-1);
840 }
841 if (marker_read_byte == (unsigned int)EOF) /* Found end of file */
842 {
843 EndofFile=2;
844 return(EOF);
845 }
846 marker_read_byte = bgetc(); /* Otherwise read another byte */
847 } /* Call processor for markers */
848 if (marker_read_byte) return(DoMarker());
849 else /* Is a FF00 so don't process */
850 {
851 current_read_byte=MARKER_MARKER; /* 255 actually read */
852 read_position=7;
853 return(-1);
854 }
855 }
856
857 /*BFUNC
858
859 Resync() does a resync action on the stream. This involves searching
860 for the next resync byte.
861
862 EFUNC*/
863
Resync()864 void Resync()
865 {
866 BEGIN("Resync")
867
868 if (!ResyncEnable)
869 {
870 WHEREAMI();
871 printf("Resync without resync enabled\n");
872 printf("Fatal error.\n");
873 TerminateFile();
874 exit(ERROR_UNRECOVERABLE);
875 }
876 WHEREAMI();
877 printf("Attempting resynchronization.\n");
878 do
879 {
880 while((marker_read_byte = bgetc())!=MARKER_MARKER)
881 {
882 if (marker_read_byte==(unsigned int)EOF)
883 {
884 WHEREAMI();
885 printf("Attempt to resync at end of file.\n");
886 printf("Sorry.\n");
887 TerminateFile();
888 exit(ERROR_PREMATURE_EOF);
889 }
890 }
891 }
892 while(((marker_read_byte = bgetc()) & MARKER_RSC_MASK)!=MARKER_RSC);
893 LastKnownResync = marker_read_byte & 0x07; /* Set up currently read */
894 WHEREAMI(); /* resync byte as future ref */
895 printf("Resync successful!\n");
896 /*
897 In general, we assume that we must add black space
898 until resynchronization. This is consistent under both
899 byte loss, byte gain, and byte corruption.
900 We assume corruption does not create new markers with
901 an RSC value--if so, we are probably dead, anyways.
902 */
903 CleartoResync=1;
904 ResyncCount = (LastKnownResync+1)&0x07;
905 current_read_byte = 0;
906 read_position = -1;
907 ResetCodec(); /* Reset the codec incase in a non-local jump. */
908
909 printf("ResyncCount: %d LastKnownResync: %d\n",
910 ResyncCount,LastKnownResync);
911 }
912
913 /*BFUNC
914
915 WriteResync() writes a resync marker out to the write stream.
916
917 EFUNC*/
918
WriteResync()919 void WriteResync()
920 {
921 BEGIN("WriteResync")
922
923 swbytealign(); /* This procedure writes a byte-aligned */
924 bputc(MARKER_MARKER); /* resync marker. */
925 bputc((MARKER_RSC|(ResyncCount & 0x07)));
926 ResyncCount = (ResyncCount + 1) & 0x07;
927 }
928
929 /*BFUNC
930
931 ReadResync() looks for a resync marker on the stream. It returns a 0
932 if successful and a -1 if a search pass was required.
933
934 EFUNC*/
935
ReadResync()936 int ReadResync()
937 {
938 BEGIN("ReadResync")
939 int ValueRead;
940
941 if (Robust) InResync=1;
942 while((ValueRead = ScreenMarker()) >= 0)
943 {
944 if ((ValueRead & MARKER_RSC_MASK)!=MARKER_RSC) /* Strange marker found */
945 {
946 if (ValueRead != MARKER_DNL) /* DNL only other possibility */
947 { /* actually excluded, never reached */
948 WHEREAMI(); /* 11/19/91 ACH */
949 printf("Non-Resync marker found for resync.\n");
950 printf("Trying again.\n");
951 }
952 }
953 else
954 {
955 ValueRead = ValueRead & 0x07; /* If so, then check resync count */
956 if (ValueRead != ResyncCount)
957 {
958 WHEREAMI();
959 printf("Bad resync counter. No search done.\n");
960 }
961 ResyncCount = (ResyncCount+1)&0x07;
962 /* Flush spurious markers. */
963 while((ValueRead = ScreenMarker()) >= 0);
964 InResync=0;
965 return(0);
966 }
967 }
968 WHEREAMI();
969 printf("Anticipated resync not found.\n");
970 Resync();
971 InResync=0;
972 return(-1);
973 }
974
975 /*BFUNC
976
977 ScreenAllMarker() looks for all the markers on the stream. It returns
978 a 0 if a marker has been found, -1 if no markers exist.
979
980 EFUNC*/
981
ScreenAllMarker()982 int ScreenAllMarker()
983 {
984 BEGIN("ScreenAllMarker")
985
986 if (ScreenMarker()<0)
987 {
988 return(-1);
989 }
990 while(ScreenMarker()>=0); /* Flush out all markers */
991 return(0);
992 }
993
994 /*BFUNC
995
996 DoAllMarker() is the same as ScreenAllMarker except we assume that the
997 prefix markerbyte (0xff) has been read and the second byte of the
998 prefix is in the marker\_byte variable. It returns a -1 if there is an
999 error in reading the marker.
1000
1001 EFUNC*/
1002
DoAllMarker()1003 int DoAllMarker()
1004 {
1005 BEGIN("DoAllMarker")
1006
1007 if (DoMarker()<0)
1008 {
1009 return(-1);
1010 }
1011 while(ScreenMarker()>=0); /* Flush out all markers */
1012 return(0);
1013 }
1014
1015 /*END*/
1016