about summary refs log tree commit diff
path: root/converter/ppm/ppmtompeg/frame.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/ppm/ppmtompeg/frame.c')
-rw-r--r--converter/ppm/ppmtompeg/frame.c836
1 files changed, 836 insertions, 0 deletions
diff --git a/converter/ppm/ppmtompeg/frame.c b/converter/ppm/ppmtompeg/frame.c
new file mode 100644
index 00000000..09f46f66
--- /dev/null
+++ b/converter/ppm/ppmtompeg/frame.c
@@ -0,0 +1,836 @@
+/*===========================================================================*
+ * frame.c                                   *
+ *                                       *
+ *  basic frame procedures                           *
+ *                                       *
+ * EXPORTED PROCEDURES:                              *
+ *  Frame_Init                               *
+ *  Frame_Exit                               *
+ *  Frame_New                                *
+ *  Frame_Free                               *
+ *  Frame_AllocBlocks                            *
+ *  Frame_AllocYCC                               *
+ *  Frame_AllocDecoded                           *
+ *  Frame_AllocHalf                                  *
+ *  Frame_Resize                                     * 
+ *                                       *
+ *===========================================================================*/
+
+/*
+ * Copyright (c) 1995 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
+ * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+
+#include "mallocvar.h"
+
+#include "all.h"
+#include "mtypes.h"
+#include "frames.h"
+#include "frame.h"
+#include "fsize.h"
+#include "dct.h"
+
+/*===========*
+ * CONSTANTS *
+ *===========*/
+
+/* The maximum number of B-Frames allowed between reference frames. */
+#define  B_FRAME_RUN  16    
+
+/*==================*
+ * GLOBAL VARIABLES *
+ *==================*/
+
+static MpegFrame * frameMemory[B_FRAME_RUN+2];
+static unsigned int numOfFrames;
+
+
+/*====================================================
+* Resize_Array_Width
+*    
+*   This function will resize any array width up
+* or down in size.  The algorithm is based on the
+* least common multiple approach more commonly
+* used in audio frequency adjustments.
+*=====================================================*/
+static void 
+Resize_Array_Width(uint8 ** const inarray,
+                   int      const in_x,
+                   int      const in_y,
+                   uint8 ** const outarray,
+                   int      const out_x) {
+
+    unsigned int i;
+    int in_total;
+    int out_total;
+    uint8 *inptr;
+    uint8 *outptr;
+    uint8 pointA,pointB;
+    /* double slope,diff; */
+    
+    for (i = 0; i < in_y; ++i) {     /* For each row */
+        unsigned int j;
+        inptr = &inarray[i][0];
+        outptr = &outarray[i][0];
+        in_total = 0;
+        out_total = 0;
+        for (j=0; j < out_x; ++j) {      /* For each output value */
+            if (in_total == out_total) {
+                *outptr = *inptr;
+                outptr++;
+                out_total=out_total+in_x;
+                while(in_total < out_total){
+                    in_total = in_total + out_x;
+                    ++inptr;
+                }
+                if (in_total > out_total) {
+                    in_total = in_total - out_x;
+                    --inptr;
+                }
+            } else {  
+                pointA = *inptr;
+                ++inptr;
+                pointB = *inptr;
+                --inptr;
+#if 0
+                /*Interpolative solution */
+                slope = ((double)(pointB -pointA))/((double)(out_x));
+                diff = (((double)(out_total - in_total)));
+                if (diff < (out_x/2)){
+                    *outptr = (pointA + (uint8)(slope*diff));
+                } else {
+                    *outptr = (pointB -
+                               (uint8)(slope*(((float)(out_x)) - diff)));
+                } 
+#endif
+                /* Non-Interpolative solution */
+                *outptr = *inptr;  
+
+                ++outptr;
+                out_total = out_total + in_x;
+                while(in_total < out_total) {
+                    in_total = in_total + out_x;
+                    ++inptr;
+                }
+                if (in_total > out_total) {
+                    in_total = in_total - out_x;
+                    --inptr;
+                }
+            }  /* end if */
+        }  /* end for each output value */
+    }  /* end for each row */
+}  /* end main */
+
+
+
+/*==============================
+* Resize_Array_Height
+*
+*    Resize any array height larger or smaller.
+* Same as Resize_array_Width except pointer
+* manipulation must change.
+*===============================*/
+static void 
+Resize_Array_Height(uint8 ** const inarray,
+                    int      const in_x,
+                    int      const in_y,
+                    uint8 ** const outarray,
+                    int      const out_y) {
+
+    unsigned int i;
+
+    for(i=0; i < in_x; ++i){    /* for each column */
+        int in_total;
+        int out_total;
+        uint8 pointA, pointB;
+        double slope, diff;
+        unsigned int j;
+        int k;
+
+        in_total = 0;
+        out_total = 0;
+        k = 0;
+        for(j=0; j < out_y; ++j){  /* for each output value */
+            if (in_total == out_total) {  
+                outarray[j][i] = inarray[k][i];
+                out_total=out_total+in_y;
+                while(in_total < out_total){
+                    in_total = in_total + out_y;
+                    ++k;
+                }
+                if (in_total > out_total) {
+                    in_total = in_total - out_y;
+                    --k;
+                }
+            } else {  
+                pointA = inarray[k][i];
+                if (k != (in_y -1)) {
+                    pointB = inarray[k+1][i];
+                } else
+                    pointB = pointA;
+                /* Interpolative case */
+                slope = ((double)(pointB -pointA))/(double)(out_y);
+                diff = (double)(out_total - in_total);
+                /*  outarray[j][i] = (inarray[k][i] + (uint8)(slope*diff)); */
+                /* Non-Interpolative case */
+                outarray[j][i] = inarray[k][i];
+                out_total = out_total + in_y;
+                while (in_total < out_total) {
+                    in_total = in_total + out_y;
+                    ++k;
+                }
+                if (in_total > out_total){
+                    in_total = in_total - out_y;
+                    --k;
+                }
+            } 
+        }
+    }
+}
+
+
+
+/*========================================================
+* Resize_Width
+*======================================================*/
+static void  
+Resize_Width(MpegFrame * const omfrw,
+             MpegFrame * const mfrw,
+             int         const in_x,
+             int         const in_y,
+             int         const out_x) {
+
+    int y;
+
+    omfrw->orig_y = NULL;
+    Fsize_x = out_x;
+
+    /* Allocate new frame memory */
+    MALLOCARRAY(omfrw->orig_y, Fsize_y);
+    ERRCHK(omfrw->orig_y, "malloc");
+    for (y = 0; y < Fsize_y; ++y) {
+        MALLOCARRAY(omfrw->orig_y[y], out_x);
+        ERRCHK(omfrw->orig_y[y], "malloc");
+    }
+
+    MALLOCARRAY(omfrw->orig_cr, Fsize_y / 2);
+    ERRCHK(omfrw->orig_cr, "malloc");
+    for (y = 0; y < Fsize_y / 2; ++y) {
+        MALLOCARRAY(omfrw->orig_cr[y], out_x / 2);
+        ERRCHK(omfrw->orig_cr[y], "malloc");
+    }
+
+    MALLOCARRAY(omfrw->orig_cb, Fsize_y / 2);
+    ERRCHK(omfrw->orig_cb, "malloc");
+    for (y = 0; y < Fsize_y / 2; ++y) {
+        MALLOCARRAY(omfrw->orig_cb[y], out_x / 2);
+        ERRCHK(omfrw->orig_cb[y], "malloc");
+    }
+
+    if (referenceFrame == ORIGINAL_FRAME) {
+        omfrw->ref_y = omfrw->orig_y;
+        omfrw->ref_cr = omfrw->orig_cr;
+        omfrw->ref_cb = omfrw->orig_cb;
+    }
+
+    /* resize each component array separately */
+    Resize_Array_Width(mfrw->orig_y, in_x, in_y, omfrw->orig_y, out_x);
+    Resize_Array_Width(mfrw->orig_cr, (in_x/2), (in_y/2), omfrw->orig_cr,
+                       (out_x/2));
+    Resize_Array_Width(mfrw->orig_cb, (in_x/2), (in_y/2), omfrw->orig_cb,
+                       (out_x/2));
+
+    /* Free old frame memory */
+    if (mfrw->orig_y) {
+        unsigned int i;
+        for (i = 0; i < in_y; ++i) {
+            free(mfrw->orig_y[i]);
+        }
+        free(mfrw->orig_y);
+        
+        for (i = 0; i < in_y / 2; ++i) {
+            free(mfrw->orig_cr[i]);
+        }
+        free(mfrw->orig_cr);
+        
+        for (i = 0; i < in_y / 2; ++i) {
+            free(mfrw->orig_cb[i]);
+        }
+        free(mfrw->orig_cb);
+    }
+}
+
+
+
+/*=======================================================
+* Resize_Height
+*
+*   Resize Frame height up or down
+*=======================================================*/
+static  void
+Resize_Height(MpegFrame * const omfrh,
+              MpegFrame * const mfrh,
+              int         const in_x,
+              int         const in_y,
+              int         const out_y) {
+    
+    unsigned int y; 
+    
+    Fsize_y = out_y;
+
+    /* Allocate new frame memory */
+    MALLOCARRAY(omfrh->orig_y, out_y);
+    ERRCHK(omfrh->orig_y, "malloc");
+    for (y = 0; y < out_y; ++y) {
+        MALLOCARRAY(omfrh->orig_y[y], Fsize_x);
+        ERRCHK(omfrh->orig_y[y], "malloc");
+    }
+
+    MALLOCARRAY(omfrh->orig_cr, out_y / 2);
+    ERRCHK(omfrh->orig_cr, "malloc");
+    for (y = 0; y < out_y / 2; ++y) {
+        MALLOCARRAY(omfrh->orig_cr[y], Fsize_x / 2);
+        ERRCHK(omfrh->orig_cr[y], "malloc");
+    }
+
+    MALLOCARRAY(omfrh->orig_cb, out_y / 2);
+    ERRCHK(omfrh->orig_cb, "malloc");
+    for (y = 0; y < out_y / 2; ++y) {
+        MALLOCARRAY(omfrh->orig_cb[y], Fsize_x / 2);
+        ERRCHK(omfrh->orig_cb[y], "malloc");
+    }
+
+    if (referenceFrame == ORIGINAL_FRAME) {
+        omfrh->ref_y = omfrh->orig_y;
+        omfrh->ref_cr = omfrh->orig_cr;
+        omfrh->ref_cb = omfrh->orig_cb;
+    }
+
+    /* resize component arrays separately */
+    Resize_Array_Height(mfrh->orig_y, in_x, in_y, omfrh->orig_y, out_y);
+    Resize_Array_Height(mfrh->orig_cr, (in_x/2), (in_y/2), omfrh->orig_cr,
+                        (out_y/2));
+    Resize_Array_Height(mfrh->orig_cb, (in_x/2), (in_y/2), omfrh->orig_cb,
+                        (out_y/2));
+
+    /* Free old frame memory */
+    if (mfrh->orig_y) {
+        unsigned int i;
+        for (i = 0; i < in_y; ++i) {
+            free(mfrh->orig_y[i]);
+        }
+        free(mfrh->orig_y);
+        
+    for (i = 0; i < in_y / 2; ++i) {
+        free(mfrh->orig_cr[i]);
+    }
+    free(mfrh->orig_cr);
+    
+    for (i = 0; i < in_y / 2; ++i) {
+        free(mfrh->orig_cb[i]);
+    }
+    free(mfrh->orig_cb);
+    }
+}
+
+
+
+/*===========================================================================*
+ *
+ * Frame_Init
+ *
+ *  initializes the memory associated with all frames ever
+ *  If the input is not coming in from stdin, only 3 frames are needed ;
+ *      else, the program must create frames equal to the greatest distance
+ *      between two reference frames to hold the B frames while it is parsing
+ *      the input from stdin.
+ *
+ * RETURNS: nothing
+ *
+ * SIDE EFFECTS:    frameMemory, numOfFrames
+ *
+ *===========================================================================*/
+void
+Frame_Init(unsigned int const numOfFramesRequested) {
+    int idx;
+
+    numOfFrames = numOfFramesRequested;
+
+    for (idx = 0; idx < numOfFrames; ++idx) {
+        MALLOCVAR(frameMemory[idx]);
+        frameMemory[idx]->inUse = FALSE;
+        frameMemory[idx]->orig_y = NULL;    
+        frameMemory[idx]->y_blocks = NULL; 
+        frameMemory[idx]->decoded_y = NULL;
+        frameMemory[idx]->halfX = NULL;
+        frameMemory[idx]->next = NULL;
+    }
+}
+
+
+/*===========================================================================*
+ *
+ * FreeFrame
+ *
+ *  frees the memory associated with the given frame
+ *
+ * RETURNS: nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static void
+FreeFrame(MpegFrame * const frameP) {
+
+    if (frameP) {
+        if (frameP->orig_y) {
+            unsigned int i;
+            for (i = 0; i < Fsize_y; ++i)
+                free(frameP->orig_y[i]);
+            free(frameP->orig_y);
+
+            for (i = 0; i < (Fsize_y / 2); ++i)
+                free(frameP->orig_cr[i]);
+            free(frameP->orig_cr);
+
+            for (i = 0; i < (Fsize_y / 2); ++i)
+                free(frameP->orig_cb[i]);
+            free(frameP->orig_cb);
+        }
+        if (frameP->decoded_y) {
+            unsigned int i;
+            for (i = 0; i < Fsize_y; ++i)
+                free(frameP->decoded_y[i]);
+            free(frameP->decoded_y);
+
+            for (i = 0; i < (Fsize_y / 2); ++i)
+                free(frameP->decoded_cr[i]);
+            free(frameP->decoded_cr);
+
+            for (i = 0; i < (Fsize_y / 2); ++i)
+                free(frameP->decoded_cb[i]);
+            free(frameP->decoded_cb);
+        }
+
+        if (frameP->y_blocks) {
+            unsigned int i;
+            for (i = 0; i < Fsize_y / DCTSIZE; ++i)
+                free(frameP->y_blocks[i]);
+            free(frameP->y_blocks);
+
+            for (i = 0; i < Fsize_y / (2 * DCTSIZE); ++i)
+                free(frameP->cr_blocks[i]);
+            free(frameP->cr_blocks);
+
+            for (i = 0; i < Fsize_y / (2 * DCTSIZE); ++i)
+                free(frameP->cb_blocks[i]);
+            free(frameP->cb_blocks);
+        }
+        if (frameP->halfX) {
+            unsigned int i;
+            for ( i = 0; i < Fsize_y; ++i )
+                free(frameP->halfX[i]);
+            free(frameP->halfX);
+            
+            for (i = 0; i < Fsize_y-1; ++i)
+                free(frameP->halfY[i]);
+            free(frameP->halfY);
+            
+            for (i = 0; i < Fsize_y-1; ++i)
+                free(frameP->halfBoth[i]);
+            free(frameP->halfBoth);
+        }
+        free(frameP);
+    }
+}
+
+
+
+/*===========================================================================*
+ *
+ * Frame_Exit
+ *
+ *  frees the memory associated with frames
+ *
+ * RETURNS: nothing
+ *
+ * SIDE EFFECTS:    frameMemory
+ *
+ *===========================================================================*/
+void
+Frame_Exit(void) {
+
+    int idx;
+
+    for (idx = 0; idx < numOfFrames; ++idx) {
+        FreeFrame(frameMemory[idx]);
+    }
+}
+
+
+/*===========================================================================*
+ *
+ * Frame_Free
+ *
+ *  frees the given frame -- allows it to be re-used
+ *
+ * RETURNS: nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+void
+Frame_Free(MpegFrame * const frameP) {
+    frameP->inUse = FALSE;
+}
+
+
+
+/*===========================================================================*
+ *
+ * GetUnusedFrame
+ *
+ *  return an unused frame
+ *
+ * RETURNS: the frame
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static MpegFrame *
+GetUnusedFrame() {
+    unsigned int idx;
+
+    for (idx = 0; idx < numOfFrames; ++idx) {
+        if (!frameMemory[idx]->inUse) {
+            frameMemory[idx]->inUse = TRUE;
+            break;
+        }
+    }
+    if (idx >= numOfFrames) {
+        fprintf(stderr, "ERROR:  No unused frames!!!\n");
+        fprintf(stderr, "        If you are using stdin for input, "
+                "it is likely that you have too many\n");
+        fprintf(stderr, "        B-frames between two reference frames.  "
+                "See the man page for help.\n");
+        exit(1);
+    }
+    return frameMemory[idx]; 
+}
+
+
+
+/*===========================================================================*
+ *
+ * ResetFrame
+ *
+ *  reset a frame to the given id and type
+ *
+ * RETURNS: nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+static void
+ResetFrame(int         const id,
+           int         const type,
+           MpegFrame * const frame) {
+
+    switch (type) {
+    case 'i':
+        frame->type = TYPE_IFRAME;
+        break;
+    case 'p':
+        frame->type = TYPE_PFRAME;
+        break;
+    case 'b':
+        frame->type = TYPE_BFRAME;
+        break;
+    default:
+        fprintf(stderr, "Invalid MPEG frame type %c\n", type);
+        exit(1);
+    }
+
+    frame->id = id;
+    frame->halfComputed = FALSE;
+    frame->next = NULL;
+}
+
+
+
+/*===========================================================================*
+ *
+ * Frame_New
+ *
+ *  finds a frame that isn't currently being used and resets it
+ *
+ * RETURNS: the frame
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+MpegFrame *
+Frame_New(int const id,
+          int const type) {
+
+    MpegFrame *frame;
+
+    frame = GetUnusedFrame();
+    ResetFrame(id, type, frame);
+
+    return frame;
+}
+
+
+
+/*===========================================================================*
+ *
+ * Frame_AllocBlocks
+ *
+ *  allocate memory for blocks for the given frame, if required
+ *
+ * RETURNS: nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+void
+Frame_AllocBlocks(MpegFrame * const frameP) {
+
+    if (frameP->y_blocks != NULL) {
+        /* already allocated */
+    } else {
+        int const dctx = Fsize_x / DCTSIZE;
+        int const dcty = Fsize_y / DCTSIZE;
+
+        unsigned int i;
+
+        MALLOCARRAY(frameP->y_blocks, dcty);
+        ERRCHK(frameP->y_blocks, "malloc");
+        for (i = 0; i < dcty; ++i) {
+            MALLOCARRAY(frameP->y_blocks[i], dctx);
+            ERRCHK(frameP->y_blocks[i], "malloc");
+        }
+    
+        MALLOCARRAY(frameP->cr_blocks, dcty / 2);
+        ERRCHK(frameP->cr_blocks, "malloc");
+        MALLOCARRAY(frameP->cb_blocks, dcty / 2);
+        ERRCHK(frameP->cb_blocks, "malloc");
+        for (i = 0; i < (dcty / 2); ++i) {
+            MALLOCARRAY(frameP->cr_blocks[i], dctx / 2);
+            ERRCHK(frameP->cr_blocks[i], "malloc");
+            MALLOCARRAY(frameP->cb_blocks[i], dctx / 2);
+            ERRCHK(frameP->cb_blocks[i], "malloc");
+        }
+    }
+}
+
+
+
+/*===========================================================================*
+ *
+ * Frame_AllocYCC
+ *
+ *  allocate memory for YCC info for the given frame, if required
+ *
+ * RETURNS: nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+void
+Frame_AllocYCC(MpegFrame * const frameP) {
+
+    if (frameP->orig_y != NULL) {
+        /* already allocated */
+    } else {
+        unsigned int y;
+    
+        DBG_PRINT(("ycc_calc:\n"));
+        /*
+         * first, allocate tons of memory
+         */
+        MALLOCARRAY(frameP->orig_y, Fsize_y);
+        ERRCHK(frameP->orig_y, "malloc");
+        for (y = 0; y < Fsize_y; ++y) {
+            MALLOCARRAY(frameP->orig_y[y], Fsize_x);
+            ERRCHK(frameP->orig_y[y], "malloc");
+        }
+
+        MALLOCARRAY(frameP->orig_cr, Fsize_y / 2);
+        ERRCHK(frameP->orig_cr, "malloc");
+        for (y = 0; y < (Fsize_y / 2); ++y) {
+            MALLOCARRAY(frameP->orig_cr[y], Fsize_x / 2);
+            ERRCHK(frameP->orig_cr[y], "malloc");
+        }
+
+        MALLOCARRAY(frameP->orig_cb, Fsize_y / 2);
+        ERRCHK(frameP->orig_cb, "malloc");
+        for (y = 0; y < (Fsize_y / 2); ++y) {
+            MALLOCARRAY(frameP->orig_cb[y], Fsize_x / 2);
+            ERRCHK(frameP->orig_cb[y], "malloc");
+        }
+
+        if (referenceFrame == ORIGINAL_FRAME) {
+            frameP->ref_y  = frameP->orig_y;
+            frameP->ref_cr = frameP->orig_cr;
+            frameP->ref_cb = frameP->orig_cb;
+        }
+    }
+}
+
+
+
+/*===========================================================================*
+ *
+ * Frame_AllocHalf
+ *
+ *  allocate memory for half-pixel values for the given frame, if required
+ *
+ * RETURNS: nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+void
+Frame_AllocHalf(MpegFrame * const frameP) {
+
+    if (frameP->halfX != NULL) {
+    } else {
+        unsigned int y;
+
+        MALLOCARRAY(frameP->halfX, Fsize_y);
+        ERRCHK(frameP->halfX, "malloc");
+        for (y = 0; y < Fsize_y; ++y) {
+            MALLOCARRAY(frameP->halfX[y], Fsize_x - 1);
+            ERRCHK(frameP->halfX[y], "malloc");
+        }
+        MALLOCARRAY(frameP->halfY, Fsize_y - 1);
+        ERRCHK(frameP->halfY, "malloc");
+        for (y = 0; y < Fsize_y - 1; ++y) {
+            MALLOCARRAY(frameP->halfY[y], Fsize_x);
+            ERRCHK(frameP->halfY[y], "malloc");
+        }
+        MALLOCARRAY(frameP->halfBoth, Fsize_y - 1);
+        ERRCHK(frameP->halfBoth, "malloc");
+        for (y = 0; y < Fsize_y - 1; ++y) {
+            MALLOCARRAY(frameP->halfBoth[y], Fsize_x - 1);
+            ERRCHK(frameP->halfBoth[y], "malloc");
+        }
+    }
+}
+
+
+
+/*===========================================================================*
+ *
+ * Frame_AllocDecoded
+ *
+ *  allocate memory for decoded frame for the given frame, if required
+ *  if makeReference == TRUE, then makes it reference frame
+ * 
+ * RETURNS: nothing
+ *
+ * SIDE EFFECTS:    none
+ *
+ *===========================================================================*/
+void
+Frame_AllocDecoded(MpegFrame * const frameP,
+                   boolean     const makeReference) {
+
+    if (frameP->decoded_y != NULL) {
+        /* already allocated */
+    } else {
+        unsigned int y;
+
+        /* allocate memory for decoded image */
+        /* can probably reuse original image memory, but may decide to use
+           it for some reason, so do it this way at least for now -- more
+           flexible
+        */
+        MALLOCARRAY(frameP->decoded_y, Fsize_y);
+        ERRCHK(frameP->decoded_y, "malloc");
+        for (y = 0; y < Fsize_y; ++y) {
+            MALLOCARRAY(frameP->decoded_y[y], Fsize_x);
+            ERRCHK(frameP->decoded_y[y], "malloc");
+        }
+        
+        MALLOCARRAY(frameP->decoded_cr, Fsize_y / 2);
+        ERRCHK(frameP->decoded_cr, "malloc");
+        for (y = 0; y < (Fsize_y / 2); ++y) {
+            MALLOCARRAY(frameP->decoded_cr[y], Fsize_x / 2);
+            ERRCHK(frameP->decoded_cr[y], "malloc");
+        }
+        
+        MALLOCARRAY(frameP->decoded_cb, Fsize_y / 2);
+        ERRCHK(frameP->decoded_cb, "malloc");
+        for (y = 0; y < (Fsize_y / 2); ++y) {
+            MALLOCARRAY(frameP->decoded_cb[y], Fsize_x / 2);
+            ERRCHK(frameP->decoded_cb[y], "malloc");
+        }
+
+        if (makeReference) {
+            frameP->ref_y  = frameP->decoded_y;
+            frameP->ref_cr = frameP->decoded_cr;
+            frameP->ref_cb = frameP->decoded_cb;
+        }
+    }
+}
+
+
+
+/*===============================================================
+ *
+ * Frame_Resize                  by James Boucher
+ *                Boston University Multimedia Communications Lab
+ *  
+ *     This function takes the mf input frame, read in READFrame(),
+ * and resizes all the input component arrays to the output
+ * dimensions specified in the parameter file as OUT_SIZE.
+ * The new frame is returned with the omf pointer.  As well,
+ * the values of Fsize_x and Fsize_y are adjusted.
+ ***************************************************************/
+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) {
+
+    MpegFrame * frameAP;  /* intermediate frame */
+
+    MALLOCVAR_NOFAIL(frameAP);
+    
+    if (insize_x != outsize_x && insize_y != outsize_y) {
+        Resize_Width(frameAP, mf, insize_x, insize_y, outsize_x);
+        Resize_Height(omf, frameAP, outsize_x, insize_y, outsize_y);
+    } else 
+        if (insize_x ==outsize_x && insize_y != outsize_y) {
+            Resize_Height(omf, mf, insize_x, insize_y, outsize_y);
+        } else
+            if (insize_x !=outsize_x && insize_y == outsize_y) {
+                Resize_Width(omf, mf, insize_x, insize_y, outsize_x);
+            } else
+                exit(1);
+
+    free(frameAP);
+    free(mf);
+}