📄 p_picture.c
字号:
/************************************************************************ * * coder.c, main coding engine of tmn (TMN encoder) * * Copyright (C) 1997 University of BC, Canada * * Contacts: * Michael Gallant <mikeg@ee.ubc.ca> * Guy Cote <guyc@ee.ubc.ca> * Berna Erol <bernae@ee.ubc.ca> * * UBC Image Processing Laboratory http://www.ee.ubc.ca/image * 2356 Main Mall tel.: +1 604 822 4051 * Vancouver BC Canada V6T1Z4 fax.: +1 604 822 5949 * * Copyright (C) 1995, 1996 Telenor R&D, Norway * * Contacts: * Robert Danielsen <Robert.Danielsen@nta.no> * * Telenor Research and Development http://www.nta.no/brukere/DVC/ * P.O.Box 83 tel.: +47 63 84 84 00 * N-2007 Kjeller, Norway fax.: +47 63 81 00 76 * ************************************************************************//* * Disclaimer of Warranty * * These software programs are available to the user without any * license fee or royalty on an "as is" basis. The University of * British Columbia disclaims any and all warranties, whether * express, implied, or statuary, including any implied warranties * or merchantability or of fitness for a particular purpose. In no * event shall the copyright-holder be liable for any incidental, * punitive, or consequential damages of any kind whatsoever arising * from the use of these programs. * * This disclaimer of warranty extends to the user of these programs * and user's customers, employees, agents, transferees, successors, * and assigns. * * The University of British Columbia does not represent or warrant * that the programs furnished hereunder are free of infringement of * any third-party patents. * * Commercial implementations of H.263, including shareware, are * subject to royalty fees to patent holders. Many of these patents * are general enough such that they are unavoidable regardless of * implementation design. **//***************************************************************** * * Modified by Pat Mulroy, BT Labs to run syntax based arithmetic * coding. SAC option, H.263 (Annex E). * *****************************************************************/#include"sim.h"/********************************************************************** * * Name: CodeOneOrTwo * Description: code one image normally or two images * as a PB-frame (CodeTwoPB and CodeOnePred merged) * * Input: pointer to image, prev_image, prev_recon, Q * * Returns: pointer to reconstructed image * Side effects: memory is allocated to recon image * * Date: 950221 Author: <klillevo@mailbox.jf.intel.com> * 970831 modified by mikeg@ee.ubc.ca * 970815 modified by guyc@ee.ubc.ca * ***********************************************************************/void CodeOneOrTwo(PictImage *curr, PictImage *B_image, PictImage *prev, PictImage *pr, int QP, int frameskip, Bits *bits, Pict *pic, PictImage *B_recon, PictImage *recon){ unsigned char *prev_ipol,*prev_ipol_woRTYPE, *pi, *pi_woRTYPE; PictImage *prev_recon=NULL, *pr_edge = NULL; MotionVector *MV[7][MBR+1][MBC+2]; MotionVector *B_f_MV[7][MBR+1][MBC+2]; MotionVector ZERO = {0,0,0,0,0}; MB_Structure *recon_data_P; MB_Structure *recon_data_B=NULL; MB_Structure *diff; int *qcoeff_P, *rcoeff, *coeff; int *qcoeff_B=NULL; int Mode; int CBP, CBPB=0; int bquant[] = {5,6,7,8}; int QP_B; int newgob, advanced_temporarily_off = DEF_ADV_MODE; int i,j,k,B; /* buffer control vars */ float QP_cumulative = (float)0.0; int abs_mb_num = 0, QuantChangePostponed = 0; int QP_new, QP_prev, dquant, QP_xmitted=QP; /* Rate control variables */ Bits *bits_prev = (Bits*)calloc(1,sizeof(Bits)); MB_Structure *pred_P = (MB_Structure *)malloc(sizeof(MB_Structure)); MB_Structure *pred_B = (MB_Structure *) malloc (sizeof (MB_Structure)); int PB_pred_type; /* advanced intra coding variables */ int *store_rcoeff, *store_coeff, *pcoeff; /* used to do prediction in advanced intra coding */ int store_pb; /* Reference Picture Selection variables */ static int sync_gob = 0; int sync_gob_done = 0; int encode_this_gob = 1; /* Always on if Annex N not used */ int sync_gob_this_frame = 0; ZeroBits(bits); /* Currently, the MV info is stored in 7 MV structs per MB. MV[0] * stores the 16x16 MV. MV[1] through MV[4] store the 8x8 MVs. MV[6] * stores the PB delta MV or the forward predicted B MV. MV[5] * stores the backward predicted MV for true-B pictures. */ InitializeMV(MV); InitializeMV(B_f_MV); /* Mark PMV's outside the frame. */ for (i = 1; i < (pels>>4)+1; i++) { for (j = 0; j < 7; j++) { MarkVec(MV[j][0][i]); MarkVec(B_f_MV[j][0][i]); } MV[0][0][i]->Mode = MODE_INTRA; B_f_MV[0][0][i]->Mode = MODE_INTRA; } /* Zero out PMV's outside the frame */ for (i = 0; i < (lines>>4)+1; i++) { for (j = 0; j < 7; j++) { ZeroVec(MV[j][i][0]); ZeroVec(MV[j][i][(pels>>4)+1]); ZeroVec(B_f_MV[j][i][0]); ZeroVec(B_f_MV[j][i][(pels>>4)+1]); } MV[0][i][0]->Mode = MODE_INTRA; MV[0][i][(pels>>4)+1]->Mode = MODE_INTRA; B_f_MV[0][i][0]->Mode = MODE_INTRA; B_f_MV[0][i][(pels>>4)+1]->Mode = MODE_INTRA; } GenerateFrameAndInterpolatedImages(pr, pic, &prev_ipol, &prev_recon, &pi, &pr_edge); /* Integer and half pel motion estimation */ MotionEstimatePicture( curr->lum,prev_recon->lum, NULL, prev_ipol, NULL, pic->seek_dist, MV, pic->use_gobsync, P_PICTURE_ESTIMATION); if (successive_B_frames) { StoreDirectModeVectors(MV, True_B_Direct_Mode_MV); } if (pic->PB) { /* Interpolate the image for B picture prediction without using ETYPE*/ if (mv_outside_frame) { if (long_vectors) B = 16; else B = 8; pi_woRTYPE = InterpolateImage(pr_edge->lum, pels+4*B, lines+4*B,0); prev_ipol_woRTYPE = pi_woRTYPE + (2*pels + 8*B) * 4*B + 4*B; } else { pi_woRTYPE = InterpolateImage(pr->lum,pels,lines,0); prev_ipol_woRTYPE = pi_woRTYPE; } } if (PCT_IPB == pic->picture_coding_type) { if (adv_pred) { /* Turn off advanced coding since there can be only 1 * motion vector for B frames of IPB. */ advanced_temporarily_off = YES; overlapping_MC = OFF; adv_pred = OFF; use_4mv = OFF; } /* Forward motion Integer and half pel estimation for improved PB frames. * Motion estimation type is set to PB_PICTURE so that long vectors will * not be used. */ MotionEstimatePicture( B_image->lum,prev_recon->lum, NULL, prev_ipol_woRTYPE, NULL, pic->seek_dist, B_f_MV, pic->use_gobsync, PB_PICTURE_ESTIMATION); if (advanced_temporarily_off) { advanced_temporarily_off = NO; overlapping_MC = ON; adv_pred = ON; use_4mv = ON; } } switch (rate_control_method) { case NO: case OFFLINE_RC: QP_new = QP_xmitted = QP_prev = QP; /* Copy the passed value of QP */ break; case TMN8_RC: /* Initialization routine for Frame Layer Rate Control */ /* Jordi Ribas added more parameters to InitializeRateControlMB */ InitializeRateControlMB(curr, (float)pic->bit_rate, (pic->PB ? pic->target_frame_rate/2 : pic->target_frame_rate), MV, prev_recon, prev_ipol, pred_P, pic->PB, pic->RTYPE); /* compute the first QP to be included in the picture header */ QP_new = Compute_QP(0,0); QP_xmitted = QP_prev = QP_new; break; case TMN5_RC: /* Initialization routine for MB Layer Rate Control */ QP_new = InitializeQuantizer(PCT_INTER, (float)pic->bit_rate, (pic->PB ? pic->target_frame_rate/2 : pic->target_frame_rate), pic->QP_mean); QP_xmitted = QP_prev = QP_new; break; default: break; } dquant = 0; for ( j = 0; j < lines/MB_SIZE; j++) { if (rate_control_method == TMN5_RC) { /* QP updated at the beginning of each row for Frame layer rate control */ AddBitsPicture(bits); QP_new = UpdateQuantizer(abs_mb_num, pic->QP_mean, PCT_INTER, (float)pic->bit_rate, pels/MB_SIZE, lines/MB_SIZE, bits->total); } newgob = 0; /* Do VRC on GOBs -- just add sync gobs at user defined frequency for now * and only in the sync frames */ if (pic->reference_picture_selection && pic->sync && (pic->use_gobsync && j%pic->use_gobsync == 0)) { /* Determine if this GOB is a sync GOB */ if (j == sync_gob && !sync_gob_done) { ++sync_gob_this_frame; sync_gob = (sync_gob+pic->use_gobsync); if (sync_gob >= (lines/MB_SIZE)) sync_gob = 0; fprintf(stdout, "Coding Sync GOB: %d\n", j); encode_this_gob = 1; if (sync_gob_this_frame == sync_gobs_per_frame) sync_gob_done = 1; } else encode_this_gob = 0; } /* encoder this GOBs (used for VRC on GOBs, otherwise always true) */ if (encode_this_gob) { if (j == 0) { if (advanced_intra_coding) { /* store the coeff for the frame */ if ((store_coeff=(int *)calloc(384*(pels/MB_SIZE)*(lines/MB_SIZE), sizeof(int))) == 0) { fprintf(stderr,"coder(): Couldn't allocate store_coeff.\n"); exit(-1); } if ((store_rcoeff=(int *)calloc(384*(pels/MB_SIZE)*(lines/MB_SIZE), sizeof(int))) == 0) { fprintf(stderr,"coder(): Couldn't allocate store_rcoeff.\n"); exit(-1); } } pic->QUANT = QP_new; bits->header += CountBitsPicture(pic); QP_xmitted = QP_prev = QP_new; } else if (pic->use_gobsync && j%pic->use_gobsync == 0) { bits->header += CountBitsGOB(j,QP_new,pic); /* insert gob header */ QP_xmitted = QP_prev = QP_new; newgob = 1; } for ( i = 0; i < pels/MB_SIZE; i++) { if (rate_control_method == TMN8_RC) { /* Compute optimized quantizer for the current macroblock */ QP_new = Compute_QP(i,j); } /* Update of dquant, check and correct its limit */ if (PCT_B != pic->picture_coding_type) { dquant = QP_new - QP_prev; if ( dquant != 0 && MV[0][j+1][i+1]->Mode == MODE_INTER4V && !EPTYPE) { /* It is not possible to change the quantizer and at the same * time use 8x8 vectors, unless H.263+ PLUS PTYPE is used. * Turning off 8x8 vectors is not * possible at this stage because the previous macroblock * encoded assumed this one should use 8x8 vectors. Therefore * the change of quantizer is postponed until the first MB * without 8x8 vectors */ dquant = 0; QP_xmitted = QP_prev; QuantChangePostponed = 1; } else { QP_xmitted = QP_new; QuantChangePostponed = 0; } /* Unless modified quantization mode is in use restrict the range of * dquant to [-2,+2]*/ if (!modified_quantization) { if (dquant > 2) { dquant = 2; QP_xmitted = QP_prev + dquant; } if (dquant < -2) { dquant = -2; QP_xmitted = QP_prev + dquant; } } else { /* Modified quantization mode is in use. */#ifdef RESTRICTED_MQ /* restrict dquant so that when the modified quantization mode is on quant only uses 2 bits*/ if (dquant != 0) { dquant= Get_restricted_MQ(dquant,QP_prev); QP_xmitted = QP_prev + dquant; }#endif if (dquant!=0) { if ((QP_prev >= 21 && dquant == -3) || (QP_prev >= 11 && QP_prev <= 20 && dquant == -2) || (QP_prev >= 2 && QP_prev <= 10 && dquant == -1) || (QP_prev == 1 && dquant == 2)) { /* dquant will be coded into 2 bits*/ pic->dquant_size = 2; dquant = 2; } else { if ((QP_prev == 31 && dquant == -5) || (QP_prev == 30 && dquant == 1) || (QP_prev == 29 && dquant == 2) || (QP_prev >= 21 && QP_prev <= 28 && dquant == 3) || (QP_prev >= 11 && QP_prev <= 20 && dquant == 2) || (QP_prev >= 1 && QP_prev <= 10 && dquant == 1)) { /* dquant will be coded into 2 bits*/ pic->dquant_size = 2; dquant = 3; } else { /* dquant will be coded intou 6 bits. */ pic->dquant_size=6; /* instead of the difference between current quantizer and
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -