📄 mp4dec.cpp
字号:
#include <stdlib.h>
#include <memory.h>
#include "sampmp4.h"
const int bits_mask_tbl[33] =
{
0x00000000, 0x00000001, 0x00000003, 0x00000007,
0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
0xffffffff
};
unsigned char default_qmat_intra_tbl [64] = {
8, 17, 18, 19, 21, 23, 25, 27,
17, 18, 19, 21, 23, 25, 27, 28,
20, 21, 22, 23, 24, 26, 28, 30,
21, 22, 23, 24, 26, 28, 30, 32,
22, 23, 24, 26, 28, 30, 32, 35,
23, 24, 26, 28, 30, 32, 35, 38,
25, 26, 28, 30, 32, 35, 38, 41,
27, 28, 30, 32, 35, 38, 41, 45
};
unsigned char default_qmat_inter_tbl [64] = {
16, 17, 18, 19, 20, 21, 22, 23,
17, 18, 19, 20, 21, 22, 23, 24,
18, 19, 20, 21, 22, 23, 24, 25,
19, 20, 21, 22, 23, 24, 26, 27,
20, 21, 22, 23, 25, 26, 27, 28,
21, 22, 23, 24, 26, 27, 28, 30,
22, 23, 24, 26, 27, 28, 30, 31,
23, 24, 25, 27, 28, 30, 31, 33
};
const Ipp16u dc_switch_thresh_tbl[8] = {512, 13, 15, 17, 19, 21, 23, 0};
const unsigned char classic_zigzag_tbl[64] = {
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36,
29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46,
53, 60, 61, 54, 47, 55, 62, 63
};
const Ipp8u cbpy4_intra_tbl[13] = {16, 16, 16, 0, 12, 10,
14, 5, 13, 3, 11, 7, 15};
const mp4_tree_node mcbpc_pvop_vlc_tbl[21] = {
{ 0, 1, 1, 0 }, { 0, 0, 2, 7 }, { 0, 0, 4, 3 }, { 1, 1, 2, 1 },
{ 0, 0, 8, 5 }, { 0, 1, 6, 12 }, { 1, 1, 16, 3 }, { 1, 1, 8, 4 },
{ 0, 0, 11, 9 }, { 0, 0, 15, 10 }, { 1, 1, 6, 5 }, { 0, 0, 12, 16},
{ 0, 0, 18, 13}, { 0, 1, 14, 14 }, { 1, 1, 17, 7 }, { 1, 1, 10, 9 },
{ 0, 1, 17, 15}, { 1, 1, 13, 11 }, { 0, 0, 20, 19}, { 1, 1, 19, 18},
{ 1, 1, -1, 48 }};
/* for intra DC only block */
const mp4_table_node dc_size_lum_tbl[8] = {
{5,3}, {4,3}, {3,3}, {0,3}, {2,2}, {2,2}, {1,2}, {1,2}};
const mp4_table_node dc_size_chr_tbl[4] = {
{3,2}, {2,2}, {1,2}, {0,2}};
/******************************************************************************
// Name: decode_block_inter_mpeg4
// Description: Decodes the INTER block coefficients. Inverse
// quantization, inversely zigzag positioning and IDCT,
// with appropriate clipping on each step, are performed
// on the coefficients. The results (residuals) are placed
// in a contiguous array of 64 elements.
//
// Input Arguments:
// stream_buf Pointer to the source video bitstream in which the
// inter block starts
// quant_para Quantization parameter of current MB
// quant_matrix Pointer to the quantization weighting matrix for inter
// macroblock. If it is NULL, it indicates to use the
// second inverse quantization method; if it is not NULL,
// the first inverse quantization method is used.
//
// Output Arguments:
// stream_buf Pointer to the updated video bitstream after the block
// is decoded
// dst_rsd pointer to the decoded residual buffer (a contiguous
// array of 64 elements of Ipp16s data type).
//
// Returns:
// SAMPLE_STATUS_NOERR If succeeds
// SAMPLE_STATUS_ERR If decoding fails
//
// Notes:
//
******************************************************************************/
sample_status decode_block_inter_mpeg4
(sample_bitstream *stream_buf, Ipp16s *dst_rsd, int quant_para,
const Ipp8u *quant_matrix)
{
/* 1. VLC decoding of inter DC and AC components and inverse zigzag scan */
/* dst_rsd must be 4 byte aligned */
if (ippStsNoErr != ippiDecodeVLCZigzag_Inter_MPEG4_1u16s (
&stream_buf->bs_cur_byte, &stream_buf->bs_cur_bitoffset, dst_rsd)) {
return SAMPLE_STATUS_ERR;
}
/* 2. inverse quantisation */
if (ippStsNoErr != ippiQuantInvInter_MPEG4_16s_I (dst_rsd, quant_para,
quant_matrix)) {
return SAMPLE_STATUS_ERR;
}
/* 3. inverse DCT */
/* dst_rsd must be 8 byte aligned */
if (ippStsNoErr != ippiDCT8x8Inv_Video_16s_C1I(dst_rsd)) {
return SAMPLE_STATUS_ERR;
}
return SAMPLE_STATUS_NOERR;
}
/******************************************************************************
//
// Name: decode_block_intradc_mpeg4
//
// Description: Decodes the INTRA block which has only intra DC
// transform coefficients in the bitstream. Inverse
// quantization, inversely zigzag positioning and IDCT,
// with appropriate clipping on each step, are performed
// on the coefficients.The results are then placed in the
// output frame/plane on a pixel basis.
//
// Input Arguments:
// stream_buf Pointer to the source video bitstream in which the
// intra block starts
// step Width of the destination plane.
// coef_bufrow Pointer to the coefficient row buffer.
// coef_bufcol Pointer to the coefficient column buffer.
// quant_para Quantization parameter of the macroblock which the
// current block belongs to.
// quant_buf Pointer to the quantization parameter buffer.
// quant_matrix Pointer to the quantization weighting matrix for intra
// MB. If it is NULL, it indicates to use the second
// inverse quantization method; if it is not NULL, the
// first inverse quantization method is used.
// blk_indx Block index indicating the component type and position
// as defined in subclause 6.1.3.8, Figure 6-5 of ISO/IEC
// 14496-2.
// intra_dcvlc_flag
// A flag determined by intra_dc_vlc_thr and Qp. This
// allows a mechanism to switch between two VLC's for
// coding of Intra DC coefficients as per Table 6-21 of
// ISO/IEC 14496-2.
// ac_pred_flag A flag indicating if the AC coefficients of the first
// row or first column are differentially coded for intra
// coded MB.
//
// Output Arguments:
// stream_buf Pointer to the source video bitstream after the block
// is decoded
// dst_val Pointer to the block in the destination plane.
// coef_bufrow Pointer to the updated coefficient row buffer.
// coef_bufcol Pointer to the updated coefficient column buffer.
//
// Returns:
// SAMPLE_STATUS_NOERR If succeeds
// SAMPLE_STATUS_ERR If decoding fails
// Notes:
//
//
******************************************************************************/
sample_status decode_block_intradc_mpeg4
(sample_bitstream *stream_buf, Ipp8u *dst_val, int step, Ipp16s *coef_bufrow,
Ipp16s *coef_bufcol, Ipp8u quant_para, Ipp8u *quant_buf,
const Ipp8u *quant_matrix, int blk_indx, int intra_dcvlc_flag,
int ac_pred_flag)
{
int pred_dir; /* prediction direction */
int dc_left, dc_top, dc_left_top; /* DC value of the left, top and
// left-top block */
Ipp16s qp_pred; /* The QP value of the prediction
// reference macroblock */
Ipp32u code;
int dc_size, i, level;
Ipp16s coef_buf[72], tmp_coef;
Ipp16s *dst_coef = (Ipp16s*)SAMPLE_ALIGN8(coef_buf);
IppVideoComponent video_comp;
qp_pred = quant_para;
/* 1. DC prediction direction */
/* Below is the neighboring blocks used in DC/AC prediction direction
// shown in Figure 7-5 of ISO/IEC 14496-2
// --- --- ---
// | b | | c | | d |
// --- --- ---
// --- --- ---
// | a | | x | | y |
// --- --- ---
// --- --- ---
// | e | | w | | z |
// --- --- ---
// Befor decoding this macroblock(block x, y, z, w), the DC coefficients
// are stored as: (Fx[0][0] means the DC coefficient of x block)
// vop_infor->coef_buf_row[-8] = Fa[0][0];
// vop_infor->coef_buf_row[0] = Fc[0][0];
// vop_infor->coef_buf_row[8] = Fd[0][0];
// vop_infor->coef_buf_col[0] = Fb[0][0];
// vop_infor->coef_buf_col[8] = Fe[0][0];
//
// After the x block has been decoded, the DC coefficients are stored as:
// vop_infor->coef_buf_row[-8] = Fa[0][0];
// vop_infor->coef_buf_row[0] = Fx[0][0];
// vop_infor->coef_buf_row[8] = Fd[0][0];
// vop_infor->coef_buf_col[0] = Fc[0][0];
// vop_infor->coef_buf_col[8] = Fe[0][0];
//
// After the y block has been decoded, the DC coefficients are stored as:
// vop_infor->coef_buf_row[-8] = Fe[0][0];
// vop_infor->coef_buf_row[0] = Fx[0][0];
// vop_infor->coef_buf_row[8] = Fy[0][0];
// vop_infor->coef_buf_col[0] = Fd[0][0];
// vop_infor->coef_buf_col[8] = Fa[0][0];
//
// After the w block has been decoded, the DC coefficients are stored as:
// vop_infor->coef_buf_row[-8] = Fe[0][0];
// vop_infor->coef_buf_row[0] = Fw[0][0];
// vop_infor->coef_buf_row[8] = Fy[0][0];
// vop_infor->coef_buf_col[0] = Fd[0][0];
// vop_infor->coef_buf_col[8] = Fx[0][0];
//
// After the z block has been decoded, the DC coefficients are stored as:
// vop_infor->coef_buf_row[-8] = Fe[0][0];
// vop_infor->coef_buf_row[0] = Fw[0][0];
// vop_infor->coef_buf_row[8] = Fy[0][0];
// vop_infor->coef_buf_col[0] = Fd[0][0];
// vop_infor->coef_buf_col[8] = Fz[0][0];
// vop_infor->coef_buf_row += 16;
// If this is the last macroblock in a row, buffer should be updated as:
// vop_infor->coef_buf_col[8] = Fz[0][0]; */
dc_top = (0 > coef_bufrow[0]) ? 1024 : coef_bufrow[0];
dc_left = (0 > coef_bufrow[-8]) ? 1024 : coef_bufrow[-8];
dc_left_top = (0 > coef_bufcol[0]) ? 1024 : coef_bufcol[0];
if (ABS_MP4(dc_left - dc_left_top) < ABS_MP4(dc_top - dc_left_top)) {
pred_dir = IPP_VIDEO_VERTICAL;
if((0 <= coef_bufrow[0]) && (Y_BLOCK3 != blk_indx)
&& (Y_BLOCK4 != blk_indx)) {
/* the reference block is from the top macro block */
qp_pred = quant_buf[1];
}
} else {
pred_dir = IPP_VIDEO_HORIZONTAL;
if((0 <= coef_bufrow[-8]) && (Y_BLOCK2 != blk_indx)
&& (Y_BLOCK4 != blk_indx)) {
/* the reference block is from the left macro block */
qp_pred = quant_buf[0];
}
}
video_comp = (Y_BLOCK4 >= blk_indx) ? IPP_VIDEO_LUMINANCE
: IPP_VIDEO_CHROMINANCE;
/* 2. intraDC VLC decoding */
if(intra_dcvlc_flag) {
if (IPP_VIDEO_LUMINANCE == video_comp) {
/* dct_dc_size_luminance */
/* prefetch 3 bits */
code = get_bits_mpeg4(stream_buf, 3);
rewind_buffer_mpeg4(stream_buf, 3 - dc_size_lum_tbl[code].numbit);
dc_size = dc_size_lum_tbl[code].value;
while ((0 == code) && (12 >= dc_size)) {
code = get_bits_mpeg4(stream_buf, 1);
if (0 == code) {
dc_size ++;
}
}
} else {
/* dct_dc_size_chrominance */
/* prefetch 2 bits */
code = get_bits_mpeg4(stream_buf, 2);
rewind_buffer_mpeg4(stream_buf, 2 - dc_size_chr_tbl[code].numbit);
dc_size = dc_size_chr_tbl[code].value;
while ((0 == code) && (12 >= dc_size)) {
code = get_bits_mpeg4(stream_buf, 1);
if (0 == code) {
dc_size++;
}
}
} /* end of decoding the length of DC coefficient */
if (12 < dc_size) {
return SAMPLE_STATUS_ERR;
}
/* dc_size bit dct_dc_differential */
code = get_bits_mpeg4(stream_buf, dc_size);
if (!(code >> (dc_size - 1))) {
level = (1 << dc_size) - code - 1;
level = - level;
} else {
level = (int)code;
}
if (8 < dc_size) {
/* assert one marker bit */
ASSERT_MARKER_BIT(stream_buf);
}
/* end of intraDC VLC decoding */
} else {
/* use_intra_dc_vlc == 0 */
level = 0;
}
dst_coef[0] = (Ipp16s)level;
/* reset all AC differential coeffs to zero */
for (i = 1; i < SAMPLE_VIDEO_BLOCK_SQUARE_SIZE; i++) {
dst_coef[i] = 0;
}
/* 3. inverse DC and AC prediction, AC buffer update */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -