ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/freemol/trunk/src/mpeg_encode/src/frame.c
Revision: 22
Committed: Mon Jul 7 22:16:37 2008 UTC (12 years, 1 month ago) by wdelano
File size: 24923 byte(s)
Log Message:
initial checkin of mpeg_encode source
Line User Rev File contents
1 wdelano 22 /*===========================================================================*
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
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
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
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
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
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
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
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
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 *
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
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
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
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
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
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 *
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
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
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
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     }