sigmaplayer/src/divx.c

2613 lines
66 KiB
C

//////////////////////////////////////////////////////////////////////////
/**
* SigmaPlayer source project - DivX3->MPEG-4 transcoder source file.
* \file divx.cpp
* \author bombur
* \version 0.1
* \date 1.04.2007
*
* Portions of code taken from libavcodec.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
//////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <libsp/sp_misc.h>
#include <libsp/sp_msg.h>
#define DIVX_INTERNAL
#include "bitstream.h"
#include "divx.h"
#include "divx-tables.h"
//#define USE_SLOW_METHOD_LIMIT
// UNCOMMENT ALL!!!
#define USE_SLOW_METHOD
//#define USE_AC_CORRECTION
//#define USE_ONLY_SLOW_METHOD
//#define DUMP
//!!!!!!!!!!!!!!!!!!!!
//static int CNT = 0;
#ifdef DUMP
#define DEBUG_MSG msg
//#define DEBUG_MSG printf
#endif
#define INLINE SP_INLINE
#define STATIC static
//#define INLINE
//#define STATIC
//////////////////////////////////////////////////////////////////
#ifdef USE_SLOW_METHOD_LIMIT
const int max_allowed_frame_size_for_correct_method = 3750*4;
#endif
int frame_number;
static int width, height;
static DWORD pict_type;
static DWORD qscale, chroma_qscale;
static int enc_y_dc_scale, enc_c_dc_scale;
static BYTE *enc_y_dc_scale_table, *enc_c_dc_scale_table;
static int dec_y_dc_scale, dec_c_dc_scale;
static BYTE *dec_y_dc_scale_table, *dec_c_dc_scale_table;
static BYTE *chroma_qscale_table;
#ifdef USE_AC_CORRECTION
static int *ac_val_base, *ac_val;
static int ac_size;
static int qmul, qadd;
static DWORD use_acpred;
#endif
static int mb_width, mb_height, mb_num;
static int slice_height;
static int use_skip_mb_code;
static int f_code;
static int rl_table_index;
static int rl_chroma_table_index;
static int dc_table_index;
static int mv_table_index;
static int no_rounding;
static BOOL flipflop_rounding;
static int b8_stride, mb_stride;
static int block_index[6], (*block_index_tbl)[6];
static BYTE *coded_block_base, *coded_block;
static signed short (*motion_val_base)[2], (*motion_val)[2];
static BOOL mb_intra;
static int mb_x, mb_y;
static BOOL mb_skip;
static int first_slice_line;
static int motion_x, motion_y;
static int ac_pred;
static int block_wrap[6];
static signed short *enc_dc_val_base, *enc_dc_val[3];
static signed short *dec_dc_val_base, *dec_dc_val[3];
static signed short old_enc_dc_val, old_dec_dc_val;
static DWORD block_flags[64], block_flag;
//static int out_block[64];
#ifdef DUMP
DWORD block_idx[64], block_run[64];
#endif
static DIVX_SCAN_TABLE inter_scantable, intra_scantable;
static DIVX_SCAN_TABLE intra_h_scantable, intra_v_scantable;
static LONGLONG pts;
static int last_time_div, time_incr_res;
static DIVX_VLC mb_intra_vlc;
static DIVX_VLC mb_non_intra_vlc;
static DIVX_VLC dc_lum_vlc[2];
static DIVX_VLC dc_chroma_vlc[2];
static BYTE uni_DCtab_lum_len[512];
static BYTE uni_DCtab_chrom_len[512];
static WORD uni_DCtab_lum_bits[512];
static WORD uni_DCtab_chrom_bits[512];
static DIVX_BITS_LEN *bits_len_tab_cur[3], *bits_len[9];
static DWORD *bits_len_tab2_cur[3], *bits_len2[9];
static DWORD *level_run_tab_cur[3], *level_run[6];
static DWORD *level_run_tab2_cur[3], *level_run2[6];
static DWORD *uni_table[2];
/*
#include <stdarg.h>
void DUMP_FRAME(char *text, ...)
{
if (frame_number == 772)
{
static FILE *fp = NULL;
if (fp == NULL)
fp = fopen("out.log", "wb");
va_list args;
va_start(args, text);
vfprintf(fp, text, args);
va_end(args);
//fclose(fp);
}
}
*/
//#include <libsp/sp_fip.h>
//#define DUMP_FRAME gui_update();while(fip_read_button(TRUE) != FIP_KEY_ENTER);msg
////////////////////////////////////////////////////
STATIC void divx_init_scantable(DIVX_SCAN_TABLE *st, const BYTE *src_scantable)
{
DWORD i;
int end;
st->scantable = src_scantable;
for (i = 0; i < 64; i++)
{
st->permutated[i] = src_scantable[i];
st->inv_permutated[src_scantable[i]] = (BYTE)i;
}
end = -1;
for (i = 0; i < 64; i++)
{
int j = st->permutated[i];
if (j > end)
end = j;
st->raster_end[i] = (BYTE)end;
}
}
static int divx_alloc_vlc_table(DIVX_VLC *vlc, int size)
{
int index;
index = vlc->table_size;
vlc->table_size += size;
if (vlc->table_size > vlc->table_allocated)
{
vlc->table_allocated += (1 << vlc->bits);
vlc->table = (signed short (*)[2])SPrealloc(vlc->table,
sizeof(signed short) * 2 * vlc->table_allocated);
if (!vlc->table)
return -1;
}
return index;
}
STATIC INLINE DWORD divx_get_vlc_data(const void *table, int i, int wrap, int size)
{
const BYTE *ptr = (const BYTE *)table + i * wrap;
switch(size)
{
case 1:
return *(const BYTE *)ptr;
case 2:
return *(const WORD *)ptr;
default:
return *(const DWORD *)ptr;
}
}
static int divx_build_vlc_table(DIVX_VLC *vlc, int table_nb_bits,
int nb_codes,
const void *bits, int bits_wrap, int bits_size,
const void *codes, int codes_wrap, int codes_size,
DWORD code_prefix, int n_prefix)
{
int i, j, k, n, table_size, table_index, nb, n1, index;
DWORD code;
signed short (*table)[2];
table_size = 1 << table_nb_bits;
table_index = divx_alloc_vlc_table(vlc, table_size);
if (table_index < 0)
return -1;
table = &vlc->table[table_index];
for (i = 0; i < table_size; i++)
{
table[i][1] = 0; //bits
table[i][0] = -1; //codes
}
// first pass: map codes and compute auxillary table sizes
for (i = 0; i < nb_codes; i++)
{
n = divx_get_vlc_data(bits, i, bits_wrap, bits_size);
code = divx_get_vlc_data(codes, i, codes_wrap, codes_size);
// we accept tables with holes
if (n <= 0)
continue;
// if code matches the prefix, it is in the table
n -= n_prefix;
if (n > 0 && (code >> n) == code_prefix)
{
if (n <= table_nb_bits)
{
// no need to add another table
j = (code << (table_nb_bits - n)) & (table_size - 1);
nb = 1 << (table_nb_bits - n);
for (k = 0; k < nb; k++)
{
if (table[j][1] != 0) // bits
{
return -1;
}
table[j][1] = (signed short)n; //bits
table[j][0] = (signed short)i; //code
j++;
}
} else
{
n -= table_nb_bits;
j = (code >> n) & ((1 << table_nb_bits) - 1);
// compute table size
n1 = -table[j][1]; //bits
if (n > n1)
n1 = n;
table[j][1] = (signed short)-n1; //bits
}
}
}
// second pass : fill auxiliary tables recursively
for (i = 0; i < table_size; i++)
{
n = table[i][1]; //bits
if (n < 0)
{
n = -n;
if (n > table_nb_bits)
{
n = table_nb_bits;
table[i][1] = (signed short)-n; //bits
}
index = divx_build_vlc_table(vlc, n, nb_codes,
bits, bits_wrap, bits_size,
codes, codes_wrap, codes_size,
(code_prefix << table_nb_bits) | i,
n_prefix + table_nb_bits);
if (index < 0)
return -1;
// note: realloc has been done, so reload tables
table = &vlc->table[table_index];
table[i][0] = (signed short)index; //code
}
}
return table_index;
}
static int divx_init_vlc(DIVX_VLC *vlc, int nb_bits, int nb_codes,
const void *bits, int bits_wrap, int bits_size,
const void *codes, int codes_wrap, int codes_size)
{
vlc->bits = nb_bits;
vlc->table = NULL;
vlc->table_allocated = 0;
vlc->table_size = 0;
if (divx_build_vlc_table(vlc, nb_bits, nb_codes,
bits, bits_wrap, bits_size,
codes, codes_wrap, codes_size, 0, 0) < 0)
{
SPSafeFree(vlc->table);
return -1;
}
return 0;
}
static int divx_init_rl(DIVX_RL_TABLE *rl)
{
signed char max_level[DIVX_MAX_RUN + 1], max_run[DIVX_MAX_LEVEL + 1];
BYTE index_run[DIVX_MAX_RUN + 1];
int last, run, level, start, end, i;
// compute max_level[], max_run[] and index_run[]
for (last = 0; last < 2; last++)
{
if (last == 0)
{
start = 0;
end = rl->last;
} else
{
start = rl->last;
end = rl->n;
}
memset(max_level, 0, DIVX_MAX_RUN + 1);
memset(max_run, 0, DIVX_MAX_LEVEL + 1);
memset(index_run, rl->n, DIVX_MAX_RUN + 1);
for (i = start; i < end; i++)
{
run = rl->table_run[i];
level = rl->table_level[i];
if (index_run[run] == rl->n)
index_run[run] = (BYTE)i;
if (level > max_level[run])
max_level[run] = (signed char)level;
if (run > max_run[level])
max_run[level] = (signed char)run;
}
rl->max_level[last] = (signed char *)SPmalloc(DIVX_MAX_RUN + 1);
if (rl->max_level[last] == NULL)
return -1;
memcpy(rl->max_level[last], max_level, DIVX_MAX_RUN + 1);
rl->max_run[last] = (signed char *)SPmalloc(DIVX_MAX_LEVEL + 1);
if (rl->max_run[last] == NULL)
return -1;
memcpy(rl->max_run[last], max_run, DIVX_MAX_LEVEL + 1);
rl->index_run[last] = (BYTE *)SPmalloc(DIVX_MAX_RUN + 1);
if (rl->index_run[last] == NULL)
return -1;
memcpy(rl->index_run[last], index_run, DIVX_MAX_RUN + 1);
}
return 0;
}
static void divx_free_rl(DIVX_RL_TABLE *rl)
{
SPSafeFree(rl->max_level[0]);
SPSafeFree(rl->max_level[1]);
SPSafeFree(rl->max_run[0]);
SPSafeFree(rl->max_run[1]);
SPSafeFree(rl->index_run[0]);
SPSafeFree(rl->index_run[1]);
}
static int divx_build_ac_tables()
{
DWORD i, k, data_mask[16];
for (i = 0; i < 16; i++)
data_mask[i] = ((1 << i) - 1) << (16 - i);
for (i = 0; i < 9; i++)
{
DIVX_BITS_LEN *bits_len_tab = bits_len[i];
DWORD *bits_len_tab2 = bits_len2[i];
DWORD *uni_tbl = uni_table[i >= 6 ? 1 : 0];
DWORD I = (i >= 6) ? i - 3 : i;
DWORD *level_run_tab = level_run[I];
DWORD *level_run_tab2 = level_run2[I];
DWORD ext_idx = 0;
DWORD rt_idx = 4, j;
int max_level[64*2], max_run[64*2];
int num = rl_table[I].n, rl_last = rl_table[I].last;
DWORD ext_next_k = 0, rt_next_k = 0;
DWORD ext_cur_j = 0;
BOOL ext_next_esc4 = FALSE;
int idx;
//const WORD (*vlc)[2] = rl_table[I].table_vlc;
memset(max_level, 0, 64 * 2 * sizeof(int));
memset(max_run, 0, 64 * 2 * sizeof(int));
for (idx = 0; idx < num; idx++)
{
// no need to add another table
int lev = rl_table[I].table_level[idx];
int run = rl_table[I].table_run[idx];
int last = (idx >= rl_last) ? 64 : 0;
if (max_level[last + run] < lev)
max_level[last + run] = lev;
if (max_run[last + lev] < run)
max_run[last + lev] = run;
/*
DWORD nb = (15 - vlc[idx][1]);
DWORD j = vlc[idx][0] << (nb + 1);
for (int sign = 0; sign <= 1; sign++)
{
DWORD jj = j | (sign << nb);
for (int k = 1 << nb; k > 0; k--, jj++)
{
bits_len_tab[jj>>2].bits = (WORD)idx;
}
}
*/
}
for (j = 0; j < (1<<14); j++)
{
/*
short idx0 = bits_len_tab[j].bits;
*/
for (k = 0; k < 4; k++)
{
DWORD data = (j << 2) | k;
int idx, left = 16, len = 0;
BOOL found = FALSE, use_esc4 = FALSE, use_1 = FALSE;
DWORD total_num = 0, total_inlen = 0, total_outlen = 0, total_last = 0;
int first_level = 0;
DWORD first_len = 0, first_outlen = 0, first_run = 0, first_last = 0, first_data = 0;
DWORD out_data = 0, esc;
DWORD lrt;
/*
if (idx0 >= 0)
{
idx = idx0;
goto found;
}
*/
do
{
found = FALSE;
len = 0;
for (idx = 0; idx < num; idx++)
{
/*
found:
*/
const WORD *vlc = rl_table[I].table_vlc[idx];
len = vlc[1];
if (len + 1 > left)
continue;
if ((data & data_mask[len]) == (((DWORD)vlc[0]) << (16 - len)))
{
int level = rl_table[I].table_level[idx];
int run = rl_table[I].table_run[idx];
int last = (idx >= rl_table[I].last) ? 1 : 0;
register int index, outlen;
len++;
if (data & (1 << (16 - len)))
level = -level;
index = last*128*64 + run*128 + level + 64;
outlen = uni_tbl[index] >> 24;
left -= len;
data <<= len;
total_inlen += len;
total_outlen += outlen;
out_data <<= outlen;
out_data |= uni_tbl[index] & 0xffffff;
total_last = last;
if (first_len == 0)
{
first_len = len;
first_outlen = outlen;
first_level = level;
first_run = run;
first_data = out_data;
first_last = last;
}
total_num++;
if (outlen > 22)
{
use_esc4 = TRUE;
break;
}
if (total_num > 0 && (total_outlen > 15 || total_inlen > 14))
{
use_1 = TRUE;
break;
}
if (last)
break;
found = TRUE;
break;
}
}
}
while (found && total_outlen < 22);
esc = 0;
if (!use_esc4 && total_num == 0) // search ESC codes
{
const WORD *vlc = rl_table[I].table_vlc[num];
int len = vlc[1];
if ((data & data_mask[len]) == (((DWORD)vlc[0]) << (16 - len)))
{
int esc_shift, esc123;
len++;
esc_shift = 15 - len;
esc123 = (data >> esc_shift) & 3;
if (esc123 == 0)
{
esc = 3;
len++;
}
else if (esc123 == 1)
{
esc = 2;
len++;
}
else
esc = 1;
first_len = len;
}
}
// truncate too long seqs
if (use_1 || (total_num == 2 && total_outlen > 15 && first_outlen <= 15))
{
total_outlen = first_outlen;
total_inlen = first_len;
total_num = 1;
total_last = first_last;
out_data = first_data;
}
if (i < 6 && !esc)
{
DWORD add_level = max_level[first_last * 64 + (first_run & 63)];
DWORD add_run = max_run[first_last * 64 + Abs(first_level)];
lrt = ((DWORD)first_level & 127) << 25;
lrt |= ((first_len - 1) & 0xf) << 18;
lrt |= (first_last & 1) << 17;
lrt |= (add_level & 31) << 12;
lrt |= (add_run & 63) << 6;
lrt |= (first_run & 63);
if (first_len > 14)
{
if (k != rt_next_k)
rt_idx = (((rt_idx >> 2) + 1) << 2) | k;
level_run_tab2[rt_idx] = lrt;
level_run_tab[j] = (rt_idx & ~3);
rt_idx++;
rt_next_k = (k + 1) & 3;
}
else
level_run_tab[j] = lrt;
}
// esc1-4
if (esc)
{
bits_len_tab[j].len = (BYTE)esc;
bits_len_tab[j].bits = (WORD)first_len;
level_run_tab[j] = 0;
}
// extended
else if (total_inlen > 14 || total_outlen > 15 || use_esc4)
{
// if one of four extended records has ESC4, then all others should too
if (ext_cur_j == j)
{
if (!use_esc4 && ext_next_esc4)
use_esc4 = TRUE;
}
if (k != ext_next_k)
ext_idx = (((ext_idx >> 2) + 1) << 2) | k;
bits_len_tab2[ext_idx] = ((DWORD)total_last << 31) | ((out_data & 0x3FFFFF) << 9)
| ((total_inlen - 1) << 5) | total_outlen;
bits_len_tab[j].len = use_esc4 ? (BYTE)4 : (BYTE)0;
bits_len_tab[j].bits = (WORD)(ext_idx & ~3);
ext_idx++;
ext_next_k = (k + 1) & 3;
ext_next_esc4 = use_esc4;
ext_cur_j = j;
}
// normal
else
{
bits_len_tab[j].len = (BYTE)(((total_outlen & 0xf) << 4) | (total_inlen & 0xf));
bits_len_tab[j].bits = (WORD)(out_data | (total_last << 15));
}
}
}
msg("DivX3: AC-init[%d]: ext_num=%d, rt_num=%d\n", i, ext_idx, rt_idx);
gui_update();
}
return 0;
}
static void divx_init_uni_dc_tab(void)
{
int level, uni_code, uni_len;
for (level = -256; level < 256; level++)
{
int size, v, l;
// find number of bits
size = 0;
v = Abs(level);
while (v)
{
v >>= 1;
size++;
}
if (level < 0)
l = (-level) ^ ((1 << size) - 1);
else
l = level;
// luminance
uni_code = DCtab_lum[size][0];
uni_len = DCtab_lum[size][1];
if (size > 0)
{
uni_code <<= size; uni_code |= l;
uni_len += size;
if (size > 8)
{
uni_code <<= 1; uni_code |= 1;
uni_len++;
}
}
uni_DCtab_lum_bits[level + 256] = (WORD)uni_code;
uni_DCtab_lum_len [level + 256] = (BYTE)uni_len;
// chrominance
uni_code = DCtab_chrom[size][0];
uni_len = DCtab_chrom[size][1];
if (size > 0)
{
uni_code <<= size; uni_code |= l;
uni_len += size;
if (size > 8)
{
uni_code <<= 1; uni_code |= 1;
uni_len++;
}
}
uni_DCtab_chrom_bits[level + 256] = (WORD)uni_code;
uni_DCtab_chrom_len [level + 256] = (BYTE)uni_len;
}
}
STATIC INLINE int divx_get_rl_index(const DIVX_RL_TABLE *rl, int last, int run, int level)
{
DWORD index;
index = rl->index_run[last][run];
if (index >= rl->n)
return rl->n;
if (level > rl->max_level[last][run])
return rl->n;
return (int)index + level - 1;
}
static void divx_init_uni_tabs()
{
DWORD i;
for (i = 0; i < 2; i++)
{
DIVX_RL_TABLE *rl = &rl_table[i == 0 ? 2 : 5];
DWORD *uni_tab = uni_table[i];
int slevel, run, last;
for (run = 0; run < 64; run++)
{
for (last = 0; last <= 1; last++)
{
const int index = ((last)*128*64 + (run)*128 + 64);
uni_tab[index] = 0;
}
}
for (slevel = -64; slevel < 64; slevel++)
{
if (slevel == 0)
continue;
for (run = 0; run < 64; run++)
{
for (last = 0; last <= 1; last++)
{
const int index = ((last)*128*64 + (run)*128 + (slevel+64));
int level = slevel < 0 ? -slevel : slevel;
int sign = slevel < 0 ? 1 : 0;
DWORD bits, len, code;
int level1, run1;
DWORD out_len = 30;
DWORD out_bits = 0;
// ESC0
code = divx_get_rl_index(rl, last, run, level);
bits = rl->table_vlc[code][0];
len = rl->table_vlc[code][1] + 1;
bits = bits * 2 + sign;
if (code != rl->n && len < out_len)
{
out_bits = bits; out_len = len;
}
// ESC1
bits = rl->table_vlc[rl->n][0];
len = rl->table_vlc[rl->n][1] + 1;
bits = bits*2;
level1 = level - rl->max_level[last][run];
if (level1 > 0)
{
code = divx_get_rl_index(rl, last, run, level1);
bits <<= rl->table_vlc[code][1];
len += rl->table_vlc[code][1];
bits += rl->table_vlc[code][0];
bits = bits * 2 + sign;
len++;
if (code != rl->n && len < out_len)
{
out_bits = bits; out_len = len;
}
}
// ESC2
bits = rl->table_vlc[rl->n][0];
len = rl->table_vlc[rl->n][1];
bits = bits * 4 + 2; len+=2;
run1 = run - rl->max_run[last][level] - 1;
if (run1 >= 0)
{
code = divx_get_rl_index(rl, last, run1, level);
bits <<= rl->table_vlc[code][1];
len += rl->table_vlc[code][1];
bits += rl->table_vlc[code][0];
bits = bits * 2 + sign; len++;
if (code != rl->n && len < out_len)
{
out_bits = bits; out_len = len;
}
}
uni_tab[index] = (out_len << 24) | (out_bits & 0xffffff);
}
}
}
}
}
//////////////////////////////////////////////////////////////
#define divx_get_vlc2(code, dec_v, dec_bitidx, dec_left, table) \
{ \
register DWORD index; \
register int n; \
\
bitstream_show_bits(index, dec_v, dec_bitidx, 9); \
code = table[index][0]; \
n = table[index][1]; \
\
if (n < 0) \
{ \
bitstream_skip_bits(0, dec_v, dec_bitidx, dec_left, 9); \
bitstream_show_bits(index, dec_v, dec_bitidx, (-n)); \
index += code; \
code = table[index][0]; \
n = table[index][1]; \
} \
bitstream_skip_bits(0, dec_v, dec_bitidx, dec_left, n); \
}
#define divx_get_vlc3(code, dec_v, dec_bitidx, dec_left, table) \
{ \
register DWORD index; \
register int n; \
\
bitstream_show_bits(index, dec_v, dec_bitidx, 9); \
code = table[index][0]; \
n = table[index][1]; \
\
if (n < 0) \
{ \
register int nb_bits = -n; \
bitstream_skip_bits(0, dec_v, dec_bitidx, dec_left, 9); \
\
bitstream_show_bits(index, dec_v, dec_bitidx, nb_bits); \
index += code; \
code = table[index][0]; \
n = table[index][1]; \
\
if (n < 0) \
{ \
bitstream_skip_bits(0, dec_v, dec_bitidx, dec_left, nb_bits); \
nb_bits = -n; \
bitstream_show_bits(index, dec_v, dec_bitidx, nb_bits); \
index += code; \
code = table[index][0]; \
n = table[index][1]; \
} \
} \
bitstream_skip_bits(0, dec_v, dec_bitidx, dec_left, n); \
}
STATIC INLINE int divx_log2(unsigned int v)
{
int n = 0;
if (v & 0xffff0000)
{
v >>= 16;
n += 16;
}
if (v & 0xff00)
{
v >>= 8;
n += 8;
}
n += divx_log2_tab[v];
return n;
}
STATIC INLINE int divx_coded_block_pred(int n, BYTE **coded_block_ptr)
{
int xy, wrap, pred, a, b, c;
xy = block_index[n];
wrap = b8_stride;
a = coded_block[xy - 1 ];
b = coded_block[xy - 1 - wrap];
c = coded_block[xy - wrap];
if (b == c)
pred = a;
else
pred = c;
*coded_block_ptr = &coded_block[xy];
return pred;
}
STATIC INLINE int divx_pred_dc(int n, int level, int *dir_ptr, BOOL encoding)
{
int a, b, c, wrap, pred, scale, ret;
WORD *dc_val;
// find prediction
if (n < 4)
{
scale = encoding ? enc_y_dc_scale : dec_y_dc_scale;
} else
{
scale = encoding ? enc_c_dc_scale : dec_c_dc_scale;
}
wrap = block_wrap[n];
dc_val = (WORD *)((encoding ? enc_dc_val[0] : dec_dc_val[0]) + block_index[n]);
/* B C
* A X
*/
a = dc_val[ - 1];
b = dc_val[ - 1 - wrap];
c = dc_val[ - wrap];
if (encoding)
{
if (Abs(a - b) < Abs(b - c))
{
pred = c;
*dir_ptr = 1; // top
} else
{
pred = a;
*dir_ptr = 0; // left
}
pred = -(pred + (scale >> 1)) / scale;
ret = (level + pred);
level *= scale;
old_enc_dc_val = dc_val[0];
} else
{
if (scale == 8)
{
a = (a + (8 >> 1)) / 8;
b = (b + (8 >> 1)) / 8;
c = (c + (8 >> 1)) / 8;
} else
{
a = (a + (scale >> 1)) / scale;
b = (b + (scale >> 1)) / scale;
c = (c + (scale >> 1)) / scale;
}
if (Abs(a - b) <= Abs(b - c))
{
pred = c;
*dir_ptr = 1; // top
} else
{
pred = a;
*dir_ptr = 0; // left
}
ret = (level + pred);
level = ret * scale;
old_dec_dc_val = dc_val[0];
}
if (level & (~2047))
{
if (level < 0)
level = 0;
}
dc_val[0] = (WORD)level;
return ret;
}
#ifdef USE_AC_CORRECTION
STATIC INLINE DWORD divx_pred_notcoded_ac(int block_i, int block[64], int dec_dc_pred_dir)
{
int i = block_index[block_i] * 16;
int *ac = ac_val + i;
DWORD non_zero = 0;
if (ac_pred)
{
if (dec_dc_pred_dir == 0)
{
int *a = ac - 16;
for(i = 1; i < 8; i++)
{
#ifdef DUMP
// DEBUG_MSG("block[%d] = %d\n", i<<3, *a);
#endif
int level = *a++;
level = (level > 0) ? (level - qadd) / qmul : (level + qadd) / qmul;
block[i<<3] = level;
non_zero |= (DWORD)level;
}
} else
{
int *a = ac - 16 * block_wrap[block_i] + 8;
for(i = 1; i < 8; i++)
{
#ifdef DUMP
// DEBUG_MSG("block[%d] = %d\n", i, *a);
#endif
int level = *a++;
level = (level > 0) ? (level - qadd) / qmul : (level + qadd) / qmul;
block[i] = level;
non_zero |= (DWORD)level;
}
}
}
int *a = ac, *a8 = a + 8;
for(i = 1; i < 8; i++)
{
int level = block[i<<3];
level = (level > 0) ? level * qmul + qadd : level * qmul - qadd;
*a++ = level;
level = block[i];
level = (level > 0) ? level * qmul + qadd : level * qmul - qadd;
*a8++ = level;
}
// non-zero if any coefs are non-zero
return non_zero != 0 ? 1 : 0;
}
STATIC INLINE DWORD divx_pred_ac(int block_i, int *block, int dec_dc_pred_dir)
{
int i = block_index[block_i] * 16;
int *ac = ac_val + i;
DWORD non_zero = 0;
if (dec_dc_pred_dir == 0)
{
int *a = ac - 16;
for(i = 1; i < 8; i++)
{
#ifdef DUMP
// DEBUG_MSG("block[%d] = %d + %d\n", i<<3, block[i<<3], *a);
#endif
int level = block[i<<3];
level = (level > 0) ? level * qmul + qadd : level * qmul - qadd;
level += *a++;
level = (level > 0) ? (level - qadd) / qmul : (level + qadd) / qmul;
block[i<<3] = level;
non_zero |= (DWORD)level;
}
} else
{
int *a = ac - 16 * block_wrap[block_i] + 8;
for(i = 1; i < 8; i++)
{
#ifdef DUMP
// DEBUG_MSG("block[%d] = %d + %d\n", i, block[i], *a);
#endif
int level = block[i];
level= (level > 0) ? level * qmul + qadd : level * qmul - qadd;
level += *a++;
level = (level > 0) ? (level - qadd) / qmul : (level + qadd) / qmul;
block[i] = level;
non_zero |= (DWORD)level;
}
}
int *a = ac, *a8 = a + 8;
for(i = 1; i < 8; i++)
{
int level = block[i<<3];
level = (level > 0) ? level * qmul + qadd : level * qmul - qadd;
*a++ = level;
level = block[i];
level = (level > 0) ? level * qmul + qadd : level * qmul - qadd;
*a8++ = level;
}
// non-zero if any coefs are non-zero
return non_zero != 0 ? 1 : 0;
}
STATIC INLINE void divx_pred_flaged_ac(int block_i, int *block, DWORD *block_f, DWORD block_flag, int dec_dc_pred_dir)
{
int i = block_index[block_i] * 16;
int *ac = ac_val + i;
int *a = ac, *a8 = a + 8;
for(i = 1; i < 8; i++)
{
if (block_f[i<<3] == block_flag)
{
int level = block[i<<3];
level = (level > 0) ? level * qmul + qadd : level * qmul - qadd;
*a++ = level;
}
else
*a++ = 0;
if (block_f[i] == block_flag)
{
int level = block[i];
level = (level > 0) ? level * qmul + qadd : level * qmul - qadd;
*a8++ = level;
}
else
*a8++ = 0;
}
}
#endif
#if 0
STATIC INLINE int divx_put_rl_vlc(DWORD &enc_v, int &enc_bitidx, int &enc_len, int level, int last, int run, DWORD *bits_tab, BYTE *len_tab)
{
register int index = last*128*64 + (run-1)*128 + level + 64;
if (index >= 0)
return bitstream_put_bits(len_tab[index], bits_tab[index], enc_v, enc_bitidx, enc_len);
return 0;
}
#endif
#define divx_put_rl_vlc_esc3(enc_v, enc_bitidx, enc_len, level, last, run) \
{ \
DWORD d = ((3 << 23) + (3 << 21) + (1 << 13) + 1) + \
(last << 20) + ((run - 1) << 14) + (((level) & 0xfff) << 1); \
bitstream_put_bits((7+2+1+6+1+12+1), d, enc_v, enc_bitidx, enc_len); \
}
#define divx_encode_dc(enc_v, enc_bitidx, enc_len, level, n) \
{ \
level += 256; \
if (n < 4) /* luminance */ \
{ \
bitstream_put_bits(uni_DCtab_lum_len[level], uni_DCtab_lum_bits[level], enc_v, enc_bitidx, enc_len); \
} else /* chrominance */ \
{ \
bitstream_put_bits(uni_DCtab_chrom_len[level], uni_DCtab_chrom_bits[level], enc_v, enc_bitidx, enc_len); \
} \
}
STATIC INLINE int divx_mid_pred(int a, int b, int c)
{
if (a > b)
{
if (c > b)
b = (c > a) ? a : c;
} else
{
if (b > c)
b = (c > a) ? c : a;
}
return b;
}
STATIC INLINE signed short *divx_pred_motion(int *px, int *py)
{
int wrap;
signed short *A, *B, *C, (*mot_val)[2];
wrap = b8_stride;
mot_val = motion_val + block_index[0];
A = mot_val[ - 1];
if (first_slice_line)
{
if (mb_x == 0)
{
*px = *py = 0;
} else
{
*px = A[0];
*py = A[1];
}
} else
{
B = mot_val[ - wrap];
C = mot_val[2 - wrap];
*px = divx_mid_pred(A[0], B[0], C[0]);
*py = divx_mid_pred(A[1], B[1], C[1]);
}
return *mot_val;
}
#define divx_decode_motion(dec_v, dec_bitidx, dec_left, mx_ptr, my_ptr) \
{ \
DIVX_MV_TABLE *mv = &mv_tables[mv_table_index]; \
\
register int code; \
int mx, my; \
divx_get_vlc2(code, dec_v, dec_bitidx, dec_left, mv->vlc.table); \
if (code < 0) \
return -1; \
if (code == mv->n) \
{ \
register DWORD mxmy; \
bitstream_get_bits(mxmy, 0, dec_v, dec_bitidx, dec_left, 12); \
mx = mxmy >> 6; \
my = mxmy & 63; \
} else \
{ \
mx = mv->table_mvx[code]; \
my = mv->table_mvy[code]; \
} \
\
mx += mx_ptr - 32; \
my += my_ptr - 32; \
/* \WARNING : they do not do exactly modulo encoding */ \
if (mx <= -64) \
mx += 64; \
else if (mx >= 64) \
mx -= 64; \
\
if (my <= -64) \
my += 64; \
else if (my >= 64) \
my -= 64; \
\
mx_ptr = mx; \
my_ptr = my; \
}
#define divx_encode_motion(enc_v, enc_bitidx, enc_len, val, pred, fc) \
{ \
register int range, l, bit_size, sign, code, bits; \
\
int local_val = val - pred; \
if (local_val == 0) \
{ \
code = 0; \
/*DUMP_FRAME("MOTION ZERO code = %d\n", code);*/ \
bitstream_put_bits(mvtab[code][1], mvtab[code][0], enc_v, enc_bitidx, enc_len); \
} else \
{ \
DWORD d; \
bit_size = fc - 1; \
range = 1 << bit_size; \
/* modulo encoding (not divx3-like!) */ \
l = range * 32; \
local_val += l; \
local_val &= 2*l-1; \
local_val -= l; \
sign = local_val >> 31; \
local_val = (local_val^sign) - sign; \
sign &= 1; \
local_val--; \
code = (local_val >> bit_size) + 1; \
bits = local_val & (range - 1); \
\
/*DUMP_FRAME("MOTION code = %d sign=%d bits=%d bs=%d\n", code, sign, bits, bit_size);*/ \
\
d = ((mvtab[code][0] << 1) | sign); \
bitstream_put_bits(mvtab[code][1] + 1, d, enc_v, enc_bitidx, enc_len); \
if (bit_size > 0) \
{ \
bitstream_put_bits(bit_size, bits, enc_v, enc_bitidx, enc_len); \
} \
} \
}
STATIC INLINE void divx_set_block_index()
{
block_index[0] = block_index_tbl[mb_y][0];
block_index[1] = block_index_tbl[mb_y][1];
block_index[2] = block_index_tbl[mb_y][2];
block_index[3] = block_index_tbl[mb_y][3];
block_index[4] = block_index_tbl[mb_y][4];
block_index[5] = block_index_tbl[mb_y][5];
}
STATIC INLINE void divx_update_block_index()
{
block_index[0] += 2;
block_index[1] += 2;
block_index[2] += 2;
block_index[3] += 2;
block_index[4]++;
block_index[5]++;
}
STATIC INLINE void divx_update_motion_val()
{
register int xy = block_index[0];
register int wrap = b8_stride;
//DUMP_FRAME("--update_motion_val xy=%d = %d,%d\n", xy, motion_x, motion_y);
register signed short smx = (signed short)motion_x;
register signed short smy = (signed short)motion_y;
motion_val[xy][0] = smx;
motion_val[xy][1] = smy;
motion_val[xy + 1][0] = smx;
motion_val[xy + 1][1] = smy;
motion_val[xy + wrap][0] = smx;
motion_val[xy + wrap][1] = smy;
motion_val[xy + 1 + wrap][0] = smx;
motion_val[xy + 1 + wrap][1] = smy;
}
STATIC INLINE void divx_clean_intra_table_entries()
{
register int wrap = b8_stride;
register int xy = block_index[0];
register int xy1 = xy + 1, xywrap = xy + wrap, xy1wrap = xy + 1 + wrap;
coded_block[xy] = coded_block[xy1] = coded_block[xywrap] = coded_block[xy1wrap] = 0;
dec_dc_val[0][xy] = dec_dc_val[0][xy1] = dec_dc_val[0][xywrap] = dec_dc_val[0][xy1wrap] = 1024;
dec_dc_val[0][xy] = dec_dc_val[0][xy1] = dec_dc_val[0][xywrap] = dec_dc_val[0][xy1wrap] = 1024;
enc_dc_val[0][xy] = enc_dc_val[0][xy1] = enc_dc_val[0][xywrap] = enc_dc_val[0][xy1wrap] = 1024;
enc_dc_val[0][xy] = enc_dc_val[0][xy1] = enc_dc_val[0][xywrap] = enc_dc_val[0][xy1wrap] = 1024;
wrap = mb_stride;
xy = mb_x + mb_y * wrap;
dec_dc_val[1][xy] = dec_dc_val[2][xy] = 1024;
enc_dc_val[1][xy] = enc_dc_val[2][xy] = 1024;
}
/////////////////////////////////////////////////////////////////
#define divx_encode_mb_header(enc_v, enc_bitidx, enc_len, param_cbp, skip, ac_pred) \
{ \
DWORD cbpc = param_cbp & 3; \
DWORD cbpy = param_cbp >> 2; \
if (pict_type == DIVX_I_TYPE) \
{ \
bitstream_put_bits(intra_MCBPC_bits[cbpc], intra_MCBPC_code[cbpc], enc_v, enc_bitidx, enc_len); \
\
if (mb_intra) \
{ \
bitstream_put_bits(1, ac_pred, enc_v, enc_bitidx, enc_len); \
} \
else \
cbpy ^= 0x0F; \
/*DUMP_FRAME("cbpc=%d cbpy=%d\n", cbpc, cbpy);*/ \
bitstream_put_bits(cbpy_tab[cbpy][1], cbpy_tab[cbpy][0], enc_v, enc_bitidx, enc_len); \
} else \
{ \
bitstream_put_bits(1, (skip ? 1 : 0), enc_v, enc_bitidx, enc_len); \
if (!skip) \
{ \
if (mb_intra) \
cbpc |= 4; \
bitstream_put_bits(inter_MCBPC_bits[cbpc], inter_MCBPC_code[cbpc], enc_v, enc_bitidx, enc_len); \
\
if (mb_intra) \
{ \
bitstream_put_bits(1, ac_pred, enc_v, enc_bitidx, enc_len); \
} \
else \
cbpy ^= 0x0F; \
/*DUMP_FRAME("cbpc=%d cbpy=%d\n", cbpc, cbpy);*/ \
bitstream_put_bits(cbpy_tab[cbpy][1], cbpy_tab[cbpy][0], enc_v, enc_bitidx, enc_len); \
} \
} \
}
#define divx_decode_picture_header(dec_v, dec_bitidx, dec_left) \
{ \
bitstream_get_bits(pict_type, 0, dec_v, dec_bitidx, dec_left, 2); \
pict_type += 1; \
if (pict_type != DIVX_I_TYPE && pict_type != DIVX_P_TYPE) \
return -1; \
bitstream_get_bits(qscale, 0, dec_v, dec_bitidx, dec_left, 5); \
if (qscale == 0) \
return -1; \
chroma_qscale = chroma_qscale_table[qscale]; \
enc_y_dc_scale = enc_y_dc_scale_table[qscale]; \
enc_c_dc_scale = enc_c_dc_scale_table[chroma_qscale]; \
dec_y_dc_scale = dec_y_dc_scale_table[qscale]; \
dec_c_dc_scale = dec_c_dc_scale_table[chroma_qscale]; \
\
if (pict_type == DIVX_I_TYPE) \
{ \
DWORD code; \
bitstream_get_bits(code, 0, dec_v, dec_bitidx, dec_left, 5); \
if (code < 0x17) \
return -1; \
\
slice_height = mb_height / (code - 0x16); \
\
bitstream_get_bits012(rl_chroma_table_index, 0, dec_v, dec_bitidx, dec_left); \
bitstream_get_bits012(rl_table_index, 0, dec_v, dec_bitidx, dec_left); \
bitstream_get_bits1(dc_table_index, 0, dec_v, dec_bitidx, dec_left); \
no_rounding = 1; \
} else \
{ \
bitstream_get_bits1(use_skip_mb_code, 0, dec_v, dec_bitidx, dec_left); \
bitstream_get_bits012(rl_table_index, 0, dec_v, dec_bitidx, dec_left); \
rl_chroma_table_index = rl_table_index; \
bitstream_get_bits1(dc_table_index, 0, dec_v, dec_bitidx, dec_left); \
bitstream_get_bits1(mv_table_index, 0, dec_v, dec_bitidx, dec_left); \
\
if(flipflop_rounding) \
no_rounding ^= 1; \
else \
no_rounding = 0; \
} \
}
#define divx_encode_vos_header(enc_v, enc_bitidx, enc_len) \
{ \
bitstream_put_bits(32, 0x000001B0, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(8, 0xf5, enc_v, enc_bitidx, enc_len); /* profile: f5=??? 01=MPEG4@SL1 */ \
}
#define divx_encode_vol_header(enc_v, enc_bitidx, enc_len) \
{ \
const int vo_number = 0; \
const int vol_number = 0; \
const int vo_ver_id = 1; \
const int vo_type = 1; \
const int aspect_ratio_info = 1; \
\
bitstream_put_bits(32, 0x100 + vo_number, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(32, 0x120 + vol_number, enc_v, enc_bitidx, enc_len); \
\
bitstream_put_bits(1, 0, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(8, vo_type, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(8, (1<<7)|(vo_ver_id<<3)|1, enc_v, enc_bitidx, enc_len); \
\
bitstream_put_bits(4, aspect_ratio_info, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(8, 0xB1, enc_v, enc_bitidx, enc_len); /*10110001b*/ \
bitstream_put_bits(16, time_incr_res, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(3, 5, enc_v, enc_bitidx, enc_len); /* 101b */ \
bitstream_put_bits(13, width, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(1, 1, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(13, height, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(1, 1, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(1, 0 /*progressive=1*/, enc_v, enc_bitidx, enc_len); \
\
bitstream_put_bits(8, 0x8C, enc_v, enc_bitidx, enc_len); /*10001100b*/ \
\
bitstream_put_bits(3, 3, enc_v, enc_bitidx, enc_len); \
}
#if 0
static int divx_encode_gop_header(DWORD &enc_v, int &enc_bitidx, int &enc_len)
{
bitstream_put_bits(32, 0x000001B3, enc_v, enc_bitidx, enc_len);
LONGLONG time= pts;
const int AV_TIME_BASE = 1000000;
time= (time * time_incr_res + AV_TIME_BASE/2) / AV_TIME_BASE;
int seconds = (int)(time / time_incr_res);
int minutes = seconds / 60; seconds %= 60;
int hours = minutes/60; minutes %= 60; hours%=24;
bitstream_put_bits(5, hours, enc_v, enc_bitidx, enc_len);
bitstream_put_bits(6, minutes, enc_v, enc_bitidx, enc_len);
bitstream_put_bits(1, 1, enc_v, enc_bitidx, enc_len);
bitstream_put_bits(6, seconds, enc_v, enc_bitidx, enc_len);
return bitstream_put_bits(6, 7, enc_v, enc_bitidx, enc_len);
}
#endif
#define divx_encode_picture_header(enc_v, enc_bitidx, enc_len) \
{ \
/* VOP header */ \
int time_increment_bits; \
int time_div = 0, time_mod = 0, time_incr; \
\
bitstream_put_bits(32, 0x000001b6, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(2, pict_type - 1, enc_v, enc_bitidx, enc_len); \
\
time_increment_bits = time_incr_res != 0 ? divx_log2(time_incr_res - 1) + 1 : 4; \
\
if (time_incr_res > 0) \
{ \
time_div = (int)(pts / time_incr_res); \
time_mod = (int)(pts % time_incr_res); \
} \
time_incr = time_div - last_time_div; \
last_time_div = time_div; \
\
while (time_incr--) \
{ \
bitstream_put_bits(1, 1, enc_v, enc_bitidx, enc_len); \
} \
bitstream_put_bits(2, 1, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(time_increment_bits, time_mod, enc_v, enc_bitidx, enc_len); \
bitstream_put_bits(2, 3, enc_v, enc_bitidx, enc_len); \
if (pict_type == DIVX_P_TYPE) \
{ \
bitstream_put_bits(1, no_rounding, enc_v, enc_bitidx, enc_len); \
} \
\
bitstream_put_bits(8, qscale & 31, enc_v, enc_bitidx, enc_len); \
\
if (pict_type != DIVX_I_TYPE) \
{ \
bitstream_put_bits(3, f_code, enc_v, enc_bitidx, enc_len); \
} \
}
/////////////////////////////////////////////////////////////////
int divx_transcode_preinit()
{
int i;
static const int bits_len2_size[9] = { 600, 800, 10, 1100, 600, 1700, 300, 500, 10 };
static const int level_run2_size[6] = { 6, 130, 6, 100, 140, 6 };
uni_table[0] = (DWORD *)SPmalloc(128*64*2 * sizeof(DWORD));
uni_table[1] = (DWORD *)SPmalloc(128*64*2 * sizeof(DWORD));
if (uni_table[0] == NULL || uni_table[1] == NULL)
return -1;
for (i = 0; i < 9; i++)
{
bits_len[i] = (DIVX_BITS_LEN *)SPmalloc(16484 * sizeof(DIVX_BITS_LEN));
if (bits_len[i] == NULL)
return -1;
//memset(bits_len[i], 0xff, 16484 * sizeof(DIVX_BITS_LEN));
bits_len2[i] = (DWORD *)SPmalloc(bits_len2_size[i] * sizeof(DWORD));
if (bits_len2[i] == NULL)
return -1;
}
for (i = 0; i < 6; i++)
{
level_run[i] = (DWORD *)SPmalloc(16484 * sizeof(DWORD));
if (level_run[i] == NULL)
return -1;
level_run2[i] = (DWORD *)SPmalloc(level_run2_size[i] * sizeof(DWORD));
if (level_run2[i] == NULL)
return -1;
}
if (divx_init_rl(&rl_table[2]) < 0)
return -1;
if (divx_init_rl(&rl_table[5]) < 0)
return -1;
return 0;
}
int divx_transcode_predeinit()
{
int i;
divx_free_rl(&rl_table[5]);
divx_free_rl(&rl_table[2]);
SPSafeFree(uni_table[0]);
SPSafeFree(uni_table[1]);
for (i = 0; i < 6; i++)
{
SPSafeFree(level_run[i]);
SPSafeFree(level_run2[i]);
}
for (i = 0; i < 9; i++)
{
SPSafeFree(bits_len[i]);
SPSafeFree(bits_len2[i]);
}
return 0;
}
int divx_transcode_init(int w, int h, int t)
{
int i, y_size, c_size, yc_size, b8_array_size;
width = w;
height = h;
mb_width = (width + 15) / 16;
mb_height = (height + 15) / 16;
mb_num = mb_width * mb_height;
no_rounding = 0;
flipflop_rounding = 1;
b8_stride = mb_width * 2 + 1;
mb_stride = mb_width + 1;
y_size = b8_stride * (2 * mb_height + 1);
c_size = mb_stride * (mb_height + 1);
yc_size = y_size + 2 * c_size;
b8_array_size = b8_stride * mb_height * 2;
enc_dc_val_base = (signed short *)SPcalloc(yc_size * sizeof(signed short));
dec_dc_val_base = (signed short *)SPcalloc(yc_size * sizeof(signed short));
coded_block_base = (BYTE *)SPcalloc(y_size);
motion_val_base = (signed short (*)[2])SPcalloc(2 * (b8_array_size + 2) * sizeof(signed short));
block_index_tbl = (int (*)[6])SPmalloc(6 * mb_height * sizeof(int));
if (enc_dc_val_base == NULL || dec_dc_val_base == NULL ||
coded_block_base == NULL || motion_val_base == NULL || block_index_tbl == NULL)
{
return -1;
}
#ifdef USE_AC_CORRECTION
ac_size = yc_size * sizeof(int) * 16;
ac_val_base = (int *)SPcalloc(ac_size);
if (ac_val_base == NULL)
return -1;
ac_val = ac_val_base + (b8_stride + 1) * 16;
#endif
block_wrap[0] = block_wrap[1] = block_wrap[2] = block_wrap[3] = b8_stride;
block_wrap[4] = block_wrap[5] = mb_stride;
enc_dc_val[0] = enc_dc_val_base + b8_stride + 1;
enc_dc_val[1] = enc_dc_val_base + y_size + mb_stride + 1;
enc_dc_val[2] = enc_dc_val[1] + c_size;
dec_dc_val[0] = dec_dc_val_base + b8_stride + 1;
dec_dc_val[1] = dec_dc_val_base + y_size + mb_stride + 1;
dec_dc_val[2] = dec_dc_val[1] + c_size;
for (i = 0; i < yc_size; i++)
{
enc_dc_val_base[i] = 1024;
dec_dc_val_base[i] = 1024;
}
for (i = 0; i < mb_height; i++)
{
block_index_tbl[i][0] = b8_stride * (i*2 ) - 2;
block_index_tbl[i][1] = b8_stride * (i*2 ) - 1;
block_index_tbl[i][2] = b8_stride * (i*2 + 1) - 2;
block_index_tbl[i][3] = b8_stride * (i*2 + 1) - 1;
block_index_tbl[i][4] = mb_stride * (i + 1) + b8_stride * mb_height*2 - 1;
block_index_tbl[i][5] = mb_stride * (i + mb_height + 2) + b8_stride * mb_height*2 - 1;
}
coded_block = coded_block_base + b8_stride + 1;
mb_x = mb_y = 0;
ac_pred = 0;
f_code = 2;
dec_y_dc_scale_table = old_y_dc_scale_table;
dec_c_dc_scale_table = old_c_dc_scale_table;
enc_y_dc_scale_table = mpeg4_y_dc_scale_table;
enc_c_dc_scale_table = mpeg4_c_dc_scale_table;
chroma_qscale_table = default_chroma_qscale_table;
if (divx_init_vlc(&mb_intra_vlc, 9, 64, &table_mb_intra[0][1], 4, 2, &table_mb_intra[0][0], 4, 2) < 0)
return -1;
if (divx_init_vlc(&mb_non_intra_vlc, 9, 128, &table_mb_non_intra[0][1], 8, 4, &table_mb_non_intra[0][0], 8, 4) < 0)
return -1;
for (i = 0; i < 2; i++)
{
DIVX_MV_TABLE *mv = &mv_tables[i];
if (divx_init_vlc(&mv->vlc, 9, mv->n + 1, mv->table_mv_bits, 1,
1, mv->table_mv_code, 2, 2) < 0)
return -1;
}
if (divx_init_vlc(&dc_lum_vlc[0], 9, 120, &table0_dc_lum[0][1], 8, 4, &table0_dc_lum[0][0], 8, 4) < 0)
return -1;
if (divx_init_vlc(&dc_chroma_vlc[0], 9, 120, &table0_dc_chroma[0][1], 8, 4, &table0_dc_chroma[0][0], 8, 4) < 0)
return -1;
if (divx_init_vlc(&dc_lum_vlc[1], 9, 120, &table1_dc_lum[0][1], 8, 4, &table1_dc_lum[0][0], 8, 4) < 0)
return -1;
if (divx_init_vlc(&dc_chroma_vlc[1], 9, 120, &table1_dc_chroma[0][1], 8, 4, &table1_dc_chroma[0][0], 8, 4) < 0)
return -1;
divx_init_scantable(&inter_scantable , zigzag_direct);
divx_init_scantable(&intra_scantable , zigzag_direct);
divx_init_scantable(&intra_h_scantable, alternate_horizontal_scan);
divx_init_scantable(&intra_v_scantable, alternate_vertical_scan);
pts = 0;
time_incr_res = t;
last_time_div = 0;
divx_init_uni_dc_tab();
divx_init_uni_tabs();
divx_build_ac_tables();
// be careful, don't use uni_table!
SPSafeFree(uni_table[0]);
SPSafeFree(uni_table[1]);
motion_val = motion_val_base + 2;
block_flag = 1;
memset(block_flags, 0, sizeof(DWORD) * 64);
frame_number = 0;
return 0;
}
int divx_transcode_deinit()
{
SPSafeFree(dc_lum_vlc[0].table);
SPSafeFree(dc_chroma_vlc[0].table);
SPSafeFree(dc_lum_vlc[1].table);
SPSafeFree(dc_chroma_vlc[1].table);
SPSafeFree(mv_tables[0].vlc.table);
SPSafeFree(mv_tables[1].vlc.table);
SPSafeFree(mb_intra_vlc.table);
SPSafeFree(mb_non_intra_vlc.table);
#ifdef USE_AC_CORRECTION
SPSafeFree(ac_val_base);
#endif
SPSafeFree(block_index_tbl);
SPSafeFree(motion_val_base);
SPSafeFree(coded_block_base);
SPSafeFree(dec_dc_val_base);
SPSafeFree(enc_dc_val_base);
return 0;
}
BOOL divx_is_key_frame()
{
return pict_type == DIVX_I_TYPE;
}
//////////////////////////////////////////////////////
#ifdef USE_AC_CORRECTION
int divx_transcode_acpred_mb(DWORD &enc_v, int &ebitidx, int &enc_len,
DWORD &dec_v, int &bitidx, int &left, DWORD cbp)
{
int blocks[6][64], *block;
int dc_levels[6];
DWORD block_i;
DWORD block_coded[6];
DWORD out_cbp = cbp & (~63);
/// \TODO: move to the frame level
for (block_i = 0; block_i < 6; block_i++)
{
int ac_i, run_diff;
int *dec_scan_table;
int dec_dc_pred_dir;
DIVX_BITS_LEN *bits_len_tab;
DWORD *level_run_tab, *level_run_tab2;
DWORD *bits_len_tab2, *uni_tbl;
int coded = (cbp >> (5 - block_i)) & 1;
int dc_level;
register int level;
register DWORD run;
run_diff = 0;
block = blocks[block_i];
memset(block, 0, sizeof(int) * 64);
// decode dc
if (block_i < 4)
divx_get_vlc3(level, dec_v, bitidx, left, dc_lum_vlc[dc_table_index].table);
else
divx_get_vlc3(level, dec_v, bitidx, left, dc_chroma_vlc[dc_table_index].table);
if (level < 0)
return -1;
if (level == 119)
{
register DWORD ret;
bitstream_get_bits(level, 0, dec_v, bitidx, left, 8);
bitstream_get_bits1(ret, 0, dec_v, bitidx, left)
if (ret)
level = -level;
}
else if (level != 0)
{
register DWORD ret;
bitstream_get_bits1(ret, 0, dec_v, bitidx, left)
if (ret)
level = -level;
}
dc_level = divx_pred_dc(block_i, level, &dec_dc_pred_dir, FALSE);
dc_levels[block_i] = dc_level;
dec_scan_table = (dec_dc_pred_dir == 0) ?
intra_v_scantable.permutated : intra_h_scantable.permutated;
#ifdef DUMP
// DEBUG_MSG("-----------------\n");
// DEBUG_MSG("{%d}: DC LEVEL=%d / INTRA=%d\n", block_i, dc_level, mb_intra);
#endif
if (!coded)
{
DWORD coded = divx_pred_notcoded_ac(block_i, block, dec_dc_pred_dir);
out_cbp |= coded << (5 - block_i);
block_coded[block_i] = coded;
continue;
}
ac_i = 0;
#ifdef DUMP
//DEBUG_MSG(" DIR: dec=%d, enc=%d\n", dec_dc_pred_dir, enc_dc_pred_dir);
#endif
DWORD tbl_idx = block_i >> 2;
bits_len_tab = bits_len_tab_cur[tbl_idx];
bits_len_tab2 = bits_len_tab2_cur[tbl_idx];
uni_tbl = uni_table[0];
level_run_tab = level_run_tab_cur[tbl_idx];
level_run_tab2 = level_run_tab2_cur[tbl_idx];
while (ac_i < 64)
{
register DWORD idx, bits, len;
bitstream_show_bits(idx, dec_v, bitidx, 16);
bits = level_run_tab[idx>>2];
if (bits == 0) // esc123
{
bits = bits_len_tab[idx>>2].bits;
len = bits_len_tab[idx>>2].len;
bitstream_skip_bits(0, dec_v, bitidx, left, bits);
if (len == 3) // esc3
{
bitstream_get_bits(bits, 0, dec_v, bitidx, left, (1+6+8));
level = (bits & 0x80) ? ((bits & 0xff) | 0xffffff00) : (bits & 0x7f);
run = ((bits >> 8) & 63) + 1;
if (bits & 0x4000)
break;
}
else // esc1,esc2
{
BOOL esc1 = (len & 1);
bitstream_show_bits(idx, dec_v, bitidx, 16);
bits = level_run_tab[idx>>2];
if ((bits >> 16) == 0)
bits = level_run_tab2[bits | (idx & 3)];
len = ((bits >> 18) & 0xf) + 1;
bitstream_skip_bits(0, dec_v, bitidx, left, len);
level = ((int)bits) >> 25;
run = (bits & 63) + 1;
if (esc1)
{
level = level > 0 ? level + ((bits >> 12) & 31) * qmul : level - ((bits >> 12) & 31) * qmul;
} else
{
run += (bits >> 6) & 63;
run += run_diff;
}
if (bits & (1 << 17))
break;
}
} else
{
if ((bits >> 16) == 0)
bits = level_run_tab2[bits | (idx & 3)];
len = ((bits >> 18) & 0xf) + 1;
bitstream_skip_bits(0, dec_v, bitidx, left, len);
level = ((int)bits) >> 25;
run = (bits & 63) + 1;
if (bits & (1 << 17))
break;
}
ac_i += run;
idx = dec_scan_table[ac_i];
block[idx] = level;
#ifdef DUMP
//DEBUG_MSG("-> level=%d, run=%d\n", level, run);
block_idx[idx] = ac_i;
block_run[idx] = run;
#endif
}
ac_i += run;
#ifdef DUMP
//DEBUG_MSG("-> level=%d, run=%d\n", level, run);
block_idx[dec_scan_table[ac_i]] = ac_i;
block_run[dec_scan_table[ac_i]] = run;
#endif
run = dec_scan_table[ac_i];
block[run] = level;
// we have reconstructed block at this moment...
coded = divx_pred_ac(block_i, block, dec_dc_pred_dir);
out_cbp |= coded << (5 - block_i);
block_coded[block_i] = coded;
}
//////////////////////////////////////////////////////////////////////////////
/// NOW ENCODE!!!
divx_encode_mb_header(enc_v, ebitidx, enc_len, out_cbp, FALSE, 0);
for (block_i = 0; block_i < 6; block_i++)
{
register int level;
register DWORD run, i;
int last_non_zero = 0;
int *enc_scan_table;
int enc_dc_pred_dir;
block = blocks[block_i];
#ifdef DUMP
DEBUG_MSG("-----------------\n");
DEBUG_MSG("{%d}: DC LEVEL=%d / INTRA=%d\n", block_i, dc_levels[block_i], mb_intra);
for (i = 0; i < 64; i++)
{
if (block[i] != 0)
{
//DEBUG_MSG("[%d] = %d (%d,run=%d)\n", i, block[i], block_idx[i], block_run[i]);
DEBUG_MSG("[%d] = %d\n", i, block[i]);
}
}
#endif
level = divx_pred_dc(block_i, dc_levels[block_i], &enc_dc_pred_dir, TRUE);
divx_encode_dc(enc_v, ebitidx, enc_len, level, block_i);
if (!block_coded[block_i])
continue;
enc_scan_table = (enc_dc_pred_dir == 0) ?
intra_v_scantable.permutated : intra_h_scantable.permutated;
// now output the table
level = 0;
run = 0;
for (i = 0; i < 64; i++)
{
register DWORD eidx = enc_scan_table[i];
if (block[eidx] != 0)
{
if (level && (int)run > last_non_zero)
{
divx_put_rl_vlc_esc3(enc_v, ebitidx, enc_len, level, 0, run - last_non_zero);
last_non_zero = run;
}
level = block[eidx];
run = i;
}
}
divx_put_rl_vlc_esc3(enc_v, ebitidx, enc_len, level, 1, run - last_non_zero);
}
return 0;
}
#endif
//////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
int divx_transcode(bitstream_callback callback)
{
int code;
int block[64];
register DWORD dec_v;
register int bitidx, left;
register DWORD enc_v = 0;
register int ebitidx = 31;
register int enc_len = 0;
DWORD *block_f;
bitstream_set_callback(0, callback);
bitstream_decode_start(0, dec_v, bitidx, left);
divx_decode_picture_header(dec_v, bitidx, left);
if (divx_is_key_frame())
{
divx_encode_vos_header(enc_v, ebitidx, enc_len);
divx_encode_vol_header(enc_v, ebitidx, enc_len);
//if (divx_encode_gop_header(enc_v, ebitidx, len) < 0)
// return -1;
bitstream_flush_output(BITSTREAM_MODE_OUTPUT, enc_v, ebitidx, enc_len);
enc_v = 0;
ebitidx = 31;
enc_len = 0;
}
divx_encode_picture_header(enc_v, ebitidx, enc_len);
// process VOP
first_slice_line = 1;
mb_x = 0;
mb_y = 0;
bits_len_tab_cur[0] = bits_len[rl_table_index];
bits_len_tab_cur[1] = bits_len[3 + rl_chroma_table_index];
bits_len_tab_cur[2] = bits_len[6 + rl_table_index];
bits_len_tab2_cur[0] = bits_len2[rl_table_index];
bits_len_tab2_cur[1] = bits_len2[3 + rl_chroma_table_index];
bits_len_tab2_cur[2] = bits_len2[6 + rl_table_index];
level_run_tab_cur[0] = level_run[rl_table_index];
level_run_tab_cur[1] = level_run[3 + rl_chroma_table_index];
level_run_tab_cur[2] = level_run[3 + rl_table_index];
level_run_tab2_cur[0] = level_run2[rl_table_index];
level_run_tab2_cur[1] = level_run2[3 + rl_chroma_table_index];
level_run_tab2_cur[2] = level_run2[3 + rl_table_index];
block_f = block_flags;
#ifdef USE_AC_CORRECTION
memset(ac_val_base, 0, ac_size);
#endif
for (; mb_y < mb_height; mb_y++)
{
divx_set_block_index();
for (; mb_x < mb_width; mb_x++)
{
// process MB
#ifdef DUMP
DEBUG_MSG("-[%d: %d %d] --------------------------------------------\n", frame_number, mb_x, mb_y);
#endif
int pred_x, pred_y;
DWORD cbp = 0;
DWORD block_i;
#ifdef USE_AC_CORRECTION
use_acpred = 1;
if (!mb_intra)
{
qmul = qscale << 1;
qadd = (qscale - 1) | 1;
#ifdef DUMP
//DEBUG_MSG("qmul=%d, qadd=%d\n", qmul, qadd);
#endif
} else
{
qmul = 1;
qadd = 0;
}
#endif
/*
if (frame_number == 0 && mb_x == 31 && mb_y == 16)
{
int kk = 1;
}
*/
pred_x = 0;
pred_y = 0;
mb_skip = FALSE;
motion_x = 0;
motion_y = 0;
divx_update_block_index();
if (pict_type == DIVX_I_TYPE)
{
BYTE *coded_val;
int i;
mb_intra = TRUE;
divx_get_vlc2(code, dec_v, bitidx, left, mb_intra_vlc.table);
for (i = 0; i < 6; i++)
{
int val = ((code >> (5 - i)) & 1);
if (i < 4)
{
int pred = divx_coded_block_pred(i, &coded_val);
val = val ^ pred;
*coded_val = (BYTE)val;
}
cbp |= val << (5 - i);
}
}
else if (pict_type == DIVX_P_TYPE)
{
if (use_skip_mb_code)
{
register DWORD ret;
bitstream_get_bits1(ret, 0, dec_v, bitidx, left);
if (ret)
{
mb_intra = FALSE;
mb_skip = TRUE;
}
}
if (!mb_skip)
{
divx_get_vlc3(code, dec_v, bitidx, left, mb_non_intra_vlc.table);
if (code < 0)
return -1;
mb_intra = ((~code & 0x40) >> 6) != 0;
cbp = code & 0x3f;
}
}
if (mb_intra)
{
bitstream_get_bits1(ac_pred, 0, dec_v, bitidx, left);
#ifdef DUMP
DEBUG_MSG("CBP=%d, ACPRED=%d\n", cbp, ac_pred);
#endif
#ifdef USE_AC_CORRECTION
use_acpred = 1;
if (use_acpred && ac_pred)
{
if (divx_transcode_acpred_mb(enc_v, ebitidx, enc_len, dec_v, bitidx, left, cbp) < 0)
return -1;
continue;
}
#endif
} else
{
#ifdef DUMP
//DEBUG_MSG("CBP=%d, intra=%d\n", cbp, mb_intra);
#endif
if (!mb_skip)
{
// predict motion
divx_pred_motion(&pred_x, &pred_y);
motion_x = pred_x;
motion_y = pred_y;
divx_decode_motion(dec_v, bitidx, left, motion_x, motion_y);
#ifdef DUMP
DEBUG_MSG("MOTION mx=%d my=%d\n", motion_x, motion_y);
#endif
}
if ((cbp | motion_x | motion_y) == 0)
mb_skip = TRUE;
}
divx_encode_mb_header(enc_v, ebitidx, enc_len, cbp, mb_skip, ac_pred);
if (!mb_intra && !mb_skip)
{
divx_encode_motion(enc_v, ebitidx, enc_len, motion_x, pred_x, f_code);
divx_encode_motion(enc_v, ebitidx, enc_len, motion_y, pred_y, f_code);
}
for (block_i = 0; block_i < 6; block_i++)
{
int ac_i, run_diff;
int last_non_zero;
int *dec_scan_table, *enc_scan_table;
int *enc_inv_scan_table;
DIVX_BITS_LEN *bits_len_tab;
DWORD *level_run_tab, *level_run_tab2;
DWORD *bits_len_tab2, *uni_tbl;
DWORD last_scan = 0;
DWORD coded = (cbp >> (5 - block_i)) & 1;
BOOL the_same_scan_table = TRUE;
int dec_dc_pred_dir, enc_dc_pred_dir;
if (mb_intra)
{
int level, dc_level;
DWORD tbl_idx;
run_diff = 0;
// decode dc
if (block_i < 4)
{
divx_get_vlc3(level, dec_v, bitidx, left, dc_lum_vlc[dc_table_index].table);
}
else
{
divx_get_vlc3(level, dec_v, bitidx, left, dc_chroma_vlc[dc_table_index].table);
}
if (level < 0)
return -1;
if (level == 119)
{
register DWORD ret;
bitstream_get_bits(level, 0, dec_v, bitidx, left, 8);
bitstream_get_bits1(ret, 0, dec_v, bitidx, left);
if (ret)
level = -level;
}
else if (level != 0)
{
register DWORD ret;
bitstream_get_bits1(ret, 0, dec_v, bitidx, left);
if (ret)
level = -level;
}
dc_level = divx_pred_dc(block_i, level, &dec_dc_pred_dir, FALSE);
#ifdef DUMP
DEBUG_MSG("-----------------\n");
DEBUG_MSG("{%d}: DC LEVEL=%d / INTRA=%d\n", block_i, dc_level, mb_intra);
#endif
level = divx_pred_dc(block_i, dc_level, &enc_dc_pred_dir, TRUE);
divx_encode_dc(enc_v, ebitidx, enc_len, level, block_i);
if (!coded)
continue;
ac_i = 0;
if (ac_pred && dec_dc_pred_dir != enc_dc_pred_dir)
the_same_scan_table = FALSE;
#ifdef DUMP
//DEBUG_MSG(" DIR: dec=%d, enc=%d\n", dec_dc_pred_dir, enc_dc_pred_dir);
#endif
tbl_idx = block_i >> 2;
bits_len_tab = bits_len_tab_cur[tbl_idx];
bits_len_tab2 = bits_len_tab2_cur[tbl_idx];
uni_tbl = uni_table[0];
level_run_tab = level_run_tab_cur[tbl_idx];
level_run_tab2 = level_run_tab2_cur[tbl_idx];
} else
{
if (!coded)
continue;
run_diff = 1;
ac_i = -1;
bits_len_tab = bits_len_tab_cur[2];
bits_len_tab2 = bits_len_tab2_cur[2];
uni_tbl = uni_table[1];
level_run_tab = level_run_tab_cur[2];
level_run_tab2 = level_run_tab2_cur[2];
}
#ifdef USE_SLOW_METHOD_LIMIT
#ifdef USE_SLOW_METHOD
if (frame_size > max_allowed_frame_size_for_correct_method)
#endif
the_same_scan_table = TRUE;
#endif
#ifdef USE_ONLY_SLOW_METHOD
if (the_same_scan_table)
{
enc_dc_pred_dir = dec_dc_pred_dir;
the_same_scan_table = FALSE;
}
#endif
if (!the_same_scan_table)
{
#ifdef USE_AC_CORRECTION
// ????????????????????????????????
dec_scan_table = ac_pred ? ((dec_dc_pred_dir == 0) ?
intra_v_scantable.permutated :
intra_h_scantable.permutated) : intra_scantable.permutated;
enc_scan_table = ac_pred ? ((enc_dc_pred_dir == 0) ?
intra_v_scantable.permutated :
intra_h_scantable.permutated) : intra_scantable.permutated;
enc_inv_scan_table = ac_pred ? ((enc_dc_pred_dir == 0) ?
intra_v_scantable.inv_permutated :
intra_h_scantable.inv_permutated) : intra_scantable.inv_permutated;
#else
dec_scan_table = (dec_dc_pred_dir == 0) ?
intra_v_scantable.permutated : // left
intra_h_scantable.permutated; // top
enc_scan_table = (enc_dc_pred_dir == 0) ?
intra_v_scantable.permutated : // left
intra_h_scantable.permutated; // top
enc_inv_scan_table = (enc_dc_pred_dir == 0) ?
intra_v_scantable.inv_permutated : // left
intra_h_scantable.inv_permutated; // top
#endif
}
last_non_zero = ac_i;
if (the_same_scan_table)
{
for(;;)
{
register DWORD idx, bits, len;
bitstream_show_bits(idx, dec_v, bitidx, 16);
bits = bits_len_tab[idx>>2].bits;
len = bits_len_tab[idx>>2].len;
if (len >= 16) // normal (outlen < 16 bits, inlen < 14 bits)
{
bitstream_skip_bits(0, dec_v, bitidx, left, len & 0xf);
len >>= 4;
if (bits & 0x8000) // last
{
bits &= ~0x8000;
bitstream_put_bits(len, bits, enc_v, ebitidx, enc_len);
break;
}
bitstream_put_bits(len, bits, enc_v, ebitidx, enc_len);
}
else // extended || esc123
{
if (len == 0) // extended (16 bits < outlen < 23 bits)
{
bits = bits_len_tab2[bits | (idx & 3)];
len = ((bits >> 5) & 0xf) + 1;
bitstream_skip_bits(0, dec_v, bitidx, left, len);
len = (bits & 31);
if (bits & 0x80000000) // last
{
bits = (bits & ~(0x80000000)) >> 9;
bitstream_put_bits(len, bits, enc_v, ebitidx, enc_len);
break;
}
bitstream_put_bits(len, bits >> 9, enc_v, ebitidx, enc_len);
}
else if (len == 4) // extended-"ESC4" (outlen >= 23 bits)
{
DWORD last;
int level;
bits = level_run_tab[idx>>2];
// if extended (first VLC is longer than 14 bits)
if ((bits >> 16) == 0)
bits = level_run_tab2[bits | (idx & 3)];
len = ((bits >> 18) & 0xf) + 1;
bitstream_skip_bits(0, dec_v, bitidx, left, len);
last = (bits & (1 << 17)) << 3;
level = ((int)bits) >> 25;
bits = ((bits & 63) << 14);
bits += ((level & 0xfff) << 1) + last + ((3 << 23) + (3 << 21) + (1 << 13) + 1);
bitstream_put_bits((7+2+1+6+1+12+1), bits, enc_v, ebitidx, enc_len);
if (last)
break;
}
else
{
bitstream_skip_bits(0, dec_v, bitidx, left, bits);
if (len == 3) // esc3
{
int level;
DWORD last;
bitstream_get_bits(bits, 0, dec_v, bitidx, left, (1+6+8));
level = (bits & 0x80) ? ((bits & 0xff) | 0xffffff00) : (bits & 0x7f);
last = ((bits << 6) & 0x100000);
bits = last + (((bits >> 8) & 63) << 14);
bits += ((3 << 23) + (3 << 21) + (1 << 13) + 1) + ((level & 0xfff) << 1);
bitstream_put_bits((7+2+1+6+1+12+1), bits, enc_v, ebitidx, enc_len);
if (last)
break;
}
else // esc1,esc2
{
BOOL esc1 = (len & 1);
int level;
DWORD run, last;
bitstream_show_bits(idx, dec_v, bitidx, 16);
bits = level_run_tab[idx>>2];
// if extended esc1/2 (first VLC is longer than 14 bits)
if ((bits >> 16) == 0)
bits = level_run_tab2[bits | (idx & 3)];
len = ((bits >> 18) & 0xf) + 1;
bitstream_skip_bits(0, dec_v, bitidx, left, len);
/* bits = level(7)+reserved(3)+first_len(4)+first_last(1)+add_level(5)+add_run(6)+run(6) */
level = ((int)bits) >> 25;
run = (bits & 63) + 1;
last = (bits & (1 << 17)) << 3;
if (esc1)
{
level = level > 0 ? level + ((bits >> 12) & 31) : level - ((bits >> 12) & 31);
} else
{
run += (bits >> 6) & 63;
run += run_diff;
}
// now we have level, run, last - output in ESC3 mode
bits = ((3 << 23) + (3 << 21) + (1 << 13) + 1) + last + ((run - 1) << 14) + ((level & 0xfff) << 1);
// TODO: use uni_tab
bitstream_put_bits((7+2+1+6+1+12+1), bits, enc_v, ebitidx, enc_len);
if (last)
break;
}
continue;
}
}
}
}
else ///////////////////////////////////////////////////////////
{
#ifdef USE_SLOW_METHOD
register int level;
register DWORD run, i;
while (ac_i < 64)
{
register DWORD idx, bits, len;
bitstream_show_bits(idx, dec_v, bitidx, 16);
bits = level_run_tab[idx>>2];
if (bits == 0) // esc123
{
bits = bits_len_tab[idx>>2].bits;
len = bits_len_tab[idx>>2].len;
bitstream_skip_bits(0, dec_v, bitidx, left, bits);
if (len == 3) // esc3
{
bitstream_get_bits(bits, 0, dec_v, bitidx, left, (1+6+8));
level = (bits & 0x80) ? ((bits & 0xff) | 0xffffff00) : (bits & 0x7f);
run = ((bits >> 8) & 63) + 1;
if (bits & 0x4000)
break;
}
else // esc1,esc2
{
BOOL esc1 = (len & 1);
bitstream_show_bits(idx, dec_v, bitidx, 16);
bits = level_run_tab[idx>>2];
if ((bits >> 16) == 0)
bits = level_run_tab2[bits | (idx & 3)];
len = ((bits >> 18) & 0xf) + 1;
bitstream_skip_bits(0, dec_v, bitidx, left, len);
level = ((int)bits) >> 25;
run = (bits & 63) + 1;
if (esc1)
{
level = level > 0 ? level + ((bits >> 12) & 31) : level - ((bits >> 12) & 31);
} else
{
run += (bits >> 6) & 63;
run += run_diff;
}
if (bits & (1 << 17))
break;
}
} else
{
if ((bits >> 16) == 0)
bits = level_run_tab2[bits | (idx & 3)];
len = ((bits >> 18) & 0xf) + 1;
bitstream_skip_bits(0, dec_v, bitidx, left, len);
level = ((int)bits) >> 25;
run = (bits & 63) + 1;
if (bits & (1 << 17))
break;
}
ac_i += run;
idx = dec_scan_table[ac_i];
bits = enc_inv_scan_table[idx];
if (last_scan < bits)
last_scan = bits;
block[idx] = level;
block_f[idx] = block_flag;
#ifdef DUMP
//DEBUG_MSG("-> level=%d, run=%d\n", level, run);
block_idx[idx] = ac_i;
block_run[idx] = run;
#endif
}
ac_i += run;
#ifdef DUMP
//DEBUG_MSG("-> level=%d, run=%d\n", level, run);
block_idx[dec_scan_table[ac_i]] = ac_i;
block_run[dec_scan_table[ac_i]] = run;
#endif
run = dec_scan_table[ac_i];
i = enc_inv_scan_table[run];
if (last_scan < i)
last_scan = i;
block[run] = level;
block_f[run] = block_flag;
// we have reconstructed block at this moment...
#ifdef DUMP
for (i = 0; i < 64; i++)
{
if (block_f[i] == block_flag)
{
//DEBUG_MSG("[%d] = %d (%d,run=%d)\n", i, block[i], block_idx[i], block_run[i]);
DEBUG_MSG("[%d] = %d\n", i, block[i]);
}
}
#endif
// now output the table
level = 0;
run = 0;
for (i = 0; i <= last_scan; i++)
{
register DWORD eidx = enc_scan_table[i];
if (block_f[eidx] == block_flag)
{
if (level && (int)run > last_non_zero)
{
#if 0
if (!((level + 64) & (~127))) // ESC3
{
idx = (DWORD)(level + 64) + (run - last_non_zero)*128;
last_non_zero = run;
idx = uni_tbl[idx];
run = idx >> 24;
idx &= 0xffffff;
bitstream_put_bits(run, idx, enc_v, ebitidx, enc_len);
}
else
#endif
{
divx_put_rl_vlc_esc3(enc_v, ebitidx, enc_len, level, 0, run - last_non_zero);
last_non_zero = run;
}
}
level = block[eidx];
run = i;
}
}
if (level && (int)run > last_non_zero)
{
#if 0
if (!((level + 64) & (~127))) // ESC3
{
idx = 128*64 + (DWORD)(level + 64) + (run - last_non_zero)*128;
idx = uni_tbl[idx];
run = idx >> 24;
idx &= 0xffffff;
bitstream_put_bits(run, idx, enc_v, ebitidx, enc_len);
} else
#endif
{
divx_put_rl_vlc_esc3(enc_v, ebitidx, enc_len, level, 1, run - last_non_zero);
}
}
#ifdef USE_AC_CORRECTION
if (use_acpred && mb_intra)
{
divx_pred_flaged_ac(block_i, block, block_f, block_flag, dec_dc_pred_dir);
}
#endif
block_flag++;
#endif
}
}
if (!mb_intra)
divx_clean_intra_table_entries();
divx_update_motion_val();
}
first_slice_line = 0;
mb_x = 0;
}
// flush last output bits
bitstream_flush_output(BITSTREAM_MODE_DONE, enc_v, ebitidx, enc_len);
frame_number++;
return 0;
}