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