cavlc.c 26 KB
Newer Older
Laurent Aimar's avatar
Laurent Aimar committed
1 2 3
/*****************************************************************************
 * cavlc.c: h264 encoder library
 *****************************************************************************
4
 * Copyright (C) 2003-2008 x264 project
Laurent Aimar's avatar
Laurent Aimar committed
5 6
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *          Loren Merritt <lorenm@u.washington.edu>
8
 *          Fiona Glaser <fiona@x264.com>
Laurent Aimar's avatar
Laurent Aimar committed
9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * 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
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
Laurent Aimar's avatar
Laurent Aimar committed
23 24
 *****************************************************************************/

25
#include "common/common.h"
Laurent Aimar's avatar
Laurent Aimar committed
26 27
#include "macroblock.h"

Fiona Glaser's avatar
Fiona Glaser committed
28 29 30 31
#ifndef RDO_SKIP_BS
#define RDO_SKIP_BS 0
#endif

Laurent Aimar's avatar
Laurent Aimar committed
32 33 34 35 36 37 38 39 40 41 42 43
static const uint8_t intra4x4_cbp_to_golomb[48]=
{
  3, 29, 30, 17, 31, 18, 37,  8, 32, 38, 19,  9, 20, 10, 11,  2,
 16, 33, 34, 21, 35, 22, 39,  4, 36, 40, 23,  5, 24,  6,  7,  1,
 41, 42, 43, 25, 44, 26, 46, 12, 45, 47, 27, 13, 28, 14, 15,  0
};
static const uint8_t inter_cbp_to_golomb[48]=
{
  0,  2,  3,  7,  4,  8, 17, 13,  5, 18,  9, 14, 10, 15, 16, 11,
  1, 32, 33, 36, 34, 37, 44, 40, 35, 45, 38, 41, 39, 42, 43, 19,
  6, 24, 25, 20, 26, 21, 46, 28, 27, 47, 22, 29, 23, 30, 31, 12
};
Loren Merritt's avatar
Loren Merritt committed
44 45 46 47 48 49
static const uint8_t mb_type_b_to_golomb[3][9]=
{
    { 4,  8, 12, 10,  6, 14, 16, 18, 20 }, /* D_16x8 */
    { 5,  9, 13, 11,  7, 15, 17, 19, 21 }, /* D_8x16 */
    { 1, -1, -1, -1,  2, -1, -1, -1,  3 }  /* D_16x16 */
};
50
static const uint8_t sub_mb_type_p_to_golomb[4]=
Loren Merritt's avatar
Loren Merritt committed
51 52 53
{
    3, 1, 2, 0
};
54
static const uint8_t sub_mb_type_b_to_golomb[13]=
Loren Merritt's avatar
Loren Merritt committed
55 56 57
{
    10,  4,  5,  1, 11,  6,  7,  2, 12,  8,  9,  3,  0
};
Laurent Aimar's avatar
Laurent Aimar committed
58

59
#define bs_write_vlc(s,v) bs_write( s, (v).i_size, (v).i_bits )
Laurent Aimar's avatar
Laurent Aimar committed
60 61 62 63

/****************************************************************************
 * block_residual_write_cavlc:
 ****************************************************************************/
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
static inline int block_residual_write_cavlc_escape( x264_t *h, bs_t *s, int i_suffix_length, int level )
{
    static const uint16_t next_suffix[7] = { 0, 3, 6, 12, 24, 48, 0xffff };
    int i_level_prefix = 15;
    int mask = level >> 15;
    int abs_level = (level^mask)-mask;
    int i_level_code = abs_level*2-mask-2;
    if( ( i_level_code >> i_suffix_length ) < 15 )
    {
        bs_write( s, (i_level_code >> i_suffix_length) + 1 + i_suffix_length,
                 (1<<i_suffix_length) + (i_level_code & ((1<<i_suffix_length)-1)) );
    }
    else
    {
        i_level_code -= 15 << i_suffix_length;
        if( i_suffix_length == 0 )
            i_level_code -= 15;

        /* If the prefix size exceeds 15, High Profile is required. */
        if( i_level_code >= 1<<12 )
        {
            if( h->sps->i_profile_idc >= PROFILE_HIGH )
            {
                while( i_level_code > 1<<(i_level_prefix-3) )
                {
                    i_level_code -= 1<<(i_level_prefix-3);
                    i_level_prefix++;
                }
            }
            else
            {
#if RDO_SKIP_BS
                /* Weight highly against overflows. */
                s->i_bits_encoded += 1000000;
#else
99
                x264_log(h, X264_LOG_WARNING, "OVERFLOW levelcode=%d is only allowed in High Profile\n", i_level_code );
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
                /* clip level, preserving sign */
                i_level_code = (1<<12) - 2 + (i_level_code & 1);
#endif
            }
        }
        bs_write( s, i_level_prefix + 1, 1 );
        bs_write( s, i_level_prefix - 3, i_level_code & ((1<<(i_level_prefix-3))-1) );
    }
    if( i_suffix_length == 0 )
        i_suffix_length++;
    if( abs_level > next_suffix[i_suffix_length] )
        i_suffix_length++;
    return i_suffix_length;
}

