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