Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
2 | pj | 1 | /* |
2 | * video.c -- |
||
3 | * |
||
4 | * This file contains C code that implements the video decoder model. |
||
5 | * |
||
6 | */ |
||
7 | |||
8 | /* |
||
9 | * Copyright (c) 1995 The Regents of the University of California. |
||
10 | * All rights reserved. |
||
11 | * |
||
12 | * Permission to use, copy, modify, and distribute this software and its |
||
13 | * documentation for any purpose, without fee, and without written agreement is |
||
14 | * hereby granted, provided that the above copyright notice and the following |
||
15 | * two paragraphs appear in all copies of this software. |
||
16 | * |
||
17 | * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR |
||
18 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT |
||
19 | * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF |
||
20 | * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
21 | * |
||
22 | * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, |
||
23 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
||
24 | * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
||
25 | * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO |
||
26 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||
27 | */ |
||
28 | |||
29 | /* |
||
30 | * Portions of this software Copyright (c) 1995 Brown University. |
||
31 | * All rights reserved. |
||
32 | * |
||
33 | * Permission to use, copy, modify, and distribute this software and its |
||
34 | * documentation for any purpose, without fee, and without written agreement |
||
35 | * is hereby granted, provided that the above copyright notice and the |
||
36 | * following two paragraphs appear in all copies of this software. |
||
37 | * |
||
38 | * IN NO EVENT SHALL BROWN UNIVERSITY BE LIABLE TO ANY PARTY FOR |
||
39 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT |
||
40 | * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF BROWN |
||
41 | * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
42 | * |
||
43 | * BROWN UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT |
||
44 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
||
45 | * PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" |
||
46 | * BASIS, AND BROWN UNIVERSITY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, |
||
47 | * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
||
48 | */ |
||
49 | |||
50 | #include <stdio.h> |
||
51 | #include <stdlib.h> |
||
52 | #include <assert.h> |
||
53 | |||
54 | #ifndef MIPS |
||
55 | #include <sys/time.h> |
||
56 | #else |
||
57 | #include <sys/types.h> |
||
58 | #include <sys/system.h> |
||
59 | #endif |
||
60 | |||
61 | #ifndef NOCONTROLS |
||
62 | #include "ctrlbar.h" |
||
63 | #endif |
||
64 | #include "decoders.h" |
||
65 | #include "video.h" |
||
66 | #include "util.h" |
||
67 | #include "proto.h" |
||
68 | |||
69 | /* Declarations of functions. */ |
||
70 | static void ReconIMBlock(); |
||
71 | static void ReconPMBlock(); |
||
72 | static void ReconBMBlock(); |
||
73 | static void ReconBiMBlock(); |
||
74 | static void ReconSkippedBlock(); |
||
75 | static void DoPictureDisplay(); |
||
76 | static int ParseSeqHead(); |
||
77 | static int ParseGOP(); |
||
78 | static int ParsePicture(); |
||
79 | static int ParseSlice(); |
||
80 | static int ParseMacroBlock(); |
||
81 | static void ProcessSkippedPFrameMBlocks(); |
||
82 | static void ProcessSkippedBFrameMBlocks(); |
||
83 | |||
84 | /* |
||
85 | Changes to make the code reentrant: |
||
86 | de-globalized: totNumFrames, realTimeStart, matched_depth, ditherType, |
||
87 | curBits, ReconPMBlock statics, first, [lc]max[xy], ditherFlags, |
||
88 | vid_stream, Parse_done, seekValue, ReadPack static, sys_layer, |
||
89 | bitOffset, bitLength, bitBuffer, curVidStream, |
||
90 | X globals to xinfo (window, et al) |
||
91 | use vid_stream->film_has_ended instead of FilmState |
||
92 | lookup tables only initialized once, global as possible |
||
93 | (default_intra_matrix, zigzag, zigzag_direct, scan) |
||
94 | get rid of setjmp, long jmp |
||
95 | Additional changes: |
||
96 | if DISABLE_DITHER defined then do not compile dithering code |
||
97 | -lsh@cs.brown.edu (Loring Holden) |
||
98 | */ |
||
99 | |||
100 | /* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */ |
||
101 | |||
102 | #define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1)) |
||
103 | |||
104 | /* Set up array for fast conversion from zig zag order to row/column |
||
105 | coordinates. |
||
106 | */ |
||
107 | |||
108 | const int zigzag[64][2] = { |
||
109 | 0, 0, 1, 0, 0, 1, 0, 2, 1, 1, 2, 0, 3, 0, 2, 1, 1, 2, 0, 3, 0, 4, 1, 3, |
||
110 | 2, 2, 3, 1, 4, 0, 5, 0, 4, 1, 3, 2, 2, 3, 1, 4, 0, 5, 0, 6, 1, 5, 2, 4, |
||
111 | 3, 3, 4, 2, 5, 1, 6, 0, 7, 0, 6, 1, 5, 2, 4, 3, 3, 4, 2, 5, 1, 6, 0, 7, |
||
112 | 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6, 2, 7, 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6, |
||
113 | 2, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 5, 7, 6, 6, |
||
114 | 7, 5, 7, 6, 6, 7, 7, 7}; |
||
115 | /* Array mapping zigzag to array pointer offset. */ |
||
116 | |||
117 | const int zigzag_direct[64] = { |
||
118 | 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, |
||
119 | 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, |
||
120 | 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, |
||
121 | 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63}; |
||
122 | /* Set up array for fast conversion from row/column coordinates to |
||
123 | zig zag order. |
||
124 | */ |
||
125 | |||
126 | const int scan[8][8] = { |
||
127 | {0, 1, 5, 6, 14, 15, 27, 28}, |
||
128 | {2, 4, 7, 13, 16, 26, 29, 42}, |
||
129 | {3, 8, 12, 17, 25, 30, 41, 43}, |
||
130 | {9, 11, 18, 24, 31, 40, 44, 53}, |
||
131 | {10, 19, 23, 32, 39, 45, 52, 54}, |
||
132 | {20, 22, 33, 38, 46, 51, 55, 60}, |
||
133 | {21, 34, 37, 47, 50, 56, 59, 61}, |
||
134 | {35, 36, 48, 49, 57, 58, 62, 63}}; |
||
135 | /* Initialize P and B skip flags. */ |
||
136 | |||
137 | static int No_P_Flag = FALSE; |
||
138 | static int No_B_Flag = FALSE; |
||
139 | |||
140 | /* Max lum, chrom indices for illegal block checking. */ |
||
141 | |||
142 | |||
143 | /* |
||
144 | * We use a lookup table to make sure values stay in the 0..255 range. |
||
145 | * Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this |
||
146 | * table the "crop table". |
||
147 | * MAX_NEG_CROP is the maximum neg/pos value we can handle. |
||
148 | */ |
||
149 | |||
150 | #define MAX_NEG_CROP 2048 |
||
151 | #define NUM_CROP_ENTRIES (2048+2*MAX_NEG_CROP) |
||
152 | static unsigned char cropTbl[NUM_CROP_ENTRIES]; |
||
153 | |||
154 | /* |
||
155 | The following accounts for time and size spent in various parsing acitivites |
||
156 | if ANALYSIS has been defined. |
||
157 | */ |
||
158 | |||
159 | #ifdef ANALYSIS |
||
160 | |||
161 | |||
162 | unsigned int bitCount = 0; |
||
163 | |||
164 | int showmb_flag = 0; |
||
165 | int showEachFlag = 0; |
||
166 | |||
167 | typedef struct { |
||
168 | int frametype; |
||
169 | unsigned int totsize; |
||
170 | unsigned int number; |
||
171 | unsigned int i_mbsize; |
||
172 | unsigned int p_mbsize; |
||
173 | unsigned int b_mbsize; |
||
174 | unsigned int bi_mbsize; |
||
175 | unsigned int i_mbnum; |
||
176 | unsigned int p_mbnum; |
||
177 | unsigned int b_mbnum; |
||
178 | unsigned int bi_mbnum; |
||
179 | unsigned int i_mbcbp[64]; |
||
180 | unsigned int p_mbcbp[64]; |
||
181 | unsigned int b_mbcbp[64]; |
||
182 | unsigned int bi_mbcbp[64]; |
||
183 | unsigned int i_mbcoeff[64]; |
||
184 | unsigned int p_mbcoeff[64]; |
||
185 | unsigned int b_mbcoeff[64]; |
||
186 | unsigned int bi_mbcoeff[64]; |
||
187 | double tottime; |
||
188 | } Statval; |
||
189 | |||
190 | Statval stat_a[4]; |
||
191 | unsigned int pictureSizeCount; |
||
192 | unsigned int mbSizeCount; |
||
193 | unsigned int *mbCBPPtr, *mbCoeffPtr, *mbSizePtr; |
||
194 | unsigned int cacheHit[8][8]; |
||
195 | unsigned int cacheMiss[8][8]; |
||
196 | |||
197 | static void |
||
198 | init_stat_struct(astat) |
||
199 | Statval *astat; |
||
200 | { |
||
201 | int j; |
||
202 | |||
203 | astat->frametype = 0; |
||
204 | astat->totsize = 0; |
||
205 | astat->number = 0; |
||
206 | astat->i_mbsize = 0; |
||
207 | astat->p_mbsize = 0; |
||
208 | astat->b_mbsize = 0; |
||
209 | astat->bi_mbsize = 0; |
||
210 | astat->i_mbnum = 0; |
||
211 | astat->p_mbnum = 0; |
||
212 | astat->b_mbnum = 0; |
||
213 | astat->bi_mbnum = 0; |
||
214 | |||
215 | for (j = 0; j < 64; j++) { |
||
216 | |||
217 | astat->i_mbcbp[j] = 0; |
||
218 | astat->p_mbcbp[j] = 0; |
||
219 | astat->b_mbcbp[j] = 0; |
||
220 | astat->bi_mbcbp[j] = 0; |
||
221 | astat->i_mbcoeff[j] = 0; |
||
222 | astat->p_mbcoeff[j] = 0; |
||
223 | astat->b_mbcoeff[j] = 0; |
||
224 | astat->bi_mbcoeff[j] = 0; |
||
225 | } |
||
226 | astat->tottime = 0.0; |
||
227 | } |
||
228 | |||
229 | void |
||
230 | init_stats() |
||
231 | { |
||
232 | int i, j; |
||
233 | |||
234 | for (i = 0; i < 4; i++) { |
||
235 | init_stat_struct(&(stat_a[i])); |
||
236 | stat_a[i].frametype = i; |
||
237 | } |
||
238 | |||
239 | for (i = 0; i < 8; i++) { |
||
240 | for (j = 0; j < 8; j++) { |
||
241 | cacheHit[i][j] = 0; |
||
242 | cacheMiss[i][j] = 0; |
||
243 | } |
||
244 | } |
||
245 | |||
246 | bitCount = 0; |
||
247 | } |
||
248 | |||
249 | static void |
||
250 | PrintOneStat() |
||
251 | { |
||
252 | int i; |
||
253 | |||
254 | printf("\n"); |
||
255 | switch (stat_a[0].frametype) { |
||
256 | case I_TYPE: |
||
257 | printf("I FRAME\n"); |
||
258 | break; |
||
259 | case P_TYPE: |
||
260 | printf("P FRAME\n"); |
||
261 | break; |
||
262 | case B_TYPE: |
||
263 | printf("B FRAME\n"); |
||
264 | break; |
||
265 | } |
||
266 | |||
267 | printf("Size: %d bytes + %d bits\n", stat_a[0].totsize / 8, stat_a[0].totsize % 8); |
||
268 | if (stat_a[0].i_mbnum > 0) { |
||
269 | printf("\tI Macro Block Stats:\n"); |
||
270 | printf("\t%d I Macroblocks\n", stat_a[0].i_mbnum); |
||
271 | printf("\tAvg. Size: %d bytes + %d bits\n", |
||
272 | stat_a[0].i_mbsize / (8 * stat_a[0].i_mbnum), |
||
273 | (stat_a[0].i_mbsize * stat_a[0].i_mbnum) % 8); |
||
274 | printf("\t\tCoded Block Pattern Histogram:\n"); |
||
275 | for (i = 0; i < 64; i += 8) { |
||
276 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcbp[i], |
||
277 | stat_a[0].i_mbcbp[i + 1], stat_a[0].i_mbcbp[i + 2], stat_a[0].i_mbcbp[i + 3], |
||
278 | stat_a[0].i_mbcbp[i + 4], stat_a[0].i_mbcbp[i + 5], stat_a[0].i_mbcbp[i + 6], |
||
279 | stat_a[0].i_mbcbp[i + 7]); |
||
280 | } |
||
281 | printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); |
||
282 | for (i = 0; i < 64; i += 8) { |
||
283 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcoeff[i], |
||
284 | stat_a[0].i_mbcoeff[i + 1], stat_a[0].i_mbcoeff[i + 2], |
||
285 | stat_a[0].i_mbcoeff[i + 3], stat_a[0].i_mbcoeff[i + 4], |
||
286 | stat_a[0].i_mbcoeff[i + 5], stat_a[0].i_mbcoeff[i + 6], |
||
287 | stat_a[0].i_mbcoeff[i + 7]); |
||
288 | } |
||
289 | } |
||
290 | if (stat_a[0].p_mbnum > 0) { |
||
291 | printf("\tP Macro Block Stats:\n"); |
||
292 | printf("\t%d P Macroblocks\n", stat_a[0].p_mbnum); |
||
293 | printf("\tAvg. Size: %d bytes + %d bits\n", |
||
294 | stat_a[0].p_mbsize / (8 * stat_a[0].p_mbnum), |
||
295 | (stat_a[0].p_mbsize / stat_a[0].p_mbnum) % 8); |
||
296 | printf("\t\tCoded Block Pattern Histogram:\n"); |
||
297 | for (i = 0; i < 64; i += 8) { |
||
298 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcbp[i], |
||
299 | stat_a[0].p_mbcbp[i + 1], stat_a[0].p_mbcbp[i + 2], stat_a[0].p_mbcbp[i + 3], |
||
300 | stat_a[0].p_mbcbp[i + 4], stat_a[0].p_mbcbp[i + 5], stat_a[0].p_mbcbp[i + 6], |
||
301 | stat_a[0].p_mbcbp[i + 7]); |
||
302 | } |
||
303 | printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); |
||
304 | for (i = 0; i < 64; i += 8) { |
||
305 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcoeff[i], |
||
306 | stat_a[0].p_mbcoeff[i + 1], stat_a[0].p_mbcoeff[i + 2], |
||
307 | stat_a[0].p_mbcoeff[i + 3], stat_a[0].p_mbcoeff[i + 4], |
||
308 | stat_a[0].p_mbcoeff[i + 5], stat_a[0].p_mbcoeff[i + 6], |
||
309 | stat_a[0].p_mbcoeff[i + 7]); |
||
310 | } |
||
311 | } |
||
312 | if (stat_a[0].b_mbnum > 0) { |
||
313 | printf("\tB Macro Block Stats:\n"); |
||
314 | printf("\t%d B Macroblocks\n", stat_a[0].b_mbnum); |
||
315 | printf("\tAvg. Size: %d bytes + %d bits\n", |
||
316 | stat_a[0].b_mbsize / (8 * stat_a[0].b_mbnum), |
||
317 | (stat_a[0].b_mbsize / stat_a[0].b_mbnum) % 8); |
||
318 | printf("\t\tCoded Block Pattern Histogram:\n"); |
||
319 | for (i = 0; i < 64; i += 8) { |
||
320 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcbp[i], |
||
321 | stat_a[0].b_mbcbp[i + 1], stat_a[0].b_mbcbp[i + 2], stat_a[0].b_mbcbp[i + 3], |
||
322 | stat_a[0].b_mbcbp[i + 4], stat_a[0].b_mbcbp[i + 5], stat_a[0].b_mbcbp[i + 6], |
||
323 | stat_a[0].b_mbcbp[i + 7]); |
||
324 | } |
||
325 | printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); |
||
326 | for (i = 0; i < 64; i += 8) { |
||
327 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcoeff[i], |
||
328 | stat_a[0].b_mbcoeff[i + 1], stat_a[0].b_mbcoeff[i + 2], |
||
329 | stat_a[0].b_mbcoeff[i + 3], stat_a[0].b_mbcoeff[i + 4], |
||
330 | stat_a[0].b_mbcoeff[i + 5], stat_a[0].b_mbcoeff[i + 6], |
||
331 | stat_a[0].b_mbcoeff[i + 7]); |
||
332 | } |
||
333 | } |
||
334 | if (stat_a[0].bi_mbnum > 0) { |
||
335 | printf("\tBi Macro Block Stats:\n"); |
||
336 | printf("\t%d Bi Macroblocks\n", stat_a[0].bi_mbnum); |
||
337 | printf("\tAvg. Size: %d bytes + %d bits\n", |
||
338 | stat_a[0].bi_mbsize / (8 * stat_a[0].bi_mbnum), |
||
339 | (stat_a[0].bi_mbsize * stat_a[0].bi_mbnum) % 8); |
||
340 | printf("\t\tCoded Block Pattern Histogram:\n"); |
||
341 | for (i = 0; i < 64; i += 8) { |
||
342 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcbp[i], |
||
343 | stat_a[0].bi_mbcbp[i + 1], stat_a[0].bi_mbcbp[i + 2], stat_a[0].bi_mbcbp[i + 3], |
||
344 | stat_a[0].bi_mbcbp[i + 4], stat_a[0].bi_mbcbp[i + 5], stat_a[0].bi_mbcbp[i + 6], |
||
345 | stat_a[0].bi_mbcbp[i + 7]); |
||
346 | } |
||
347 | printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); |
||
348 | for (i = 0; i < 64; i += 8) { |
||
349 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcoeff[i], |
||
350 | stat_a[0].bi_mbcoeff[i + 1], stat_a[0].bi_mbcoeff[i + 2], |
||
351 | stat_a[0].bi_mbcoeff[i + 3], stat_a[0].bi_mbcoeff[i + 4], |
||
352 | stat_a[0].bi_mbcoeff[i + 5], stat_a[0].bi_mbcoeff[i + 6], |
||
353 | stat_a[0].bi_mbcoeff[i + 7]); |
||
354 | } |
||
355 | } |
||
356 | printf("\nTime to Decode: %g secs.\n", stat_a[0].tottime); |
||
357 | printf("****************\n"); |
||
358 | } |
||
359 | |||
360 | void |
||
361 | PrintAllStats(vid_stream) |
||
362 | VidStream *vid_stream; |
||
363 | { |
||
364 | int i, j; |
||
365 | unsigned int supertot, supernum; |
||
366 | double supertime; |
||
367 | |||
368 | printf("\n"); |
||
369 | printf("General Info: \n"); |
||
370 | printf("Width: %d\nHeight: %d\n", vid_stream->mb_width * 16, vid_stream->mb_height * 16); |
||
371 | |||
372 | for (i = 1; i < 4; i++) { |
||
373 | |||
374 | if (stat_a[i].number == 0) |
||
375 | continue; |
||
376 | |||
377 | switch (i) { |
||
378 | case 1: |
||
379 | printf("I FRAMES\n"); |
||
380 | break; |
||
381 | case 2: |
||
382 | printf("P FRAMES\n"); |
||
383 | break; |
||
384 | case 3: |
||
385 | printf("B FRAMES\n"); |
||
386 | break; |
||
387 | } |
||
388 | |||
389 | printf("Number: %d\n", stat_a[i].number); |
||
390 | printf("Avg. Size: %d bytes + %d bits\n", |
||
391 | stat_a[i].totsize / (8 * stat_a[i].number), (stat_a[i].totsize / stat_a[i].number) % 8); |
||
392 | if (stat_a[i].i_mbnum > 0) { |
||
393 | printf("\tI Macro Block Stats:\n"); |
||
394 | printf("\t%d I Macroblocks\n", stat_a[i].i_mbnum); |
||
395 | printf("\tAvg. Size: %d bytes + %d bits\n", |
||
396 | stat_a[i].i_mbsize / (8 * stat_a[i].i_mbnum), |
||
397 | (stat_a[i].i_mbsize / stat_a[i].i_mbnum) % 8); |
||
398 | printf("\t\tCoded Block Pattern Histogram:\n"); |
||
399 | for (j = 0; j < 64; j += 8) { |
||
400 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcbp[j], |
||
401 | stat_a[i].i_mbcbp[j + 1], stat_a[i].i_mbcbp[j + 2], stat_a[i].i_mbcbp[j + 3], |
||
402 | stat_a[i].i_mbcbp[j + 4], stat_a[i].i_mbcbp[j + 5], stat_a[i].i_mbcbp[j + 6], |
||
403 | stat_a[i].i_mbcbp[j + 7]); |
||
404 | } |
||
405 | printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); |
||
406 | for (j = 0; j < 64; j += 8) { |
||
407 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcoeff[j], |
||
408 | stat_a[i].i_mbcoeff[j + 1], stat_a[i].i_mbcoeff[j + 2], |
||
409 | stat_a[i].i_mbcoeff[j + 3], stat_a[i].i_mbcoeff[j + 4], |
||
410 | stat_a[i].i_mbcoeff[j + 5], stat_a[i].i_mbcoeff[j + 6], |
||
411 | stat_a[i].i_mbcoeff[j + 7]); |
||
412 | } |
||
413 | } |
||
414 | if (stat_a[i].p_mbnum > 0) { |
||
415 | printf("\tP Macro Block Stats:\n"); |
||
416 | printf("\t%d P Macroblocks\n", stat_a[i].p_mbnum); |
||
417 | printf("\tAvg. Size: %d bytes + %d bits\n", |
||
418 | stat_a[i].p_mbsize / (8 * stat_a[i].p_mbnum), |
||
419 | (stat_a[i].p_mbsize / stat_a[i].p_mbnum) % 8); |
||
420 | printf("\t\tCoded Block Pattern Histogram:\n"); |
||
421 | for (j = 0; j < 64; j += 8) { |
||
422 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcbp[j], |
||
423 | stat_a[i].p_mbcbp[j + 1], stat_a[i].p_mbcbp[j + 2], stat_a[i].p_mbcbp[j + 3], |
||
424 | stat_a[i].p_mbcbp[j + 4], stat_a[i].p_mbcbp[j + 5], stat_a[i].p_mbcbp[j + 6], |
||
425 | stat_a[i].p_mbcbp[j + 7]); |
||
426 | } |
||
427 | printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); |
||
428 | for (j = 0; j < 64; j += 8) { |
||
429 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcoeff[j], |
||
430 | stat_a[i].p_mbcoeff[j + 1], stat_a[i].p_mbcoeff[j + 2], |
||
431 | stat_a[i].p_mbcoeff[j + 3], stat_a[i].p_mbcoeff[j + 4], |
||
432 | stat_a[i].p_mbcoeff[j + 5], stat_a[i].p_mbcoeff[j + 6], |
||
433 | stat_a[i].p_mbcoeff[j + 7]); |
||
434 | } |
||
435 | } |
||
436 | if (stat_a[i].b_mbnum > 0) { |
||
437 | printf("\tB Macro Block Stats:\n"); |
||
438 | printf("\t%d B Macroblocks\n", stat_a[i].b_mbnum); |
||
439 | printf("\tAvg. Size: %d bytes + %d bits\n", |
||
440 | stat_a[i].b_mbsize / (8 * stat_a[i].b_mbnum), |
||
441 | (stat_a[i].b_mbsize * stat_a[i].b_mbnum) % 8); |
||
442 | printf("\t\tCoded Block Pattern Histogram:\n"); |
||
443 | for (j = 0; j < 64; j += 8) { |
||
444 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcbp[j], |
||
445 | stat_a[i].b_mbcbp[j + 1], stat_a[i].b_mbcbp[j + 2], stat_a[i].b_mbcbp[j + 3], |
||
446 | stat_a[i].b_mbcbp[j + 4], stat_a[i].b_mbcbp[j + 5], stat_a[i].b_mbcbp[j + 6], |
||
447 | stat_a[i].b_mbcbp[j + 7]); |
||
448 | } |
||
449 | printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); |
||
450 | for (j = 0; j < 64; j += 8) { |
||
451 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcoeff[j], |
||
452 | stat_a[i].b_mbcoeff[j + 1], stat_a[i].b_mbcoeff[j + 2], |
||
453 | stat_a[i].b_mbcoeff[j + 3], stat_a[i].b_mbcoeff[j + 4], |
||
454 | stat_a[i].b_mbcoeff[j + 5], stat_a[i].b_mbcoeff[j + 6], |
||
455 | stat_a[i].b_mbcoeff[j + 7]); |
||
456 | } |
||
457 | } |
||
458 | if (stat_a[i].bi_mbnum > 0) { |
||
459 | printf("\tBi Macro Block Stats:\n"); |
||
460 | printf("\t%d Bi Macroblocks\n", stat_a[i].bi_mbnum); |
||
461 | printf("\tAvg. Size: %d bytes + %d bits\n", |
||
462 | stat_a[i].bi_mbsize / (8 * stat_a[i].bi_mbnum), |
||
463 | (stat_a[i].bi_mbsize * stat_a[i].bi_mbnum) % 8); |
||
464 | printf("\t\tCoded Block Pattern Histogram:\n"); |
||
465 | for (j = 0; j < 64; j += 8) { |
||
466 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcbp[j], |
||
467 | stat_a[i].bi_mbcbp[j + 1], stat_a[i].bi_mbcbp[j + 2], stat_a[i].bi_mbcbp[j + 3], |
||
468 | stat_a[i].bi_mbcbp[j + 4], stat_a[i].bi_mbcbp[j + 5], stat_a[i].bi_mbcbp[j + 6], |
||
469 | stat_a[i].bi_mbcbp[j + 7]); |
||
470 | } |
||
471 | printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); |
||
472 | for (j = 0; j < 64; j += 8) { |
||
473 | printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcoeff[j], |
||
474 | stat_a[i].bi_mbcoeff[j + 1], stat_a[i].bi_mbcoeff[j + 2], |
||
475 | stat_a[i].bi_mbcoeff[j + 3], stat_a[i].bi_mbcoeff[j + 4], |
||
476 | stat_a[i].bi_mbcoeff[j + 5], stat_a[i].bi_mbcoeff[j + 6], |
||
477 | stat_a[i].bi_mbcoeff[j + 7]); |
||
478 | } |
||
479 | } |
||
480 | printf("\nAvg. Time to Decode: %f secs.\n", |
||
481 | (stat_a[i].tottime / ((double) stat_a[i].number))); |
||
482 | printf("\n"); |
||
483 | printf("*************************\n\n"); |
||
484 | } |
||
485 | |||
486 | supertot = stat_a[1].totsize + stat_a[2].totsize + stat_a[3].totsize; |
||
487 | supernum = stat_a[1].number + stat_a[2].number + stat_a[3].number; |
||
488 | supertime = stat_a[1].tottime + stat_a[2].tottime + stat_a[3].tottime; |
||
489 | |||
490 | printf("Total Number of Frames: %d\n", supernum); |
||
491 | printf("Avg Frame Size: %d bytes %d bits\n", |
||
492 | supertot / (8 * supernum), (supertot / supernum) % 8); |
||
493 | printf("Total Time Decoding: %g secs.\n", supertime); |
||
494 | printf("Avg Decoding Time/Frame: %g secs.\n", supertime / ((double) supernum)); |
||
495 | printf("Avg Decoding Frames/Sec: %g secs.\n", ((double) supernum) / supertime); |
||
496 | printf("\n"); |
||
497 | |||
498 | printf("Cache Hits/Miss\n"); |
||
499 | for (i = 0; i < 8; i++) { |
||
500 | printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n", |
||
501 | cacheHit[i][0], cacheMiss[i][0], cacheHit[i][1], cacheMiss[i][1], |
||
502 | cacheHit[i][2], cacheMiss[i][2], cacheHit[i][3], cacheMiss[i][3]); |
||
503 | printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n", |
||
504 | cacheHit[i][4], cacheMiss[i][4], cacheHit[i][5], cacheMiss[i][5], |
||
505 | cacheHit[i][6], cacheMiss[i][6], cacheHit[i][7], cacheMiss[i][7]); |
||
506 | } |
||
507 | |||
508 | } |
||
509 | |||
510 | static void |
||
511 | CollectStats() |
||
512 | { |
||
513 | int i, j; |
||
514 | |||
515 | i = stat_a[0].frametype; |
||
516 | |||
517 | stat_a[i].totsize += stat_a[0].totsize; |
||
518 | stat_a[i].number += stat_a[0].number; |
||
519 | stat_a[i].i_mbsize += stat_a[0].i_mbsize; |
||
520 | stat_a[i].p_mbsize += stat_a[0].p_mbsize; |
||
521 | stat_a[i].b_mbsize += stat_a[0].b_mbsize; |
||
522 | stat_a[i].bi_mbsize += stat_a[0].bi_mbsize; |
||
523 | stat_a[i].i_mbnum += stat_a[0].i_mbnum; |
||
524 | stat_a[i].p_mbnum += stat_a[0].p_mbnum; |
||
525 | stat_a[i].b_mbnum += stat_a[0].b_mbnum; |
||
526 | stat_a[i].bi_mbnum += stat_a[0].bi_mbnum; |
||
527 | |||
528 | for (j = 0; j < 64; j++) { |
||
529 | |||
530 | stat_a[i].i_mbcbp[j] += stat_a[0].i_mbcbp[j]; |
||
531 | stat_a[i].p_mbcbp[j] += stat_a[0].p_mbcbp[j]; |
||
532 | stat_a[i].b_mbcbp[j] += stat_a[0].b_mbcbp[j]; |
||
533 | stat_a[i].bi_mbcbp[j] += stat_a[0].bi_mbcbp[j]; |
||
534 | stat_a[i].i_mbcoeff[j] += stat_a[0].i_mbcoeff[j]; |
||
535 | stat_a[i].p_mbcoeff[j] += stat_a[0].p_mbcoeff[j]; |
||
536 | stat_a[i].b_mbcoeff[j] += stat_a[0].b_mbcoeff[j]; |
||
537 | stat_a[i].bi_mbcoeff[j] += stat_a[0].bi_mbcoeff[j]; |
||
538 | } |
||
539 | |||
540 | stat_a[i].tottime += stat_a[0].tottime; |
||
541 | |||
542 | init_stat_struct(&(stat_a[0])); |
||
543 | } |
||
544 | |||
545 | static unsigned int |
||
546 | bitCountRead() |
||
547 | { |
||
548 | return bitCount; |
||
549 | } |
||
550 | |||
551 | static void |
||
552 | StartTime() |
||
553 | { |
||
554 | stat_a[0].tottime = ReadSysClock(); |
||
555 | } |
||
556 | |||
557 | static void |
||
558 | EndTime() |
||
559 | { |
||
560 | stat_a[0].tottime = ReadSysClock() - stat_a[0].tottime; |
||
561 | } |
||
562 | #endif |
||
563 | |||
564 | |||
565 | /* |
||
566 | *-------------------------------------------------------------- |
||
567 | * |
||
568 | * ReadSysClock -- |
||
569 | * |
||
570 | * Computes the current time according to the system clock. |
||
571 | * |
||
572 | * Results: |
||
573 | * The current time according to the system clock. |
||
574 | * |
||
575 | * Side effects: |
||
576 | * None. |
||
577 | * |
||
578 | *-------------------------------------------------------------- |
||
579 | */ |
||
580 | |||
581 | double |
||
582 | ReadSysClock() |
||
583 | { |
||
584 | extern long sys_gettime(void*); |
||
585 | /*struct timeval tv; |
||
586 | (void) gettimeofday(&tv, (struct timezone *)NULL); |
||
587 | return (tv.tv_sec + tv.tv_usec / 1000000.0);*/ |
||
588 | //return sys_time(); |
||
589 | return sys_gettime(NULL)/1000000.0; |
||
590 | } |
||
591 | |||
592 | |||
593 | /* |
||
594 | *-------------------------------------------------------------- |
||
595 | * |
||
596 | * PrintTimeInfo -- |
||
597 | * |
||
598 | * Displays statistics regarding the video playback time. |
||
599 | * |
||
600 | * Results: |
||
601 | * Outputs time statistics to the screen. |
||
602 | * |
||
603 | * Side effects: |
||
604 | * None. |
||
605 | * |
||
606 | *-------------------------------------------------------------- |
||
607 | */ |
||
608 | |||
609 | void |
||
610 | PrintTimeInfo(vid_stream) |
||
611 | VidStream *vid_stream; |
||
612 | { |
||
613 | double spent; |
||
614 | |||
615 | #ifndef NOCONTROLS |
||
616 | if (ControlShow != CTRLBAR_NONE) |
||
617 | spent = StopWatch(STOPWATCH_STOP); |
||
618 | else |
||
619 | spent = ReadSysClock() - vid_stream->realTimeStart; |
||
620 | #else |
||
621 | spent = ReadSysClock() - vid_stream->realTimeStart; |
||
622 | #endif |
||
623 | if (!quietFlag) { |
||
624 | printf("\nReal Time Spent (After Initializations): %f secs.\n", spent); |
||
625 | printf("Avg. Frames/Sec: %f\n", |
||
626 | ((double) vid_stream->totNumFrames) / spent); |
||
627 | } |
||
628 | } |
||
629 | |||
630 | |||
631 | /* |
||
632 | *-------------------------------------------------------------- |
||
633 | * |
||
634 | * InitCrop -- |
||
635 | * |
||
636 | * Initializes cropTbl - this was taken from newVidStream so |
||
637 | * that it wasn't done for each new video stream |
||
638 | * |
||
639 | * Results: |
||
640 | * None |
||
641 | * |
||
642 | * Side effects: |
||
643 | * cropTbl will be initialized |
||
644 | * |
||
645 | *-------------------------------------------------------------- |
||
646 | */ |
||
647 | void |
||
648 | InitCrop() |
||
649 | { |
||
650 | int i; |
||
651 | |||
652 | /* Initialize crop table. */ |
||
653 | |||
654 | for (i = (-MAX_NEG_CROP); i < NUM_CROP_ENTRIES - MAX_NEG_CROP; i++) { |
||
655 | if (i <= 0) { |
||
656 | cropTbl[i + MAX_NEG_CROP] = 0; |
||
657 | #ifdef TWELVE_BITS |
||
658 | } else if (i >= 2047) { |
||
659 | cropTbl[i + MAX_NEG_CROP] = 2047; |
||
660 | #endif |
||
661 | } else if (i >= 255) { |
||
662 | cropTbl[i + MAX_NEG_CROP] = 255; |
||
663 | } else { |
||
664 | cropTbl[i + MAX_NEG_CROP] = i; |
||
665 | } |
||
666 | } |
||
667 | |||
668 | } |
||
669 | |||
670 | |||
671 | |||
672 | /* |
||
673 | *-------------------------------------------------------------- |
||
674 | * |
||
675 | * NewVidStream -- |
||
676 | * |
||
677 | * Allocates and initializes a VidStream structure. Takes |
||
678 | * as parameter requested size for buffer length. |
||
679 | * |
||
680 | * Results: |
||
681 | * A pointer to the new VidStream structure. |
||
682 | * |
||
683 | * Side effects: |
||
684 | * None. |
||
685 | * |
||
686 | *-------------------------------------------------------------- |
||
687 | */ |
||
688 | |||
689 | VidStream * |
||
690 | NewVidStream(buffer_len) |
||
691 | unsigned int buffer_len; |
||
692 | { |
||
693 | int i, j; |
||
694 | VidStream *new; |
||
695 | static const unsigned char default_intra_matrix[64] = { |
||
696 | 8, 16, 19, 22, 26, 27, 29, 34, |
||
697 | 16, 16, 22, 24, 27, 29, 34, 37, |
||
698 | 19, 22, 26, 27, 29, 34, 34, 38, |
||
699 | 22, 22, 26, 27, 29, 34, 37, 40, |
||
700 | 22, 26, 27, 29, 32, 35, 40, 48, |
||
701 | 26, 27, 29, 32, 35, 40, 48, 58, |
||
702 | 26, 27, 29, 34, 38, 46, 56, 69, |
||
703 | 27, 29, 35, 38, 46, 56, 69, 83}; |
||
704 | |||
705 | /* Check for legal buffer length. */ |
||
706 | |||
707 | if (buffer_len < 4) |
||
708 | return NULL; |
||
709 | |||
710 | /* Make buffer length multiple of 4. */ |
||
711 | |||
712 | buffer_len = (buffer_len + 3) >> 2; |
||
713 | |||
714 | /* Allocate memory for new structure. */ |
||
715 | |||
716 | new = (VidStream *) malloc(sizeof(VidStream)); |
||
717 | |||
718 | /* Initialize pointers to extension and user data. */ |
||
719 | |||
720 | new->group.ext_data = new->group.user_data = |
||
721 | new->picture.extra_info = new->picture.user_data = |
||
722 | new->picture.ext_data = new->slice.extra_info = |
||
723 | new->ext_data = new->user_data = NULL; |
||
724 | |||
725 | /* Copy default intra matrix. */ |
||
726 | |||
727 | for (i = 0; i < 8; i++) { |
||
728 | for (j = 0; j < 8; j++) { |
||
729 | new->intra_quant_matrix[i][j] = default_intra_matrix[i * 8 + j]; |
||
730 | } |
||
731 | } |
||
732 | |||
733 | /* Initialize non intra quantization matrix. */ |
||
734 | |||
735 | for (i = 0; i < 8; i++) { |
||
736 | for (j = 0; j < 8; j++) { |
||
737 | new->non_intra_quant_matrix[i][j] = 16; |
||
738 | } |
||
739 | } |
||
740 | |||
741 | /* Initialize pointers to image spaces. */ |
||
742 | |||
743 | new->current = new->past = new->future = NULL; |
||
744 | for (i = 0; i < RING_BUF_SIZE; i++) { |
||
745 | new->ring[i] = NULL; |
||
746 | } |
||
747 | |||
748 | /* Create buffer. */ |
||
749 | |||
750 | new->buf_start = (unsigned int *) malloc(buffer_len * 4); |
||
751 | |||
752 | /* |
||
753 | * Set max_buf_length to one less than actual length to deal with messy |
||
754 | * data without proper seq. end codes. |
||
755 | */ |
||
756 | |||
757 | new->max_buf_length = buffer_len - 1; |
||
758 | |||
759 | /* Initialize bitstream i/o fields. */ |
||
760 | |||
761 | new->bit_offset = 0; |
||
762 | new->buf_length = 0; |
||
763 | new->buffer = new->buf_start; |
||
764 | |||
765 | /* Initialize fields that used to be global */ |
||
766 | new->film_has_ended = FALSE; |
||
767 | new->filename = NULL; |
||
768 | new->totNumFrames = 0; |
||
769 | new->ditherFlags = NULL; |
||
770 | new->EOF_flag = FALSE; |
||
771 | |||
772 | /* Return structure. */ |
||
773 | |||
774 | return new; |
||
775 | } |
||
776 | |||
777 | |||
778 | |||
779 | /* |
||
780 | *-------------------------------------------------------------- |
||
781 | * |
||
782 | * ResetVidStream -- |
||
783 | * |
||
784 | * Re-initializes a VidStream structure. Takes |
||
785 | * as parameter a pointer to the VidStream to reset. |
||
786 | * |
||
787 | * Results: |
||
788 | * None. |
||
789 | * |
||
790 | * Side effects: |
||
791 | * None. |
||
792 | * |
||
793 | *-------------------------------------------------------------- |
||
794 | */ |
||
795 | |||
796 | void |
||
797 | ResetVidStream(vid) |
||
798 | VidStream *vid; |
||
799 | { |
||
800 | int i; |
||
801 | |||
802 | /* Initialize pointers to image spaces. */ |
||
803 | vid->current = vid->past = vid->future = NULL; |
||
804 | |||
805 | /* Initialize rings */ |
||
806 | for (i = 0; i < RING_BUF_SIZE; i++) |
||
807 | vid->ring[i]->locked = 0; /* Unlock */ |
||
808 | |||
809 | /* Initialize bitstream i/o fields. */ |
||
810 | vid->bit_offset = vid->buf_length = 0; |
||
811 | vid->buffer = vid->buf_start; |
||
812 | vid->curBits = 0; |
||
813 | |||
814 | /* We are at the beginning of the film, so film has not ended */ |
||
815 | vid->film_has_ended = FALSE; |
||
816 | |||
817 | /* Initialize start time */ |
||
818 | vid->realTimeStart = ReadSysClock(); |
||
819 | |||
820 | /* Reset number of frames to zero */ |
||
821 | vid->totNumFrames=0; |
||
822 | |||
823 | /* Reset EOF_flag to 0 */ |
||
824 | vid->EOF_flag = 0; |
||
825 | } |
||
826 | |||
827 | |||
828 | /* |
||
829 | *-------------------------------------------------------------- |
||
830 | * |
||
831 | * DestroyVidStream -- |
||
832 | * |
||
833 | * Deallocates a VidStream structure. |
||
834 | * |
||
835 | * Results: |
||
836 | * None. |
||
837 | * |
||
838 | * Side effects: |
||
839 | * None. |
||
840 | * |
||
841 | *-------------------------------------------------------------- |
||
842 | */ |
||
843 | void |
||
844 | DestroyVidStream(astream, xinfo) |
||
845 | VidStream *astream; |
||
846 | XInfo *xinfo; |
||
847 | { |
||
848 | int i; |
||
849 | |||
850 | if (astream->ext_data != NULL) |
||
851 | free(astream->ext_data); |
||
852 | |||
853 | if (astream->user_data != NULL) |
||
854 | free(astream->user_data); |
||
855 | |||
856 | if (astream->group.ext_data != NULL) |
||
857 | free(astream->group.ext_data); |
||
858 | |||
859 | if (astream->group.user_data != NULL) |
||
860 | free(astream->group.user_data); |
||
861 | |||
862 | if (astream->picture.extra_info != NULL) |
||
863 | free(astream->picture.extra_info); |
||
864 | |||
865 | if (astream->picture.ext_data != NULL) |
||
866 | free(astream->picture.ext_data); |
||
867 | |||
868 | if (astream->picture.user_data != NULL) |
||
869 | free(astream->picture.user_data); |
||
870 | |||
871 | if (astream->slice.extra_info != NULL) |
||
872 | free(astream->slice.extra_info); |
||
873 | |||
874 | if (astream->buf_start != NULL) |
||
875 | free(astream->buf_start); |
||
876 | |||
877 | for (i = 0; i < RING_BUF_SIZE; i++) { |
||
878 | if (astream->ring[i] != NULL) { |
||
879 | DestroyPictImage(astream->ring[i], xinfo); |
||
880 | astream->ring[i] = NULL; |
||
881 | } |
||
882 | } |
||
883 | |||
884 | if (astream->ditherFlags !=NULL) |
||
885 | free(astream->ditherFlags); |
||
886 | |||
887 | free((char *) astream); |
||
888 | } |
||
889 | |||
890 | |||
891 | |||
892 | |||
893 | /* |
||
894 | *-------------------------------------------------------------- |
||
895 | * |
||
896 | * NewPictImage -- |
||
897 | * |
||
898 | * Allocates and initializes a PictImage structure. |
||
899 | * The width and height of the image space are passed in |
||
900 | * as parameters. |
||
901 | * |
||
902 | * Results: |
||
903 | * A pointer to the new PictImage structure. |
||
904 | * |
||
905 | * Side effects: |
||
906 | * None. |
||
907 | * |
||
908 | *-------------------------------------------------------------- |
||
909 | */ |
||
910 | |||
911 | PictImage * |
||
912 | NewPictImage(vid_stream,xinfo) |
||
913 | VidStream *vid_stream; |
||
914 | XInfo *xinfo; |
||
915 | { |
||
916 | PictImage *new; |
||
917 | int ditherType=vid_stream->ditherType; |
||
918 | unsigned int width=vid_stream->mb_width * 16; |
||
919 | unsigned int height=vid_stream->mb_height * 16; |
||
920 | #ifdef SH_MEM |
||
921 | Display *display=xinfo->display; |
||
922 | #endif |
||
923 | |||
924 | /* Allocate memory space for new structure. */ |
||
925 | |||
926 | new = (PictImage *) malloc(sizeof(PictImage)); |
||
927 | |||
928 | |||
929 | /* Allocate memory for image spaces. */ |
||
930 | |||
931 | #ifdef SH_MEM |
||
932 | new->ximage = NULL; |
||
933 | |||
934 | if (shmemFlag) { |
||
935 | Visual *fc_visual; |
||
936 | int depth; |
||
937 | /* |
||
938 | * factor is 1 or 2 |
||
939 | */ |
||
940 | int factor = 1 + IS_2x2_DITHER(ditherType); |
||
941 | |||
942 | Visual *FindFullColorVisual(); |
||
943 | |||
944 | #ifndef DISABLE_DITHER |
||
945 | if (ditherType == FULL_COLOR_DITHER || ditherType == FULL_COLOR2_DITHER) { |
||
946 | #endif |
||
947 | fc_visual = FindFullColorVisual(display, &depth); |
||
948 | new->ximage = XShmCreateImage(display, fc_visual, (unsigned int) depth, |
||
949 | ZPixmap, |
||
950 | NULL, &(new->shminfo), width * factor, |
||
951 | height * factor); |
||
952 | #ifndef DISABLE_DITHER |
||
953 | } else if (ditherType == FULL_COLOR2_DITHER) { |
||
954 | fc_visual = FindFullColorVisual(display, &depth); |
||
955 | new->ximage = XShmCreateImage(display, fc_visual, (unsigned int) depth, |
||
956 | ZPixmap, |
||
957 | NULL, &(new->shminfo), width*2, height*2); |
||
958 | } else if (ditherType == MONO_DITHER || ditherType == MONO_THRESHOLD) { |
||
959 | new->ximage = XShmCreateImage(display, None, 1, XYBitmap, |
||
960 | NULL, &(new->shminfo), width * factor, |
||
961 | height * factor); |
||
962 | } else { |
||
963 | new->ximage = XShmCreateImage(display, None, xinfo->depth, ZPixmap, NULL, |
||
964 | &(new->shminfo), width * factor, |
||
965 | height * factor); |
||
966 | } |
||
967 | #endif |
||
968 | |||
969 | /* If no go, then revert to normal Xlib calls. */ |
||
970 | |||
971 | if (new->ximage == NULL) { |
||
972 | shmemFlag = 0; |
||
973 | if (!quietFlag) { |
||
974 | fprintf(stderr, "Shared memory error, disabling.\n"); |
||
975 | fprintf(stderr, "Ximage error.\n"); |
||
976 | } |
||
977 | goto shmemerror; |
||
978 | } |
||
979 | |||
980 | /* Success here, continue. */ |
||
981 | |||
982 | #ifdef LITTLE_ENDIAN_ARCHITECTURE |
||
983 | new->ximage->byte_order = LSBFirst; |
||
984 | new->ximage->bitmap_bit_order = LSBFirst; |
||
985 | #else |
||
986 | new->ximage->byte_order = MSBFirst; |
||
987 | new->ximage->bitmap_bit_order = MSBFirst; |
||
988 | #endif |
||
989 | |||
990 | new->shminfo.shmid = shmget(IPC_PRIVATE, (unsigned int) (new->ximage->bytes_per_line * |
||
991 | new->ximage->height), |
||
992 | IPC_CREAT | 0777); |
||
993 | |||
994 | if (new->shminfo.shmid < 0) { |
||
995 | XDestroyImage(new->ximage); |
||
996 | new->ximage = NULL; |
||
997 | shmemFlag = 0; |
||
998 | if (!quietFlag) { |
||
999 | fprintf(stderr, "Shared memory error, disabling.\n"); |
||
1000 | fprintf(stderr, "Seg. id. error.\n"); |
||
1001 | } |
||
1002 | goto shmemerror; |
||
1003 | } |
||
1004 | |||
1005 | new->shminfo.shmaddr = (char *) shmat(new->shminfo.shmid, 0, 0); |
||
1006 | |||
1007 | if (new->shminfo.shmaddr == ((char *) -1)) { |
||
1008 | XDestroyImage(new->ximage); |
||
1009 | new->ximage = NULL; |
||
1010 | shmemFlag = 0; |
||
1011 | if (!quietFlag) { |
||
1012 | fprintf(stderr, "Shared memory error, disabling.\n"); |
||
1013 | fprintf(stderr, "Address error.\n"); |
||
1014 | } |
||
1015 | goto shmemerror; |
||
1016 | } |
||
1017 | |||
1018 | new->ximage->data = new->shminfo.shmaddr; |
||
1019 | new->display = (unsigned char *) new->ximage->data; |
||
1020 | new->shminfo.readOnly = False; |
||
1021 | |||
1022 | XShmAttach(display, &(new->shminfo)); |
||
1023 | XSync(display, False); |
||
1024 | |||
1025 | if (gXErrorFlag) { |
||
1026 | /* Ultimate failure here. */ |
||
1027 | XShmDetach(display,&(new->shminfo)); |
||
1028 | XSync(display, False); |
||
1029 | XDestroyImage(new->ximage); |
||
1030 | shmdt (new->shminfo.shmaddr); |
||
1031 | shmctl (new->shminfo.shmid, IPC_RMID, 0); |
||
1032 | new->ximage = NULL; |
||
1033 | shmemFlag = 0; |
||
1034 | if (!quietFlag) { |
||
1035 | fprintf(stderr, "Shared memory error, disabling.\n"); |
||
1036 | } |
||
1037 | gXErrorFlag = 0; |
||
1038 | goto shmemerror; |
||
1039 | } else { |
||
1040 | shmctl(new->shminfo.shmid, IPC_RMID, 0); |
||
1041 | } |
||
1042 | |||
1043 | if (!quietFlag) { |
||
1044 | fprintf(stderr, "Sharing memory.\n"); |
||
1045 | } |
||
1046 | } else |
||
1047 | #endif |
||
1048 | { |
||
1049 | int temp_sz; |
||
1050 | int factor; |
||
1051 | shmemerror: |
||
1052 | #ifndef DISABLE_DITHER |
||
1053 | temp_sz = vid_stream->matched_depth >> 3; |
||
1054 | #else |
||
1055 | temp_sz = 4; |
||
1056 | #endif |
||
1057 | if(!temp_sz) temp_sz = 1; |
||
1058 | if(temp_sz == 3) temp_sz = 4; |
||
1059 | factor = 1 + IS_2x2_DITHER(ditherType); /* 1 or 2 */ |
||
1060 | |||
1061 | new->display = (unsigned char *) malloc(width * height * temp_sz * |
||
1062 | factor * factor); |
||
1063 | } |
||
1064 | new->luminance = (unsigned char *) malloc(width * height); |
||
1065 | new->Cr = (unsigned char *) malloc(width * height / 4); |
||
1066 | new->Cb = (unsigned char *) malloc(width * height / 4); |
||
1067 | |||
1068 | /* Reset locked flag. */ |
||
1069 | |||
1070 | new->locked = 0; |
||
1071 | |||
1072 | /* Return pointer to new structure. */ |
||
1073 | |||
1074 | return new; |
||
1075 | } |
||
1076 | |||
1077 | |||
1078 | |||
1079 | /* |
||
1080 | *-------------------------------------------------------------- |
||
1081 | * |
||
1082 | * DestroyPictImage -- |
||
1083 | * |
||
1084 | * Deallocates a PictImage structure. |
||
1085 | * |
||
1086 | * Results: |
||
1087 | * None. |
||
1088 | * |
||
1089 | * Side effects: |
||
1090 | * None. |
||
1091 | * |
||
1092 | *-------------------------------------------------------------- |
||
1093 | */ |
||
1094 | void |
||
1095 | DestroyPictImage(apictimage, xinfo) |
||
1096 | PictImage *apictimage; |
||
1097 | XInfo *xinfo; |
||
1098 | { |
||
1099 | if (apictimage->luminance != NULL) { |
||
1100 | free(apictimage->luminance); |
||
1101 | } |
||
1102 | if (apictimage->Cr != NULL) { |
||
1103 | free(apictimage->Cr); |
||
1104 | } |
||
1105 | if (apictimage->Cb != NULL) { |
||
1106 | free(apictimage->Cb); |
||
1107 | } |
||
1108 | #ifdef SH_MEM |
||
1109 | if ((apictimage->ximage != NULL)&&!noDisplayFlag&&shmemFlag) { |
||
1110 | if (xinfo!=NULL) XShmDetach(xinfo->display, &(apictimage->shminfo)); |
||
1111 | XDestroyImage(apictimage->ximage); |
||
1112 | shmdt(apictimage->shminfo.shmaddr); |
||
1113 | apictimage->ximage = NULL; |
||
1114 | apictimage->display = NULL; |
||
1115 | } |
||
1116 | #endif |
||
1117 | |||
1118 | if (apictimage->display != NULL) { |
||
1119 | free(apictimage->display); |
||
1120 | } |
||
1121 | free(apictimage); |
||
1122 | } |
||
1123 | |||
1124 | |||
1125 | /* |
||
1126 | *-------------------------------------------------------------- |
||
1127 | * |
||
1128 | * mpegVidRsrc -- |
||
1129 | * |
||
1130 | * Parses bit stream until MB_QUANTUM number of |
||
1131 | * macroblocks have been decoded or current slice or |
||
1132 | * picture ends, whichever comes first. If the start |
||
1133 | * of a frame is encountered, the frame is time stamped |
||
1134 | * with the value passed in time_stamp. If the value |
||
1135 | * passed in buffer is not null, the video stream buffer |
||
1136 | * is set to buffer and the length of the buffer is |
||
1137 | * expected in value passed in through length. The current |
||
1138 | * video stream is set to vid_stream. If vid_stream |
||
1139 | * is passed as NULL, a new VidStream structure is created |
||
1140 | * and initialized and used as the current video stream. |
||
1141 | * |
||
1142 | * Results: |
||
1143 | * A pointer to the video stream structure used. |
||
1144 | * |
||
1145 | * Side effects: |
||
1146 | * Bit stream is irreversibly parsed. If a picture is completed, |
||
1147 | * a function is called to display the frame at the correct time. |
||
1148 | * |
||
1149 | *-------------------------------------------------------------- |
||
1150 | */ |
||
1151 | |||
1152 | VidStream * |
||
1153 | mpegVidRsrc(time_stamp, vid_stream, first, xinfo) |
||
1154 | TimeStamp time_stamp; |
||
1155 | VidStream *vid_stream; |
||
1156 | int first; |
||
1157 | XInfo *xinfo; |
||
1158 | { |
||
1159 | unsigned int data; |
||
1160 | int i, status; |
||
1161 | |||
1162 | /* If vid_stream is null, create new VidStream structure. */ |
||
1163 | |||
1164 | if (vid_stream == NULL) { |
||
1165 | return NULL; |
||
1166 | } |
||
1167 | |||
1168 | /* |
||
1169 | * If called for the first time, find start code, make sure it is a |
||
1170 | * sequence start code. |
||
1171 | */ |
||
1172 | |||
1173 | if (first) { |
||
1174 | vid_stream->sys_layer=-1; |
||
1175 | vid_stream->num_left=0; |
||
1176 | vid_stream->leftover_bytes=0; |
||
1177 | vid_stream->seekValue=0; |
||
1178 | vid_stream->Parse_done=FALSE; |
||
1179 | next_start_code(vid_stream); /* sets curBits */ |
||
1180 | show_bits32(data); |
||
1181 | if (data != SEQ_START_CODE) { |
||
1182 | fprintf(stderr, "This is not an MPEG video stream. (%x)\n",data); |
||
1183 | DestroyVidStream(vid_stream,xinfo); |
||
1184 | return NULL; |
||
1185 | } |
||
1186 | } else { |
||
1187 | #ifdef UTIL2 |
||
1188 | vid_stream->curBits = *vid_stream->buffer << vid_stream->bit_offset; |
||
1189 | #else |
||
1190 | vid_stream->curBits = *vid_stream->buffer; |
||
1191 | #endif |
||
1192 | } |
||
1193 | |||
1194 | /* Get next 32 bits (size of start codes). */ |
||
1195 | |||
1196 | show_bits32(data); |
||
1197 | |||
1198 | /* |
||
1199 | * Process according to start code (or parse macroblock if not a start code |
||
1200 | * at all). |
||
1201 | */ |
||
1202 | |||
1203 | switch (data) { |
||
1204 | |||
1205 | case SEQ_END_CODE: |
||
1206 | case 0x000001b9: /* handle ISO_11172_END_CODE too */ |
||
1207 | |||
1208 | /* Display last frame. */ |
||
1209 | |||
1210 | if (vid_stream->future != NULL) { |
||
1211 | vid_stream->current = vid_stream->future; |
||
1212 | #ifndef NOCONTROLS |
||
1213 | ExecuteDisplay(vid_stream, 1, xinfo); |
||
1214 | #else |
||
1215 | ExecuteDisplay(vid_stream, xinfo); |
||
1216 | #endif |
||
1217 | } |
||
1218 | |||
1219 | /* Sequence done. Do the right thing. For right now, exit. */ |
||
1220 | if (!quietFlag) { |
||
1221 | fprintf(stderr, "\nDone!\n"); |
||
1222 | } |
||
1223 | |||
1224 | #ifdef ANALYSIS |
||
1225 | PrintAllStats(vid_stream); |
||
1226 | #endif |
||
1227 | PrintTimeInfo(vid_stream); |
||
1228 | |||
1229 | vid_stream->film_has_ended=TRUE; |
||
1230 | #ifdef NOCONTROLS |
||
1231 | if (loopFlag) { |
||
1232 | clear_data_stream(vid_stream); |
||
1233 | } else DestroyVidStream(vid_stream, xinfo); |
||
1234 | #endif /* !NOCONTROLS */ |
||
1235 | goto done; |
||
1236 | break; |
||
1237 | |||
1238 | case SEQ_START_CODE: |
||
1239 | |||
1240 | /* Sequence start code. Parse sequence header. */ |
||
1241 | |||
1242 | if (ParseSeqHead(vid_stream,xinfo) != PARSE_OK) |
||
1243 | goto error; |
||
1244 | |||
1245 | /* |
||
1246 | * Return after sequence start code so that application above can use |
||
1247 | * info in header. |
||
1248 | */ |
||
1249 | if (vid_stream->seekValue > 0) { |
||
1250 | SeekStream(vid_stream); |
||
1251 | } |
||
1252 | |||
1253 | |||
1254 | goto done; |
||
1255 | |||
1256 | case GOP_START_CODE: |
||
1257 | |||
1258 | /* Group of Pictures start code. Parse gop header. */ |
||
1259 | |||
1260 | if (ParseGOP(vid_stream) != PARSE_OK) |
||
1261 | goto error; |
||
1262 | goto done; |
||
1263 | |||
1264 | case PICTURE_START_CODE: |
||
1265 | |||
1266 | /* Picture start code. Parse picture header and first slice header. */ |
||
1267 | |||
1268 | status = ParsePicture(vid_stream, time_stamp); |
||
1269 | |||
1270 | if (status == SKIP_PICTURE) { |
||
1271 | next_start_code(vid_stream); |
||
1272 | while (!next_bits(32, PICTURE_START_CODE, vid_stream)) { |
||
1273 | if (next_bits(32, GOP_START_CODE, vid_stream)) |
||
1274 | break; |
||
1275 | else if (next_bits(32, SEQ_END_CODE, vid_stream)) |
||
1276 | break; |
||
1277 | flush_bits(24); |
||
1278 | next_start_code(vid_stream); |
||
1279 | } |
||
1280 | goto done; |
||
1281 | } else if (status != PARSE_OK) |
||
1282 | goto error; |
||
1283 | |||
1284 | |||
1285 | if (ParseSlice(vid_stream) != PARSE_OK) |
||
1286 | goto error; |
||
1287 | break; |
||
1288 | |||
1289 | case SEQUENCE_ERROR_CODE: |
||
1290 | flush_bits32; |
||
1291 | next_start_code(vid_stream); |
||
1292 | goto done; |
||
1293 | |||
1294 | default: |
||
1295 | |||
1296 | /* Check for slice start code. */ |
||
1297 | |||
1298 | if ((data >= SLICE_MIN_START_CODE) && (data <= SLICE_MAX_START_CODE)) { |
||
1299 | |||
1300 | /* Slice start code. Parse slice header. */ |
||
1301 | |||
1302 | if (ParseSlice(vid_stream) != PARSE_OK) |
||
1303 | goto error; |
||
1304 | } |
||
1305 | break; |
||
1306 | } |
||
1307 | |||
1308 | /* Parse next MB_QUANTUM macroblocks. */ |
||
1309 | |||
1310 | for (i = 0; i < MB_QUANTUM; i++) { |
||
1311 | |||
1312 | /* Check to see if actually a startcode and not a macroblock. */ |
||
1313 | |||
1314 | if (!next_bits(23, 0x00000000, vid_stream)) { |
||
1315 | |||
1316 | /* Not start code. Parse Macroblock. */ |
||
1317 | |||
1318 | if (ParseMacroBlock(vid_stream) != PARSE_OK) |
||
1319 | goto error; |
||
1320 | |||
1321 | #ifdef ANALYSIS |
||
1322 | if (showmb_flag) { |
||
1323 | DoDitherImage(vid_stream); |
||
1324 | #ifndef NOCONTROLS |
||
1325 | ExecuteDisplay(vid_stream, 1, xinfo); |
||
1326 | #else |
||
1327 | ExecuteDisplay(vid_stream, xinfo); |
||
1328 | #endif /* !NOCONTROLS */ |
||
1329 | } |
||
1330 | #endif /* ANALYSIS */ |
||
1331 | |||
1332 | } else { |
||
1333 | |||
1334 | /* Not macroblock, actually start code. Get start code. */ |
||
1335 | |||
1336 | next_start_code(vid_stream); |
||
1337 | show_bits32(data); |
||
1338 | |||
1339 | /* |
||
1340 | * If start code is outside range of slice start codes, frame is |
||
1341 | * complete, display frame. |
||
1342 | */ |
||
1343 | |||
1344 | if (((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) && |
||
1345 | (data != SEQUENCE_ERROR_CODE)) { |
||
1346 | |||
1347 | #ifdef ANALYSIS |
||
1348 | EndTime(); |
||
1349 | stat_a[0].totsize += bitCountRead() - pictureSizeCount; |
||
1350 | if (showEachFlag) { |
||
1351 | PrintOneStat(); |
||
1352 | }; |
||
1353 | |||
1354 | CollectStats(); |
||
1355 | #endif |
||
1356 | |||
1357 | DoPictureDisplay(vid_stream, xinfo); |
||
1358 | } |
||
1359 | goto done; |
||
1360 | } |
||
1361 | } |
||
1362 | |||
1363 | /* Check if we just finished a picture on the MB_QUANTUMth macroblock */ |
||
1364 | if (next_bits(23, 0x00000000, vid_stream)) { |
||
1365 | next_start_code(vid_stream); |
||
1366 | show_bits32(data); |
||
1367 | if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) { |
||
1368 | |||
1369 | #ifdef ANALYSIS |
||
1370 | EndTime(); |
||
1371 | stat_a[0].totsize += bitCountRead() - pictureSizeCount; |
||
1372 | if (showEachFlag) { |
||
1373 | PrintOneStat(); |
||
1374 | }; |
||
1375 | |||
1376 | CollectStats(); |
||
1377 | #endif |
||
1378 | |||
1379 | DoPictureDisplay(vid_stream, xinfo); |
||
1380 | } |
||
1381 | } |
||
1382 | |||
1383 | /* Return pointer to video stream structure. */ |
||
1384 | |||
1385 | goto done; |
||
1386 | |||
1387 | error: |
||
1388 | fprintf(stderr, "Error!!!!\n"); |
||
1389 | next_start_code(vid_stream); |
||
1390 | goto done; |
||
1391 | |||
1392 | done: |
||
1393 | |||
1394 | return vid_stream; |
||
1395 | |||
1396 | } |
||
1397 | |||
1398 | |||
1399 | |||
1400 | |||
1401 | /* |
||
1402 | *-------------------------------------------------------------- |
||
1403 | * |
||
1404 | * ParseSeqHead -- |
||
1405 | * |
||
1406 | * Assumes bit stream is at the begining of the sequence |
||
1407 | * header start code. Parses off the sequence header. |
||
1408 | * |
||
1409 | * Results: |
||
1410 | * Fills the vid_stream structure with values derived and |
||
1411 | * decoded from the sequence header. Allocates the pict image |
||
1412 | * structures based on the dimensions of the image space |
||
1413 | * found in the sequence header. |
||
1414 | * |
||
1415 | * Side effects: |
||
1416 | * Bit stream irreversibly parsed off. |
||
1417 | * |
||
1418 | *-------------------------------------------------------------- |
||
1419 | */ |
||
1420 | static int |
||
1421 | ParseSeqHead(vid_stream,xinfo) |
||
1422 | VidStream *vid_stream; |
||
1423 | XInfo *xinfo; |
||
1424 | { |
||
1425 | unsigned int data; |
||
1426 | int i, ditherType=vid_stream->ditherType; |
||
1427 | |||
1428 | /* Flush off sequence start code. */ |
||
1429 | |||
1430 | flush_bits32; |
||
1431 | |||
1432 | /* Get horizontal size of image space. */ |
||
1433 | |||
1434 | get_bits12(data); |
||
1435 | vid_stream->h_size = data; |
||
1436 | |||
1437 | /* Get vertical size of image space. */ |
||
1438 | |||
1439 | get_bits12(data); |
||
1440 | vid_stream->v_size = data; |
||
1441 | |||
1442 | /* Calculate macroblock width and height of image space. */ |
||
1443 | |||
1444 | vid_stream->mb_width = (vid_stream->h_size + 15) / 16; |
||
1445 | vid_stream->mb_height = (vid_stream->v_size + 15) / 16; |
||
1446 | |||
1447 | #ifndef DISABLE_DITHER |
||
1448 | /* If dither type is MBORDERED allocate ditherFlags. */ |
||
1449 | if (ditherType == MBORDERED_DITHER) { |
||
1450 | vid_stream->ditherFlags = |
||
1451 | (char *) malloc(vid_stream->mb_width*vid_stream->mb_height); |
||
1452 | } |
||
1453 | #endif |
||
1454 | |||
1455 | /* |
||
1456 | * Initialize ring buffer of pict images now that dimensions of image space |
||
1457 | * are known. |
||
1458 | */ |
||
1459 | |||
1460 | #ifdef SH_MEM |
||
1461 | if (xinfo->display != NULL) { |
||
1462 | InstallXErrorHandler(xinfo->display); |
||
1463 | } |
||
1464 | #endif |
||
1465 | |||
1466 | if (vid_stream->ring[0] == NULL) { |
||
1467 | for (i = 0; i < RING_BUF_SIZE; i++) { |
||
1468 | vid_stream->ring[i] = NewPictImage(vid_stream,xinfo); |
||
1469 | } |
||
1470 | } |
||
1471 | #ifdef SH_MEM |
||
1472 | if (xinfo->display != NULL) { |
||
1473 | DeInstallXErrorHandler(xinfo->display); |
||
1474 | } |
||
1475 | #endif |
||
1476 | |||
1477 | /* Parse of aspect ratio code. */ |
||
1478 | |||
1479 | get_bits4(data); |
||
1480 | vid_stream->aspect_ratio = (unsigned char) data; |
||
1481 | |||
1482 | /* Parse off picture rate code. */ |
||
1483 | |||
1484 | get_bits4(data); |
||
1485 | vid_stream->picture_rate = (unsigned char) data; |
||
1486 | |||
1487 | /* Parse off bit rate. */ |
||
1488 | |||
1489 | get_bits18(data); |
||
1490 | vid_stream->bit_rate = data; |
||
1491 | |||
1492 | /* Flush marker bit. */ |
||
1493 | |||
1494 | flush_bits(1); |
||
1495 | |||
1496 | /* Parse off vbv buffer size. */ |
||
1497 | |||
1498 | get_bits10(data); |
||
1499 | vid_stream->vbv_buffer_size = data; |
||
1500 | |||
1501 | #ifdef not_def |
||
1502 | /* Lets not bother with this. Only increases memory image */ |
||
1503 | if (data*1024>vid_stream->max_buf_length) { |
||
1504 | unsigned int *newbuf; |
||
1505 | int sz=1024*data+1; |
||
1506 | /* If they actually want a bigger buffer than we default to, |
||
1507 | let them have it! (if we can) */ |
||
1508 | newbuf = (unsigned int *) realloc(vid_stream->buf_start, (unsigned int) 4*sz); |
||
1509 | if (newbuf!=(unsigned int *)NULL) { |
||
1510 | vid_stream->max_buf_length=sz; |
||
1511 | vid_stream->buffer= |
||
1512 | (vid_stream->buffer-vid_stream->buf_start)+newbuf; |
||
1513 | vid_stream->buf_start=newbuf; |
||
1514 | }} |
||
1515 | #endif |
||
1516 | |||
1517 | /* Parse off contrained parameter flag. */ |
||
1518 | |||
1519 | get_bits1(data); |
||
1520 | if (data) { |
||
1521 | vid_stream->const_param_flag = TRUE; |
||
1522 | } else |
||
1523 | vid_stream->const_param_flag = FALSE; |
||
1524 | |||
1525 | /* |
||
1526 | * If intra_quant_matrix_flag set, parse off intra quant matrix values. |
||
1527 | */ |
||
1528 | |||
1529 | get_bits1(data); |
||
1530 | if (data) { |
||
1531 | for (i = 0; i < 64; i++) { |
||
1532 | get_bits8(data); |
||
1533 | |||
1534 | vid_stream->intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] = |
||
1535 | (unsigned char) data; |
||
1536 | } |
||
1537 | } |
||
1538 | /* |
||
1539 | * If non intra quant matrix flag set, parse off non intra quant matrix |
||
1540 | * values. |
||
1541 | */ |
||
1542 | |||
1543 | get_bits1(data); |
||
1544 | if (data) { |
||
1545 | for (i = 0; i < 64; i++) { |
||
1546 | get_bits8(data); |
||
1547 | |||
1548 | vid_stream->non_intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] = |
||
1549 | (unsigned char) data; |
||
1550 | } |
||
1551 | } |
||
1552 | /* Go to next start code. */ |
||
1553 | |||
1554 | next_start_code(vid_stream); |
||
1555 | |||
1556 | /* |
||
1557 | * If next start code is extension start code, parse off extension data. |
||
1558 | */ |
||
1559 | |||
1560 | if (next_bits(32, EXT_START_CODE, vid_stream)) { |
||
1561 | flush_bits32; |
||
1562 | if (vid_stream->ext_data != NULL) { |
||
1563 | free(vid_stream->ext_data); |
||
1564 | vid_stream->ext_data = NULL; |
||
1565 | } |
||
1566 | vid_stream->ext_data = get_ext_data(vid_stream); |
||
1567 | } |
||
1568 | /* If next start code is user start code, parse off user data. */ |
||
1569 | |||
1570 | if (next_bits(32, USER_START_CODE, vid_stream)) { |
||
1571 | flush_bits32; |
||
1572 | if (vid_stream->user_data != NULL) { |
||
1573 | free(vid_stream->user_data); |
||
1574 | vid_stream->user_data = NULL; |
||
1575 | } |
||
1576 | vid_stream->user_data = get_ext_data(vid_stream); |
||
1577 | } |
||
1578 | return PARSE_OK; |
||
1579 | } |
||
1580 | |||
1581 | |||
1582 | |||
1583 | /* |
||
1584 | *-------------------------------------------------------------- |
||
1585 | * |
||
1586 | * ParseGOP -- |
||
1587 | * |
||
1588 | * Parses of group of pictures header from bit stream |
||
1589 | * associated with vid_stream. |
||
1590 | * |
||
1591 | * Results: |
||
1592 | * Values in gop header placed into video stream structure. |
||
1593 | * |
||
1594 | * Side effects: |
||
1595 | * Bit stream irreversibly parsed. |
||
1596 | * |
||
1597 | *-------------------------------------------------------------- |
||
1598 | */ |
||
1599 | |||
1600 | static int |
||
1601 | ParseGOP(vid_stream) |
||
1602 | VidStream *vid_stream; |
||
1603 | { |
||
1604 | unsigned int data; |
||
1605 | |||
1606 | /* Flush group of pictures start code. */ |
||
1607 | |||
1608 | flush_bits32; |
||
1609 | |||
1610 | /* Parse off drop frame flag. */ |
||
1611 | |||
1612 | get_bits1(data); |
||
1613 | if (data) { |
||
1614 | vid_stream->group.drop_flag = TRUE; |
||
1615 | } else |
||
1616 | vid_stream->group.drop_flag = FALSE; |
||
1617 | |||
1618 | /* Parse off hour component of time code. */ |
||
1619 | |||
1620 | get_bits5(data); |
||
1621 | vid_stream->group.tc_hours = data; |
||
1622 | |||
1623 | /* Parse off minute component of time code. */ |
||
1624 | |||
1625 | get_bits6(data); |
||
1626 | vid_stream->group.tc_minutes = data; |
||
1627 | |||
1628 | /* Flush marker bit. */ |
||
1629 | |||
1630 | flush_bits(1); |
||
1631 | |||
1632 | /* Parse off second component of time code. */ |
||
1633 | |||
1634 | get_bits6(data); |
||
1635 | vid_stream->group.tc_seconds = data; |
||
1636 | |||
1637 | /* Parse off picture count component of time code. */ |
||
1638 | |||
1639 | get_bits6(data); |
||
1640 | vid_stream->group.tc_pictures = data; |
||
1641 | |||
1642 | /* Parse off closed gop and broken link flags. */ |
||
1643 | |||
1644 | get_bits2(data); |
||
1645 | if (data > 1) { |
||
1646 | vid_stream->group.closed_gop = TRUE; |
||
1647 | if (data > 2) { |
||
1648 | vid_stream->group.broken_link = TRUE; |
||
1649 | } else |
||
1650 | vid_stream->group.broken_link = FALSE; |
||
1651 | } else { |
||
1652 | vid_stream->group.closed_gop = FALSE; |
||
1653 | if (data) { |
||
1654 | vid_stream->group.broken_link = TRUE; |
||
1655 | } else |
||
1656 | vid_stream->group.broken_link = FALSE; |
||
1657 | } |
||
1658 | |||
1659 | /* Goto next start code. */ |
||
1660 | |||
1661 | next_start_code(vid_stream); |
||
1662 | |||
1663 | /* If next start code is extension data, parse off extension data. */ |
||
1664 | |||
1665 | if (next_bits(32, EXT_START_CODE, vid_stream)) { |
||
1666 | flush_bits32; |
||
1667 | if (vid_stream->group.ext_data != NULL) { |
||
1668 | free(vid_stream->group.ext_data); |
||
1669 | vid_stream->group.ext_data = NULL; |
||
1670 | } |
||
1671 | vid_stream->group.ext_data = get_ext_data(vid_stream); |
||
1672 | } |
||
1673 | /* If next start code is user data, parse off user data. */ |
||
1674 | |||
1675 | if (next_bits(32, USER_START_CODE,vid_stream)) { |
||
1676 | flush_bits32; |
||
1677 | if (vid_stream->group.user_data != NULL) { |
||
1678 | free(vid_stream->group.user_data); |
||
1679 | vid_stream->group.user_data = NULL; |
||
1680 | } |
||
1681 | vid_stream->group.user_data = get_ext_data(vid_stream); |
||
1682 | } |
||
1683 | return PARSE_OK; |
||
1684 | } |
||
1685 | |||
1686 | |||
1687 | |||
1688 | /* |
||
1689 | *-------------------------------------------------------------- |
||
1690 | * |
||
1691 | * ParsePicture -- |
||
1692 | * |
||
1693 | * Parses picture header. Marks picture to be presented |
||
1694 | * at particular time given a time stamp. |
||
1695 | * |
||
1696 | * Results: |
||
1697 | * Values from picture header put into video stream structure. |
||
1698 | * |
||
1699 | * Side effects: |
||
1700 | * Bit stream irreversibly parsed. |
||
1701 | * |
||
1702 | *-------------------------------------------------------------- |
||
1703 | */ |
||
1704 | |||
1705 | static int |
||
1706 | ParsePicture(vid_stream, time_stamp) |
||
1707 | VidStream *vid_stream; |
||
1708 | TimeStamp time_stamp; |
||
1709 | { |
||
1710 | unsigned int data; |
||
1711 | int i; |
||
1712 | |||
1713 | /* Flush header start code. */ |
||
1714 | flush_bits32; |
||
1715 | |||
1716 | /* Parse off temporal reference. */ |
||
1717 | get_bits10(data); |
||
1718 | vid_stream->picture.temp_ref = data; |
||
1719 | |||
1720 | /* Parse of picture type. */ |
||
1721 | get_bits3(data); |
||
1722 | vid_stream->picture.code_type = data; |
||
1723 | |||
1724 | if ((vid_stream->picture.code_type == B_TYPE) && |
||
1725 | (/* No_B_Flag || */ |
||
1726 | (vid_stream->future == NULL) || |
||
1727 | ((vid_stream->past == NULL) && !(vid_stream->group.closed_gop)))) |
||
1728 | /* According to 2-D.5.1 (p D-18) this is ok, if the refereneces are OK */ |
||
1729 | return SKIP_PICTURE; |
||
1730 | |||
1731 | if ((vid_stream->picture.code_type == P_TYPE) && |
||
1732 | (No_P_Flag || (vid_stream->future == NULL))) |
||
1733 | return SKIP_PICTURE; |
||
1734 | |||
1735 | #ifdef ANALYSIS |
||
1736 | StartTime(); |
||
1737 | stat_a[0].frametype = vid_stream->picture.code_type; |
||
1738 | stat_a[0].number = 1; |
||
1739 | stat_a[0].totsize = 45; |
||
1740 | pictureSizeCount = bitCountRead(); |
||
1741 | #endif |
||
1742 | |||
1743 | /* Parse off vbv buffer delay value. */ |
||
1744 | get_bits16(data); |
||
1745 | vid_stream->picture.vbv_delay = data; |
||
1746 | |||
1747 | /* If P or B type frame... */ |
||
1748 | |||
1749 | if ((vid_stream->picture.code_type == P_TYPE) || |
||
1750 | (vid_stream->picture.code_type == B_TYPE)) { |
||
1751 | |||
1752 | /* Parse off forward vector full pixel flag. */ |
||
1753 | get_bits1(data); |
||
1754 | if (data) { |
||
1755 | vid_stream->picture.full_pel_forw_vector = TRUE; |
||
1756 | } else { |
||
1757 | vid_stream->picture.full_pel_forw_vector = FALSE; |
||
1758 | } |
||
1759 | |||
1760 | /* Parse of forw_r_code. */ |
||
1761 | get_bits3(data); |
||
1762 | |||
1763 | /* Decode forw_r_code into forw_r_size and forw_f. */ |
||
1764 | |||
1765 | vid_stream->picture.forw_r_size = data - 1; |
||
1766 | vid_stream->picture.forw_f = (1 << vid_stream->picture.forw_r_size); |
||
1767 | } |
||
1768 | /* If B type frame... */ |
||
1769 | |||
1770 | if (vid_stream->picture.code_type == B_TYPE) { |
||
1771 | |||
1772 | /* Parse off back vector full pixel flag. */ |
||
1773 | get_bits1(data); |
||
1774 | if (data) |
||
1775 | vid_stream->picture.full_pel_back_vector = TRUE; |
||
1776 | else |
||
1777 | vid_stream->picture.full_pel_back_vector = FALSE; |
||
1778 | |||
1779 | /* Parse off back_r_code. */ |
||
1780 | get_bits3(data); |
||
1781 | |||
1782 | /* Decode back_r_code into back_r_size and back_f. */ |
||
1783 | |||
1784 | vid_stream->picture.back_r_size = data - 1; |
||
1785 | vid_stream->picture.back_f = (1 << vid_stream->picture.back_r_size); |
||
1786 | } |
||
1787 | /* Get extra bit picture info. */ |
||
1788 | |||
1789 | if (vid_stream->picture.extra_info != NULL) { |
||
1790 | free(vid_stream->picture.extra_info); |
||
1791 | vid_stream->picture.extra_info = NULL; |
||
1792 | } |
||
1793 | vid_stream->picture.extra_info = get_extra_bit_info(vid_stream); |
||
1794 | |||
1795 | /* Goto next start code. */ |
||
1796 | next_start_code(vid_stream); |
||
1797 | |||
1798 | /* If start code is extension start code, parse off extension data. */ |
||
1799 | |||
1800 | if (next_bits(32, EXT_START_CODE, vid_stream)) { |
||
1801 | flush_bits32; |
||
1802 | |||
1803 | if (vid_stream->picture.ext_data != NULL) { |
||
1804 | free(vid_stream->picture.ext_data); |
||
1805 | vid_stream->picture.ext_data = NULL; |
||
1806 | } |
||
1807 | vid_stream->picture.ext_data = get_ext_data(vid_stream); |
||
1808 | } |
||
1809 | /* If start code is user start code, parse off user data. */ |
||
1810 | |||
1811 | if (next_bits(32, USER_START_CODE, vid_stream)) { |
||
1812 | flush_bits32; |
||
1813 | |||
1814 | if (vid_stream->picture.user_data != NULL) { |
||
1815 | free(vid_stream->picture.user_data); |
||
1816 | vid_stream->picture.user_data = NULL; |
||
1817 | } |
||
1818 | vid_stream->picture.user_data = get_ext_data(vid_stream); |
||
1819 | } |
||
1820 | /* Find a pict image structure in ring buffer not currently locked. */ |
||
1821 | |||
1822 | i = 0; |
||
1823 | |||
1824 | while (vid_stream->ring[i]->locked != 0) { |
||
1825 | if (++i >= RING_BUF_SIZE) { |
||
1826 | perror("Fatal error. Ring buffer full."); |
||
1827 | exit(1); |
||
1828 | } |
||
1829 | } |
||
1830 | |||
1831 | /* Set current pict image structure to the one just found in ring. */ |
||
1832 | |||
1833 | vid_stream->current = vid_stream->ring[i]; |
||
1834 | |||
1835 | /* Set time stamp. */ |
||
1836 | |||
1837 | vid_stream->current->show_time = time_stamp; |
||
1838 | |||
1839 | /* Reset past macroblock address field. */ |
||
1840 | |||
1841 | vid_stream->mblock.past_mb_addr = -1; |
||
1842 | |||
1843 | return PARSE_OK; |
||
1844 | } |
||
1845 | |||
1846 | |||
1847 | |||
1848 | /* |
||
1849 | *-------------------------------------------------------------- |
||
1850 | * |
||
1851 | * ParseSlice -- |
||
1852 | * |
||
1853 | * Parses off slice header. |
||
1854 | * |
||
1855 | * Results: |
||
1856 | * Values found in slice header put into video stream structure. |
||
1857 | * |
||
1858 | * Side effects: |
||
1859 | * Bit stream irreversibly parsed. |
||
1860 | * |
||
1861 | *-------------------------------------------------------------- |
||
1862 | */ |
||
1863 | |||
1864 | static int |
||
1865 | ParseSlice(vid_stream) |
||
1866 | VidStream *vid_stream; |
||
1867 | { |
||
1868 | unsigned int data; |
||
1869 | |||
1870 | /* Flush slice start code. */ |
||
1871 | |||
1872 | flush_bits(24); |
||
1873 | |||
1874 | /* Parse off slice vertical position. */ |
||
1875 | |||
1876 | get_bits8(data); |
||
1877 | vid_stream->slice.vert_pos = data; |
||
1878 | |||
1879 | /* Parse off quantization scale. */ |
||
1880 | |||
1881 | get_bits5(data); |
||
1882 | vid_stream->slice.quant_scale = data; |
||
1883 | |||
1884 | /* Parse off extra bit slice info. */ |
||
1885 | |||
1886 | if (vid_stream->slice.extra_info != NULL) { |
||
1887 | free(vid_stream->slice.extra_info); |
||
1888 | vid_stream->slice.extra_info = NULL; |
||
1889 | } |
||
1890 | vid_stream->slice.extra_info = get_extra_bit_info(vid_stream); |
||
1891 | |||
1892 | /* Reset past intrablock address. */ |
||
1893 | |||
1894 | vid_stream->mblock.past_intra_addr = -2; |
||
1895 | |||
1896 | /* Reset previous recon motion vectors. */ |
||
1897 | |||
1898 | vid_stream->mblock.recon_right_for_prev = 0; |
||
1899 | vid_stream->mblock.recon_down_for_prev = 0; |
||
1900 | vid_stream->mblock.recon_right_back_prev = 0; |
||
1901 | vid_stream->mblock.recon_down_back_prev = 0; |
||
1902 | |||
1903 | /* Reset macroblock address. */ |
||
1904 | |||
1905 | vid_stream->mblock.mb_address = ((vid_stream->slice.vert_pos - 1) * |
||
1906 | vid_stream->mb_width) - 1; |
||
1907 | |||
1908 | /* Reset past dct dc y, cr, and cb values. */ |
||
1909 | |||
1910 | vid_stream->block.dct_dc_y_past = 1024 << 3; |
||
1911 | vid_stream->block.dct_dc_cr_past = 1024 << 3; |
||
1912 | vid_stream->block.dct_dc_cb_past = 1024 << 3; |
||
1913 | |||
1914 | return PARSE_OK; |
||
1915 | } |
||
1916 | |||
1917 | |||
1918 | |||
1919 | /* |
||
1920 | *-------------------------------------------------------------- |
||
1921 | * |
||
1922 | * ParseMacroBlock -- |
||
1923 | * |
||
1924 | * Parseoff macroblock. Reconstructs DCT values. Applies |
||
1925 | * inverse DCT, reconstructs motion vectors, calculates and |
||
1926 | * set pixel values for macroblock in current pict image |
||
1927 | * structure. |
||
1928 | * |
||
1929 | * Results: |
||
1930 | * Here's where everything really happens. Welcome to the |
||
1931 | * heart of darkness. |
||
1932 | * |
||
1933 | * Side effects: |
||
1934 | * Bit stream irreversibly parsed off. |
||
1935 | * |
||
1936 | *-------------------------------------------------------------- |
||
1937 | */ |
||
1938 | |||
1939 | static int |
||
1940 | ParseMacroBlock(vid_stream) |
||
1941 | VidStream *vid_stream; |
||
1942 | { |
||
1943 | int addr_incr; |
||
1944 | unsigned int data; |
||
1945 | int mask, i, recon_right_for, recon_down_for, recon_right_back, |
||
1946 | recon_down_back; |
||
1947 | int zero_block_flag; |
||
1948 | BOOLEAN mb_quant = 0, mb_motion_forw = 0, mb_motion_back = 0, |
||
1949 | mb_pattern = 0; |
||
1950 | int no_dith_flag = 0; |
||
1951 | int ditherType = vid_stream->ditherType; |
||
1952 | |||
1953 | #ifdef ANALYSIS |
||
1954 | mbSizeCount = bitCountRead(); |
||
1955 | #endif |
||
1956 | |||
1957 | /* |
||
1958 | * Parse off macroblock address increment and add to macroblock address. |
||
1959 | */ |
||
1960 | do { |
||
1961 | unsigned int ind; |
||
1962 | show_bits11(ind); |
||
1963 | DecodeMBAddrInc(addr_incr); |
||
1964 | if (mb_addr_inc[ind].num_bits==0) { |
||
1965 | addr_incr = 1; |
||
1966 | } |
||
1967 | if (addr_incr == MB_ESCAPE) { |
||
1968 | vid_stream->mblock.mb_address += 33; |
||
1969 | addr_incr = MB_STUFFING; |
||
1970 | } |
||
1971 | } while (addr_incr == MB_STUFFING); |
||
1972 | vid_stream->mblock.mb_address += addr_incr; |
||
1973 | |||
1974 | if (vid_stream->mblock.mb_address > (vid_stream->mb_height * |
||
1975 | vid_stream->mb_width - 1)) |
||
1976 | return SKIP_TO_START_CODE; |
||
1977 | |||
1978 | /* |
||
1979 | * If macroblocks have been skipped, process skipped macroblocks. |
||
1980 | */ |
||
1981 | |||
1982 | if (vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr > 1) { |
||
1983 | if (vid_stream->picture.code_type == P_TYPE) |
||
1984 | ProcessSkippedPFrameMBlocks(vid_stream); |
||
1985 | else if (vid_stream->picture.code_type == B_TYPE) |
||
1986 | ProcessSkippedBFrameMBlocks(vid_stream); |
||
1987 | } |
||
1988 | /* Set past macroblock address to current macroblock address. */ |
||
1989 | vid_stream->mblock.past_mb_addr = vid_stream->mblock.mb_address; |
||
1990 | |||
1991 | /* Based on picture type decode macroblock type. */ |
||
1992 | switch (vid_stream->picture.code_type) { |
||
1993 | case I_TYPE: |
||
1994 | DecodeMBTypeI(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern, |
||
1995 | vid_stream->mblock.mb_intra); |
||
1996 | break; |
||
1997 | |||
1998 | case P_TYPE: |
||
1999 | DecodeMBTypeP(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern, |
||
2000 | vid_stream->mblock.mb_intra); |
||
2001 | break; |
||
2002 | |||
2003 | case B_TYPE: |
||
2004 | DecodeMBTypeB(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern, |
||
2005 | vid_stream->mblock.mb_intra); |
||
2006 | break; |
||
2007 | case D_TYPE: |
||
2008 | fprintf(stderr, "ERROR: MPEG-1 Streams with D-frames are not supported\n"); |
||
2009 | exit(1); |
||
2010 | } |
||
2011 | |||
2012 | /* If quantization flag set, parse off new quantization scale. */ |
||
2013 | |||
2014 | if (mb_quant == TRUE) { |
||
2015 | get_bits5(data); |
||
2016 | vid_stream->slice.quant_scale = data; |
||
2017 | } |
||
2018 | /* If forward motion vectors exist... */ |
||
2019 | if (mb_motion_forw == TRUE) { |
||
2020 | |||
2021 | /* Parse off and decode horizontal forward motion vector. */ |
||
2022 | DecodeMotionVectors(vid_stream->mblock.motion_h_forw_code); |
||
2023 | |||
2024 | /* If horiz. forward r data exists, parse off. */ |
||
2025 | |||
2026 | if ((vid_stream->picture.forw_f != 1) && |
||
2027 | (vid_stream->mblock.motion_h_forw_code != 0)) { |
||
2028 | get_bitsn(vid_stream->picture.forw_r_size, data); |
||
2029 | vid_stream->mblock.motion_h_forw_r = data; |
||
2030 | } |
||
2031 | /* Parse off and decode vertical forward motion vector. */ |
||
2032 | DecodeMotionVectors(vid_stream->mblock.motion_v_forw_code); |
||
2033 | |||
2034 | /* If vert. forw. r data exists, parse off. */ |
||
2035 | |||
2036 | if ((vid_stream->picture.forw_f != 1) && |
||
2037 | (vid_stream->mblock.motion_v_forw_code != 0)) { |
||
2038 | get_bitsn(vid_stream->picture.forw_r_size, data); |
||
2039 | vid_stream->mblock.motion_v_forw_r = data; |
||
2040 | } |
||
2041 | } |
||
2042 | /* If back motion vectors exist... */ |
||
2043 | if (mb_motion_back == TRUE) { |
||
2044 | |||
2045 | /* Parse off and decode horiz. back motion vector. */ |
||
2046 | DecodeMotionVectors(vid_stream->mblock.motion_h_back_code); |
||
2047 | |||
2048 | /* If horiz. back r data exists, parse off. */ |
||
2049 | |||
2050 | if ((vid_stream->picture.back_f != 1) && |
||
2051 | (vid_stream->mblock.motion_h_back_code != 0)) { |
||
2052 | get_bitsn(vid_stream->picture.back_r_size, data); |
||
2053 | vid_stream->mblock.motion_h_back_r = data; |
||
2054 | } |
||
2055 | /* Parse off and decode vert. back motion vector. */ |
||
2056 | DecodeMotionVectors(vid_stream->mblock.motion_v_back_code); |
||
2057 | |||
2058 | /* If vert. back r data exists, parse off. */ |
||
2059 | |||
2060 | if ((vid_stream->picture.back_f != 1) && |
||
2061 | (vid_stream->mblock.motion_v_back_code != 0)) { |
||
2062 | get_bitsn(vid_stream->picture.back_r_size, data); |
||
2063 | vid_stream->mblock.motion_v_back_r = data; |
||
2064 | } |
||
2065 | } |
||
2066 | #ifdef ANALYSIS |
||
2067 | if (vid_stream->mblock.mb_intra) { |
||
2068 | stat_a[0].i_mbnum++; |
||
2069 | mbCBPPtr = stat_a[0].i_mbcbp; |
||
2070 | mbCoeffPtr = stat_a[0].i_mbcoeff; |
||
2071 | mbSizePtr = &(stat_a[0].i_mbsize); |
||
2072 | } else if (mb_motion_back && mb_motion_forw) { |
||
2073 | stat_a[0].bi_mbnum++; |
||
2074 | mbCBPPtr = stat_a[0].bi_mbcbp; |
||
2075 | mbCoeffPtr = stat_a[0].bi_mbcoeff; |
||
2076 | mbSizePtr = &(stat_a[0].bi_mbsize); |
||
2077 | } else if (mb_motion_back) { |
||
2078 | stat_a[0].b_mbnum++; |
||
2079 | mbCBPPtr = stat_a[0].b_mbcbp; |
||
2080 | mbCoeffPtr = stat_a[0].b_mbcoeff; |
||
2081 | mbSizePtr = &(stat_a[0].b_mbsize); |
||
2082 | } else { |
||
2083 | stat_a[0].p_mbnum++; |
||
2084 | mbCBPPtr = stat_a[0].p_mbcbp; |
||
2085 | mbCoeffPtr = stat_a[0].p_mbcoeff; |
||
2086 | mbSizePtr = &(stat_a[0].p_mbsize); |
||
2087 | } |
||
2088 | #endif |
||
2089 | |||
2090 | /* If mblock pattern flag set, parse and decode CBP (code block pattern). */ |
||
2091 | if (mb_pattern == TRUE) { |
||
2092 | DecodeCBP(vid_stream->mblock.cbp); |
||
2093 | } |
||
2094 | /* Otherwise, set CBP to zero. */ |
||
2095 | else |
||
2096 | vid_stream->mblock.cbp = 0; |
||
2097 | |||
2098 | |||
2099 | #ifdef ANALYSIS |
||
2100 | mbCBPPtr[vid_stream->mblock.cbp]++; |
||
2101 | #endif |
||
2102 | |||
2103 | /* Reconstruct motion vectors depending on picture type. */ |
||
2104 | if (vid_stream->picture.code_type == P_TYPE) { |
||
2105 | |||
2106 | /* |
||
2107 | * If no forw motion vectors, reset previous and current vectors to 0. |
||
2108 | */ |
||
2109 | |||
2110 | if (!mb_motion_forw) { |
||
2111 | recon_right_for = 0; |
||
2112 | recon_down_for = 0; |
||
2113 | vid_stream->mblock.recon_right_for_prev = 0; |
||
2114 | vid_stream->mblock.recon_down_for_prev = 0; |
||
2115 | } |
||
2116 | /* |
||
2117 | * Otherwise, compute new forw motion vectors. Reset previous vectors to |
||
2118 | * current vectors. |
||
2119 | */ |
||
2120 | |||
2121 | else { |
||
2122 | ComputeForwVector(&recon_right_for, &recon_down_for, vid_stream); |
||
2123 | } |
||
2124 | } |
||
2125 | if (vid_stream->picture.code_type == B_TYPE) { |
||
2126 | |||
2127 | /* Reset prev. and current vectors to zero if mblock is intracoded. */ |
||
2128 | |||
2129 | if (vid_stream->mblock.mb_intra) { |
||
2130 | vid_stream->mblock.recon_right_for_prev = 0; |
||
2131 | vid_stream->mblock.recon_down_for_prev = 0; |
||
2132 | vid_stream->mblock.recon_right_back_prev = 0; |
||
2133 | vid_stream->mblock.recon_down_back_prev = 0; |
||
2134 | } else { |
||
2135 | |||
2136 | /* If no forw vectors, current vectors equal prev. vectors. */ |
||
2137 | |||
2138 | if (!mb_motion_forw) { |
||
2139 | recon_right_for = vid_stream->mblock.recon_right_for_prev; |
||
2140 | recon_down_for = vid_stream->mblock.recon_down_for_prev; |
||
2141 | } |
||
2142 | /* |
||
2143 | * Otherwise compute forw. vectors. Reset prev vectors to new values. |
||
2144 | */ |
||
2145 | |||
2146 | else { |
||
2147 | ComputeForwVector(&recon_right_for, &recon_down_for, vid_stream); |
||
2148 | } |
||
2149 | |||
2150 | /* If no back vectors, set back vectors to prev back vectors. */ |
||
2151 | |||
2152 | if (!mb_motion_back) { |
||
2153 | recon_right_back = vid_stream->mblock.recon_right_back_prev; |
||
2154 | recon_down_back = vid_stream->mblock.recon_down_back_prev; |
||
2155 | } |
||
2156 | /* Otherwise compute new vectors and reset prev. back vectors. */ |
||
2157 | |||
2158 | else { |
||
2159 | ComputeBackVector(&recon_right_back, &recon_down_back, vid_stream); |
||
2160 | } |
||
2161 | |||
2162 | /* |
||
2163 | * Store vector existence flags in structure for possible skipped |
||
2164 | * macroblocks to follow. |
||
2165 | */ |
||
2166 | |||
2167 | vid_stream->mblock.bpict_past_forw = mb_motion_forw; |
||
2168 | vid_stream->mblock.bpict_past_back = mb_motion_back; |
||
2169 | } |
||
2170 | } |
||
2171 | |||
2172 | #ifndef DISABLE_DITHER |
||
2173 | /* For each possible block in macroblock. */ |
||
2174 | if (ditherType == GRAY_DITHER || |
||
2175 | ditherType == GRAY2_DITHER || |
||
2176 | ditherType == GRAY256_DITHER || |
||
2177 | ditherType == GRAY2562_DITHER || |
||
2178 | ditherType == MONO_DITHER || |
||
2179 | ditherType == MONO_THRESHOLD) { |
||
2180 | for (mask = 32, i = 0; i < 4; mask >>= 1, i++) { |
||
2181 | |||
2182 | /* If block exists... */ |
||
2183 | if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) { |
||
2184 | zero_block_flag = 0; |
||
2185 | ParseReconBlock(i, vid_stream); |
||
2186 | } else { |
||
2187 | zero_block_flag = 1; |
||
2188 | } |
||
2189 | |||
2190 | /* If macroblock is intra coded... */ |
||
2191 | if (vid_stream->mblock.mb_intra) { |
||
2192 | ReconIMBlock(vid_stream, i); |
||
2193 | } else if (mb_motion_forw && mb_motion_back) { |
||
2194 | ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for, |
||
2195 | recon_right_back, recon_down_back, zero_block_flag); |
||
2196 | } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) { |
||
2197 | ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for, |
||
2198 | zero_block_flag); |
||
2199 | } else if (mb_motion_back) { |
||
2200 | ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back, |
||
2201 | zero_block_flag); |
||
2202 | } |
||
2203 | } |
||
2204 | /* Kill the Chrominance blocks... */ |
||
2205 | if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x2)) { |
||
2206 | ParseAwayBlock(4, vid_stream); |
||
2207 | } |
||
2208 | if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x1)) { |
||
2209 | ParseAwayBlock(5, vid_stream); |
||
2210 | } |
||
2211 | } else { |
||
2212 | if ((ditherType == MBORDERED_DITHER) && |
||
2213 | (vid_stream->mblock.cbp == 0) && |
||
2214 | (vid_stream->picture.code_type == 3) && |
||
2215 | (!vid_stream->mblock.mb_intra) && |
||
2216 | (!(mb_motion_forw && mb_motion_back))) { |
||
2217 | MBOrderedDitherDisplayCopy(vid_stream, vid_stream->mblock.mb_address, |
||
2218 | mb_motion_forw, recon_right_for, recon_down_for, |
||
2219 | mb_motion_back, recon_right_back, recon_down_back, |
||
2220 | vid_stream->past->display, vid_stream->future->display); |
||
2221 | vid_stream->ditherFlags[vid_stream->mblock.mb_address] = 0; |
||
2222 | no_dith_flag = 1; |
||
2223 | } |
||
2224 | else { |
||
2225 | #endif |
||
2226 | for (mask = 32, i = 0; i < 6; mask >>= 1, i++) { |
||
2227 | |||
2228 | /* If block exists... */ |
||
2229 | if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) { |
||
2230 | zero_block_flag = 0; |
||
2231 | ParseReconBlock(i, vid_stream); |
||
2232 | } else { |
||
2233 | zero_block_flag = 1; |
||
2234 | } |
||
2235 | |||
2236 | /* If macroblock is intra coded... */ |
||
2237 | if (vid_stream->mblock.mb_intra) { |
||
2238 | ReconIMBlock(vid_stream, i); |
||
2239 | } else if (mb_motion_forw && mb_motion_back) { |
||
2240 | ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for, |
||
2241 | recon_right_back, recon_down_back, zero_block_flag); |
||
2242 | } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) { |
||
2243 | ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for, |
||
2244 | zero_block_flag); |
||
2245 | } else if (mb_motion_back) { |
||
2246 | ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back, |
||
2247 | zero_block_flag); |
||
2248 | } |
||
2249 | } |
||
2250 | #ifndef DISABLE_DITHER |
||
2251 | } |
||
2252 | } |
||
2253 | #endif |
||
2254 | |||
2255 | #ifndef DISABLE_DITHER |
||
2256 | if ((ditherType == MBORDERED_DITHER) && (!no_dith_flag)) { |
||
2257 | if ((vid_stream->picture.code_type == 2) && |
||
2258 | (vid_stream->mblock.cbp == 0) && |
||
2259 | (!vid_stream->mblock.mb_intra)) { |
||
2260 | MBOrderedDitherDisplayCopy(vid_stream, vid_stream->mblock.mb_address, |
||
2261 | 1, recon_right_for, recon_down_for, |
||
2262 | 0, 0, 0, |
||
2263 | vid_stream->future->display, |
||
2264 | (unsigned char *) NULL); |
||
2265 | vid_stream->ditherFlags[vid_stream->mblock.mb_address] = 0; |
||
2266 | } |
||
2267 | else { |
||
2268 | vid_stream->ditherFlags[vid_stream->mblock.mb_address] = 1; |
||
2269 | } |
||
2270 | } |
||
2271 | #endif |
||
2272 | |||
2273 | /* If D Type picture, flush marker bit. */ |
||
2274 | if (vid_stream->picture.code_type == 4) |
||
2275 | flush_bits(1); |
||
2276 | |||
2277 | /* If macroblock was intracoded, set macroblock past intra address. */ |
||
2278 | if (vid_stream->mblock.mb_intra) |
||
2279 | vid_stream->mblock.past_intra_addr = |
||
2280 | vid_stream->mblock.mb_address; |
||
2281 | |||
2282 | #ifdef ANALYSIS |
||
2283 | *mbSizePtr += bitCountRead() - mbSizeCount; |
||
2284 | #endif |
||
2285 | return PARSE_OK; |
||
2286 | } |
||
2287 | |||
2288 | |||
2289 | |||
2290 | /* |
||
2291 | *-------------------------------------------------------------- |
||
2292 | * |
||
2293 | * ReconIMBlock -- |
||
2294 | * |
||
2295 | * Reconstructs intra coded macroblock. |
||
2296 | * |
||
2297 | * Results: |
||
2298 | * None. |
||
2299 | * |
||
2300 | * Side effects: |
||
2301 | * None. |
||
2302 | * |
||
2303 | *-------------------------------------------------------------- |
||
2304 | */ |
||
2305 | #ifndef NDEBUG |
||
2306 | /* If people really want to see such things, check 'em */ |
||
2307 | #define myassert(x,expression)\ |
||
2308 | if (!(expression)) {\ |
||
2309 | fprintf (stderr,"Bad crop value (%d) at line %d\n", x, __LINE__);\ |
||
2310 | next_start_code(vid_stream); return;} |
||
2311 | #define assertCrop(x) myassert(x,((x) >= -MAX_NEG_CROP) && \ |
||
2312 | ((x) <= 2048+MAX_NEG_CROP)) |
||
2313 | #else |
||
2314 | #define assertCrop(x) |
||
2315 | #endif |
||
2316 | |||
2317 | static void |
||
2318 | ReconIMBlock(vid_stream, bnum) |
||
2319 | VidStream *vid_stream; |
||
2320 | int bnum; |
||
2321 | { |
||
2322 | int mb_row, mb_col, row, col, row_size, rr; |
||
2323 | unsigned char *dest; |
||
2324 | |||
2325 | /* Calculate macroblock row and column from address. */ |
||
2326 | |||
2327 | mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width; |
||
2328 | mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width; |
||
2329 | |||
2330 | |||
2331 | /* If block is luminance block... */ |
||
2332 | |||
2333 | if (bnum < 4) { |
||
2334 | |||
2335 | /* Calculate row and col values for upper left pixel of block. */ |
||
2336 | |||
2337 | row = mb_row * 16; |
||
2338 | col = mb_col * 16; |
||
2339 | if (bnum > 1) |
||
2340 | row += 8; |
||
2341 | if (bnum % 2) |
||
2342 | col += 8; |
||
2343 | |||
2344 | /* Set dest to luminance plane of current pict image. */ |
||
2345 | |||
2346 | dest = vid_stream->current->luminance; |
||
2347 | |||
2348 | /* Establish row size. */ |
||
2349 | |||
2350 | row_size = vid_stream->mb_width * 16; |
||
2351 | } |
||
2352 | /* Otherwise if block is Cr block... */ |
||
2353 | /* Cr first because of the earlier mixup */ |
||
2354 | |||
2355 | else if (bnum == 5) { |
||
2356 | |||
2357 | /* Set dest to Cr plane of current pict image. */ |
||
2358 | |||
2359 | dest = vid_stream->current->Cr; |
||
2360 | |||
2361 | /* Establish row size. */ |
||
2362 | |||
2363 | row_size = vid_stream->mb_width * 8; |
||
2364 | |||
2365 | /* Calculate row,col for upper left pixel of block. */ |
||
2366 | |||
2367 | row = mb_row * 8; |
||
2368 | col = mb_col * 8; |
||
2369 | } |
||
2370 | /* Otherwise block is Cb block, and ... */ |
||
2371 | |||
2372 | else { |
||
2373 | |||
2374 | /* Set dest to Cb plane of current pict image. */ |
||
2375 | |||
2376 | dest = vid_stream->current->Cb; |
||
2377 | |||
2378 | /* Establish row size. */ |
||
2379 | |||
2380 | row_size = vid_stream->mb_width * 8; |
||
2381 | |||
2382 | /* Calculate row,col for upper left pixel value of block. */ |
||
2383 | |||
2384 | row = mb_row * 8; |
||
2385 | col = mb_col * 8; |
||
2386 | } |
||
2387 | |||
2388 | /* |
||
2389 | * For each pixel in block, set to cropped reconstructed value from inverse |
||
2390 | * dct. |
||
2391 | */ |
||
2392 | { |
||
2393 | short *sp = &vid_stream->block.dct_recon[0][0]; |
||
2394 | unsigned char *cm = cropTbl + MAX_NEG_CROP; |
||
2395 | dest += row * row_size + col; |
||
2396 | for (rr = 0; rr < 4; rr++, sp += 16, dest += row_size) { |
||
2397 | dest[0] = cm[sp[0]]; |
||
2398 | assertCrop(sp[0]); |
||
2399 | dest[1] = cm[sp[1]]; |
||
2400 | assertCrop(sp[1]); |
||
2401 | dest[2] = cm[sp[2]]; |
||
2402 | assertCrop(sp[2]); |
||
2403 | dest[3] = cm[sp[3]]; |
||
2404 | assertCrop(sp[3]); |
||
2405 | dest[4] = cm[sp[4]]; |
||
2406 | assertCrop(sp[4]); |
||
2407 | dest[5] = cm[sp[5]]; |
||
2408 | assertCrop(sp[5]); |
||
2409 | dest[6] = cm[sp[6]]; |
||
2410 | assertCrop(sp[6]); |
||
2411 | dest[7] = cm[sp[7]]; |
||
2412 | assertCrop(sp[7]); |
||
2413 | |||
2414 | dest += row_size; |
||
2415 | dest[0] = cm[sp[8]]; |
||
2416 | assertCrop(sp[8]); |
||
2417 | dest[1] = cm[sp[9]]; |
||
2418 | assertCrop(sp[9]); |
||
2419 | dest[2] = cm[sp[10]]; |
||
2420 | assertCrop(sp[10]); |
||
2421 | dest[3] = cm[sp[11]]; |
||
2422 | assertCrop(sp[11]); |
||
2423 | dest[4] = cm[sp[12]]; |
||
2424 | assertCrop(sp[12]); |
||
2425 | dest[5] = cm[sp[13]]; |
||
2426 | assertCrop(sp[13]); |
||
2427 | dest[6] = cm[sp[14]]; |
||
2428 | assertCrop(sp[14]); |
||
2429 | dest[7] = cm[sp[15]]; |
||
2430 | assertCrop(sp[15]); |
||
2431 | } |
||
2432 | } |
||
2433 | } |
||
2434 | |||
2435 | |||
2436 | |||
2437 | /* |
||
2438 | *-------------------------------------------------------------- |
||
2439 | * |
||
2440 | * ReconPMBlock -- |
||
2441 | * |
||
2442 | * Reconstructs forward predicted macroblocks. |
||
2443 | * |
||
2444 | * Results: |
||
2445 | * None. |
||
2446 | * |
||
2447 | * Side effects: |
||
2448 | * None. |
||
2449 | * |
||
2450 | *-------------------------------------------------------------- |
||
2451 | */ |
||
2452 | |||
2453 | static void |
||
2454 | ReconPMBlock(vid_stream, bnum, recon_right_for, recon_down_for, zflag) |
||
2455 | VidStream *vid_stream; |
||
2456 | int bnum, recon_right_for, recon_down_for, zflag; |
||
2457 | { |
||
2458 | int mb_row, mb_col, row, col, row_size, rr; |
||
2459 | unsigned char *dest, *past; |
||
2460 | unsigned char *rindex1, *rindex2, *rindex3, *rindex4; |
||
2461 | unsigned char *index; |
||
2462 | short int *blockvals; |
||
2463 | |||
2464 | #ifdef LOOSE_MPEG |
||
2465 | int maxx, maxy, cc; |
||
2466 | int illegalBlock = 0; |
||
2467 | int row_start, row_end, rfirst, rlast, col_start, col_end, cfirst, clast; |
||
2468 | #endif |
||
2469 | |||
2470 | /* Calculate macroblock row and column from address. */ |
||
2471 | |||
2472 | mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width; |
||
2473 | mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width; |
||
2474 | |||
2475 | if (bnum < 4) { |
||
2476 | |||
2477 | /* Calculate right_for, down_for motion vectors. */ |
||
2478 | |||
2479 | vid_stream->right_for = recon_right_for >> 1; |
||
2480 | vid_stream->down_for = recon_down_for >> 1; |
||
2481 | vid_stream->right_half_for = recon_right_for & 0x1; |
||
2482 | vid_stream->down_half_for = recon_down_for & 0x1; |
||
2483 | |||
2484 | /* Set dest to luminance plane of current pict image. */ |
||
2485 | |||
2486 | dest = vid_stream->current->luminance; |
||
2487 | |||
2488 | if (vid_stream->picture.code_type == B_TYPE) { |
||
2489 | if (vid_stream->past != NULL) |
||
2490 | past = vid_stream->past->luminance; |
||
2491 | } else { |
||
2492 | |||
2493 | /* Set predictive frame to current future frame. */ |
||
2494 | |||
2495 | if (vid_stream->future != NULL) |
||
2496 | past = vid_stream->future->luminance; |
||
2497 | } |
||
2498 | |||
2499 | /* Establish row size. */ |
||
2500 | |||
2501 | row_size = vid_stream->mb_width << 4; |
||
2502 | |||
2503 | /* Calculate row,col of upper left pixel in block. */ |
||
2504 | |||
2505 | row = mb_row << 4; |
||
2506 | col = mb_col << 4; |
||
2507 | if (bnum > 1) |
||
2508 | row += 8; |
||
2509 | if (bnum % 2) |
||
2510 | col += 8; |
||
2511 | |||
2512 | #ifdef LOOSE_MPEG |
||
2513 | /* Check for block illegality. */ |
||
2514 | |||
2515 | maxx = vid_stream->mb_width*16-1; |
||
2516 | maxy = vid_stream->mb_height*16-1; |
||
2517 | |||
2518 | if (row + vid_stream->down_for + 7 > maxy) illegalBlock |= 0x4; |
||
2519 | else if (row + vid_stream->down_for < 0) illegalBlock |= 0x1; |
||
2520 | |||
2521 | if (col + vid_stream->right_for + 7 > maxx) illegalBlock |= 0x2; |
||
2522 | else if (col + vid_stream->right_for < 0) illegalBlock |= 0x8; |
||
2523 | |||
2524 | #endif |
||
2525 | } |
||
2526 | /* Otherwise, block is NOT luminance block, ... */ |
||
2527 | |||
2528 | else { |
||
2529 | |||
2530 | /* Construct motion vectors. */ |
||
2531 | |||
2532 | recon_right_for /= 2; |
||
2533 | recon_down_for /= 2; |
||
2534 | vid_stream->right_for = recon_right_for >> 1; |
||
2535 | vid_stream->down_for = recon_down_for >> 1; |
||
2536 | vid_stream->right_half_for = recon_right_for & 0x1; |
||
2537 | vid_stream->down_half_for = recon_down_for & 0x1; |
||
2538 | |||
2539 | /* Establish row size. */ |
||
2540 | |||
2541 | row_size = vid_stream->mb_width << 3; |
||
2542 | |||
2543 | /* Calculate row,col of upper left pixel in block. */ |
||
2544 | |||
2545 | row = mb_row << 3; |
||
2546 | col = mb_col << 3; |
||
2547 | |||
2548 | #ifdef LOOSE_MPEG |
||
2549 | /* Check for block illegality. */ |
||
2550 | |||
2551 | maxx = vid_stream->mb_width*16-1; |
||
2552 | maxy = vid_stream->mb_height*16-1; |
||
2553 | |||
2554 | if (row + vid_stream->down_for + 7 > maxy) illegalBlock |= 0x4; |
||
2555 | else if (row + vid_stream->down_for < 0) illegalBlock |= 0x1; |
||
2556 | |||
2557 | if (col + vid_stream->right_for + 7 > maxx) illegalBlock |= 0x2; |
||
2558 | else if (col + vid_stream->right_for < 0) illegalBlock |= 0x8; |
||
2559 | |||
2560 | #endif |
||
2561 | |||
2562 | /* If block is Cr block... */ |
||
2563 | /* 5 first because order was mixed up in earlier versions */ |
||
2564 | |||
2565 | if (bnum == 5) { |
||
2566 | |||
2567 | /* Set dest to Cr plane of current pict image. */ |
||
2568 | |||
2569 | dest = vid_stream->current->Cr; |
||
2570 | |||
2571 | if (vid_stream->picture.code_type == B_TYPE) { |
||
2572 | |||
2573 | if (vid_stream->past != NULL) |
||
2574 | past = vid_stream->past->Cr; |
||
2575 | } else { |
||
2576 | if (vid_stream->future != NULL) |
||
2577 | past = vid_stream->future->Cr; |
||
2578 | } |
||
2579 | } |
||
2580 | /* Otherwise, block is Cb block... */ |
||
2581 | |||
2582 | else { |
||
2583 | |||
2584 | /* Set dest to Cb plane of current pict image. */ |
||
2585 | |||
2586 | dest = vid_stream->current->Cb; |
||
2587 | |||
2588 | if (vid_stream->picture.code_type == B_TYPE) { |
||
2589 | if (vid_stream->past != NULL) |
||
2590 | past = vid_stream->past->Cb; |
||
2591 | } else { |
||
2592 | if (vid_stream->future != NULL) |
||
2593 | past = vid_stream->future->Cb; |
||
2594 | } |
||
2595 | } |
||
2596 | } |
||
2597 | |||
2598 | /* For each pixel in block... */ |
||
2599 | |||
2600 | #ifdef LOOSE_MPEG |
||
2601 | |||
2602 | if (illegalBlock) { |
||
2603 | if (illegalBlock & 0x1) { |
||
2604 | row_start = 0; |
||
2605 | row_end = row+vid_stream->down_for+8; |
||
2606 | rfirst = rlast = 8 - row_end; |
||
2607 | } |
||
2608 | else if (illegalBlock & 0x4) { |
||
2609 | row_start = row + vid_stream->down_for; |
||
2610 | row_end = maxy+1; |
||
2611 | rlast = row_end - row_start - 1; |
||
2612 | rfirst = 0; |
||
2613 | } |
||
2614 | else { |
||
2615 | row_start = row+vid_stream->down_for; |
||
2616 | row_end = row_start+8; |
||
2617 | rfirst = 0; |
||
2618 | } |
||
2619 | |||
2620 | if (illegalBlock & 0x8) { |
||
2621 | col_start = 0; |
||
2622 | col_end = col + vid_stream->right_for + 8; |
||
2623 | cfirst = clast = 8 - col_end; |
||
2624 | } |
||
2625 | else if (illegalBlock & 0x2) { |
||
2626 | col_start = col + vid_stream->right_for; |
||
2627 | col_end = maxx + 1; |
||
2628 | clast = col_end - col_start - 1; |
||
2629 | cfirst = 0; |
||
2630 | } |
||
2631 | else { |
||
2632 | col_start = col + vid_stream->right_for; |
||
2633 | col_end = col_start + 8; |
||
2634 | cfirst = 0; |
||
2635 | } |
||
2636 | |||
2637 | for (rr = row_start; rr < row_end; rr++) { |
||
2638 | rindex1 = past + (rr * row_size) + col_start; |
||
2639 | index = dest + ((row + rfirst) * row_size) + col + cfirst; |
||
2640 | for (cc = col_start; cc < col_end; cc++) { |
||
2641 | *index++ = *rindex1++; |
||
2642 | } |
||
2643 | } |
||
2644 | |||
2645 | if (illegalBlock & 0x1) { |
||
2646 | for (rr = rlast -1; rr >=0; rr--) { |
||
2647 | index = dest + ((row + rr) * row_size) + col; |
||
2648 | rindex1 = dest + ((row + rlast) * row_size) + col; |
||
2649 | for (cc = 0; cc < 8; cc ++) { |
||
2650 | *index++ = *rindex1++; |
||
2651 | } |
||
2652 | } |
||
2653 | } |
||
2654 | else if (illegalBlock & 0x4) { |
||
2655 | for (rr = rlast+1; rr < 8; rr++) { |
||
2656 | index = dest + ((row + rr) * row_size) + col; |
||
2657 | rindex1 = dest + ((row + rlast) * row_size) + col; |
||
2658 | for (cc = 0; cc < 8; cc ++) { |
||
2659 | *index++ = *rindex1++; |
||
2660 | } |
||
2661 | } |
||
2662 | } |
||
2663 | |||
2664 | if (illegalBlock & 0x2) { |
||
2665 | for (cc = clast+1; cc < 8; cc++) { |
||
2666 | index = dest + (row * row_size) + (col + cc); |
||
2667 | rindex1 = dest + (row * row_size) + (col + clast); |
||
2668 | for (rr = 0; rr < 8; rr++) { |
||
2669 | *index = *rindex1; |
||
2670 | index += row_size; |
||
2671 | rindex1 += row_size; |
||
2672 | } |
||
2673 | } |
||
2674 | } |
||
2675 | else if (illegalBlock & 0x8) { |
||
2676 | for (cc = clast-1; cc >= 0; cc--) { |
||
2677 | index = dest + (row * row_size) + (col + cc); |
||
2678 | rindex1 = dest + (row * row_size) + (col + clast); |
||
2679 | for (rr = 0; rr < 8; rr++) { |
||
2680 | *index = *rindex1; |
||
2681 | index += row_size; |
||
2682 | rindex1 += row_size; |
||
2683 | } |
||
2684 | } |
||
2685 | } |
||
2686 | |||
2687 | if (!zflag) { |
||
2688 | for (rr = 0; rr < 8; rr++) { |
||
2689 | index = dest + (row*row_size) + col; |
||
2690 | blockvals = &(vid_stream->block.dct_recon[rr][0]); |
||
2691 | index[0] += blockvals[0]; |
||
2692 | index[1] += blockvals[1]; |
||
2693 | index[2] += blockvals[2]; |
||
2694 | index[3] += blockvals[3]; |
||
2695 | index[4] += blockvals[4]; |
||
2696 | index[5] += blockvals[5]; |
||
2697 | index[6] += blockvals[6]; |
||
2698 | index[7] += blockvals[7]; |
||
2699 | } |
||
2700 | } |
||
2701 | } |
||
2702 | else { |
||
2703 | |||
2704 | #endif |
||
2705 | |||
2706 | index = dest + (row * row_size) + col; |
||
2707 | rindex1 = past + (row + vid_stream->down_for) * row_size |
||
2708 | + col + vid_stream->right_for; |
||
2709 | |||
2710 | blockvals = &(vid_stream->block.dct_recon[0][0]); |
||
2711 | |||
2712 | /* |
||
2713 | * Calculate predictive pixel value based on motion vectors and copy to |
||
2714 | * dest plane. |
||
2715 | */ |
||
2716 | |||
2717 | if ((!vid_stream->down_half_for) && (!vid_stream->right_half_for)) { |
||
2718 | unsigned char *cm = cropTbl + MAX_NEG_CROP; |
||
2719 | if (!zflag) |
||
2720 | for (rr = 0; rr < 4; rr++) { |
||
2721 | index[0] = cm[(int) rindex1[0] + (int) blockvals[0]]; |
||
2722 | index[1] = cm[(int) rindex1[1] + (int) blockvals[1]]; |
||
2723 | index[2] = cm[(int) rindex1[2] + (int) blockvals[2]]; |
||
2724 | index[3] = cm[(int) rindex1[3] + (int) blockvals[3]]; |
||
2725 | index[4] = cm[(int) rindex1[4] + (int) blockvals[4]]; |
||
2726 | index[5] = cm[(int) rindex1[5] + (int) blockvals[5]]; |
||
2727 | index[6] = cm[(int) rindex1[6] + (int) blockvals[6]]; |
||
2728 | index[7] = cm[(int) rindex1[7] + (int) blockvals[7]]; |
||
2729 | index += row_size; |
||
2730 | rindex1 += row_size; |
||
2731 | |||
2732 | index[0] = cm[(int) rindex1[0] + (int) blockvals[8]]; |
||
2733 | index[1] = cm[(int) rindex1[1] + (int) blockvals[9]]; |
||
2734 | index[2] = cm[(int) rindex1[2] + (int) blockvals[10]]; |
||
2735 | index[3] = cm[(int) rindex1[3] + (int) blockvals[11]]; |
||
2736 | index[4] = cm[(int) rindex1[4] + (int) blockvals[12]]; |
||
2737 | index[5] = cm[(int) rindex1[5] + (int) blockvals[13]]; |
||
2738 | index[6] = cm[(int) rindex1[6] + (int) blockvals[14]]; |
||
2739 | index[7] = cm[(int) rindex1[7] + (int) blockvals[15]]; |
||
2740 | blockvals += 16; |
||
2741 | index += row_size; |
||
2742 | rindex1 += row_size; |
||
2743 | } |
||
2744 | else { |
||
2745 | if (vid_stream->right_for & 0x1) { |
||
2746 | /* No alignment, use bye copy */ |
||
2747 | for (rr = 0; rr < 4; rr++) { |
||
2748 | index[0] = rindex1[0]; |
||
2749 | index[1] = rindex1[1]; |
||
2750 | index[2] = rindex1[2]; |
||
2751 | index[3] = rindex1[3]; |
||
2752 | index[4] = rindex1[4]; |
||
2753 | index[5] = rindex1[5]; |
||
2754 | index[6] = rindex1[6]; |
||
2755 | index[7] = rindex1[7]; |
||
2756 | index += row_size; |
||
2757 | rindex1 += row_size; |
||
2758 | |||
2759 | index[0] = rindex1[0]; |
||
2760 | index[1] = rindex1[1]; |
||
2761 | index[2] = rindex1[2]; |
||
2762 | index[3] = rindex1[3]; |
||
2763 | index[4] = rindex1[4]; |
||
2764 | index[5] = rindex1[5]; |
||
2765 | index[6] = rindex1[6]; |
||
2766 | index[7] = rindex1[7]; |
||
2767 | index += row_size; |
||
2768 | rindex1 += row_size; |
||
2769 | } |
||
2770 | } else if (vid_stream->right_for & 0x2) { |
||
2771 | /* Half-word bit aligned, use 16 bit copy */ |
||
2772 | short *src = (short *)rindex1; |
||
2773 | short *dest = (short *)index; |
||
2774 | row_size >>= 1; |
||
2775 | for (rr = 0; rr < 4; rr++) { |
||
2776 | dest[0] = src[0]; |
||
2777 | dest[1] = src[1]; |
||
2778 | dest[2] = src[2]; |
||
2779 | dest[3] = src[3]; |
||
2780 | dest += row_size; |
||
2781 | src += row_size; |
||
2782 | |||
2783 | dest[0] = src[0]; |
||
2784 | dest[1] = src[1]; |
||
2785 | dest[2] = src[2]; |
||
2786 | dest[3] = src[3]; |
||
2787 | dest += row_size; |
||
2788 | src += row_size; |
||
2789 | } |
||
2790 | } else { |
||
2791 | /* Word aligned, use 32 bit copy */ |
||
2792 | int *src = (int *)rindex1; |
||
2793 | int *dest = (int *)index; |
||
2794 | row_size >>= 2; |
||
2795 | for (rr = 0; rr < 4; rr++) { |
||
2796 | dest[0] = src[0]; |
||
2797 | dest[1] = src[1]; |
||
2798 | dest += row_size; |
||
2799 | src += row_size; |
||
2800 | |||
2801 | dest[0] = src[0]; |
||
2802 | dest[1] = src[1]; |
||
2803 | dest += row_size; |
||
2804 | src += row_size; |
||
2805 | } |
||
2806 | } |
||
2807 | } |
||
2808 | } else { |
||
2809 | unsigned char *cm = cropTbl + MAX_NEG_CROP; |
||
2810 | rindex2 = rindex1 + vid_stream->right_half_for |
||
2811 | + (vid_stream->down_half_for * row_size); |
||
2812 | |||
2813 | /* if one of the two is zero, then quality makes no difference */ |
||
2814 | if ((!vid_stream->right_half_for) || |
||
2815 | (!vid_stream->down_half_for) || (!qualityFlag)) { |
||
2816 | |||
2817 | if (!zflag) { |
||
2818 | for (rr = 0; rr < 4; rr++) { |
||
2819 | index[0] = cm[((int) (rindex1[0] + rindex2[0] + 1) >> 1) + blockvals[0]]; |
||
2820 | index[1] = cm[((int) (rindex1[1] + rindex2[1] + 1) >> 1) + blockvals[1]]; |
||
2821 | index[2] = cm[((int) (rindex1[2] + rindex2[2] + 1) >> 1) + blockvals[2]]; |
||
2822 | index[3] = cm[((int) (rindex1[3] + rindex2[3] + 1) >> 1) + blockvals[3]]; |
||
2823 | index[4] = cm[((int) (rindex1[4] + rindex2[4] + 1) >> 1) + blockvals[4]]; |
||
2824 | index[5] = cm[((int) (rindex1[5] + rindex2[5] + 1) >> 1) + blockvals[5]]; |
||
2825 | index[6] = cm[((int) (rindex1[6] + rindex2[6] + 1) >> 1) + blockvals[6]]; |
||
2826 | index[7] = cm[((int) (rindex1[7] + rindex2[7] + 1) >> 1) + blockvals[7]]; |
||
2827 | index += row_size; |
||
2828 | rindex1 += row_size; |
||
2829 | rindex2 += row_size; |
||
2830 | |||
2831 | index[0] = cm[((int) (rindex1[0] + rindex2[0] + 1) >> 1) + blockvals[8]]; |
||
2832 | index[1] = cm[((int) (rindex1[1] + rindex2[1] + 1) >> 1) + blockvals[9]]; |
||
2833 | index[2] = cm[((int) (rindex1[2] + rindex2[2] + 1) >> 1) + blockvals[10]]; |
||
2834 | index[3] = cm[((int) (rindex1[3] + rindex2[3] + 1) >> 1) + blockvals[11]]; |
||
2835 | index[4] = cm[((int) (rindex1[4] + rindex2[4] + 1) >> 1) + blockvals[12]]; |
||
2836 | index[5] = cm[((int) (rindex1[5] + rindex2[5] + 1) >> 1) + blockvals[13]]; |
||
2837 | index[6] = cm[((int) (rindex1[6] + rindex2[6] + 1) >> 1) + blockvals[14]]; |
||
2838 | index[7] = cm[((int) (rindex1[7] + rindex2[7] + 1) >> 1) + blockvals[15]]; |
||
2839 | blockvals += 16; |
||
2840 | index += row_size; |
||
2841 | rindex1 += row_size; |
||
2842 | rindex2 += row_size; |
||
2843 | } |
||
2844 | } else { /* zflag */ |
||
2845 | for (rr = 0; rr < 8; rr++) { |
||
2846 | index[0] = (int) (rindex1[0] + rindex2[0] + 1) >> 1; |
||
2847 | index[1] = (int) (rindex1[1] + rindex2[1] + 1) >> 1; |
||
2848 | index[2] = (int) (rindex1[2] + rindex2[2] + 1) >> 1; |
||
2849 | index[3] = (int) (rindex1[3] + rindex2[3] + 1) >> 1; |
||
2850 | index[4] = (int) (rindex1[4] + rindex2[4] + 1) >> 1; |
||
2851 | index[5] = (int) (rindex1[5] + rindex2[5] + 1) >> 1; |
||
2852 | index[6] = (int) (rindex1[6] + rindex2[6] + 1) >> 1; |
||
2853 | index[7] = (int) (rindex1[7] + rindex2[7] + 1) >> 1; |
||
2854 | index += row_size; |
||
2855 | rindex1 += row_size; |
||
2856 | rindex2 += row_size; |
||
2857 | } |
||
2858 | } |
||
2859 | } else { /* qualityFlag on and both vectors are non-zero */ |
||
2860 | rindex3 = rindex1 + vid_stream->right_half_for; |
||
2861 | rindex4 = rindex1 + (vid_stream->down_half_for * row_size); |
||
2862 | if (!zflag) { |
||
2863 | for (rr = 0; rr < 4; rr++) { |
||
2864 | index[0] = cm[((int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2) + blockvals[0]]; |
||
2865 | index[1] = cm[((int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2) + blockvals[1]]; |
||
2866 | index[2] = cm[((int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2) + blockvals[2]]; |
||
2867 | index[3] = cm[((int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2) + blockvals[3]]; |
||
2868 | index[4] = cm[((int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2) + blockvals[4]]; |
||
2869 | index[5] = cm[((int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2) + blockvals[5]]; |
||
2870 | index[6] = cm[((int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2) + blockvals[6]]; |
||
2871 | index[7] = cm[((int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2) + blockvals[7]]; |
||
2872 | index += row_size; |
||
2873 | rindex1 += row_size; |
||
2874 | rindex2 += row_size; |
||
2875 | rindex3 += row_size; |
||
2876 | rindex4 += row_size; |
||
2877 | |||
2878 | index[0] = cm[((int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2) + blockvals[8]]; |
||
2879 | index[1] = cm[((int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2) + blockvals[9]]; |
||
2880 | index[2] = cm[((int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2) + blockvals[10]]; |
||
2881 | index[3] = cm[((int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2) + blockvals[11]]; |
||
2882 | index[4] = cm[((int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2) + blockvals[12]]; |
||
2883 | index[5] = cm[((int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2) + blockvals[13]]; |
||
2884 | index[6] = cm[((int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2) + blockvals[14]]; |
||
2885 | index[7] = cm[((int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2) + blockvals[15]]; |
||
2886 | blockvals += 16; |
||
2887 | index += row_size; |
||
2888 | rindex1 += row_size; |
||
2889 | rindex2 += row_size; |
||
2890 | rindex3 += row_size; |
||
2891 | rindex4 += row_size; |
||
2892 | } |
||
2893 | } else { /* zflag */ |
||
2894 | for (rr = 0; rr < 8; rr++) { |
||
2895 | index[0] = (int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2; |
||
2896 | index[1] = (int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2; |
||
2897 | index[2] = (int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2; |
||
2898 | index[3] = (int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2; |
||
2899 | index[4] = (int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2; |
||
2900 | index[5] = (int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2; |
||
2901 | index[6] = (int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2; |
||
2902 | index[7] = (int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2; |
||
2903 | index += row_size; |
||
2904 | rindex1 += row_size; |
||
2905 | rindex2 += row_size; |
||
2906 | rindex3 += row_size; |
||
2907 | rindex4 += row_size; |
||
2908 | } |
||
2909 | } |
||
2910 | } |
||
2911 | |||
2912 | } |
||
2913 | #ifdef LOOSE_MPEG |
||
2914 | } |
||
2915 | #endif |
||
2916 | } |
||
2917 | |||
2918 | |||
2919 | /* |
||
2920 | *-------------------------------------------------------------- |
||
2921 | * |
||
2922 | * ReconBMBlock -- |
||
2923 | * |
||
2924 | * Reconstructs back predicted macroblocks. |
||
2925 | * |
||
2926 | * Results: |
||
2927 | * None. |
||
2928 | * |
||
2929 | * Side effects: |
||
2930 | * None. |
||
2931 | * |
||
2932 | *-------------------------------------------------------------- |
||
2933 | */ |
||
2934 | |||
2935 | static void |
||
2936 | ReconBMBlock(vid_stream, bnum, recon_right_back, recon_down_back, zflag) |
||
2937 | VidStream *vid_stream; |
||
2938 | int bnum, recon_right_back, recon_down_back, zflag; |
||
2939 | { |
||
2940 | int mb_row, mb_col, row, col, row_size, rr; |
||
2941 | unsigned char *dest, *future; |
||
2942 | int right_back, down_back, right_half_back, down_half_back; |
||
2943 | unsigned char *rindex1, *rindex2, *rindex3, *rindex4; |
||
2944 | unsigned char *index; |
||
2945 | short int *blockvals; |
||
2946 | |||
2947 | #ifdef LOOSE_MPEG |
||
2948 | int illegalBlock = 0; |
||
2949 | int maxx, maxy, cc; |
||
2950 | int row_start, row_end, rlast, rfirst, col_start, col_end, clast, cfirst; |
||
2951 | #endif |
||
2952 | |||
2953 | /* Calculate macroblock row and column from address. */ |
||
2954 | |||
2955 | mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width; |
||
2956 | mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width; |
||
2957 | |||
2958 | /* If block is luminance block... */ |
||
2959 | |||
2960 | if (bnum < 4) { |
||
2961 | |||
2962 | /* Calculate right_back, down_back motion vectors. */ |
||
2963 | |||
2964 | right_back = recon_right_back >> 1; |
||
2965 | down_back = recon_down_back >> 1; |
||
2966 | right_half_back = recon_right_back & 0x1; |
||
2967 | down_half_back = recon_down_back & 0x1; |
||
2968 | |||
2969 | /* Set dest to luminance plane of current pict image. */ |
||
2970 | |||
2971 | dest = vid_stream->current->luminance; |
||
2972 | |||
2973 | /* |
||
2974 | * If future frame exists, set future to luminance plane of future frame. |
||
2975 | */ |
||
2976 | |||
2977 | if (vid_stream->future != NULL) |
||
2978 | future = vid_stream->future->luminance; |
||
2979 | |||
2980 | /* Establish row size. */ |
||
2981 | |||
2982 | row_size = vid_stream->mb_width << 4; |
||
2983 | |||
2984 | /* Calculate row,col of upper left pixel in block. */ |
||
2985 | |||
2986 | row = mb_row << 4; |
||
2987 | col = mb_col << 4; |
||
2988 | if (bnum > 1) |
||
2989 | row += 8; |
||
2990 | if (bnum % 2) |
||
2991 | col += 8; |
||
2992 | |||
2993 | #ifdef LOOSE_MPEG |
||
2994 | |||
2995 | /* Check for block illegality. */ |
||
2996 | |||
2997 | maxx = vid_stream->mb_width*16-1; |
||
2998 | maxy = vid_stream->mb_height*16-1; |
||
2999 | |||
3000 | if (row + down_back + 7 > maxy) illegalBlock |= 0x4; |
||
3001 | else if (row + down_back < 0) illegalBlock |= 0x1; |
||
3002 | |||
3003 | if (col + right_back + 7 > maxx) illegalBlock |= 0x2; |
||
3004 | else if (col + right_back < 0) illegalBlock |= 0x8; |
||
3005 | |||
3006 | #endif |
||
3007 | |||
3008 | } |
||
3009 | /* Otherwise, block is NOT luminance block, ... */ |
||
3010 | |||
3011 | else { |
||
3012 | |||
3013 | /* Construct motion vectors. */ |
||
3014 | |||
3015 | recon_right_back /= 2; |
||
3016 | recon_down_back /= 2; |
||
3017 | right_back = recon_right_back >> 1; |
||
3018 | down_back = recon_down_back >> 1; |
||
3019 | right_half_back = recon_right_back & 0x1; |
||
3020 | down_half_back = recon_down_back & 0x1; |
||
3021 | |||
3022 | /* Establish row size. */ |
||
3023 | |||
3024 | row_size = vid_stream->mb_width << 3; |
||
3025 | |||
3026 | /* Calculate row,col of upper left pixel in block. */ |
||
3027 | |||
3028 | row = mb_row << 3; |
||
3029 | col = mb_col << 3; |
||
3030 | |||
3031 | #ifdef LOOSE_MPEG |
||
3032 | |||
3033 | /* Check for block illegality. */ |
||
3034 | |||
3035 | maxx = vid_stream->mb_width*8-1; |
||
3036 | maxy = vid_stream->mb_height*8-1; |
||
3037 | |||
3038 | if (row + down_back + 7 > maxy) illegalBlock |= 0x4; |
||
3039 | else if (row + down_back < 0) illegalBlock |= 0x1; |
||
3040 | |||
3041 | if (col + right_back + 7 > maxx) illegalBlock |= 0x2; |
||
3042 | else if (col + right_back < 0) illegalBlock |= 0x8; |
||
3043 | |||
3044 | #endif |
||
3045 | |||
3046 | /* If block is Cr block... */ |
||
3047 | /* They were switched earlier, so 5 is first - eyhung */ |
||
3048 | |||
3049 | if (bnum == 5) { |
||
3050 | |||
3051 | /* Set dest to Cr plane of current pict image. */ |
||
3052 | |||
3053 | dest = vid_stream->current->Cr; |
||
3054 | |||
3055 | /* |
||
3056 | * If future frame exists, set future to Cr plane of future image. |
||
3057 | */ |
||
3058 | |||
3059 | if (vid_stream->future != NULL) |
||
3060 | future = vid_stream->future->Cr; |
||
3061 | } |
||
3062 | /* Otherwise, block is Cb block... */ |
||
3063 | |||
3064 | else { |
||
3065 | |||
3066 | /* Set dest to Cb plane of current pict image. */ |
||
3067 | |||
3068 | dest = vid_stream->current->Cb; |
||
3069 | |||
3070 | /* |
||
3071 | * If future frame exists, set future to Cb plane of future frame. |
||
3072 | */ |
||
3073 | |||
3074 | if (vid_stream->future != NULL) |
||
3075 | future = vid_stream->future->Cb; |
||
3076 | } |
||
3077 | } |
||
3078 | |||
3079 | /* For each pixel in block do... */ |
||
3080 | |||
3081 | #ifdef LOOSE_MPEG |
||
3082 | |||
3083 | if (illegalBlock) { |
||
3084 | if (illegalBlock & 0x1) { |
||
3085 | row_start = 0; |
||
3086 | row_end = row+down_back+8; |
||
3087 | rfirst = rlast = 8 - row_end; |
||
3088 | } |
||
3089 | else if (illegalBlock & 0x4) { |
||
3090 | row_start = row + down_back; |
||
3091 | row_end = maxy+1; |
||
3092 | rlast = row_end - row_start - 1; |
||
3093 | rfirst = 0; |
||
3094 | } |
||
3095 | else { |
||
3096 | row_start = row+down_back; |
||
3097 | row_end = row_start+8; |
||
3098 | rfirst = 0; |
||
3099 | } |
||
3100 | |||
3101 | if (illegalBlock & 0x8) { |
||
3102 | col_start = 0; |
||
3103 | col_end = col + right_back + 8; |
||
3104 | cfirst = clast = 8 - col_end; |
||
3105 | } |
||
3106 | else if (illegalBlock & 0x2) { |
||
3107 | col_start = col + right_back; |
||
3108 | col_end = maxx + 1; |
||
3109 | clast = col_end - col_start - 1; |
||
3110 | cfirst = 0; |
||
3111 | } |
||
3112 | else { |
||
3113 | col_start = col + right_back; |
||
3114 | col_end = col_start + 8; |
||
3115 | cfirst = 0; |
||
3116 | } |
||
3117 | |||
3118 | for (rr = row_start; rr < row_end; rr++) { |
||
3119 | rindex1 = future + (rr * row_size) + col_start; |
||
3120 | index = dest + ((row + rfirst) * row_size) + col + cfirst; |
||
3121 | for (cc = col_start; cc < col_end; cc++) { |
||
3122 | *index++ = *rindex1++; |
||
3123 | } |
||
3124 | } |
||
3125 | |||
3126 | if (illegalBlock & 0x1) { |
||
3127 | for (rr = rlast -1; rr >=0; rr--) { |
||
3128 | index = dest + ((row + rr) * row_size) + col; |
||
3129 | rindex1 = dest + ((row + rlast) * row_size) + col; |
||
3130 | for (cc = 0; cc < 8; cc ++) { |
||
3131 | *index++ = *rindex1++; |
||
3132 | } |
||
3133 | } |
||
3134 | } |
||
3135 | else if (illegalBlock & 0x4) { |
||
3136 | for (rr = rlast+1; rr < 8; rr++) { |
||
3137 | index = dest + ((row + rr) * row_size) + col; |
||
3138 | rindex1 = dest + ((row + rlast) * row_size) + col; |
||
3139 | for (cc = 0; cc < 8; cc ++) { |
||
3140 | *index++ = *rindex1++; |
||
3141 | } |
||
3142 | } |
||
3143 | } |
||
3144 | |||
3145 | if (illegalBlock & 0x2) { |
||
3146 | for (cc = clast+1; cc < 8; cc++) { |
||
3147 | index = dest + (row * row_size) + (col + cc); |
||
3148 | rindex1 = dest + (row * row_size) + (col + clast); |
||
3149 | for (rr = 0; rr < 8; rr++) { |
||
3150 | *index = *rindex1; |
||
3151 | index += row_size; |
||
3152 | rindex1 += row_size; |
||
3153 | } |
||
3154 | } |
||
3155 | } |
||
3156 | else if (illegalBlock & 0x8) { |
||
3157 | for (cc = clast-1; cc >= 0; cc--) { |
||
3158 | index = dest + (row * row_size) + (col + cc); |
||
3159 | rindex1 = dest + (row * row_size) + (col + clast); |
||
3160 | for (rr = 0; rr < 8; rr++) { |
||
3161 | *index = *rindex1; |
||
3162 | index += row_size; |
||
3163 | rindex1 += row_size; |
||
3164 | } |
||
3165 | } |
||
3166 | } |
||
3167 | |||
3168 | if (!zflag) { |
||
3169 | for (rr = 0; rr < 8; rr++) { |
||
3170 | index = dest + (row*row_size) + col; |
||
3171 | blockvals = &(vid_stream->block.dct_recon[rr][0]); |
||
3172 | index[0] += blockvals[0]; |
||
3173 | index[1] += blockvals[1]; |
||
3174 | index[2] += blockvals[2]; |
||
3175 | index[3] += blockvals[3]; |
||
3176 | index[4] += blockvals[4]; |
||
3177 | index[5] += blockvals[5]; |
||
3178 | index[6] += blockvals[6]; |
||
3179 | index[7] += blockvals[7]; |
||
3180 | } |
||
3181 | } |
||
3182 | } |
||
3183 | else { |
||
3184 | |||
3185 | #endif |
||
3186 | |||
3187 | index = dest + (row * row_size) + col; |
||
3188 | rindex1 = future + (row + down_back) * row_size + col + right_back; |
||
3189 | |||
3190 | blockvals = &(vid_stream->block.dct_recon[0][0]); |
||
3191 | |||
3192 | if ((!right_half_back) && (!down_half_back)) { |
||
3193 | unsigned char *cm = cropTbl + MAX_NEG_CROP; |
||
3194 | if (!zflag) |
||
3195 | for (rr = 0; rr < 4; rr++) { |
||
3196 | index[0] = cm[(int) rindex1[0] + (int) blockvals[0]]; |
||
3197 | index[1] = cm[(int) rindex1[1] + (int) blockvals[1]]; |
||
3198 | index[2] = cm[(int) rindex1[2] + (int) blockvals[2]]; |
||
3199 | index[3] = cm[(int) rindex1[3] + (int) blockvals[3]]; |
||
3200 | index[4] = cm[(int) rindex1[4] + (int) blockvals[4]]; |
||
3201 | index[5] = cm[(int) rindex1[5] + (int) blockvals[5]]; |
||
3202 | index[6] = cm[(int) rindex1[6] + (int) blockvals[6]]; |
||
3203 | index[7] = cm[(int) rindex1[7] + (int) blockvals[7]]; |
||
3204 | index += row_size; |
||
3205 | rindex1 += row_size; |
||
3206 | |||
3207 | index[0] = cm[(int) rindex1[0] + (int) blockvals[8]]; |
||
3208 | index[1] = cm[(int) rindex1[1] + (int) blockvals[9]]; |
||
3209 | index[2] = cm[(int) rindex1[2] + (int) blockvals[10]]; |
||
3210 | index[3] = cm[(int) rindex1[3] + (int) blockvals[11]]; |
||
3211 | index[4] = cm[(int) rindex1[4] + (int) blockvals[12]]; |
||
3212 | index[5] = cm[(int) rindex1[5] + (int) blockvals[13]]; |
||
3213 | index[6] = cm[(int) rindex1[6] + (int) blockvals[14]]; |
||
3214 | index[7] = cm[(int) rindex1[7] + (int) blockvals[15]]; |
||
3215 | blockvals += 16; |
||
3216 | index += row_size; |
||
3217 | rindex1 += row_size; |
||
3218 | } |
||
3219 | else { |
||
3220 | if (right_back & 0x1) { |
||
3221 | /* No alignment, use bye copy */ |
||
3222 | for (rr = 0; rr < 4; rr++) { |
||
3223 | index[0] = rindex1[0]; |
||
3224 | index[1] = rindex1[1]; |
||
3225 | index[2] = rindex1[2]; |
||
3226 | index[3] = rindex1[3]; |
||
3227 | index[4] = rindex1[4]; |
||
3228 | index[5] = rindex1[5]; |
||
3229 | index[6] = rindex1[6]; |
||
3230 | index[7] = rindex1[7]; |
||
3231 | index += row_size; |
||
3232 | rindex1 += row_size; |
||
3233 | |||
3234 | index[0] = rindex1[0]; |
||
3235 | index[1] = rindex1[1]; |
||
3236 | index[2] = rindex1[2]; |
||
3237 | index[3] = rindex1[3]; |
||
3238 | index[4] = rindex1[4]; |
||
3239 | index[5] = rindex1[5]; |
||
3240 | index[6] = rindex1[6]; |
||
3241 | index[7] = rindex1[7]; |
||
3242 | index += row_size; |
||
3243 | rindex1 += row_size; |
||
3244 | } |
||
3245 | } else if (right_back & 0x2) { |
||
3246 | /* Half-word bit aligned, use 16 bit copy */ |
||
3247 | short *src = (short *)rindex1; |
||
3248 | short *dest = (short *)index; |
||
3249 | row_size >>= 1; |
||
3250 | for (rr = 0; rr < 4; rr++) { |
||
3251 | dest[0] = src[0]; |
||
3252 | dest[1] = src[1]; |
||
3253 | dest[2] = src[2]; |
||
3254 | dest[3] = src[3]; |
||
3255 | dest += row_size; |
||
3256 | src += row_size; |
||
3257 | |||
3258 | dest[0] = src[0]; |
||
3259 | dest[1] = src[1]; |
||
3260 | dest[2] = src[2]; |
||
3261 | dest[3] = src[3]; |
||
3262 | dest += row_size; |
||
3263 | src += row_size; |
||
3264 | } |
||
3265 | } else { |
||
3266 | /* Word aligned, use 32 bit copy */ |
||
3267 | int *src = (int *)rindex1; |
||
3268 | int *dest = (int *)index; |
||
3269 | row_size >>= 2; |
||
3270 | for (rr = 0; rr < 4; rr++) { |
||
3271 | dest[0] = src[0]; |
||
3272 | dest[1] = src[1]; |
||
3273 | dest += row_size; |
||
3274 | src += row_size; |
||
3275 | |||
3276 | dest[0] = src[0]; |
||
3277 | dest[1] = src[1]; |
||
3278 | dest += row_size; |
||
3279 | src += row_size; |
||
3280 | } |
||
3281 | } |
||
3282 | } |
||
3283 | } else { |
||
3284 | unsigned char *cm = cropTbl + MAX_NEG_CROP; |
||
3285 | rindex2 = rindex1 + right_half_back + (down_half_back * row_size); |
||
3286 | if (!qualityFlag) { |
||
3287 | |||
3288 | if (!zflag) { |
||
3289 | for (rr = 0; rr < 4; rr++) { |
||
3290 | index[0] = cm[((int) (rindex1[0] + rindex2[0] + 1) >> 1) + blockvals[0]]; |
||
3291 | index[1] = cm[((int) (rindex1[1] + rindex2[1] + 1) >> 1) + blockvals[1]]; |
||
3292 | index[2] = cm[((int) (rindex1[2] + rindex2[2] + 1) >> 1) + blockvals[2]]; |
||
3293 | index[3] = cm[((int) (rindex1[3] + rindex2[3] + 1) >> 1) + blockvals[3]]; |
||
3294 | index[4] = cm[((int) (rindex1[4] + rindex2[4] + 1) >> 1) + blockvals[4]]; |
||
3295 | index[5] = cm[((int) (rindex1[5] + rindex2[5] + 1) >> 1) + blockvals[5]]; |
||
3296 | index[6] = cm[((int) (rindex1[6] + rindex2[6] + 1) >> 1) + blockvals[6]]; |
||
3297 | index[7] = cm[((int) (rindex1[7] + rindex2[7] + 1) >> 1) + blockvals[7]]; |
||
3298 | index += row_size; |
||
3299 | rindex1 += row_size; |
||
3300 | rindex2 += row_size; |
||
3301 | |||
3302 | index[0] = cm[((int) (rindex1[0] + rindex2[0] + 1) >> 1) + blockvals[8]]; |
||
3303 | index[1] = cm[((int) (rindex1[1] + rindex2[1] + 1) >> 1) + blockvals[9]]; |
||
3304 | index[2] = cm[((int) (rindex1[2] + rindex2[2] + 1) >> 1) + blockvals[10]]; |
||
3305 | index[3] = cm[((int) (rindex1[3] + rindex2[3] + 1) >> 1) + blockvals[11]]; |
||
3306 | index[4] = cm[((int) (rindex1[4] + rindex2[4] + 1) >> 1) + blockvals[12]]; |
||
3307 | index[5] = cm[((int) (rindex1[5] + rindex2[5] + 1) >> 1) + blockvals[13]]; |
||
3308 | index[6] = cm[((int) (rindex1[6] + rindex2[6] + 1) >> 1) + blockvals[14]]; |
||
3309 | index[7] = cm[((int) (rindex1[7] + rindex2[7] + 1) >> 1) + blockvals[15]]; |
||
3310 | blockvals += 16; |
||
3311 | index += row_size; |
||
3312 | rindex1 += row_size; |
||
3313 | rindex2 += row_size; |
||
3314 | } |
||
3315 | } else { /* zflag */ |
||
3316 | for (rr = 0; rr < 8; rr++) { |
||
3317 | index[0] = (int) (rindex1[0] + rindex2[0] + 1) >> 1; |
||
3318 | index[1] = (int) (rindex1[1] + rindex2[1] + 1) >> 1; |
||
3319 | index[2] = (int) (rindex1[2] + rindex2[2] + 1) >> 1; |
||
3320 | index[3] = (int) (rindex1[3] + rindex2[3] + 1) >> 1; |
||
3321 | index[4] = (int) (rindex1[4] + rindex2[4] + 1) >> 1; |
||
3322 | index[5] = (int) (rindex1[5] + rindex2[5] + 1) >> 1; |
||
3323 | index[6] = (int) (rindex1[6] + rindex2[6] + 1) >> 1; |
||
3324 | index[7] = (int) (rindex1[7] + rindex2[7] + 1) >> 1; |
||
3325 | index += row_size; |
||
3326 | rindex1 += row_size; |
||
3327 | rindex2 += row_size; |
||
3328 | } |
||
3329 | } |
||
3330 | } else { /* qualityFlag on */ |
||
3331 | rindex3 = rindex1 + right_half_back; |
||
3332 | rindex4 = rindex1 + (down_half_back * row_size); |
||
3333 | if (!zflag) { |
||
3334 | for (rr = 0; rr < 4; rr++) { |
||
3335 | index[0] = cm[((int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2) + blockvals[0]]; |
||
3336 | index[1] = cm[((int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2) + blockvals[1]]; |
||
3337 | index[2] = cm[((int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2) + blockvals[2]]; |
||
3338 | index[3] = cm[((int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2) + blockvals[3]]; |
||
3339 | index[4] = cm[((int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2) + blockvals[4]]; |
||
3340 | index[5] = cm[((int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2) + blockvals[5]]; |
||
3341 | index[6] = cm[((int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2) + blockvals[6]]; |
||
3342 | index[7] = cm[((int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2) + blockvals[7]]; |
||
3343 | index += row_size; |
||
3344 | rindex1 += row_size; |
||
3345 | rindex2 += row_size; |
||
3346 | rindex3 += row_size; |
||
3347 | rindex4 += row_size; |
||
3348 | |||
3349 | index[0] = cm[((int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2) + blockvals[8]]; |
||
3350 | index[1] = cm[((int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2) + blockvals[9]]; |
||
3351 | index[2] = cm[((int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2) + blockvals[10]]; |
||
3352 | index[3] = cm[((int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2) + blockvals[11]]; |
||
3353 | index[4] = cm[((int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2) + blockvals[12]]; |
||
3354 | index[5] = cm[((int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2) + blockvals[13]]; |
||
3355 | index[6] = cm[((int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2) + blockvals[14]]; |
||
3356 | index[7] = cm[((int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2) + blockvals[15]]; |
||
3357 | blockvals += 16; |
||
3358 | index += row_size; |
||
3359 | rindex1 += row_size; |
||
3360 | rindex2 += row_size; |
||
3361 | rindex3 += row_size; |
||
3362 | rindex4 += row_size; |
||
3363 | } |
||
3364 | } else { /* zflag */ |
||
3365 | for (rr = 0; rr < 8; rr++) { |
||
3366 | index[0] = (int) (rindex1[0] + rindex2[0] + rindex3[0] + rindex4[0] + 2) >> 2; |
||
3367 | index[1] = (int) (rindex1[1] + rindex2[1] + rindex3[1] + rindex4[1] + 2) >> 2; |
||
3368 | index[2] = (int) (rindex1[2] + rindex2[2] + rindex3[2] + rindex4[2] + 2) >> 2; |
||
3369 | index[3] = (int) (rindex1[3] + rindex2[3] + rindex3[3] + rindex4[3] + 2) >> 2; |
||
3370 | index[4] = (int) (rindex1[4] + rindex2[4] + rindex3[4] + rindex4[4] + 2) >> 2; |
||
3371 | index[5] = (int) (rindex1[5] + rindex2[5] + rindex3[5] + rindex4[5] + 2) >> 2; |
||
3372 | index[6] = (int) (rindex1[6] + rindex2[6] + rindex3[6] + rindex4[6] + 2) >> 2; |
||
3373 | index[7] = (int) (rindex1[7] + rindex2[7] + rindex3[7] + rindex4[7] + 2) >> 2; |
||
3374 | index += row_size; |
||
3375 | rindex1 += row_size; |
||
3376 | rindex2 += row_size; |
||
3377 | rindex3 += row_size; |
||
3378 | rindex4 += row_size; |
||
3379 | } |
||
3380 | } |
||
3381 | } |
||
3382 | |||
3383 | } |
||
3384 | #ifdef LOOSE_MPEG |
||
3385 | } |
||
3386 | #endif |
||
3387 | } |
||
3388 | |||
3389 | |||
3390 | /* |
||
3391 | *-------------------------------------------------------------- |
||
3392 | * |
||
3393 | * ReconBiMBlock -- |
||
3394 | * |
||
3395 | * Reconstructs bidirectionally predicted macroblocks. |
||
3396 | * |
||
3397 | * Results: |
||
3398 | * None. |
||
3399 | * |
||
3400 | * Side effects: |
||
3401 | * None. |
||
3402 | * |
||
3403 | *-------------------------------------------------------------- |
||
3404 | */ |
||
3405 | |||
3406 | static void |
||
3407 | ReconBiMBlock(vid_stream, bnum, recon_right_for, recon_down_for, |
||
3408 | recon_right_back, recon_down_back, zflag) |
||
3409 | VidStream *vid_stream; |
||
3410 | int bnum, recon_right_for, recon_down_for, recon_right_back, recon_down_back; |
||
3411 | int zflag; |
||
3412 | { |
||
3413 | int mb_row, mb_col, row, col, row_size, rr; |
||
3414 | unsigned char *dest, *past=NULL, *future=NULL; |
||
3415 | int right_for, down_for, right_half_for, down_half_for; |
||
3416 | int right_back, down_back, right_half_back, down_half_back; |
||
3417 | unsigned char *index, *rindex1, *bindex1; |
||
3418 | short int *blockvals; |
||
3419 | int forw_row_start, back_row_start, forw_col_start, back_col_start; |
||
3420 | #ifdef LOOSE_MPEG |
||
3421 | int lmaxx = vid_stream->mb_width*16-1; |
||
3422 | int lmaxy = vid_stream->mb_height*16-1; |
||
3423 | int cmaxx = vid_stream->mb_width*8-1; |
||
3424 | int cmaxy = vid_stream->mb_height*8-1; |
||
3425 | #endif |
||
3426 | |||
3427 | #ifdef LOOSE_MPEG |
||
3428 | int illegal_forw = 0; |
||
3429 | int illegal_back = 0; |
||
3430 | #endif |
||
3431 | |||
3432 | /* Calculate macroblock row and column from address. */ |
||
3433 | |||
3434 | mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width; |
||
3435 | mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width; |
||
3436 | |||
3437 | /* If block is luminance block... */ |
||
3438 | |||
3439 | if (bnum < 4) { |
||
3440 | |||
3441 | /* |
||
3442 | * Calculate right_for, down_for, right_half_for, down_half_for, |
||
3443 | * right_back, down_bakc, right_half_back, and down_half_back, motion |
||
3444 | * vectors. |
||
3445 | */ |
||
3446 | |||
3447 | right_for = recon_right_for >> 1; |
||
3448 | down_for = recon_down_for >> 1; |
||
3449 | right_half_for = recon_right_for & 0x1; |
||
3450 | down_half_for = recon_down_for & 0x1; |
||
3451 | |||
3452 | right_back = recon_right_back >> 1; |
||
3453 | down_back = recon_down_back >> 1; |
||
3454 | right_half_back = recon_right_back & 0x1; |
||
3455 | down_half_back = recon_down_back & 0x1; |
||
3456 | |||
3457 | /* Set dest to luminance plane of current pict image. */ |
||
3458 | |||
3459 | dest = vid_stream->current->luminance; |
||
3460 | |||
3461 | /* If past frame exists, set past to luminance plane of past frame. */ |
||
3462 | |||
3463 | if (vid_stream->past != NULL) |
||
3464 | past = vid_stream->past->luminance; |
||
3465 | |||
3466 | /* |
||
3467 | * If future frame exists, set future to luminance plane of future frame. |
||
3468 | */ |
||
3469 | |||
3470 | if (vid_stream->future != NULL) |
||
3471 | future = vid_stream->future->luminance; |
||
3472 | |||
3473 | /* Establish row size. */ |
||
3474 | |||
3475 | row_size = (vid_stream->mb_width << 4); |
||
3476 | |||
3477 | /* Calculate row,col of upper left pixel in block. */ |
||
3478 | |||
3479 | row = (mb_row << 4); |
||
3480 | col = (mb_col << 4); |
||
3481 | if (bnum > 1) |
||
3482 | row += 8; |
||
3483 | if (bnum & 0x01) |
||
3484 | col += 8; |
||
3485 | |||
3486 | forw_col_start = col + right_for; |
||
3487 | forw_row_start = row + down_for; |
||
3488 | |||
3489 | back_col_start = col + right_back; |
||
3490 | back_row_start = row + down_back; |
||
3491 | |||
3492 | #ifdef LOOSE_MPEG |
||
3493 | |||
3494 | /* Check for illegal pred. blocks. */ |
||
3495 | |||
3496 | |||
3497 | if (forw_col_start+7 > lmaxx) illegal_forw = 1; |
||
3498 | else if (forw_col_start < 0) illegal_forw = 1; |
||
3499 | |||
3500 | if (forw_row_start+7 > lmaxy) illegal_forw = 1; |
||
3501 | else if (forw_row_start < 0) illegal_forw = 1; |
||
3502 | |||
3503 | if (back_col_start+7 > lmaxx) illegal_back = 1; |
||
3504 | else if (back_col_start < 0) illegal_back = 1; |
||
3505 | |||
3506 | if (back_row_start+7 > lmaxy) illegal_back = 1; |
||
3507 | else if (back_row_start < 0) illegal_back = 1; |
||
3508 | |||
3509 | #endif |
||
3510 | |||
3511 | } |
||
3512 | /* Otherwise, block is NOT luminance block, ... */ |
||
3513 | |||
3514 | else { |
||
3515 | |||
3516 | /* Construct motion vectors. */ |
||
3517 | |||
3518 | recon_right_for /= 2; |
||
3519 | recon_down_for /= 2; |
||
3520 | right_for = recon_right_for >> 1; |
||
3521 | down_for = recon_down_for >> 1; |
||
3522 | right_half_for = recon_right_for & 0x1; |
||
3523 | down_half_for = recon_down_for & 0x1; |
||
3524 | |||
3525 | recon_right_back /= 2; |
||
3526 | recon_down_back /= 2; |
||
3527 | right_back = recon_right_back >> 1; |
||
3528 | down_back = recon_down_back >> 1; |
||
3529 | right_half_back = recon_right_back & 0x1; |
||
3530 | down_half_back = recon_down_back & 0x1; |
||
3531 | |||
3532 | /* Establish row size. */ |
||
3533 | |||
3534 | row_size = (vid_stream->mb_width << 3); |
||
3535 | |||
3536 | /* Calculate row,col of upper left pixel in block. */ |
||
3537 | |||
3538 | row = (mb_row << 3); |
||
3539 | col = (mb_col << 3); |
||
3540 | |||
3541 | forw_col_start = col + right_for; |
||
3542 | forw_row_start = row + down_for; |
||
3543 | |||
3544 | back_col_start = col + right_back; |
||
3545 | back_row_start = row + down_back; |
||
3546 | |||
3547 | #ifdef LOOSE_MPEG |
||
3548 | |||
3549 | /* Check for illegal pred. blocks. */ |
||
3550 | |||
3551 | if (forw_col_start+7 > cmaxx) illegal_forw = 1; |
||
3552 | else if (forw_col_start < 0) illegal_forw = 1; |
||
3553 | |||
3554 | if (forw_row_start+7 > cmaxy) illegal_forw = 1; |
||
3555 | else if (forw_row_start < 0) illegal_forw = 1; |
||
3556 | |||
3557 | if (back_col_start+7 > cmaxx) illegal_back = 1; |
||
3558 | else if (back_col_start < 0) illegal_back = 1; |
||
3559 | |||
3560 | if (back_row_start+7 > cmaxy) illegal_back = 1; |
||
3561 | else if (back_row_start < 0) illegal_back = 1; |
||
3562 | |||
3563 | #endif |
||
3564 | |||
3565 | /* If block is Cr block... */ |
||
3566 | /* Switched earlier, so we test Cr first - eyhung */ |
||
3567 | |||
3568 | if (bnum == 5) { |
||
3569 | |||
3570 | /* Set dest to Cr plane of current pict image. */ |
||
3571 | |||
3572 | dest = vid_stream->current->Cr; |
||
3573 | |||
3574 | /* If past frame exists, set past to Cr plane of past image. */ |
||
3575 | |||
3576 | if (vid_stream->past != NULL) |
||
3577 | past = vid_stream->past->Cr; |
||
3578 | |||
3579 | /* |
||
3580 | * If future frame exists, set future to Cr plane of future image. |
||
3581 | */ |
||
3582 | |||
3583 | if (vid_stream->future != NULL) |
||
3584 | future = vid_stream->future->Cr; |
||
3585 | } |
||
3586 | /* Otherwise, block is Cb block... */ |
||
3587 | |||
3588 | else { |
||
3589 | |||
3590 | /* Set dest to Cb plane of current pict image. */ |
||
3591 | |||
3592 | dest = vid_stream->current->Cb; |
||
3593 | |||
3594 | /* If past frame exists, set past to Cb plane of past frame. */ |
||
3595 | |||
3596 | if (vid_stream->past != NULL) |
||
3597 | past = vid_stream->past->Cb; |
||
3598 | |||
3599 | /* |
||
3600 | * If future frame exists, set future to Cb plane of future frame. |
||
3601 | */ |
||
3602 | |||
3603 | if (vid_stream->future != NULL) |
||
3604 | future = vid_stream->future->Cb; |
||
3605 | } |
||
3606 | } |
||
3607 | |||
3608 | /* For each pixel in block... */ |
||
3609 | |||
3610 | index = dest + (row * row_size) + col; |
||
3611 | |||
3612 | #ifdef LOOSE_MPEG |
||
3613 | if (illegal_forw) |
||
3614 | rindex1 = future + back_row_start * row_size + back_col_start; |
||
3615 | else |
||
3616 | #endif |
||
3617 | rindex1 = past + forw_row_start * row_size + forw_col_start; |
||
3618 | |||
3619 | #ifdef LOOSE_MPEG |
||
3620 | if (illegal_back) |
||
3621 | bindex1 = past + forw_row_start * row_size + forw_col_start; |
||
3622 | else |
||
3623 | #endif |
||
3624 | bindex1 = future + back_row_start * row_size + back_col_start; |
||
3625 | |||
3626 | blockvals = (short int *) &(vid_stream->block.dct_recon[0][0]); |
||
3627 | |||
3628 | { |
||
3629 | unsigned char *cm = cropTbl + MAX_NEG_CROP; |
||
3630 | if (!zflag) |
||
3631 | for (rr = 0; rr < 4; rr++) { |
||
3632 | index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[0]]; |
||
3633 | index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[1]]; |
||
3634 | index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[2]]; |
||
3635 | index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[3]]; |
||
3636 | index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[4]]; |
||
3637 | index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[5]]; |
||
3638 | index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[6]]; |
||
3639 | index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[7]]; |
||
3640 | index += row_size; |
||
3641 | rindex1 += row_size; |
||
3642 | bindex1 += row_size; |
||
3643 | |||
3644 | index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[8]]; |
||
3645 | index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[9]]; |
||
3646 | index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[10]]; |
||
3647 | index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[11]]; |
||
3648 | index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[12]]; |
||
3649 | index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[13]]; |
||
3650 | index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[14]]; |
||
3651 | index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[15]]; |
||
3652 | blockvals += 16; |
||
3653 | index += row_size; |
||
3654 | rindex1 += row_size; |
||
3655 | bindex1 += row_size; |
||
3656 | } |
||
3657 | |||
3658 | else |
||
3659 | for (rr = 0; rr < 4; rr++) { |
||
3660 | index[0] = (int) (rindex1[0] + bindex1[0]) >> 1; |
||
3661 | index[1] = (int) (rindex1[1] + bindex1[1]) >> 1; |
||
3662 | index[2] = (int) (rindex1[2] + bindex1[2]) >> 1; |
||
3663 | index[3] = (int) (rindex1[3] + bindex1[3]) >> 1; |
||
3664 | index[4] = (int) (rindex1[4] + bindex1[4]) >> 1; |
||
3665 | index[5] = (int) (rindex1[5] + bindex1[5]) >> 1; |
||
3666 | index[6] = (int) (rindex1[6] + bindex1[6]) >> 1; |
||
3667 | index[7] = (int) (rindex1[7] + bindex1[7]) >> 1; |
||
3668 | index += row_size; |
||
3669 | rindex1 += row_size; |
||
3670 | bindex1 += row_size; |
||
3671 | |||
3672 | index[0] = (int) (rindex1[0] + bindex1[0]) >> 1; |
||
3673 | index[1] = (int) (rindex1[1] + bindex1[1]) >> 1; |
||
3674 | index[2] = (int) (rindex1[2] + bindex1[2]) >> 1; |
||
3675 | index[3] = (int) (rindex1[3] + bindex1[3]) >> 1; |
||
3676 | index[4] = (int) (rindex1[4] + bindex1[4]) >> 1; |
||
3677 | index[5] = (int) (rindex1[5] + bindex1[5]) >> 1; |
||
3678 | index[6] = (int) (rindex1[6] + bindex1[6]) >> 1; |
||
3679 | index[7] = (int) (rindex1[7] + bindex1[7]) >> 1; |
||
3680 | index += row_size; |
||
3681 | rindex1 += row_size; |
||
3682 | bindex1 += row_size; |
||
3683 | } |
||
3684 | } |
||
3685 | } |
||
3686 | |||
3687 | |||
3688 | /* |
||
3689 | *-------------------------------------------------------------- |
||
3690 | * |
||
3691 | * ProcessSkippedPFrameMBlocks -- |
||
3692 | * |
||
3693 | * Processes skipped macroblocks in P frames. |
||
3694 | * |
||
3695 | * Results: |
||
3696 | * Calculates pixel values for luminance, Cr, and Cb planes |
||
3697 | * in current pict image for skipped macroblocks. |
||
3698 | * |
||
3699 | * Side effects: |
||
3700 | * Pixel values in pict image changed. |
||
3701 | * |
||
3702 | *-------------------------------------------------------------- |
||
3703 | */ |
||
3704 | |||
3705 | static void |
||
3706 | ProcessSkippedPFrameMBlocks(vid_stream) |
||
3707 | VidStream *vid_stream; |
||
3708 | { |
||
3709 | int row_size, half_row, mb_row, mb_col, row, col, rr; |
||
3710 | int addr, row_incr, half_row_incr, crow, ccol; |
||
3711 | int *dest, *src, *dest1, *src1; |
||
3712 | int ditherType=vid_stream->ditherType; |
||
3713 | |||
3714 | /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */ |
||
3715 | |||
3716 | row_size = vid_stream->mb_width << 4; |
||
3717 | half_row = (row_size >> 1); |
||
3718 | row_incr = row_size >> 2; |
||
3719 | half_row_incr = half_row >> 2; |
||
3720 | |||
3721 | /* For each skipped macroblock, do... */ |
||
3722 | |||
3723 | for (addr = vid_stream->mblock.past_mb_addr + 1; |
||
3724 | addr < vid_stream->mblock.mb_address; addr++) { |
||
3725 | |||
3726 | /* Calculate macroblock row and col. */ |
||
3727 | |||
3728 | mb_row = addr / vid_stream->mb_width; |
||
3729 | mb_col = addr % vid_stream->mb_width; |
||
3730 | |||
3731 | /* Calculate upper left pixel row,col for luminance plane. */ |
||
3732 | |||
3733 | row = mb_row << 4; |
||
3734 | col = mb_col << 4; |
||
3735 | |||
3736 | |||
3737 | /* For each row in macroblock luminance plane... */ |
||
3738 | |||
3739 | dest = (int *)(vid_stream->current->luminance + (row * row_size) + col); |
||
3740 | src = (int *)(vid_stream->future->luminance + (row * row_size) + col); |
||
3741 | |||
3742 | for (rr = 0; rr < 8; rr++) { |
||
3743 | |||
3744 | /* Copy pixel values from last I or P picture. */ |
||
3745 | |||
3746 | dest[0] = src[0]; |
||
3747 | dest[1] = src[1]; |
||
3748 | dest[2] = src[2]; |
||
3749 | dest[3] = src[3]; |
||
3750 | dest += row_incr; |
||
3751 | src += row_incr; |
||
3752 | |||
3753 | dest[0] = src[0]; |
||
3754 | dest[1] = src[1]; |
||
3755 | dest[2] = src[2]; |
||
3756 | dest[3] = src[3]; |
||
3757 | dest += row_incr; |
||
3758 | src += row_incr; |
||
3759 | } |
||
3760 | |||
3761 | /* |
||
3762 | * Divide row,col to get upper left pixel of macroblock in Cr and Cb |
||
3763 | * planes. |
||
3764 | */ |
||
3765 | |||
3766 | crow = row >> 1; |
||
3767 | ccol = col >> 1; |
||
3768 | |||
3769 | /* For each row in Cr, and Cb planes... */ |
||
3770 | |||
3771 | dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol); |
||
3772 | src = (int *)(vid_stream->future->Cr + (crow * half_row) + ccol); |
||
3773 | dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol); |
||
3774 | src1 = (int *)(vid_stream->future->Cb + (crow * half_row) + ccol); |
||
3775 | |||
3776 | for (rr = 0; rr < 4; rr++) { |
||
3777 | |||
3778 | /* Copy pixel values from last I or P picture. */ |
||
3779 | |||
3780 | dest[0] = src[0]; |
||
3781 | dest[1] = src[1]; |
||
3782 | |||
3783 | dest1[0] = src1[0]; |
||
3784 | dest1[1] = src1[1]; |
||
3785 | |||
3786 | dest += half_row_incr; |
||
3787 | src += half_row_incr; |
||
3788 | dest1 += half_row_incr; |
||
3789 | src1 += half_row_incr; |
||
3790 | |||
3791 | dest[0] = src[0]; |
||
3792 | dest[1] = src[1]; |
||
3793 | |||
3794 | dest1[0] = src1[0]; |
||
3795 | dest1[1] = src1[1]; |
||
3796 | |||
3797 | dest += half_row_incr; |
||
3798 | src += half_row_incr; |
||
3799 | dest1 += half_row_incr; |
||
3800 | src1 += half_row_incr; |
||
3801 | } |
||
3802 | |||
3803 | #ifndef DISABLE_DITHER |
||
3804 | if (ditherType == MBORDERED_DITHER) { |
||
3805 | MBOrderedDitherDisplayCopy(vid_stream, addr, |
||
3806 | 1, 0, 0, 0, 0, 0, |
||
3807 | vid_stream->future->display, |
||
3808 | (unsigned char *) NULL); |
||
3809 | vid_stream->ditherFlags[addr] = 0; |
||
3810 | } |
||
3811 | #endif |
||
3812 | } |
||
3813 | |||
3814 | vid_stream->mblock.recon_right_for_prev = 0; |
||
3815 | vid_stream->mblock.recon_down_for_prev = 0; |
||
3816 | } |
||
3817 | |||
3818 | |||
3819 | |||
3820 | |||
3821 | |||
3822 | /* |
||
3823 | *-------------------------------------------------------------- |
||
3824 | * |
||
3825 | * ProcessSkippedBFrameMBlocks -- |
||
3826 | * |
||
3827 | * Processes skipped macroblocks in B frames. |
||
3828 | * |
||
3829 | * Results: |
||
3830 | * Calculates pixel values for luminance, Cr, and Cb planes |
||
3831 | * in current pict image for skipped macroblocks. |
||
3832 | * |
||
3833 | * Side effects: |
||
3834 | * Pixel values in pict image changed. |
||
3835 | * |
||
3836 | *-------------------------------------------------------------- |
||
3837 | */ |
||
3838 | |||
3839 | static void |
||
3840 | ProcessSkippedBFrameMBlocks(vid_stream) |
||
3841 | VidStream *vid_stream; |
||
3842 | { |
||
3843 | int row_size, half_row, mb_row, mb_col, row, col, rr; |
||
3844 | int right_half_for = 0, down_half_for = 0; |
||
3845 | int c_right_half_for = 0, c_down_half_for = 0; |
||
3846 | int right_half_back = 0, down_half_back = 0; |
||
3847 | int c_right_half_back = 0, c_down_half_back = 0; |
||
3848 | int addr, right_for = 0, down_for = 0; |
||
3849 | int recon_right_for, recon_down_for; |
||
3850 | int recon_right_back, recon_down_back; |
||
3851 | int right_back = 0, down_back = 0; |
||
3852 | int c_right_for = 0, c_down_for = 0; |
||
3853 | int c_right_back = 0, c_down_back = 0; |
||
3854 | unsigned char forw_lum[256]; |
||
3855 | unsigned char forw_cr[64], forw_cb[64]; |
||
3856 | unsigned char back_lum[256], back_cr[64], back_cb[64]; |
||
3857 | int row_incr, half_row_incr; |
||
3858 | int ccol, crow; |
||
3859 | int ditherType=vid_stream->ditherType; |
||
3860 | |||
3861 | /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */ |
||
3862 | |||
3863 | row_size = vid_stream->mb_width << 4; |
||
3864 | half_row = (row_size >> 1); |
||
3865 | row_incr = row_size >> 2; |
||
3866 | half_row_incr = half_row >> 2; |
||
3867 | |||
3868 | /* Establish motion vector codes based on full pixel flag. */ |
||
3869 | |||
3870 | if (vid_stream->picture.full_pel_forw_vector) { |
||
3871 | recon_right_for = vid_stream->mblock.recon_right_for_prev << 1; |
||
3872 | recon_down_for = vid_stream->mblock.recon_down_for_prev << 1; |
||
3873 | } else { |
||
3874 | recon_right_for = vid_stream->mblock.recon_right_for_prev; |
||
3875 | recon_down_for = vid_stream->mblock.recon_down_for_prev; |
||
3876 | } |
||
3877 | |||
3878 | if (vid_stream->picture.full_pel_back_vector) { |
||
3879 | recon_right_back = vid_stream->mblock.recon_right_back_prev << 1; |
||
3880 | recon_down_back = vid_stream->mblock.recon_down_back_prev << 1; |
||
3881 | } else { |
||
3882 | recon_right_back = vid_stream->mblock.recon_right_back_prev; |
||
3883 | recon_down_back = vid_stream->mblock.recon_down_back_prev; |
||
3884 | } |
||
3885 | |||
3886 | |||
3887 | /* If only one motion vector, do display copy, else do full |
||
3888 | calculation. |
||
3889 | */ |
||
3890 | |||
3891 | #ifndef DISABLE_DITHER |
||
3892 | if (ditherType == MBORDERED_DITHER) { |
||
3893 | if (vid_stream->mblock.bpict_past_forw && |
||
3894 | !vid_stream->mblock.bpict_past_back) { |
||
3895 | for (addr = vid_stream->mblock.past_mb_addr+1; |
||
3896 | addr < vid_stream->mblock.mb_address; addr++) { |
||
3897 | |||
3898 | MBOrderedDitherDisplayCopy(vid_stream, addr, |
||
3899 | 1, recon_right_for, recon_down_for, |
||
3900 | 0, 0, 0, vid_stream->past->display, |
||
3901 | vid_stream->future->display); |
||
3902 | vid_stream->ditherFlags[addr] = 0; |
||
3903 | } |
||
3904 | return; |
||
3905 | } |
||
3906 | if (vid_stream->mblock.bpict_past_back && |
||
3907 | !vid_stream->mblock.bpict_past_forw) { |
||
3908 | for (addr = vid_stream->mblock.past_mb_addr+1; |
||
3909 | addr < vid_stream->mblock.mb_address; addr++) { |
||
3910 | |||
3911 | MBOrderedDitherDisplayCopy(vid_stream, addr, |
||
3912 | 0, 0, 0, |
||
3913 | 1, recon_right_back, recon_down_back, |
||
3914 | vid_stream->past->display, vid_stream->future->display); |
||
3915 | vid_stream->ditherFlags[addr] = 0; |
||
3916 | } |
||
3917 | return; |
||
3918 | } |
||
3919 | } |
||
3920 | #endif |
||
3921 | |||
3922 | /* Calculate motion vectors. */ |
||
3923 | |||
3924 | if (vid_stream->mblock.bpict_past_forw) { |
||
3925 | right_for = recon_right_for >> 1; |
||
3926 | down_for = recon_down_for >> 1; |
||
3927 | right_half_for = recon_right_for & 0x1; |
||
3928 | down_half_for = recon_down_for & 0x1; |
||
3929 | |||
3930 | recon_right_for /= 2; |
||
3931 | recon_down_for /= 2; |
||
3932 | c_right_for = recon_right_for >> 1; |
||
3933 | c_down_for = recon_down_for >> 1; |
||
3934 | c_right_half_for = recon_right_for & 0x1; |
||
3935 | c_down_half_for = recon_down_for & 0x1; |
||
3936 | |||
3937 | } |
||
3938 | if (vid_stream->mblock.bpict_past_back) { |
||
3939 | right_back = recon_right_back >> 1; |
||
3940 | down_back = recon_down_back >> 1; |
||
3941 | right_half_back = recon_right_back & 0x1; |
||
3942 | down_half_back = recon_down_back & 0x1; |
||
3943 | |||
3944 | recon_right_back /= 2; |
||
3945 | recon_down_back /= 2; |
||
3946 | c_right_back = recon_right_back >> 1; |
||
3947 | c_down_back = recon_down_back >> 1; |
||
3948 | c_right_half_back = recon_right_back & 0x1; |
||
3949 | c_down_half_back = recon_down_back & 0x1; |
||
3950 | |||
3951 | } |
||
3952 | /* For each skipped macroblock, do... */ |
||
3953 | |||
3954 | for (addr = vid_stream->mblock.past_mb_addr + 1; |
||
3955 | addr < vid_stream->mblock.mb_address; addr++) { |
||
3956 | |||
3957 | /* Calculate macroblock row and col. */ |
||
3958 | |||
3959 | mb_row = addr / vid_stream->mb_width; |
||
3960 | mb_col = addr % vid_stream->mb_width; |
||
3961 | |||
3962 | /* Calculate upper left pixel row,col for luminance plane. */ |
||
3963 | |||
3964 | row = mb_row << 4; |
||
3965 | col = mb_col << 4; |
||
3966 | crow = row / 2; |
||
3967 | ccol = col / 2; |
||
3968 | |||
3969 | /* If forward predicted, calculate prediction values. */ |
||
3970 | |||
3971 | if (vid_stream->mblock.bpict_past_forw) { |
||
3972 | |||
3973 | ReconSkippedBlock(vid_stream->past->luminance, forw_lum, |
||
3974 | row, col, row_size, right_for, down_for, |
||
3975 | right_half_for, down_half_for, 16); |
||
3976 | ReconSkippedBlock(vid_stream->past->Cr, forw_cr, crow, |
||
3977 | ccol, half_row, |
||
3978 | c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8); |
||
3979 | ReconSkippedBlock(vid_stream->past->Cb, forw_cb, crow, |
||
3980 | ccol, half_row, |
||
3981 | c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8); |
||
3982 | } |
||
3983 | /* If back predicted, calculate prediction values. */ |
||
3984 | |||
3985 | if (vid_stream->mblock.bpict_past_back) { |
||
3986 | ReconSkippedBlock(vid_stream->future->luminance, back_lum, |
||
3987 | row, col, row_size, right_back, down_back, |
||
3988 | right_half_back, down_half_back, 16); |
||
3989 | ReconSkippedBlock(vid_stream->future->Cr, back_cr, crow, |
||
3990 | ccol, half_row, |
||
3991 | c_right_back, c_down_back, |
||
3992 | c_right_half_back, c_down_half_back, 8); |
||
3993 | ReconSkippedBlock(vid_stream->future->Cb, back_cb, crow, |
||
3994 | ccol, half_row, |
||
3995 | c_right_back, c_down_back, |
||
3996 | c_right_half_back, c_down_half_back, 8); |
||
3997 | } |
||
3998 | if (vid_stream->mblock.bpict_past_forw && |
||
3999 | !vid_stream->mblock.bpict_past_back) { |
||
4000 | |||
4001 | int *dest, *dest1; |
||
4002 | int *src, *src1; |
||
4003 | dest = (int *)(vid_stream->current->luminance + (row * row_size) + col); |
||
4004 | src = (int *)forw_lum; |
||
4005 | |||
4006 | for (rr = 0; rr < 16; rr++) { |
||
4007 | |||
4008 | /* memcpy(dest, forw_lum+(rr<<4), 16); */ |
||
4009 | dest[0] = src[0]; |
||
4010 | dest[1] = src[1]; |
||
4011 | dest[2] = src[2]; |
||
4012 | dest[3] = src[3]; |
||
4013 | dest += row_incr; |
||
4014 | src += 4; |
||
4015 | } |
||
4016 | |||
4017 | dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol); |
||
4018 | dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol); |
||
4019 | src = (int *)forw_cr; |
||
4020 | src1 = (int *)forw_cb; |
||
4021 | |||
4022 | for (rr = 0; rr < 8; rr++) { |
||
4023 | /* |
||
4024 | * memcpy(dest, forw_cr+(rr<<3), 8); memcpy(dest1, forw_cb+(rr<<3), |
||
4025 | * 8); |
||
4026 | */ |
||
4027 | |||
4028 | dest[0] = src[0]; |
||
4029 | dest[1] = src[1]; |
||
4030 | |||
4031 | dest1[0] = src1[0]; |
||
4032 | dest1[1] = src1[1]; |
||
4033 | |||
4034 | dest += half_row_incr; |
||
4035 | dest1 += half_row_incr; |
||
4036 | src += 2; |
||
4037 | src1 += 2; |
||
4038 | } |
||
4039 | } else if (vid_stream->mblock.bpict_past_back && |
||
4040 | !vid_stream->mblock.bpict_past_forw) { |
||
4041 | |||
4042 | int *src, *src1; |
||
4043 | int *dest, *dest1; |
||
4044 | dest = (int *)(vid_stream->current->luminance + (row * row_size) + col); |
||
4045 | src = (int *)back_lum; |
||
4046 | |||
4047 | for (rr = 0; rr < 16; rr++) { |
||
4048 | dest[0] = src[0]; |
||
4049 | dest[1] = src[1]; |
||
4050 | dest[2] = src[2]; |
||
4051 | dest[3] = src[3]; |
||
4052 | dest += row_incr; |
||
4053 | src += 4; |
||
4054 | } |
||
4055 | |||
4056 | |||
4057 | dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol); |
||
4058 | dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol); |
||
4059 | src = (int *)back_cr; |
||
4060 | src1 = (int *)back_cb; |
||
4061 | |||
4062 | for (rr = 0; rr < 8; rr++) { |
||
4063 | /* |
||
4064 | * memcpy(dest, back_cr+(rr<<3), 8); memcpy(dest1, back_cb+(rr<<3), |
||
4065 | * 8); |
||
4066 | */ |
||
4067 | |||
4068 | dest[0] = src[0]; |
||
4069 | dest[1] = src[1]; |
||
4070 | |||
4071 | dest1[0] = src1[0]; |
||
4072 | dest1[1] = src1[1]; |
||
4073 | |||
4074 | dest += half_row_incr; |
||
4075 | dest1 += half_row_incr; |
||
4076 | src += 2; |
||
4077 | src1 += 2; |
||
4078 | } |
||
4079 | } else { |
||
4080 | |||
4081 | unsigned char *src1, *src2, *src1a, *src2a; |
||
4082 | unsigned char *dest, *dest1; |
||
4083 | dest = vid_stream->current->luminance + (row * row_size) + col; |
||
4084 | src1 = forw_lum; |
||
4085 | src2 = back_lum; |
||
4086 | |||
4087 | for (rr = 0; rr < 16; rr++) { |
||
4088 | dest[0] = (int) (src1[0] + src2[0]) >> 1; |
||
4089 | dest[1] = (int) (src1[1] + src2[1]) >> 1; |
||
4090 | dest[2] = (int) (src1[2] + src2[2]) >> 1; |
||
4091 | dest[3] = (int) (src1[3] + src2[3]) >> 1; |
||
4092 | dest[4] = (int) (src1[4] + src2[4]) >> 1; |
||
4093 | dest[5] = (int) (src1[5] + src2[5]) >> 1; |
||
4094 | dest[6] = (int) (src1[6] + src2[6]) >> 1; |
||
4095 | dest[7] = (int) (src1[7] + src2[7]) >> 1; |
||
4096 | dest[8] = (int) (src1[8] + src2[8]) >> 1; |
||
4097 | dest[9] = (int) (src1[9] + src2[9]) >> 1; |
||
4098 | dest[10] = (int) (src1[10] + src2[10]) >> 1; |
||
4099 | dest[11] = (int) (src1[11] + src2[11]) >> 1; |
||
4100 | dest[12] = (int) (src1[12] + src2[12]) >> 1; |
||
4101 | dest[13] = (int) (src1[13] + src2[13]) >> 1; |
||
4102 | dest[14] = (int) (src1[14] + src2[14]) >> 1; |
||
4103 | dest[15] = (int) (src1[15] + src2[15]) >> 1; |
||
4104 | dest += row_size; |
||
4105 | src1 += 16; |
||
4106 | src2 += 16; |
||
4107 | } |
||
4108 | |||
4109 | |||
4110 | dest = vid_stream->current->Cr + (crow * half_row) + ccol; |
||
4111 | dest1 = vid_stream->current->Cb + (crow * half_row) + ccol; |
||
4112 | src1 = forw_cr; |
||
4113 | src2 = back_cr; |
||
4114 | src1a = forw_cb; |
||
4115 | src2a = back_cb; |
||
4116 | |||
4117 | for (rr = 0; rr < 8; rr++) { |
||
4118 | dest[0] = (int) (src1[0] + src2[0]) >> 1; |
||
4119 | dest[1] = (int) (src1[1] + src2[1]) >> 1; |
||
4120 | dest[2] = (int) (src1[2] + src2[2]) >> 1; |
||
4121 | dest[3] = (int) (src1[3] + src2[3]) >> 1; |
||
4122 | dest[4] = (int) (src1[4] + src2[4]) >> 1; |
||
4123 | dest[5] = (int) (src1[5] + src2[5]) >> 1; |
||
4124 | dest[6] = (int) (src1[6] + src2[6]) >> 1; |
||
4125 | dest[7] = (int) (src1[7] + src2[7]) >> 1; |
||
4126 | dest += half_row; |
||
4127 | src1 += 8; |
||
4128 | src2 += 8; |
||
4129 | |||
4130 | dest1[0] = (int) (src1a[0] + src2a[0]) >> 1; |
||
4131 | dest1[1] = (int) (src1a[1] + src2a[1]) >> 1; |
||
4132 | dest1[2] = (int) (src1a[2] + src2a[2]) >> 1; |
||
4133 | dest1[3] = (int) (src1a[3] + src2a[3]) >> 1; |
||
4134 | dest1[4] = (int) (src1a[4] + src2a[4]) >> 1; |
||
4135 | dest1[5] = (int) (src1a[5] + src2a[5]) >> 1; |
||
4136 | dest1[6] = (int) (src1a[6] + src2a[6]) >> 1; |
||
4137 | dest1[7] = (int) (src1a[7] + src2a[7]) >> 1; |
||
4138 | dest1 += half_row; |
||
4139 | src1a += 8; |
||
4140 | src2a += 8; |
||
4141 | } |
||
4142 | } |
||
4143 | |||
4144 | #ifndef DISABLE_DITHER |
||
4145 | if (ditherType == MBORDERED_DITHER) { |
||
4146 | vid_stream->ditherFlags[addr] = 1; |
||
4147 | } |
||
4148 | #endif |
||
4149 | } |
||
4150 | } |
||
4151 | |||
4152 | |||
4153 | |||
4154 | |||
4155 | |||
4156 | /* |
||
4157 | *-------------------------------------------------------------- |
||
4158 | * |
||
4159 | * ReconSkippedBlock -- |
||
4160 | * |
||
4161 | * Reconstructs predictive block for skipped macroblocks |
||
4162 | * in B Frames. |
||
4163 | * |
||
4164 | * Results: |
||
4165 | * No return values. |
||
4166 | * |
||
4167 | * Side effects: |
||
4168 | * None. |
||
4169 | * |
||
4170 | *-------------------------------------------------------------- |
||
4171 | */ |
||
4172 | |||
4173 | static void |
||
4174 | ReconSkippedBlock(source, dest, row, col, row_size, |
||
4175 | right, down, right_half, down_half, width) |
||
4176 | unsigned char *source; |
||
4177 | unsigned char *dest; |
||
4178 | int row, col, row_size, right, down, right_half, down_half, width; |
||
4179 | { |
||
4180 | int rr; |
||
4181 | unsigned char *source2; |
||
4182 | |||
4183 | source += ((row + down) * row_size) + col + right; |
||
4184 | |||
4185 | if (width == 16) { |
||
4186 | if ((!right_half) && (!down_half)) { |
||
4187 | if (right & 0x1) { |
||
4188 | /* No alignment, use bye copy */ |
||
4189 | for (rr = 0; rr < 16; rr++) { |
||
4190 | dest[0] = source[0]; |
||
4191 | dest[1] = source[1]; |
||
4192 | dest[2] = source[2]; |
||
4193 | dest[3] = source[3]; |
||
4194 | dest[4] = source[4]; |
||
4195 | dest[5] = source[5]; |
||
4196 | dest[6] = source[6]; |
||
4197 | dest[7] = source[7]; |
||
4198 | dest[8] = source[8]; |
||
4199 | dest[9] = source[9]; |
||
4200 | dest[10] = source[10]; |
||
4201 | dest[11] = source[11]; |
||
4202 | dest[12] = source[12]; |
||
4203 | dest[13] = source[13]; |
||
4204 | dest[14] = source[14]; |
||
4205 | dest[15] = source[15]; |
||
4206 | dest += 16; |
||
4207 | source += row_size; |
||
4208 | } |
||
4209 | } else if (right & 0x2) { |
||
4210 | /* Half-word bit aligned, use 16 bit copy */ |
||
4211 | short *src = (short *)source; |
||
4212 | short *d = (short *)dest; |
||
4213 | row_size >>= 1; |
||
4214 | for (rr = 0; rr < 16; rr++) { |
||
4215 | d[0] = src[0]; |
||
4216 | d[1] = src[1]; |
||
4217 | d[2] = src[2]; |
||
4218 | d[3] = src[3]; |
||
4219 | d[4] = src[4]; |
||
4220 | d[5] = src[5]; |
||
4221 | d[6] = src[6]; |
||
4222 | d[7] = src[7]; |
||
4223 | d += 8; |
||
4224 | src += row_size; |
||
4225 | } |
||
4226 | } else { |
||
4227 | /* Word aligned, use 32 bit copy */ |
||
4228 | int *src = (int *)source; |
||
4229 | int *d = (int *)dest; |
||
4230 | row_size >>= 2; |
||
4231 | for (rr = 0; rr < 16; rr++) { |
||
4232 | d[0] = src[0]; |
||
4233 | d[1] = src[1]; |
||
4234 | d[2] = src[2]; |
||
4235 | d[3] = src[3]; |
||
4236 | d += 4; |
||
4237 | src += row_size; |
||
4238 | } |
||
4239 | } |
||
4240 | } else { |
||
4241 | source2 = source + right_half + (row_size * down_half); |
||
4242 | for (rr = 0; rr < width; rr++) { |
||
4243 | dest[0] = (int) (source[0] + source2[0]) >> 1; |
||
4244 | dest[1] = (int) (source[1] + source2[1]) >> 1; |
||
4245 | dest[2] = (int) (source[2] + source2[2]) >> 1; |
||
4246 | dest[3] = (int) (source[3] + source2[3]) >> 1; |
||
4247 | dest[4] = (int) (source[4] + source2[4]) >> 1; |
||
4248 | dest[5] = (int) (source[5] + source2[5]) >> 1; |
||
4249 | dest[6] = (int) (source[6] + source2[6]) >> 1; |
||
4250 | dest[7] = (int) (source[7] + source2[7]) >> 1; |
||
4251 | dest[8] = (int) (source[8] + source2[8]) >> 1; |
||
4252 | dest[9] = (int) (source[9] + source2[9]) >> 1; |
||
4253 | dest[10] = (int) (source[10] + source2[10]) >> 1; |
||
4254 | dest[11] = (int) (source[11] + source2[11]) >> 1; |
||
4255 | dest[12] = (int) (source[12] + source2[12]) >> 1; |
||
4256 | dest[13] = (int) (source[13] + source2[13]) >> 1; |
||
4257 | dest[14] = (int) (source[14] + source2[14]) >> 1; |
||
4258 | dest[15] = (int) (source[15] + source2[15]) >> 1; |
||
4259 | dest += width; |
||
4260 | source += row_size; |
||
4261 | source2 += row_size; |
||
4262 | } |
||
4263 | } |
||
4264 | } else { /* (width == 8) */ |
||
4265 | assert(width == 8); |
||
4266 | if ((!right_half) && (!down_half)) { |
||
4267 | if (right & 0x1) { |
||
4268 | for (rr = 0; rr < width; rr++) { |
||
4269 | dest[0] = source[0]; |
||
4270 | dest[1] = source[1]; |
||
4271 | dest[2] = source[2]; |
||
4272 | dest[3] = source[3]; |
||
4273 | dest[4] = source[4]; |
||
4274 | dest[5] = source[5]; |
||
4275 | dest[6] = source[6]; |
||
4276 | dest[7] = source[7]; |
||
4277 | dest += 8; |
||
4278 | source += row_size; |
||
4279 | } |
||
4280 | } else if (right & 0x02) { |
||
4281 | short *d = (short *)dest; |
||
4282 | short *src = (short *)source; |
||
4283 | row_size >>= 1; |
||
4284 | for (rr = 0; rr < width; rr++) { |
||
4285 | d[0] = src[0]; |
||
4286 | d[1] = src[1]; |
||
4287 | d[2] = src[2]; |
||
4288 | d[3] = src[3]; |
||
4289 | d += 4; |
||
4290 | src += row_size; |
||
4291 | } |
||
4292 | } else { |
||
4293 | int *d = (int *)dest; |
||
4294 | int *src = (int *)source; |
||
4295 | row_size >>= 2; |
||
4296 | for (rr = 0; rr < width; rr++) { |
||
4297 | d[0] = src[0]; |
||
4298 | d[1] = src[1]; |
||
4299 | d += 2; |
||
4300 | src += row_size; |
||
4301 | } |
||
4302 | } |
||
4303 | } else { |
||
4304 | source2 = source + right_half + (row_size * down_half); |
||
4305 | for (rr = 0; rr < width; rr++) { |
||
4306 | dest[0] = (int) (source[0] + source2[0]) >> 1; |
||
4307 | dest[1] = (int) (source[1] + source2[1]) >> 1; |
||
4308 | dest[2] = (int) (source[2] + source2[2]) >> 1; |
||
4309 | dest[3] = (int) (source[3] + source2[3]) >> 1; |
||
4310 | dest[4] = (int) (source[4] + source2[4]) >> 1; |
||
4311 | dest[5] = (int) (source[5] + source2[5]) >> 1; |
||
4312 | dest[6] = (int) (source[6] + source2[6]) >> 1; |
||
4313 | dest[7] = (int) (source[7] + source2[7]) >> 1; |
||
4314 | dest += width; |
||
4315 | source += row_size; |
||
4316 | source2 += row_size; |
||
4317 | } |
||
4318 | } |
||
4319 | } |
||
4320 | } |
||
4321 | |||
4322 | |||
4323 | |||
4324 | |||
4325 | /* |
||
4326 | *-------------------------------------------------------------- |
||
4327 | * |
||
4328 | * DoPictureDisplay -- |
||
4329 | * |
||
4330 | * Converts image from Lum, Cr, Cb to colormap space. Puts |
||
4331 | * image in lum plane. Updates past and future frame |
||
4332 | * pointers. Dithers image. Sends to display mechanism. |
||
4333 | * |
||
4334 | * Results: |
||
4335 | * Pict image structure locked if displaying or if frame |
||
4336 | * is needed as past or future reference. |
||
4337 | * |
||
4338 | * Side effects: |
||
4339 | * Lum plane pummelled. |
||
4340 | * |
||
4341 | *-------------------------------------------------------------- |
||
4342 | */ |
||
4343 | |||
4344 | static void |
||
4345 | DoPictureDisplay(vid_stream, xinfo) |
||
4346 | VidStream *vid_stream; |
||
4347 | XInfo *xinfo; |
||
4348 | { |
||
4349 | |||
4350 | if (No_B_Flag && (vid_stream->picture.code_type == B_TYPE)) return; |
||
4351 | |||
4352 | /* Convert to colormap space and dither. */ |
||
4353 | DoDitherImage(vid_stream); |
||
4354 | |||
4355 | /* Update past and future references if needed. */ |
||
4356 | |||
4357 | if ((vid_stream->picture.code_type == I_TYPE) || (vid_stream->picture.code_type == P_TYPE)) { |
||
4358 | if (vid_stream->future == NULL) { |
||
4359 | vid_stream->future = vid_stream->current; |
||
4360 | vid_stream->future->locked |= FUTURE_LOCK; |
||
4361 | } else { |
||
4362 | if (vid_stream->past != NULL) { |
||
4363 | vid_stream->past->locked &= ~PAST_LOCK; |
||
4364 | } |
||
4365 | vid_stream->past = vid_stream->future; |
||
4366 | vid_stream->past->locked &= ~FUTURE_LOCK; |
||
4367 | vid_stream->past->locked |= PAST_LOCK; |
||
4368 | vid_stream->future = vid_stream->current; |
||
4369 | vid_stream->future->locked |= FUTURE_LOCK; |
||
4370 | vid_stream->current = vid_stream->past; |
||
4371 | #ifndef NOCONTROLS |
||
4372 | ExecuteDisplay(vid_stream, 1, xinfo); |
||
4373 | #else |
||
4374 | ExecuteDisplay(vid_stream, xinfo); |
||
4375 | #endif /* !NOCONTROLS */ |
||
4376 | } |
||
4377 | } else { |
||
4378 | #ifndef NOCONTROLS |
||
4379 | ExecuteDisplay(vid_stream, 1, xinfo); |
||
4380 | #else |
||
4381 | ExecuteDisplay(vid_stream, xinfo); |
||
4382 | #endif /* !NOCONTROLS */ |
||
4383 | } |
||
4384 | } |
||
4385 | |||
4386 | |||
4387 | |||
4388 | |||
4389 | /* |
||
4390 | *-------------------------------------------------------------- |
||
4391 | * |
||
4392 | * SetBFlag -- |
||
4393 | * |
||
4394 | * Called to set no b frame processing flag. |
||
4395 | * |
||
4396 | * Results: |
||
4397 | * No_B_Flag flag is set to its argument. |
||
4398 | * |
||
4399 | * Side effects: |
||
4400 | * None. |
||
4401 | * |
||
4402 | *-------------------------------------------------------------- |
||
4403 | */ |
||
4404 | |||
4405 | void |
||
4406 | SetBFlag(val) |
||
4407 | BOOLEAN val; |
||
4408 | { |
||
4409 | No_B_Flag = val; |
||
4410 | } |
||
4411 | |||
4412 | |||
4413 | |||
4414 | |||
4415 | |||
4416 | /* |
||
4417 | *-------------------------------------------------------------- |
||
4418 | * |
||
4419 | * SetPFlag -- |
||
4420 | * |
||
4421 | * Called to set no p frame processing flag. |
||
4422 | * |
||
4423 | * Results: |
||
4424 | * No_P_Flag flag is set to value of argument |
||
4425 | * |
||
4426 | * Side effects: |
||
4427 | * None. |
||
4428 | * |
||
4429 | *-------------------------------------------------------------- |
||
4430 | */ |
||
4431 | |||
4432 | void |
||
4433 | SetPFlag(val) |
||
4434 | BOOLEAN val; |
||
4435 | { |
||
4436 | No_P_Flag = val; |
||
4437 | } |