📄 bframe.c
字号:
/*===========================================================================* * bframe.c * * Procedures concerned with the B-frame encoding *===========================================================================*//* * Copyright (c) 1995 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. *//*==============* * HEADER FILES * *==============*/#include "all.h"#include <sys/param.h>#include <assert.h>#include "ppm.h"#include "mtypes.h"#include "bitio.h"#include "frames.h"#include "prototypes.h"#include "fsize.h"#include "param.h"#include "mheaders.h"#include "postdct.h"#include "rate.h"#include "opts.h"#include "specifics.h"/*==================* * STATIC VARIABLES * *==================*/static int numBIBlocks = 0;static int numBBBlocks = 0;static int numBSkipped = 0;static int numBIBits = 0;static int numBBBits = 0;static int numFrames = 0;static int numFrameBits = 0;static int32 totalTime = 0;static int qscaleB;static float totalSNR = 0.0;static float totalPSNR = 0.0;static int numBFOBlocks = 0; /* forward only */static int numBBABlocks = 0; /* backward only */static int numBINBlocks = 0; /* interpolate */static int numBFOBits = 0;static int numBBABits = 0;static int numBINBits = 0;/*====================* * EXTERNAL VARIABLES * *====================*/extern Block **dct, **dctr, **dctb;extern dct_data_type **dct_data;#define NO_MOTION 0#define MOTION 1#define SKIP 2 /* used in useMotion in dct_data *//*===============================* * INTERNAL PROCEDURE prototypes * *===============================*/static boolean MotionSufficient _ANSI_ARGS_((MpegFrame *curr, LumBlock currBlock, MpegFrame *prev, MpegFrame *next, int by, int bx, int mode, int fmy, int fmx, int bmy, int bmx));static void ComputeBMotionBlock _ANSI_ARGS_((MpegFrame *prev, MpegFrame *next, int by, int bx, int mode, int fmy, int fmx, int bmy, int bmx, Block motionBlock, int type));static void ComputeBDiffDCTs _ANSI_ARGS_((MpegFrame *current, MpegFrame *prev, MpegFrame *next, int by, int bx, int mode, int fmy, int fmx, int bmy, int bmx, int *pattern));static boolean DoBIntraCode _ANSI_ARGS_((MpegFrame *current, MpegFrame *prev, MpegFrame *next, int by, int bx, int mode, int fmy, int fmx, int bmy, int bmx));static int ComputeBlockColorDiff _ANSI_ARGS_((Block current, Block motionBlock));/*=====================* * EXPORTED PROCEDURES * *=====================*//*===========================================================================* * * GenBFrame * * generate a B-frame from previous and next frames, adding the result * to the given bit bucket * * RETURNS: frame appended to bb * * SIDE EFFECTS: none * *===========================================================================*/voidGenBFrame(BitBucket * const bb, MpegFrame * const curr, MpegFrame * const prev, MpegFrame * const next) { extern int **bfmvHistogram; extern int **bbmvHistogram; FlatBlock fba[6], fb[6]; Block dec[6]; int32 y_dc_pred, cr_dc_pred, cb_dc_pred; int x, y; int fMotionX = 0, fMotionY = 0; int bMotionX = 0, bMotionY = 0; int oldFMotionX = 0, oldFMotionY = 0; int oldBMotionX = 0, oldBMotionY = 0; int oldMode = MOTION_FORWARD; int mode = MOTION_FORWARD; int offsetX, offsetY; int tempX, tempY; int fMotionXrem = 0, fMotionXquot = 0; int fMotionYrem = 0, fMotionYquot = 0; int bMotionXrem = 0, bMotionXquot = 0; int bMotionYrem = 0, bMotionYquot = 0; int pattern; int numIBlocks = 0, numBBlocks = 0; int numSkipped = 0, totalBits; int numIBits = 0, numBBits = 0; boolean lastIntra = TRUE; boolean motionForward, motionBackward; int totalFrameBits; int32 startTime, endTime; int lastX, lastY; int lastBlockX, lastBlockY; int ix, iy; LumBlock currentBlock; int fy, fx; boolean make_skip_block; int mbAddrInc = 1; int mbAddress; int slicePos; float snr[3], psnr[3]; int idx; int QScale; BlockMV *info; int bitstreamMode, newQScale; int rc_blockStart=0; boolean overflowChange=FALSE; int overflowValue = 0; assert(prev != NULL); assert(next != NULL); if (collect_quant) {fprintf(collect_quant_fp, "# B\n");} if (dct == NULL) AllocDctBlocks(); numFrames++; totalFrameBits = bb->cumulativeBits; startTime = time_elapsed(); /* Rate Control */ bitstreamMode = getRateMode(); if (bitstreamMode == FIXED_RATE) { targetRateControl(curr); } QScale = GetBQScale(); Mhead_GenPictureHeader(bb, B_FRAME, curr->id, fCodeB); /* Check for Qscale change */ if (specificsOn) { newQScale = SpecLookup(curr->id, 0, 0 /* junk */, &info, QScale); if (newQScale != -1) { QScale = newQScale; } /* check for slice */ newQScale = SpecLookup(curr->id, 1, 1, &info, QScale); if (newQScale != -1) { QScale = newQScale; } } Mhead_GenSliceHeader(bb, 1, QScale, NULL, 0); Frame_AllocBlocks(curr); BlockifyFrame(curr); if ( printSNR ) { Frame_AllocDecoded(curr, FALSE); } /* for I-blocks */ y_dc_pred = cr_dc_pred = cb_dc_pred = 128; totalBits = bb->cumulativeBits; if ( ! pixelFullSearch ) { if ( ! prev->halfComputed ) { ComputeHalfPixelData(prev); } if ( ! next->halfComputed ) { ComputeHalfPixelData(next); } } lastBlockX = Fsize_x>>3; lastBlockY = Fsize_y>>3; lastX = lastBlockX-2; lastY = lastBlockY-2; mbAddress = 0; /* find motion vectors and do dcts */ /* In this first loop, all MVs are in half-pixel scope, (if FULL is set then they will be multiples of 2). This is not true in the second loop. */ for (y = 0; y < lastBlockY; y += 2) { for (x = 0; x < lastBlockX; x += 2) { slicePos = (mbAddress % blocksPerSlice); /* compute currentBlock */ BLOCK_TO_FRAME_COORD(y, x, fy, fx); for ( iy = 0; iy < 16; iy++ ) { for ( ix = 0; ix < 16; ix++ ) { currentBlock[iy][ix] = (int16)curr->orig_y[fy+iy][fx+ix]; } } if (slicePos == 0) { oldFMotionX = 0; oldFMotionY = 0; oldBMotionX = 0; oldBMotionY = 0; oldMode = MOTION_FORWARD; lastIntra = TRUE; } /* STEP 1: Select Forward, Backward, or Interpolated motion vectors */ /* see if old motion is good enough */ /* but force last block to be non-skipped */ /* can only skip if: * 1) not the last block in frame * 2) not the last block in slice * 3) not the first block in slice * 4) previous block was not intra-coded */ if ( ((y < lastY) || (x < lastX)) && (slicePos+1 != blocksPerSlice) && (slicePos != 0) && (! lastIntra) && (BSkipBlocks) ) { make_skip_block = MotionSufficient(curr, currentBlock, prev, next, y, x, oldMode, oldFMotionY, oldFMotionX, oldBMotionY, oldBMotionX); } else { make_skip_block = FALSE; } if ( make_skip_block ) { skip_it: /* skipped macro block */ dct_data[y][x].useMotion = SKIP; } else { if (specificsOn) { (void) SpecLookup(curr->id, 2, mbAddress, &info, QScale); if (info == (BlockMV*)NULL) goto gosearch; else { switch (info->typ) { case TYP_SKIP: goto skip_it; case TYP_FORW: fMotionX = info->fx; fMotionY = info->fy; mode = MOTION_FORWARD; break; case TYP_BACK: bMotionX = info->bx; bMotionY = info->by; mode = MOTION_BACKWARD; break; case TYP_BOTH: fMotionX = info->fx; fMotionY = info->fy; bMotionX = info->bx; bMotionY = info->by; mode = MOTION_INTERPOLATE; break; default: pm_error("Unreachable code in GenBFrame!"); goto gosearch; } goto skipsearch; }} gosearch: /* do bsearch */ mode = BMotionSearch(currentBlock, prev, next, y, x, &fMotionY, &fMotionX, &bMotionY, &bMotionX, mode); skipsearch: /* STEP 2: INTRA OR NON-INTRA CODING */ if ( IntraPBAllowed && DoBIntraCode(curr, prev, next, y, x, mode, fMotionY, fMotionX, bMotionY, bMotionX) ) { /* output I-block inside a B-frame */ numIBlocks++; oldFMotionX = 0; oldFMotionY = 0; oldBMotionX = 0; oldBMotionY = 0; lastIntra = TRUE; dct_data[y][x].useMotion = NO_MOTION; oldMode = MOTION_FORWARD; /* calculate forward dct's */ if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "l\n"); mp_fwd_dct_block2(curr->y_blocks[y][x], dct[y][x]); mp_fwd_dct_block2(curr->y_blocks[y][x+1], dct[y][x+1]); mp_fwd_dct_block2(curr->y_blocks[y+1][x], dct[y+1][x]); mp_fwd_dct_block2(curr->y_blocks[y+1][x+1], dct[y+1][x+1]); if (collect_quant && (collect_quant_detailed & 1)) { fprintf(collect_quant_fp, "c\n"); } mp_fwd_dct_block2(curr->cb_blocks[y>>1][x>>1], dctb[y>>1][x>>1]); mp_fwd_dct_block2(curr->cr_blocks[y>>1][x>>1], dctr[y>>1][x>>1]); } else { /* dct P/Bi/B block */ pattern = 63; lastIntra = FALSE; numBBlocks++; dct_data[y][x].mode = mode; oldMode = mode; dct_data[y][x].fmotionX = fMotionX; dct_data[y][x].fmotionY = fMotionY; dct_data[y][x].bmotionX = bMotionX; dct_data[y][x].bmotionY = bMotionY; switch (mode) { case MOTION_FORWARD: numBFOBlocks++; oldFMotionX = fMotionX; oldFMotionY = fMotionY; break; case MOTION_BACKWARD: numBBABlocks++; oldBMotionX = bMotionX; oldBMotionY = bMotionY; break; case MOTION_INTERPOLATE: numBINBlocks++; oldFMotionX = fMotionX; oldFMotionY = fMotionY; oldBMotionX = bMotionX; oldBMotionY = bMotionY; break; default: pm_error("INTERNAL ERROR: Illegal mode: %d", mode); } ComputeBDiffDCTs(curr, prev, next, y, x, mode, fMotionY, fMotionX, bMotionY, bMotionX, &pattern); dct_data[y][x].pattern = pattern; dct_data[y][x].useMotion = MOTION; if ( computeMVHist ) { assert(fMotionX+searchRangeB+1 >= 0); assert(fMotionY+searchRangeB+1 >= 0); assert(fMotionX+searchRangeB+1 <= 2*searchRangeB+2); assert(fMotionY+searchRangeB+1 <= 2*searchRangeB+2); assert(bMotionX+searchRangeB+1 >= 0); assert(bMotionY+searchRangeB+1 >= 0); assert(bMotionX+searchRangeB+1 <= 2*searchRangeB+2); assert(bMotionY+searchRangeB+1 <= 2*searchRangeB+2); bfmvHistogram[fMotionX+searchRangeB+1][fMotionY+searchRangeB+1]++; bbmvHistogram[bMotionX+searchRangeB+1][bMotionY+searchRangeB+1]++; } } /* motion-block */ } /* not skipped */ mbAddress++; } } /* reset everything */ oldFMotionX = 0; oldFMotionY = 0; oldBMotionX = 0; oldBMotionY = 0; oldMode = MOTION_FORWARD; lastIntra = TRUE; y_dc_pred = cr_dc_pred = cb_dc_pred = 128; mbAddress = 0; /* Now generate the frame */ for (y = 0; y < lastBlockY; y += 2) { for (x = 0; x < lastBlockX; x += 2) { slicePos = (mbAddress % blocksPerSlice); if ( (slicePos == 0) && (mbAddress != 0) ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -