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 |
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 |
} |