115
static int block_residual_write_cavlc( x264_t *h, bs_t *s, int i_ctxBlockCat, int16_t *l, int nC )
Laurent Aimar's avatar
Laurent Aimar committed
116
{
117
    static const uint8_t ctz_index[8] = {3,0,1,0,2,0,1,0};
118
    static const int count_cat[5] = {16, 15, 16, 4, 15};
119 120
    x264_run_level_t runlevel;
    int i_trailing, i_total_zero, i_suffix_length, i;
121
    int i_total = 0;
Laurent Aimar's avatar
Laurent Aimar committed
122 123
    unsigned int i_sign;

124
    /* level and run and total */
125
    /* set these to 2 to allow branchless i_trailing calculation */
126 127 128 129
    runlevel.level[1] = 2;
    runlevel.level[2] = 2;
    i_total = h->quantf.coeff_level_run[i_ctxBlockCat]( l, &runlevel );
    i_total_zero = runlevel.last + 1 - i_total;
Laurent Aimar's avatar
Laurent Aimar committed
130

131 132 133
    i_trailing = ((((runlevel.level[0]+1) | (1-runlevel.level[0])) >> 31) & 1) // abs(runlevel.level[0])>1
               | ((((runlevel.level[1]+1) | (1-runlevel.level[1])) >> 31) & 2)
               | ((((runlevel.level[2]+1) | (1-runlevel.level[2])) >> 31) & 4);
134
    i_trailing = ctz_index[i_trailing];
135 136 137
    i_sign = ((runlevel.level[2] >> 31) & 1)
           | ((runlevel.level[1] >> 31) & 2)
           | ((runlevel.level[0] >> 31) & 4);
138
    i_sign >>= 3-i_trailing;
Laurent Aimar's avatar
Laurent Aimar committed
139 140

    /* total/trailing */
Fiona Glaser's avatar
Fiona Glaser committed
141
    bs_write_vlc( s, x264_coeff_token[nC][i_total*4+i_trailing-4] );
Laurent Aimar's avatar
Laurent Aimar committed
142

143
    i_suffix_length = i_total > 10 && i_trailing < 3;
144
    bs_write( s, i_trailing, i_sign );
145 146

    if( i_trailing < i_total )
Laurent Aimar's avatar
Laurent Aimar committed
147
    {
148 149
        int16_t val = runlevel.level[i_trailing];
        int16_t val_original = runlevel.level[i_trailing]+LEVEL_TABLE_SIZE/2;
150
        if( i_trailing < 3 )
151
            val -= (val>>15)|1; /* as runlevel.level[i] can't be 1 for the first one if i_trailing < 3 */
152 153 154 155 156 157 158
        val += LEVEL_TABLE_SIZE/2;

        if( (unsigned)val_original < LEVEL_TABLE_SIZE )
        {
            bs_write_vlc( s, x264_level_token[i_suffix_length][val] );
            i_suffix_length = x264_level_token[i_suffix_length][val_original].i_next;
        }
Laurent Aimar's avatar
Laurent Aimar committed
159
        else
160 161
            i_suffix_length = block_residual_write_cavlc_escape( h, s, i_suffix_length, val-LEVEL_TABLE_SIZE/2 );
        for( i = i_trailing+1; i < i_total; i++ )
Laurent Aimar's avatar
Laurent Aimar committed
162
        {
163
            val = runlevel.level[i] + LEVEL_TABLE_SIZE/2;
164
            if( (unsigned)val < LEVEL_TABLE_SIZE )
165
            {
166 167
                bs_write_vlc( s, x264_level_token[i_suffix_length][val] );
                i_suffix_length = x264_level_token[i_suffix_length][val].i_next;
168
            }
169 170
            else
                i_suffix_length = block_residual_write_cavlc_escape( h, s, i_suffix_length, val-LEVEL_TABLE_SIZE/2 );
Laurent Aimar's avatar
Laurent Aimar committed
171 172 173
        }
    }

174
    if( i_total < count_cat[i_ctxBlockCat] )
Laurent Aimar's avatar
Laurent Aimar committed
175
    {
176
        if( i_ctxBlockCat == DCT_CHROMA_DC )
Laurent Aimar's avatar
Laurent Aimar committed
177 178 179 180 181
            bs_write_vlc( s, x264_total_zeros_dc[i_total-1][i_total_zero] );
        else
            bs_write_vlc( s, x264_total_zeros[i_total-1][i_total_zero] );
    }

Loren Merritt's avatar
Loren Merritt committed
182
    for( i = 0; i < i_total-1 && i_total_zero > 0; i++ )
Laurent Aimar's avatar
Laurent Aimar committed
183
    {
184 185
        int i_zl = X264_MIN( i_total_zero, 7 );
        bs_write_vlc( s, x264_run_before[i_zl-1][runlevel.run[i]] );
186
        i_total_zero -= runlevel.run[i];
Laurent Aimar's avatar
Laurent Aimar committed
187
    }
188 189

    return i_total;
Laurent Aimar's avatar
Laurent Aimar committed
190 191
}

Fiona Glaser's avatar
Fiona Glaser committed
192 193
static const uint8_t ct_index[17] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,3};

194
#define block_residual_write_cavlc(h,s,cat,idx,l)\
Fiona Glaser's avatar
Fiona Glaser committed
195 196
{\
    int nC = cat == DCT_CHROMA_DC ? 4 : ct_index[x264_mb_predict_non_zero_code( h, cat == DCT_LUMA_DC ? 0 : idx )];\
197 198 199 200 201
    uint8_t *nnz = &h->mb.cache.non_zero_count[x264_scan8[idx]];\
    if( !*nnz )\
        bs_write_vlc( s, x264_coeff0_token[nC] );\
    else\
        *nnz = block_residual_write_cavlc(h,s,cat,l,nC);\
Fiona Glaser's avatar
Fiona Glaser committed
202 203
}

