/* 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"<mpegVideoHeader)->getMB_Height(); int w=(vid_stream->mpegVideoHeader)->getMB_Width(); DEBUG_MACROBLOCK(cout <<"mb_height*mb_width-1:"<<(h*w - 1)<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"<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"<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"<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"<> 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"<= picSrc+lumEnd) || (picSrcStart < picSrc)) { DEBUG_MACROBLOCK(cout << "urg! last resort caught before sigsev skipped -2"<> 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"<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)"<> 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"<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"<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"<>= 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); } } }