blob: 2aec815ad64c9003da2b4faa77104e12bff816c4 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
/******************************************************************************
*
* This software module was originally developed by
*
* Robert Danielsen (Telenor / ACTS-MoMuSys).
*
* and edited by
*
* Luis Ducla-Soares (IST / ACTS-MoMuSys).
* Cor Quist (KPN / ACTS-MoMuSys).
*
* in the course of development of the MPEG-4 Video (ISO/IEC 14496-2) standard.
* This software module is an implementation of a part of one or more MPEG-4
* Video (ISO/IEC 14496-2) tools as specified by the MPEG-4 Video (ISO/IEC
* 14496-2) standard.
*
* ISO/IEC gives users of the MPEG-4 Video (ISO/IEC 14496-2) standard free
* license to this software module or modifications thereof for use in hardware
* or software products claiming conformance to the MPEG-4 Video (ISO/IEC
* 14496-2) standard.
*
* Those intending to use this software module in hardware or software products
* are advised that its use may infringe existing patents. The original
* developer of this software module and his/her company, the subsequent
* editors and their companies, and ISO/IEC have no liability for use of this
* software module or modifications thereof in an implementation. Copyright is
* not released for non MPEG-4 Video (ISO/IEC 14496-2) standard conforming
* products.
*
* ACTS-MoMuSys partners retain full right to use the code for his/her own
* purpose, assign or donate the code to a third party and to inhibit third
* parties from using the code for non MPEG-4 Video (ISO/IEC 14496-2) standard
* conforming products. This copyright notice must be included in all copies or
* derivative works.
*
* Copyright (c) 1997
*
*****************************************************************************/
/***********************************************************HeaderBegin*******
*
* File: putvlc.c
*
* Author: Robert Danielsen, Telenor R&D
* Created: 07.07.96
*
* Description: Functions for writing to bitstream
*
* Notes: Same kind of tables as in the MPEG-2 software simulation
* group software.
*
* Modified:
* 28.10.96 Robert Danielsen: Added PutCoeff_Intra(), renamed
* PutCoeff() to PutCoeff_Inter().
* 06.11.96 Robert Danielsen: Added PutMCBPC_sep()
* 01.05.97 Luis Ducla-Soares: added PutCoeff_Intra_RVLC() and
* PutCoeff_Inter_RVLC().
*
***********************************************************HeaderEnd*********/
/************************ INCLUDE FILES ********************************/
#include "mp4lib_int.h"
#include "mp4enc_lib.h"
#include "vlc_enc_tab.h"
#include "bitstream_io.h"
#include "m4venc_oscl.h"
#include "vlc_encode_inline.h"
typedef void (*BlockCodeCoeffPtr)(RunLevelBlock*, BitstreamEncVideo*, Int, Int, UChar) ;
const static Int mode_MBtype[] =
{
3,
0,
4,
1,
2,
};
const static Int zigzag_inv[NCOEFF_BLOCK] =
{
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
};
/* Horizontal zigzag inverse */
const static Int zigzag_h_inv[NCOEFF_BLOCK] =
{
0, 1, 2, 3, 8, 9, 16, 17,
10, 11, 4, 5, 6, 7, 15, 14,
13, 12, 19, 18, 24, 25, 32, 33,
26, 27, 20, 21, 22, 23, 28, 29,
30, 31, 34, 35, 40, 41, 48, 49,
42, 43, 36, 37, 38, 39, 44, 45,
46, 47, 50, 51, 56, 57, 58, 59,
52, 53, 54, 55, 60, 61, 62, 63
};
/* Vertical zigzag inverse */
const static Int zigzag_v_inv[NCOEFF_BLOCK] =
{
0, 8, 16, 24, 1, 9, 2, 10,
17, 25, 32, 40, 48, 56, 57, 49,
41, 33, 26, 18, 3, 11, 4, 12,
19, 27, 34, 42, 50, 58, 35, 43,
51, 59, 20, 28, 5, 13, 6, 14,
21, 29, 36, 44, 52, 60, 37, 45,
53, 61, 22, 30, 7, 15, 23, 31,
38, 46, 54, 62, 39, 47, 55, 63
};
#ifdef __cplusplus
extern "C"
{
#endif
Int PutCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutCBPY(Int cbpy, Char intra, BitstreamEncVideo *bitstream);
Int PutMCBPC_Inter(Int cbpc, Int mode, BitstreamEncVideo *bitstream);
Int PutMCBPC_Intra(Int cbpc, Int mode, BitstreamEncVideo *bitstream);
Int PutMV(Int mvint, BitstreamEncVideo *bitstream);
Int PutDCsize_chrom(Int size, BitstreamEncVideo *bitstream);
Int PutDCsize_lum(Int size, BitstreamEncVideo *bitstream);
Int PutDCsize_lum(Int size, BitstreamEncVideo *bitstream);
#ifndef NO_RVLC
Int PutCoeff_Inter_RVLC(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutCoeff_Inter_RVLC_Last(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutCoeff_Intra_RVLC(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutCoeff_Intra_RVLC_Last(Int run, Int level, BitstreamEncVideo *bitstream);
#endif
Int PutRunCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutRunCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutRunCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutRunCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutLevelCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutLevelCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutLevelCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream);
Int PutLevelCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream);
void RunLevel(VideoEncData *video, Int intra, Int intraDC_decision, Int ncoefblck[]);
Int IntraDC_dpcm(Int val, Int lum, BitstreamEncVideo *bitstream);
Void DCACPred(VideoEncData *video, UChar Mode, Int *intraDC_decision, Int intraDCVlcQP);
Void find_pmvs(VideoEncData *video, Int block, Int *mvx, Int *mvy);
Void WriteMVcomponent(Int f_code, Int dmv, BitstreamEncVideo *bs);
static Bool IntraDCSwitch_Decision(Int Mode, Int intra_dc_vlc_threshold, Int intraDCVlcQP);
Void ScaleMVD(Int f_code, Int diff_vector, Int *residual, Int *vlc_code_mag);
#ifdef __cplusplus
}
#endif
Int
PutDCsize_lum(Int size, BitstreamEncVideo *bitstream)
{
Int length;
if (!(size >= 0 && size < 13))
return -1;
length = DCtab_lum[size].len;
if (length)
BitstreamPutBits(bitstream, length, DCtab_lum[size].code);
return length;
}
Int
PutDCsize_chrom(Int size, BitstreamEncVideo *bitstream)
{
Int length;
if (!(size >= 0 && size < 13))
return -1;
length = DCtab_chrom[size].len;
if (length)
BitstreamPutBits(bitstream, length, DCtab_chrom[size].code);
return length;
}
Int
PutMV(Int mvint, BitstreamEncVideo *bitstream)
{
Int sign = 0;
Int absmv;
Int length;
if (mvint > 32)
{
absmv = -mvint + 65;
sign = 1;
}
else
absmv = mvint;
length = mvtab[absmv].len;
if (length)
BitstreamPutBits(bitstream, length, mvtab[absmv].code);
if (mvint != 0)
{
BitstreamPut1Bits(bitstream, sign);
return (length + 1);
}
else
return length;
}
Int
PutMCBPC_Intra(Int cbp, Int mode, BitstreamEncVideo *bitstream)
{
Int ind;
Int length;
ind = ((mode_MBtype[mode] >> 1) & 3) | ((cbp & 3) << 2);
length = mcbpc_intra_tab[ind].len;
if (length)
BitstreamPutBits(bitstream, length, mcbpc_intra_tab[ind].code);
return length;
}
Int
PutMCBPC_Inter(Int cbp, Int mode, BitstreamEncVideo *bitstream)
{
Int ind;
Int length;
ind = (mode_MBtype[mode] & 7) | ((cbp & 3) << 3);
length = mcbpc_inter_tab[ind].len;
if (length)
BitstreamPutBits(bitstream, length, mcbpc_inter_tab[ind].code);
return length;
}
Int
PutCBPY(Int cbpy, Char intra, BitstreamEncVideo *bitstream)
{
Int ind;
Int length;
if (intra == 0)
cbpy = 15 - cbpy;
ind = cbpy;
length = cbpy_tab[ind].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)cbpy_tab[ind].code);
return length;
}
/* 5/16/01, break up function for last and not-last coefficient */
/* Note:::: I checked the ARM assembly for if( run > x && run < y) type
of code, they do a really good job compiling it to if( (UInt)(run-x) < y-x).
No need to hand-code it!!!!!, 6/1/2001 */
Int PutCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run < 2 && level < 13)
{
length = coeff_tab0[run][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_tab0[run][level-1].code);
}
else if (run > 1 && run < 27 && level < 5)
{
length = coeff_tab1[run-2][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_tab1[run-2][level-1].code);
}
return length;
}
Int PutCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run < 2 && level < 4)
{
length = coeff_tab2[run][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_tab2[run][level-1].code);
}
else if (run > 1 && run < 42 && level == 1)
{
length = coeff_tab3[run-2].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_tab3[run-2].code);
}
return length;
}
/* 5/16/01, break up function for last and not-last coefficient */
Int PutCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run == 0 && level < 28)
{
length = coeff_tab4[level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_tab4[level-1].code);
}
else if (run == 1 && level < 11)
{
length = coeff_tab5[level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_tab5[level-1].code);
}
else if (run > 1 && run < 10 && level < 6)
{
length = coeff_tab6[run-2][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_tab6[run-2][level-1].code);
}
else if (run > 9 && run < 15 && level == 1)
{
length = coeff_tab7[run-10].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_tab7[run-10].code);
}
return length;
}
Int PutCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run == 0 && level < 9)
{
length = coeff_tab8[level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_tab8[level-1].code);
}
else if (run > 0 && run < 7 && level < 4)
{
length = coeff_tab9[run-1][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_tab9[run-1][level-1].code);
}
else if (run > 6 && run < 21 && level == 1)
{
length = coeff_tab10[run-7].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_tab10[run-7].code);
}
return length;
}
/* 5/16/01, break up function for last and not-last coefficient */
#ifndef NO_RVLC
Int PutCoeff_Inter_RVLC(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run == 0 && level < 20)
{
length = coeff_RVLCtab14[level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab14[level-1].code);
}
else if (run == 1 && level < 11)
{
length = coeff_RVLCtab15[level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab15[level-1].code);
}
else if (run > 1 && run < 4 && level < 8)
{
length = coeff_RVLCtab16[run-2][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab16[run-2][level-1].code);
}
else if (run == 4 && level < 6)
{
length = coeff_RVLCtab17[level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab17[level-1].code);
}
else if (run > 4 && run < 8 && level < 5)
{
length = coeff_RVLCtab18[run-5][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab18[run-5][level-1].code);
}
else if (run > 7 && run < 10 && level < 4)
{
length = coeff_RVLCtab19[run-8][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab19[run-8][level-1].code);
}
else if (run > 9 && run < 18 && level < 3)
{
length = coeff_RVLCtab20[run-10][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab20[run-10][level-1].code);
}
else if (run > 17 && run < 39 && level == 1)
{
length = coeff_RVLCtab21[run-18].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab21[run-18].code);
}
return length;
}
Int PutCoeff_Inter_RVLC_Last(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run >= 0 && run < 2 && level < 6)
{
length = coeff_RVLCtab22[run][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab22[run][level-1].code);
}
else if (run == 2 && level < 4)
{
length = coeff_RVLCtab23[level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab23[level-1].code);
}
else if (run > 2 && run < 14 && level < 3)
{
length = coeff_RVLCtab24[run-3][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab24[run-3][level-1].code);
}
else if (run > 13 && run < 45 && level == 1)
{
length = coeff_RVLCtab25[run-14].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab25[run-14].code);
}
return length;
}
/* 5/16/01, break up function for last and not-last coefficient */
Int PutCoeff_Intra_RVLC(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run == 0 && level < 28)
{
length = coeff_RVLCtab1[level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab1[level-1].code);
}
else if (run == 1 && level < 14)
{
length = coeff_RVLCtab2[level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab2[level-1].code);
}
else if (run == 2 && level < 12)
{
length = coeff_RVLCtab3[level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab3[level-1].code);
}
else if (run == 3 && level < 10)
{
length = coeff_RVLCtab4[level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab4[level-1].code);
}
else if (run > 3 && run < 6 && level < 7)
{
length = coeff_RVLCtab5[run-4][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab5[run-4][level-1].code);
}
else if (run > 5 && run < 8 && level < 6)
{
length = coeff_RVLCtab6[run-6][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab6[run-6][level-1].code);
}
else if (run > 7 && run < 10 && level < 5)
{
length = coeff_RVLCtab7[run-8][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab7[run-8][level-1].code);
}
else if (run > 9 && run < 13 && level < 3)
{
length = coeff_RVLCtab8[run-10][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab8[run-10][level-1].code);
}
else if (run > 12 && run < 20 && level == 1)
{
length = coeff_RVLCtab9[run-13].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab9[run-13].code);
}
return length;
}
Int PutCoeff_Intra_RVLC_Last(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run >= 0 && run < 2 && level < 6)
{
length = coeff_RVLCtab10[run][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab10[run][level-1].code);
}
else if (run == 2 && level < 4)
{
length = coeff_RVLCtab11[level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab11[level-1].code);
}
else if (run > 2 && run < 14 && level < 3)
{
length = coeff_RVLCtab12[run-3][level-1].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab12[run-3][level-1].code);
}
else if (run > 13 && run < 45 && level == 1)
{
length = coeff_RVLCtab13[run-14].len;
if (length)
BitstreamPutBits(bitstream, length, (UInt)coeff_RVLCtab13[run-14].code);
}
return length;
}
#endif
/* The following is for 3-mode VLC */
Int
PutRunCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run < 2 && level < 13)
{
length = coeff_tab0[run][level-1].len;
if (length)
{
BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
//BitstreamPutBits(bitstream, 2, 2);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab0[run][level-1].code);
length += 9;
}
}
else if (run > 1 && run < 27 && level < 5)
{
length = coeff_tab1[run-2][level-1].len;
if (length)
{
BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
//BitstreamPutBits(bitstream, 2, 2);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab1[run-2][level-1].code);
length += 9;
}
}
return length;
}
Int PutRunCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run < 2 && level < 4)
{
length = coeff_tab2[run][level-1].len;
if (length)
{
BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
//BitstreamPutBits(bitstream, 2, 2);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab2[run][level-1].code);
length += 9;
}
}
else if (run > 1 && run < 42 && level == 1)
{
length = coeff_tab3[run-2].len;
if (length)
{
BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
//BitstreamPutBits(bitstream, 2, 2);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab3[run-2].code);
length += 9;
}
}
return length;
}
Int PutRunCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run == 0 && level < 28)
{
length = coeff_tab4[level-1].len;
if (length)
{
BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
//BitstreamPutBits(bitstream, 2, 2);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab4[level-1].code);
length += 9;
}
}
else if (run == 1 && level < 11)
{
length = coeff_tab5[level-1].len;
if (length)
{
BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
//BitstreamPutBits(bitstream, 2, 2);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab5[level-1].code);
length += 9;
}
}
else if (run > 1 && run < 10 && level < 6)
{
length = coeff_tab6[run-2][level-1].len;
if (length)
{
BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
//BitstreamPutBits(bitstream, 2, 2);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab6[run-2][level-1].code);
length += 9;
}
}
else if (run > 9 && run < 15 && level == 1)
{
length = coeff_tab7[run-10].len;
if (length)
{
BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
//BitstreamPutBits(bitstream, 2, 2);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab7[run-10].code);
length += 9;
}
}
return length;
}
Int PutRunCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run == 0 && level < 9)
{
length = coeff_tab8[level-1].len;
if (length)
{
BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
//BitstreamPutBits(bitstream, 2, 2);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab8[level-1].code);
length += 9;
}
}
else if (run > 0 && run < 7 && level < 4)
{
length = coeff_tab9[run-1][level-1].len;
if (length)
{
BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
//BitstreamPutBits(bitstream, 2, 2);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab9[run-1][level-1].code);
length += 9;
}
}
else if (run > 6 && run < 21 && level == 1)
{
length = coeff_tab10[run-7].len;
if (length)
{
BitstreamPutGT8Bits(bitstream, 7 + 2, 14/*3*/);
//BitstreamPutBits(bitstream, 2, 2);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab10[run-7].code);
length += 9;
}
}
return length;
}
Int
PutLevelCoeff_Inter(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run < 2 && level < 13)
{
length = coeff_tab0[run][level-1].len;
if (length)
{
BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab0[run][level-1].code);
length += 8;
}
}
else if (run > 1 && run < 27 && level < 5)
{
length = coeff_tab1[run-2][level-1].len;
if (length)
{
BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab1[run-2][level-1].code);
length += 8;
}
}
return length;
}
Int PutLevelCoeff_Inter_Last(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run < 2 && level < 4)
{
length = coeff_tab2[run][level-1].len;
if (length)
{
BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab2[run][level-1].code);
length += 8;
}
}
else if (run > 1 && run < 42 && level == 1)
{
length = coeff_tab3[run-2].len;
if (length)
{
BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab3[run-2].code);
length += 8;
}
}
return length;
}
Int PutLevelCoeff_Intra(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run == 0 && level < 28)
{
length = coeff_tab4[level-1].len;
if (length)
{
BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab4[level-1].code);
length += 8;
}
}
else if (run == 1 && level < 11)
{
length = coeff_tab5[level-1].len;
if (length)
{
BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab5[level-1].code);
length += 8;
}
}
else if (run > 1 && run < 10 && level < 6)
{
length = coeff_tab6[run-2][level-1].len;
if (length)
{
BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab6[run-2][level-1].code);
length += 8;
}
}
else if (run > 9 && run < 15 && level == 1)
{
length = coeff_tab7[run-10].len;
if (length)
{
BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab7[run-10].code);
length += 8;
}
}
return length;
}
Int PutLevelCoeff_Intra_Last(Int run, Int level, BitstreamEncVideo *bitstream)
{
Int length = 0;
if (run == 0 && level < 9)
{
length = coeff_tab8[level-1].len;
if (length)
{
BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab8[level-1].code);
length += 8;
}
}
else if (run > 0 && run < 7 && level < 4)
{
length = coeff_tab9[run-1][level-1].len;
if (length)
{
BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab9[run-1][level-1].code);
length += 8;
}
}
else if (run > 6 && run < 21 && level == 1)
{
length = coeff_tab10[run-7].len;
if (length)
{
BitstreamPutBits(bitstream, 7 + 1, 6/*3*/);
BitstreamPutBits(bitstream, length, (UInt)coeff_tab10[run-7].code);
length += 8;
}
}
return length;
}
/* ======================================================================== */
/* Function : MBVlcEncode() */
/* Date : 09/10/2000 */
/* Purpose : Encode GOV Header */
/* In/out : */
/* Return : */
/* Modified : 5/21/01, break up into smaller functions */
/* ======================================================================== */
#ifndef H263_ONLY
/**************************************/
/* Data Partitioning I-VOP Encoding */
/**************************************/
void MBVlcEncodeDataPar_I_VOP(
VideoEncData *video,
Int ncoefblck[],
void *blkCodePtr)
{
BitstreamEncVideo *bs1 = video->bitstream1;
BitstreamEncVideo *bs2 = video->bitstream2;
BitstreamEncVideo *bs3 = video->bitstream3;
int i;
UChar Mode = video->headerInfo.Mode[video->mbnum];
UChar CBP;
// MacroBlock *MB=video->outputMB;
Int mbnum = video->mbnum;
Int intraDC_decision, DC;
// int temp;
Int dquant; /* 3/15/01 */
RunLevelBlock *RLB = video->RLB;
BlockCodeCoeffPtr BlockCodeCoeff = (BlockCodeCoeffPtr) blkCodePtr;
/* DC and AC Prediction, 5/28/01, compute CBP, intraDC_decision*/
DCACPred(video, Mode, &intraDC_decision, video->QP_prev);
/* CBP, Run, Level, and Sign */
RunLevel(video, 1, intraDC_decision, ncoefblck);
CBP = video->headerInfo.CBP[mbnum];
/* Compute DQuant */
dquant = video->QPMB[mbnum] - video->QP_prev; /* 3/15/01, QP_prev may not equal QPMB[mbnum-1] if mbnum-1 is skipped*/
video->QP_prev = video->QPMB[mbnum];
if (dquant && Mode == MODE_INTRA)
{
Mode = MODE_INTRA_Q;
}
if (dquant >= 0)
dquant = (PV_ABS(dquant) + 1);
else
dquant = (PV_ABS(dquant) - 1);
/* FIRST PART: ALL TO BS1 */
PutMCBPC_Intra(CBP, Mode, bs1); /* MCBPC */
if (Mode == MODE_INTRA_Q)
/* MAY NEED TO CHANGE DQUANT HERE */
BitstreamPutBits(bs1, 2, dquant); /* dquant*/
if (intraDC_decision == 0)
{
for (i = 0; i < 6; i++)
{
DC = video->RLB[i].level[0];
if (video->RLB[i].s[0])
DC = -DC;
if (i < 4)
/*temp =*/ IntraDC_dpcm(DC, 1, bs1); /* dct_dc_size_luminance, */
else /* dct_dc_differential, and */
/*temp =*/ IntraDC_dpcm(DC, 0, bs1); /* marker bit */
}
}
/* SECOND PART: ALL TO BS2*/
BitstreamPut1Bits(bs2, video->acPredFlag[video->mbnum]); /* ac_pred_flag */
/*temp=*/
PutCBPY(CBP >> 2, (Char)(1), bs2); /* cbpy */
/* THIRD PART: ALL TO BS3*/
/* MB_CodeCoeff(video,bs3); */ /* 5/22/01, replaced with below */
for (i = 0; i < 6; i++)
{
if (CBP&(1 << (5 - i)))
(*BlockCodeCoeff)(&(RLB[i]), bs3, 1 - intraDC_decision, ncoefblck[i], Mode);/* Code Intra AC*/
}
return ;
}
/************************************/
/* Data Partitioning P-VOP Encoding */
/************************************/
void MBVlcEncodeDataPar_P_VOP(
VideoEncData *video,
Int ncoefblck[],
void *blkCodePtr)
{
BitstreamEncVideo *bs1 = video->bitstream1;
BitstreamEncVideo *bs2 = video->bitstream2;
BitstreamEncVideo *bs3 = video->bitstream3;
int i;
Int mbnum = video->mbnum;
UChar Mode = video->headerInfo.Mode[mbnum];
Int QP_tmp = video->QPMB[mbnum];
UChar CBP;
// MacroBlock *MB=video->outputMB;
Int intra, intraDC_decision, DC;
Int pmvx, pmvy;
// int temp;
Int dquant; /* 3/15/01 */
RunLevelBlock *RLB = video->RLB;
BlockCodeCoeffPtr BlockCodeCoeff = (BlockCodeCoeffPtr) blkCodePtr;
intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
/* DC and AC Prediction, 5/28/01, compute CBP, intraDC_decision*/
if (intra)
{
if (video->usePrevQP)
{
QP_tmp = video->QPMB[mbnum-1];
}
DCACPred(video, Mode, &intraDC_decision, QP_tmp);
}
else
intraDC_decision = 0; /* used in RunLevel */
/* CBP, Run, Level, and Sign */
RunLevel(video, intra, intraDC_decision, ncoefblck);
CBP = video->headerInfo.CBP[mbnum];
/* Compute DQuant */
dquant = video->QPMB[mbnum] - video->QP_prev; /* 3/15/01, QP_prev may not equal QPMB[mbnum-1] if mbnum-1 is skipped*/
if (dquant && (Mode == MODE_INTRA || Mode == MODE_INTER))
{
Mode += 2; /* make it MODE_INTRA_Q and MODE_INTER_Q */
}
if (dquant >= 0)
dquant = (PV_ABS(dquant) + 1);
else
dquant = (PV_ABS(dquant) - 1);
/* FIRST PART: ALL TO BS1 */
if (CBP == 0 && intra == 0) /* Determine if Skipped MB */
{
if ((Mode == MODE_INTER) && (video->mot[mbnum][0].x == 0) && (video->mot[mbnum][0].y == 0))
Mode = video->headerInfo.Mode[video->mbnum] = MODE_SKIPPED;
else if ((Mode == MODE_INTER4V) && (video->mot[mbnum][1].x == 0) && (video->mot[mbnum][1].y == 0)
&& (video->mot[mbnum][2].x == 0) && (video->mot[mbnum][2].y == 0)
&& (video->mot[mbnum][3].x == 0) && (video->mot[mbnum][3].y == 0)
&& (video->mot[mbnum][4].x == 0) && (video->mot[mbnum][4].y == 0))
Mode = video->headerInfo.Mode[video->mbnum] = MODE_SKIPPED;
}
if (Mode == MODE_SKIPPED)
{
BitstreamPut1Bits(bs1, 1); /* not_coded = 1 */
return;
}
else
BitstreamPut1Bits(bs1, 0); /* not_coded =0 */
video->QP_prev = video->QPMB[mbnum];
video->usePrevQP = 1;
PutMCBPC_Inter(CBP, Mode, bs1); /* MCBPC */
video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
if (Mode == MODE_INTER || Mode == MODE_INTER_Q)
{
find_pmvs(video, 0, &pmvx, &pmvy); /* Get predicted motion vectors */
WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][0].x - pmvx, bs1); /* Write x to bitstream */
WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][0].y - pmvy, bs1); /* Write y to bitstream */
}
else if (Mode == MODE_INTER4V)
{
for (i = 1; i < 5; i++)
{
find_pmvs(video, i, &pmvx, &pmvy);
WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][i].x - pmvx, bs1);
WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][i].y - pmvy, bs1);
}
}
video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
/* SECOND PART: ALL TO BS2 */
if (intra)
{
BitstreamPut1Bits(bs2, video->acPredFlag[video->mbnum]); /* ac_pred_flag */
/*temp=*/
PutCBPY(CBP >> 2, (Char)(Mode == MODE_INTRA || Mode == MODE_INTRA_Q), bs2); /* cbpy */
if (Mode == MODE_INTRA_Q)
BitstreamPutBits(bs2, 2, dquant); /* dquant, 3/15/01*/
if (intraDC_decision == 0)
{
for (i = 0; i < 6; i++)
{
DC = video->RLB[i].level[0];
if (video->RLB[i].s[0])
DC = -DC;
if (i < 4)
/*temp =*/ IntraDC_dpcm(DC, 1, bs2); /* dct_dc_size_luminance, */
else /* dct_dc_differential, and */
/*temp =*/ IntraDC_dpcm(DC, 0, bs2); /* marker bit */
}
}
/****************************/ /* THIRD PART: ALL TO BS3 */
for (i = 0; i < 6; i++)
{
if (CBP&(1 << (5 - i)))
(*BlockCodeCoeff)(&(RLB[i]), bs3, 1 - intraDC_decision, ncoefblck[i], Mode);/* Code Intra AC*/
}
}
else
{
/*temp=*/
PutCBPY(CBP >> 2, (Char)(Mode == MODE_INTRA || Mode == MODE_INTRA_Q), bs2); /* cbpy */
if (Mode == MODE_INTER_Q)
/* MAY NEED TO CHANGE DQUANT HERE */
BitstreamPutBits(bs2, 2, dquant); /* dquant, 3/15/01*/
/****************************/ /* THIRD PART: ALL TO BS3 */
for (i = 0; i < 6; i++)
{
if (CBP&(1 << (5 - i)))
(*BlockCodeCoeff)(&(RLB[i]), bs3, 0, ncoefblck[i], Mode);/* Code Intra AC*/
}
}
return ;
}
#endif /* H263_ONLY */
/****************************************************************************************/
/* Short Header/Combined Mode with or without Error Resilience I-VOP and P-VOP Encoding */
/* 5/21/01, B-VOP is not implemented yet!!!! */
/****************************************************************************************/
void MBVlcEncodeCombined_I_VOP(
VideoEncData *video,
Int ncoefblck[],
void *blkCodePtr)
{
BitstreamEncVideo *bs1 = video->bitstream1;
// BitstreamEncVideo *bs2 = video->bitstream2;
// BitstreamEncVideo *bs3 = video->bitstream3;
int i;
UChar Mode = video->headerInfo.Mode[video->mbnum];
UChar CBP = video->headerInfo.CBP[video->mbnum];
// MacroBlock *MB=video->outputMB;
Int mbnum = video->mbnum;
Int intraDC_decision;
// int temp;
Int dquant; /* 3/15/01 */
RunLevelBlock *RLB = video->RLB;
Int DC;
Int shortVideoHeader = video->vol[video->currLayer]->shortVideoHeader;
BlockCodeCoeffPtr BlockCodeCoeff = (BlockCodeCoeffPtr) blkCodePtr;
/* DC and AC Prediction, 5/28/01, compute CBP, intraDC_decision*/
#ifndef H263_ONLY
if (!shortVideoHeader)
DCACPred(video, Mode, &intraDC_decision, video->QP_prev);
else
#endif
{
intraDC_decision = 0;
}
/* CBP, Run, Level, and Sign */
RunLevel(video, 1, intraDC_decision, ncoefblck);
CBP = video->headerInfo.CBP[mbnum];
/* Compute DQuant */
dquant = video->QPMB[mbnum] - video->QP_prev; /* 3/15/01, QP_prev may not equal QPMB[mbnum-1] if mbnum-1 is skipped*/
video->QP_prev = video->QPMB[mbnum];
if (dquant && Mode == MODE_INTRA)
{
Mode = MODE_INTRA_Q;
}
if (dquant >= 0)
dquant = (PV_ABS(dquant) + 1);
else
dquant = (PV_ABS(dquant) - 1);
PutMCBPC_Intra(CBP, Mode, bs1); /* mcbpc I_VOP */
if (!video->vol[video->currLayer]->shortVideoHeader)
{
BitstreamPut1Bits(bs1, video->acPredFlag[video->mbnum]); /* ac_pred_flag */
}
/*temp=*/
PutCBPY(CBP >> 2, (Char)(1), bs1); /* cbpy */
if (Mode == MODE_INTRA_Q)
/* MAY NEED TO CHANGE DQUANT HERE */
BitstreamPutBits(bs1, 2, dquant); /* dquant, 3/15/01*/
/*MB_CodeCoeff(video,bs1); 5/21/01, replaced by below */
/*******************/
#ifndef H263_ONLY
if (shortVideoHeader) /* Short Header DC coefficients */
{
#endif
for (i = 0; i < 6; i++)
{
DC = RLB[i].level[0];
if (RLB[i].s[0])
DC = -DC;
if (DC != 128)
BitstreamPutBits(bs1, 8, DC); /* intra_dc_size_luminance */
else
BitstreamPutBits(bs1, 8, 255); /* intra_dc_size_luminance */
if (CBP&(1 << (5 - i)))
(*BlockCodeCoeff)(&(RLB[i]), bs1, 1, ncoefblck[i], Mode); /* Code short header Intra AC*/
}
#ifndef H263_ONLY
}
else if (intraDC_decision == 0) /* Combined Intra Mode DC and AC coefficients */
{
for (i = 0; i < 6; i++)
{
DC = RLB[i].level[0];
if (RLB[i].s[0])
DC = -DC;
if (i < 4)
/*temp =*/ IntraDC_dpcm(DC, 1, bs1); /* dct_dc_size_luminance, */
else /* dct_dc_differential, and */
/*temp =*/ IntraDC_dpcm(DC, 0, bs1); /* marker bit */
if (CBP&(1 << (5 - i)))
(*BlockCodeCoeff)(&(RLB[i]), bs1, 1, ncoefblck[i], Mode);/* Code Intra AC */
}
}
else /* Combined Mode Intra DC/AC coefficients */
{
for (i = 0; i < 6; i++)
{
if (CBP&(1 << (5 - i)))
(*BlockCodeCoeff)(&(RLB[i]), bs1, 0, ncoefblck[i], Mode);/* Code Intra AC */
}
}
#endif
/*******************/
return ;
}
void MBVlcEncodeCombined_P_VOP(
VideoEncData *video,
Int ncoefblck[],
void *blkCodePtr)
{
BitstreamEncVideo *bs1 = video->bitstream1;
// BitstreamEncVideo *bs2 = video->bitstream2;
// BitstreamEncVideo *bs3 = video->bitstream3;
int i;
Int mbnum = video->mbnum;
UChar Mode = video->headerInfo.Mode[mbnum];
Int QP_tmp = video->QPMB[mbnum];
UChar CBP ;
// MacroBlock *MB=video->outputMB;
Int intra, intraDC_decision;
Int pmvx, pmvy;
// int temp;
Int dquant; /* 3/15/01 */
RunLevelBlock *RLB = video->RLB;
Int DC;
Int shortVideoHeader = video->vol[video->currLayer]->shortVideoHeader;
BlockCodeCoeffPtr BlockCodeCoeff = (BlockCodeCoeffPtr) blkCodePtr;
intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
/* DC and AC Prediction, 5/28/01, compute intraDC_decision*/
#ifndef H263_ONLY
if (!shortVideoHeader && intra)
{
if (video->usePrevQP)
{
QP_tmp = video->QPMB[mbnum-1];
}
DCACPred(video, Mode, &intraDC_decision, QP_tmp);
}
else
#endif
intraDC_decision = 0;
/* CBP, Run, Level, and Sign */
RunLevel(video, intra, intraDC_decision, ncoefblck);
CBP = video->headerInfo.CBP[mbnum];
/* Compute DQuant */
dquant = video->QPMB[mbnum] - video->QP_prev; /* 3/15/01, QP_prev may not equal QPMB[mbnum-1] if mbnum-1 is skipped*/
if (dquant && (Mode == MODE_INTRA || Mode == MODE_INTER))
{
Mode += 2; /* make it MODE_INTRA_Q and MODE_INTER_Q */
}
if (dquant >= 0)
dquant = (PV_ABS(dquant) + 1);
else
dquant = (PV_ABS(dquant) - 1);
if (CBP == 0 && intra == 0) /* Determine if Skipped MB */
{
if ((Mode == MODE_INTER) && (video->mot[mbnum][0].x == 0) && (video->mot[mbnum][0].y == 0))
Mode = video->headerInfo.Mode[video->mbnum] = MODE_SKIPPED;
else if ((Mode == MODE_INTER4V) && (video->mot[mbnum][1].x == 0) && (video->mot[mbnum][1].y == 0)
&& (video->mot[mbnum][2].x == 0) && (video->mot[mbnum][2].y == 0)
&& (video->mot[mbnum][3].x == 0) && (video->mot[mbnum][3].y == 0)
&& (video->mot[mbnum][4].x == 0) && (video->mot[mbnum][4].y == 0))
Mode = video->headerInfo.Mode[video->mbnum] = MODE_SKIPPED;
}
if (Mode == MODE_SKIPPED)
{
BitstreamPut1Bits(bs1, 1); /* not_coded = 1 */
return;
}
else
BitstreamPut1Bits(bs1, 0); /* not_coded =0 */
video->QP_prev = video->QPMB[mbnum];
video->usePrevQP = 1;
PutMCBPC_Inter(CBP, Mode, bs1); /* mcbpc P_VOP */
if (!video->vol[video->currLayer]->shortVideoHeader && intra)
{
BitstreamPut1Bits(bs1, video->acPredFlag[video->mbnum]); /* ac_pred_flag */
}
/*temp=*/
PutCBPY(CBP >> 2, (Char)(intra), bs1); /* cbpy */
if (Mode == MODE_INTRA_Q || Mode == MODE_INTER_Q)
/* MAY NEED TO CHANGE DQUANT HERE */
BitstreamPutBits(bs1, 2, dquant); /* dquant, 3/15/01*/
video->header_bits -= BitstreamGetPos(bs1); /* Header Bits */
if (!((video->vol[video->currLayer]->scalability) && (video->currVop->refSelectCode == 3)))
{
if (Mode == MODE_INTER || Mode == MODE_INTER_Q)
{
find_pmvs(video, 0, &pmvx, &pmvy); /* Get predicted motion vectors */
WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][0].x - pmvx, bs1); /* Write x to bitstream */
WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][0].y - pmvy, bs1); /* Write y to bitstream */
}
else if (Mode == MODE_INTER4V)
{
for (i = 1; i < 5; i++)
{
find_pmvs(video, i, &pmvx, &pmvy);
WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][i].x - pmvx, bs1);
WriteMVcomponent(video->currVop->fcodeForward, video->mot[mbnum][i].y - pmvy, bs1);
}
}
}
video->header_bits += BitstreamGetPos(bs1); /* Header Bits */
/* MB_CodeCoeff(video,bs1); */ /* 5/22/01, replaced with below */
/****************************/
if (intra)
{
#ifndef H263_ONLY
if (shortVideoHeader) /* Short Header DC coefficients */
{
#endif
for (i = 0; i < 6; i++)
{
DC = RLB[i].level[0];
if (RLB[i].s[0])
DC = -DC;
if (DC != 128)
BitstreamPutBits(bs1, 8, DC); /* intra_dc_size_luminance */
else
BitstreamPutBits(bs1, 8, 255); /* intra_dc_size_luminance */
if (CBP&(1 << (5 - i)))
(*BlockCodeCoeff)(&(RLB[i]), bs1, 1, ncoefblck[i], Mode); /* Code short header Intra AC*/
}
#ifndef H263_ONLY
}
else if (intraDC_decision == 0) /* Combined Intra Mode DC and AC coefficients */
{
for (i = 0; i < 6; i++)
{
DC = RLB[i].level[0];
if (RLB[i].s[0])
DC = -DC;
if (i < 4)
/*temp =*/ IntraDC_dpcm(DC, 1, bs1); /* dct_dc_size_luminance, */
else /* dct_dc_differential, and */
/*temp =*/ IntraDC_dpcm(DC, 0, bs1); /* marker bit */
if (CBP&(1 << (5 - i)))
(*BlockCodeCoeff)(&(RLB[i]), bs1, 1, ncoefblck[i], Mode);/* Code Intra AC */
}
}
else /* Combined Mode Intra DC/AC coefficients */
{
for (i = 0; i < 6; i++)
{
if (CBP&(1 << (5 - i)))
(*BlockCodeCoeff)(&(RLB[i]), bs1, 0, ncoefblck[i], Mode);/* Code Intra AC */
}
}
#endif
}
else /* Shortheader or Combined INTER Mode AC coefficients */
{
for (i = 0; i < 6; i++)
{
if (CBP&(1 << (5 - i)))
(*BlockCodeCoeff)(&(RLB[i]), bs1, 0, ncoefblck[i], Mode);/* Code Inter AC*/
}
}
/****************************/
return ;
}
/* ======================================================================== */
/* Function : BlockCodeCoeff() */
/* Date : 09/18/2000 */
/* Purpose : VLC Encode AC/DC coeffs */
/* In/out : */
/* Return : */
/* Modified : 5/16/01 grouping BitstreamPutBits calls */
/* 5/22/01 break up function */
/* ======================================================================== */
#ifndef NO_RVLC
/*****************/
/* RVLC ENCODING */
/*****************/
Void BlockCodeCoeff_RVLC(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode)
{
int length = 0;
int i;
Int level;
Int run;
Int intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
/* Not Last Coefficient */
for (i = j_start; i < j_stop - 1; i++)
{
run = RLB->run[i];
level = RLB->level[i];
//if(i==63||RLB->run[i+1] == -1) /* Don't Code Last Coefficient Here */
// break;
/*ENCODE RUN LENGTH */
if (level < 28 && run < 39)
{
if (intra)
length = PutCoeff_Intra_RVLC(run, level, bs);
else
length = PutCoeff_Inter_RVLC(run, level, bs);
}
else
length = 0;
/* ESCAPE CODING */
if (length == 0)
{
BitstreamPutBits(bs, 5 + 1, 2); /* ESCAPE + Not Last Coefficient */
//BitstreamPutBits(bs,1,0); /* Not Last Coefficient */
BitstreamPutBits(bs, 6 + 1, (run << 1) | 1); /* RUN + MARKER BIT*/
//BitstreamPutBits(bs,1,1); /* MARKER BIT */
BitstreamPutGT8Bits(bs, 11, level); /* LEVEL */
BitstreamPutBits(bs, 1 + 4, 16); /* MARKER BIT */
//BitstreamPutBits(bs,4,0); /* RVLC TRAILING ESCAPE */
}
BitstreamPutBits(bs, 1, RLB->s[i]); /* SIGN BIT */
}
/* Last Coefficient!!! */
run = RLB->run[i];
level = RLB->level[i];
/*ENCODE RUN LENGTH */
if (level < 6 && run < 45)
{
if (intra)
length = PutCoeff_Intra_RVLC_Last(run, level, bs);
else
length = PutCoeff_Inter_RVLC_Last(run, level, bs);
}
else
length = 0;
/* ESCAPE CODING */
if (length == 0)
{
BitstreamPutBits(bs, 5 + 1, 3); /* ESCAPE CODE + Last Coefficient*/
//BitstreamPutBits(bs,1,1); /* Last Coefficient !*/
BitstreamPutBits(bs, 6 + 1, (run << 1) | 1); /* RUN + MARKER BIT*/
//BitstreamPutBits(bs,1,1); /* MARKER BIT */
BitstreamPutGT8Bits(bs, 11, level); /* LEVEL */
BitstreamPutBits(bs, 1 + 4, 16); /* MARKER BIT + RVLC TRAILING ESCAPE */
//BitstreamPutBits(bs,4,0); /* */
}
BitstreamPut1Bits(bs, RLB->s[i]); /* SIGN BIT */
return ;
}
#endif
/*******************************/
/* SHORT VIDEO HEADER ENCODING */
/*******************************/
Void BlockCodeCoeff_ShortHeader(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode)
{
int length = 0;
int i;
// int temp;
Int level;
Int run;
OSCL_UNUSED_ARG(Mode);
/* Not Last Coefficient */
for (i = j_start; i < j_stop - 1; i++)
{
run = RLB->run[i];
level = RLB->level[i];
// if(i==63 ||RLB->run[i+1] == -1) /* Don't Code Last Coefficient Here */
// break;
/*ENCODE RUN LENGTH */
if (level < 13)
{
length = PutCoeff_Inter(run, level, bs);
if (length != 0)
/*temp =*/ BitstreamPut1Bits(bs, RLB->s[i]); /* Sign Bit */
}
else
length = 0;
/* ESCAPE CODING */
if (length == 0)
{
if (RLB->s[i])
level = -level;
BitstreamPutBits(bs, 7 + 1, 6); /* ESCAPE CODE + Not Last Coefficient */
//BitstreamPutBits(bs,1,0); /* Not Last Coefficient */
BitstreamPutBits(bs, 6, run); /* RUN */
BitstreamPutBits(bs, 8, level&0xFF); /* LEVEL, mask to make sure length 8 */
}
}
/* Last Coefficient!!! */
run = RLB->run[i];
level = RLB->level[i];
/*ENCODE RUN LENGTH */
if (level < 13)
{
length = PutCoeff_Inter_Last(run, level, bs);
if (length != 0)
/*temp =*/ BitstreamPut1Bits(bs, RLB->s[i]); /* Sign Bit */
}
else
length = 0;
/* ESCAPE CODING */
if (length == 0)
{
if (RLB->s[i])
level = -level;
BitstreamPutBits(bs, 7 + 1, 7); /* ESCAPE CODE + Last Coefficient */
//BitstreamPutBits(bs,1,1); /* Last Coefficient !!!*/
BitstreamPutBits(bs, 6, run); /* RUN */
BitstreamPutBits(bs, 8, level&0xFF); /* LEVEL, mask to make sure length 8 */
}
return ;
}
#ifndef H263_ONLY
/****************/
/* VLC ENCODING */
/****************/
Void BlockCodeCoeff_Normal(RunLevelBlock *RLB, BitstreamEncVideo *bs, Int j_start, Int j_stop, UChar Mode)
{
int length = 0;
int i;
//int temp;
Int level;
Int run;
Int intra = (Mode == MODE_INTRA || Mode == MODE_INTRA_Q);
Int level_minus_max;
Int run_minus_max;
Int(*PutCoeff)(Int, Int, BitstreamEncVideo *); /* pointer to functions, 5/28/01 */
/* Not Last Coefficient!!! */
if (intra)
PutCoeff = &PutCoeff_Intra;
else
PutCoeff = &PutCoeff_Inter;
for (i = j_start; i < j_stop - 1; i++)
{
run = RLB->run[i];
level = RLB->level[i];
/* Encode Run Length */
if (level < 28)
{
length = (*PutCoeff)(run, level, bs); /* 5/28/01 replaces above */
}
else
{
length = 0;
}
/* First escape mode: LEVEL OFFSET */
if (length == 0)
{
if (intra)
{
level_minus_max = level - intra_max_level[0][run];
if (level_minus_max < 28)
length = PutLevelCoeff_Intra(run, level_minus_max, bs);
else
length = 0;
}
else
{
level_minus_max = level - inter_max_level[0][run];
if (level_minus_max < 13)
length = PutLevelCoeff_Inter(run, level_minus_max, bs);
else
length = 0;
}
/* Second escape mode: RUN OFFSET */
if (length == 0)
{
if (level < 28)
{
if (intra)
{
run_minus_max = run - (intra_max_run0[level] + 1);
length = PutRunCoeff_Intra(run_minus_max, level, bs);
}
else if (level < 13)
{
run_minus_max = run - (inter_max_run0[level] + 1);
length = PutRunCoeff_Inter(run_minus_max, level, bs);
}
else
{
length = 0;
}
}
else
{
length = 0;
}
/* Third escape mode: FIXED LENGTH CODE */
if (length == 0)
{
if (RLB->s[i])
level = -level;
/*temp =*/
BitstreamPutBits(bs, 7 + 2 + 1, 30); /* ESCAPE CODE + Followed by 11 + Not Last Coefficient*/
//temp = BitstreamPutBits(bs,2,3); /* Followed by 11 */
//temp = BitstreamPutBits(bs, 1, 0); /* Not Last Coefficient*/
/*temp =*/
BitstreamPutBits(bs, 6 + 1, (run << 1) | 1); /* Encode Run + Marker Bit */
//temp = BitstreamPutBits(bs,1,1); /* Marker Bit */
/*temp =*/
BitstreamPutGT8Bits(bs, 12 + 1, ((level << 1) | 1)&0x1FFF); /* Encode Level, mask to make sure length 12 */
//temp = BitstreamPutBits(bs,1,1); /* Marker Bit */
}
}
}
/* Encode Sign Bit */
if (length != 0)
/*temp =*/ BitstreamPut1Bits(bs, RLB->s[i]); /* Sign Bit */
}
/* Last Coefficient */
run = RLB->run[i];
level = RLB->level[i];
/* Encode Run Length */
if (level < 9)
{
if (intra)
{
length = PutCoeff_Intra_Last(run, level, bs);
}
else if (level < 4)
{
length = PutCoeff_Inter_Last(run, level, bs);
}
else
{
length = 0;
}
}
else
{
length = 0;
}
/* First escape mode: LEVEL OFFSET */
if (length == 0)
{
if (intra)
{
level_minus_max = level - intra_max_level[1][run];
if (level_minus_max < 9)
length = PutLevelCoeff_Intra_Last(run, level_minus_max, bs);
else
length = 0;
}
else
{
level_minus_max = level - inter_max_level[1][run];
if (level_minus_max < 4)
length = PutLevelCoeff_Inter_Last(run, level_minus_max, bs);
else
length = 0;
}
/* Second escape mode: RUN OFFSET */
if (length == 0)
{
if (level < 9)
{
if (intra)
{
run_minus_max = run - (intra_max_run1[level] + 1);
length = PutRunCoeff_Intra_Last(run_minus_max, level, bs);
}
else if (level < 4)
{
run_minus_max = run - (inter_max_run1[level] + 1);
length = PutRunCoeff_Inter_Last(run_minus_max, level, bs);
}
else
{
length = 0;
}
}
else
{
length = 0;
}
/* Third escape mode: FIXED LENGTH CODE */
if (length == 0)
{
if (RLB->s[i])
level = -level;
/*temp =*/
BitstreamPutGT8Bits(bs, 7 + 2 + 1, 31); /* ESCAPE CODE + Followed by 11 + Last Coefficient*/
//temp = BitstreamPutBits(bs,2,3); /* Followed by 11 */
//temp = BitstreamPutBits(bs, 1, 1); /* Last Coefficient!!!*/
/*temp =*/
BitstreamPutBits(bs, 6 + 1, (run << 1) | 1); /* Encode Run + Marker Bit */
//temp = BitstreamPutBits(bs,1,1); /* Marker Bit */
/*temp =*/
BitstreamPutGT8Bits(bs, 12 + 1, ((level << 1) | 1)&0x1FFF); /* Encode Level, mask to make sure length 8 */
//temp = BitstreamPutBits(bs,1,1); /* Marker Bit */
}
}
}
/* Encode Sign Bit */
if (length != 0)
/*temp =*/ BitstreamPut1Bits(bs, RLB->s[i]);
return ;
}
#endif /* H263_ONLY */
/* ======================================================================== */
/* Function : RUNLevel */
/* Date : 09/20/2000 */
/* Purpose : Get the Coded Block Pattern for each block */
/* In/out : */
/* Int* qcoeff Quantized DCT coefficients
Int Mode Coding Mode
Int ncoeffs Number of coefficients */
/* Return : */
/* Int CBP Coded Block Pattern */
/* Modified : */
/* ======================================================================== */
void RunLevel(VideoEncData *video, Int intra, Int intraDC_decision, Int ncoefblck[])
{
Int i, j;
Int CBP = video->headerInfo.CBP[video->mbnum];
Int ShortNacNintra = (!(video->vol[video->currLayer]->shortVideoHeader) && video->acPredFlag[video->mbnum] && intra);
MacroBlock *MB = video->outputMB;
Short *dataBlock;
Int level;
RunLevelBlock *RLB;
Int run, idx;
Int *zz, nc, zzorder;
UChar imask[6] = {0x1F, 0x2F, 0x37, 0x3B, 0x3D, 0x3E};
UInt *bitmapzz;
/* Set Run, Level and CBP for this Macroblock */
/* ZZ scan is done here. */
if (intra)
{
if (intraDC_decision != 0)
intra = 0; /* DC/AC in Run/Level */
for (i = 0; i < 6 ; i++)
{
zz = (Int *) zigzag_inv;
RLB = video->RLB + i;
dataBlock = MB->block[i];
if (intra)
{
RLB->run[0] = 0;
level = dataBlock[0];
dataBlock[0] = 0; /* reset to zero */
if (level < 0)
{
RLB->level[0] = -level;
RLB->s[0] = 1;
}
else
{
RLB->level[0] = level;
RLB->s[0] = 0;
}
}
idx = intra;
if ((CBP >> (5 - i)) & 1)
{
if (ShortNacNintra)
{
switch ((video->zz_direction >> (5 - i))&1)
{
case 0:
zz = (Int *)zigzag_v_inv;
break;
case 1:
zz = (Int *)zigzag_h_inv;
break;
}
}
run = 0;
nc = ncoefblck[i];
for (j = intra, zz += intra; j < nc; j++, zz++)
{
zzorder = *zz;
level = dataBlock[zzorder];
if (level == 0)
run++;
else
{
dataBlock[zzorder] = 0; /* reset output */
if (level < 0)
{
RLB->level[idx] = -level;
RLB->s[idx] = 1;
RLB->run[idx] = run;
run = 0;
idx++;
}
else
{
RLB->level[idx] = level;
RLB->s[idx] = 0;
RLB->run[idx] = run;
run = 0;
idx++;
}
}
}
}
ncoefblck[i] = idx; /* 5/22/01, reuse ncoefblck */
if (idx == intra) /* reset CBP, nothing to be coded */
CBP &= imask[i];
}
video->headerInfo.CBP[video->mbnum] = CBP;
return ;
}
else
{
// zz = (Int *) zigzag_inv; no need to use it, default
if (CBP)
{
for (i = 0; i < 6 ; i++)
{
RLB = video->RLB + i;
idx = 0;
if ((CBP >> (5 - i)) & 1)
{ /* 7/30/01 */
/* Use bitmapzz to find the Run,Level,Sign symbols */
bitmapzz = video->bitmapzz[i];
dataBlock = MB->block[i];
nc = ncoefblck[i];
idx = zero_run_search(bitmapzz, dataBlock, RLB, nc);
}
ncoefblck[i] = idx; /* 5/22/01, reuse ncoefblck */
if (idx == 0) /* reset CBP, nothing to be coded */
CBP &= imask[i];
}
video->headerInfo.CBP[video->mbnum] = CBP;
}
return ;
}
}
#ifndef H263_ONLY
#ifdef __cplusplus
extern "C"
{
#endif
static Bool IntraDCSwitch_Decision(Int Mode, Int intra_dc_vlc_thr, Int intraDCVlcQP)
{
Bool switched = FALSE;
if (Mode == MODE_INTRA || Mode == MODE_INTRA_Q)
{
if (intra_dc_vlc_thr != 0)
{
switched = (intra_dc_vlc_thr == 7 || intraDCVlcQP >= intra_dc_vlc_thr * 2 + 11);
}
}
return switched;
}
#ifdef __cplusplus
}
#endif
Int IntraDC_dpcm(Int val, Int lum, BitstreamEncVideo *bitstream)
{
Int n_bits;
Int absval, size = 0;
absval = (val < 0) ? -val : val; /* abs(val) */
/* compute dct_dc_size */
size = 0;
while (absval)
{
absval >>= 1;
size++;
}
if (lum)
{ /* luminance */
n_bits = PutDCsize_lum(size, bitstream);
}
else
{ /* chrominance */
n_bits = PutDCsize_chrom(size, bitstream);
}
if (size != 0)
{
if (val >= 0)
{
;
}
else
{
absval = -val; /* set to "-val" MW 14-NOV-1996 */
val = absval ^((1 << size) - 1);
}
BitstreamPutBits(bitstream, (size), (UInt)(val));
n_bits += size;
if (size > 8)
BitstreamPut1Bits(bitstream, 1);
}
return n_bits; /* # bits for intra_dc dpcm */
}
/* ======================================================================== */
/* Function : DC_AC_PRED */
/* Date : 09/24/2000 */
/* Purpose : DC and AC encoding of Intra Blocks */
/* In/out : */
/* VideoEncData *video
UChar Mode */
/* Return : */
/* */
/* ======================================================================== */
Int cal_dc_scalerENC(Int QP, Int type) ;
#define PREDICT_AC for (m = 0; m < 7; m++){ \
tmp = DCAC[0]*QPtmp;\
if(tmp<0) tmp = (tmp-(QP/2))/QP;\
else tmp = (tmp+(QP/2))/QP;\
pred[m] = tmp;\
DCAC++;\
}
Void DCACPred(VideoEncData *video, UChar Mode, Int *intraDC_decision, Int intraDCVlcQP)
{
MacroBlock *MB = video->outputMB;
Int mbnum = video->mbnum;
typeDCStore *DC_store = video->predDC + mbnum;
typeDCACStore *DCAC_row = video->predDCAC_row;
typeDCACStore *DCAC_col = video->predDCAC_col;
Short *DCAC;
UChar Mode_top, Mode_left;
Vol *currVol = video->vol[video->currLayer];
Int nMBPerRow = currVol->nMBPerRow;
Int x_pos = video->outputMB->mb_x; /* 5/28/01 */
Int y_pos = video->outputMB->mb_y;
UChar QP = video->QPMB[mbnum];
UChar *QPMB = video->QPMB;
UChar *slice_nb = video->sliceNo;
Bool bACPredEnable = video->encParams->ACDCPrediction;
Int *ACpred_flag = video->acPredFlag;
Int mid_grey = 128 << 3;
Int m;
Int comp;
Int dc_scale = 8, tmp;
static const Int Xpos[6] = { -1, 0, -1, 0, -1, -1};
static const Int Ypos[6] = { -1, -1, 0, 0, -1, -1};
static const Int Xtab[6] = {1, 0, 3, 2, 4, 5};
static const Int Ytab[6] = {2, 3, 0, 1, 4, 5};
static const Int Ztab[6] = {3, 2, 1, 0, 4, 5};
/* I added these to speed up comparisons */
static const Int Pos0[6] = { 1, 1, 0, 0, 1, 1};
static const Int Pos1[6] = { 1, 0, 1, 0, 1, 1};
static const Int B_Xtab[6] = {0, 1, 0, 1, 2, 3};
static const Int B_Ytab[6] = {0, 0, 1, 1, 2, 3};
Int direction[6]; /* 0: HORIZONTAL, 1: VERTICAL */
Int block_A, block_B, block_C;
Int grad_hor, grad_ver, DC_pred;
Short pred[7], *predptr;
Short pcoeff[42];
Short *qcoeff;
Int S = 0, S1, S2;
Int diff, QPtmp;
Int newCBP[6];
UChar mask1[6] = {0x20, 0x10, 0x8, 0x4, 0x2, 0x1};
// UChar mask2[6] = {0x1f,0x2f,0x37,0x3b,0x3d,0x3e};
Int y_offset, x_offset, x_tab, y_tab, z_tab; /* speedup coefficients */
Int b_xtab, b_ytab;
video->zz_direction = 0;
/* Standard MPEG-4 Headers do DC/AC prediction*/
/* check whether neighbors are INTER */
if (y_pos > 0)
{
Mode_top = video->headerInfo.Mode[mbnum-nMBPerRow];
if (!(Mode_top == MODE_INTRA || Mode_top == MODE_INTRA_Q))
{
DCAC = DC_store[-nMBPerRow];
*DCAC++ = mid_grey;
*DCAC++ = mid_grey;
*DCAC++ = mid_grey;
*DCAC++ = mid_grey;
*DCAC++ = mid_grey;
*DCAC++ = mid_grey;
/* set to 0 DCAC_row[x_pos][0..3] */
if (bACPredEnable == TRUE)
{
M4VENC_MEMSET(DCAC_row[x_pos][0], 0, sizeof(Short) << 5);
}
}
}
if (x_pos > 0)
{
Mode_left = video->headerInfo.Mode[mbnum-1];
if (!(Mode_left == MODE_INTRA || Mode_left == MODE_INTRA_Q))
{
DCAC = DC_store[-1];
*DCAC++ = mid_grey;
*DCAC++ = mid_grey;
*DCAC++ = mid_grey;
*DCAC++ = mid_grey;
*DCAC++ = mid_grey;
*DCAC++ = mid_grey;
/* set to 0 DCAC_col[x_pos][0..3] */
if (bACPredEnable == TRUE)
{
M4VENC_MEMSET(DCAC_col[0][0], 0, sizeof(Short) << 5);
}
}
}
S1 = 0;
S2 = 0;
for (comp = 0; comp < 6; comp++)
{
if (Ypos[comp] != 0) y_offset = -nMBPerRow;
else y_offset = 0;
x_offset = Xpos[comp];
x_tab = Xtab[comp];
y_tab = Ytab[comp];
z_tab = Ztab[comp];
b_xtab = B_Xtab[comp];
b_ytab = B_Ytab[comp];
qcoeff = MB->block[comp];
/****************************/
/* Store DC coefficients */
/****************************/
/* Store coeff values for Intra MB */
if (comp == 0) dc_scale = cal_dc_scalerENC(QP, 1) ;
if (comp == 4) dc_scale = cal_dc_scalerENC(QP, 2) ;
QPtmp = qcoeff[0] * dc_scale; /* DC value */
if (QPtmp > 2047) /* 10/10/01, add clipping (bug fixed) */
DC_store[0][comp] = 2047;
else if (QPtmp < -2048)
DC_store[0][comp] = -2048;
else
DC_store[0][comp] = QPtmp;
/**************************************************************/
/* Find the direction of the prediction and the DC prediction */
/**************************************************************/
if ((x_pos == 0) && y_pos == 0)
{ /* top left corner */
block_A = (comp == 1 || comp == 3) ? DC_store[0][x_tab] : mid_grey;
block_B = (comp == 3) ? DC_store[x_offset][z_tab] : mid_grey;
block_C = (comp == 2 || comp == 3) ? DC_store[0][y_tab] : mid_grey;
}
else if (x_pos == 0)
{ /* left edge */
block_A = (comp == 1 || comp == 3) ? DC_store[0][x_tab] : mid_grey;
block_B = ((comp == 1 && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])) || comp == 3) ?
DC_store[y_offset+x_offset][z_tab] : mid_grey;
block_C = (comp == 2 || comp == 3 ||
(Pos0[comp] && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]))) ?
DC_store[y_offset][y_tab] : mid_grey;
}
else if (y_pos == 0)
{ /* top row */
block_A = (comp == 1 || comp == 3 || (Pos1[comp] && (slice_nb[mbnum] == slice_nb[mbnum-1]))) ?
DC_store[x_offset][x_tab] : mid_grey;
block_B = ((comp == 2 && (slice_nb[mbnum] == slice_nb[mbnum-1])) || comp == 3) ?
DC_store[y_offset + x_offset][z_tab] : mid_grey;
block_C = (comp == 2 || comp == 3) ?
DC_store[y_offset][y_tab] : mid_grey;
}
else
{
block_A = (comp == 1 || comp == 3 || (Pos1[comp] && (slice_nb[mbnum] == slice_nb[mbnum-1]))) ?
DC_store[x_offset][x_tab] : mid_grey;
block_B = (((comp == 0 || comp == 4 || comp == 5) &&
(slice_nb[mbnum] == slice_nb[mbnum-1-nMBPerRow])) ||
(comp == 1 && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow])) ||
(comp == 2 && (slice_nb[mbnum] == slice_nb[mbnum-1])) || (comp == 3)) ?
(DC_store[y_offset + x_offset][z_tab]) : mid_grey;
block_C = (comp == 2 || comp == 3 || (Pos0[comp] && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]))) ?
DC_store[y_offset][y_tab] : mid_grey;
}
grad_hor = block_B - block_C;
grad_ver = block_A - block_B;
if ((PV_ABS(grad_ver)) < (PV_ABS(grad_hor)))
{
DC_pred = block_C;
direction[comp] = 1;
video->zz_direction = (video->zz_direction) | mask1[comp];
}
else
{
DC_pred = block_A;
direction[comp] = 0;
//video->zz_direction=video->zz_direction<<1;
}
/* DC prediction */
QPtmp = dc_scale; /* 5/28/01 */
qcoeff[0] -= (DC_pred + QPtmp / 2) / QPtmp;
if (bACPredEnable)
{
/***********************/
/* Find AC prediction */
/***********************/
if ((x_pos == 0) && y_pos == 0) /* top left corner */
{
if (direction[comp] == 0)
{
if (comp == 1 || comp == 3)
{
QPtmp = QPMB[mbnum+x_offset];
DCAC = DCAC_col[0][b_ytab];
if (QPtmp != QP)
{
predptr = pred;
PREDICT_AC
}
else
{
predptr = DCAC;
}
}
else
{
predptr = pred;
pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
}
}
else
{
if (comp == 2 || comp == 3)
{
QPtmp = QPMB[mbnum+ y_offset];
DCAC = DCAC_row[x_pos][b_xtab];
if (QPtmp != QP)
{
predptr = pred;
PREDICT_AC
}
else
{
predptr = DCAC;
}
}
else
{
predptr = pred;
pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
}
}
}
else if (x_pos == 0) /* left edge */
{
if (direction[comp] == 0)
{
if (comp == 1 || comp == 3)
{
QPtmp = QPMB[mbnum+x_offset];
DCAC = DCAC_col[0][b_ytab];
if (QPtmp != QP)
{
predptr = pred;
PREDICT_AC
}
else
{
predptr = DCAC;
}
}
else
{
predptr = pred;
pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
}
}
else
{
if ((Pos0[comp] && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]))
|| comp == 2 || comp == 3)
{
QPtmp = QPMB[mbnum+y_offset];
DCAC = DCAC_row[x_pos][b_xtab];
if (QPtmp != QP)
{
predptr = pred;
PREDICT_AC
}
else
{
predptr = DCAC;
}
}
else
{
predptr = pred;
pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
}
}
}
else if (y_pos == 0) /* top row */
{
if (direction[comp] == 0)
{
if ((Pos1[comp] && (slice_nb[mbnum] == slice_nb[mbnum-1]))
|| comp == 1 || comp == 3)
{
QPtmp = QPMB[mbnum+x_offset];
DCAC = DCAC_col[0][b_ytab];
if (QPtmp != QP)
{
predptr = pred;
PREDICT_AC
}
else
{
predptr = DCAC;
}
}
else
{
predptr = pred;
pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
}
}
else
{
if (comp == 2 || comp == 3)
{
QPtmp = QPMB[mbnum+y_offset];
DCAC = DCAC_row[x_pos][b_xtab];
if (QPtmp != QP)
{
predptr = pred;
PREDICT_AC
}
else
{
predptr = DCAC;
}
}
else
{
predptr = pred;
pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
}
}
}
else
{
if (direction[comp] == 0)
{
if ((Pos1[comp] && (slice_nb[mbnum] == slice_nb[mbnum-1]))
|| comp == 1 || comp == 3)
{
QPtmp = QPMB[mbnum+x_offset];
DCAC = DCAC_col[0][b_ytab];
if (QPtmp != QP)
{
predptr = pred;
PREDICT_AC
}
else
{
predptr = DCAC;
}
}
else
{
predptr = pred;
pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
}
}
else
{
if ((Pos0[comp] && (slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]))
|| comp == 2 || comp == 3)
{
QPtmp = QPMB[mbnum+y_offset];
DCAC = DCAC_row[x_pos][b_xtab];
if (QPtmp != QP)
{
predptr = pred;
PREDICT_AC
}
else
{
predptr = DCAC;
}
}
else
{
predptr = pred;
pred[0] = pred[1] = pred[2] = pred[3] = pred[4] = pred[5] = pred[6] = 0;
}
}
}
/************************************/
/* Decide and Perform AC prediction */
/************************************/
newCBP[comp] = 0;
if (direction[comp] == 0) /* Horizontal, left COLUMN of block A */
{
DCAC = pcoeff + comp * 7; /* re-use DCAC as local var */
qcoeff += 8;
for (m = 0; m < 7; m++)
{
QPtmp = qcoeff[m<<3];
if (QPtmp > 0) S1 += QPtmp;
else S1 -= QPtmp;
QPtmp -= predptr[m];
DCAC[m] = QPtmp; /* save prediction residue to pcoeff*/
if (QPtmp) newCBP[comp] = 1;
diff = PV_ABS(QPtmp);
S2 += diff;
}
}
else /* Vertical, top ROW of block C */