summaryrefslogtreecommitdiffstats
path: root/mpeglib/lib/mpegplay/macroBlock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mpeglib/lib/mpegplay/macroBlock.cpp')
-rw-r--r--mpeglib/lib/mpegplay/macroBlock.cpp1152
1 files changed, 1152 insertions, 0 deletions
diff --git a/mpeglib/lib/mpegplay/macroBlock.cpp b/mpeglib/lib/mpegplay/macroBlock.cpp
new file mode 100644
index 00000000..2e35e551
--- /dev/null
+++ b/mpeglib/lib/mpegplay/macroBlock.cpp
@@ -0,0 +1,1152 @@
+/*
+ stores macroblock infos
+ Copyright (C) 2000 Martin Vogt
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation.
+
+ For more information look at the file COPYRIGHT in this package
+
+ */
+
+
+#include "macroBlock.h"
+
+#define DEBUG_MACROBLOCK(x)
+//#define DEBUG_MACROBLOCK(x) x
+
+
+
+MacroBlock::MacroBlock(VideoDecoder* vid_stream) {
+ this->vid_stream=vid_stream;
+ copyFunctions=new CopyFunctions();
+}
+
+
+MacroBlock::~MacroBlock() {
+ delete copyFunctions;
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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.
+ *
+ *--------------------------------------------------------------
+ */
+
+int MacroBlock::processMacroBlock(PictureArray* pictureArray) {
+ unsigned int data;
+ int recon_right_for, recon_down_for, recon_right_back,
+ recon_down_back;
+ int mb_quant = 0, mb_motion_forw = 0, mb_motion_back = 0,
+ mb_pattern = 0;
+
+ int addr_incr;
+ MpegVideoStream* mpegVideoStream=vid_stream->mpegVideoStream;
+ DecoderClass* decoderClass=vid_stream->decoderClass;
+
+ /*
+ * Parse off macroblock address increment and add to macroblock address.
+ */
+ do {
+ addr_incr=decoderClass->decodeMBAddrInc();
+ if (addr_incr==MB_ESCAPE) {
+ mb_address += 33;
+ addr_incr=MB_STUFFING;
+ }
+
+ } while (addr_incr == MB_STUFFING);
+ mb_address+=addr_incr;
+
+
+
+ if (mb_address > (vid_stream->mpegVideoHeader)->getMB_Size()) {
+
+ DEBUG_MACROBLOCK(cout <<"ParseMacroBlock: SKIP_TO_START_CODE"<<endl;)
+ DEBUG_MACROBLOCK(cout <<"mb_address "<<mb_address<<endl;)
+
+ int h=(vid_stream->mpegVideoHeader)->getMB_Height();
+ int w=(vid_stream->mpegVideoHeader)->getMB_Width();
+
+
+ DEBUG_MACROBLOCK(cout <<"mb_height*mb_width-1:"<<(h*w - 1)<<endl;)
+ return false;
+ }
+
+ /*
+ * If macroblocks have been skipped, process skipped macroblocks.
+ */
+
+ int code_type=(vid_stream->picture)->getCodeType();
+
+ if (mb_address - past_mb_addr > 1) {
+
+ processSkippedPictures(pictureArray,code_type,
+ (vid_stream->mpegVideoHeader)->getMB_Width());
+
+ }
+
+
+ /* Set past macroblock address to current macroblock address. */
+ past_mb_addr = mb_address;
+ /* Based on picture type decode macroblock type. */
+
+
+ switch (code_type) {
+ case I_TYPE:
+ decoderClass->decodeMBTypeI(mb_quant, mb_motion_forw,
+ mb_motion_back, mb_pattern,
+ mb_intra);
+ break;
+
+ case P_TYPE:
+ decoderClass->decodeMBTypeP(mb_quant, mb_motion_forw,
+ mb_motion_back, mb_pattern,
+ mb_intra);
+ break;
+
+ case B_TYPE:
+ decoderClass->decodeMBTypeB(mb_quant, mb_motion_forw,
+ mb_motion_back, mb_pattern,
+ mb_intra);
+ break;
+ case D_TYPE:
+ DEBUG_MACROBLOCK(cout <<"ERROR: MPEG-1 Streams with D-frames are not supported"<<endl;)
+ return false;
+
+ }
+ /* If quantization flag set, parse off new quantization scale. */
+ if (mb_quant == true) {
+ data=mpegVideoStream->getBits(5);
+ (vid_stream->slice)->setQuantScale(data);
+ }
+ /* If forward motion vectors exist... */
+
+ if (mb_motion_forw == true) {
+ // Parse off and decode horizontal forward motion vector.
+ motion_h_forw_code=decoderClass->decodeMotionVectors();
+
+ // If horiz. forward r data exists, parse off.
+
+ if ((vid_stream->picture->getForw_f() != 1) &&
+ (motion_h_forw_code != 0)) {
+ data=vid_stream->picture->geth_forw_r(mpegVideoStream);
+ motion_h_forw_r = data;
+ }
+ // Parse off and decode vertical forward motion vector.
+
+ motion_v_forw_code=decoderClass->decodeMotionVectors();
+
+ // If vert. forw. r data exists, parse off.
+
+ if ((vid_stream->picture->getForw_f() != 1) &&
+ (motion_v_forw_code != 0)) {
+
+ data=vid_stream->picture->getv_forw_r(mpegVideoStream);
+ motion_v_forw_r = data;
+ }
+ }
+
+ /* If back motion vectors exist... */
+
+ if (mb_motion_back == true) {
+ // Parse off and decode horiz. back motion vector.
+ motion_h_back_code=decoderClass->decodeMotionVectors();
+
+ // If horiz. back r data exists, parse off.
+
+ if ((vid_stream->picture->getBack_f() != 1) &&
+ (motion_h_back_code != 0)) {
+ data=vid_stream->picture->geth_back_r(mpegVideoStream);
+ motion_h_back_r = data;
+ }
+ // Parse off and decode vert. back motion vector.
+ motion_v_back_code=decoderClass->decodeMotionVectors();
+
+ // If vert. back r data exists, parse off.
+
+ if ((vid_stream->picture->getBack_f() != 1) &&
+ (motion_v_back_code != 0)) {
+ data=vid_stream->picture->getv_back_r(mpegVideoStream);
+ motion_v_back_r = data;
+ }
+ }
+
+ /* If mblock pattern flag set, parse and decode CBP (code block pattern). */
+ if (mb_pattern == true) {
+ cbp=decoderClass->decodeCBP();
+ }
+ /* Otherwise, set CBP to zero. */
+ else
+ cbp = 0;
+
+
+
+ /* Reconstruct motion vectors depending on picture type. */
+ if (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;
+ recon_right_for_prev = 0;
+ 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 (code_type == B_TYPE) {
+
+ /* Reset prev. and current vectors to zero if mblock is intracoded. */
+ if (mb_intra) {
+ recon_right_for_prev = 0;
+ recon_down_for_prev = 0;
+ recon_right_back_prev = 0;
+ recon_down_back_prev = 0;
+ } else {
+
+ /* If no forw vectors, current vectors equal prev. vectors. */
+
+ if (!mb_motion_forw) {
+ recon_right_for = recon_right_for_prev;
+ recon_down_for = 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 = recon_right_back_prev;
+ recon_down_back = recon_down_back_prev;
+ }
+ /* Otherwise compute new vectors and reset prev. back vectors. */
+
+ else {
+ computeBackVector(&recon_right_back,&recon_down_back);
+
+ }
+
+ /*
+ * Store vector existence flags in structure for possible skipped
+ * macroblocks to follow.
+ */
+
+ bpict_past_forw = mb_motion_forw;
+ bpict_past_back = mb_motion_back;
+ }
+ }
+ int back;
+ back=reconstruct(recon_right_for,
+ recon_down_for,
+ recon_right_back,
+ recon_down_back,
+ mb_motion_forw,
+ mb_motion_back,
+ pictureArray);
+
+
+ /* If D Type picture, flush marker bit. */
+ if (code_type == D_TYPE) {
+ mpegVideoStream->flushBits(1);
+ }
+
+ /* If macroblock was intracoded, set macroblock past intra address. */
+ if (mb_intra) {
+ past_intra_addr=mb_address;
+ }
+ if (back == false) {
+ return false;
+ }
+ return true;
+}
+
+
+int MacroBlock::resetMacroBlock() {
+ /* Reset past intrablock address. */
+ past_intra_addr = -2;
+
+ /* Reset previous recon motion vectors. */
+
+
+ recon_right_for_prev = 0;
+ recon_down_for_prev = 0;
+ recon_right_back_prev = 0;
+ recon_down_back_prev = 0;
+
+ /* Reset macroblock address. */
+ mb_address = (((vid_stream->slice)->getVertPos()-1) *
+ (vid_stream->mpegVideoHeader)->getMB_Width()) - 1;
+ return true;
+
+}
+
+
+int MacroBlock::resetPastMacroBlock() {
+ /* Reset past macroblock address field. */
+
+ past_mb_addr = -1;
+ return true;
+}
+
+
+
+
+int MacroBlock::reconstruct(int& recon_right_for,
+ int& recon_down_for,
+ int& recon_right_back,
+ int& recon_down_back,
+ int& mb_motion_forw,
+ int& mb_motion_back,
+ PictureArray* pictureArray) {
+ int mask, i;
+ int zero_block_flag;
+ int mb_row;
+ int mb_col;
+ int mb_width=(vid_stream->mpegVideoHeader)->getMB_Width();
+ int row_size=pictureArray->getWidth();
+ short int* dct_start=(vid_stream->decoderClass)->getDCT();
+ unsigned int qscale=(vid_stream->slice)->getQuantScale();
+ int codeType=(vid_stream->picture)->getCodeType();
+ DecoderClass* decoderClass=vid_stream->decoderClass;
+ int lflag=false;
+ Recon* recon=vid_stream->recon;
+ unsigned int* iqmatrixptr=
+ (vid_stream->mpegVideoHeader)->getIntra_quant_matrix();
+ unsigned int* niqmatrixptr=
+ (vid_stream->mpegVideoHeader)->getNon_intra_quant_matrix();
+
+
+
+
+
+ if (mb_address-past_intra_addr > 1) {
+ lflag=true;
+ }
+
+ if (mb_width <= 0) {
+ DEBUG_MACROBLOCK(cout << "mb_width <= 0"<<endl;)
+ return false;
+ }
+ /* Calculate macroblock row and column from address. */
+ mb_row=mb_address / mb_width;
+ mb_col=mb_address % mb_width;
+
+ copyFunctions->startNOFloatSection();
+
+ for (mask = 32, i = 0; i < 6; mask >>= 1, i++) {
+
+
+ /* If block exists... */
+ if ((mb_intra) || (cbp & mask)) {
+ zero_block_flag = 0;
+ //copyFunctions->endNOFloatSection();
+ decoderClass->ParseReconBlock(i,mb_intra,
+ qscale,lflag,iqmatrixptr,niqmatrixptr);
+ //copyFunctions->endNOFloatSection();
+ } else {
+ zero_block_flag = 1;
+ }
+
+
+ // If macroblock is intra coded...
+
+
+ if (mb_intra) {
+ recon->ReconIMBlock(i,mb_row,mb_col,row_size,
+ dct_start,pictureArray);
+ //copyFunctions->endNOFloatSection();
+ } else if (mb_motion_forw && mb_motion_back) {
+ recon->ReconBiMBlock(i,recon_right_for,
+ recon_down_for,recon_right_back,
+ recon_down_back,zero_block_flag,
+ mb_row,mb_col,row_size,dct_start,
+ pictureArray);
+ //copyFunctions->endNOFloatSection();
+ } else if (mb_motion_forw || (codeType ==P_TYPE)){
+ recon->ReconPMBlock(i,recon_right_for,
+ recon_down_for,zero_block_flag,
+ mb_row,mb_col,row_size,dct_start,
+ pictureArray, codeType);
+ //copyFunctions->endNOFloatSection();
+ } else if (mb_motion_back) {
+ recon->ReconBMBlock(i,recon_right_back,
+ recon_down_back,zero_block_flag,
+ mb_row,mb_col,row_size,dct_start,
+ pictureArray);
+ //copyFunctions->endNOFloatSection();
+
+ } else {
+ //DEBUG_MACROBLOCK(cout << "nothing"<<endl;)
+ }
+
+ }
+ copyFunctions->endNOFloatSection();
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeForwVector --
+ *
+ * Computes forward motion vector by calling ComputeVector
+ * with appropriate parameters.
+ *
+ * Results:
+ * Reconstructed motion vector placed in recon_right_for_ptr and
+ * recon_down_for_ptr.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void MacroBlock::computeForwVector(int* recon_right_for_ptr,
+ int* recon_down_for_ptr) {
+
+ Picture *picture;
+
+
+ picture = vid_stream->picture;
+
+
+ unsigned int forw_f=picture->getForw_f();
+ unsigned int full_pel_forw_vector=picture->getFull_pel_forw_vector();
+ vid_stream->motionVector->computeVector(recon_right_for_ptr,
+ recon_down_for_ptr,
+ recon_right_for_prev,
+ recon_down_for_prev,
+ forw_f,
+ full_pel_forw_vector,
+ motion_h_forw_code,
+ motion_v_forw_code,
+ motion_h_forw_r,
+ motion_v_forw_r);
+ picture->setForw_f(forw_f);
+ picture->setFull_pel_forw_vector(full_pel_forw_vector);
+}
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ComputeBackVector --
+ *
+ * Computes backward motion vector by calling ComputeVector
+ * with appropriate parameters.
+ *
+ * Results:
+ * Reconstructed motion vector placed in recon_right_back_ptr and
+ * recon_down_back_ptr.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+
+void MacroBlock::computeBackVector(int* recon_right_back_ptr,
+ int* recon_down_back_ptr) {
+
+ Picture *picture;
+
+
+ picture = vid_stream->picture;
+
+
+ unsigned int back_f=picture->getBack_f();
+ unsigned int full_pel_back_vector=picture->getFull_pel_back_vector();
+
+ vid_stream->motionVector->computeVector(recon_right_back_ptr,
+ recon_down_back_ptr,
+ recon_right_back_prev,
+ recon_down_back_prev,
+ back_f,
+ full_pel_back_vector,
+ motion_h_back_code,
+ motion_v_back_code,
+ motion_h_back_r,
+ motion_v_back_r);
+ picture->setBack_f(back_f);
+ picture->setFull_pel_back_vector(full_pel_back_vector);
+}
+
+
+
+
+
+int MacroBlock::processSkippedPictures(PictureArray* pictureArray,
+ int code_type,
+ int mb_width) {
+ copyFunctions->startNOFloatSection();
+
+ if (code_type == P_TYPE) {
+
+ ProcessSkippedPFrameMBlocks(pictureArray->getCurrent(),
+ pictureArray->getFuture(),
+ mb_width);
+
+ } else {
+ if (code_type == B_TYPE) {
+ ProcessSkippedBFrameMBlocks(vid_stream->picture,
+ pictureArray->getPast(),
+ pictureArray->getCurrent(),
+ pictureArray->getFuture(),
+ mb_width);
+ }
+ }
+
+ copyFunctions->endNOFloatSection();
+
+ return true;
+}
+
+/*
+ *--------------------------------------------------------------
+ *
+ * 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.
+ *
+ *--------------------------------------------------------------
+ */
+void MacroBlock::ProcessSkippedPFrameMBlocks(YUVPicture* current,
+ YUVPicture* future,
+ int mb_width) {
+
+ 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;
+
+ /* For each row in macroblock luminance plane... */
+ if (mb_width == 0) {
+ DEBUG_MACROBLOCK(cout << "mb_width in skipped is 0"<<endl;)
+ return;
+ }
+
+
+ /* Calculate row sizes for luminance and Cr/Cb macroblock areas. */
+
+ row_size = mb_width << 4;
+ half_row = (row_size >> 1);
+ row_incr = row_size >> 2;
+ half_row_incr = half_row >> 2;
+
+ /* For each skipped macroblock, do... */
+ int lumEnd=current->getLumLength();
+ int colorEnd=current->getColorLength();
+
+ unsigned char *picDest;
+ unsigned char *picSrc;
+
+ unsigned char *picDestStart;
+ unsigned char *picSrcStart;
+
+
+
+ for (addr = past_mb_addr + 1; addr < mb_address; addr++) {
+
+ /* Calculate macroblock row and col. */
+
+ mb_row = addr / mb_width;
+ mb_col = addr % mb_width;
+
+ /* Calculate upper left pixel row,col for luminance plane. */
+
+ row = mb_row << 4;
+ col = mb_col << 4;
+
+ picDest=current->getLuminancePtr();
+ picSrc=future->getLuminancePtr();
+
+ picDestStart=(picDest+(row*row_size)+col);
+ picSrcStart=(picSrc+(row*row_size)+col);
+
+ if ((picDestStart+7*row_size+7 >= picDest+lumEnd) ||
+ (picDestStart < picDest)) {
+ DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -1"<<endl;)
+ break;
+ }
+ if ((picSrcStart+7*row_size+7 >= picSrc+lumEnd) ||
+ (picSrcStart < picSrc)) {
+ DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -2"<<endl;)
+ break;
+ }
+
+ dest=(int*)picDestStart;
+ src=(int*)picSrcStart;
+
+
+
+ for (rr = 0; rr < 8; rr++) {
+
+ /* Copy pixel values from last I or P picture. */
+ memcpy(dest,src,sizeof(int)*4);
+
+ dest += row_incr;
+ src += row_incr;
+ memcpy(dest,src,sizeof(int)*4);
+
+ 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... */
+ picDest=current->getCrPtr();
+ picDestStart=(picDest+(crow*half_row)+ccol);
+ if ((picDestStart+7*half_row_incr+7 >= picDest+colorEnd) ||
+ (picDestStart < picDest)) {
+ DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -3"<<endl;)
+ break;
+ }
+
+
+ dest=(int*)(current->getCrPtr()+(crow*half_row)+ccol);
+ src=(int*)(future->getCrPtr()+(crow*half_row)+ccol);
+ dest1=(int*)(current->getCbPtr()+(crow*half_row)+ccol);
+ src1=(int*)(future->getCbPtr()+(crow*half_row)+ccol);
+
+ for (rr = 0; rr < 4; rr++) {
+
+ /* Copy pixel values from last I or P picture. */
+ memcpy(dest,src,sizeof(int)*2);
+ memcpy(dest1,src1,sizeof(int)*2);
+
+
+ dest += half_row_incr;
+ src += half_row_incr;
+ dest1 += half_row_incr;
+ src1 += half_row_incr;
+
+ memcpy(dest,src,sizeof(int)*2);
+ memcpy(dest1,src1,sizeof(int)*2);
+
+ dest += half_row_incr;
+ src += half_row_incr;
+ dest1 += half_row_incr;
+ src1 += half_row_incr;
+ }
+
+ }
+
+ recon_right_for_prev = 0;
+ 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.
+ *
+ *--------------------------------------------------------------
+ */
+
+void MacroBlock::ProcessSkippedBFrameMBlocks(Picture* picture,
+ YUVPicture* past,
+ YUVPicture* current,
+ YUVPicture* future,
+ int mb_width) {
+ int row_size, half_row, mb_row, mb_col, row, col, rr;
+ int right_half_for = 0, down_half_for = 0;
+ int c_right_half_for = 0, c_down_half_for = 0;
+ int right_half_back = 0, down_half_back = 0;
+ int c_right_half_back = 0, c_down_half_back = 0;
+ int addr, right_for = 0, down_for = 0;
+ int recon_right_for, recon_down_for;
+ int recon_right_back, recon_down_back;
+ int right_back = 0, down_back = 0;
+ int c_right_for = 0, c_down_for = 0;
+ int c_right_back = 0, c_down_back = 0;
+ 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. */
+
+ if (mb_width == 0) {
+ DEBUG_MACROBLOCK(cout << "mb_width in skipped is 0 (2)"<<endl;)
+ return;
+ }
+
+ row_size = 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 (picture->getFull_pel_forw_vector()) {
+ recon_right_for = recon_right_for_prev << 1;
+ recon_down_for = recon_down_for_prev << 1;
+ } else {
+ recon_right_for = recon_right_for_prev;
+ recon_down_for = recon_down_for_prev;
+ }
+
+ if (picture->getFull_pel_back_vector()) {
+ recon_right_back = recon_right_back_prev << 1;
+ recon_down_back = recon_down_back_prev << 1;
+ } else {
+ recon_right_back = recon_right_back_prev;
+ recon_down_back = recon_down_back_prev;
+ }
+
+
+ /* If only one motion vector, do display copy, else do full
+ calculation.
+ */
+
+ /* Calculate motion vectors. */
+
+ if (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 (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 = past_mb_addr + 1;
+ addr < mb_address; addr++) {
+
+ /* Calculate macroblock row and col. */
+
+ mb_row = addr / mb_width;
+ mb_col = addr % 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 (bpict_past_forw) {
+ int lumEnd=current->getLumLength();
+ int colorEnd=current->getColorLength();
+ ReconSkippedBlock(past->getLuminancePtr(),
+ forw_lum,row,col,row_size,
+ right_for,down_for,
+ right_half_for,
+ down_half_for,16,lumEnd);
+ ReconSkippedBlock(past->getCrPtr(),
+ forw_cr,crow,ccol, half_row,
+ c_right_for,c_down_for,
+ c_right_half_for,
+ c_down_half_for,8,colorEnd);
+ ReconSkippedBlock(past->getCbPtr(),
+ forw_cb,crow,ccol,half_row,
+ c_right_for,c_down_for,
+ c_right_half_for,
+ c_down_half_for,8,colorEnd);
+ }
+ /* If back predicted, calculate prediction values. */
+
+ if (bpict_past_back) {
+ int lumEnd=current->getLumLength();
+ int colorEnd=current->getColorLength();
+ ReconSkippedBlock(future->getLuminancePtr(),
+ back_lum,row,col,row_size,
+ right_back,down_back,
+ right_half_back,down_half_back,
+ 16,lumEnd);
+ ReconSkippedBlock(future->getCrPtr(),
+ back_cr,crow,ccol,
+ half_row,c_right_back,
+ c_down_back,c_right_half_back,
+ c_down_half_back,8,colorEnd);
+ ReconSkippedBlock(future->getCbPtr(),
+ back_cb,crow,ccol,half_row,
+ c_right_back,c_down_back,
+ c_right_half_back,
+ c_down_half_back,8,colorEnd);
+ }
+ unsigned char* picDest=current->getLuminancePtr();
+ int lumEnd=current->getLumLength();
+ int colorEnd=current->getColorLength();
+
+ unsigned char* picDestStart=(picDest+(row*row_size)+col);
+
+
+ if ((picDestStart+7*row_size+7 >= picDest+lumEnd) ||
+ (picDestStart < picDest)) {
+ DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -4"<<endl;)
+ return;
+ }
+
+ picDest=current->getCrPtr();
+ picDestStart=(picDest+(crow*half_row)+ccol);
+ if ((picDestStart+7*half_row_incr+7 >= picDest+colorEnd) ||
+ (picDestStart < picDest)) {
+ DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -5"<<endl;)
+ exit(0);
+ }
+
+
+ if (bpict_past_forw && !bpict_past_back) {
+
+ int *dest, *dest1;
+ int *src, *src1;
+ dest=(int*)(current->getLuminancePtr()+(row*row_size)+col);
+ src=(int*)forw_lum;
+
+ for (rr = 0; rr < 16; rr++) {
+
+ /* 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*)(current->getCrPtr()+(crow*half_row)+ccol);
+ dest1 = (int*)(current->getCbPtr()+(crow*half_row)+ccol);
+ src = (int*)forw_cr;
+ src1 = (int*)forw_cb;
+
+ for (rr = 0; rr < 8; rr++) {
+ /*
+ * memcpy(dest, forw_cr+(rr<<3), 8); 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 (bpict_past_back && !bpict_past_forw) {
+
+ int *src, *src1;
+ int *dest, *dest1;
+ dest=(int*)(current->getLuminancePtr()+(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 *)(current->getCrPtr()+(crow*half_row)+ccol);
+ dest1 = (int *)(current->getCbPtr()+(crow*half_row)+ccol);
+ src = (int *)back_cr;
+ src1 = (int *)back_cb;
+
+ for (rr = 0; rr < 8; rr++) {
+ /*
+ * memcpy(dest, back_cr+(rr<<3), 8); 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 = current->getLuminancePtr()+(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 = current->getCrPtr() + (crow * half_row) + ccol;
+ dest1 = current->getCbPtr() + (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;
+ }
+ }
+
+ }
+}
+
+
+
+
+
+
+
+/*
+ *--------------------------------------------------------------
+ *
+ * ReconSkippedBlock --
+ *
+ * Reconstructs predictive block for skipped macroblocks
+ * in B Frames.
+ *
+ * Results:
+ * No return values.
+ *
+ * Side effects:
+ * None.
+ *
+ *--------------------------------------------------------------
+ */
+void MacroBlock::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 maxLen) {
+ int rr;
+ unsigned char *source2;
+ unsigned char *tmp;
+
+ tmp = source+((row + down) * row_size) + col + right;
+
+
+ if ((tmp+7*row_size+7 >= source+maxLen) ||
+ (tmp < source)) {
+ DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -6"<<endl;)
+ return;
+ }
+
+ source=tmp;
+ if (width == 16) {
+ if ((!right_half) && (!down_half)) {
+ if (right & 0x1) {
+ /* No alignment, use bye copy */
+ for (rr = 0; rr < 16; rr++) {
+
+ memcpy(dest,source,sizeof(char)*16);
+
+ 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++) {
+
+ memcpy(d,src,sizeof(short)*8);
+
+ 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);
+ copyFunctions->copy16_div2_destlinear_nocrop(source,source2,dest,
+ row_size);
+
+
+ }
+ } else { /* (width == 8) */
+ assert(width == 8);
+ if ((!right_half) && (!down_half)) {
+ if (right & 0x1) {
+ for (rr = 0; rr < width; rr++) {
+
+ memcpy(dest,source,sizeof(char)*8);
+
+ 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);
+ copyFunctions->copy8_div2_destlinear_nocrop(source,source2,
+ dest,row_size);
+ }
+ }
+}
+