summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/m4v_h263/enc/src/vlc_encode.cpp
diff options
context:
space:
mode:
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.cpp2799
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);
+ }
+}