204 205 206
static void cavlc_qp_delta( x264_t *h, bs_t *s )
{
    int i_dqp = h->mb.i_qp - h->mb.i_last_qp;
207 208 209

    /* Avoid writing a delta quant if we have an empty i16x16 block, e.g. in a completely flat background area */
    if( h->mb.i_type == I_16x16 && !(h->mb.i_cbp_luma | h->mb.i_cbp_chroma)
210
        && !h->mb.cache.non_zero_count[x264_scan8[24]] )
211
    {
Fiona Glaser's avatar
Fiona Glaser committed
212
#if !RDO_SKIP_BS
213 214 215 216 217
        h->mb.i_qp = h->mb.i_last_qp;
#endif
        i_dqp = 0;
    }

218 219
    if( i_dqp )
    {
220 221 222 223
        if( i_dqp < -26 )
            i_dqp += 52;
        else if( i_dqp > 25 )
            i_dqp -= 52;
224
    }
225
    bs_write_se( s, i_dqp );
226 227
}

228
static void cavlc_mb_mvd( x264_t *h, bs_t *s, int i_list, int idx, int width )
229
{
230
    DECLARE_ALIGNED_4( int16_t mvp[2] );
231 232 233 234
    x264_mb_predict_mv( h, i_list, idx, width, mvp );
    bs_write_se( s, h->mb.cache.mv[i_list][x264_scan8[idx]][0] - mvp[0] );
    bs_write_se( s, h->mb.cache.mv[i_list][x264_scan8[idx]][1] - mvp[1] );
}
235

236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
static void cavlc_mb8x8_mvd( x264_t *h, bs_t *s, int i_list, int i )
{
    if( !x264_mb_partition_listX_table[i_list][ h->mb.i_sub_partition[i] ] )
        return;

    switch( h->mb.i_sub_partition[i] )
    {
        case D_L0_8x8:
        case D_L1_8x8:
        case D_BI_8x8:
            cavlc_mb_mvd( h, s, i_list, 4*i, 2 );
            break;
        case D_L0_8x4:
        case D_L1_8x4:
        case D_BI_8x4:
            cavlc_mb_mvd( h, s, i_list, 4*i+0, 2 );
            cavlc_mb_mvd( h, s, i_list, 4*i+2, 2 );
            break;
        case D_L0_4x8:
        case D_L1_4x8:
        case D_BI_4x8:
            cavlc_mb_mvd( h, s, i_list, 4*i+0, 1 );
            cavlc_mb_mvd( h, s, i_list, 4*i+1, 1 );
            break;
        case D_L0_4x4:
        case D_L1_4x4:
        case D_BI_4x4:
            cavlc_mb_mvd( h, s, i_list, 4*i+0, 1 );
            cavlc_mb_mvd( h, s, i_list, 4*i+1, 1 );
            cavlc_mb_mvd( h, s, i_list, 4*i+2, 1 );
            cavlc_mb_mvd( h, s, i_list, 4*i+3, 1 );
            break;
268 269 270
    }
}

271
static inline void x264_macroblock_luma_write_cavlc( x264_t *h, bs_t *s, int i8start, int i8end )
272
{
273
    int i8, i4;
274 275 276
    if( h->mb.b_transform_8x8 )
    {
        /* shuffle 8x8 dct coeffs into 4x4 lists */
277
        for( i8 = i8start; i8 <= i8end; i8++ )
278
            if( h->mb.i_cbp_luma & (1 << i8) )
Fiona Glaser's avatar
Fiona Glaser committed
279
                h->zigzagf.interleave_8x8_cavlc( h->dct.luma4x4[i8*4], h->dct.luma8x8[i8], &h->mb.cache.non_zero_count[x264_scan8[i8*4]] );
280 281
    }

282
    for( i8 = i8start; i8 <= i8end; i8++ )
283 284
        if( h->mb.i_cbp_luma & (1 << i8) )
            for( i4 = 0; i4 < 4; i4++ )
285
                block_residual_write_cavlc( h, s, DCT_LUMA_4x4, i4+i8*4, h->dct.luma4x4[i4+i8*4] );
286 287
}

Laurent Aimar's avatar
Laurent Aimar committed
288 289 290 291 292 293 294 295 296
/*****************************************************************************
 * x264_macroblock_write:
 *****************************************************************************/
