📄 mp4_predict.c
字号:
/********************************************************************************
* *
* This code has been developed by Project Mayo. This software is an *
* implementation of a part of one or more MPEG-4 Video tools as *
* specified in ISO/IEC 14496-2 standard. Those intending to use this *
* software module in hardware or software products are advised that its *
* use may infringe existing patents or copyrights, and any such use *
* would be at such party's own risk. The original developer of this *
* software module and his/her company, and subsequent editors and their *
* companies (including Project Mayo), will have no liability for use of *
* this software or modifications or derivatives thereof. *
* *
********************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* The GPL can be found at: http://www.gnu.org/copyleft/gpl.html *
* *
* Authors: *
* *
* Andrea Graziani (Ag): *
* - Original source code (Open Divx Decoder 0.4a). *
* *
* Pedro Mateu (Pm): *
* - Modified and optimized code *
* *
********************************************************************************/
// mp4_predict.c //
#include "global.h"
#include "mp4_predict.h"
/**/
void dc_recon(int block_num, idct_block_t * dc_value);
void ac_recon(int block_num, idct_block_t * psBlock);
void rescue_predict();
/*
B - C
| |
A - x
*/
void dc_recon(int block_num, idct_block_t * dc_value)
{
int b_xpos,b_ypos;
int Fa,Fb,Fc;
int DC_pred;
if (block_num < 4)
{
b_xpos = (mp4_hdr.mb_xpos << 1) + (block_num & 1);
b_ypos = (mp4_hdr.mb_ypos << 1) + ((block_num & 2) >> 1);
// set prediction direction
if (!b_ypos){
Fb=Fc=1024;
Fa=coeff_pred.dc_lum[b_xpos][0];
}
else {
Fb=coeff_pred.dc_lum[b_xpos][(b_ypos-1)&3];
Fc=coeff_pred.dc_lum[b_xpos+1][(b_ypos-1)&3];
Fa=coeff_pred.dc_lum[b_xpos][b_ypos&3];
}
if (abs(Fb - Fa) < abs(Fb - Fc))
{
coeff_pred.predict_dir = TOP;
DC_pred = Fc;
}
else
{
coeff_pred.predict_dir = LEFT;
DC_pred = Fa;
}
dc_value[0] += _div_div(DC_pred, mp4_hdr.dc_scaler);
dc_value[0] *= mp4_hdr.dc_scaler;
// store dc value
coeff_pred.dc_lum[b_xpos+1][b_ypos&3] = dc_value[0];
}
else // chrominance blocks
{
block_num = block_num - 4;
b_xpos = mp4_hdr.mb_xpos;
b_ypos = mp4_hdr.mb_ypos;
if (b_ypos==0){
Fb=Fc=1024;
Fa=coeff_pred.dc_chr[block_num][b_xpos][0];
}
else {
Fb=coeff_pred.dc_chr[block_num][b_xpos][(b_ypos-1)&1];
Fc=coeff_pred.dc_chr[block_num][b_xpos+1][(b_ypos-1)&1];
Fa=coeff_pred.dc_chr[block_num][b_xpos][b_ypos&1];
}
// set prediction direction
if (abs(Fb - Fa) < abs(Fb - Fc))
{
coeff_pred.predict_dir = TOP;
DC_pred = Fc;
}
else
{
coeff_pred.predict_dir = LEFT;
DC_pred = Fa;
}
dc_value[0] += _div_div(DC_pred, mp4_hdr.dc_scaler);
dc_value[0] *= mp4_hdr.dc_scaler;
// store dc value
coeff_pred.dc_chr[block_num][b_xpos+1][b_ypos&1] = dc_value[0];
}
}
/**/
void ac_recon(unsigned char block_num, idct_block_t * psBlock)
{
int b_xpos, b_ypos;
int i;
if (block_num < 4)
{
b_xpos = (mp4_hdr.mb_xpos << 1) + (block_num & 1);
b_ypos = (block_num & 2) >> 1;
if (mp4_hdr.ac_pred_flag)
{
if (coeff_pred.predict_dir == TOP)
{
if (mp4_hdr.mb_ypos|b_ypos){
for (i = 1; i < 8; i++)
psBlock[i] += coeff_pred.ac_top_lum[b_xpos][i];
}
}
else // left prediction
{
if (b_xpos){
for (i = 1; i < 8; i++)
psBlock[i<<3] += coeff_pred.ac_left_lum[b_ypos][i];
}
}
}
// store coefficients
for (i = 1; i < 8; i++)
coeff_pred.ac_top_lum[b_xpos][i] = psBlock[i];
for (i = 1; i < 8; i++)
coeff_pred.ac_left_lum[b_ypos][i] = psBlock[i<<3];
}
else {
block_num -= 4;
b_xpos = mp4_hdr.mb_xpos;
if (mp4_hdr.ac_pred_flag)
{
if (coeff_pred.predict_dir == TOP)
{
if (mp4_hdr.mb_ypos){
for (i = 1; i < 8; i++)
psBlock[i] += coeff_pred.ac_top_chr[b_xpos][block_num][i];
}
}
else // left prediction
{
if (b_xpos!=0){
for (i = 1; i < 8; i++)
psBlock[i<<3] += coeff_pred.ac_left_chr[block_num][i];
}
}
}
// store coefficients
for (i = 1; i < 8; i++)
coeff_pred.ac_top_chr[b_xpos][block_num][i] = psBlock[i];
for (i = 1; i < 8; i++)
coeff_pred.ac_left_chr[block_num][i] = psBlock[i<<3];
}
}
/**/
#define _IsIntra(mb) ((modemap[mb] == INTRA) || \
(modemap[mb] == INTRA_Q))
#define MIPS_Reset_AC(a) __asm("sdr $0,0($4);" \
"sdr $0,8($4);" \
"sdr $0,16($4);" \
"sdr $0,24($4);",a);
void rescue_predict()
{
int i;
int current_pos = mp4_hdr.mba;
int former_pos = mp4_hdr.mba-mp4_hdr.mb_xsize;
int mb_ypos = mp4_hdr.mb_ypos;
int mb_xpos = mp4_hdr.mb_xpos;
if (! _IsIntra(former_pos-1)) {
// rescue -A- DC value
coeff_pred.dc_lum[2*mb_xpos][(2*mb_ypos-1)&3] = 1024;
coeff_pred.dc_chr[0][mb_xpos][(mb_ypos-1)&1] = 1024;
coeff_pred.dc_chr[1][mb_xpos][(mb_ypos-1)&1] = 1024;
}
// left
if (! _IsIntra(current_pos-1)) {
// rescue -B- DC values
coeff_pred.dc_lum[2*mb_xpos][(2*mb_ypos)&3] = 1024;
coeff_pred.dc_lum[2*mb_xpos][(2*mb_ypos+1)&3] = 1024;
#ifdef MIPS_ASM_64
MIPS_Reset_AC(&coeff_pred.ac_left_lum[0][0]);
#elif defined ARM_VARS
// memset (&coeff_pred.ac_left_lum[0][0],0,64);
for(i = 1; i < 8; i++) coeff_pred.ac_left_lum[0][i] = 0;
for(i = 1; i < 8; i++) coeff_pred.ac_left_lum[1][i] = 0;
#else
// memset (&coeff_pred.ac_left_lum[0][0],0,32);
for(i = 1; i < 8; i++) coeff_pred.ac_left_lum[0][i] = 0;
for(i = 1; i < 8; i++) coeff_pred.ac_left_lum[1][i] = 0;
#endif
coeff_pred.dc_chr[0][mb_xpos][mb_ypos&1] = 1024;
coeff_pred.dc_chr[1][mb_xpos][mb_ypos&1] = 1024;
// rescue -B- AC values
#ifdef MIPS_ASM_64
MIPS_Reset_AC(&coeff_pred.ac_left_chr[0][0]);
#elif defined ARM_VARS
//memset (&coeff_pred.ac_left_chr[0][0],0,64);
for(i = 1; i < 8; i++) coeff_pred.ac_left_chr[0][i] = 0;
for(i = 1; i < 8; i++) coeff_pred.ac_left_chr[1][i] = 0;
#else
// memset (&coeff_pred.ac_left_chr[0][0],0,32);
for(i = 1; i < 8; i++) coeff_pred.ac_left_chr[0][i] = 0;
for(i = 1; i < 8; i++) coeff_pred.ac_left_chr[1][i] = 0;
#endif
}
// top
if (! _IsIntra(former_pos)) {
// rescue -C- DC values
coeff_pred.dc_lum[2*mb_xpos+1][(2*mb_ypos-1)&3] = 1024;
coeff_pred.dc_lum[2*mb_xpos+2][(2*mb_ypos-1)&3] = 1024;
#ifdef MIPS_ASM_64
MIPS_Reset_AC(&coeff_pred.ac_top_lum[2*mb_xpos][0]);
#elif defined ARM_VARS
//memset (&coeff_pred.ac_top_lum[2*mb_xpos][0],0,64);
for(i = 1; i < 8; i++) coeff_pred.ac_top_lum[2*mb_xpos][i] = 0;
for(i = 1; i < 8; i++) coeff_pred.ac_top_lum[2*mb_xpos+1][i] = 0;
#else
for(i = 1; i < 8; i++) coeff_pred.ac_top_lum[2*mb_xpos][i] = 0;
for(i = 1; i < 8; i++) coeff_pred.ac_top_lum[2*mb_xpos+1][i] = 0;
// memset (&coeff_pred.ac_top_lum[2*mb_xpos][0],0,32);
#endif
coeff_pred.dc_chr[0][mb_xpos+1][(mb_ypos-1)&1] = 1024;
coeff_pred.dc_chr[1][mb_xpos+1][(mb_ypos-1)&1] = 1024;
// rescue -C- AC values
#ifdef MIPS_ASM_64
MIPS_Reset_AC(&coeff_pred.ac_top_chr[mb_xpos][0][0]);
#elif defined ARM_VARS
for(i = 1; i < 8; i++) coeff_pred.ac_top_chr[0][mb_xpos][i] = 0;
for(i = 1; i < 8; i++) coeff_pred.ac_top_chr[1][mb_xpos][i] = 0;
// memset (&coeff_pred.ac_top_chr[mb_xpos][0][0],0,64);
#else
for(i = 1; i < 8; i++) coeff_pred.ac_top_chr[0][mb_xpos][i] = 0;
for(i = 1; i < 8; i++) coeff_pred.ac_top_chr[1][mb_xpos][i] = 0;
// memset (&coeff_pred.ac_top_chr[mb_xpos][0][0],0,32);
#endif
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -