diff options
author | James Dong <jdong@google.com> | 2010-07-12 21:46:25 -0700 |
---|---|---|
committer | James Dong <jdong@google.com> | 2010-07-15 13:28:21 -0700 |
commit | 59f566c4ec3dfc097ad8163523e522280b27e5c3 (patch) | |
tree | 6afe2f257d631e487a959e21015152d1d156cb5b /media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp | |
parent | e957045dcfdc7e08a5d76463b125d2a9e92bc0e8 (diff) | |
download | frameworks_av-59f566c4ec3dfc097ad8163523e522280b27e5c3.zip frameworks_av-59f566c4ec3dfc097ad8163523e522280b27e5c3.tar.gz frameworks_av-59f566c4ec3dfc097ad8163523e522280b27e5c3.tar.bz2 |
Initial check-in for software m4v_h263 encoder
Change-Id: I4b49fa5c3a5e6e21cfd2419441d98dd784046367
Diffstat (limited to 'media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp')
-rw-r--r-- | media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp | 2799 |
1 files changed, 2799 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp new file mode 100644 index 0000000..7ea5dc4 --- /dev/null +++ b/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp @@ -0,0 +1,2799 @@ +/* ------------------------------------------------------------------ + * 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 */ + { + qcoeff++; + DCAC = pcoeff + comp * 7; /* re-use DCAC as local var */ + for (m = 0; m < 7; m++) + { + QPtmp = qcoeff[m]; + 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; + } + } + + /****************************/ + /* Store DCAC coefficients */ + /****************************/ + /* Store coeff values for Intra MB */ + qcoeff = MB->block[comp]; + DCAC = DCAC_row[x_pos][b_xtab]; + DCAC[0] = qcoeff[1]; + DCAC[1] = qcoeff[2]; + DCAC[2] = qcoeff[3]; + DCAC[3] = qcoeff[4]; + DCAC[4] = qcoeff[5]; + DCAC[5] = qcoeff[6]; + DCAC[6] = qcoeff[7]; + + DCAC = DCAC_col[0][b_ytab]; + DCAC[0] = qcoeff[8]; + DCAC[1] = qcoeff[16]; + DCAC[2] = qcoeff[24]; + DCAC[3] = qcoeff[32]; + DCAC[4] = qcoeff[40]; + DCAC[5] = qcoeff[48]; + DCAC[6] = qcoeff[56]; + + + } /* bACPredEnable */ + + } /* END COMP FOR LOOP */ + + //if (diff > 2047) + // break; + S += (S1 - S2); + + + if (S >= 0 && bACPredEnable == TRUE) + { + ACpred_flag[mbnum] = 1; + DCAC = pcoeff; /* prediction residue */ + qcoeff = MB->block[0]; + + for (comp = 0; comp < 6; comp++) + { + if (direction[comp] == 0) + { + qcoeff[8] = DCAC[0]; + qcoeff[16] = DCAC[1]; + qcoeff[24] = DCAC[2]; + qcoeff[32] = DCAC[3]; + qcoeff[40] = DCAC[4]; + qcoeff[48] = DCAC[5]; + qcoeff[56] = DCAC[6]; + + } + else + { + qcoeff[1] = DCAC[0]; + qcoeff[2] = DCAC[1]; + qcoeff[3] = DCAC[2]; + qcoeff[4] = DCAC[3]; + qcoeff[5] = DCAC[4]; + qcoeff[6] = DCAC[5]; + qcoeff[7] = DCAC[6]; + } + if (newCBP[comp]) /* 5/28/01, update CBP */ + video->headerInfo.CBP[mbnum] |= mask1[comp]; + DCAC += 7; + qcoeff += 64; + } + } + else /* Only DC Prediction */ + { + ACpred_flag[mbnum] = 0; + } + + *intraDC_decision = IntraDCSwitch_Decision(Mode, video->currVop->intraDCVlcThr, intraDCVlcQP); + if (*intraDC_decision) /* code DC with AC , 5/28/01*/ + { + qcoeff = MB->block[0]; + for (comp = 0; comp < 6; comp++) + { + if (*qcoeff) + video->headerInfo.CBP[mbnum] |= mask1[comp]; + qcoeff += 64; + } + } + return; +} +#endif /* H263_ONLY */ + + + +Void find_pmvs(VideoEncData *video, Int block, Int *mvx, Int *mvy) +{ + Vol *currVol = video->vol[video->currLayer]; +// UChar *Mode = video->headerInfo.Mode; /* modes for MBs */ + UChar *slice_nb = video->sliceNo; + Int nMBPerRow = currVol->nMBPerRow; + Int mbnum = video->mbnum; + + Int p1x, p2x, p3x; + Int p1y, p2y, p3y; + Int xin1, xin2, xin3; + Int yin1, yin2, yin3; + Int vec1, vec2, vec3; + Int rule1, rule2, rule3; + MOT **motdata = video->mot; + Int x = mbnum % nMBPerRow; + Int y = mbnum / nMBPerRow; + + /* + In a previous version, a MB vector (block = 0) was predicted the same way + as block 1, which is the most likely interpretation of the VM. + + Therefore, if we have advanced pred. mode, and if all MBs around have + only one 16x16 vector each, we chose the appropiate block as if these + MBs have 4 vectors. + + This different prediction affects only 16x16 vectors of MBs with + transparent blocks. + + In the current version, we choose for the 16x16 mode the first + non-transparent block in the surrounding MBs + */ + + switch (block) + { + case 0: + vec1 = 2 ; + yin1 = y ; + xin1 = x - 1; + vec2 = 3 ; + yin2 = y - 1; + xin2 = x; + vec3 = 3 ; + yin3 = y - 1; + xin3 = x + 1; + break; + + case 1: + vec1 = 2 ; + yin1 = y ; + xin1 = x - 1; + vec2 = 3 ; + yin2 = y - 1; + xin2 = x; + vec3 = 3 ; + yin3 = y - 1; + xin3 = x + 1; + break; + + case 2: + vec1 = 1 ; + yin1 = y ; + xin1 = x; + vec2 = 4 ; + yin2 = y - 1; + xin2 = x; + vec3 = 3 ; + yin3 = y - 1; + xin3 = x + 1; + break; + + case 3: + vec1 = 4 ; + yin1 = y ; + xin1 = x - 1; + vec2 = 1 ; + yin2 = y ; + xin2 = x; + vec3 = 2 ; + yin3 = y ; + xin3 = x; + break; + + default: /* case 4 */ + vec1 = 3 ; + yin1 = y ; + xin1 = x; + vec2 = 1 ; + yin2 = y ; + xin2 = x; + vec3 = 2 ; + yin3 = y ; + xin3 = x; + break; + } + + if (block == 0) + { + /* according to the motion encoding, we must choose a first non-transparent + block in the surrounding MBs (16-mode) + */ + + if (x > 0 && slice_nb[mbnum] == slice_nb[mbnum-1]) + rule1 = 0; + else + rule1 = 1; + + if (y > 0 && slice_nb[mbnum] == slice_nb[mbnum-nMBPerRow]) + rule2 = 0; + else + rule2 = 1; + + if ((x != nMBPerRow - 1) && (y > 0) && slice_nb[mbnum] == slice_nb[mbnum+1-nMBPerRow]) + rule3 = 0; + else + rule3 = 1; + } + else + { + /* check borders for single blocks (advanced mode) */ + /* rule 1 */ + if (((block == 1 || block == 3) && + (x == 0 || slice_nb[mbnum] != slice_nb[mbnum-1]))) + rule1 = 1; + else + rule1 = 0; + + /* rule 2 */ + if (((block == 1 || block == 2) && + (y == 0 || slice_nb[mbnum] != slice_nb[mbnum-nMBPerRow]))) + rule2 = 1; + else + rule2 = 0; + + /* rule 3 */ + if (((block == 1 || block == 2) && + (x == nMBPerRow - 1 || y == 0 || slice_nb[mbnum] != slice_nb[mbnum+1-nMBPerRow]))) + rule3 = 1; + else + rule3 = 0; + } + + if (rule1) + { + p1x = p1y = 0; + } + else + { + + p1x = motdata[yin1*nMBPerRow+xin1][vec1].x; + p1y = motdata[yin1*nMBPerRow+xin1][vec1].y; + //p1x = motxdata[xin1*2+(vec1&0x1) + (yin1*2+(vec1>>1))*xB]; + //p1y = motydata[xin1*2+(vec1&0x1) + (yin1*2+(vec1>>1))*xB]; + } + + if (rule2) + { + p2x = p2y = 0; + } + else + { + p2x = motdata[yin2*nMBPerRow+xin2][vec2].x; + p2y = motdata[yin2*nMBPerRow+xin2][vec2].y; + //p2x = motxdata[xin2*2+(vec2&0x1) + (yin2*2+(vec2>>1))*xB]; + //p2y = motydata[xin2*2+(vec2&0x1) + (yin2*2+(vec2>>1))*xB]; + } + + if (rule3) + { + p3x = p3y = 0; + } + else + { + p3x = motdata[yin3*nMBPerRow+xin3][vec3].x; + p3y = motdata[yin3*nMBPerRow+xin3][vec3].y; + //p3x = motxdata[xin3*2+ (vec3&0x1) + (yin3*2+(vec3>>1))*xB]; + //p3y = motydata[xin3*2+ (vec3&0x1) + (yin3*2+(vec3>>1))*xB]; + } + + if (rule1 && rule2 && rule3) + { + /* all MBs are outside the VOP */ + *mvx = *mvy = 0; + } + else if (rule1 + rule2 + rule3 == 2) + { + /* two of three are zero */ + *mvx = (p1x + p2x + p3x); + *mvy = (p1y + p2y + p3y); + } + else + { + *mvx = ((p1x + p2x + p3x - PV_MAX(p1x, PV_MAX(p2x, p3x)) - PV_MIN(p1x, PV_MIN(p2x, p3x)))); + *mvy = ((p1y + p2y + p3y - PV_MAX(p1y, PV_MAX(p2y, p3y)) - PV_MIN(p1y, PV_MIN(p2y, p3y)))); + } + + return; +} + + +Void WriteMVcomponent(Int f_code, Int dmv, BitstreamEncVideo *bs) +{ + Int residual, vlc_code_mag, bits, entry; + + ScaleMVD(f_code, dmv, &residual, &vlc_code_mag); + + if (vlc_code_mag < 0) + entry = vlc_code_mag + 65; + else + entry = vlc_code_mag; + + bits = PutMV(entry, bs); + + if ((f_code != 1) && (vlc_code_mag != 0)) + { + BitstreamPutBits(bs, f_code - 1, residual); + bits += f_code - 1; + } + return; +} + + +Void +ScaleMVD( + Int f_code, /* <-- MV range in 1/2 units: 1=32,2=64,...,7=2048 */ + Int diff_vector, /* <-- MV Difference commponent in 1/2 units */ + Int *residual, /* --> value to be FLC coded */ + Int *vlc_code_mag /* --> value to be VLC coded */ +) +{ + Int range; + Int scale_factor; + Int r_size; + Int low; + Int high; + Int aux; + + r_size = f_code - 1; + scale_factor = 1 << r_size; + range = 32 * scale_factor; + low = -range; + high = range - 1; + + if (diff_vector < low) + diff_vector += 2 * range; + else if (diff_vector > high) + diff_vector -= 2 * range; + + if (diff_vector == 0) + { + *vlc_code_mag = 0; + *residual = 0; + } + else if (scale_factor == 1) + { + *vlc_code_mag = diff_vector; + *residual = 0; + } + else + { + aux = PV_ABS(diff_vector) + scale_factor - 1; + *vlc_code_mag = aux >> r_size; + + if (diff_vector < 0) + *vlc_code_mag = -*vlc_code_mag; + *residual = aux & (scale_factor - 1); + } +} |