void x264_macroblock_write_cavlc( x264_t *h, bs_t *s )
{
    const int i_mb_type = h->mb.i_type;
    int i_mb_i_offset;
    int i;

Fiona Glaser's avatar
Fiona Glaser committed
297
#if !RDO_SKIP_BS
298 299 300 301
    const int i_mb_pos_start = bs_pos( s );
    int       i_mb_pos_tex;
#endif

Laurent Aimar's avatar
Laurent Aimar committed
302 303 304 305 306 307 308 309 310 311 312 313
    switch( h->sh.i_type )
    {
        case SLICE_TYPE_I:
            i_mb_i_offset = 0;
            break;
        case SLICE_TYPE_P:
            i_mb_i_offset = 5;
            break;
        case SLICE_TYPE_B:
            i_mb_i_offset = 23;
            break;
        default:
314
            x264_log(h, X264_LOG_ERROR, "internal error or slice unsupported\n" );
Laurent Aimar's avatar
Laurent Aimar committed
315 316 317
            return;
    }

318 319 320 321 322 323
    if( h->sh.b_mbaff
        && (!(h->mb.i_mb_y & 1) || IS_SKIP(h->mb.type[h->mb.i_mb_xy - h->mb.i_mb_stride])) )
    {
        bs_write1( s, h->mb.b_interlaced );
    }

Fiona Glaser's avatar
Fiona Glaser committed
324
#if !RDO_SKIP_BS
Fiona Glaser's avatar
Fiona Glaser committed
325
    if( i_mb_type == I_PCM )
Laurent Aimar's avatar
Laurent Aimar committed
326 327
    {
        bs_write_ue( s, i_mb_i_offset + 25 );
328
        i_mb_pos_tex = bs_pos( s );
329
        h->stat.frame.i_mv_bits += i_mb_pos_tex - i_mb_pos_start;
Laurent Aimar's avatar
Laurent Aimar committed
330 331

        bs_align_0( s );
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346

        memcpy( s->p, h->mb.pic.p_fenc[0], 256 );
        s->p += 256;
        for( i = 0; i < 8; i++ )
            memcpy( s->p + i*8, h->mb.pic.p_fenc[1] + i*FENC_STRIDE, 8 );
        s->p += 64;
        for( i = 0; i < 8; i++ )
            memcpy( s->p + i*8, h->mb.pic.p_fenc[2] + i*FENC_STRIDE, 8 );
        s->p += 64;

        /* if PCM is chosen, we need to store reconstructed frame data */
        h->mc.copy[PIXEL_16x16]( h->mb.pic.p_fdec[0], FDEC_STRIDE, h->mb.pic.p_fenc[0], FENC_STRIDE, 16 );
        h->mc.copy[PIXEL_8x8]  ( h->mb.pic.p_fdec[1], FDEC_STRIDE, h->mb.pic.p_fenc[1], FENC_STRIDE, 8 );
        h->mc.copy[PIXEL_8x8]  ( h->mb.pic.p_fdec[2], FDEC_STRIDE, h->mb.pic.p_fenc[2], FENC_STRIDE, 8 );

347
        h->stat.frame.i_tex_bits += bs_pos(s) - i_mb_pos_tex;
Laurent Aimar's avatar
Laurent Aimar committed
348 349
        return;
    }
350 351 352 353 354 355 356
#endif

    /* Write:
      - type
      - prediction
      - mv */
    if( i_mb_type == I_4x4 || i_mb_type == I_8x8 )
Laurent Aimar's avatar
Laurent Aimar committed
357
    {
358
        int di = i_mb_type == I_8x8 ? 4 : 1;
Laurent Aimar's avatar
Laurent Aimar committed
359
        bs_write_ue( s, i_mb_i_offset + 0 );
360 361
        if( h->pps->b_transform_8x8_mode )
            bs_write1( s, h->mb.b_transform_8x8 );
Laurent Aimar's avatar
Laurent Aimar committed
362 363

        /* Prediction: Luma */
364
        for( i = 0; i < 16; i += di )
Laurent Aimar's avatar
Laurent Aimar committed
365 366
        {
            int i_pred = x264_mb_predict_intra4x4_mode( h, i );
367
            int i_mode = x264_mb_pred_mode4x4_fix( h->mb.cache.intra4x4_pred_mode[x264_scan8[i]] );
Laurent Aimar's avatar
Laurent Aimar committed
368

Fiona Glaser's avatar
Fiona Glaser committed
369
            if( i_pred == i_mode )
Laurent Aimar's avatar
Laurent Aimar committed
370 371
                bs_write1( s, 1 );  /* b_prev_intra4x4_pred_mode */
            else
Fiona Glaser's avatar
Fiona Glaser committed
372
                bs_write( s, 4, i_mode - (i_mode > i_pred) );
Laurent Aimar's avatar
Laurent Aimar committed
373
        }
374
        bs_write_ue( s, x264_mb_pred_mode8x8c_fix[ h->mb.i_chroma_pred_mode ] );
Laurent Aimar's avatar
Laurent Aimar committed
375 376 377
    }
    else if( i_mb_type == I_16x16 )
    {
378
        bs_write_ue( s, i_mb_i_offset + 1 + x264_mb_pred_mode16x16_fix[h->mb.i_intra16x16_pred_mode] +
Laurent Aimar's avatar
Laurent Aimar committed
379
                        h->mb.i_cbp_chroma * 4 + ( h->mb.i_cbp_luma == 0 ? 0 : 12 ) );
380
        bs_write_ue( s, x264_mb_pred_mode8x8c_fix[ h->mb.i_chroma_pred_mode ] );
Laurent Aimar's avatar
Laurent Aimar committed
381 382 383
    }
    else if( i_mb_type == P_L0 )
    {
384
        DECLARE_ALIGNED_4( int16_t mvp[2] );
Laurent Aimar's avatar
Laurent Aimar committed
385 386 387

        if( h->mb.i_partition == D_16x16 )
        {
Fiona Glaser's avatar
Fiona Glaser committed
388
            bs_write1( s, 1 );
Laurent Aimar's avatar
Laurent Aimar committed
389

390 391
            if( h->mb.pic.i_fref[0] > 1 )
                bs_write_te( s, h->mb.pic.i_fref[0] - 1, h->mb.cache.ref[0][x264_scan8[0]] );
Laurent Aimar's avatar
Laurent Aimar committed
392 393 394 395 396 397 398
            x264_mb_predict_mv( h, 0, 0, 4, mvp );
            bs_write_se( s, h->mb.cache.mv[0][x264_scan8[0]][0] - mvp[0] );
            bs_write_se( s, h->mb.cache.mv[0][x264_scan8[0]][1] - mvp[1] );
        }
        else if( h->mb.i_partition == D_16x8 )
        {
            bs_write_ue( s, 1 );
399
            if( h->mb.pic.i_fref[0] > 1 )
Laurent Aimar's avatar
Laurent Aimar committed
400
            {
401 402
                bs_write_te( s, h->mb.pic.i_fref[0] - 1, h->mb.cache.ref[0][x264_scan8[0]] );
                bs_write_te( s, h->mb.pic.i_fref[0] - 1, h->mb.cache.ref[0][x264_scan8[8]] );
Laurent Aimar's avatar
Laurent Aimar committed
403 404 405 406 407 408 409 410 411 412 413 414 415
            }

            x264_mb_predict_mv( h, 0, 0, 4, mvp );
            bs_write_se( s, h->mb.cache.mv[0][x264_scan8[0]][0] - mvp[0] );
            bs_write_se( s, h->mb.cache.mv[0][x264_scan8[0]][1] - mvp[1] );

            x264_mb_predict_mv( h, 0, 8, 4, mvp );
            bs_write_se( s, h->mb.cache.mv[0][x264_scan8[8]][0] - mvp[0] );
            bs_write_se( s, h->mb.cache.mv[0][x264_scan8[8]][1] - mvp[1] );
        }
        else if( h->mb.i_partition == D_8x16 )
        {
            bs_write_ue( s, 2 );
416
            if( h->mb.pic.i_fref[0] > 1 )
Laurent Aimar's avatar
Laurent Aimar committed
417
            {
418 419
                bs_write_te( s, h->mb.pic.i_fref[0] - 1, h->mb.cache.ref[0][x264_scan8[0]] );
                bs_write_te( s, h->mb.pic.i_fref[0] - 1, h->mb.cache.ref[0][x264_scan8[4]] );
Laurent Aimar's avatar
Laurent Aimar committed
420 421 422 423 424 425 426 427 428 429 430 431 432
            }

            x264_mb_predict_mv( h, 0, 0, 2, mvp );
            bs_write_se( s, h->mb.cache.mv[0][x264_scan8[0]][0] - mvp[0] );
            bs_write_se( s, h->mb.cache.mv[0][x264_scan8[0]][1] - mvp[1] );

            x264_mb_predict_mv( h, 0, 4, 2, mvp );
            bs_write_se( s, h->mb.cache.mv[0][x264_scan8[4]][0] - mvp[0] );
            bs_write_se( s, h->mb.cache.mv[0][x264_scan8[4]][1] - mvp[1] );
        }
    }
    else if( i_mb_type == P_8x8 )
    {
Fiona Glaser's avatar
Fiona Glaser committed
433
        int b_sub_ref;
Fiona Glaser's avatar
Fiona Glaser committed
434 435
        if( (h->mb.cache.ref[0][x264_scan8[0]] | h->mb.cache.ref[0][x264_scan8[ 4]] |
             h->mb.cache.ref[0][x264_scan8[8]] | h->mb.cache.ref[0][x264_scan8[12]]) == 0 )
Laurent Aimar's avatar
Laurent Aimar committed
436 437
        {
            bs_write_ue( s, 4 );
Fiona Glaser's avatar
Fiona Glaser committed
438
            b_sub_ref = 0;
Laurent Aimar's avatar
Laurent Aimar committed
439 440 441 442
        }
        else
        {
            bs_write_ue( s, 3 );
Fiona Glaser's avatar
Fiona Glaser committed
443
            b_sub_ref = 1;
Laurent Aimar's avatar
Laurent Aimar committed
444
        }
Fiona Glaser's avatar
Fiona Glaser committed
445

Laurent Aimar's avatar
Laurent Aimar committed
446
        /* sub mb type */
Fiona Glaser's avatar
Fiona Glaser committed
447 448 449 450 451 452
        if( h->param.analyse.inter & X264_ANALYSE_PSUB8x8 )
            for( i = 0; i < 4; i++ )
                bs_write_ue( s, sub_mb_type_p_to_golomb[ h->mb.i_sub_partition[i] ] );
        else
            bs_write( s, 4, 0xf );

Laurent Aimar's avatar
Laurent Aimar committed
453
        /* ref0 */
Fiona Glaser's avatar
Fiona Glaser committed
454
        if( b_sub_ref )
Laurent Aimar's avatar
Laurent Aimar committed
455
        {
456 457 458 459
            bs_write_te( s, h->mb.pic.i_fref[0] - 1, h->mb.cache.ref[0][x264_scan8[0]] );
            bs_write_te( s, h->mb.pic.i_fref[0] - 1, h->mb.cache.ref[0][x264_scan8[4]] );
            bs_write_te( s, h->mb.pic.i_fref[0] - 1, h->mb.cache.ref[0][x264_scan8[8]] );
            bs_write_te( s, h->mb.pic.i_fref[0] - 1, h->mb.cache.ref[0][x264_scan8[12]] );
Laurent Aimar's avatar
Laurent Aimar committed
460
        }
461

462 463
        for( i = 0; i < 4; i++ )
            cavlc_mb8x8_mvd( h, s, 0, i );
464 465 466 467 468 469 470 471
    }
    else if( i_mb_type == B_8x8 )
    {
        bs_write_ue( s, 22 );

        /* sub mb type */
        for( i = 0; i < 4; i++ )
            bs_write_ue( s, sub_mb_type_b_to_golomb[ h->mb.i_sub_partition[i] ] );
Fiona Glaser's avatar
Fiona Glaser committed
472

473
        /* ref */
Fiona Glaser's avatar
Fiona Glaser committed
474 475 476 477 478 479 480 481
        if( h->mb.pic.i_fref[0] > 1 )
            for( i = 0; i < 4; i++ )
                if( x264_mb_partition_listX_table[0][ h->mb.i_sub_partition[i] ] )
                    bs_write_te( s, h->mb.pic.i_fref[0] - 1, h->mb.cache.ref[0][x264_scan8[i*4]] );
        if( h->mb.pic.i_fref[1] > 1 )
            for( i = 0; i < 4; i++ )
                if( x264_mb_partition_listX_table[1][ h->mb.i_sub_partition[i] ] )
                    bs_write_te( s, h->mb.pic.i_fref[1] - 1, h->mb.cache.ref[1][x264_scan8[i*4]] );
Fiona Glaser's avatar
Fiona Glaser committed
482

483
        /* mvd */
484 485 486 487
        for( i = 0; i < 4; i++ )
            cavlc_mb8x8_mvd( h, s, 0, i );
        for( i = 0; i < 4; i++ )
            cavlc_mb8x8_mvd( h, s, 1, i );
Laurent Aimar's avatar
Laurent Aimar committed
488 489 490 491 492 493
    }
    else if( i_mb_type != B_DIRECT )
    {
        /* All B mode */
        /* Motion Vector */
        int i_list;
494
        DECLARE_ALIGNED_4( int16_t mvp[2] );
495
        const uint8_t (*b_list)[2] = x264_mb_type_list_table[i_mb_type];
Laurent Aimar's avatar
Laurent Aimar committed
496

Loren Merritt's avatar
Loren Merritt committed
497
        bs_write_ue( s, mb_type_b_to_golomb[ h->mb.i_partition - D_16x8 ][ i_mb_type - B_L0_L0 ] );
Laurent Aimar's avatar
Laurent Aimar committed
498 499 500

        for( i_list = 0; i_list < 2; i_list++ )
        {
Fiona Glaser's avatar
Fiona Glaser committed
501
            const int i_ref_max = (i_list == 0 ? h->mb.pic.i_fref[0] : h->mb.pic.i_fref[1]) - 1;
Laurent Aimar's avatar
Laurent Aimar committed
502

Fiona Glaser's avatar
Fiona Glaser committed
503
            if( i_ref_max )
Laurent Aimar's avatar
Laurent Aimar committed
504 505 506
                switch( h->mb.i_partition )
                {
                    case D_16x16:
Fiona Glaser's avatar
Fiona Glaser committed
507
                        if( b_list[i_list][0] ) bs_write_te( s, i_ref_max, h->mb.cache.ref[i_list][x264_scan8[0]] );
Laurent Aimar's avatar
Laurent Aimar committed
508 509
                        break;
                    case D_16x8:
Fiona Glaser's avatar
Fiona Glaser committed
510 511
                        if( b_list[i_list][0] ) bs_write_te( s, i_ref_max, h->mb.cache.ref[i_list][x264_scan8[0]] );
                        if( b_list[i_list][1] ) bs_write_te( s, i_ref_max, h->mb.cache.ref[i_list][x264_scan8[8]] );
Laurent Aimar's avatar
Laurent Aimar committed
512 513
                        break;
                    case D_8x16:
Fiona Glaser's avatar
Fiona Glaser committed
514 515
                        if( b_list[i_list][0] ) bs_write_te( s, i_ref_max, h->mb.cache.ref[i_list][x264_scan8[0]] );
                        if( b_list[i_list][1] ) bs_write_te( s, i_ref_max, h->mb.cache.ref[i_list][x264_scan8[4]] );
Laurent Aimar's avatar
Laurent Aimar committed
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562
                        break;
                }
        }
        for( i_list = 0; i_list < 2; i_list++ )
        {
            switch( h->mb.i_partition )
            {
                case D_16x16:
                    if( b_list[i_list][0] )
                    {
                        x264_mb_predict_mv( h, i_list, 0, 4, mvp );
                        bs_write_se( s, h->mb.cache.mv[i_list][x264_scan8[0]][0] - mvp[0] );
                        bs_write_se( s, h->mb.cache.mv[i_list][x264_scan8[0]][1] - mvp[1] );
                    }
                    break;
                case D_16x8:
                    if( b_list[i_list][0] )
                    {
                        x264_mb_predict_mv( h, i_list, 0, 4, mvp );
                        bs_write_se( s, h->mb.cache.mv[i_list][x264_scan8[0]][0] - mvp[0] );
                        bs_write_se( s, h->mb.cache.mv[i_list][x264_scan8[0]][1] - mvp[1] );
                    }
                    if( b_list[i_list][1] )
                    {
                        x264_mb_predict_mv( h, i_list, 8, 4, mvp );
                        bs_write_se( s, h->mb.cache.mv[i_list][x264_scan8[8]][0] - mvp[0] );
                        bs_write_se( s, h->mb.cache.mv[i_list][x264_scan8[8]][1] - mvp[1] );
                    }
                    break;
                case D_8x16:
                    if( b_list[i_list][0] )
                    {
                        x264_mb_predict_mv( h, i_list, 0, 2, mvp );
                        bs_write_se( s, h->mb.cache.mv[i_list][x264_scan8[0]][0] - mvp[0] );
                        bs_write_se( s, h->mb.cache.mv[i_list][x264_scan8[0]][1] - mvp[1] );
                    }
                    if( b_list[i_list][1] )
                    {
                        x264_mb_predict_mv( h, i_list, 4, 2, mvp );
                        bs_write_se( s, h->mb.cache.mv[i_list][x264_scan8[4]][0] - mvp[0] );
                        bs_write_se( s, h->mb.cache.mv[i_list][x264_scan8[4]][1] - mvp[1] );
                    }
                    break;
            }
        }
    }
    else if( i_mb_type == B_DIRECT )
Fiona Glaser's avatar
Fiona Glaser committed
563
        bs_write1( s, 1 );
Laurent Aimar's avatar
Laurent Aimar committed
564 565
    else
    {
566
        x264_log(h, X264_LOG_ERROR, "invalid/unhandled mb_type\n" );
Laurent Aimar's avatar
Laurent Aimar committed
567 568 569
        return;
    }

Fiona Glaser's avatar
Fiona Glaser committed
570
#if !RDO_SKIP_BS
571
    i_mb_pos_tex = bs_pos( s );
572
    h->stat.frame.i_mv_bits += i_mb_pos_tex - i_mb_pos_start;
573
#endif
574

Laurent Aimar's avatar
Laurent Aimar committed
575
    /* Coded block patern */
576
    if( i_mb_type == I_4x4 || i_mb_type == I_8x8 )
Laurent Aimar's avatar
Laurent Aimar committed
577 578 579 580
        bs_write_ue( s, intra4x4_cbp_to_golomb[( h->mb.i_cbp_chroma << 4 )|h->mb.i_cbp_luma] );
    else if( i_mb_type != I_16x16 )
        bs_write_ue( s, inter_cbp_to_golomb[( h->mb.i_cbp_chroma << 4 )|h->mb.i_cbp_luma] );

581
    /* transform size 8x8 flag */
582
    if( x264_mb_transform_8x8_allowed( h ) && h->mb.i_cbp_luma )
583 584
        bs_write1( s, h->mb.b_transform_8x8 );

Laurent Aimar's avatar
Laurent Aimar committed
585 586 587
    /* write residual */
    if( i_mb_type == I_16x16 )
    {
588
        cavlc_qp_delta( h, s );
Laurent Aimar's avatar
Laurent Aimar committed
589 590

        /* DC Luma */
591
        block_residual_write_cavlc( h, s, DCT_LUMA_DC, 24 , h->dct.luma16x16_dc );
Laurent Aimar's avatar
Laurent Aimar committed
592

593
        /* AC Luma */
Fiona Glaser's avatar
Fiona Glaser committed
594
        if( h->mb.i_cbp_luma )
Laurent Aimar's avatar
Laurent Aimar committed
595
            for( i = 0; i < 16; i++ )
596
                block_residual_write_cavlc( h, s, DCT_LUMA_AC, i, h->dct.luma4x4[i]+1 );
Laurent Aimar's avatar
Laurent Aimar committed
597
    }
Fiona Glaser's avatar
Fiona Glaser committed
598
    else if( h->mb.i_cbp_luma | h->mb.i_cbp_chroma )
Laurent Aimar's avatar
Laurent Aimar committed
599
    {
600
        cavlc_qp_delta( h, s );
601
        x264_macroblock_luma_write_cavlc( h, s, 0, 3 );
Laurent Aimar's avatar
Laurent Aimar committed
602
    }
Fiona Glaser's avatar
Fiona Glaser committed
603
    if( h->mb.i_cbp_chroma )
Laurent Aimar's avatar
Laurent Aimar committed
604 605
    {
        /* Chroma DC residual present */
606 607
        block_residual_write_cavlc( h, s, DCT_CHROMA_DC, 25, h->dct.chroma_dc[0] );
        block_residual_write_cavlc( h, s, DCT_CHROMA_DC, 26, h->dct.chroma_dc[1] );
Laurent Aimar's avatar
Laurent Aimar committed
608
        if( h->mb.i_cbp_chroma&0x02 ) /* Chroma AC residual present */
Loren Merritt's avatar
Loren Merritt committed
609
            for( i = 16; i < 24; i++ )
610
                block_residual_write_cavlc( h, s, DCT_CHROMA_AC, i, h->dct.luma4x4[i]+1 );
Laurent Aimar's avatar
Laurent Aimar committed
611
    }
612

Fiona Glaser's avatar
Fiona Glaser committed
613
#if !RDO_SKIP_BS
614
    h->stat.frame.i_tex_bits += bs_pos(s) - i_mb_pos_tex;
615
#endif
Laurent Aimar's avatar
Laurent Aimar committed
616
}
617

