1 /*===========================================================================*
2  * frame.c								     *
3  *									     *
4  *	basic frame procedures						     *
5  *									     *
6  * EXPORTED PROCEDURES:							     *
7  *	Frame_Init							     *
8  *	Frame_Exit							     *
9  *	Frame_New							     *
10  *	Frame_Free							     *
11  *	Frame_AllocPPM							     *
12  *	Frame_AllocBlocks						     *
13  *	Frame_AllocYCC							     *
14  *	Frame_AllocDecoded						     *
15  *	Frame_AllocHalf						             *
16  *	Frame_Resize						             *
17  *									     *
18  *===========================================================================*/
19 
20 /*
21  * Copyright (c) 1995 The Regents of the University of California.
22  * All rights reserved.
23  *
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation for any purpose, without fee, and without written agreement is
26  * hereby granted, provided that the above copyright notice and the following
27  * two paragraphs appear in all copies of this software.
28  *
29  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
30  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
31  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
32  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  *
34  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
36  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
37  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
38  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
39  */
40 
41 
42 /*==============*
43  * HEADER FILES *
44  *==============*/
45 
46 #include "all.h"
47 #include "mtypes.h"
48 #include "frames.h"
49 #include "frame.h"
50 #include "fsize.h"
51 #include "dct.h"
52 
53 /*===========*
54  * CONSTANTS *
55  *===========*/
56 
57 /* The maximum number of B-Frames allowed between reference frames. */
58 #define  B_FRAME_RUN  16
59 
60 /*==================*
61  * GLOBAL VARIABLES *
62  *==================*/
63 
64 MpegFrame      *frameMemory[B_FRAME_RUN+2];
65 extern boolean stdinUsed;
66 extern char    *framePattern;
67 
68 
69 /*===============================*
70  * INTERNAL PROCEDURE prototypes *
71  *===============================*/
72 
73 static void FreeFrame _ANSI_ARGS_((MpegFrame * mf));
74 static MpegFrame *GetUnusedFrame _ANSI_ARGS_((void));
75 static void GetNumOfFrames _ANSI_ARGS_((int *numOfFrames));
76 static void ResetFrame _ANSI_ARGS_((int fnumber, int type, MpegFrame *frame));
77 static void Resize_Width _ANSI_ARGS_((MpegFrame *omfrw,MpegFrame *mfrw, int in_x,
78        int in_y, int out_x));
79 static void Resize_Height _ANSI_ARGS_((MpegFrame *omfrh,MpegFrame *mfrh,
80        int in_x,
81        int in_y,  int out_y));
82 static void Resize_Array_Width _ANSI_ARGS_((uint8 **inarray,int in_x,
83        int in_y,uint8 **outarray, int out_x));
84 static void Resize_Array_Height _ANSI_ARGS_((uint8 **inarray,int in_x,
85        int in_y,uint8 **outarray, int out_y));
86 
87 
88 /*=====================*
89  * EXPORTED PROCEDURES *
90  *=====================*/
91 
92 /*===============================================================
93  *
94  * Frame_Resize                  by James Boucher
95  *                Boston University Multimedia Communications Lab
96  *
97  *     This function takes the mf input frame, read in READFrame(),
98  * and resizes all the input component arrays to the output
99  * dimensions specified in the parameter file as OUT_SIZE.
100  * The new frame is returned with the omf pointer.  As well,
101  * the values of Fsize_x and Fsize_y are adjusted.
102  ***************************************************************/
103 void
Frame_Resize(omf,mf,insize_x,insize_y,outsize_x,outsize_y)104  Frame_Resize(omf,mf,insize_x,insize_y,outsize_x,outsize_y)
105  MpegFrame *omf,*mf;
106  int insize_x,insize_y,outsize_x,outsize_y;
107 {
108 MpegFrame *frameA;  /* intermediate frame */
109 
110 frameA = (MpegFrame *)malloc(sizeof(MpegFrame));
111 
112 if((insize_x != outsize_x)&&(insize_y != outsize_y)){
113 Resize_Width(frameA,mf,insize_x,insize_y,outsize_x);
114 Resize_Height(omf,frameA,outsize_x,insize_y,outsize_y);
115 }else
116 if((insize_x ==outsize_x)&&(insize_y != outsize_y)){
117 Resize_Height(omf,mf,insize_x,insize_y,outsize_y);
118 } else
119 if((insize_x !=outsize_x)&&(insize_y == outsize_y)){
120 Resize_Width(omf,mf,insize_x,insize_y,outsize_x);
121 }
122 else{
123   exit(1);
124   }
125 /* Free memory */
126 free(frameA);
127 free(mf);
128 }
129 /*========================================================
130 * Resize_Width
131 *======================================================*/
132 static void
Resize_Width(omfrw,mfrw,in_x,in_y,out_x)133 Resize_Width(omfrw,mfrw,in_x,in_y, out_x)
134 MpegFrame *omfrw,*mfrw;
135 int in_x,in_y, out_x;
136 {
137 register int y;
138 int i;
139 
140 omfrw->orig_y = NULL;
141 Fsize_x = out_x;
142 /* Allocate new frame memory */
143     omfrw->orig_y = (uint8 **) malloc(sizeof(uint8 *) * Fsize_y);
144     ERRCHK(omfrw->orig_y, "malloc");
145     for (y = 0; y < Fsize_y; y++) {
146 	omfrw->orig_y[y] = (uint8 *) malloc(sizeof(uint8) * out_x);
147 	ERRCHK(omfrw->orig_y[y], "malloc");
148     }
149 
150     omfrw->orig_cr = (uint8 **) malloc(sizeof(int8 *) * Fsize_y / 2);
151     ERRCHK(omfrw->orig_cr, "malloc");
152     for (y = 0; y < Fsize_y / 2; y++) {
153 	omfrw->orig_cr[y] = (uint8 *) malloc(sizeof(int8) * out_x / 2);
154 	ERRCHK(omfrw->orig_cr[y], "malloc");
155     }
156 
157     omfrw->orig_cb = (uint8 **) malloc(sizeof(int8 *) * Fsize_y / 2);
158     ERRCHK(omfrw->orig_cb, "malloc");
159     for (y = 0; y < Fsize_y / 2; y++) {
160 	omfrw->orig_cb[y] = (uint8 *) malloc(sizeof(int8) * out_x / 2);
161 	ERRCHK(omfrw->orig_cb[y], "malloc");
162     }
163 
164     if ( referenceFrame == ORIGINAL_FRAME ) {
165 	omfrw->ref_y = omfrw->orig_y;
166 	omfrw->ref_cr = omfrw->orig_cr;
167 	omfrw->ref_cb = omfrw->orig_cb;
168     }
169 
170 /* resize each component array separately */
171 Resize_Array_Width(mfrw->orig_y,in_x,in_y,omfrw->orig_y,out_x);
172 Resize_Array_Width(mfrw->orig_cr,(in_x/2),(in_y/2),omfrw->orig_cr,(out_x/2));
173 Resize_Array_Width(mfrw->orig_cb,(in_x/2),(in_y/2),omfrw->orig_cb,(out_x/2));
174 
175 /* Free old frame memory */
176     if (mfrw->orig_y) {
177 	for (i = 0; i < in_y; i++) {
178 	    free(mfrw->orig_y[i]);
179 	}
180 	free(mfrw->orig_y);
181 
182 	for (i = 0; i < in_y / 2; i++) {
183 	    free(mfrw->orig_cr[i]);
184 	}
185 	free(mfrw->orig_cr);
186 
187 	for (i = 0; i < in_y / 2; i++) {
188 	    free(mfrw->orig_cb[i]);
189 	}
190 	free(mfrw->orig_cb);
191     }
192 
193 }
194 
195 /*=======================================================
196 * Resize_Height
197 *
198 *   Resize Frame height up or down
199 *=======================================================*/
200 static  void
Resize_Height(omfrh,mfrh,in_x,in_y,out_y)201 Resize_Height(omfrh,mfrh,in_x,in_y,out_y)
202 MpegFrame *omfrh,*mfrh;
203 int in_x,in_y, out_y;
204 {
205 register int y;
206 int i;
207 
208 Fsize_y = out_y;
209 
210 /* Allocate new frame memory */
211     omfrh->orig_y = (uint8 **) malloc(sizeof(uint8 *) * out_y);
212     ERRCHK(omfrh->orig_y, "malloc");
213     for (y = 0; y < out_y; y++) {
214 	omfrh->orig_y[y] = (uint8 *) malloc(sizeof(uint8) * Fsize_x);
215 	ERRCHK(omfrh->orig_y[y], "malloc");
216     }
217 
218     omfrh->orig_cr = (uint8 **) malloc(sizeof(int8 *) * out_y / 2);
219     ERRCHK(omfrh->orig_cr, "malloc");
220     for (y = 0; y < out_y / 2; y++) {
221 	omfrh->orig_cr[y] = (uint8 *) malloc(sizeof(int8) * Fsize_x / 2);
222 	ERRCHK(omfrh->orig_cr[y], "malloc");
223     }
224 
225     omfrh->orig_cb = (uint8 **) malloc(sizeof(int8 *) * out_y / 2);
226     ERRCHK(omfrh->orig_cb, "malloc");
227     for (y = 0; y < out_y / 2; y++) {
228 	omfrh->orig_cb[y] = (uint8 *) malloc(sizeof(int8) * Fsize_x / 2);
229 	ERRCHK(omfrh->orig_cb[y], "malloc");
230     }
231 
232     if ( referenceFrame == ORIGINAL_FRAME ) {
233 	omfrh->ref_y = omfrh->orig_y;
234 	omfrh->ref_cr = omfrh->orig_cr;
235 	omfrh->ref_cb = omfrh->orig_cb;
236     }
237 
238 /* resize component arrays separately */
239 Resize_Array_Height(mfrh->orig_y,in_x,in_y,omfrh->orig_y,out_y);
240 Resize_Array_Height(mfrh->orig_cr,(in_x/2),(in_y/2),omfrh->orig_cr,(out_y/2));
241 Resize_Array_Height(mfrh->orig_cb,(in_x/2),(in_y/2),omfrh->orig_cb,(out_y/2));
242 
243 /* Free old frame memory */
244     if (mfrh->orig_y) {
245 	for (i = 0; i < in_y; i++) {
246 	    free(mfrh->orig_y[i]);
247 	}
248 	free(mfrh->orig_y);
249 
250 	for (i = 0; i < in_y / 2; i++) {
251 	    free(mfrh->orig_cr[i]);
252 	}
253 	free(mfrh->orig_cr);
254 
255 	for (i = 0; i < in_y / 2; i++) {
256 	    free(mfrh->orig_cb[i]);
257 	}
258 	free(mfrh->orig_cb);
259     }
260 
261 }
262 /*====================================================
263 * Resize_Array_Width
264 *
265 *   This function will resize any array width up
266 * or down in size.  The algorithm is based on the
267 * least common multiple approach more commonly
268 * used in audio frequency adjustments.
269 *=====================================================*/
270 static void
Resize_Array_Width(inarray,in_x,in_y,outarray,out_x)271 Resize_Array_Width(inarray,in_x,in_y,outarray,out_x)
272 uint8 **inarray;
273 int in_x;
274 int in_y;
275 uint8 **outarray;
276 int out_x;
277 {
278 int i,j;
279 int in_total;
280 int out_total;
281 uint8 *inptr;
282 uint8 *outptr;
283 uint8 pointA,pointB;
284 /* double slope,diff; */
285 
286  for(i=0;i<in_y;i++){     /* For every row */
287   inptr = &inarray[i][0];
288   outptr = &outarray[i][0];
289   in_total = 0;
290   out_total = 0;
291   for(j=0;j<out_x;j++){      /* For every output value */
292     if(in_total == out_total){
293       *outptr = *inptr;
294       outptr++;
295       out_total=out_total+in_x;
296       while(in_total < out_total){
297 	in_total = in_total + out_x;
298 	inptr++;
299       }
300       if(in_total > out_total){
301 	in_total = in_total - out_x;
302 	inptr--;
303       }
304     } else {
305       pointA = *inptr;
306       inptr++;
307       pointB = *inptr;
308       inptr--;
309 /*Interpolative solution */
310 /*      slope = ((double)(pointB -pointA))/((double)(out_x));
311       diff = (((double)(out_total - in_total)));
312       if(diff < (out_x/2)){
313       *outptr = (pointA + (uint8)(slope*diff));
314     } else {
315       *outptr = (pointB - (uint8)(slope*(((float)(out_x)) - diff)));
316     } */
317 /* Non-Interpolative solution */
318     *outptr = *inptr;
319 
320       outptr++;
321       out_total=out_total+in_x;
322       while(in_total < out_total){
323 	in_total = in_total + out_x;
324 	inptr++;
325       }
326       if(in_total > out_total){
327 	in_total = in_total - out_x;
328 	inptr--;
329       }
330     }  /* end if */
331   }  /* end for each output value */
332 
333  }  /* end for each row */
334 }  /* end main */
335 /*==============================
336 * Resize_Array_Height
337 *
338 *    Resize any array height larger or smaller.
339 * Same as Resize_array_Width except pointer
340 * manipulation must change.
341 *===============================*/
342 static void
Resize_Array_Height(inarray,in_x,in_y,outarray,out_y)343 Resize_Array_Height(inarray,in_x,in_y,outarray,out_y)
344 uint8 **inarray;
345 int in_x;
346 int in_y;
347 uint8 **outarray;
348 int out_y;
349 {
350 int i,j,k;
351 int in_total;
352 int out_total;
353 uint8 pointA,pointB;
354 double slope,diff;
355 
356  for(i=0;i<in_x;i++){    /* for each column */
357   in_total = 0;
358   out_total = 0;
359   k = 0;
360   for(j=0;j<out_y;j++){  /* for each output value */
361     if(in_total == out_total){
362       outarray[j][i] = inarray[k][i];
363       out_total=out_total+in_y;
364       while(in_total < out_total){
365 	in_total = in_total + out_y;
366 	k++;
367       }
368       if(in_total > out_total){
369 	in_total = in_total - out_y;
370 	k--;
371       }
372     } else {
373 
374       pointA = inarray[k][i];
375       if(k != (in_y -1)){
376       pointB = inarray[k+1][i];
377       } else {
378       pointB = pointA;
379       }
380 /* Interpolative case */
381       slope = ((double)(pointB -pointA))/(double)(out_y);
382       diff = (double)(out_total - in_total);
383 /*      outarray[j][i] = (inarray[k][i] + (uint8)(slope*diff));
384 */
385 /* Non-Interpolative case */
386     outarray[j][i] = inarray[k][i];
387       out_total=out_total+in_y;
388       while(in_total < out_total){
389 	in_total = in_total + out_y;
390 	k++;
391       }
392       if(in_total > out_total){
393 	in_total = in_total - out_y;
394 	k--;
395       }
396     }
397   }
398  }
399 
400 }
401 
402 
403 
404 /*===========================================================================*
405  *
406  * Frame_Init
407  *
408  *	initializes the memory associated with all frames ever
409  *	If the input is not coming in from stdin, only 3 frames are needed ;
410  *      else, the program must create frames equal to the greatest distance
411  *      between two reference frames to hold the B frames while it is parsing
412  *      the input from stdin.
413  *
414  * RETURNS:	nothing
415  *
416  * SIDE EFFECTS:    frameMemory
417  *
418  *===========================================================================*/
419 void
Frame_Init()420 Frame_Init()
421 {
422     register int idx;
423     int numOfFrames = 0;
424 
425     GetNumOfFrames(&numOfFrames);
426 
427     for ( idx = 0; idx < numOfFrames; idx++ ) {
428 	frameMemory[idx] = (MpegFrame *) malloc(sizeof(MpegFrame));
429 	frameMemory[idx]->inUse = FALSE;
430 	frameMemory[idx]->ppm_data = NULL;
431 	frameMemory[idx]->rgb_data = NULL;
432 	frameMemory[idx]->orig_y = NULL;	/* if NULL, then orig_cr, orig_cb invalid */
433 	frameMemory[idx]->y_blocks = NULL; /* if NULL, then cr_blocks, cb_blocks invalid */
434 	frameMemory[idx]->decoded_y = NULL;	/* if NULL, then blah blah */
435 	frameMemory[idx]->halfX = NULL;
436 	frameMemory[idx]->next = NULL;
437     }
438 
439 #ifdef BLEAH
440 fprintf (stderr, "%d frames allocated.\n", numOfFrames);
441 #endif
442 }
443 
444 
445 /*===========================================================================*
446  *
447  * Frame_Exit
448  *
449  *	frees the memory associated with frames
450  *
451  * RETURNS:	nothing
452  *
453  * SIDE EFFECTS:    frameMemory
454  *
455  *===========================================================================*/
456 void
Frame_Exit()457 Frame_Exit()
458 {
459     register int idx;
460     int numOfFrames = 0;
461 
462     GetNumOfFrames(&numOfFrames);
463 
464     for ( idx = 0; idx < numOfFrames; idx++ ) {
465 	FreeFrame(frameMemory[idx]);
466     }
467 }
468 
469 
470 /*===========================================================================*
471  *
472  * Frame_Free
473  *
474  *	frees the given frame -- allows it to be re-used
475  *
476  * RETURNS:	nothing
477  *
478  * SIDE EFFECTS:    none
479  *
480  *===========================================================================*/
481 void
Frame_Free(frame)482 Frame_Free(frame)
483     MpegFrame *frame;
484 {
485     frame->inUse = FALSE;
486 }
487 
488 
489 /*===========================================================================*
490  *
491  * Frame_New
492  *
493  *	finds a frame that isn't currently being used and resets it
494  *
495  * RETURNS:	the frame
496  *
497  * SIDE EFFECTS:    none
498  *
499  *===========================================================================*/
500 MpegFrame *
Frame_New(id,type)501 Frame_New(id, type)
502     int id;
503     int type;
504 {
505     MpegFrame *frame;
506 
507     frame = GetUnusedFrame();
508     ResetFrame(id, type, frame);
509 
510     return frame;
511 }
512 
513 
514 /*===========================================================================*
515  *
516  * Frame_AllocPPM
517  *
518  *	allocate memory for ppm data for the given frame, if required
519  *
520  * RETURNS:	nothing
521  *
522  * SIDE EFFECTS:    none
523  *
524  *===========================================================================*/
525 void
Frame_AllocPPM(frame)526 Frame_AllocPPM(frame)
527     MpegFrame *frame;
528 {
529     register int y;
530 
531     if ( frame->ppm_data != NULL ) {	/* already allocated */
532 	return;
533     }
534 
535     frame->ppm_data = (uint8 **) malloc(sizeof(uint8 *) * Fsize_y);
536     ERRCHK(frame->ppm_data, "malloc");
537 
538     for ( y = 0; y < Fsize_y; y++ ) {
539 	frame->ppm_data[y] = (uint8 *) malloc(3*sizeof(uint8) * Fsize_x);
540 	ERRCHK(frame->ppm_data[y], "malloc");
541     }
542 }
543 
544 
545 /*===========================================================================*
546  *
547  * Frame_AllocBlocks
548  *
549  *	allocate memory for blocks for the given frame, if required
550  *
551  * RETURNS:	nothing
552  *
553  * SIDE EFFECTS:    none
554  *
555  *===========================================================================*/
556 void
Frame_AllocBlocks(frame)557 Frame_AllocBlocks(frame)
558     MpegFrame *frame;
559 {
560     int dctx, dcty;
561     int i;
562 
563     if ( frame->y_blocks != NULL ) {	    /* already allocated */
564 	return;
565     }
566 
567     dctx = Fsize_x / DCTSIZE;
568     dcty = Fsize_y / DCTSIZE;
569 
570     frame->y_blocks = (Block **) malloc(sizeof(Block *) * dcty);
571     ERRCHK(frame->y_blocks, "malloc");
572     for (i = 0; i < dcty; i++) {
573 	frame->y_blocks[i] = (Block *) malloc(sizeof(Block) * dctx);
574 	ERRCHK(frame->y_blocks[i], "malloc");
575     }
576 
577     frame->cr_blocks = (Block **) malloc(sizeof(Block *) * (dcty >> 1));
578     frame->cb_blocks = (Block **) malloc(sizeof(Block *) * (dcty >> 1));
579     ERRCHK(frame->cr_blocks, "malloc");
580     ERRCHK(frame->cb_blocks, "malloc");
581     for (i = 0; i < (dcty >> 1); i++) {
582 	frame->cr_blocks[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1));
583 	frame->cb_blocks[i] = (Block *) malloc(sizeof(Block) * (dctx >> 1));
584 	ERRCHK(frame->cr_blocks[i], "malloc");
585 	ERRCHK(frame->cb_blocks[i], "malloc");
586     }
587 }
588 
589 
590 /*===========================================================================*
591  *
592  * Frame_AllocYCC
593  *
594  *	allocate memory for YCC info for the given frame, if required
595  *
596  * RETURNS:	nothing
597  *
598  * SIDE EFFECTS:    none
599  *
600  *===========================================================================*/
601 void
Frame_AllocYCC(frame)602 Frame_AllocYCC(frame)
603     MpegFrame *frame;
604 {
605     register int y;
606 
607     if ( frame->orig_y != NULL ) {	/* already allocated */
608 	return /* nothing */ ;
609     }
610 
611     DBG_PRINT(("ycc_calc:\n"));
612     /*
613      * first, allocate tons of memory
614      */
615     frame->orig_y = (uint8 **) malloc(sizeof(uint8 *) * Fsize_y);
616     ERRCHK(frame->orig_y, "malloc");
617     for (y = 0; y < Fsize_y; y++) {
618 	frame->orig_y[y] = (uint8 *) malloc(sizeof(uint8) * Fsize_x);
619 	ERRCHK(frame->orig_y[y], "malloc");
620     }
621 
622     frame->orig_cr = (uint8 **) malloc(sizeof(int8 *) * (Fsize_y >> 1));
623     ERRCHK(frame->orig_cr, "malloc");
624     for (y = 0; y < (Fsize_y >> 1); y++) {
625 	frame->orig_cr[y] = (uint8 *) malloc(sizeof(int8) * (Fsize_x >> 1));
626 	ERRCHK(frame->orig_cr[y], "malloc");
627     }
628 
629     frame->orig_cb = (uint8 **) malloc(sizeof(int8 *) * (Fsize_y >> 1));
630     ERRCHK(frame->orig_cb, "malloc");
631     for (y = 0; y < (Fsize_y >> 1); y++) {
632 	frame->orig_cb[y] = (uint8 *) malloc(sizeof(int8) * (Fsize_x >> 1));
633 	ERRCHK(frame->orig_cb[y], "malloc");
634     }
635 
636     if ( referenceFrame == ORIGINAL_FRAME ) {
637 	frame->ref_y = frame->orig_y;
638 	frame->ref_cr = frame->orig_cr;
639 	frame->ref_cb = frame->orig_cb;
640     }
641 }
642 
643 
644 
645 /*===========================================================================*
646  *
647  * Frame_AllocHalf
648  *
649  *	allocate memory for half-pixel values for the given frame, if required
650  *
651  * RETURNS:	nothing
652  *
653  * SIDE EFFECTS:    none
654  *
655  *===========================================================================*/
656 void
Frame_AllocHalf(frame)657 Frame_AllocHalf(frame)
658     MpegFrame *frame;
659 {
660     register int y;
661 
662     if ( frame->halfX != NULL ) {
663         return;
664     }
665 
666 	frame->halfX = (uint8 **) malloc(Fsize_y*sizeof(uint8 *));
667 	ERRCHK(frame->halfX, "malloc");
668 	frame->halfY = (uint8 **) malloc((Fsize_y-1)*sizeof(uint8 *));
669 	ERRCHK(frame->halfY, "malloc");
670 	frame->halfBoth = (uint8 **) malloc((Fsize_y-1)*sizeof(uint8 *));
671 	ERRCHK(frame->halfBoth, "malloc");
672 	for ( y = 0; y < Fsize_y; y++ ) {
673 	    frame->halfX[y] = (uint8 *) malloc((Fsize_x-1)*sizeof(uint8));
674 	    ERRCHK(frame->halfX[y], "malloc");
675 	}
676 	for ( y = 0; y < Fsize_y-1; y++ ) {
677 	    frame->halfY[y] = (uint8 *) malloc(Fsize_x*sizeof(uint8));
678 	    ERRCHK(frame->halfY[y], "malloc");
679 	}
680 	for ( y = 0; y < Fsize_y-1; y++ ) {
681 	    frame->halfBoth[y] = (uint8 *) malloc((Fsize_x-1)*sizeof(uint8));
682 	    ERRCHK(frame->halfBoth[y], "malloc");
683 	}
684 }
685 
686 
687 /*===========================================================================*
688  *
689  * Frame_AllocDecoded
690  *
691  *	allocate memory for decoded frame for the given frame, if required
692  *	if makeReference == TRUE, then makes it reference frame
693  *
694  * RETURNS:	nothing
695  *
696  * SIDE EFFECTS:    none
697  *
698  *===========================================================================*/
699 void
Frame_AllocDecoded(frame,makeReference)700 Frame_AllocDecoded(frame, makeReference)
701     MpegFrame *frame;
702     boolean makeReference;
703 {
704     register int y;
705 
706     if ( frame->decoded_y != NULL) {	/* already allocated */
707 	return;
708     }
709 
710     /* allocate memory for decoded image */
711     /* can probably reuse original image memory, but may decide to use
712        it for some reason, so do it this way at least for now -- more
713        flexible
714      */
715     frame->decoded_y = (uint8 **) malloc(sizeof(uint8 *) * Fsize_y);
716     ERRCHK(frame->decoded_y, "malloc");
717     for (y = 0; y < Fsize_y; y++) {
718 	frame->decoded_y[y] = (uint8 *) malloc(sizeof(uint8) * Fsize_x);
719 	ERRCHK(frame->decoded_y[y], "malloc");
720     }
721 
722     frame->decoded_cr = (uint8 **) malloc(sizeof(int8 *) * (Fsize_y >> 1));
723     ERRCHK(frame->decoded_cr, "malloc");
724     for (y = 0; y < (Fsize_y >> 1); y++) {
725 	frame->decoded_cr[y] = (uint8 *) malloc(sizeof(uint8) * (Fsize_x >> 1));
726 	ERRCHK(frame->decoded_cr[y], "malloc");
727     }
728 
729     frame->decoded_cb = (uint8 **) malloc(sizeof(int8 *) * (Fsize_y >> 1));
730     ERRCHK(frame->decoded_cb, "malloc");
731     for (y = 0; y < (Fsize_y >> 1); y++) {
732 	frame->decoded_cb[y] = (uint8 *) malloc(sizeof(uint8) * (Fsize_x >> 1));
733 	ERRCHK(frame->decoded_cb[y], "malloc");
734     }
735 
736     if ( makeReference ) {
737 	frame->ref_y = frame->decoded_y;
738 	frame->ref_cr = frame->decoded_cr;
739 	frame->ref_cb = frame->decoded_cb;
740     }
741 }
742 
743 
744 /*=====================*
745  * INTERNAL PROCEDURES *
746  *=====================*/
747 
748 
749 /*===========================================================================*
750  *
751  * GetUnusedFrame
752  *
753  *	return an unused frame
754  *
755  * RETURNS:	the frame
756  *
757  * SIDE EFFECTS:    none
758  *
759  *===========================================================================*/
760 static MpegFrame *
GetUnusedFrame()761 GetUnusedFrame()
762 {
763     register int idx;
764     int numOfFrames;
765 
766     GetNumOfFrames(&numOfFrames);
767 
768     for ( idx = 0; idx < numOfFrames; idx++ ) {
769 	if ( ! frameMemory[idx]->inUse ) {
770 	    frameMemory[idx]->inUse = TRUE;
771 	    return frameMemory[idx];
772 	}
773     }
774 
775     fprintf(stderr, "ERROR:  No unused frames!!!\n");
776     fprintf(stderr, "        If you are using stdin for input, it is likely that you have too many\n");
777     fprintf(stderr, "        B-frames between two reference frames.  See the man page for help.\n");
778     exit(1);
779 }
780 
781 
782 /*===========================================================================*
783  *
784  * GetNumOfFrames
785  *
786  *	return the number of frames to allocate
787  *
788  * RETURNS:	nothing
789  *
790  * SIDE EFFECTS:    numOfFrames contains the number to allocate
791  *
792  *===========================================================================*/
793 static void
GetNumOfFrames(numOfFrames)794 GetNumOfFrames(numOfFrames)
795     int *numOfFrames;
796 {
797     int idx, bcount;
798 
799     if (stdinUsed) {
800       for ( idx = 0, bcount = 0; idx < strlen(framePattern); idx++) {
801 
802 	/* counts the maximum number of B frames between two reference
803 	 * frames.
804 	 */
805 
806 	switch( framePattern[idx] ) {
807 	  case 'b':
808 	    bcount++;
809 	    break;
810 	  case 'i':
811 	  case 'p':
812             if (bcount > *numOfFrames) {
813               *numOfFrames = bcount;
814             }
815 	    bcount = 0;
816 	    break;
817         }
818 
819 	/* add 2 to hold the forward and past reference frames in addition
820 	 * to the maximum number of B's
821 	 */
822       }
823 
824       *numOfFrames += 2;
825 
826     } else {
827       /* non-interactive, only 3 frames needed */
828       *numOfFrames = 3;
829     }
830 }
831 
832 /*===========================================================================*
833  *
834  * ResetFrame
835  *
836  *	reset a frame to the given id and type
837  *
838  * RETURNS:	nothing
839  *
840  * SIDE EFFECTS:    none
841  *
842  *===========================================================================*/
843 static void
ResetFrame(id,type,frame)844 ResetFrame(id, type, frame)
845     int id;
846     int type;
847     MpegFrame *frame;
848 {
849     switch (type) {
850     case 'i':
851 	frame->type = TYPE_IFRAME;
852 	break;
853     case 'p':
854 	frame->type = TYPE_PFRAME;
855 	break;
856     case 'b':
857 	frame->type = TYPE_BFRAME;
858 	break;
859     default:
860 	fprintf(stderr, "frame type %c: not supported\n", type);
861 	exit(1);
862     }
863 
864     frame->id = id;
865     frame->halfComputed = FALSE;
866     frame->next = NULL;
867 }
868 
869 
870 /*===========================================================================*
871  *
872  * FreeFrame
873  *
874  *	frees the memory associated with the given frame
875  *
876  * RETURNS:	nothing
877  *
878  * SIDE EFFECTS:    none
879  *
880  *===========================================================================*/
881 static void
FreeFrame(frame)882 FreeFrame(frame)
883     MpegFrame *frame;
884 {
885     int i;
886 
887     if (!frame) {
888 	return;
889     }
890 
891     if ( frame->ppm_data ) {
892 	/* it may be a little bigger than Fsize_y, but that's fine for
893 	   our purposes, since we aren't going to free until we exit anyway,
894 	   so by the time we call this we won't care
895 	 */
896 	pnm_freearray(frame->ppm_data, Fsize_y);
897 	frame->ppm_data = NULL;
898     }
899 
900     if (frame->rgb_data) {
901 	pnm_freearray(frame->rgb_data, Fsize_y);
902     }
903     if (frame->orig_y) {
904 	for (i = 0; i < Fsize_y; i++) {
905 	    free(frame->orig_y[i]);
906 	}
907 	free(frame->orig_y);
908 
909 	for (i = 0; i < (Fsize_y >> 1); i++) {
910 	    free(frame->orig_cr[i]);
911 	}
912 	free(frame->orig_cr);
913 
914 	for (i = 0; i < (Fsize_y >> 1); i++) {
915 	    free(frame->orig_cb[i]);
916 	}
917 	free(frame->orig_cb);
918     }
919     if ( frame->decoded_y ) {
920 	for (i = 0; i < Fsize_y; i++) {
921 	    free(frame->decoded_y[i]);
922 	}
923 	free(frame->decoded_y);
924 
925 	for (i = 0; i < (Fsize_y >> 1); i++) {
926 	    free(frame->decoded_cr[i]);
927 	}
928 	free(frame->decoded_cr);
929 
930 	for (i = 0; i < (Fsize_y >> 1); i++) {
931 	    free(frame->decoded_cb[i]);
932 	}
933 	free(frame->decoded_cb);
934     }
935 
936     if (frame->y_blocks) {
937 	for (i = 0; i < Fsize_y / DCTSIZE; i++) {
938 	    free(frame->y_blocks[i]);
939 	}
940 	free(frame->y_blocks);
941 
942 	for (i = 0; i < Fsize_y / (2 * DCTSIZE); i++) {
943 	    free(frame->cr_blocks[i]);
944 	}
945 	free(frame->cr_blocks);
946 
947 	for (i = 0; i < Fsize_y / (2 * DCTSIZE); i++) {
948 	    free(frame->cb_blocks[i]);
949 	}
950 	free(frame->cb_blocks);
951     }
952     if ( frame->halfX ) {
953 	for ( i = 0; i < Fsize_y; i++ ) {
954 	    free(frame->halfX[i]);
955 	}
956 	free(frame->halfX);
957 
958 	for ( i = 0; i < Fsize_y-1; i++ ) {
959 	    free(frame->halfY[i]);
960 	}
961 	free(frame->halfY);
962 
963 	for ( i = 0; i < Fsize_y-1; i++ ) {
964 	    free(frame->halfBoth[i]);
965 	}
966 	free(frame->halfBoth);
967     }
968 
969 
970     free(frame);
971 }
972 
973 
974