diff options
Diffstat (limited to 'TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_client/video.cpp')
-rw-r--r-- | TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_client/video.cpp | 3762 |
1 files changed, 3762 insertions, 0 deletions
diff --git a/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_client/video.cpp b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_client/video.cpp new file mode 100644 index 00000000000..07c106b63a6 --- /dev/null +++ b/TAO/orbsvcs/tests/AVStreams/mpeg/source/mpeg_client/video.cpp @@ -0,0 +1,3762 @@ +/* $Id$ */ + +/* + * Copyright (c) 1992 The Regents of the University of California. + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation for any purpose, without fee, and without written agreement is + * hereby granted, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT + * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF + * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +/* + * This file contains C code that implements + * the video decoder model. + */ + +#include "ace/OS.h" +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> + +#ifndef MIPS +#include <sys/time.h> +#else +#include <sys/types.h> +#include <sys/system.h> +#endif + +#include "include/common.h" +#include "decoders.h" +#include "video.h" +#include "util.h" +#include "proto.h" +#include "global.h" +#include "ui.h" + +ACE_RCSID(mpeg_client, video, "$Id$") + +/* Declarations of functions. */ +static void ReconIMBlock(VidStream *vid_stream, int bnum); +static void ReconPMBlock(VidStream *vid_stream, int bnum, + int recon_right_for, int recon_down_for, int zflag); +static void ReconBMBlock(VidStream *vid_stream, + int bnum, int recon_right_back, + int recon_down_back, int zflag); +static void ReconBiMBlock(VidStream *vid_stream, int bnum, int recon_right_for, + int recon_down_for, int recon_right_back, + int recon_down_back, int zflag); +static void ReconSkippedBlock(unsigned char *source, unsigned char *dest, + int row, int col, int row_size, int right, int down, + int right_half, int down_half, int width); +static int ParseSeqHead(VidStream *vid_stream); +static int ParseGOP(VidStream *vid_stream); +static int ParsePicture(VidStream *vid_stream,TimeStamp time_stamp); +static int ParseSlice(VidStream *vid_stream); +static int ParseMacroBlock(VidStream *vid_stream); +static void ProcessSkippedPFrameMBlocks(VidStream *vid_stream); +static void ProcessSkippedBFrameMBlocks(VidStream *vid_stream); + +extern int ditherType; +char *ditherFlags; + +/* Macro for returning 1 if num is positive, -1 if negative, 0 if 0. */ + +#define Sign(num) ((num > 0) ? 1 : ((num == 0) ? 0 : -1)) + +/* Declare global pointer to vid stream used for current decoding. */ + +VidStream *curVidStream = NULL; + +/* Set up array for fast conversion from zig zag order to row/column + coordinates. +*/ + +int zigzag[64][2] = { + 0, 0, 1, 0, 0, 1, 0, 2, 1, 1, 2, 0, 3, 0, 2, 1, 1, 2, 0, 3, 0, 4, 1, 3, + 2, 2, 3, 1, 4, 0, 5, 0, 4, 1, 3, 2, 2, 3, 1, 4, 0, 5, 0, 6, 1, 5, 2, 4, + 3, 3, 4, 2, 5, 1, 6, 0, 7, 0, 6, 1, 5, 2, 4, 3, 3, 4, 2, 5, 1, 6, 0, 7, + 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6, 2, 7, 1, 7, 2, 6, 3, 5, 4, 4, 5, 3, 6, + 2, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 3, 7, 4, 6, 5, 5, 6, 4, 7, 5, 7, 6, 6, +7, 5, 7, 6, 6, 7, 7, 7}; +/* Array mapping zigzag to array pointer offset. */ + +int zigzag_direct[64] = { + 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, + 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, + 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, +58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63}; +/* Set up array for fast conversion from row/column coordinates to + zig zag order. +*/ + +int scan[8][8] = { + {0, 1, 5, 6, 14, 15, 27, 28}, + {2, 4, 7, 13, 16, 26, 29, 42}, + {3, 8, 12, 17, 25, 30, 41, 43}, + {9, 11, 18, 24, 31, 40, 44, 53}, + {10, 19, 23, 32, 39, 45, 52, 54}, + {20, 22, 33, 38, 46, 51, 55, 60}, + {21, 34, 37, 47, 50, 56, 59, 61}, +{35, 36, 48, 49, 57, 58, 62, 63}}; +/* Initialize P and B skip flags. */ + +static int No_P_Flag = 0; +static int No_B_Flag = 0; + +/* Max lum, chrom indices for illegal block checking. */ + +static int lmaxx; +static int lmaxy; +static int cmaxx; +static int cmaxy; + +/* + * We use a lookup table to make sure values stay in the 0..255 range. + * Since this is cropping (ie, x = (x < 0)?0:(x>255)?255:x; ), wee call this + * table the "crop table". + * MAX_NEG_CROP is the maximum neg/pos value we can handle. + */ + +#define MAX_NEG_CROP 384 +#define NUM_CROP_ENTRIES (256+2*MAX_NEG_CROP) +#define assertCrop(x) assert(((x) >= -MAX_NEG_CROP) && \ + ((x) <= 256+MAX_NEG_CROP)) +static unsigned char cropTbl[NUM_CROP_ENTRIES]; + +/* + The following accounts for time and size spent in various parsing acitivites + if ANALYSIS has been defined. +*/ + +#ifdef ANALYSIS + + +unsigned int bitCount = 0; + +int showmb_flag = 0; +int showEachFlag = 0; + +typedef struct { + int frametype; + unsigned int totsize; + unsigned int number; + unsigned int i_mbsize; + unsigned int p_mbsize; + unsigned int b_mbsize; + unsigned int bi_mbsize; + unsigned int i_mbnum; + unsigned int p_mbnum; + unsigned int b_mbnum; + unsigned int bi_mbnum; + unsigned int i_mbcbp[64]; + unsigned int p_mbcbp[64]; + unsigned int b_mbcbp[64]; + unsigned int bi_mbcbp[64]; + unsigned int i_mbcoeff[64]; + unsigned int p_mbcoeff[64]; + unsigned int b_mbcoeff[64]; + unsigned int bi_mbcoeff[64]; + double tottime; +} Statval; + +Statval stat_a[4]; +unsigned int pictureSizeCount; +unsigned int mbSizeCount; +unsigned int *mbCBPPtr, *mbCoeffPtr, *mbSizePtr; +unsigned int cacheHit[8][8]; +unsigned int cacheMiss[8][8]; + +static void +init_stat_struct(astat) + Statval *astat; +{ + int j; + + astat->frametype = 0; + astat->totsize = 0; + astat->number = 0; + astat->i_mbsize = 0; + astat->p_mbsize = 0; + astat->b_mbsize = 0; + astat->bi_mbsize = 0; + astat->i_mbnum = 0; + astat->p_mbnum = 0; + astat->b_mbnum = 0; + astat->bi_mbnum = 0; + + for (j = 0; j < 64; j++) { + + astat->i_mbcbp[j] = 0; + astat->p_mbcbp[j] = 0; + astat->b_mbcbp[j] = 0; + astat->bi_mbcbp[j] = 0; + astat->i_mbcoeff[j] = 0; + astat->p_mbcoeff[j] = 0; + astat->b_mbcoeff[j] = 0; + astat->bi_mbcoeff[j] = 0; + } + astat->tottime = 0.0; +} + +void +init_stats() +{ + int i, j; + + for (i = 0; i < 4; i++) { + init_stat_struct(&(stat_a[i])); + stat_a[i].frametype = i; + } + + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + cacheHit[i][j] = 0; + cacheMiss[i][j] = 0; + } + } + + bitCount = 0; +} + +static void +PrintOneStat() +{ + int i; + + printf("\n"); + switch (stat_a[0].frametype) { + case I_TYPE: + printf("I FRAME\n"); + break; + case P_TYPE: + printf("P FRAME\n"); + break; + case B_TYPE: + printf("B FRAME\n"); + break; + } + + printf("Size: %d bytes + %d bits\n", stat_a[0].totsize / 8, stat_a[0].totsize % 8); + if (stat_a[0].i_mbnum > 0) { + printf("\tI Macro Block Stats:\n"); + printf("\t%d I Macroblocks\n", stat_a[0].i_mbnum); + printf("\tAvg. Size: %d bytes + %d bits\n", + stat_a[0].i_mbsize / (8 * stat_a[0].i_mbnum), + (stat_a[0].i_mbsize * stat_a[0].i_mbnum) % 8); + printf("\t\tCoded Block Pattern Histogram:\n"); + for (i = 0; i < 64; i += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcbp[i], + stat_a[0].i_mbcbp[i + 1], stat_a[0].i_mbcbp[i + 2], stat_a[0].i_mbcbp[i + 3], + stat_a[0].i_mbcbp[i + 4], stat_a[0].i_mbcbp[i + 5], stat_a[0].i_mbcbp[i + 6], + stat_a[0].i_mbcbp[i + 7]); + } + printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); + for (i = 0; i < 64; i += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].i_mbcoeff[i], + stat_a[0].i_mbcoeff[i + 1], stat_a[0].i_mbcoeff[i + 2], + stat_a[0].i_mbcoeff[i + 3], stat_a[0].i_mbcoeff[i + 4], + stat_a[0].i_mbcoeff[i + 5], stat_a[0].i_mbcoeff[i + 6], + stat_a[0].i_mbcoeff[i + 7]); + } + } + if (stat_a[0].p_mbnum > 0) { + printf("\tP Macro Block Stats:\n"); + printf("\t%d P Macroblocks\n", stat_a[0].p_mbnum); + printf("\tAvg. Size: %d bytes + %d bits\n", + stat_a[0].p_mbsize / (8 * stat_a[0].p_mbnum), + (stat_a[0].p_mbsize / stat_a[0].p_mbnum) % 8); + printf("\t\tCoded Block Pattern Histogram:\n"); + for (i = 0; i < 64; i += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcbp[i], + stat_a[0].p_mbcbp[i + 1], stat_a[0].p_mbcbp[i + 2], stat_a[0].p_mbcbp[i + 3], + stat_a[0].p_mbcbp[i + 4], stat_a[0].p_mbcbp[i + 5], stat_a[0].p_mbcbp[i + 6], + stat_a[0].p_mbcbp[i + 7]); + } + printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); + for (i = 0; i < 64; i += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].p_mbcoeff[i], + stat_a[0].p_mbcoeff[i + 1], stat_a[0].p_mbcoeff[i + 2], + stat_a[0].p_mbcoeff[i + 3], stat_a[0].p_mbcoeff[i + 4], + stat_a[0].p_mbcoeff[i + 5], stat_a[0].p_mbcoeff[i + 6], + stat_a[0].p_mbcoeff[i + 7]); + } + } + if (stat_a[0].b_mbnum > 0) { + printf("\tB Macro Block Stats:\n"); + printf("\t%d B Macroblocks\n", stat_a[0].b_mbnum); + printf("\tAvg. Size: %d bytes + %d bits\n", + stat_a[0].b_mbsize / (8 * stat_a[0].b_mbnum), + (stat_a[0].b_mbsize / stat_a[0].b_mbnum) % 8); + printf("\t\tCoded Block Pattern Histogram:\n"); + for (i = 0; i < 64; i += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcbp[i], + stat_a[0].b_mbcbp[i + 1], stat_a[0].b_mbcbp[i + 2], stat_a[0].b_mbcbp[i + 3], + stat_a[0].b_mbcbp[i + 4], stat_a[0].b_mbcbp[i + 5], stat_a[0].b_mbcbp[i + 6], + stat_a[0].b_mbcbp[i + 7]); + } + printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); + for (i = 0; i < 64; i += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].b_mbcoeff[i], + stat_a[0].b_mbcoeff[i + 1], stat_a[0].b_mbcoeff[i + 2], + stat_a[0].b_mbcoeff[i + 3], stat_a[0].b_mbcoeff[i + 4], + stat_a[0].b_mbcoeff[i + 5], stat_a[0].b_mbcoeff[i + 6], + stat_a[0].b_mbcoeff[i + 7]); + } + } + if (stat_a[0].bi_mbnum > 0) { + printf("\tBi Macro Block Stats:\n"); + printf("\t%d Bi Macroblocks\n", stat_a[0].bi_mbnum); + printf("\tAvg. Size: %d bytes + %d bits\n", + stat_a[0].bi_mbsize / (8 * stat_a[0].bi_mbnum), + (stat_a[0].bi_mbsize * stat_a[0].bi_mbnum) % 8); + printf("\t\tCoded Block Pattern Histogram:\n"); + for (i = 0; i < 64; i += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcbp[i], + stat_a[0].bi_mbcbp[i + 1], stat_a[0].bi_mbcbp[i + 2], stat_a[0].bi_mbcbp[i + 3], + stat_a[0].bi_mbcbp[i + 4], stat_a[0].bi_mbcbp[i + 5], stat_a[0].bi_mbcbp[i + 6], + stat_a[0].bi_mbcbp[i + 7]); + } + printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); + for (i = 0; i < 64; i += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[0].bi_mbcoeff[i], + stat_a[0].bi_mbcoeff[i + 1], stat_a[0].bi_mbcoeff[i + 2], + stat_a[0].bi_mbcoeff[i + 3], stat_a[0].bi_mbcoeff[i + 4], + stat_a[0].bi_mbcoeff[i + 5], stat_a[0].bi_mbcoeff[i + 6], + stat_a[0].bi_mbcoeff[i + 7]); + } + } + printf("\nTime to Decode: %g secs.\n", stat_a[0].tottime); + printf("****************\n"); +} + +void +PrintAllStats() +{ + int i, j; + unsigned int supertot, supernum; + double supertime; + + printf("\n"); + printf("General Info: \n"); + printf("Width: %d\nHeight: %d\n", curVidStream->mb_width * 16, curVidStream->mb_height * 16); + + for (i = 1; i < 4; i++) { + + if (stat_a[i].number == 0) + continue; + + switch (i) { + case 1: + printf("I FRAMES\n"); + break; + case 2: + printf("P FRAMES\n"); + break; + case 3: + printf("B FRAMES\n"); + break; + } + + printf("Number: %d\n", stat_a[i].number); + printf("Avg. Size: %d bytes + %d bits\n", + stat_a[i].totsize / (8 * stat_a[i].number), (stat_a[i].totsize / stat_a[i].number) % 8); + if (stat_a[i].i_mbnum > 0) { + printf("\tI Macro Block Stats:\n"); + printf("\t%d I Macroblocks\n", stat_a[i].i_mbnum); + printf("\tAvg. Size: %d bytes + %d bits\n", + stat_a[i].i_mbsize / (8 * stat_a[i].i_mbnum), + (stat_a[i].i_mbsize / stat_a[i].i_mbnum) % 8); + printf("\t\tCoded Block Pattern Histogram:\n"); + for (j = 0; j < 64; j += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcbp[j], + stat_a[i].i_mbcbp[j + 1], stat_a[i].i_mbcbp[j + 2], stat_a[i].i_mbcbp[j + 3], + stat_a[i].i_mbcbp[j + 4], stat_a[i].i_mbcbp[j + 5], stat_a[i].i_mbcbp[j + 6], + stat_a[i].i_mbcbp[j + 7]); + } + printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); + for (j = 0; j < 64; j += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].i_mbcoeff[j], + stat_a[i].i_mbcoeff[j + 1], stat_a[i].i_mbcoeff[j + 2], + stat_a[i].i_mbcoeff[j + 3], stat_a[i].i_mbcoeff[j + 4], + stat_a[i].i_mbcoeff[j + 5], stat_a[i].i_mbcoeff[j + 6], + stat_a[i].i_mbcoeff[j + 7]); + } + } + if (stat_a[i].p_mbnum > 0) { + printf("\tP Macro Block Stats:\n"); + printf("\t%d P Macroblocks\n", stat_a[i].p_mbnum); + printf("\tAvg. Size: %d bytes + %d bits\n", + stat_a[i].p_mbsize / (8 * stat_a[i].p_mbnum), + (stat_a[i].p_mbsize / stat_a[i].p_mbnum) % 8); + printf("\t\tCoded Block Pattern Histogram:\n"); + for (j = 0; j < 64; j += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcbp[j], + stat_a[i].p_mbcbp[j + 1], stat_a[i].p_mbcbp[j + 2], stat_a[i].p_mbcbp[j + 3], + stat_a[i].p_mbcbp[j + 4], stat_a[i].p_mbcbp[j + 5], stat_a[i].p_mbcbp[j + 6], + stat_a[i].p_mbcbp[j + 7]); + } + printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); + for (j = 0; j < 64; j += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].p_mbcoeff[j], + stat_a[i].p_mbcoeff[j + 1], stat_a[i].p_mbcoeff[j + 2], + stat_a[i].p_mbcoeff[j + 3], stat_a[i].p_mbcoeff[j + 4], + stat_a[i].p_mbcoeff[j + 5], stat_a[i].p_mbcoeff[j + 6], + stat_a[i].p_mbcoeff[j + 7]); + } + } + if (stat_a[i].b_mbnum > 0) { + printf("\tB Macro Block Stats:\n"); + printf("\t%d B Macroblocks\n", stat_a[i].b_mbnum); + printf("\tAvg. Size: %d bytes + %d bits\n", + stat_a[i].b_mbsize / (8 * stat_a[i].b_mbnum), + (stat_a[i].b_mbsize * stat_a[i].b_mbnum) % 8); + printf("\t\tCoded Block Pattern Histogram:\n"); + for (j = 0; j < 64; j += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcbp[j], + stat_a[i].b_mbcbp[j + 1], stat_a[i].b_mbcbp[j + 2], stat_a[i].b_mbcbp[j + 3], + stat_a[i].b_mbcbp[j + 4], stat_a[i].b_mbcbp[j + 5], stat_a[i].b_mbcbp[j + 6], + stat_a[i].b_mbcbp[j + 7]); + } + printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); + for (j = 0; j < 64; j += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].b_mbcoeff[j], + stat_a[i].b_mbcoeff[j + 1], stat_a[i].b_mbcoeff[j + 2], + stat_a[i].b_mbcoeff[j + 3], stat_a[i].b_mbcoeff[j + 4], + stat_a[i].b_mbcoeff[j + 5], stat_a[i].b_mbcoeff[j + 6], + stat_a[i].b_mbcoeff[j + 7]); + } + } + if (stat_a[i].bi_mbnum > 0) { + printf("\tBi Macro Block Stats:\n"); + printf("\t%d Bi Macroblocks\n", stat_a[i].bi_mbnum); + printf("\tAvg. Size: %d bytes + %d bits\n", + stat_a[i].bi_mbsize / (8 * stat_a[i].bi_mbnum), + (stat_a[i].bi_mbsize * stat_a[i].bi_mbnum) % 8); + printf("\t\tCoded Block Pattern Histogram:\n"); + for (j = 0; j < 64; j += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcbp[j], + stat_a[i].bi_mbcbp[j + 1], stat_a[i].bi_mbcbp[j + 2], stat_a[i].bi_mbcbp[j + 3], + stat_a[i].bi_mbcbp[j + 4], stat_a[i].bi_mbcbp[j + 5], stat_a[i].bi_mbcbp[j + 6], + stat_a[i].bi_mbcbp[j + 7]); + } + printf("\n\t\tNumber of Coefficients/Block Histogram:\n"); + for (j = 0; j < 64; j += 8) { + printf("\t%.6d %.6d %.6d %.6d %.6d %.6d %.6d %.6d\n", stat_a[i].bi_mbcoeff[j], + stat_a[i].bi_mbcoeff[j + 1], stat_a[i].bi_mbcoeff[j + 2], + stat_a[i].bi_mbcoeff[j + 3], stat_a[i].bi_mbcoeff[j + 4], + stat_a[i].bi_mbcoeff[j + 5], stat_a[i].bi_mbcoeff[j + 6], + stat_a[i].bi_mbcoeff[j + 7]); + } + } + printf("\nAvg. Time to Decode: %f secs.\n", + (stat_a[i].tottime / ((double) stat_a[i].number))); + printf("\n"); + printf("*************************\n\n"); + } + + supertot = stat_a[1].totsize + stat_a[2].totsize + stat_a[3].totsize; + supernum = stat_a[1].number + stat_a[2].number + stat_a[3].number; + supertime = stat_a[1].tottime + stat_a[2].tottime + stat_a[3].tottime; + + printf("Total Number of Frames: %d\n", supernum); + printf("Avg Frame Size: %d bytes %d bits\n", + supertot / (8 * supernum), (supertot / supernum) % 8); + printf("Total Time Decoding: %g secs.\n", supertime); + printf("Avg Decoding Time/Frame: %g secs.\n", supertime / ((double) supernum)); + printf("Avg Decoding Frames/Sec: %g secs.\n", ((double) supernum) / supertime); + printf("\n"); + + printf("Cache Hits/Miss\n"); + for (i = 0; i < 8; i++) { + printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n", + cacheHit[i][0], cacheMiss[i][0], cacheHit[i][1], cacheMiss[i][1], + cacheHit[i][2], cacheMiss[i][2], cacheHit[i][3], cacheMiss[i][3]); + printf("%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\t%.6d/%.6d\n", + cacheHit[i][4], cacheMiss[i][4], cacheHit[i][5], cacheMiss[i][5], + cacheHit[i][6], cacheMiss[i][6], cacheHit[i][7], cacheMiss[i][7]); + } + +} + +static void +CollectStats() +{ + int i, j; + + i = stat_a[0].frametype; + + stat_a[i].totsize += stat_a[0].totsize; + stat_a[i].number += stat_a[0].number; + stat_a[i].i_mbsize += stat_a[0].i_mbsize; + stat_a[i].p_mbsize += stat_a[0].p_mbsize; + stat_a[i].b_mbsize += stat_a[0].b_mbsize; + stat_a[i].bi_mbsize += stat_a[0].bi_mbsize; + stat_a[i].i_mbnum += stat_a[0].i_mbnum; + stat_a[i].p_mbnum += stat_a[0].p_mbnum; + stat_a[i].b_mbnum += stat_a[0].b_mbnum; + stat_a[i].bi_mbnum += stat_a[0].bi_mbnum; + + for (j = 0; j < 64; j++) { + + stat_a[i].i_mbcbp[j] += stat_a[0].i_mbcbp[j]; + stat_a[i].p_mbcbp[j] += stat_a[0].p_mbcbp[j]; + stat_a[i].b_mbcbp[j] += stat_a[0].b_mbcbp[j]; + stat_a[i].bi_mbcbp[j] += stat_a[0].bi_mbcbp[j]; + stat_a[i].i_mbcoeff[j] += stat_a[0].i_mbcoeff[j]; + stat_a[i].p_mbcoeff[j] += stat_a[0].p_mbcoeff[j]; + stat_a[i].b_mbcoeff[j] += stat_a[0].b_mbcoeff[j]; + stat_a[i].bi_mbcoeff[j] += stat_a[0].bi_mbcoeff[j]; + } + + stat_a[i].tottime += stat_a[0].tottime; + + init_stat_struct(&(stat_a[0])); +} + +static unsigned int +bitCountRead() +{ + return bitCount; +} + +static void +StartTime() +{ + stat_a[0].tottime = ReadSysClock(); +} + +static void +EndTime() +{ + stat_a[0].tottime = ReadSysClock() - stat_a[0].tottime; +} +#endif + +double realTimeStart; +int totNumFrames = 0; + +double +ReadSysClock() +{ + struct timeval tv; + (void) gettimeofday(&tv, (struct timezone *)NULL); + return (tv.tv_sec + tv.tv_usec / 1000000.0); +} + +void +PrintTimeInfo() +{ + double spent; + + spent = ReadSysClock() - realTimeStart; + + if (!quietFlag) { + printf("\nReal Time Spent (After Initializations): %f secs.\n", spent); + printf("Avg. Frames/Sec: %f\n", ((double) totNumFrames) / spent); +/* + print_delta(); +*/ + } +} + + + +/* + *-------------------------------------------------------------- + * + * NewVidStream -- + * + * Allocates and initializes a VidStream structure. Takes + * as parameter requested size for buffer length. + * + * Results: + * A pointer to the new VidStream structure. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +VidStream * NewVidStream(void) +{ + int i, j; + VidStream *new_stream; + static unsigned char default_intra_matrix[64] = { + 8, 16, 19, 22, 26, 27, 29, 34, + 16, 16, 22, 24, 27, 29, 34, 37, + 19, 22, 26, 27, 29, 34, 34, 38, + 22, 22, 26, 27, 29, 34, 37, 40, + 22, 26, 27, 29, 32, 35, 40, 48, + 26, 27, 29, 32, 35, 40, 48, 58, + 26, 27, 29, 34, 38, 46, 56, 69, + 27, 29, 35, 38, 46, 56, 69, 83}; + + /* Allocate memory for new structure. */ + + new_stream = (VidStream *) ACE_OS::malloc(sizeof(VidStream)); + + /* Initialize pointers to extension and user data. */ + + new_stream->group.ext_data = new_stream->group.user_data = + new_stream->picture.extra_info = new_stream->picture.user_data = + new_stream->picture.ext_data = new_stream->slice.extra_info = + new_stream->ext_data = new_stream->user_data = NULL; + + /* Copy default intra matrix. */ + + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + new_stream->intra_quant_matrix[j][i] = default_intra_matrix[i * 8 + j]; + } + } + + /* Initialize crop table. */ + + for (i = (-MAX_NEG_CROP); i < NUM_CROP_ENTRIES - MAX_NEG_CROP; i++) { + if (i <= 0) { + cropTbl[i + MAX_NEG_CROP] = 0; + } else if (i >= 255) { + cropTbl[i + MAX_NEG_CROP] = 255; + } else { + cropTbl[i + MAX_NEG_CROP] = i; + } + } + + /* Initialize non intra quantization matrix. */ + + for (i = 0; i < 8; i++) { + for (j = 0; j < 8; j++) { + new_stream->non_intra_quant_matrix[j][i] = 16; + } + } + + /* Initialize pointers to image spaces. */ + + new_stream->current = new_stream->past = new_stream->future = NULL; + for (i = 0; i < RING_BUF_SIZE; i++) { + new_stream->ring[i] = NULL; + } + + + /* Initialize bitstream i/o fields. */ + + new_stream->max_buf_length = 0; + new_stream->bit_offset = 0; + new_stream->buf_length = 0; + new_stream->buffer = new_stream->buf_start = NULL; + + + /* Return structure. */ + + return new_stream; +} + + + +/* + *-------------------------------------------------------------- + * + * DestroyVidStream -- + * + * Deallocates a VidStream structure. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +void +DestroyVidStream(VidStream *astream) +{ + int i; + + if (astream->ext_data != NULL) + ACE_OS::free (astream->ext_data); + + if (astream->user_data != NULL) + ACE_OS::free (astream->user_data); + + if (astream->group.ext_data != NULL) + ACE_OS::free (astream->group.ext_data); + + if (astream->group.user_data != NULL) + ACE_OS::free (astream->group.user_data); + + if (astream->picture.extra_info != NULL) + ACE_OS::free (astream->picture.extra_info); + + if (astream->picture.ext_data != NULL) + ACE_OS::free (astream->picture.ext_data); + + if (astream->picture.user_data != NULL) + ACE_OS::free (astream->picture.user_data); + + if (astream->slice.extra_info != NULL) + ACE_OS::free (astream->slice.extra_info); + + if (astream->buf_start != NULL) + ACE_OS::free (astream->buf_start); + + for (i = 0; i < RING_BUF_SIZE; i++) { + if (astream->ring[i] != NULL) { + DestroyPictImage(astream->ring[i]); + astream->ring[i] = NULL; + } + } + + ACE_OS::free ((char *) astream); +} + + + + +/* + *-------------------------------------------------------------- + * + * NewPictImage -- + * + * Allocates and initializes a PictImage structure. + * The width and height of the image space are passed in + * as parameters. + * + * Results: + * A pointer to the new PictImage structure. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +PictImage * +NewPictImage(unsigned int width, unsigned int height) +{ + PictImage *new_pi; + + /* Allocate memory space for new structure. */ + + new_pi = (PictImage *) ACE_OS::malloc(sizeof(PictImage)); + new_pi->luminance = (unsigned char *) ACE_OS::malloc(width * height); + new_pi->Cr = (unsigned char *) ACE_OS::malloc(width * height / 4); + new_pi->Cb = (unsigned char *) ACE_OS::malloc(width * height / 4); + + /* Reset locked flag. */ + + new_pi->locked = 0; + + /* Return pointer to new structure. */ + + return new_pi; +} + + + +/* + *-------------------------------------------------------------- + * + * DestroyPictImage -- + * + * Deallocates a PictImage structure. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ +void +DestroyPictImage(PictImage *apictimage) +{ + if (apictimage->luminance != NULL) { + ACE_OS::free (apictimage->luminance); + } + if (apictimage->Cr != NULL) { + ACE_OS::free (apictimage->Cr); + } + if (apictimage->Cb != NULL) { + ACE_OS::free (apictimage->Cb); + } + ACE_OS::free (apictimage); +} + + + +/* + *-------------------------------------------------------------- + * + * mpegVidRsrc -- + * + * Parses bit stream until a picture is decoded + * + * Results: + * 0 - successfully decoded a frame, -1 - failed + * + * Side effects: + * Bit stream is irreversibly parsed. + * + *-------------------------------------------------------------- + */ +int mpegVidRsrc(char *packet) +{ + TimeStamp time_stamp = 0; + VidStream *vid_stream = curVidStream; + unsigned int data; + int i, status; + VideoPacket *p = (VideoPacket *) packet; + + /* initialize buffer info and allocate ring item for current frame */ + (curVidStream->buf_start) = (curVidStream->buffer) = + (unsigned int *)(packet + sizeof(*p)); + curVidStream->max_buf_length = curVidStream->buf_length = + (p->dataBytes + 11)>>2; + curVidStream->bit_offset = 0; + + i = 0; + while (curVidStream->ring[i]->locked != 0) + if (++i >= RING_BUF_SIZE) { + ACE_OS::perror ("VD fatal error. Ring buffer full."); + ACE_OS::exit (1); + } + curVidStream->current = curVidStream->ring[i]; + curVidStream->current->sh = p->sh; + curVidStream->current->gop = p->gop; + curVidStream->current->frame = p->frame; + curVidStream->current->display = p->display; + curVidStream->current->future = p->future; + curVidStream->current->past = p->past; + + bitOffset = curVidStream->bit_offset; +#ifdef UTIL2 + curBits = *curVidStream->buffer << bitOffset; +#else + curBits = *curVidStream->buffer; +#endif + bufLength = curVidStream->buf_length; + bitBuffer = curVidStream->buffer; + + /* + * If called for the INIT command, find start code, make sure it is a + * sequence start code. + */ + + if (shared->cmd == CmdINIT) { + next_start_code(); + show_bits32(data); + if (data != SEQ_START_CODE) { + fprintf(stderr, "VD error: This is not first packet of the an MPEG stream, data %u.", data); + DestroyVidStream(curVidStream); + ACE_OS::exit (1); + } + } + /* Get next 32 bits (size of start codes). */ + + show_bits32(data); + + /* Process according to start code */ + + switch (data) + { + case SEQ_END_CODE: + + /* Display last frame. */ + /* + fprintf(stderr, "VD: SEQ_END_CODE decoded.\n"); + */ + if (vid_stream->future != NULL) + { + vid_stream->current = vid_stream->future; + return 0; + } + else + { + fprintf(stderr, "VD error: no more picture for SEQ_END_CODE\n"); + return -1; + } + + case SEQ_START_CODE: + + /* Sequence start code. Parse sequence header. */ + + if (ParseSeqHead(vid_stream) != PARSE_OK) + { + fprintf(stderr, "VD error on decoding SequenceHeader.\n"); + return -1; + } + + /* + * modify vid_stream after sequence start code so that application above can use + * info in header. + */ + + vid_stream->buffer = bitBuffer; + vid_stream->buf_length = bufLength; + vid_stream->bit_offset = bitOffset; + vid_stream->shid = ((VideoPacket *)packet)->sh; + + case GOP_START_CODE: + + /* Group of Pictures start code. Parse gop header. */ + + if (ParseGOP(vid_stream) != PARSE_OK) + { + fprintf(stderr, "VD error on decoding GOP\n"); + return -1; + } + + vid_stream->gopid = ((VideoPacket *)packet)->gop; + + case PICTURE_START_CODE: + + /* Picture start code. Parse picture header and first slice header. */ + + if (vid_stream->gopid != ((VideoPacket *)packet)->gop || + vid_stream->shid != ((VideoPacket *)packet)->sh) + { + shared->needHeader = 1; + /* + fprintf(stderr, "VD error: SeqHeader and/or GOP not available for the picture"); + */ + return -1; + } + + if (ParsePicture(vid_stream, time_stamp) != PARSE_OK) + { + /* + fprintf(stderr, "VD error on parsing Picture header\n"); + */ + return -1; + } + /* parse all the following slices */ + for (;;) + { + if (ParseSlice(vid_stream) != PARSE_OK) + { + fprintf(stderr, "VD error on decoding a Slice header.\n"); + return -1; + } + /* Parse all following macroblocks. */ + for (;;) + { + int res; + /* Check to see if actually a startcode and not a macroblock. */ + if (!next_bits(23, 0x00000000)) + { + /* Not start code. Parse Macroblock. */ + if ((res = ParseMacroBlock(vid_stream)) != PARSE_OK) + { + fprintf(stderr, "VD error on parsing a MacroBlock, res = %d\n", res); + return -1; + } + } + else + { + /* Not macroblock, actually start code. Get start code. */ + next_start_code(); + show_bits32(data); + + /* If start code is outside range of slice start codes, frame is + complete, display frame, otherwise another slice */ + if ((data < SLICE_MIN_START_CODE) || (data > SLICE_MAX_START_CODE)) + return 0; + else + break; + } + } + } + break; + default: + fprintf(stderr, "VD error: fail to clasify the packet.\n"); + return -1; + } + fprintf(stderr, "VD get wired.\n"); + return -1; +} + + +/* + *-------------------------------------------------------------- + * + * ParseSeqHead -- + * + * Assumes bit stream is at the begining of the sequence + * header start code. Parses off the sequence header. + * + * Results: + * Fills the vid_stream structure with values derived and + * decoded from the sequence header. Allocates the pict image + * structures based on the dimensions of the image space + * found in the sequence header. + * + * Side effects: + * Bit stream irreversibly parsed off. + * + *-------------------------------------------------------------- + */ + +static int +ParseSeqHead(VidStream *vid_stream) +{ + + unsigned int data; + int i; + + /* Flush off sequence start code. */ + + flush_bits32; + + /* Get horizontal size of image space. */ + + get_bits12(data); + vid_stream->h_size = data; + + /* Get vertical size of image space. */ + + get_bits12(data); + vid_stream->v_size = data; + + /* Calculate macroblock width and height of image space. */ + + vid_stream->mb_width = (vid_stream->h_size + 15) / 16; + vid_stream->mb_height = (vid_stream->v_size + 15) / 16; + + /* If dither type is MBORDERED allocate ditherFlags. */ + + if (ditherType == MBORDERED_DITHER) { + ditherFlags = (char *) ACE_OS::malloc(vid_stream->mb_width*vid_stream->mb_height); + } + + /* Initialize lmaxx, lmaxy, cmaxx, cmaxy. */ + + lmaxx = vid_stream->mb_width*16-1; + lmaxy = vid_stream->mb_height*16-1; + cmaxx = vid_stream->mb_width*8-1; + cmaxy = vid_stream->mb_height*8-1; + + /* Parse of aspect ratio code. */ + + get_bits4(data); + vid_stream->aspect_ratio = (unsigned char) data; + + /* Parse off picture rate code. */ + + get_bits4(data); + vid_stream->picture_rate = (unsigned char) data; + + /* Parse off bit rate. */ + + get_bits18(data); + vid_stream->bit_rate = data; + + /* Flush marker bit. */ + + flush_bits(1); + + /* Parse off vbv buffer size. */ + + get_bits10(data); + vid_stream->vbv_buffer_size = data; + + /* Parse off contrained parameter flag. */ + + get_bits1(data); + if (data) { + vid_stream->const_param_flag = TRUE; + } else + vid_stream->const_param_flag = FALSE; + + /* + * If intra_quant_matrix_flag set, parse off intra quant matrix values. + */ + + get_bits1(data); + if (data) { + for (i = 0; i < 64; i++) { + get_bits8(data); + + vid_stream->intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] = + (unsigned char) data; + } + } + /* + * If non intra quant matrix flag set, parse off non intra quant matrix + * values. + */ + + get_bits1(data); + if (data) { + for (i = 0; i < 64; i++) { + get_bits8(data); + + vid_stream->non_intra_quant_matrix[zigzag[i][1]][zigzag[i][0]] = + (unsigned char) data; + } + } + /* Go to next start code. */ + + next_start_code(); + + /* + * If next start code is extension start code, parse off extension data. + */ + + if (next_bits(32, EXT_START_CODE)) { + flush_bits32; + if (vid_stream->ext_data != NULL) { + ACE_OS::free (vid_stream->ext_data); + vid_stream->ext_data = NULL; + } + vid_stream->ext_data = get_ext_data(); + } + /* If next start code is user start code, parse off user data. */ + + if (next_bits(32, USER_START_CODE)) { + flush_bits32; + if (vid_stream->user_data != NULL) { + ACE_OS::free (vid_stream->user_data); + vid_stream->user_data = NULL; + } + vid_stream->user_data = get_ext_data(); + } + return PARSE_OK; +} + + + +/* + *-------------------------------------------------------------- + * + * ParseGOP -- + * + * Parses of group of pictures header from bit stream + * associated with vid_stream. + * + * Results: + * Values in gop header placed into video stream structure. + * + * Side effects: + * Bit stream irreversibly parsed. + * + *-------------------------------------------------------------- + */ + +static int +ParseGOP(VidStream *vid_stream) +{ + unsigned int data; + + /* Flush group of pictures start code. WWWWWWOOOOOOOSSSSSSHHHHH!!! */ + + flush_bits32; + + /* Parse off drop frame flag. */ + + get_bits1(data); + if (data) { + vid_stream->group.drop_flag = TRUE; + } else + vid_stream->group.drop_flag = FALSE; + + /* Parse off hour component of time code. */ + + get_bits5(data); + vid_stream->group.tc_hours = data; + + /* Parse off minute component of time code. */ + + get_bits6(data); + vid_stream->group.tc_minutes = data; + + /* Flush marker bit. */ + + flush_bits(1); + + /* Parse off second component of time code. */ + + get_bits6(data); + vid_stream->group.tc_seconds = data; + + /* Parse off picture count component of time code. */ + + get_bits6(data); + vid_stream->group.tc_pictures = data; + /* + Fprintf(stderr, "GOP time_code:%d:%02d:%02d-%02d\n", + vid_stream->group.tc_hours, + vid_stream->group.tc_minutes, + vid_stream->group.tc_seconds, + vid_stream->group.tc_pictures); + */ + /* Parse off closed gop and broken link flags. */ + + get_bits2(data); + if (data > 1) { + vid_stream->group.closed_gop = TRUE; + if (data > 2) { + vid_stream->group.broken_link = TRUE; + } else + vid_stream->group.broken_link = FALSE; + } else { + vid_stream->group.closed_gop = FALSE; + if (data) { + vid_stream->group.broken_link = TRUE; + } else + vid_stream->group.broken_link = FALSE; + } + + /* Goto next start code. */ + + next_start_code(); + + /* If next start code is extension data, parse off extension data. */ + + if (next_bits(32, EXT_START_CODE)) { + flush_bits32; + if (vid_stream->group.ext_data != NULL) { + ACE_OS::free (vid_stream->group.ext_data); + vid_stream->group.ext_data = NULL; + } + vid_stream->group.ext_data = get_ext_data(); + } + /* If next start code is user data, parse off user data. */ + + if (next_bits(32, USER_START_CODE)) { + flush_bits32; + if (vid_stream->group.user_data != NULL) { + ACE_OS::free (vid_stream->group.user_data); + vid_stream->group.user_data = NULL; + } + vid_stream->group.user_data = get_ext_data(); + } + return PARSE_OK; +} + + + +/* + *-------------------------------------------------------------- + * + * ParsePicture -- + * + * Parses picture header. Marks picture to be presented + * at particular time given a time stamp. + * + * Results: + * Values from picture header put into video stream structure. + * + * Side effects: + * Bit stream irreversibly parsed. + * + *-------------------------------------------------------------- + */ + +static int +ParsePicture(VidStream *vid_stream,TimeStamp time_stamp) +{ + unsigned int data; + int i; + + /* Flush header start code. */ + flush_bits32; + + /* Parse off temporal reference. */ + get_bits10(data); + vid_stream->picture.temp_ref = data; + /* + Fprintf(stderr, "Pic temp_ref %d\n", vid_stream->picture.temp_ref); + */ + /* Parse of picture type. */ + get_bits3(data); + vid_stream->picture.code_type = data; + + if ((vid_stream->picture.code_type == B_TYPE) && + (No_B_Flag || + (vid_stream->past == NULL) || + (vid_stream->future == NULL))) + return SKIP_PICTURE; + + if ((vid_stream->picture.code_type == P_TYPE) && + (No_P_Flag || (vid_stream->future == NULL))) + return SKIP_PICTURE; + + /* Parse off vbv buffer delay value. */ + get_bits16(data); + vid_stream->picture.vbv_delay = data; + + /* If P or B type frame... */ + + if ((vid_stream->picture.code_type == 2) || (vid_stream->picture.code_type == 3)) { + + /* Parse off forward vector full pixel flag. */ + get_bits1(data); + if (data) + vid_stream->picture.full_pel_forw_vector = TRUE; + else + vid_stream->picture.full_pel_forw_vector = FALSE; + + /* Parse of forw_r_code. */ + get_bits3(data); + + /* Decode forw_r_code into forw_r_size and forw_f. */ + + vid_stream->picture.forw_r_size = data - 1; + vid_stream->picture.forw_f = (1 << vid_stream->picture.forw_r_size); + } + /* If B type frame... */ + + if (vid_stream->picture.code_type == 3) { + + /* Parse off back vector full pixel flag. */ + get_bits1(data); + if (data) + vid_stream->picture.full_pel_back_vector = TRUE; + else + vid_stream->picture.full_pel_back_vector = FALSE; + + /* Parse off back_r_code. */ + get_bits3(data); + + /* Decode back_r_code into back_r_size and back_f. */ + + vid_stream->picture.back_r_size = data - 1; + vid_stream->picture.back_f = (1 << vid_stream->picture.back_r_size); + } + /* Get extra bit picture info. */ + + if (vid_stream->picture.extra_info != NULL) { + ACE_OS::free (vid_stream->picture.extra_info); + vid_stream->picture.extra_info = NULL; + } + vid_stream->picture.extra_info = get_extra_bit_info(); + + /* Goto next start code. */ + next_start_code(); + + /* If start code is extension start code, parse off extension data. */ + + if (next_bits(32, EXT_START_CODE)) { + flush_bits32; + + if (vid_stream->picture.ext_data != NULL) { + ACE_OS::free (vid_stream->picture.ext_data); + vid_stream->picture.ext_data = NULL; + } + vid_stream->picture.ext_data = get_ext_data(); + } + /* If start code is user start code, parse off user data. */ + + if (next_bits(32, USER_START_CODE)) { + flush_bits32; + + if (vid_stream->picture.user_data != NULL) { + ACE_OS::free (vid_stream->picture.user_data); + vid_stream->picture.user_data = NULL; + } + vid_stream->picture.user_data = get_ext_data(); + } + + /* Reset past macroblock address field. */ + + vid_stream->mblock.past_mb_addr = -1; + + return PARSE_OK; +} + +/* + *-------------------------------------------------------------- + * + * ParseSlice -- + * + * Parses off slice header. + * + * Results: + * Values found in slice header put into video stream structure. + * + * Side effects: + * Bit stream irreversibly parsed. + * + *-------------------------------------------------------------- + */ + +static int +ParseSlice(VidStream *vid_stream) +{ + unsigned int data; + + /* Flush slice start code. */ + + flush_bits(24); + + /* Parse off slice vertical position. */ + + get_bits8(data); + vid_stream->slice.vert_pos = data; + + /* Parse off quantization scale. */ + + get_bits5(data); + vid_stream->slice.quant_scale = data; + + /* Parse off extra bit slice info. */ + + if (vid_stream->slice.extra_info != NULL) { + ACE_OS::free (vid_stream->slice.extra_info); + vid_stream->slice.extra_info = NULL; + } + vid_stream->slice.extra_info = get_extra_bit_info(); + + /* Reset past intrablock address. */ + + vid_stream->mblock.past_intra_addr = -2; + + /* Reset previous recon motion vectors. */ + + vid_stream->mblock.recon_right_for_prev = 0; + vid_stream->mblock.recon_down_for_prev = 0; + vid_stream->mblock.recon_right_back_prev = 0; + vid_stream->mblock.recon_down_back_prev = 0; + + /* Reset macroblock address. */ + + vid_stream->mblock.mb_address = ((vid_stream->slice.vert_pos - 1) * + vid_stream->mb_width) - 1; + + /* Reset past dct dc y, cr, and cb values. */ + + vid_stream->block.dct_dc_y_past = 1024; + vid_stream->block.dct_dc_cr_past = 1024; + vid_stream->block.dct_dc_cb_past = 1024; + + return PARSE_OK; +} + + + +/* + *-------------------------------------------------------------- + * + * ParseMacroBlock -- + * + * Parseoff macroblock. Reconstructs DCT values. Applies + * inverse DCT, reconstructs motion vectors, calculates and + * set pixel values for macroblock in current pict image + * structure. + * + * Results: + * Here's where everything really happens. Welcome to the + * heart of darkness. + * + * Side effects: + * Bit stream irreversibly parsed off. + * + *-------------------------------------------------------------- + */ + +static int +ParseMacroBlock(VidStream *vid_stream) +{ + int addr_incr; + unsigned int data; + int mask, i, recon_right_for, recon_down_for, recon_right_back, + recon_down_back; + int zero_block_flag; + BOOLEAN mb_quant, mb_motion_forw, mb_motion_back, mb_pattern; + int no_dith_flag = 0; + +#ifdef ANALYSIS + mbSizeCount = bitCountRead(); +#endif + + /* + * Parse off macroblock address increment and add to macroblock address. + */ + do { + DecodeMBAddrInc(addr_incr); + if (addr_incr == MB_ESCAPE) { + vid_stream->mblock.mb_address += 33; + addr_incr = MB_STUFFING; + } + } while (addr_incr == MB_STUFFING); + vid_stream->mblock.mb_address += addr_incr; + + if (vid_stream->mblock.mb_address > ((vid_stream->mb_height) * (vid_stream->mb_width) - 1)) + { + fprintf(stderr, "mblock.mb_address-%d, mb_height-%d, mb_width-%d, addr_incr-%d\n", + vid_stream->mblock.mb_address, vid_stream->mb_height, vid_stream->mb_width, addr_incr); + return SKIP_TO_START_CODE; + } + + /* + * If macroblocks have been skipped, process skipped macroblocks. + */ + + if (vid_stream->mblock.mb_address - vid_stream->mblock.past_mb_addr > 1) { + if (vid_stream->picture.code_type == P_TYPE) + ProcessSkippedPFrameMBlocks(vid_stream); + else if (vid_stream->picture.code_type == B_TYPE) + ProcessSkippedBFrameMBlocks(vid_stream); + } + /* Set past macroblock address to current macroblock address. */ + vid_stream->mblock.past_mb_addr = vid_stream->mblock.mb_address; + + /* Based on picture type decode macroblock type. */ + switch (vid_stream->picture.code_type) { + case I_TYPE: + DecodeMBTypeI(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern, + vid_stream->mblock.mb_intra); + break; + + case P_TYPE: + DecodeMBTypeP(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern, + vid_stream->mblock.mb_intra); + break; + + case B_TYPE: + DecodeMBTypeB(mb_quant, mb_motion_forw, mb_motion_back, mb_pattern, + vid_stream->mblock.mb_intra); + break; + } + + /* If quantization flag set, parse off new quantization scale. */ + + if (mb_quant == TRUE) { + get_bits5(data); + vid_stream->slice.quant_scale = data; + } + /* If forward motion vectors exist... */ + if (mb_motion_forw == TRUE) { + + /* Parse off and decode horizontal forward motion vector. */ + DecodeMotionVectors(vid_stream->mblock.motion_h_forw_code); + + /* If horiz. forward r data exists, parse off. */ + + if ((vid_stream->picture.forw_f != 1) && + (vid_stream->mblock.motion_h_forw_code != 0)) { + get_bitsn(vid_stream->picture.forw_r_size, data); + vid_stream->mblock.motion_h_forw_r = data; + } + /* Parse off and decode vertical forward motion vector. */ + DecodeMotionVectors(vid_stream->mblock.motion_v_forw_code); + + /* If vert. forw. r data exists, parse off. */ + + if ((vid_stream->picture.forw_f != 1) && + (vid_stream->mblock.motion_v_forw_code != 0)) { + get_bitsn(vid_stream->picture.forw_r_size, data); + vid_stream->mblock.motion_v_forw_r = data; + } + } + /* If back motion vectors exist... */ + if (mb_motion_back == TRUE) { + + /* Parse off and decode horiz. back motion vector. */ + DecodeMotionVectors(vid_stream->mblock.motion_h_back_code); + + /* If horiz. back r data exists, parse off. */ + + if ((vid_stream->picture.back_f != 1) && + (vid_stream->mblock.motion_h_back_code != 0)) { + get_bitsn(vid_stream->picture.back_r_size, data); + vid_stream->mblock.motion_h_back_r = data; + } + /* Parse off and decode vert. back motion vector. */ + DecodeMotionVectors(vid_stream->mblock.motion_v_back_code); + + /* If vert. back r data exists, parse off. */ + + if ((vid_stream->picture.back_f != 1) && + (vid_stream->mblock.motion_v_back_code != 0)) { + get_bitsn(vid_stream->picture.back_r_size, data); + vid_stream->mblock.motion_v_back_r = data; + } + } +#ifdef ANALYSIS + if (vid_stream->mblock.mb_intra) { + stat_a[0].i_mbnum++; + mbCBPPtr = stat_a[0].i_mbcbp; + mbCoeffPtr = stat_a[0].i_mbcoeff; + mbSizePtr = &(stat_a[0].i_mbsize); + } else if (mb_motion_back && mb_motion_forw) { + stat_a[0].bi_mbnum++; + mbCBPPtr = stat_a[0].bi_mbcbp; + mbCoeffPtr = stat_a[0].bi_mbcoeff; + mbSizePtr = &(stat_a[0].bi_mbsize); + } else if (mb_motion_back) { + stat_a[0].b_mbnum++; + mbCBPPtr = stat_a[0].b_mbcbp; + mbCoeffPtr = stat_a[0].b_mbcoeff; + mbSizePtr = &(stat_a[0].b_mbsize); + } else { + stat_a[0].p_mbnum++; + mbCBPPtr = stat_a[0].p_mbcbp; + mbCoeffPtr = stat_a[0].p_mbcoeff; + mbSizePtr = &(stat_a[0].p_mbsize); + } +#endif + + /* If mblock pattern flag set, parse and decode CBP (code block pattern). */ + if (mb_pattern == TRUE) { + DecodeCBP(vid_stream->mblock.cbp); + } + /* Otherwise, set CBP to zero. */ + else + vid_stream->mblock.cbp = 0; + + +#ifdef ANALYSIS + mbCBPPtr[vid_stream->mblock.cbp]++; +#endif + + /* Reconstruct motion vectors depending on picture type. */ + if (vid_stream->picture.code_type == P_TYPE) { + + /* + * If no forw motion vectors, reset previous and current vectors to 0. + */ + + if (!mb_motion_forw) { + recon_right_for = 0; + recon_down_for = 0; + vid_stream->mblock.recon_right_for_prev = 0; + vid_stream->mblock.recon_down_for_prev = 0; + } + /* + * Otherwise, compute new forw motion vectors. Reset previous vectors to + * current vectors. + */ + + else { + ComputeForwVector(&recon_right_for, &recon_down_for); + } + } + if (vid_stream->picture.code_type == B_TYPE) { + + /* Reset prev. and current vectors to zero if mblock is intracoded. */ + + if (vid_stream->mblock.mb_intra) { + vid_stream->mblock.recon_right_for_prev = 0; + vid_stream->mblock.recon_down_for_prev = 0; + vid_stream->mblock.recon_right_back_prev = 0; + vid_stream->mblock.recon_down_back_prev = 0; + } else { + + /* If no forw vectors, current vectors equal prev. vectors. */ + + if (!mb_motion_forw) { + recon_right_for = vid_stream->mblock.recon_right_for_prev; + recon_down_for = vid_stream->mblock.recon_down_for_prev; + } + /* + * Otherwise compute forw. vectors. Reset prev vectors to new values. + */ + + else { + ComputeForwVector(&recon_right_for, &recon_down_for); + } + + /* If no back vectors, set back vectors to prev back vectors. */ + + if (!mb_motion_back) { + recon_right_back = vid_stream->mblock.recon_right_back_prev; + recon_down_back = vid_stream->mblock.recon_down_back_prev; + } + /* Otherwise compute new vectors and reset prev. back vectors. */ + + else { + ComputeBackVector(&recon_right_back, &recon_down_back); + } + + /* + * Store vector existance flags in structure for possible skipped + * macroblocks to follow. + */ + + vid_stream->mblock.bpict_past_forw = mb_motion_forw; + vid_stream->mblock.bpict_past_back = mb_motion_back; + } + } + + /* For each possible block in macroblock. */ + if (ditherType == GRAY_DITHER || + ditherType == MONO_DITHER || + ditherType == MONO_THRESHOLD) { + for (mask = 32, i = 0; i < 4; mask >>= 1, i++) { + + /* If block exists... */ + if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) { + zero_block_flag = 0; + ParseReconBlock(i); + } else { + zero_block_flag = 1; + } + + /* If macroblock is intra coded... */ + if (vid_stream->mblock.mb_intra) { + ReconIMBlock(vid_stream, i); + } else if (mb_motion_forw && mb_motion_back) { + ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for, + recon_right_back, recon_down_back, zero_block_flag); + } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) { + ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for, + zero_block_flag); + } else if (mb_motion_back) { + ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back, + zero_block_flag); + } + } + /* Kill the Chrominace blocks... */ + if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x2)) { + ParseAwayBlock(4); + } + if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & 0x1)) { + ParseAwayBlock(5); + } + } else { + if ((ditherType == MBORDERED_DITHER) && + (vid_stream->mblock.cbp == 0) && + (vid_stream->picture.code_type == 3) && + (!vid_stream->mblock.mb_intra) && + (!(mb_motion_forw && mb_motion_back))) { + /* + MBOrderedDitherDisplayCopy(vid_stream, vid_stream->mblock.mb_address, + mb_motion_forw, recon_right_for, recon_down_for, + mb_motion_back, recon_right_back, recon_down_back, + vid_stream->past->display, vid_stream->future->display); + ditherFlags[vid_stream->mblock.mb_address] = 0; + no_dith_flag = 1; + */ + } + else { + for (mask = 32, i = 0; i < 6; mask >>= 1, i++) { + + /* If block exists... */ + if ((vid_stream->mblock.mb_intra) || (vid_stream->mblock.cbp & mask)) { + zero_block_flag = 0; + ParseReconBlock(i); + } else { + zero_block_flag = 1; + } + + /* If macroblock is intra coded... */ + if (vid_stream->mblock.mb_intra) { + ReconIMBlock(vid_stream, i); + } else if (mb_motion_forw && mb_motion_back) { + ReconBiMBlock(vid_stream, i, recon_right_for, recon_down_for, + recon_right_back, recon_down_back, zero_block_flag); + } else if (mb_motion_forw || (vid_stream->picture.code_type == P_TYPE)) { + ReconPMBlock(vid_stream, i, recon_right_for, recon_down_for, + zero_block_flag); + } else if (mb_motion_back) { + ReconBMBlock(vid_stream, i, recon_right_back, recon_down_back, + zero_block_flag); + } + } + } + } + + if ((ditherType == MBORDERED_DITHER) && (!no_dith_flag)) { + if ((vid_stream->picture.code_type == 2) && + (vid_stream->mblock.cbp == 0) && + (!vid_stream->mblock.mb_intra)) { + /* + MBOrderedDitherDisplayCopy(vid_stream, vid_stream->mblock.mb_address, + 1, recon_right_for, recon_down_for, + 0, 0, 0, + vid_stream->future->display, + (unsigned char *) NULL); + ditherFlags[vid_stream->mblock.mb_address] = 0; + */ + } + else { + ditherFlags[vid_stream->mblock.mb_address] = 1; + } + } + + + /* If D Type picture, flush marker bit. */ + if (vid_stream->picture.code_type == 4) + flush_bits(1); + + /* If macroblock was intracoded, set macroblock past intra address. */ + if (vid_stream->mblock.mb_intra) + vid_stream->mblock.past_intra_addr = + vid_stream->mblock.mb_address; + +#ifdef ANALYSIS + *mbSizePtr += bitCountRead() - mbSizeCount; +#endif + return PARSE_OK; +} + + + +/* + *-------------------------------------------------------------- + * + * ReconIMBlock -- + * + * Reconstructs intra coded macroblock. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static void +ReconIMBlock(VidStream *vid_stream, int bnum) +{ + int mb_row, mb_col, row, col, row_size, rr; + unsigned char *dest; + + /* Calculate macroblock row and column from address. */ + + mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width; + mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width; + + + /* If block is luminance block... */ + + if (bnum < 4) { + + /* Calculate row and col values for upper left pixel of block. */ + + row = mb_row * 16; + col = mb_col * 16; + if (bnum > 1) + row += 8; + if (bnum % 2) + col += 8; + + /* Set dest to luminance plane of current pict image. */ + + dest = vid_stream->current->luminance; + + /* Establish row size. */ + + row_size = vid_stream->mb_width * 16; + } + /* Otherwise if block is Cr block... */ + + else if (bnum == 4) { + + /* Set dest to Cr plane of current pict image. */ + + dest = vid_stream->current->Cr; + + /* Establish row size. */ + + row_size = vid_stream->mb_width * 8; + + /* Calculate row,col for upper left pixel of block. */ + + row = mb_row * 8; + col = mb_col * 8; + } + /* Otherwise block is Cb block, and ... */ + + else { + + /* Set dest to Cb plane of current pict image. */ + + dest = vid_stream->current->Cb; + + /* Establish row size. */ + + row_size = vid_stream->mb_width * 8; + + /* Calculate row,col for upper left pixel value of block. */ + + row = mb_row * 8; + col = mb_col * 8; + } + + /* + * For each pixel in block, set to cropped reconstructed value from inverse + * dct. + */ + { + short *sp = &vid_stream->block.dct_recon[0][0]; + unsigned char *cm = cropTbl + MAX_NEG_CROP; + dest += row * row_size + col; + for (rr = 0; rr < 4; rr++, sp += 16, dest += row_size) { + dest[0] = cm[sp[0]]; + assertCrop(sp[0]); + dest[1] = cm[sp[1]]; + assertCrop(sp[1]); + dest[2] = cm[sp[2]]; + assertCrop(sp[2]); + dest[3] = cm[sp[3]]; + assertCrop(sp[3]); + dest[4] = cm[sp[4]]; + assertCrop(sp[4]); + dest[5] = cm[sp[5]]; + assertCrop(sp[5]); + dest[6] = cm[sp[6]]; + assertCrop(sp[6]); + dest[7] = cm[sp[7]]; + assertCrop(sp[7]); + + dest += row_size; + dest[0] = cm[sp[8]]; + assertCrop(sp[8]); + dest[1] = cm[sp[9]]; + assertCrop(sp[9]); + dest[2] = cm[sp[10]]; + assertCrop(sp[10]); + dest[3] = cm[sp[11]]; + assertCrop(sp[11]); + dest[4] = cm[sp[12]]; + assertCrop(sp[12]); + dest[5] = cm[sp[13]]; + assertCrop(sp[13]); + dest[6] = cm[sp[14]]; + assertCrop(sp[14]); + dest[7] = cm[sp[15]]; + assertCrop(sp[15]); + } + } +} + + + +/* + *-------------------------------------------------------------- + * + * ReconPMBlock -- + * + * Reconstructs forward predicted macroblocks. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static void +ReconPMBlock(VidStream *vid_stream, int bnum, + int recon_right_for, int recon_down_for, int zflag) +{ + int mb_row, mb_col, row, col, row_size, rr; + unsigned char *dest, *past; + static int right_for, down_for, right_half_for, down_half_for; + unsigned char *rindex1, *rindex2; + unsigned char *index; + short int *blockvals; + +#ifdef LOOSE_MPEG + int maxx, maxy; + int illegalBlock = 0; + int row_start, row_end, rfirst, rlast, col_start, col_end, cfirst, clast; +#endif + + /* Calculate macroblock row and column from address. */ + + mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width; + mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width; + + if (bnum < 4) { + + /* Calculate right_for, down_for motion vectors. */ + + right_for = recon_right_for >> 1; + down_for = recon_down_for >> 1; + right_half_for = recon_right_for & 0x1; + down_half_for = recon_down_for & 0x1; + + /* Set dest to luminance plane of current pict image. */ + + dest = vid_stream->current->luminance; + + if (vid_stream->picture.code_type == B_TYPE) { + if (vid_stream->past != NULL) + past = vid_stream->past->luminance; + } else { + + /* Set predicitive frame to current future frame. */ + + if (vid_stream->future != NULL) + past = vid_stream->future->luminance; + } + + /* Establish row size. */ + + row_size = vid_stream->mb_width << 4; + + /* Calculate row,col of upper left pixel in block. */ + + row = mb_row << 4; + col = mb_col << 4; + if (bnum > 1) + row += 8; + if (bnum % 2) + col += 8; + +#ifdef LOOSE_MPEG + /* Check for block illegality. */ + + maxx = lmaxx; maxy = lmaxy; + + if (row + down_for + 7 > maxy) illegalBlock |= 0x4; + else if (row + down_for < 0) illegalBlock |= 0x1; + + if (col + right_for + 7 > maxx) illegalBlock |= 0x2; + else if (col + right_for < 0) illegalBlock |= 0x8; + +#endif + } + /* Otherwise, block is NOT luminance block, ... */ + + else { + + /* Construct motion vectors. */ + + recon_right_for /= 2; + recon_down_for /= 2; + right_for = recon_right_for >> 1; + down_for = recon_down_for >> 1; + right_half_for = recon_right_for & 0x1; + down_half_for = recon_down_for & 0x1; + + /* Establish row size. */ + + row_size = vid_stream->mb_width << 3; + + /* Calculate row,col of upper left pixel in block. */ + + row = mb_row << 3; + col = mb_col << 3; + +#ifdef LOOSE_MPEG + /* Check for block illegality. */ + + maxx = cmaxx; maxy = cmaxy; + + if (row + down_for + 7 > maxy) illegalBlock |= 0x4; + else if (row + down_for < 0) illegalBlock |= 0x1; + + if (col + right_for + 7 > maxx) illegalBlock |= 0x2; + else if (col + right_for < 0) illegalBlock |= 0x8; + +#endif + + /* If block is Cr block... */ + + if (bnum == 4) { + + /* Set dest to Cr plane of current pict image. */ + + dest = vid_stream->current->Cr; + + if (vid_stream->picture.code_type == B_TYPE) { + + if (vid_stream->past != NULL) + past = vid_stream->past->Cr; + } else { + if (vid_stream->future != NULL) + past = vid_stream->future->Cr; + } + } + /* Otherwise, block is Cb block... */ + + else { + + /* Set dest to Cb plane of current pict image. */ + + dest = vid_stream->current->Cb; + + if (vid_stream->picture.code_type == B_TYPE) { + if (vid_stream->past != NULL) + past = vid_stream->past->Cb; + } else { + if (vid_stream->future != NULL) + past = vid_stream->future->Cb; + } + } + } + + /* For each pixel in block... */ + +#ifdef LOOSE_MPEG + + if (illegalBlock) { + if (illegalBlock & 0x1) { + row_start = 0; + row_end = row+down_for+8; + rfirst = rlast = 8 - row_end; + } + else if (illegalBlock & 0x4) { + row_start = row + down_for; + row_end = maxy+1; + rlast = row_end - row_start - 1; + rfirst = 0; + } + else { + row_start = row+down_for; + row_end = row_start+8; + rfirst = 0; + } + + if (illegalBlock & 0x8) { + col_start = 0; + col_end = col + right_for + 8; + cfirst = clast = 8 - col_end; + } + else if (illegalBlock & 0x2) { + col_start = col + right_for; + col_end = maxx + 1; + clast = col_end - col_start - 1; + cfirst = 0; + } + else { + col_start = col + right_for; + col_end = col_start + 8; + cfirst = 0; + } + + for (rr = row_start; rr < row_end; rr++) { + rindex1 = past + (rr * row_size) + col_start; + index = dest + ((row + rfirst) * row_size) + col + cfirst; + for (cc = col_start; cc < col_end; cc++) { + *index++ = *rindex1++; + } + } + + if (illegalBlock & 0x1) { + for (rr = rlast -1; rr >=0; rr--) { + index = dest + ((row + rr) * row_size) + col; + rindex1 = dest + ((row + rlast) * row_size) + col; + for (cc = 0; cc < 8; cc ++) { + *index++ = *rindex1++; + } + } + } + else if (illegalBlock & 0x4) { + for (rr = rlast+1; rr < 8; rr++) { + index = dest + ((row + rr) * row_size) + col; + rindex1 = dest + ((row + rlast) * row_size) + col; + for (cc = 0; cc < 8; cc ++) { + *index++ = *rindex1++; + } + } + } + + if (illegalBlock & 0x2) { + for (cc = clast+1; cc < 8; cc++) { + index = dest + (row * row_size) + (col + cc); + rindex1 = dest + (row * row_size) + (col + clast); + for (rr = 0; rr < 8; rr++) { + *index = *rindex1; + index += row_size; + rindex1 += row_size; + } + } + } + else if (illegalBlock & 0x8) { + for (cc = clast-1; cc >= 0; cc--) { + index = dest + (row * row_size) + (col + cc); + rindex1 = dest + (row * row_size) + (col + clast); + for (rr = 0; rr < 8; rr++) { + *index = *rindex1; + index += row_size; + rindex1 += row_size; + } + } + } + + if (!zflag) { + for (rr = 0; rr < 8; rr++) { + index = dest + (row*row_size) + col; + blockvals = &(vid_stream->block.dct_recon[rr][0]); + index[0] += blockvals[0]; + index[1] += blockvals[1]; + index[2] += blockvals[2]; + index[3] += blockvals[3]; + index[4] += blockvals[4]; + index[5] += blockvals[5]; + index[6] += blockvals[6]; + index[7] += blockvals[7]; + } + } + } + else { + +#endif + + index = dest + (row * row_size) + col; + rindex1 = past + (row + down_for) * row_size + col + right_for; + + blockvals = &(vid_stream->block.dct_recon[0][0]); + + /* + * Calculate predictive pixel value based on motion vectors and copy to + * dest plane. + */ + + if ((!down_half_for) && (!right_half_for)) { + unsigned char *cm = cropTbl + MAX_NEG_CROP; + if (!zflag) + for (rr = 0; rr < 4; rr++) { + index[0] = cm[(int) rindex1[0] + (int) blockvals[0]]; + index[1] = cm[(int) rindex1[1] + (int) blockvals[1]]; + index[2] = cm[(int) rindex1[2] + (int) blockvals[2]]; + index[3] = cm[(int) rindex1[3] + (int) blockvals[3]]; + index[4] = cm[(int) rindex1[4] + (int) blockvals[4]]; + index[5] = cm[(int) rindex1[5] + (int) blockvals[5]]; + index[6] = cm[(int) rindex1[6] + (int) blockvals[6]]; + index[7] = cm[(int) rindex1[7] + (int) blockvals[7]]; + index += row_size; + rindex1 += row_size; + + index[0] = cm[(int) rindex1[0] + (int) blockvals[8]]; + index[1] = cm[(int) rindex1[1] + (int) blockvals[9]]; + index[2] = cm[(int) rindex1[2] + (int) blockvals[10]]; + index[3] = cm[(int) rindex1[3] + (int) blockvals[11]]; + index[4] = cm[(int) rindex1[4] + (int) blockvals[12]]; + index[5] = cm[(int) rindex1[5] + (int) blockvals[13]]; + index[6] = cm[(int) rindex1[6] + (int) blockvals[14]]; + index[7] = cm[(int) rindex1[7] + (int) blockvals[15]]; + blockvals += 16; + index += row_size; + rindex1 += row_size; + } + else { + if (right_for & 0x1) { + /* No alignment, use bye copy */ + for (rr = 0; rr < 4; rr++) { + index[0] = rindex1[0]; + index[1] = rindex1[1]; + index[2] = rindex1[2]; + index[3] = rindex1[3]; + index[4] = rindex1[4]; + index[5] = rindex1[5]; + index[6] = rindex1[6]; + index[7] = rindex1[7]; + index += row_size; + rindex1 += row_size; + + index[0] = rindex1[0]; + index[1] = rindex1[1]; + index[2] = rindex1[2]; + index[3] = rindex1[3]; + index[4] = rindex1[4]; + index[5] = rindex1[5]; + index[6] = rindex1[6]; + index[7] = rindex1[7]; + index += row_size; + rindex1 += row_size; + } + } else if (right_for & 0x2) { + /* Half-word bit aligned, use 16 bit copy */ + short *src = (short *)rindex1; + short *dest = (short *)index; + row_size >>= 1; + for (rr = 0; rr < 4; rr++) { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = src[3]; + dest += row_size; + src += row_size; + + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = src[3]; + dest += row_size; + src += row_size; + } + } else { + /* Word aligned, use 32 bit copy */ + int *src = (int *)rindex1; + int *dest = (int *)index; + row_size >>= 2; + for (rr = 0; rr < 4; rr++) { + dest[0] = src[0]; + dest[1] = src[1]; + dest += row_size; + src += row_size; + + dest[0] = src[0]; + dest[1] = src[1]; + dest += row_size; + src += row_size; + } + } + } + } else { + unsigned char *cm = cropTbl + MAX_NEG_CROP; + rindex2 = rindex1 + right_half_for + (down_half_for * row_size); + if (!zflag) + for (rr = 0; rr < 4; rr++) { + index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]]; + index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]]; + index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]]; + index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]]; + index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]]; + index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]]; + index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]]; + index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]]; + index += row_size; + rindex1 += row_size; + rindex2 += row_size; + + index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]]; + index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]]; + index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]]; + index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]]; + index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]]; + index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]]; + index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]]; + index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]]; + blockvals += 16; + index += row_size; + rindex1 += row_size; + rindex2 += row_size; + } + else + for (rr = 0; rr < 4; rr++) { + index[0] = (int) (rindex1[0] + rindex2[0]) >> 1; + index[1] = (int) (rindex1[1] + rindex2[1]) >> 1; + index[2] = (int) (rindex1[2] + rindex2[2]) >> 1; + index[3] = (int) (rindex1[3] + rindex2[3]) >> 1; + index[4] = (int) (rindex1[4] + rindex2[4]) >> 1; + index[5] = (int) (rindex1[5] + rindex2[5]) >> 1; + index[6] = (int) (rindex1[6] + rindex2[6]) >> 1; + index[7] = (int) (rindex1[7] + rindex2[7]) >> 1; + index += row_size; + rindex1 += row_size; + rindex2 += row_size; + + index[0] = (int) (rindex1[0] + rindex2[0]) >> 1; + index[1] = (int) (rindex1[1] + rindex2[1]) >> 1; + index[2] = (int) (rindex1[2] + rindex2[2]) >> 1; + index[3] = (int) (rindex1[3] + rindex2[3]) >> 1; + index[4] = (int) (rindex1[4] + rindex2[4]) >> 1; + index[5] = (int) (rindex1[5] + rindex2[5]) >> 1; + index[6] = (int) (rindex1[6] + rindex2[6]) >> 1; + index[7] = (int) (rindex1[7] + rindex2[7]) >> 1; + index += row_size; + rindex1 += row_size; + rindex2 += row_size; + } + } + +#ifdef LOOSE_MPEG + } +#endif +} + + +/* + *-------------------------------------------------------------- + * + * ReconBMBlock -- + * + * Reconstructs back predicted macroblocks. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static void +ReconBMBlock(VidStream *vid_stream, + int bnum, int recon_right_back, int recon_down_back, int zflag) +{ + int mb_row, mb_col, row, col, row_size, rr; + unsigned char *dest, *future; + int right_back, down_back, right_half_back, down_half_back; + unsigned char *rindex1, *rindex2; + unsigned char *index; + short int *blockvals; + +#ifdef LOOSE_MPEG + int illegalBlock = 0; + int maxx, maxy; + int row_start, row_end, rlast, rfirst, col_start, col_end, clast, cfirst; +#endif + + /* Calculate macroblock row and column from address. */ + + mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width; + mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width; + + /* If block is luminance block... */ + + if (bnum < 4) { + + /* Calculate right_back, down_bakc motion vectors. */ + + right_back = recon_right_back >> 1; + down_back = recon_down_back >> 1; + right_half_back = recon_right_back & 0x1; + down_half_back = recon_down_back & 0x1; + + /* Set dest to luminance plane of current pict image. */ + + dest = vid_stream->current->luminance; + + /* + * If future frame exists, set future to luminance plane of future frame. + */ + + if (vid_stream->future != NULL) + future = vid_stream->future->luminance; + + /* Establish row size. */ + + row_size = vid_stream->mb_width << 4; + + /* Calculate row,col of upper left pixel in block. */ + + row = mb_row << 4; + col = mb_col << 4; + if (bnum > 1) + row += 8; + if (bnum % 2) + col += 8; + +#ifdef LOOSE_MPEG + + /* Check for block illegality. */ + + maxx = lmaxx; maxy = lmaxy; + + if (row + down_back + 7 > maxy) illegalBlock |= 0x4; + else if (row + down_back < 0) illegalBlock |= 0x1; + + if (col + right_back + 7 > maxx) illegalBlock |= 0x2; + else if (col + right_back < 0) illegalBlock |= 0x8; + +#endif + + } + /* Otherwise, block is NOT luminance block, ... */ + + else { + + /* Construct motion vectors. */ + + recon_right_back /= 2; + recon_down_back /= 2; + right_back = recon_right_back >> 1; + down_back = recon_down_back >> 1; + right_half_back = recon_right_back & 0x1; + down_half_back = recon_down_back & 0x1; + + /* Establish row size. */ + + row_size = vid_stream->mb_width << 3; + + /* Calculate row,col of upper left pixel in block. */ + + row = mb_row << 3; + col = mb_col << 3; + +#ifdef LOOSE_MPEG + + /* Check for block illegality. */ + + maxx = cmaxx; maxy = cmaxy; + + if (row + down_back + 7 > maxy) illegalBlock |= 0x4; + else if (row + down_back < 0) illegalBlock |= 0x1; + + if (col + right_back + 7 > maxx) illegalBlock |= 0x2; + else if (col + right_back < 0) illegalBlock |= 0x8; + +#endif + + /* If block is Cr block... */ + + if (bnum == 4) { + + /* Set dest to Cr plane of current pict image. */ + + dest = vid_stream->current->Cr; + + /* + * If future frame exists, set future to Cr plane of future image. + */ + + if (vid_stream->future != NULL) + future = vid_stream->future->Cr; + } + /* Otherwise, block is Cb block... */ + + else { + + /* Set dest to Cb plane of current pict image. */ + + dest = vid_stream->current->Cb; + + /* + * If future frame exists, set future to Cb plane of future frame. + */ + + if (vid_stream->future != NULL) + future = vid_stream->future->Cb; + } + } + + /* For each pixel in block do... */ + +#ifdef LOOSE_MPEG + + if (illegalBlock) { + if (illegalBlock & 0x1) { + row_start = 0; + row_end = row+down_back+8; + rfirst = rlast = 8 - row_end; + } + else if (illegalBlock & 0x4) { + row_start = row + down_back; + row_end = maxy+1; + rlast = row_end - row_start - 1; + rfirst = 0; + } + else { + row_start = row+down_back; + row_end = row_start+8; + rfirst = 0; + } + + if (illegalBlock & 0x8) { + col_start = 0; + col_end = col + right_back + 8; + cfirst = clast = 8 - col_end; + } + else if (illegalBlock & 0x2) { + col_start = col + right_back; + col_end = maxx + 1; + clast = col_end - col_start - 1; + cfirst = 0; + } + else { + col_start = col + right_back; + col_end = col_start + 8; + cfirst = 0; + } + + for (rr = row_start; rr < row_end; rr++) { + rindex1 = future + (rr * row_size) + col_start; + index = dest + ((row + rfirst) * row_size) + col + cfirst; + for (cc = col_start; cc < col_end; cc++) { + *index++ = *rindex1++; + } + } + + if (illegalBlock & 0x1) { + for (rr = rlast -1; rr >=0; rr--) { + index = dest + ((row + rr) * row_size) + col; + rindex1 = dest + ((row + rlast) * row_size) + col; + for (cc = 0; cc < 8; cc ++) { + *index++ = *rindex1++; + } + } + } + else if (illegalBlock & 0x4) { + for (rr = rlast+1; rr < 8; rr++) { + index = dest + ((row + rr) * row_size) + col; + rindex1 = dest + ((row + rlast) * row_size) + col; + for (cc = 0; cc < 8; cc ++) { + *index++ = *rindex1++; + } + } + } + + if (illegalBlock & 0x2) { + for (cc = clast+1; cc < 8; cc++) { + index = dest + (row * row_size) + (col + cc); + rindex1 = dest + (row * row_size) + (col + clast); + for (rr = 0; rr < 8; rr++) { + *index = *rindex1; + index += row_size; + rindex1 += row_size; + } + } + } + else if (illegalBlock & 0x8) { + for (cc = clast-1; cc >= 0; cc--) { + index = dest + (row * row_size) + (col + cc); + rindex1 = dest + (row * row_size) + (col + clast); + for (rr = 0; rr < 8; rr++) { + *index = *rindex1; + index += row_size; + rindex1 += row_size; + } + } + } + + if (!zflag) { + for (rr = 0; rr < 8; rr++) { + index = dest + (row*row_size) + col; + blockvals = &(vid_stream->block.dct_recon[rr][0]); + index[0] += blockvals[0]; + index[1] += blockvals[1]; + index[2] += blockvals[2]; + index[3] += blockvals[3]; + index[4] += blockvals[4]; + index[5] += blockvals[5]; + index[6] += blockvals[6]; + index[7] += blockvals[7]; + } + } + } + else { + +#endif + + index = dest + (row * row_size) + col; + rindex1 = future + (row + down_back) * row_size + col + right_back; + + blockvals = &(vid_stream->block.dct_recon[0][0]); + + if ((!right_half_back) && (!down_half_back)) { + unsigned char *cm = cropTbl + MAX_NEG_CROP; + if (!zflag) + for (rr = 0; rr < 4; rr++) { + index[0] = cm[(int) rindex1[0] + (int) blockvals[0]]; + index[1] = cm[(int) rindex1[1] + (int) blockvals[1]]; + index[2] = cm[(int) rindex1[2] + (int) blockvals[2]]; + index[3] = cm[(int) rindex1[3] + (int) blockvals[3]]; + index[4] = cm[(int) rindex1[4] + (int) blockvals[4]]; + index[5] = cm[(int) rindex1[5] + (int) blockvals[5]]; + index[6] = cm[(int) rindex1[6] + (int) blockvals[6]]; + index[7] = cm[(int) rindex1[7] + (int) blockvals[7]]; + index += row_size; + rindex1 += row_size; + + index[0] = cm[(int) rindex1[0] + (int) blockvals[8]]; + index[1] = cm[(int) rindex1[1] + (int) blockvals[9]]; + index[2] = cm[(int) rindex1[2] + (int) blockvals[10]]; + index[3] = cm[(int) rindex1[3] + (int) blockvals[11]]; + index[4] = cm[(int) rindex1[4] + (int) blockvals[12]]; + index[5] = cm[(int) rindex1[5] + (int) blockvals[13]]; + index[6] = cm[(int) rindex1[6] + (int) blockvals[14]]; + index[7] = cm[(int) rindex1[7] + (int) blockvals[15]]; + blockvals += 16; + index += row_size; + rindex1 += row_size; + } + else { + if (right_back & 0x1) { + /* No alignment, use bye copy */ + for (rr = 0; rr < 4; rr++) { + index[0] = rindex1[0]; + index[1] = rindex1[1]; + index[2] = rindex1[2]; + index[3] = rindex1[3]; + index[4] = rindex1[4]; + index[5] = rindex1[5]; + index[6] = rindex1[6]; + index[7] = rindex1[7]; + index += row_size; + rindex1 += row_size; + + index[0] = rindex1[0]; + index[1] = rindex1[1]; + index[2] = rindex1[2]; + index[3] = rindex1[3]; + index[4] = rindex1[4]; + index[5] = rindex1[5]; + index[6] = rindex1[6]; + index[7] = rindex1[7]; + index += row_size; + rindex1 += row_size; + } + } else if (right_back & 0x2) { + /* Half-word bit aligned, use 16 bit copy */ + short *src = (short *)rindex1; + short *dest = (short *)index; + row_size >>= 1; + for (rr = 0; rr < 4; rr++) { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = src[3]; + dest += row_size; + src += row_size; + + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = src[3]; + dest += row_size; + src += row_size; + } + } else { + /* Word aligned, use 32 bit copy */ + int *src = (int *)rindex1; + int *dest = (int *)index; + row_size >>= 2; + for (rr = 0; rr < 4; rr++) { + dest[0] = src[0]; + dest[1] = src[1]; + dest += row_size; + src += row_size; + + dest[0] = src[0]; + dest[1] = src[1]; + dest += row_size; + src += row_size; + } + } + } + } else { + unsigned char *cm = cropTbl + MAX_NEG_CROP; + rindex2 = rindex1 + right_half_back + (down_half_back * row_size); + if (!zflag) + for (rr = 0; rr < 4; rr++) { + index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[0]]; + index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[1]]; + index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[2]]; + index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[3]]; + index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[4]]; + index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[5]]; + index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[6]]; + index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[7]]; + index += row_size; + rindex1 += row_size; + rindex2 += row_size; + + index[0] = cm[((int) (rindex1[0] + rindex2[0]) >> 1) + blockvals[8]]; + index[1] = cm[((int) (rindex1[1] + rindex2[1]) >> 1) + blockvals[9]]; + index[2] = cm[((int) (rindex1[2] + rindex2[2]) >> 1) + blockvals[10]]; + index[3] = cm[((int) (rindex1[3] + rindex2[3]) >> 1) + blockvals[11]]; + index[4] = cm[((int) (rindex1[4] + rindex2[4]) >> 1) + blockvals[12]]; + index[5] = cm[((int) (rindex1[5] + rindex2[5]) >> 1) + blockvals[13]]; + index[6] = cm[((int) (rindex1[6] + rindex2[6]) >> 1) + blockvals[14]]; + index[7] = cm[((int) (rindex1[7] + rindex2[7]) >> 1) + blockvals[15]]; + blockvals += 16; + index += row_size; + rindex1 += row_size; + rindex2 += row_size; + } + else + for (rr = 0; rr < 4; rr++) { + index[0] = (int) (rindex1[0] + rindex2[0]) >> 1; + index[1] = (int) (rindex1[1] + rindex2[1]) >> 1; + index[2] = (int) (rindex1[2] + rindex2[2]) >> 1; + index[3] = (int) (rindex1[3] + rindex2[3]) >> 1; + index[4] = (int) (rindex1[4] + rindex2[4]) >> 1; + index[5] = (int) (rindex1[5] + rindex2[5]) >> 1; + index[6] = (int) (rindex1[6] + rindex2[6]) >> 1; + index[7] = (int) (rindex1[7] + rindex2[7]) >> 1; + index += row_size; + rindex1 += row_size; + rindex2 += row_size; + + index[0] = (int) (rindex1[0] + rindex2[0]) >> 1; + index[1] = (int) (rindex1[1] + rindex2[1]) >> 1; + index[2] = (int) (rindex1[2] + rindex2[2]) >> 1; + index[3] = (int) (rindex1[3] + rindex2[3]) >> 1; + index[4] = (int) (rindex1[4] + rindex2[4]) >> 1; + index[5] = (int) (rindex1[5] + rindex2[5]) >> 1; + index[6] = (int) (rindex1[6] + rindex2[6]) >> 1; + index[7] = (int) (rindex1[7] + rindex2[7]) >> 1; + index += row_size; + rindex1 += row_size; + rindex2 += row_size; + } + } + +#ifdef LOOSE_MPEG + } +#endif + +} + + +/* + *-------------------------------------------------------------- + * + * ReconBiMBlock -- + * + * Reconstructs bidirectionally predicted macroblocks. + * + * Results: + * None. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static void +ReconBiMBlock(VidStream *vid_stream, int bnum, int recon_right_for, + int recon_down_for, int recon_right_back, + int recon_down_back, int zflag) +{ + int mb_row, mb_col, row, col, row_size, rr; + unsigned char *dest, *past, *future; + int right_for, down_for, right_half_for, down_half_for; + int right_back, down_back, right_half_back, down_half_back; + unsigned char *index, *rindex1, *bindex1; + short int *blockvals; + int forw_row_start, back_row_start, forw_col_start, back_col_start; + +#ifdef LOOSE_MPEG + int illegal_forw = 0; + int illegal_back = 0; +#endif + + /* Calculate macroblock row and column from address. */ + + mb_row = vid_stream->mblock.mb_address / vid_stream->mb_width; + mb_col = vid_stream->mblock.mb_address % vid_stream->mb_width; + + /* If block is luminance block... */ + + if (bnum < 4) { + + /* + * Calculate right_for, down_for, right_half_for, down_half_for, + * right_back, down_bakc, right_half_back, and down_half_back, motion + * vectors. + */ + + right_for = recon_right_for >> 1; + down_for = recon_down_for >> 1; + right_half_for = recon_right_for & 0x1; + down_half_for = recon_down_for & 0x1; + + right_back = recon_right_back >> 1; + down_back = recon_down_back >> 1; + right_half_back = recon_right_back & 0x1; + down_half_back = recon_down_back & 0x1; + + /* Set dest to luminance plane of current pict image. */ + + dest = vid_stream->current->luminance; + + /* If past frame exists, set past to luminance plane of past frame. */ + + if (vid_stream->past != NULL) + past = vid_stream->past->luminance; + + /* + * If future frame exists, set future to luminance plane of future frame. + */ + + if (vid_stream->future != NULL) + future = vid_stream->future->luminance; + + /* Establish row size. */ + + row_size = (vid_stream->mb_width << 4); + + /* Calculate row,col of upper left pixel in block. */ + + row = (mb_row << 4); + col = (mb_col << 4); + if (bnum > 1) + row += 8; + if (bnum & 0x01) + col += 8; + + forw_col_start = col + right_for; + forw_row_start = row + down_for; + + back_col_start = col + right_back; + back_row_start = row + down_back; + +#ifdef LOOSE_MPEG + + /* Check for illegal pred. blocks. */ + + + if (forw_col_start+8 > lmaxx) illegal_forw = 1; + else if (forw_col_start < 0) illegal_forw = 1; + + if (forw_row_start+8 > lmaxy) illegal_forw = 1; + else if (forw_row_start < 0) illegal_forw = 1; + + if (back_col_start+8 > lmaxx) illegal_back = 1; + else if (back_col_start < 0) illegal_back = 1; + + if (back_row_start+8 > lmaxy) illegal_back = 1; + else if (back_row_start < 0) illegal_back = 1; + +#endif + + } + /* Otherwise, block is NOT luminance block, ... */ + + else { + + /* Construct motion vectors. */ + + recon_right_for /= 2; + recon_down_for /= 2; + right_for = recon_right_for >> 1; + down_for = recon_down_for >> 1; + right_half_for = recon_right_for & 0x1; + down_half_for = recon_down_for & 0x1; + + recon_right_back /= 2; + recon_down_back /= 2; + right_back = recon_right_back >> 1; + down_back = recon_down_back >> 1; + right_half_back = recon_right_back & 0x1; + down_half_back = recon_down_back & 0x1; + + /* Establish row size. */ + + row_size = (vid_stream->mb_width << 3); + + /* Calculate row,col of upper left pixel in block. */ + + row = (mb_row << 3); + col = (mb_col << 3); + + forw_col_start = col + right_for; + forw_row_start = row + down_for; + + back_col_start = col + right_back; + back_row_start = row + down_back; + +#ifdef LOOSE_MPEG + + /* Check for illegal pred. blocks. */ + + if (forw_col_start+8 > cmaxx) illegal_forw = 1; + else if (forw_col_start < 0) illegal_forw = 1; + + if (forw_row_start+8 > cmaxy) illegal_forw = 1; + else if (forw_row_start < 0) illegal_forw = 1; + + if (back_col_start+8 > cmaxx) illegal_back = 1; + else if (back_col_start < 0) illegal_back = 1; + + if (back_row_start+8 > cmaxy) illegal_back = 1; + else if (back_row_start < 0) illegal_back = 1; + +#endif + + /* If block is Cr block... */ + + if (bnum == 4) { + + /* Set dest to Cr plane of current pict image. */ + + dest = vid_stream->current->Cr; + + /* If past frame exists, set past to Cr plane of past image. */ + + if (vid_stream->past != NULL) + past = vid_stream->past->Cr; + + /* + * If future frame exists, set future to Cr plane of future image. + */ + + if (vid_stream->future != NULL) + future = vid_stream->future->Cr; + } + /* Otherwise, block is Cb block... */ + + else { + + /* Set dest to Cb plane of current pict image. */ + + dest = vid_stream->current->Cb; + + /* If past frame exists, set past to Cb plane of past frame. */ + + if (vid_stream->past != NULL) + past = vid_stream->past->Cb; + + /* + * If future frame exists, set future to Cb plane of future frame. + */ + + if (vid_stream->future != NULL) + future = vid_stream->future->Cb; + } + } + + /* For each pixel in block... */ + + index = dest + (row * row_size) + col; + +#ifdef LOOSE_MPEG + if (illegal_forw) + rindex1 = future + back_row_start * row_size + back_col_start; + else +#endif + rindex1 = past + forw_row_start * row_size + forw_col_start; + +#ifdef LOOSE_MPEG + if (illegal_back) + bindex1 = past + forw_row_start * row_size + forw_col_start; + else +#endif + bindex1 = future + back_row_start * row_size + back_col_start; + + blockvals = (short int *) &(vid_stream->block.dct_recon[0][0]); + + { + unsigned char *cm = cropTbl + MAX_NEG_CROP; + if (!zflag) + for (rr = 0; rr < 4; rr++) { + index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[0]]; + index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[1]]; + index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[2]]; + index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[3]]; + index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[4]]; + index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[5]]; + index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[6]]; + index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[7]]; + index += row_size; + rindex1 += row_size; + bindex1 += row_size; + + index[0] = cm[((int) (rindex1[0] + bindex1[0]) >> 1) + blockvals[8]]; + index[1] = cm[((int) (rindex1[1] + bindex1[1]) >> 1) + blockvals[9]]; + index[2] = cm[((int) (rindex1[2] + bindex1[2]) >> 1) + blockvals[10]]; + index[3] = cm[((int) (rindex1[3] + bindex1[3]) >> 1) + blockvals[11]]; + index[4] = cm[((int) (rindex1[4] + bindex1[4]) >> 1) + blockvals[12]]; + index[5] = cm[((int) (rindex1[5] + bindex1[5]) >> 1) + blockvals[13]]; + index[6] = cm[((int) (rindex1[6] + bindex1[6]) >> 1) + blockvals[14]]; + index[7] = cm[((int) (rindex1[7] + bindex1[7]) >> 1) + blockvals[15]]; + blockvals += 16; + index += row_size; + rindex1 += row_size; + bindex1 += row_size; + } + + else + for (rr = 0; rr < 4; rr++) { + index[0] = (int) (rindex1[0] + bindex1[0]) >> 1; + index[1] = (int) (rindex1[1] + bindex1[1]) >> 1; + index[2] = (int) (rindex1[2] + bindex1[2]) >> 1; + index[3] = (int) (rindex1[3] + bindex1[3]) >> 1; + index[4] = (int) (rindex1[4] + bindex1[4]) >> 1; + index[5] = (int) (rindex1[5] + bindex1[5]) >> 1; + index[6] = (int) (rindex1[6] + bindex1[6]) >> 1; + index[7] = (int) (rindex1[7] + bindex1[7]) >> 1; + index += row_size; + rindex1 += row_size; + bindex1 += row_size; + + index[0] = (int) (rindex1[0] + bindex1[0]) >> 1; + index[1] = (int) (rindex1[1] + bindex1[1]) >> 1; + index[2] = (int) (rindex1[2] + bindex1[2]) >> 1; + index[3] = (int) (rindex1[3] + bindex1[3]) >> 1; + index[4] = (int) (rindex1[4] + bindex1[4]) >> 1; + index[5] = (int) (rindex1[5] + bindex1[5]) >> 1; + index[6] = (int) (rindex1[6] + bindex1[6]) >> 1; + index[7] = (int) (rindex1[7] + bindex1[7]) >> 1; + index += row_size; + rindex1 += row_size; + bindex1 += row_size; + } + } +} + +/* + *-------------------------------------------------------------- + * + * ProcessSkippedPFrameMBlocks -- + * + * Processes skipped macroblocks in P frames. + * + * Results: + * Calculates pixel values for luminance, Cr, and Cb planes + * in current pict image for skipped macroblocks. + * + * Side effects: + * Pixel values in pict image changed. + * + *-------------------------------------------------------------- + */ + +static void +ProcessSkippedPFrameMBlocks(VidStream *vid_stream) +{ + int row_size, half_row, mb_row, mb_col, row, col, rr; + int addr, row_incr, half_row_incr, crow, ccol; + int *dest, *src, *dest1, *src1; + + /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */ + + row_size = vid_stream->mb_width << 4; + half_row = (row_size >> 1); + row_incr = row_size >> 2; + half_row_incr = half_row >> 2; + + /* For each skipped macroblock, do... */ + + for (addr = vid_stream->mblock.past_mb_addr + 1; + addr < vid_stream->mblock.mb_address; addr++) { + + /* Calculate macroblock row and col. */ + + mb_row = addr / vid_stream->mb_width; + mb_col = addr % vid_stream->mb_width; + + /* Calculate upper left pixel row,col for luminance plane. */ + + row = mb_row << 4; + col = mb_col << 4; + + + /* For each row in macroblock luminance plane... */ + + dest = (int *)(vid_stream->current->luminance + (row * row_size) + col); + src = (int *)(vid_stream->future->luminance + (row * row_size) + col); + + for (rr = 0; rr < 8; rr++) { + + /* Copy pixel values from last I or P picture. */ + + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = src[3]; + dest += row_incr; + src += row_incr; + + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = src[3]; + dest += row_incr; + src += row_incr; + } + + /* + * Divide row,col to get upper left pixel of macroblock in Cr and Cb + * planes. + */ + + crow = row >> 1; + ccol = col >> 1; + + /* For each row in Cr, and Cb planes... */ + + dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol); + src = (int *)(vid_stream->future->Cr + (crow * half_row) + ccol); + dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol); + src1 = (int *)(vid_stream->future->Cb + (crow * half_row) + ccol); + + for (rr = 0; rr < 4; rr++) { + + /* Copy pixel values from last I or P picture. */ + + dest[0] = src[0]; + dest[1] = src[1]; + + dest1[0] = src1[0]; + dest1[1] = src1[1]; + + dest += half_row_incr; + src += half_row_incr; + dest1 += half_row_incr; + src1 += half_row_incr; + + dest[0] = src[0]; + dest[1] = src[1]; + + dest1[0] = src1[0]; + dest1[1] = src1[1]; + + dest += half_row_incr; + src += half_row_incr; + dest1 += half_row_incr; + src1 += half_row_incr; + } + + if (ditherType == MBORDERED_DITHER) { + /* + MBOrderedDitherDisplayCopy(vid_stream, addr, + 1, 0, 0, 0, 0, 0, + vid_stream->future->display, + (unsigned char *) NULL); + ditherFlags[addr] = 0; + */ + } + } + + vid_stream->mblock.recon_right_for_prev = 0; + vid_stream->mblock.recon_down_for_prev = 0; +} + + + + +/* + *-------------------------------------------------------------- + * + * ProcessSkippedBFrameMBlocks -- + * + * Processes skipped macroblocks in B frames. + * + * Results: + * Calculates pixel values for luminance, Cr, and Cb planes + * in current pict image for skipped macroblocks. + * + * Side effects: + * Pixel values in pict image changed. + * + *-------------------------------------------------------------- + */ + +static void +ProcessSkippedBFrameMBlocks(VidStream *vid_stream) +{ + int row_size, half_row, mb_row, mb_col, row, col, rr; + int right_half_for, down_half_for, c_right_half_for, c_down_half_for; + int right_half_back, down_half_back, c_right_half_back, c_down_half_back; + int addr, right_for, down_for; + int recon_right_for, recon_down_for; + int recon_right_back, recon_down_back; + int right_back, down_back; + int c_right_for, c_down_for; + int c_right_back, c_down_back; + unsigned char forw_lum[256]; + unsigned char forw_cr[64], forw_cb[64]; + unsigned char back_lum[256], back_cr[64], back_cb[64]; + int row_incr, half_row_incr; + int ccol, crow; + + /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */ + + row_size = vid_stream->mb_width << 4; + half_row = (row_size >> 1); + row_incr = row_size >> 2; + half_row_incr = half_row >> 2; + + /* Establish motion vector codes based on full pixel flag. */ + + if (vid_stream->picture.full_pel_forw_vector) { + recon_right_for = vid_stream->mblock.recon_right_for_prev << 1; + recon_down_for = vid_stream->mblock.recon_down_for_prev << 1; + } else { + recon_right_for = vid_stream->mblock.recon_right_for_prev; + recon_down_for = vid_stream->mblock.recon_down_for_prev; + } + + if (vid_stream->picture.full_pel_back_vector) { + recon_right_back = vid_stream->mblock.recon_right_back_prev << 1; + recon_down_back = vid_stream->mblock.recon_down_back_prev << 1; + } else { + recon_right_back = vid_stream->mblock.recon_right_back_prev; + recon_down_back = vid_stream->mblock.recon_down_back_prev; + } + + + /* If only one motion vector, do display copy, else do full + calculation. + */ + + if (ditherType == MBORDERED_DITHER) { + if (vid_stream->mblock.bpict_past_forw && + !vid_stream->mblock.bpict_past_back) { + for (addr = vid_stream->mblock.past_mb_addr+1; + addr < vid_stream->mblock.mb_address; addr++) { + /* + MBOrderedDitherDisplayCopy(vid_stream, addr, + 1, recon_right_for, recon_down_for, + 0, 0, 0, vid_stream->past->display, + vid_stream->future->display); + ditherFlags[addr] = 0; + */ + } + return; + } + if (vid_stream->mblock.bpict_past_back && + !vid_stream->mblock.bpict_past_forw) { + for (addr = vid_stream->mblock.past_mb_addr+1; + addr < vid_stream->mblock.mb_address; addr++) { + /* + MBOrderedDitherDisplayCopy(vid_stream, addr, + 0, 0, 0, + 1, recon_right_back, recon_down_back, + vid_stream->past->display, vid_stream->future->display); + ditherFlags[addr] = 0; + */ + } + return; + } + } + + /* Calculate motion vectors. */ + + if (vid_stream->mblock.bpict_past_forw) { + right_for = recon_right_for >> 1; + down_for = recon_down_for >> 1; + right_half_for = recon_right_for & 0x1; + down_half_for = recon_down_for & 0x1; + + recon_right_for /= 2; + recon_down_for /= 2; + c_right_for = recon_right_for >> 1; + c_down_for = recon_down_for >> 1; + c_right_half_for = recon_right_for & 0x1; + c_down_half_for = recon_down_for & 0x1; + + } + if (vid_stream->mblock.bpict_past_back) { + right_back = recon_right_back >> 1; + down_back = recon_down_back >> 1; + right_half_back = recon_right_back & 0x1; + down_half_back = recon_down_back & 0x1; + + recon_right_back /= 2; + recon_down_back /= 2; + c_right_back = recon_right_back >> 1; + c_down_back = recon_down_back >> 1; + c_right_half_back = recon_right_back & 0x1; + c_down_half_back = recon_down_back & 0x1; + + } + /* For each skipped macroblock, do... */ + + for (addr = vid_stream->mblock.past_mb_addr + 1; + addr < vid_stream->mblock.mb_address; addr++) { + + /* Calculate macroblock row and col. */ + + mb_row = addr / vid_stream->mb_width; + mb_col = addr % vid_stream->mb_width; + + /* Calculate upper left pixel row,col for luminance plane. */ + + row = mb_row << 4; + col = mb_col << 4; + crow = row / 2; + ccol = col / 2; + + /* If forward predicted, calculate prediction values. */ + + if (vid_stream->mblock.bpict_past_forw) { + + ReconSkippedBlock(vid_stream->past->luminance, forw_lum, + row, col, row_size, right_for, down_for, + right_half_for, down_half_for, 16); + ReconSkippedBlock(vid_stream->past->Cr, forw_cr, crow, + ccol, half_row, + c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8); + ReconSkippedBlock(vid_stream->past->Cb, forw_cb, crow, + ccol, half_row, + c_right_for, c_down_for, c_right_half_for, c_down_half_for, 8); + } + /* If back predicted, calculate prediction values. */ + + if (vid_stream->mblock.bpict_past_back) { + ReconSkippedBlock(vid_stream->future->luminance, back_lum, + row, col, row_size, right_back, down_back, + right_half_back, down_half_back, 16); + ReconSkippedBlock(vid_stream->future->Cr, back_cr, crow, + ccol, half_row, + c_right_back, c_down_back, + c_right_half_back, c_down_half_back, 8); + ReconSkippedBlock(vid_stream->future->Cb, back_cb, crow, + ccol, half_row, + c_right_back, c_down_back, + c_right_half_back, c_down_half_back, 8); + } + if (vid_stream->mblock.bpict_past_forw && + !vid_stream->mblock.bpict_past_back) { + + int *dest, *dest1; + int *src, *src1; + dest = (int *)(vid_stream->current->luminance + (row * row_size) + col); + src = (int *)forw_lum; + + for (rr = 0; rr < 16; rr++) { + + /* ACE_OS::memcpy (dest, forw_lum+(rr<<4), 16); */ + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = src[3]; + dest += row_incr; + src += 4; + } + + dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol); + dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol); + src = (int *)forw_cr; + src1 = (int *)forw_cb; + + for (rr = 0; rr < 8; rr++) { + /* + * ACE_OS::memcpy (dest, forw_cr+(rr<<3), 8); ACE_OS::memcpy (dest1, forw_cb+(rr<<3), + * 8); + */ + + dest[0] = src[0]; + dest[1] = src[1]; + + dest1[0] = src1[0]; + dest1[1] = src1[1]; + + dest += half_row_incr; + dest1 += half_row_incr; + src += 2; + src1 += 2; + } + } else if (vid_stream->mblock.bpict_past_back && + !vid_stream->mblock.bpict_past_forw) { + + int *src, *src1; + int *dest, *dest1; + dest = (int *)(vid_stream->current->luminance + (row * row_size) + col); + src = (int *)back_lum; + + for (rr = 0; rr < 16; rr++) { + dest[0] = src[0]; + dest[1] = src[1]; + dest[2] = src[2]; + dest[3] = src[3]; + dest += row_incr; + src += 4; + } + + + dest = (int *)(vid_stream->current->Cr + (crow * half_row) + ccol); + dest1 = (int *)(vid_stream->current->Cb + (crow * half_row) + ccol); + src = (int *)back_cr; + src1 = (int *)back_cb; + + for (rr = 0; rr < 8; rr++) { + /* + * ACE_OS::memcpy (dest, back_cr+(rr<<3), 8); ACE_OS::memcpy (dest1, back_cb+(rr<<3), + * 8); + */ + + dest[0] = src[0]; + dest[1] = src[1]; + + dest1[0] = src1[0]; + dest1[1] = src1[1]; + + dest += half_row_incr; + dest1 += half_row_incr; + src += 2; + src1 += 2; + } + } else { + + unsigned char *src1, *src2, *src1a, *src2a; + unsigned char *dest, *dest1; + dest = vid_stream->current->luminance + (row * row_size) + col; + src1 = forw_lum; + src2 = back_lum; + + for (rr = 0; rr < 16; rr++) { + dest[0] = (int) (src1[0] + src2[0]) >> 1; + dest[1] = (int) (src1[1] + src2[1]) >> 1; + dest[2] = (int) (src1[2] + src2[2]) >> 1; + dest[3] = (int) (src1[3] + src2[3]) >> 1; + dest[4] = (int) (src1[4] + src2[4]) >> 1; + dest[5] = (int) (src1[5] + src2[5]) >> 1; + dest[6] = (int) (src1[6] + src2[6]) >> 1; + dest[7] = (int) (src1[7] + src2[7]) >> 1; + dest[8] = (int) (src1[8] + src2[8]) >> 1; + dest[9] = (int) (src1[9] + src2[9]) >> 1; + dest[10] = (int) (src1[10] + src2[10]) >> 1; + dest[11] = (int) (src1[11] + src2[11]) >> 1; + dest[12] = (int) (src1[12] + src2[12]) >> 1; + dest[13] = (int) (src1[13] + src2[13]) >> 1; + dest[14] = (int) (src1[14] + src2[14]) >> 1; + dest[15] = (int) (src1[15] + src2[15]) >> 1; + dest += row_size; + src1 += 16; + src2 += 16; + } + + + dest = vid_stream->current->Cr + (crow * half_row) + ccol; + dest1 = vid_stream->current->Cb + (crow * half_row) + ccol; + src1 = forw_cr; + src2 = back_cr; + src1a = forw_cb; + src2a = back_cb; + + for (rr = 0; rr < 8; rr++) { + dest[0] = (int) (src1[0] + src2[0]) >> 1; + dest[1] = (int) (src1[1] + src2[1]) >> 1; + dest[2] = (int) (src1[2] + src2[2]) >> 1; + dest[3] = (int) (src1[3] + src2[3]) >> 1; + dest[4] = (int) (src1[4] + src2[4]) >> 1; + dest[5] = (int) (src1[5] + src2[5]) >> 1; + dest[6] = (int) (src1[6] + src2[6]) >> 1; + dest[7] = (int) (src1[7] + src2[7]) >> 1; + dest += half_row; + src1 += 8; + src2 += 8; + + dest1[0] = (int) (src1a[0] + src2a[0]) >> 1; + dest1[1] = (int) (src1a[1] + src2a[1]) >> 1; + dest1[2] = (int) (src1a[2] + src2a[2]) >> 1; + dest1[3] = (int) (src1a[3] + src2a[3]) >> 1; + dest1[4] = (int) (src1a[4] + src2a[4]) >> 1; + dest1[5] = (int) (src1a[5] + src2a[5]) >> 1; + dest1[6] = (int) (src1a[6] + src2a[6]) >> 1; + dest1[7] = (int) (src1a[7] + src2a[7]) >> 1; + dest1 += half_row; + src1a += 8; + src2a += 8; + } + } + + if (ditherType == MBORDERED_DITHER) { + ditherFlags[addr] = 1; + } + } +} + + + + +/* + *-------------------------------------------------------------- + * + * ReconSkippedBlock -- + * + * Reconstructs predictive block for skipped macroblocks + * in B Frames. + * + * Results: + * No return values. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +static void +ReconSkippedBlock(unsigned char *source, unsigned char *dest, + int row, int col, int row_size, int right, int down, + int right_half, int down_half, int width) +{ + int rr; + unsigned char *source2; + + source += ((row + down) * row_size) + col + right; + + if (width == 16) { + if ((!right_half) && (!down_half)) { + if (right & 0x1) { + /* No alignment, use bye copy */ + for (rr = 0; rr < 16; rr++) { + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; + dest[4] = source[4]; + dest[5] = source[5]; + dest[6] = source[6]; + dest[7] = source[7]; + dest[8] = source[8]; + dest[9] = source[9]; + dest[10] = source[10]; + dest[11] = source[11]; + dest[12] = source[12]; + dest[13] = source[13]; + dest[14] = source[14]; + dest[15] = source[15]; + dest += 16; + source += row_size; + } + } else if (right & 0x2) { + /* Half-word bit aligned, use 16 bit copy */ + short *src = (short *)source; + short *d = (short *)dest; + row_size >>= 1; + for (rr = 0; rr < 16; rr++) { + d[0] = src[0]; + d[1] = src[1]; + d[2] = src[2]; + d[3] = src[3]; + d[4] = src[4]; + d[5] = src[5]; + d[6] = src[6]; + d[7] = src[7]; + d += 8; + src += row_size; + } + } else { + /* Word aligned, use 32 bit copy */ + int *src = (int *)source; + int *d = (int *)dest; + row_size >>= 2; + for (rr = 0; rr < 16; rr++) { + d[0] = src[0]; + d[1] = src[1]; + d[2] = src[2]; + d[3] = src[3]; + d += 4; + src += row_size; + } + } + } else { + source2 = source + right_half + (row_size * down_half); + for (rr = 0; rr < width; rr++) { + dest[0] = (int) (source[0] + source2[0]) >> 1; + dest[1] = (int) (source[1] + source2[1]) >> 1; + dest[2] = (int) (source[2] + source2[2]) >> 1; + dest[3] = (int) (source[3] + source2[3]) >> 1; + dest[4] = (int) (source[4] + source2[4]) >> 1; + dest[5] = (int) (source[5] + source2[5]) >> 1; + dest[6] = (int) (source[6] + source2[6]) >> 1; + dest[7] = (int) (source[7] + source2[7]) >> 1; + dest[8] = (int) (source[8] + source2[8]) >> 1; + dest[9] = (int) (source[9] + source2[9]) >> 1; + dest[10] = (int) (source[10] + source2[10]) >> 1; + dest[11] = (int) (source[11] + source2[11]) >> 1; + dest[12] = (int) (source[12] + source2[12]) >> 1; + dest[13] = (int) (source[13] + source2[13]) >> 1; + dest[14] = (int) (source[14] + source2[14]) >> 1; + dest[15] = (int) (source[15] + source2[15]) >> 1; + dest += width; + source += row_size; + source2 += row_size; + } + } + } else { /* (width == 8) */ + assert(width == 8); + if ((!right_half) && (!down_half)) { + if (right & 0x1) { + for (rr = 0; rr < width; rr++) { + dest[0] = source[0]; + dest[1] = source[1]; + dest[2] = source[2]; + dest[3] = source[3]; + dest[4] = source[4]; + dest[5] = source[5]; + dest[6] = source[6]; + dest[7] = source[7]; + dest += 8; + source += row_size; + } + } else if (right & 0x02) { + short *d = (short *)dest; + short *src = (short *)source; + row_size >>= 1; + for (rr = 0; rr < width; rr++) { + d[0] = src[0]; + d[1] = src[1]; + d[2] = src[2]; + d[3] = src[3]; + d += 4; + src += row_size; + } + } else { + int *d = (int *)dest; + int *src = (int *)source; + row_size >>= 2; + for (rr = 0; rr < width; rr++) { + d[0] = src[0]; + d[1] = src[1]; + d += 2; + src += row_size; + } + } + } else { + source2 = source + right_half + (row_size * down_half); + for (rr = 0; rr < width; rr++) { + dest[0] = (int) (source[0] + source2[0]) >> 1; + dest[1] = (int) (source[1] + source2[1]) >> 1; + dest[2] = (int) (source[2] + source2[2]) >> 1; + dest[3] = (int) (source[3] + source2[3]) >> 1; + dest[4] = (int) (source[4] + source2[4]) >> 1; + dest[5] = (int) (source[5] + source2[5]) >> 1; + dest[6] = (int) (source[6] + source2[6]) >> 1; + dest[7] = (int) (source[7] + source2[7]) >> 1; + dest += width; + source += row_size; + source2 += row_size; + } + } + } +} + +/* + *-------------------------------------------------------------- + * + * ToggleBFlag -- + * + * Called to set no b frame processing flag. + * + * Results: + * No_B_Flag flag is toggled from present value to opposite value. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +void +ToggleBFlag() +{ + if (No_B_Flag) { + No_B_Flag = 0; + } else + No_B_Flag = 1; +} + + + + +/* + *-------------------------------------------------------------- + * + * TogglePFlag -- + * + * Called to set no p frame processing flag. + * + * Results: + * No_P_Flag flag is toggled from present value to opposite value. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +void +TogglePFlag() +{ + if (No_P_Flag) { + No_P_Flag = 0; + } else + No_P_Flag = 1; +} |