Fiona Glaser's avatar
Fiona Glaser committed
618
#if RDO_SKIP_BS
619 620 621
/*****************************************************************************
 * RD only; doesn't generate a valid bitstream
 * doesn't write cbp or chroma dc (I don't know how much this matters)
622
 * doesn't write ref or subpartition (never varies between calls, so no point in doing so)
623 624 625
 * works on all partition sizes except 16x16
 * for sub8x8, call once per 8x8 block
 *****************************************************************************/
Loic Le Loarer's avatar
Loic Le Loarer committed
626
static int x264_partition_size_cavlc( x264_t *h, int i8, int i_pixel )
627 628
{
    const int i_mb_type = h->mb.i_type;
629
    int b_8x16 = h->mb.i_partition == D_8x16;
630
    int j;
631
    h->out.bs.i_bits_encoded = 0;
632 633

    if( i_mb_type == P_8x8 )
634
        cavlc_mb8x8_mvd( h, &h->out.bs, 0, i8 );
635
    else if( i_mb_type == P_L0 )
636
        cavlc_mb_mvd( h, &h->out.bs, 0, 4*i8, 4>>b_8x16 );
637
    else if( i_mb_type > B_DIRECT && i_mb_type < B_8x8 )
638
    {
639 640
        if( x264_mb_type_list_table[ i_mb_type ][0][!!i8] ) cavlc_mb_mvd( h, &h->out.bs, 0, 4*i8, 4>>b_8x16 );
        if( x264_mb_type_list_table[ i_mb_type ][1][!!i8] ) cavlc_mb_mvd( h, &h->out.bs, 1, 4*i8, 4>>b_8x16 );
641 642 643
    }
    else if( i_mb_type == B_8x8 )
    {
644 645
        cavlc_mb8x8_mvd( h, &h->out.bs, 0, i8 );
        cavlc_mb8x8_mvd( h, &h->out.bs, 1, i8 );
646 647 648 649 650 651 652 653 654
    }
    else
    {
        x264_log(h, X264_LOG_ERROR, "invalid/unhandled mb_type\n" );
        return 0;
    }

    for( j = (i_pixel < PIXEL_8x8); j >= 0; j-- )
    {
655 656 657
        x264_macroblock_luma_write_cavlc( h, &h->out.bs, i8, i8 );
        block_residual_write_cavlc( h, &h->out.bs, DCT_CHROMA_AC, 16+i8, h->dct.luma4x4[16+i8]+1 );
        block_residual_write_cavlc( h, &h->out.bs, DCT_CHROMA_AC, 20+i8, h->dct.luma4x4[20+i8]+1 );
658 659 660
        i8 += x264_pixel_size[i_pixel].h >> 3;
    }

661
    return h->out.bs.i_bits_encoded;
662 663
}

