📄 pictureb.cpp
字号:
#include <stdio.h>
#include <math.h>
#include "block.h"
#include "mot_est.h"
#include "macroblock.h"
#include "vlc.h"
#include "image.h"
#include "bitstream.h"
int findIntraSAD(unsigned char *curr, int lx_curr);
void chooseBmode(H263VencStatus *encoder, MCParam *MC);
int setBtype(int a, int b, int c);
int MB_Encode_B(H263VencStatus *encoder, int pix_x, int pix_y, MCParam *MC,
INT16 *qcoeff_p);
/*!
*******************************************************************************
*
* Name: EncBfrm
* Description: Encode one B Picture
* Input:
* Output:
* Last modified: 2003/1/8 by lcl
*
*******************************************************************************/
int EncBfrm(H263VencStatus *encoder, MCParam *MC)
{
int total_bits = 0;
int pix_x, pix_y;
int mb_x, mb_y;
int lines = encoder->lines;
int pels = encoder->pels;
int newgob;
int cod;
int cbp;
INT16 qcoeff[384];
int dquant = 0;
int mb_mode;
int mb_type;
int gob_nbr = 0;
int gob_quant = encoder->total_Q;
int TRP = encoder->TR - encoder->ref_pic*(encoder->B_frame+1);
encoder->method.interpolate_lum(encoder);
/* Search for forward MV */
grabVec(encoder, MC, 0);
/* Search for backward MV */
grabVec(encoder, MC, 1);
chooseBmode(encoder, MC);
total_bits += EncPicHdrPlus(encoder);
for (pix_y = 0, mb_y = 0; pix_y < lines; pix_y += 16, mb_y++)
{
newgob = 0;
if (encoder->advanced_intra_coding && (pix_y == 0))
{
clear_coeff_top(encoder->rcoeff.top_lum, encoder->rcoeff.top_cb, encoder->rcoeff.top_cr);
clear_coeff_top(encoder->coeff.top_lum, encoder->coeff.top_cb, encoder->coeff.top_cr);
}
if(encoder->gobsync && pix_y && mb_y%(encoder->gobsync) == 0)
{
gob_nbr++;
total_bits += EncGOBHdr(&(encoder->putstrmctrl), gob_nbr, encoder->gfid, gob_quant, encoder->TRB, TRP);
newgob = 1;
if (encoder->advanced_intra_coding)
{
clear_coeff_top(encoder->rcoeff.top_lum, encoder->rcoeff.top_cb, encoder->rcoeff.top_cr);
clear_coeff_top(encoder->coeff.top_lum, encoder->coeff.top_cb, encoder->coeff.top_cr);
}
}
for (pix_x = 0, mb_x = 0; pix_x < pels; pix_x += 16, mb_x++)
{
if (encoder->advanced_intra_coding && pix_x == 0)
{
clear_coeff_left(encoder->rcoeff.left_lum, encoder->rcoeff.left_cr, encoder->rcoeff.left_cb);
clear_coeff_left(encoder->coeff.left_lum, encoder->coeff.left_cr, encoder->coeff.left_cb);
}
mb_mode = (MC->mv_frame[0][mb_y+1][mb_x+1])->Mode; //!< set mode of current mb
cod = 0;
if (B_INTRA == mb_mode)
{
if (!encoder->advanced_intra_coding)
{
cbp = MB_Encode_I(encoder, pix_x, pix_y, qcoeff);
mb_type = setBtype(mb_mode, cbp, dquant);
total_bits += EncMBHdr_B(&(encoder->putstrmctrl), mb_type, cbp, dquant); //!< write MCBPC, CBPY, DQUANT
total_bits += EncCoeff(&(encoder->putstrmctrl), 1, cbp, qcoeff, 64); //!< write coefficients
}
else
{
cbp = MB_Encode_AI(encoder, pix_x, pix_y, qcoeff);
mb_type = setBtype(mb_mode, cbp, dquant);
total_bits += EncMBHdr_B(&(encoder->putstrmctrl), mb_type, cbp, dquant);
total_bits += EncCoeff(&(encoder->putstrmctrl), 2, cbp, qcoeff, 64);
}
}
else
{
cbp = MB_Encode_B(encoder, pix_x, pix_y, MC, qcoeff);
mb_type = setBtype(mb_mode, cbp, dquant);
total_bits += EncMBHdr_B(&(encoder->putstrmctrl), mb_type, cbp, dquant); //!< write COD, MCBPC, CBPY, DQUANT
total_bits += EncMVD_B(&(encoder->putstrmctrl), MC, mb_x, mb_y, mb_mode, newgob); //!< write MVD
total_bits += EncCoeff(&(encoder->putstrmctrl), 0, cbp, qcoeff, 64); //!< write coefficients
if (encoder->advanced_intra_coding)
{
set_coeff_inter(mb_x, encoder->rcoeff.top_lum, encoder->rcoeff.top_cr, encoder->rcoeff.top_cb,
encoder->rcoeff.left_lum, encoder->rcoeff.left_cr, encoder->rcoeff.left_cb);
}
}
}
}
total_bits += alignbits(&(encoder->putstrmctrl));
clear_buff(&(encoder->putstrmctrl));
return total_bits;
}
/*!
*******************************************************************************
*
* Name: chooseBmode
* Description: choose prediction mode for a B frame
* Input:
* Output:
* Last modified: 2003/1/8 by lcl
*
*******************************************************************************/
void chooseBmode(H263VencStatus *encoder, MCParam *MC)
{
int i, j;
int block;
int pix_x, pix_y;
int lx_curr = encoder->pels;
int lx_ipol = encoder->mv_outside_frame ? encoder->pels * 2 + 64 : encoder->pels * 2;
int lines = encoder->lines/16;
int pels = encoder->pels/16;
int sadfwd;
int sadbwd;
int saddir;
int sadbid;
int sadmin;
int sadintra;
int trd;
int trb;
int dx, dy, dxf, dyf, dxb, dyb;
unsigned char *curr;
unsigned char *prev;
unsigned char *next;
trb = encoder->TRB - encoder->TRP[encoder->ref_index];
if (trb < 0)
{
trb += 256;
}
trd = encoder->TRP[encoder->zero_index] - encoder->TRP[encoder->ref_index];
if (trd < 0)
{
trd += 256;
}
for (j = 0, pix_y = 0; j < lines; j++, pix_y+=16)
{
for ( i = 0, pix_x = 0; i < pels; i++, pix_x+=16)
{
sadfwd = MC->mv_frame[0][j+1][i+1]->min_sad;
sadbwd = MC->mv_frame[5][j+1][i+1]->min_sad;
/* compute saddir */
if (MC->mv_lastframe[0][j][i]->Mode == MODE_INTER4V ||
MC->mv_lastframe[0][j][i]->Mode == MODE_INTER4V_Q)
{
saddir = 0;
for (block = 0; block < 4; block++)
{
dx = (MC->mv_lastframe[block+1][j][i]->x*2+MC->mv_lastframe[block+1][j][i]->x_half);
dy = (MC->mv_lastframe[block+1][j][i]->y*2+MC->mv_lastframe[block+1][j][i]->y_half);
dxf = trb * dx / trd;
dyf = trb * dy / trd;
dxb = (trb - trd) * dx / trd;
dyb = (trb - trd) * dy / trd;
curr = encoder->BPicture[encoder->B_count].pLum +pix_y*lx_curr + pix_x;
prev = encoder->prev_ipol + (dyf+2*pix_y+((block&2)<<3))*lx_ipol + dxf+2*pix_x+((block&1)<<4);
next = encoder->next_ipol + (dyb+2*pix_y+((block&2)<<3))*lx_ipol + dxb+2*pix_x+((block&1)<<4);
saddir += encoder->method.findbiSAD(prev, next, curr, lx_ipol, lx_curr, 8);
}
}
else
{
dx = (MC->mv_lastframe[0][j][i]->x*2+MC->mv_lastframe[0][j][i]->x_half);
dy = (MC->mv_lastframe[0][j][i]->y*2+MC->mv_lastframe[0][j][i]->y_half);
dxf = trb * dx / trd;
dyf = trb * dy / trd;
dxb = (trb - trd) * dx / trd;
dyb = (trb - trd) * dy / trd;
curr = encoder->BPicture[encoder->B_count].pLum +pix_y*lx_curr + pix_x;
prev = encoder->prev_ipol + (dyf+2*pix_y)*lx_ipol + dxf+2*pix_x;
next = encoder->next_ipol + (dyb+2*pix_y)*lx_ipol + dxb+2*pix_x;
saddir = encoder->method.findbiSAD(prev, next, curr, lx_ipol, lx_curr, 16);
}
/* compute sadbid */
dxf = MC->mv_frame[0][j+1][i+1]->x*2 + MC->mv_frame[0][j+1][i+1]->x_half;
dyf = MC->mv_frame[0][j+1][i+1]->y*2 + MC->mv_frame[0][j+1][i+1]->y_half;
dxb = MC->mv_frame[5][j+1][i+1]->x*2 + MC->mv_frame[5][j+1][i+1]->x_half;
dyb = MC->mv_frame[5][j+1][i+1]->y*2 + MC->mv_frame[5][j+1][i+1]->y_half;
curr = encoder->BPicture[encoder->B_count].pLum + pix_y*lx_curr + pix_x;
prev = encoder->prev_ipol + (dyf+2*pix_y)*lx_ipol + dxf+2*pix_x;
next = encoder->next_ipol + (dyb+2*pix_y)*lx_ipol + dxb+2*pix_x;
sadbid = encoder->method.findbiSAD(prev, next, curr, lx_ipol, lx_curr, 16);
/* compute sadintra */
curr = encoder->BPicture[encoder->B_count].pLum + pix_y*lx_curr + pix_x;
sadintra = findIntraSAD(curr, lx_curr);
/* mode decision */
if ((saddir < sadfwd) && (saddir < sadbwd) && (saddir < sadbid))
{
MC->mv_frame[0][j+1][i+1]->Mode = B_DIRECT;
sadmin = saddir;
zeroVec(MC->mv_frame[0][j+1][i+1]);
zeroVec(MC->mv_frame[5][j+1][i+1]);
}
else if((sadfwd < saddir) && (sadfwd < sadbwd) && (sadfwd <sadbid))
{
MC->mv_frame[0][j+1][i+1]->Mode = B_FORWARD;
sadmin = sadfwd;
zeroVec(MC->mv_frame[5][j+1][i+1]);
}
else if((sadbwd < saddir) && (sadbwd < sadfwd) && (sadbwd <sadbid))
{
MC->mv_frame[0][j+1][i+1]->Mode = B_BACKWARD;
sadmin = sadbwd;
zeroVec(MC->mv_frame[0][j+1][i+1]);
}
else
{
MC->mv_frame[0][j+1][i+1]->Mode = B_BIDIRECTIONAL;
sadmin = sadbid;
}
if (sadintra < sadmin - 500)
{
MC->mv_frame[0][j+1][i+1]->Mode = B_INTRA;
zeroVec(MC->mv_frame[0][j+1][i+1]);
zeroVec(MC->mv_frame[5][j+1][i+1]);
}
#ifdef PRINTMODE
printf("%d ", MC->mv_frame[0][j+1][i+1]->Mode);
#endif
}
#ifdef PRINTMODE
printf("\n");
#endif
}
}
/*!
*******************************************************************************
*
* Name: setBtype
* Description: set MB type for B frames
* Input:
* Output:
* Last modified: 2003/1/8 by lcl
*
*******************************************************************************/
int setBtype(int a, int b, int c)
{
int type = a * 3;
if (b != 0)
{
type = c ? type+2 : type+1;
}
// intra and intra+q
if ((13 == type) || (14 == type))
{
type--;
}
return type - 1;
}
/*!
*******************************************************************************
*
* Name: MB_Encode_B
* Description: Encode one Macroblock in for B frame(make diff,dct,Q,IQ,IDct,data-recon)
* Input: position of curr-MB, encoder structure, MV
* Output: qcoeff_p
* Side effect: write reconstructive data to recon_pic in corresponding position
* Return: cbp
* Last modified: 2003/1/8
*
*******************************************************************************/
int MB_Encode_B(H263VencStatus *encoder, int pix_x, int pix_y, MCParam *MC,
INT16 *qcoeff_p)
{
int i, j;
int flag = 32;
unsigned char *curr_block;
unsigned char *recon_block;
unsigned char pred_block[64];
INT16 diff_block[64];
MB_structure curr_mb;
MB_structure recon_mb;
int trb;
int trd;
int dxf, dyf, dxb, dyb;
MotionVector *MV; //!< pointer to MV of last P frame
trb = encoder->TRB - encoder->TRP[encoder->ref_index];
if (trb < 0)
{
trb += 256;
}
trd = encoder->TRP[encoder->zero_index] - encoder->TRP[encoder->ref_index];
if (trd < 0)
{
trd += 256;
}
int mb_x = pix_x/16;
int mb_y = pix_y/16;
int pred_mode = MC->mv_frame[0][mb_y+1][mb_x+1]->Mode;
int cbp = 0;
int pic_width = encoder->pels;
int rec_width = encoder->pels;
int lx_ipol = encoder->mv_outside_frame ? pic_width*2+64 : pic_width*2;
int lx_ref_c = encoder->mv_outside_frame ? pic_width/2+16 : pic_width/2;
int QP = encoder->total_Q;
int sad_gate = QP * 8;
unsigned char *prev_ipol = encoder->prev_ipol;
unsigned char *next_ipol = encoder->next_ipol;
Image *ref_img = &(encoder->frame_buf[encoder->ref_index]);
Image *next_img = &(encoder->frame_buf[encoder->zero_index]);
Image *curr_img = &(encoder->BPicture[encoder->B_count]);
Image *recon_img = &(encoder->BPicture[0]);
//! Find MB in the image
curr_mb.pLum = curr_img->pLum + pix_y * pic_width + pix_x;
curr_mb.pCb = curr_img->pCb + pix_y * pic_width/4 + pix_x/2;
curr_mb.pCr = curr_img->pCr + pix_y * pic_width/4 + pix_x/2;
recon_mb.pLum = recon_img->pLum + pix_y * rec_width + pix_x;
recon_mb.pCb = recon_img->pCb + pix_y * rec_width/4 + pix_x/2;
recon_mb.pCr = recon_img->pCr + pix_y * rec_width/4 + pix_x/2;
/* direct mode */
if (B_DIRECT == pred_mode)
{
//! Encode each block in the MB
//!4 lum blocks
for (i = 0; i < 16; i+=8)
{
for (j = 0; j < 16; j+=8)
{
curr_block = curr_mb.pLum + i*pic_width + j;
recon_block = recon_mb.pLum + i*rec_width + j;
MV = MC->mv_lastframe[0][mb_y][mb_x];
if (MV->Mode == MODE_INTER4V || MV->Mode == MODE_INTER4V_Q)
{
MV = MC->mv_lastframe[(j>>3)+(i>>2)+1][mb_y][mb_x];
}
dxf = (MV->x*2 + MV->x_half) * trb / trd;
dyf = (MV->y*2 + MV->y_half) * trb / trd;
dxb = (MV->x*2 + MV->x_half) * (trb-trd) / trd;
dyb = (MV->y*2 + MV->y_half) * (trb-trd) / trd;
encoder->method.pred_lum_bid(pix_x+j, pix_y+i, dxf, dyf, dxb, dyb, prev_ipol, next_ipol,
lx_ipol, pred_block);
encoder->method.make_diff(curr_block, pic_width, pred_block, diff_block);
if (block_SAD(diff_block) > sad_gate)
{
encoder->method.DCT(diff_block, diff_block);
if (encoder->method.Quant_blk_P(diff_block, qcoeff_p, QP))
{
cbp|=flag;
encoder->method.DeQuant_blk_P(qcoeff_p, diff_block, QP);
encoder->method.IDCT(diff_block, diff_block);
encoder->method.recon_pic(recon_block, rec_width, pred_block, diff_block);
}
else
{
encoder->method.block_copy1(recon_block, pred_block, rec_width);
}
}
else
{
encoder->method.block_copy1(recon_block, pred_block, rec_width);
}
flag = flag >> 1;
qcoeff_p+=64;
}
}
/* find both forward MV and backward MV for chrom blocks in direct mode */
findchromMV_dir(encoder, MC, pix_x, pix_y, &dxf, &dyf, &dxb, &dyb);
//! Cb block
curr_block = curr_mb.pCb;
recon_block = recon_mb.pCb;
encoder->method.pred_chrom_bid(pix_x/2, pix_y/2, ref_img->pCb, next_img->pCb, lx_ref_c, dxf, dyf, dxb, dyb, pred_block);
encoder->method.make_diff(curr_block, pic_width/2, pred_block, diff_block);
if (block_SAD(diff_block) > sad_gate)
{
encoder->method.DCT(diff_block, diff_block);
if (encoder->method.Quant_blk_P(diff_block, qcoeff_p, QP))
{
cbp|=flag;
encoder->method.DeQuant_blk_P (qcoeff_p, diff_block, QP);
encoder->method.IDCT(diff_block, diff_block);
encoder->method.recon_pic(recon_block, rec_width/2, pred_block, diff_block);
}
else
{
encoder->method.block_copy1(recon_block, pred_block, rec_width/2);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -