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

📄 macroblock.c

📁 H.264 source codes
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** * macroblock.c: h264 decoder library ***************************************************************************** * Copyright (C) 2003 Laurent Aimar * $Id: macroblock.c,v 1.1 2004/06/03 19:27:07 fenrir Exp $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA. *****************************************************************************/#include <stdlib.h>#include <stdio.h>#include <string.h>#include <stdint.h>#include "common/common.h"#include "common/vlc.h"#include "vlc.h"#include "macroblock.h"static const uint8_t block_idx_x[16] ={    0, 1, 0, 1, 2, 3, 2, 3, 0, 1, 0, 1, 2, 3, 2, 3};static const uint8_t block_idx_y[16] ={    0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3};static const uint8_t block_idx_xy[4][4] ={    { 0, 2, 8,  10},    { 1, 3, 9,  11},    { 4, 6, 12, 14},    { 5, 7, 13, 15}};static const int golomb_to_intra4x4_cbp[48]={    47, 31, 15,  0, 23, 27, 29, 30,  7, 11, 13, 14, 39, 43, 45, 46,    16,  3,  5, 10, 12, 19, 21, 26, 28, 35, 37, 42, 44,  1,  2,  4,     8, 17, 18, 20, 24,  6,  9, 22, 25, 32, 33, 34, 36, 40, 38, 41};static const int golomb_to_inter_cbp[48]={     0, 16,  1,  2,  4,  8, 32,  3,  5, 10, 12, 15, 47,  7, 11, 13,    14,  6,  9, 31, 35, 37, 42, 44, 33, 34, 36, 40, 39, 43, 45, 46,    17, 18, 20, 24, 19, 21, 26, 28, 23, 27, 29, 30, 22, 25, 38, 41};static const int i_chroma_qp_table[52] ={     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,    20, 21, 22, 23, 24, 25, 26, 27, 28, 29,    29, 30, 31, 32, 32, 33, 34, 34, 35, 35,    36, 36, 37, 37, 37, 38, 38, 38, 39, 39,    39, 39};void x264_mb_partition_ref_set( x264_macroblock_t *mb, int i_list, int i_part, int i_ref ){    int x,  y;    int w,  h;    int dx, dy;    x264_mb_partition_getxy( mb, i_part, 0, &x, &y );    if( mb->i_partition == D_16x16 )    {        w = 4; h = 4;    }    else if( mb->i_partition == D_16x8 )    {        w = 4; h = 2;    }    else if( mb->i_partition == D_8x16 )    {        w = 2; h = 4;    }    else    {        /* D_8x8 */        w = 2; h = 2;    }    for( dx = 0; dx < w; dx++ )    {        for( dy = 0; dy < h; dy++ )        {            mb->partition[x+dx][y+dy].i_ref[i_list] = i_ref;        }    }}void x264_mb_partition_mv_set( x264_macroblock_t *mb, int i_list, int i_part, int i_sub, int mv[2] ){    int x,  y;    int w,  h;    int dx, dy;    x264_mb_partition_getxy( mb, i_part, i_sub, &x, &y );    x264_mb_partition_size ( mb, i_part, i_sub, &w, &h );    for( dx = 0; dx < w; dx++ )    {        for( dy = 0; dy < h; dy++ )        {            mb->partition[x+dx][y+dy].mv[i_list][0] = mv[0];            mb->partition[x+dx][y+dy].mv[i_list][1] = mv[1];        }    }}int x264_macroblock_read_cabac( x264_t *h, bs_t *s, x264_macroblock_t *mb ){    return -1;}static int x264_macroblock_decode_ipcm( x264_t *h, bs_t *s, x264_macroblock_t *mb ){    /* TODO */    return -1;}#define BLOCK_INDEX_CHROMA_DC   (-1)#define BLOCK_INDEX_LUMA_DC     (-2)static int bs_read_vlc( bs_t *s, x264_vlc_table_t *table ){    int i_nb_bits;    int i_value = 0;    int i_bits;    int i_index;    int i_level = 0;    i_index = bs_show( s, table->i_lookup_bits );    if( i_index >= table->i_lookup )    {        return( -1 );    }    i_value = table->lookup[i_index].i_value;    i_bits  = table->lookup[i_index].i_size;    while( i_bits < 0 )    {        i_level++;        if( i_level > 5 )        {            return( -1 );        // FIXME what to do ?        }        bs_skip( s, table->i_lookup_bits );        i_nb_bits = -i_bits;        i_index = bs_show( s, i_nb_bits ) + i_value;        if( i_index >= table->i_lookup )        {            return( -1 );        }        i_value = table->lookup[i_index].i_value;        i_bits  = table->lookup[i_index].i_size;    }    bs_skip( s, i_bits );    return( i_value );}static int block_residual_read_cavlc( x264_t *h, bs_t *s, x264_macroblock_t *mb,                                      int i_idx, int *l, int i_count ){    int i;    int level[16], run[16];    int i_coeff;    int i_total, i_trailing;    int i_suffix_length;    int i_zero_left;    for( i = 0; i < i_count; i++ )    {        l[i] = 0;    }    /* total/trailing */    if( i_idx == BLOCK_INDEX_CHROMA_DC )    {        int i_tt;        if( ( i_tt = bs_read_vlc( s, h->x264_coeff_token_lookup[4] )) < 0 )        {            return -1;        }        i_total = i_tt / 4;        i_trailing = i_tt % 4;    }    else    {        /* x264_mb_predict_non_zero_code return 0 <-> (16+16+1)>>1 = 16 */        static const int ct_index[17] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,3 };        int nC;        int i_tt;        if( i_idx == BLOCK_INDEX_LUMA_DC )        {            nC = x264_mb_predict_non_zero_code( h, mb, 0 );        }        else        {            nC = x264_mb_predict_non_zero_code( h, mb, i_idx );        }        if( ( i_tt = bs_read_vlc( s, h->x264_coeff_token_lookup[ct_index[nC]] ) ) < 0 )        {            return -1;        }        i_total = i_tt / 4;        i_trailing = i_tt % 4;    }    if( i_idx >= 0 )    {        mb->block[i_idx].i_non_zero_count = i_total;    }    if( i_total <= 0 )    {        return 0;    }    i_suffix_length = i_total > 10 && i_trailing < 3 ? 1 : 0;    for( i = 0; i < i_trailing; i++ )    {        level[i] = 1 - 2 * bs_read1( s );    }    for( ; i < i_total; i++ )    {        int i_prefix;        int i_level_code;        i_prefix = bs_read_vlc( s, h->x264_level_prefix_lookup );        if( i_prefix == -1 )        {            return -1;        }        else if( i_prefix < 14 )        {            if( i_suffix_length > 0 )            {                i_level_code = (i_prefix << i_suffix_length) + bs_read( s, i_suffix_length );            }            else            {                i_level_code = i_prefix;            }        }        else if( i_prefix == 14 )        {            if( i_suffix_length > 0 )            {                i_level_code = (i_prefix << i_suffix_length) + bs_read( s, i_suffix_length );            }            else            {                i_level_code = i_prefix + bs_read( s, 4 );            }        }        else /* if( i_prefix == 15 ) */        {            i_level_code = (i_prefix << i_suffix_length) + bs_read( s, 12 );            if( i_suffix_length == 0 )            {                i_level_code += 15;            }        }        if( i == i_trailing && i_trailing < 3 )        {            i_level_code += 2;        }        /* Optimise */        level[i] = i_level_code&0x01 ? -((i_level_code+1)/2) : (i_level_code+2)/2;        if( i_suffix_length == 0 )        {            i_suffix_length++;        }        if( abs( level[i] ) > ( 3 << ( i_suffix_length - 1 ) ) && i_suffix_length < 6 )        {            i_suffix_length++;        }    }    if( i_total < i_count )    {        if( i_idx == BLOCK_INDEX_CHROMA_DC )        {            i_zero_left = bs_read_vlc( s, h->x264_total_zeros_dc_lookup[i_total-1] );        }        else        {            i_zero_left = bs_read_vlc( s, h->x264_total_zeros_lookup[i_total-1] );        }        if( i_zero_left < 0 )        {            return -1;        }    }    else    {        i_zero_left = 0;    }    for( i = 0; i < i_total - 1; i++ )    {        if( i_zero_left <= 0 )        {            break;        }        run[i] = bs_read_vlc( s, h->x264_run_before_lookup[X264_MIN( i_zero_left - 1, 6 )] );        if( run[i] < 0 )        {            return -1;        }        i_zero_left -= run[i];    }    if( i_zero_left < 0 )    {        return -1;    }    for( ; i < i_total - 1; i++ )    {        run[i] = 0;    }    run[i_total-1] = i_zero_left;    i_coeff = -1;    for( i = i_total - 1; i >= 0; i-- )    {        i_coeff += run[i] + 1;        l[i_coeff] = level[i];    }    return 0;}static inline void array_zero_set( int *l, int i_count ){    int i;    for( i = 0; i < i_count; i++ )    {        l[i] = 0;    }}int x264_macroblock_read_cavlc( x264_t *h, bs_t *s, x264_macroblock_t *mb ){    int i_mb_i_offset;    int i_mb_p_offset;    int b_sub_ref0 = 0;    int i_type;    int i;    /* read the mb type */    switch( h->sh.i_type )    {        case SLICE_TYPE_I:            i_mb_p_offset = 0;  /* shut up gcc */            i_mb_i_offset = 0;            break;        case SLICE_TYPE_P:            i_mb_p_offset = 0;            i_mb_i_offset = 5;            break;        case SLICE_TYPE_B:            i_mb_p_offset = 23;            i_mb_i_offset = 23 + 5;            break;        default:            fprintf( stderr, "internal error or slice unsupported\n" );            return -1;    }    i_type = bs_read_ue( s );    if( i_type < i_mb_i_offset )    {        if( i_type < i_mb_p_offset )        {            fprintf( stderr, "unsupported mb type(B*)\n" );            /* TODO for B frame */            return -1;        }        else        {            i_type -= i_mb_p_offset;            if( i_type == 0 )            {                mb->i_type = P_L0;                mb->i_partition = D_16x16;            }            else if( i_type == 1 )            {                mb->i_type = P_L0;                mb->i_partition = D_16x8;            }            else if( i_type == 2 )            {                mb->i_type = P_L0;                mb->i_partition = D_8x16;            }            else if( i_type == 3 || i_type == 4 )            {                mb->i_type = P_8x8;                mb->i_partition = D_8x8;                b_sub_ref0 = i_type == 4 ? 1 : 0;            }            else            {                fprintf( stderr, "invalid mb type\n" );                return -1;            }        }    }    else    {        i_type -= i_mb_i_offset;        if( i_type == 0 )        {            mb->i_type = I_4x4;        }        else if( i_type < 25 )        {            mb->i_type = I_16x16;            mb->i_intra16x16_pred_mode = (i_type - 1)%4;            mb->i_cbp_chroma = ( (i_type-1) / 4 )%3;            mb->i_cbp_luma   = ((i_type-1) / 12) ? 0x0f : 0x00;        }        else if( i_type == 25 )        {            mb->i_type = I_PCM;        }        else        {            fprintf( stderr, "invalid mb type (%d)\n", i_type );            return -1;        }    }    if( mb->i_type == I_PCM )    {        return x264_macroblock_decode_ipcm( h, s, mb );    }    if( IS_INTRA( mb->i_type ) )    {        if( mb->i_type == I_4x4 )        {            for( i = 0; i < 16; i++ )            {                int b_coded;                b_coded = bs_read1( s );                if( b_coded )                {                    mb->block[i].i_intra4x4_pred_mode = x264_mb_predict_intra4x4_mode( h, mb, i );                }                else                {                    int i_predicted_mode = x264_mb_predict_intra4x4_mode( h, mb, i );                    int i_mode = bs_read( s, 3 );                    if( i_mode >= i_predicted_mode )                    {                        mb->block[i].i_intra4x4_pred_mode = i_mode + 1;                    }                    else                    {                        mb->block[i].i_intra4x4_pred_mode = i_mode;                    }                }            }        }        mb->i_chroma_pred_mode = bs_read_ue( s );    }    else if( mb->i_type == P_8x8 || mb->i_type == B_8x8)    {        /* FIXME won't work for B_8x8 */        for( i = 0; i < 4; i++ )        {            int i_sub_partition;            i_sub_partition = bs_read_ue( s );            switch( i_sub_partition )            {                case 0:                    mb->i_sub_partition[i] = D_L0_8x8;                    break;                case 1:                    mb->i_sub_partition[i] = D_L0_8x4;                    break;                case 2:                    mb->i_sub_partition[i] = D_L0_4x8;                    break;                case 3:                    mb->i_sub_partition[i] = D_L0_4x4;                    break;                default:                    fprintf( stderr, "invalid i_sub_partition\n" );                    return -1;            }        }        for( i = 0; i < 4; i++ )        {            int i_ref;            i_ref = b_sub_ref0 ? 0 : bs_read_te( s, h->sh.i_num_ref_idx_l0_active - 1 );            x264_mb_partition_ref_set( mb, 0, i, i_ref );        }        for( i = 0; i < 4; i++ )        {            int i_sub;            int i_ref;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -