00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131 #include "all.h"
00132 #include <sys/param.h>
00133 #include <assert.h>
00134 #include "mtypes.h"
00135 #include "bitio.h"
00136 #include "frames.h"
00137 #include "prototypes.h"
00138 #include "fsize.h"
00139 #include "param.h"
00140 #include "mheaders.h"
00141 #include "postdct.h"
00142 #include "rate.h"
00143 #include "opts.h"
00144
00145
00146
00147
00148
00149 static int numBIBlocks = 0;
00150 static int numBBBlocks = 0;
00151 static int numBSkipped = 0;
00152 static int numBIBits = 0;
00153 static int numBBBits = 0;
00154 static int numFrames = 0;
00155 static int numFrameBits = 0;
00156 static int32 totalTime = 0;
00157 static int qscaleB;
00158 static float totalSNR = 0.0;
00159 static float totalPSNR = 0.0;
00160
00161 static int numBFOBlocks = 0;
00162 static int numBBABlocks = 0;
00163 static int numBINBlocks = 0;
00164 static int numBFOBits = 0;
00165 static int numBBABits = 0;
00166 static int numBINBits = 0;
00167
00168
00169
00170
00171
00172 extern Block **dct, **dctr, **dctb;
00173 extern dct_data_type **dct_data;
00174 #define NO_MOTION 0
00175 #define MOTION 1
00176 #define SKIP 2
00177
00178
00179
00180
00181
00182 static boolean MotionSufficient _ANSI_ARGS_((MpegFrame *curr, LumBlock currBlock, MpegFrame *prev, MpegFrame *next,
00183 int by, int bx, int mode, int fmy, int fmx,
00184 int bmy, int bmx));
00185 static void ComputeBMotionBlock _ANSI_ARGS_((MpegFrame *prev, MpegFrame *next,
00186 int by, int bx, int mode, int fmy, int fmx,
00187 int bmy, int bmx, Block motionBlock, int type));
00188 static void ComputeBDiffDCTs _ANSI_ARGS_((MpegFrame *current, MpegFrame *prev, MpegFrame *next,
00189 int by, int bx, int mode, int fmy, int fmx,
00190 int bmy, int bmx, int *pattern));
00191 static boolean DoBIntraCode _ANSI_ARGS_((MpegFrame *current, MpegFrame *prev, MpegFrame *next,
00192 int by, int bx, int mode, int fmy, int fmx, int bmy,
00193 int bmx));
00194
00195 static int ComputeBlockColorDiff _ANSI_ARGS_((Block current, Block motionBlock));
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 void
00214 GenBFrame(bb, curr, prev, next)
00215 BitBucket *bb;
00216 MpegFrame *curr;
00217 MpegFrame *prev;
00218 MpegFrame *next;
00219 {
00220 extern int **bfmvHistogram;
00221 extern int **bbmvHistogram;
00222 FlatBlock fba[6], fb[6];
00223 Block dec[6];
00224 int32 y_dc_pred, cr_dc_pred, cb_dc_pred;
00225 int x, y;
00226 int fMotionX = 0, fMotionY = 0;
00227 int bMotionX = 0, bMotionY = 0;
00228 int oldFMotionX = 0, oldFMotionY = 0;
00229 int oldBMotionX = 0, oldBMotionY = 0;
00230 int oldMode = MOTION_FORWARD;
00231 int mode = MOTION_FORWARD;
00232 int offsetX, offsetY;
00233 int tempX, tempY;
00234 int fMotionXrem = 0, fMotionXquot = 0;
00235 int fMotionYrem = 0, fMotionYquot = 0;
00236 int bMotionXrem = 0, bMotionXquot = 0;
00237 int bMotionYrem = 0, bMotionYquot = 0;
00238 int pattern;
00239 int numIBlocks = 0, numBBlocks = 0;
00240 int numSkipped = 0, totalBits;
00241 int numIBits = 0, numBBits = 0;
00242 boolean lastIntra = TRUE;
00243 boolean motionForward, motionBackward;
00244 int totalFrameBits;
00245 int32 startTime, endTime;
00246 int lastX, lastY;
00247 int lastBlockX, lastBlockY;
00248 register int ix, iy;
00249 LumBlock currentBlock;
00250 int fy, fx;
00251 boolean make_skip_block;
00252 int mbAddrInc = 1;
00253 int mbAddress;
00254 int slicePos;
00255 float snr[3], psnr[3];
00256 int idx;
00257 int QScale;
00258 BlockMV *info;
00259 int bitstreamMode, newQScale;
00260 int rc_blockStart=0;
00261 boolean overflowChange=FALSE;
00262 int overflowValue = 0;
00263
00264 if (collect_quant) {fprintf(collect_quant_fp, "# B\n");}
00265 if (dct == NULL) AllocDctBlocks();
00266 numFrames++;
00267 totalFrameBits = bb->cumulativeBits;
00268 startTime = time_elapsed();
00269
00270
00271 bitstreamMode = getRateMode();
00272 if (bitstreamMode == FIXED_RATE) {
00273 targetRateControl(curr);
00274 }
00275
00276 QScale = GetBQScale();
00277 Mhead_GenPictureHeader(bb, B_FRAME, curr->id, fCodeB);
00278
00279 if (specificsOn) {
00280 newQScale = SpecLookup(curr->id, 0, 0 , &info, QScale);
00281 if (newQScale != -1) {
00282 QScale = newQScale;
00283 }
00284
00285 newQScale = SpecLookup(curr->id, 1, 1, &info, QScale);
00286 if (newQScale != -1) {
00287 QScale = newQScale;
00288 }
00289 }
00290
00291 Mhead_GenSliceHeader(bb, 1, QScale, NULL, 0);
00292
00293 Frame_AllocBlocks(curr);
00294 BlockifyFrame(curr);
00295
00296 if ( printSNR ) {
00297 Frame_AllocDecoded(curr, FALSE);
00298 }
00299
00300
00301 y_dc_pred = cr_dc_pred = cb_dc_pred = 128;
00302
00303 totalBits = bb->cumulativeBits;
00304
00305 if ( ! pixelFullSearch ) {
00306 if ( ! prev->halfComputed && (prev != NULL)) {
00307 ComputeHalfPixelData(prev);
00308 }
00309
00310 if ( ! next->halfComputed ) {
00311 ComputeHalfPixelData(next);
00312 }
00313 }
00314
00315 lastBlockX = Fsize_x>>3;
00316 lastBlockY = Fsize_y>>3;
00317 lastX = lastBlockX-2;
00318 lastY = lastBlockY-2;
00319 mbAddress = 0;
00320
00321
00322
00323
00324 for (y = 0; y < lastBlockY; y += 2) {
00325 for (x = 0; x < lastBlockX; x += 2) {
00326 slicePos = (mbAddress % blocksPerSlice);
00327
00328
00329 BLOCK_TO_FRAME_COORD(y, x, fy, fx);
00330 for ( iy = 0; iy < 16; iy++ ) {
00331 for ( ix = 0; ix < 16; ix++ ) {
00332 currentBlock[iy][ix] = (int16)curr->orig_y[fy+iy][fx+ix];
00333 }
00334 }
00335
00336 if (slicePos == 0) {
00337 oldFMotionX = 0; oldFMotionY = 0;
00338 oldBMotionX = 0; oldBMotionY = 0;
00339 oldMode = MOTION_FORWARD;
00340 lastIntra = TRUE;
00341 }
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 if ( ((y < lastY) || (x < lastX)) &&
00353 (slicePos+1 != blocksPerSlice) &&
00354 (slicePos != 0) &&
00355 (! lastIntra) &&
00356 (BSkipBlocks) ) {
00357 make_skip_block = MotionSufficient(curr, currentBlock, prev, next, y, x, oldMode,
00358 oldFMotionY, oldFMotionX,
00359 oldBMotionY, oldBMotionX);
00360 } else {
00361 make_skip_block = FALSE;
00362 }
00363
00364 if ( make_skip_block ) {
00365 skip_it:
00366
00367 dct_data[y][x].useMotion = SKIP;
00368 } else {
00369 if (specificsOn) {
00370 (void) SpecLookup(curr->id, 2, mbAddress, &info, QScale);
00371 if (info == (BlockMV*)NULL) goto gosearch;
00372 else {
00373 switch (info->typ) {
00374 case TYP_SKIP:
00375 goto skip_it;
00376 case TYP_FORW:
00377 fMotionX = info->fx;
00378 fMotionY = info->fy;
00379 mode = MOTION_FORWARD;
00380 break;
00381 case TYP_BACK:
00382 bMotionX = info->bx;
00383 bMotionY = info->by;
00384 mode = MOTION_BACKWARD;
00385 break;
00386 case TYP_BOTH:
00387 fMotionX = info->fx;
00388 fMotionY = info->fy;
00389 bMotionX = info->bx;
00390 bMotionY = info->by;
00391 mode = MOTION_INTERPOLATE;
00392 break;
00393 default:
00394 fprintf(stderr,"Unreachable code in GenBFrame!\n");
00395 goto gosearch;
00396 }
00397 goto skipsearch;
00398 }}
00399 gosearch:
00400 mode = BMotionSearch(currentBlock, prev, next, y, x, &fMotionY,
00401 &fMotionX, &bMotionY, &bMotionX, mode);
00402 skipsearch:
00403
00404
00405 if ( IntraPBAllowed && DoBIntraCode(curr, prev, next, y, x, mode, fMotionY,
00406 fMotionX, bMotionY, bMotionX) ) {
00407
00408 numIBlocks++;
00409 oldFMotionX = 0; oldFMotionY = 0;
00410 oldBMotionX = 0; oldBMotionY = 0;
00411 lastIntra = TRUE;
00412 dct_data[y][x].useMotion = NO_MOTION;
00413 oldMode = MOTION_FORWARD;
00414
00415 if (collect_quant && (collect_quant_detailed & 1)) fprintf(collect_quant_fp, "l\n");
00416 mp_fwd_dct_block2(curr->y_blocks[y][x], dct[y][x]);
00417 mp_fwd_dct_block2(curr->y_blocks[y][x+1], dct[y][x+1]);
00418 mp_fwd_dct_block2(curr->y_blocks[y+1][x], dct[y+1][x]);
00419 mp_fwd_dct_block2(curr->y_blocks[y+1][x+1], dct[y+1][x+1]);
00420 if (collect_quant && (collect_quant_detailed & 1)) {fprintf(collect_quant_fp, "c\n");}
00421 mp_fwd_dct_block2(curr->cb_blocks[y>>1][x>>1], dctb[y>>1][x>>1]);
00422 mp_fwd_dct_block2(curr->cr_blocks[y>>1][x>>1], dctr[y>>1][x>>1]);
00423
00424 } else {
00425
00426 pattern = 63;
00427 lastIntra = FALSE;
00428 numBBlocks++;
00429 dct_data[y][x].mode = mode;
00430 oldMode = mode;
00431 dct_data[y][x].fmotionX = fMotionX;
00432 dct_data[y][x].fmotionY = fMotionY;
00433 dct_data[y][x].bmotionX = bMotionX;
00434 dct_data[y][x].bmotionY = bMotionY;
00435 switch (mode) {
00436 case MOTION_FORWARD:
00437 numBFOBlocks++;
00438 oldFMotionX = fMotionX; oldFMotionY = fMotionY;
00439 break;
00440 case MOTION_BACKWARD:
00441 numBBABlocks++;
00442 oldBMotionX = bMotionX; oldBMotionY = bMotionY;
00443 break;
00444 case MOTION_INTERPOLATE:
00445 numBINBlocks++;
00446 oldFMotionX = fMotionX; oldFMotionY = fMotionY;
00447 oldBMotionX = bMotionX; oldBMotionY = bMotionY;
00448 break;
00449 default:
00450 fprintf(stderr, "PROGRAMMER ERROR: Illegal mode: %d\n", mode);
00451 exit(1);
00452 }
00453
00454 ComputeBDiffDCTs(curr, prev, next, y, x, mode, fMotionY,
00455 fMotionX, bMotionY, bMotionX, &pattern);
00456
00457 dct_data[y][x].pattern = pattern;
00458 dct_data[y][x].useMotion = MOTION;
00459 if ( computeMVHist ) {
00460 assert(fMotionX+searchRangeB+1 >= 0);
00461 assert(fMotionY+searchRangeB+1 >= 0);
00462 assert(fMotionX+searchRangeB+1 <= 2*searchRangeB+2);
00463 assert(fMotionY+searchRangeB+1 <= 2*searchRangeB+2);
00464 assert(bMotionX+searchRangeB+1 >= 0);
00465 assert(bMotionY+searchRangeB+1 >= 0);
00466 assert(bMotionX+searchRangeB+1 <= 2*searchRangeB+2);
00467 assert(bMotionY+searchRangeB+1 <= 2*searchRangeB+2);
00468
00469 bfmvHistogram[fMotionX+searchRangeB+1][fMotionY+searchRangeB+1]++;
00470 bbmvHistogram[bMotionX+searchRangeB+1][bMotionY+searchRangeB+1]++;
00471 }
00472 }
00473 }
00474 mbAddress++;
00475 }}
00476
00477
00478 oldFMotionX = 0; oldFMotionY = 0;
00479 oldBMotionX = 0; oldBMotionY = 0;
00480 oldMode = MOTION_FORWARD;
00481 lastIntra = TRUE;
00482 y_dc_pred = cr_dc_pred = cb_dc_pred = 128;
00483 mbAddress = 0;
00484
00485
00486 for (y = 0; y < lastBlockY; y += 2) {
00487 for (x = 0; x < lastBlockX; x += 2) {
00488 slicePos = (mbAddress % blocksPerSlice);
00489
00490 if ( (slicePos == 0) && (mbAddress != 0) ) {
00491 if (specificsOn) {
00492
00493 newQScale = SpecLookup(curr->id,1,mbAddress/blocksPerSlice, &info, QScale);
00494 if (newQScale != -1) QScale = newQScale;
00495 }
00496 Mhead_GenSliceEnder(bb);
00497 Mhead_GenSliceHeader(bb, 1+(y>>1), QScale, NULL, 0);
00498
00499
00500 oldFMotionX = 0; oldFMotionY = 0;
00501 oldBMotionX = 0; oldBMotionY = 0;
00502 oldMode = MOTION_FORWARD;
00503 lastIntra = TRUE;
00504 y_dc_pred = cr_dc_pred = cb_dc_pred = 128;
00505
00506 mbAddrInc = 1+(x>>1);
00507 }
00508
00509
00510 if (bitstreamMode == FIXED_RATE) {
00511 rc_blockStart = bb->cumulativeBits;
00512 newQScale = needQScaleChange(QScale,
00513 curr->y_blocks[y][x],
00514 curr->y_blocks[y][x+1],
00515 curr->y_blocks[y+1][x],
00516 curr->y_blocks[y+1][x+1]);
00517 if (newQScale > 0) {
00518 QScale = newQScale;
00519 }
00520 }
00521
00522 if (specificsOn) {
00523 newQScale = SpecLookup(curr->id, 2, mbAddress, &info, QScale);
00524 if (newQScale != -1) {
00525 QScale = newQScale;
00526 }}
00527
00528 if (dct_data[y][x].useMotion == NO_MOTION) {
00529
00530 GEN_I_BLOCK(B_FRAME, curr, bb, mbAddrInc, QScale);
00531 mbAddrInc = 1;
00532 numIBits += (bb->cumulativeBits-totalBits);
00533 totalBits = bb->cumulativeBits;
00534
00535
00536 oldFMotionX = 0; oldFMotionY = 0;
00537 oldBMotionX = 0; oldBMotionY = 0;
00538 oldMode = MOTION_FORWARD;
00539 lastIntra = TRUE;
00540
00541 if ( printSNR ) {
00542
00543
00544 for ( idx = 0; idx < 6; idx++ ) {
00545 Mpost_UnQuantZigBlock(fb[idx], dec[idx], QScale, TRUE);
00546 mpeg_jrevdct((int16 *)dec[idx]);
00547 }
00548
00549
00550 BlockToData(curr->decoded_y, dec[0], y, x);
00551 BlockToData(curr->decoded_y, dec[1], y, x+1);
00552 BlockToData(curr->decoded_y, dec[2], y+1, x);
00553 BlockToData(curr->decoded_y, dec[3], y+1, x+1);
00554 BlockToData(curr->decoded_cb, dec[4], y>>1, x>>1);
00555 BlockToData(curr->decoded_cr, dec[5], y>>1, x>>1);
00556 }
00557 } else if (dct_data[y][x].useMotion == SKIP) {
00558 skip_block:
00559 numSkipped++;
00560 mbAddrInc++;
00561
00562
00563 if ( printSNR ) {
00564 int fmy, fmx, bmy, bmx;
00565
00566 for ( idx = 0; idx < 6; idx++ ) {
00567 memset((char *)dec[idx], 0, sizeof(Block));
00568 }
00569
00570 if ( pixelFullSearch ) {
00571 fmy = 2*oldFMotionY;
00572 fmx = 2*oldFMotionX;
00573 bmy = 2*oldBMotionY;
00574 bmx = 2*oldBMotionX;
00575 } else {
00576 fmy = oldFMotionY;
00577 fmx = oldFMotionX;
00578 bmy = oldBMotionY;
00579 bmx = oldBMotionX;
00580 }
00581
00582
00583 AddBMotionBlock(dec[0], prev->decoded_y,
00584 next->decoded_y, y, x, mode,
00585 fmy, fmx, bmy, bmx);
00586 AddBMotionBlock(dec[1], prev->decoded_y,
00587 next->decoded_y, y, x+1, mode,
00588 fmy, fmx, bmy, bmx);
00589 AddBMotionBlock(dec[2], prev->decoded_y,
00590 next->decoded_y, y+1, x, mode,
00591 fmy, fmx, bmy, bmx);
00592 AddBMotionBlock(dec[3], prev->decoded_y,
00593 next->decoded_y, y+1, x+1, mode,
00594 fmy, fmx, bmy, bmx);
00595 AddBMotionBlock(dec[4], prev->decoded_cb,
00596 next->decoded_cb, y>>1, x>>1, mode,
00597 fmy/2, fmx/2,
00598 bmy/2, bmx/2);
00599 AddBMotionBlock(dec[5], prev->decoded_cr,
00600 next->decoded_cr, y>>1, x>>1, mode,
00601 fmy/2, fmx/2,
00602 bmy/2, bmx/2);
00603
00604
00605 BlockToData(curr->decoded_y, dec[0], y, x);
00606 BlockToData(curr->decoded_y, dec[1], y, x+1);
00607 BlockToData(curr->decoded_y, dec[2], y+1, x);
00608 BlockToData(curr->decoded_y, dec[3], y+1, x+1);
00609 BlockToData(curr->decoded_cb, dec[4], y>>1, x>>1);
00610 BlockToData(curr->decoded_cr, dec[5], y>>1, x>>1);
00611 }
00612 } else {
00613 int fCode = fCodeB;
00614
00615 pattern = dct_data[y][x].pattern;
00616 fMotionX = dct_data[y][x].fmotionX;
00617 fMotionY = dct_data[y][x].fmotionY;
00618 bMotionX = dct_data[y][x].bmotionX;
00619 bMotionY = dct_data[y][x].bmotionY;
00620
00621 if ( pixelFullSearch ) {
00622 fMotionX /= 2; fMotionY /= 2;
00623 bMotionX /= 2; bMotionY /= 2;
00624 }
00625
00626
00627 calc_blocks:
00628
00629
00630 DoQuant(0x20, dct[y][x], fba[0]);
00631 DoQuant(0x10, dct[y][x+1], fba[1]);
00632 DoQuant(0x08, dct[y+1][x], fba[2]);
00633 DoQuant(0x04, dct[y+1][x+1], fba[3]);
00634 DoQuant(0x02, dctb[y>>1][x>>1], fba[4]);
00635 DoQuant(0x01, dctr[y>>1][x>>1], fba[5]);
00636
00637 motionForward = (dct_data[y][x].mode != MOTION_BACKWARD);
00638 motionBackward = (dct_data[y][x].mode != MOTION_FORWARD);
00639
00640 #ifdef BUGGY_CODE
00641
00642
00643
00644
00645
00646
00647
00648 if ((pattern == 0) &&
00649 ((y < lastY) || (x < lastX)) &&
00650 (slicePos+1 != blocksPerSlice) &&
00651 (slicePos != 0) &&
00652 (!lastIntra) &&
00653 ( (!motionForward) ||
00654 (motionForward &&
00655 fMotionX == oldFMotionX && fMotionY == oldFMotionY)) &&
00656 ( (!motionBackward) ||
00657 (motionBackward &&
00658 bMotionX == oldBMotionX && bMotionY == oldBMotionY))
00659 ) {
00660
00661 goto skip_block;
00662 }
00663 #endif
00664
00665 if ( motionForward ) {
00666
00667 offsetX = fMotionX - oldFMotionX;
00668 offsetY = fMotionY - oldFMotionY;
00669
00670 ENCODE_MOTION_VECTOR(offsetX, offsetY, fMotionXquot,
00671 fMotionYquot, fMotionXrem, fMotionYrem,
00672 FORW_F);
00673 oldFMotionX = fMotionX; oldFMotionY = fMotionY;
00674 }
00675
00676 if ( motionBackward ) {
00677
00678 offsetX = bMotionX - oldBMotionX;
00679 offsetY = bMotionY - oldBMotionY;
00680 ENCODE_MOTION_VECTOR(offsetX, offsetY, bMotionXquot,
00681 bMotionYquot, bMotionXrem, bMotionYrem,
00682 BACK_F);
00683 oldBMotionX = bMotionX; oldBMotionY = bMotionY;
00684 }
00685
00686 oldMode = dct_data[y][x].mode;
00687
00688 if ( printSNR ) {
00689 if ( pixelFullSearch ) {
00690 fMotionX *= 2; fMotionY *= 2;
00691 bMotionX *= 2; bMotionY *= 2;
00692 }
00693 for ( idx = 0; idx < 6; idx++ ) {
00694 if ( pattern & (1 << (5-idx)) ) {
00695 Mpost_UnQuantZigBlock(fba[idx], dec[idx], QScale, FALSE);
00696 mpeg_jrevdct((int16 *)dec[idx]);
00697 } else {
00698 memset((char *)dec[idx], 0, sizeof(Block));
00699 }
00700 }
00701
00702
00703 AddBMotionBlock(dec[0], prev->decoded_y,
00704 next->decoded_y, y, x, mode,
00705 fMotionY, fMotionX, bMotionY, bMotionX);
00706 AddBMotionBlock(dec[1], prev->decoded_y,
00707 next->decoded_y, y, x+1, mode,
00708 fMotionY, fMotionX, bMotionY, bMotionX);
00709 AddBMotionBlock(dec[2], prev->decoded_y,
00710 next->decoded_y, y+1, x, mode,
00711 fMotionY, fMotionX, bMotionY, bMotionX);
00712 AddBMotionBlock(dec[3], prev->decoded_y,
00713 next->decoded_y, y+1, x+1, mode,
00714 fMotionY, fMotionX, bMotionY, bMotionX);
00715 AddBMotionBlock(dec[4], prev->decoded_cb,
00716 next->decoded_cb, y>>1, x>>1, mode,
00717 fMotionY/2, fMotionX/2,
00718 bMotionY/2, bMotionX/2);
00719 AddBMotionBlock(dec[5], prev->decoded_cr,
00720 next->decoded_cr, y>>1, x>>1, mode,
00721 fMotionY/2, fMotionX/2,
00722 bMotionY/2, bMotionX/2);
00723
00724
00725 BlockToData(curr->decoded_y, dec[0], y, x);
00726 BlockToData(curr->decoded_y, dec[1], y, x+1);
00727 BlockToData(curr->decoded_y, dec[2], y+1, x);
00728 BlockToData(curr->decoded_y, dec[3], y+1, x+1);
00729 BlockToData(curr->decoded_cb, dec[4], y>>1, x>>1);
00730 BlockToData(curr->decoded_cr, dec[5], y>>1, x>>1);
00731 }
00732
00733
00734 y_dc_pred = cr_dc_pred = cb_dc_pred = 128;
00735 lastIntra = FALSE;
00736 mode = dct_data[y][x].mode;
00737
00738
00739 Mhead_GenMBHeader(bb, 3 , mbAddrInc ,
00740 QScale ,
00741 fCodeB , fCodeB ,
00742 fMotionXrem , fMotionYrem ,
00743 bMotionXrem , bMotionYrem ,
00744 motionForward , fMotionXquot ,
00745 fMotionYquot , motionBackward ,
00746 bMotionXquot , bMotionYquot ,
00747 pattern , FALSE );
00748 mbAddrInc = 1;
00749
00750
00751 for ( tempX = 0; tempX < 6; tempX++ ) {
00752 if ( GET_ITH_BIT(pattern, 5-tempX) ) {
00753 Mpost_RLEHuffPBlock(fba[tempX], bb);
00754 }
00755 }
00756
00757
00758 switch (mode) {
00759 case MOTION_FORWARD:
00760 numBFOBits += (bb->cumulativeBits-totalBits);
00761 break;
00762 case MOTION_BACKWARD:
00763 numBBABits += (bb->cumulativeBits-totalBits);
00764 break;
00765 case MOTION_INTERPOLATE:
00766 numBINBits += (bb->cumulativeBits-totalBits);
00767 break;
00768 default:
00769 fprintf(stderr, "PROGRAMMER ERROR: Illegal mode: %d\n",
00770 mode);
00771 exit(1);
00772 }
00773
00774 numBBits += (bb->cumulativeBits-totalBits);
00775 totalBits = bb->cumulativeBits;
00776
00777 if (overflowChange) {
00778
00779 overflowChange = FALSE;
00780 QScale -= overflowValue;
00781 overflowValue = 0;
00782 }
00783 }
00784
00785 mbAddress++;
00786
00787 if (bitstreamMode == FIXED_RATE) {
00788 incMacroBlockBits( bb->cumulativeBits - rc_blockStart);
00789 rc_blockStart = bb->cumulativeBits;
00790 MB_RateOut(TYPE_BFRAME);
00791 }
00792
00793 }
00794 }
00795
00796 if ( printSNR ) {
00797 BlockComputeSNR(curr,snr,psnr);
00798 totalSNR += snr[0];
00799 totalPSNR += psnr[0];
00800 }
00801
00802 Mhead_GenSliceEnder(bb);
00803
00804 if (bitstreamMode == FIXED_RATE) {
00805 updateRateControl(TYPE_BFRAME);
00806 }
00807
00808 endTime = time_elapsed();
00809 totalTime += (endTime-startTime);
00810
00811 if ( ( ! childProcess) && showBitRatePerFrame ) {
00812
00813 fprintf(bitRateFile, "%5d\t%8d\n", curr->id,
00814 30*(bb->cumulativeBits-totalFrameBits));
00815 }
00816
00817 if ( (! childProcess) && frameSummary && !realQuiet) {
00818 fprintf(stdout, "FRAME %d (B): I BLOCKS: %d; B BLOCKS: %d SKIPPED: %d (%ld seconds)\n",
00819 curr->id, numIBlocks, numBBlocks, numSkipped, (long)((endTime-startTime)/TIME_RATE));
00820 if ( printSNR )
00821 fprintf(stdout, "FRAME %d: SNR: %.1f\t%.1f\t%.1f\tPSNR: %.1f\t%.1f\t%.1f\n",
00822 curr->id, snr[0], snr[1], snr[2],
00823 psnr[0], psnr[1], psnr[2]);
00824 }
00825
00826 numFrameBits += (bb->cumulativeBits-totalFrameBits);
00827 numBIBlocks += numIBlocks;
00828 numBBBlocks += numBBlocks;
00829 numBSkipped += numSkipped;
00830 numBIBits += numIBits;
00831 numBBBits += numBBits;
00832 }
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 void
00847 SetBQScale(qB)
00848 int qB;
00849 {
00850 qscaleB = qB;
00851 }
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 int
00866 GetBQScale()
00867 {
00868 return qscaleB;
00869 }
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883 void
00884 ResetBFrameStats()
00885 {
00886 numBIBlocks = 0;
00887 numBBBlocks = 0;
00888 numBSkipped = 0;
00889 numBIBits = 0;
00890 numBBBits = 0;
00891 numFrames = 0;
00892 numFrameBits = 0;
00893 totalTime = 0;
00894 }
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908 float
00909 ShowBFrameSummary(inputFrameBits, totalBits, fpointer)
00910 int inputFrameBits;
00911 int32 totalBits;
00912 FILE *fpointer;
00913 {
00914 if ( numFrames == 0 ) {
00915 return 0.0;
00916 }
00917
00918 fprintf(fpointer, "-------------------------\n");
00919 fprintf(fpointer, "*****B FRAME SUMMARY*****\n");
00920 fprintf(fpointer, "-------------------------\n");
00921
00922 if ( numBIBlocks != 0 ) {
00923 fprintf(fpointer, " I Blocks: %5d (%6d bits) (%5d bpb)\n",
00924 numBIBlocks, numBIBits, numBIBits/numBIBlocks);
00925 } else {
00926 fprintf(fpointer, " I Blocks: %5d\n", 0);
00927 }
00928
00929 if ( numBBBlocks != 0 ) {
00930 fprintf(fpointer, " B Blocks: %5d (%6d bits) (%5d bpb)\n",
00931 numBBBlocks, numBBBits, numBBBits/numBBBlocks);
00932 fprintf(fpointer, " B types: %5d (%4d bpb) forw %5d (%4d bpb) back %5d (%4d bpb) bi\n",
00933 numBFOBlocks, (numBFOBlocks==0)?0:numBFOBits/numBFOBlocks,
00934 numBBABlocks, (numBBABlocks==0)?0:numBBABits/numBBABlocks,
00935 numBINBlocks, (numBINBlocks==0)?0:numBINBits/numBINBlocks);
00936 } else {
00937 fprintf(fpointer, " B Blocks: %5d\n", 0);
00938 }
00939
00940 fprintf(fpointer, " Skipped: %5d\n", numBSkipped);
00941
00942 fprintf(fpointer, " Frames: %5d (%6d bits) (%5d bpf) (%2.1f%% of total)\n",
00943 numFrames, numFrameBits, numFrameBits/numFrames,
00944 100.0*(float)numFrameBits/(float)totalBits);
00945 fprintf(fpointer, " Compression: %3d:1 (%9.4f bpp)\n",
00946 numFrames*inputFrameBits/numFrameBits,
00947 24.0*(float)numFrameBits/(float)(numFrames*inputFrameBits));
00948 if ( printSNR )
00949 fprintf(fpointer, " Avg Y SNR/PSNR: %.1f %.1f\n",
00950 totalSNR/(float)numFrames, totalPSNR/(float)numFrames);
00951 if ( totalTime == 0 ) {
00952 fprintf(fpointer, " Seconds: NONE\n");
00953 } else {
00954 fprintf(fpointer, " Seconds: %9ld (%9.4f fps) (%9ld pps) (%9ld mps)\n",
00955 (long)(totalTime/TIME_RATE),
00956 (float)((float)(TIME_RATE*numFrames)/(float)totalTime),
00957 (long)((float)TIME_RATE*(float)numFrames*(float)inputFrameBits/(24.0*(float)totalTime)),
00958 (long)((float)TIME_RATE*(float)numFrames*(float)inputFrameBits/(256.0*24.0*(float)totalTime)));
00959 }
00960
00961 return (float)totalTime/TIME_RATE;
00962 }
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 void
00979 ComputeBMotionLumBlock(prev, next, by, bx, mode, fmy, fmx, bmy, bmx, motionBlock)
00980 MpegFrame *prev;
00981 MpegFrame *next;
00982 int by;
00983 int bx;
00984 int mode;
00985 int fmy;
00986 int fmx;
00987 int bmy;
00988 int bmx;
00989 LumBlock motionBlock;
00990 {
00991 LumBlock prevBlock, nextBlock;
00992 register int y, x;
00993
00994 switch(mode) {
00995 case MOTION_FORWARD:
00996 ComputeMotionLumBlock(prev, by, bx, fmy, fmx, motionBlock);
00997 break;
00998 case MOTION_BACKWARD:
00999 ComputeMotionLumBlock(next, by, bx, bmy, bmx, motionBlock);
01000 break;
01001 case MOTION_INTERPOLATE:
01002 ComputeMotionLumBlock(prev, by, bx, fmy, fmx, prevBlock);
01003 ComputeMotionLumBlock(next, by, bx, bmy, bmx, nextBlock);
01004
01005 for ( y = 0; y < 16; y++ ) {
01006 for ( x = 0; x < 16; x++ ) {
01007 motionBlock[y][x] = (prevBlock[y][x]+nextBlock[y][x]+1)/2;
01008 }
01009 }
01010 break;
01011 default:
01012 fprintf(stderr, "Bad mode!\nProgrammer error!\n");
01013 break;
01014
01015 }
01016 }
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030 float
01031 EstimateSecondsPerBFrame()
01032 {
01033 if ( numFrames == 0 ) {
01034 return 20.0;
01035 } else {
01036 return (float)totalTime/((float)TIME_RATE*(float)numFrames);
01037 }
01038 }
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058 static void
01059 ComputeBMotionBlock(prev, next, by, bx, mode, fmy, fmx, bmy, bmx, motionBlock, type)
01060 MpegFrame *prev;
01061 MpegFrame *next;
01062 int by;
01063 int bx;
01064 int mode;
01065 int fmy;
01066 int fmx;
01067 int bmy;
01068 int bmx;
01069 Block motionBlock;
01070 int type;
01071 {
01072 Block prevBlock, nextBlock;
01073 register int y, x;
01074
01075 switch(mode) {
01076 case MOTION_FORWARD:
01077 if ( type == LUM_BLOCK ) {
01078 ComputeMotionBlock(prev->ref_y, by, bx, fmy, fmx, motionBlock);
01079 } else if ( type == CB_BLOCK ) {
01080 ComputeMotionBlock(prev->ref_cb, by, bx, fmy, fmx, motionBlock);
01081 } else if ( type == CR_BLOCK ) {
01082 ComputeMotionBlock(prev->ref_cr, by, bx, fmy, fmx, motionBlock);
01083 }
01084 break;
01085 case MOTION_BACKWARD:
01086 if ( type == LUM_BLOCK ) {
01087 ComputeMotionBlock(next->ref_y, by, bx, bmy, bmx, motionBlock);
01088 } else if ( type == CB_BLOCK ) {
01089 ComputeMotionBlock(next->ref_cb, by, bx, bmy, bmx, motionBlock);
01090 } else if ( type == CR_BLOCK ) {
01091 ComputeMotionBlock(next->ref_cr, by, bx, bmy, bmx, motionBlock);
01092 }
01093 break;
01094 case MOTION_INTERPOLATE:
01095 if ( type == LUM_BLOCK ) {
01096 ComputeMotionBlock(prev->ref_y, by, bx, fmy, fmx, prevBlock);
01097 ComputeMotionBlock(next->ref_y, by, bx, bmy, bmx, nextBlock);
01098 } else if ( type == CB_BLOCK ) {
01099 ComputeMotionBlock(prev->ref_cb, by, bx, fmy, fmx, prevBlock);
01100 ComputeMotionBlock(next->ref_cb, by, bx, bmy, bmx, nextBlock);
01101 } else if ( type == CR_BLOCK ) {
01102 ComputeMotionBlock(prev->ref_cr, by, bx, fmy, fmx, prevBlock);
01103 ComputeMotionBlock(next->ref_cr, by, bx, bmy, bmx, nextBlock);
01104 }
01105
01106 for ( y = 0; y < 8; y++ ) {
01107 for ( x = 0; x < 8; x++ ) {
01108 motionBlock[y][x] = (prevBlock[y][x]+nextBlock[y][x]+1)/2;
01109 }
01110 }
01111 break;
01112 }
01113 }
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129 static void
01130 ComputeBDiffDCTs(current, prev, next, by, bx, mode, fmy, fmx, bmy, bmx, pattern)
01131 MpegFrame *current;
01132 MpegFrame *prev;
01133 MpegFrame *next;
01134 int by;
01135 int bx;
01136 int mode;
01137 int fmy;
01138 int fmx;
01139 int bmy;
01140 int bmx;
01141 int *pattern;
01142 {
01143 Block motionBlock;
01144
01145 if ( *pattern & 0x20 ) {
01146 ComputeBMotionBlock(prev, next, by, bx, mode, fmy, fmx,
01147 bmy, bmx, motionBlock, LUM_BLOCK);
01148 if (! ComputeDiffDCTBlock(current->y_blocks[by][bx], dct[by][bx], motionBlock)) {
01149 *pattern ^= 0x20;
01150 }
01151 }
01152
01153 if ( *pattern & 0x10 ) {
01154 ComputeBMotionBlock(prev, next, by, bx+1, mode, fmy, fmx,
01155 bmy, bmx, motionBlock, LUM_BLOCK);
01156 if (! ComputeDiffDCTBlock(current->y_blocks[by][bx+1], dct[by][bx+1], motionBlock)) {
01157 *pattern ^= 0x10;
01158 }
01159 }
01160
01161 if ( *pattern & 0x8 ) {
01162 ComputeBMotionBlock(prev, next, by+1, bx, mode, fmy, fmx,
01163 bmy, bmx, motionBlock, LUM_BLOCK);
01164 if (! ComputeDiffDCTBlock(current->y_blocks[by+1][bx], dct[by+1][bx], motionBlock)) {
01165 *pattern ^= 0x8;
01166 }
01167 }
01168
01169 if ( *pattern & 0x4 ) {
01170 ComputeBMotionBlock(prev, next, by+1, bx+1, mode, fmy, fmx,
01171 bmy, bmx, motionBlock, LUM_BLOCK);
01172 if (! ComputeDiffDCTBlock(current->y_blocks[by+1][bx+1], dct[by+1][bx+1], motionBlock)) {
01173 *pattern ^= 0x4;
01174 }
01175 }
01176
01177 if ( *pattern & 0x2 ) {
01178 ComputeBMotionBlock(prev, next, by>>1, bx>>1, mode, fmy/2, fmx/2,
01179 bmy/2, bmx/2, motionBlock, CB_BLOCK);
01180 if (! ComputeDiffDCTBlock(current->cb_blocks[by >> 1][bx >> 1], dctb[by >> 1][bx >> 1], motionBlock)) {
01181 *pattern ^= 0x2;
01182 }
01183 }
01184
01185 if ( *pattern & 0x1 ) {
01186 ComputeBMotionBlock(prev, next, by>>1, bx>>1, mode, fmy/2, fmx/2,
01187 bmy/2, bmx/2, motionBlock, CR_BLOCK);
01188 if (! ComputeDiffDCTBlock(current->cr_blocks[by >> 1][bx >> 1], dctr[by >> 1][bx >> 1], motionBlock)) {
01189 *pattern ^= 0x1;
01190 }
01191 }
01192 }
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210 static boolean
01211 DoBIntraCode(current, prev, next, by, bx, mode, fmy, fmx, bmy, bmx)
01212 MpegFrame *current;
01213 MpegFrame *prev;
01214 MpegFrame *next;
01215 int by;
01216 int bx;
01217 int mode;
01218 int fmy;
01219 int fmx;
01220 int bmy;
01221 int bmx;
01222 {
01223 int x, y;
01224 int32 sum = 0, vard = 0, varc = 0, dif;
01225 int32 currPixel, prevPixel;
01226 LumBlock motionBlock;
01227 int fy, fx;
01228
01229 ComputeBMotionLumBlock(prev, next, by, bx, mode, fmy, fmx,
01230 bmy, bmx, motionBlock);
01231
01232 MOTION_TO_FRAME_COORD(by, bx, 0, 0, fy, fx);
01233
01234 for ( y = 0; y < 16; y++ ) {
01235 for ( x = 0; x < 16; x++ ) {
01236 currPixel = current->orig_y[fy+y][fx+x];
01237 prevPixel = motionBlock[y][x];
01238
01239 sum += currPixel;
01240 varc += currPixel*currPixel;
01241
01242 dif = currPixel - prevPixel;
01243 vard += dif*dif;
01244 }
01245 }
01246
01247 vard >>= 8;
01248 varc = (varc>>8) - (sum>>8)*(sum>>8);
01249
01250 if ( vard <= 64 ) {
01251 return FALSE;
01252 } else if ( vard < varc ) {
01253 return FALSE;
01254 } else {
01255 return TRUE;
01256 }
01257 }
01258
01259 static int
01260 ComputeBlockColorDiff(current, motionBlock)
01261 Block current, motionBlock;
01262 {
01263 register int x, y, diff_total = 0, diff_tmp;
01264
01265 for ( y = 0; y < 8; y++ ) {
01266 for ( x = 0; x < 8; x++ ) {
01267 diff_tmp = current[y][x] - motionBlock[y][x];
01268 diff_total += ABS(diff_tmp);
01269 }
01270 }
01271 return diff_total;
01272 }
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289 static boolean
01290 MotionSufficient(curr, currBlock, prev, next, by, bx, mode, fmy, fmx, bmy, bmx)
01291 MpegFrame *curr;
01292 LumBlock currBlock;
01293 MpegFrame *prev;
01294 MpegFrame *next;
01295 int by, bx;
01296 int mode;
01297 int fmy, fmx;
01298 int bmy, bmx;
01299 {
01300 LumBlock mLumBlock;
01301 Block mColorBlock;
01302 int lumErr, colorErr;
01303
01304
01305 if ( mode != MOTION_BACKWARD ) {
01306 if ( (by*DCTSIZE+(fmy-1)/2 < 0) || ((by+2)*DCTSIZE+(fmy+1)/2-1 >= Fsize_y) ) {
01307 return FALSE;
01308 }
01309 if ( (bx*DCTSIZE+(fmx-1)/2 < 0) || ((bx+2)*DCTSIZE+(fmx+1)/2-1 >= Fsize_x) ) {
01310 return FALSE;
01311 }
01312 }
01313
01314 if ( mode != MOTION_FORWARD ) {
01315 if ( (by*DCTSIZE+(bmy-1)/2 < 0) || ((by+2)*DCTSIZE+(bmy+1)/2-1 >= Fsize_y) ) {
01316 return FALSE;
01317 }
01318 if ( (bx*DCTSIZE+(bmx-1)/2 < 0) || ((bx+2)*DCTSIZE+(bmx+1)/2-1 >= Fsize_x) ) {
01319 return FALSE;
01320 }
01321 }
01322
01323
01324 ComputeBMotionLumBlock(prev, next, by, bx, mode, fmy, fmx,
01325 bmy, bmx, mLumBlock);
01326 lumErr = LumBlockMAD(currBlock, mLumBlock, 0x7fffffff);
01327 if (lumErr > 512) {
01328 return FALSE;
01329 }
01330
01331
01332 ComputeBMotionBlock(prev, next, by>>1, bx>>1, mode, fmy/2, fmx/2,
01333 bmy/2, bmx/2, mColorBlock, CR_BLOCK);
01334 colorErr = ComputeBlockColorDiff(curr->cr_blocks[by >> 1][bx >> 1], mColorBlock);
01335 ComputeBMotionBlock(prev, next, by>>1, bx>>1, mode, fmy/2, fmx/2,
01336 bmy/2, bmx/2, mColorBlock, CB_BLOCK);
01337 colorErr += ComputeBlockColorDiff(curr->cr_blocks[by >> 1][bx >> 1], mColorBlock);
01338
01339 return (colorErr < 256);
01340 }
01341
01342