Fiona Glaser's avatar
Fiona Glaser committed
664 665 666
static int x264_subpartition_size_cavlc( x264_t *h, int i4, int i_pixel )
{
    int b_8x4 = i_pixel == PIXEL_8x4;
667 668 669
    h->out.bs.i_bits_encoded = 0;
    cavlc_mb_mvd( h, &h->out.bs, 0, i4, 1+b_8x4 );
    block_residual_write_cavlc( h, &h->out.bs, DCT_LUMA_4x4, i4, h->dct.luma4x4[i4] );
Fiona Glaser's avatar
Fiona Glaser committed
670 671 672
    if( i_pixel != PIXEL_4x4 )
    {
        i4 += 2-b_8x4;
673
        block_residual_write_cavlc( h, &h->out.bs, DCT_LUMA_4x4, i4, h->dct.luma4x4[i4] );
Fiona Glaser's avatar
Fiona Glaser committed
674 675
    }

676
    return h->out.bs.i_bits_encoded;
Fiona Glaser's avatar
Fiona Glaser committed
677 678
}

679 680 681 682 683 684 685 686 687 688 689
static int cavlc_intra4x4_pred_size( x264_t *h, int i4, int i_mode )
{
    if( x264_mb_predict_intra4x4_mode( h, i4 ) == x264_mb_pred_mode4x4_fix( i_mode ) )
        return 1;
    else
        return 4;
}

