📄 mp4_block.c
字号:
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "mp4_vars.h"
#include "getbits.h"
#include "clearblock.h"
#include "mp4_iquant.h"
#include "mp4_predict.h"
#include "mp4_vld.h"
#include "debug.h"
#include "mp4_block.h"
/**
*
**/
static int getDCsizeLum();
static int getDCsizeChr();
static int getDCdiff();
static void setDCscaler(int block_num);
static int getACdir();
/***/
int block(int block_num, int coded)
{
int i;
int dct_dc_size, dct_dc_diff;
int intraFlag = ((mp4_state->hdr.derived_mb_type == INTRA) ||
(mp4_state->hdr.derived_mb_type == INTRA_Q)) ? 1 : 0;
event_t event;
clearblock(ld->block);
if (intraFlag)
{
setDCscaler(block_num);
if (block_num < 4) {
dct_dc_size = getDCsizeLum();
if (dct_dc_size != 0)
dct_dc_diff = getDCdiff(dct_dc_size);
else
dct_dc_diff = 0;
if (dct_dc_size > 8)
getbits1();
}
else {
dct_dc_size = getDCsizeChr();
if (dct_dc_size != 0)
dct_dc_diff = getDCdiff(dct_dc_size);
else
dct_dc_diff = 0;
if (dct_dc_size > 8)
getbits1();
}
ld->block[0] = (short) dct_dc_diff;
}
if (intraFlag)
{
dc_recon(block_num, &ld->block[0]);
}
if (coded)
{
unsigned int * zigzag;
if ((intraFlag) && (mp4_state->hdr.ac_pred_flag == 1)) {
if (mp4_state->coeff_pred.predict_dir == TOP)
zigzag = mp4_tables->alternate_horizontal_scan;
else
zigzag = mp4_tables->alternate_vertical_scan;
}
else {
zigzag = mp4_tables->zig_zag_scan;
}
i = intraFlag ? 1 : 0;
do
{
event = vld_event(intraFlag);
i+= event.run;
ld->block[zigzag[i]] = (short) event.level;
i++;
} while (! event.last);
}
if (intraFlag)
{
ac_recon(block_num, &ld->block[0]);
}
#ifdef _DEBUG_B_ACDC
if (intraFlag)
{
int i;
_Print("After AcDcRecon:\n");
_Print(" x ");
for (i = 1; i < 64; i++) {
if ((i != 0) && ((i % 8) == 0))
_Print("\n");
_Print("%4d ", ld->block[i]);
}
_Print("\n");
}
#endif // _DEBUG_ACDC
if (mp4_state->hdr.quant_type == 0)
{
iquant(ld->block, intraFlag);
}
else
{
_Error("Error: MPEG-2 inverse quantization NOT implemented\n");
exit(110);
}
#ifdef _DEBUG_B_QUANT
{
int i;
_Print("After IQuant:\n");
_Print(" x ");
for (i = 1; i < 64; i++) {
if ((i != 0) && ((i % 8) == 0))
_Print("\n");
_Print("%4d ", ld->block[i]);
}
_Print("\n");
}
#endif
idct(ld->block);
return 1;
}
/***/
int blockIntra(int block_num, int coded)
{
int i;
int dct_dc_size, dct_dc_diff;
event_t event;
clearblock(ld->block);
setDCscaler(block_num);
if (block_num < 4) {
dct_dc_size = getDCsizeLum();
if (dct_dc_size != 0)
dct_dc_diff = getDCdiff(dct_dc_size);
else
dct_dc_diff = 0;
if (dct_dc_size > 8)
getbits1();
}
else {
dct_dc_size = getDCsizeChr();
if (dct_dc_size != 0)
dct_dc_diff = getDCdiff(dct_dc_size);
else
dct_dc_diff = 0;
if (dct_dc_size > 8)
getbits1();
}
ld->block[0] = (short) dct_dc_diff;
dc_recon(block_num, &ld->block[0]);
if (coded)
{
unsigned int * zigzag;
if (mp4_state->hdr.ac_pred_flag == 1) {
if (mp4_state->coeff_pred.predict_dir == TOP)
zigzag = mp4_tables->alternate_horizontal_scan;
else
zigzag = mp4_tables->alternate_vertical_scan;
}
else {
zigzag = mp4_tables->zig_zag_scan;
}
i = 1;
do
{
event = vld_intra_dct();
i+= event.run;
ld->block[zigzag[i]] = (short) event.level;
i++;
} while (! event.last);
}
mp4_state->hdr.intrablock_rescaled = ac_rescaling(block_num, &ld->block[0]);
if (! mp4_state->hdr.intrablock_rescaled)
{
ac_recon(block_num, &ld->block[0]);
}
ac_store(block_num, &ld->block[0]);
if (mp4_state->hdr.quant_type == 0)
{
iquant(ld->block, 1);
}
else
{
iquant_typefirst(ld->block);
}
idct(ld->block);
return 1;
}
/***/
int blockInter(int block_num, int coded)
{
event_t event;
unsigned int * zigzag = mp4_tables->zig_zag_scan; // zigzag scan dir
int i;
clearblock(ld->block);
if (mp4_state->hdr.quant_type == 0)
{
int q_scale = mp4_state->hdr.quantizer;
int q_2scale = q_scale << 1;
int q_add = (q_scale & 1) ? q_scale : (q_scale - 1);
i = 0;
do
{
event = vld_inter_dct();
i+= event.run;
if (event.level > 0) {
ld->block[zigzag[i]] = (q_2scale * event.level) + q_add;
}
else {
ld->block[zigzag[i]] = (q_2scale * event.level) - q_add;
}
i++;
} while (! event.last);
}
else
{
int k, m = 0;
i = 0;
do
{
event = vld_inter_dct();
i+= event.run;
k = (event.level > 0) ? 1 : -1;
assert(ld->block[zigzag[i]] < 2047);
assert(ld->block[zigzag[i]] > -2048);
ld->block[zigzag[i]] = ((2 * event.level + k) * mp4_state->hdr.quantizer *
mp4_tables->nonintra_quant_matrix[zigzag[i]]) >> 4;
assert(ld->block[zigzag[i]] < 2047);
assert(ld->block[zigzag[i]] > -2048);
m ^= ld->block[zigzag[i]];
i++;
} while (! event.last);
if (!(m%2)) ld->block[63] ^= 1;
}
idct(ld->block);
return 1;
}
static int getDCsizeLum()
{
int code;
if (showbits(11) == 1) {
flushbits(11);
return 12;
}
if (showbits(10) == 1) {
flushbits(10);
return 11;
}
if (showbits(9) == 1) {
flushbits(9);
return 10;
}
if (showbits(8) == 1) {
flushbits(8);
return 9;
}
if (showbits(7) == 1) {
flushbits(7);
return 8;
}
if (showbits(6) == 1) {
flushbits(6);
return 7;
}
if (showbits(5) == 1) {
flushbits(5);
return 6;
}
if (showbits(4) == 1) {
flushbits(4);
return 5;
}
code = showbits(3);
if (code == 1) {
flushbits(3);
return 4;
} else if (code == 2) {
flushbits(3);
return 3;
} else if (code == 3) {
flushbits(3);
return 0;
}
code = showbits(2);
if (code == 2) {
flushbits(2);
return 2;
} else if (code == 3) {
flushbits(2);
return 1;
}
return 0;
}
static int getDCsizeChr()
{
if (showbits(12) == 1) {
flushbits(12);
return 12;
}
if (showbits(11) == 1) {
flushbits(11);
return 11;
}
if (showbits(10) == 1) {
flushbits(10);
return 10;
}
if (showbits(9) == 1) {
flushbits(9);
return 9;
}
if (showbits(8) == 1) {
flushbits(8);
return 8;
}
if (showbits(7) == 1) {
flushbits(7);
return 7;
}
if (showbits(6) == 1) {
flushbits(6);
return 6;
}
if (showbits(5) == 1) {
flushbits(5);
return 5;
}
if (showbits(4) == 1) {
flushbits(4);
return 4;
}
if (showbits(3) == 1) {
flushbits(3);
return 3;
}
return (3 - getbits(2));
}
static int getDCdiff(int dct_dc_size)
{
int code = getbits(dct_dc_size);
int msb = code >> (dct_dc_size - 1);
if (msb == 0) {
return (-1 * (code^((int) pow(2.0,(double) dct_dc_size) - 1)));
}
else {
return code;
}
}
static void setDCscaler(int block_num)
{
int type = (block_num < 4) ? 0 : 1;
int quant = mp4_state->hdr.quantizer;
if (type == 0) {
if (quant > 0 && quant < 5)
mp4_state->hdr.dc_scaler = 8;
else if (quant > 4 && quant < 9)
mp4_state->hdr.dc_scaler = (2 * quant);
else if (quant > 8 && quant < 25)
mp4_state->hdr.dc_scaler = (quant + 8);
else
mp4_state->hdr.dc_scaler = (2 * quant - 16);
}
else {
if (quant > 0 && quant < 5)
mp4_state->hdr.dc_scaler = 8;
else if (quant > 4 && quant < 25)
mp4_state->hdr.dc_scaler = ((quant + 13) / 2);
else
mp4_state->hdr.dc_scaler = (quant - 6);
}
}
/***/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -