⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mp4dec.cpp

📁 一个使用 linux编写的mpeg4解码代码,包括mpeg4解码库和示例代码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
#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 + -