static int x264_partition_i8x8_size_cavlc( x264_t *h, int i8, int i_mode )
{
    h->out.bs.i_bits_encoded = cavlc_intra4x4_pred_size( h, 4*i8, i_mode );
690 691
    bs_write_ue( &h->out.bs, intra4x4_cbp_to_golomb[( h->mb.i_cbp_chroma << 4 )|h->mb.i_cbp_luma] );
    x264_macroblock_luma_write_cavlc( h, &h->out.bs, i8, i8 );
692 693 694 695 696 697
    return h->out.bs.i_bits_encoded;
}

static int x264_partition_i4x4_size_cavlc( x264_t *h, int i4, int i_mode )
{
    h->out.bs.i_bits_encoded = cavlc_intra4x4_pred_size( h, i4, i_mode );
698
    block_residual_write_cavlc( h, &h->out.bs, DCT_LUMA_4x4, i4, h->dct.luma4x4[i4] );
699 700
    return h->out.bs.i_bits_encoded;
}
701 702 703 704

static int x264_i8x8_chroma_size_cavlc( x264_t *h )
{
    h->out.bs.i_bits_encoded = bs_size_ue( x264_mb_pred_mode8x8c_fix[ h->mb.i_chroma_pred_mode ] );
Fiona Glaser's avatar
Fiona Glaser committed
705
    if( h->mb.i_cbp_chroma )
706
    {
707 708
        block_residual_write_cavlc( h, &h->out.bs, DCT_CHROMA_DC, 25, h->dct.chroma_dc[0] );
        block_residual_write_cavlc( h, &h->out.bs, DCT_CHROMA_DC, 26, h->dct.chroma_dc[1] );
709 710 711 712

        if( h->mb.i_cbp_chroma == 2 )
        {
            int i;
Loren Merritt's avatar
Loren Merritt committed
713
            for( i = 16; i < 24; i++ )
714
                block_residual_write_cavlc( h, &h->out.bs, DCT_CHROMA_AC, i, h->dct.luma4x4[i]+1 );
715 716 717 718
        }
    }
    return h->out.bs.i_bits_encoded;
}
719
#endif