- renaming the AC coding set variable names to more meaningful ones

- removed old MB decoding functions, and moved around macros to be used in
the previously unused code, which match better msmpeg4.c/whole MPV
framework
- cleaned (not yet functionnal, lots missing) DC prediction
- trying to pass the proper coded status to block decoder
patch by anonymous

Originally committed as revision 3973 to svn://svn.ffmpeg.org/ffmpeg/trunk
pull/126/head
anonymous 20 years ago committed by Michael Niedermayer
parent 0ce5275d78
commit 8da75fb272
  1. 610
      libavcodec/vc9.c

@ -45,7 +45,7 @@ extern VLC ff_msmp4_mb_i_vlc;
static const uint16_t table_mb_intra[64][2]; static const uint16_t table_mb_intra[64][2];
/* Some inhibiting stuff */ /* Some inhibiting stuff */
#define HAS_ADVANCED_PROFILE 1 #define HAS_ADVANCED_PROFILE 0
#define TRACE 1 #define TRACE 1
#if TRACE #if TRACE
@ -190,7 +190,10 @@ typedef struct BitPlane {
uint8_t is_raw; ///< Bit values must be read at MB level uint8_t is_raw; ///< Bit values must be read at MB level
} BitPlane; } BitPlane;
/** The VC9 Context */ /** The VC9 Context
* @fixme Change size wherever another size is more efficient
* Many members are only used for Advanced Profile
*/
typedef struct VC9Context{ typedef struct VC9Context{
MpegEncContext s; MpegEncContext s;
@ -257,7 +260,13 @@ typedef struct VC9Context{
uint8_t dqsbedge; uint8_t dqsbedge;
uint8_t dqbilevel; uint8_t dqbilevel;
//@} //@}
int ac_table_level; ///< Index for AC tables from ACFRM element /** AC coding set indexes
* @see 8.1.1.10, p(1)10
*/
//@{
int c_ac_table_index; ///< Chroma index from ACFRM element
int y_ac_table_index; ///< Luma index from AC2FRM element
//@}
int ttfrm; ///< Transform type info present at frame level int ttfrm; ///< Transform type info present at frame level
uint8_t ttmbf; ///< Transform type flag uint8_t ttmbf; ///< Transform type flag
int ttmb; ///< Transform type int ttmb; ///< Transform type
@ -312,7 +321,6 @@ typedef struct VC9Context{
BitPlane over_flags_plane; ///< Overflags bitplane BitPlane over_flags_plane; ///< Overflags bitplane
uint8_t condover; uint8_t condover;
uint16_t *hrd_rate, *hrd_buffer; uint16_t *hrd_rate, *hrd_buffer;
int ac2_table_level; ///< Index for AC2 tables from AC2FRM element
//@} //@}
#endif #endif
} VC9Context; } VC9Context;
@ -1145,13 +1153,14 @@ static int decode_b_picture_primary_header(VC9Context *v)
if (pqindex < 9) v->halfpq = get_bits(gb, 1); if (pqindex < 9) v->halfpq = get_bits(gb, 1);
if (v->quantizer_mode == QUANT_FRAME_EXPLICIT) if (v->quantizer_mode == QUANT_FRAME_EXPLICIT)
v->pquantizer = get_bits(gb, 1); v->pquantizer = get_bits(gb, 1);
#if HAS_ADVANCED_PROFILE
if (v->profile == PROFILE_ADVANCED) if (v->profile == PROFILE_ADVANCED)
{ {
if (v->postprocflag) v->postproc = get_bits(gb, 2); if (v->postprocflag) v->postproc = get_bits(gb, 2);
if (v->extended_mv == 1 && v->s.pict_type != BI_TYPE) if (v->extended_mv == 1 && v->s.pict_type != BI_TYPE)
v->mvrange = get_prefix(gb, 0, 3); v->mvrange = get_prefix(gb, 0, 3);
} }
#endif
else else
{ {
if (v->extended_mv == 1) if (v->extended_mv == 1)
@ -1285,12 +1294,13 @@ static int decode_i_picture_primary_header(VC9Context *v)
/** I frame header decoding, secondary part /** I frame header decoding, secondary part
* @param v VC9 context * @param v VC9 context
* @return Status * @return Status
* @warning Not called in A/S/C profiles, it seems
* @todo Support Advanced Profile headers * @todo Support Advanced Profile headers
*/ */
static int decode_i_picture_secondary_header(VC9Context *v) static int decode_i_picture_secondary_header(VC9Context *v)
{ {
int status;
#if HAS_ADVANCED_PROFILE #if HAS_ADVANCED_PROFILE
int status;
if (v->profile == PROFILE_ADVANCED) if (v->profile == PROFILE_ADVANCED)
{ {
v->s.ac_pred = get_bits(&v->s.gb, 1); v->s.ac_pred = get_bits(&v->s.gb, 1);
@ -1492,10 +1502,10 @@ static int standard_decode_picture_secondary_header(VC9Context *v)
if (status < 0) return FRAME_SKIPED; if (status < 0) return FRAME_SKIPED;
/* AC Syntax */ /* AC Syntax */
v->ac_table_level = decode012(gb); v->c_ac_table_index = decode012(gb);
if (v->s.pict_type == I_TYPE || v->s.pict_type == BI_TYPE) if (v->s.pict_type == I_TYPE || v->s.pict_type == BI_TYPE)
{ {
v->ac2_table_level = decode012(gb); v->y_ac_table_index = decode012(gb);
} }
/* DC Syntax */ /* DC Syntax */
v->s.dc_table_index = decode012(gb); v->s.dc_table_index = decode012(gb);
@ -1592,10 +1602,10 @@ static int advanced_decode_picture_secondary_header(VC9Context *v)
if (status<0) return FRAME_SKIPED; if (status<0) return FRAME_SKIPED;
/* AC Syntax */ /* AC Syntax */
v->ac_table_level = decode012(gb); v->c_ac_table_index = decode012(gb);
if (v->s.pict_type == I_TYPE || v->s.pict_type == BI_TYPE) if (v->s.pict_type == I_TYPE || v->s.pict_type == BI_TYPE)
{ {
v->ac2_table_level = decode012(gb); v->y_ac_table_index = decode012(gb);
} }
/* DC Syntax */ /* DC Syntax */
v->s.dc_table_index = decode012(gb); v->s.dc_table_index = decode012(gb);
@ -1616,6 +1626,8 @@ static int advanced_decode_picture_secondary_header(VC9Context *v)
/** /**
* @def GET_MQUANT * @def GET_MQUANT
* @brief Get macroblock-level quantizer scale * @brief Get macroblock-level quantizer scale
* @warning XXX: qdiff to the frame quant, not previous quant ?
* @fixme XXX: Don't know how to initialize mquant otherwise in last case
*/ */
#define GET_MQUANT() \ #define GET_MQUANT() \
if (v->dquantfrm) \ if (v->dquantfrm) \
@ -1633,14 +1645,16 @@ static int advanced_decode_picture_secondary_header(VC9Context *v)
else mquant = get_bits(gb, 5); \ else mquant = get_bits(gb, 5); \
} \ } \
} \ } \
else mquant = v->pq; \
} }
/** /**
* @def GET_MVDATA(_dmv_x, _dmv_y) * @def GET_MVDATA(_dmv_x, _dmv_y)
* @brief Get MV differentials * @brief Get MV differentials
* @see MVDATA decoding from 8.3.5.2, p(1)20 * @see MVDATA decoding from 8.3.5.2, p(1)20
* @param dmv_x Horizontal differential for decoded MV * @param _dmv_x Horizontal differential for decoded MV
* @param dmv_y Vertical differential for decoded MV * @param _dmv_y Vertical differential for decoded MV
* @todo TODO: Use MpegEncContext arrays to store them
*/ */
#define GET_MVDATA(_dmv_x, _dmv_y) \ #define GET_MVDATA(_dmv_x, _dmv_y) \
index = 1 + get_vlc2(gb, vc9_mv_diff_vlc[s->mv_table_index].table,\ index = 1 + get_vlc2(gb, vc9_mv_diff_vlc[s->mv_table_index].table,\
@ -1678,19 +1692,28 @@ static int advanced_decode_picture_secondary_header(VC9Context *v)
/** Get predicted DC value /** Get predicted DC value
* prediction dir: left=0, top=1 * prediction dir: left=0, top=1
* @param s MpegEncContext
* @param[in] n block index in the current MB
* @param dc_val_ptr Pointer to DC predictor
* @param dir_ptr Prediction direction for use in AC prediction
* @todo TODO: Actually do it the VC9 way
* @todo TODO: Handle properly edges
*/ */
static inline int vc9_pred_dc(MpegEncContext *s, int n, static inline int vc9_pred_dc(MpegEncContext *s, int n,
uint16_t **dc_val_ptr, int *dir_ptr) uint16_t **dc_val_ptr, int *dir_ptr)
{ {
int a, b, c, wrap, pred, scale; int a, b, c, wrap, pred, scale;
int16_t *dc_val; int16_t *dc_val;
static const uint16_t dcpred[31] = {
1024, 512, 341, 256, 205, 171, 146, 128,
114, 102, 93, 85, 79, 73, 68, 64,
60, 57, 54, 51, 49, 47, 45, 43,
41, 39, 38, 37, 35, 34, 33
};
/* find prediction */ /* find prediction - wmv3_dc_scale always used here in fact */
if (n < 4) { if (n < 4) scale = s->y_dc_scale;
scale = s->y_dc_scale; else scale = s->c_dc_scale;
} else {
scale = s->c_dc_scale;
}
wrap = s->block_wrap[n]; wrap = s->block_wrap[n];
dc_val= s->dc_val[0] + s->block_index[n]; dc_val= s->dc_val[0] + s->block_index[n];
@ -1702,46 +1725,31 @@ static inline int vc9_pred_dc(MpegEncContext *s, int n,
b = dc_val[ - 1 - wrap]; b = dc_val[ - 1 - wrap];
c = dc_val[ - wrap]; c = dc_val[ - wrap];
if(s->first_slice_line && (n&2)==0) b=c=1024; /* XXX: Rule B is used only for I and BI frames in S/M/C profile
* with overlap filtering off
/* XXX: the following solution consumes divisions, but it does not
necessitate to modify mpegvideo.c. The problem comes from the
fact they decided to store the quantized DC (which would lead
to problems if Q could vary !) */
#if (defined(ARCH_X86) || defined(ARCH_X86_64)) && !defined PIC
asm volatile(
"movl %3, %%eax \n\t"
"shrl $1, %%eax \n\t"
"addl %%eax, %2 \n\t"
"addl %%eax, %1 \n\t"
"addl %0, %%eax \n\t"
"mull %4 \n\t"
"movl %%edx, %0 \n\t"
"movl %1, %%eax \n\t"
"mull %4 \n\t"
"movl %%edx, %1 \n\t"
"movl %2, %%eax \n\t"
"mull %4 \n\t"
"movl %%edx, %2 \n\t"
: "+b" (a), "+c" (b), "+D" (c)
: "g" (scale), "S" (inverse[scale])
: "%eax", "%edx"
);
#else
/* #elif defined (ARCH_ALPHA) */
/* Divisions are extremely costly on Alpha; optimize the most
common case. But they are costly everywhere...
*/ */
if (scale == 8) { if ((s->pict_type == I_TYPE || s->pict_type == BI_TYPE) &&
a = (a + (8 >> 1)) / 8; 1 /* XXX: overlap filtering off */)
b = (b + (8 >> 1)) / 8; {
c = (c + (8 >> 1)) / 8; /* Set outer values */
} else { if (s->first_slice_line && n!=2) b=c=dcpred[scale];
a = FASTDIV((a + (scale >> 1)), scale); if (s->mb_x == 0) b=a=dcpred[scale];
b = FASTDIV((b + (scale >> 1)), scale); }
c = FASTDIV((c + (scale >> 1)), scale); else
{
/* Set outer values */
if (s->first_slice_line && n!=2) b=c=0;
if (s->mb_x == 0) b=a=0;
/* XXX: Rule A needs to know if blocks are inter or intra :/ */
if (0)
{
/* update predictor */
*dc_val_ptr = &dc_val[0];
dir_ptr = 0;
return a;
}
} }
#endif
if (abs(a - b) <= abs(b - c)) { if (abs(a - b) <= abs(b - c)) {
pred = c; pred = c;
@ -1761,7 +1769,7 @@ static inline int vc9_pred_dc(MpegEncContext *s, int n,
* @param block 8x8 DCT block * @param block 8x8 DCT block
* @param n Block index in the current MB (<4=>luma) * @param n Block index in the current MB (<4=>luma)
* @param coded If the block is coded * @param coded If the block is coded
* @param MB quant, if decoded at the MB layer * @param mquant Quantizer step for the current block
* @see Inter TT: Table 21, p73 + p91-85 * @see Inter TT: Table 21, p73 + p91-85
* @see Intra TT: Table 20, p72 + p(1)05-(1)07 * @see Intra TT: Table 20, p72 + p(1)05-(1)07
* @todo TODO: Process the blocks * @todo TODO: Process the blocks
@ -1776,6 +1784,13 @@ int vc9_decode_block(VC9Context *v, DCTELEM block[64], int n, int coded, int mqu
int dc_pred_dir; /* Direction of the DC prediction used */ int dc_pred_dir; /* Direction of the DC prediction used */
int run_diff, i; int run_diff, i;
/* XXX: Guard against dumb values of mquant */
mquant = (mquant < 1) ? 0 : ( (mquant>31) ? 31 : mquant );
/* Set DC scale - y and c use the same */
s->y_dc_scale = s->y_dc_scale_table[mquant];
s->c_dc_scale = s->c_dc_scale_table[mquant];
if (s->mb_intra) if (s->mb_intra)
{ {
int dcdiff; int dcdiff;
@ -1788,7 +1803,7 @@ int vc9_decode_block(VC9Context *v, DCTELEM block[64], int n, int coded, int mqu
dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3); dcdiff = get_vlc2(&s->gb, ff_msmp4_dc_chroma_vlc[s->dc_table_index].table, DC_VLC_BITS, 3);
} }
if (dcdiff < 0){ if (dcdiff < 0){
av_log(s->avctx, AV_LOG_ERROR, "illegal dc vlc\n"); av_log(s->avctx, AV_LOG_ERROR, "Illegal DC VLC\n");
return -1; return -1;
} }
if (dcdiff) if (dcdiff)
@ -1813,18 +1828,20 @@ int vc9_decode_block(VC9Context *v, DCTELEM block[64], int n, int coded, int mqu
/* Prediction */ /* Prediction */
dcdiff += vc9_pred_dc(s, n, &dc_val, &dc_pred_dir); dcdiff += vc9_pred_dc(s, n, &dc_val, &dc_pred_dir);
*dc_val = dcdiff;
/* Store the quantized DC coeff, used for prediction */
if (n < 4) { if (n < 4) {
*dc_val = dcdiff * s->y_dc_scale; block[0] = dcdiff * s->y_dc_scale;
} else { } else {
*dc_val = dcdiff * s->c_dc_scale; block[0] = dcdiff * s->c_dc_scale;
} }
if (dcdiff < 0) if (block[0] < 0) {
{ #if TRACE
av_log(s->avctx, AV_LOG_ERROR, "DC=%i<0\n", dcdiff); //av_log(s->avctx, AV_LOG_ERROR, "DC=%i<0\n", dcdiff);
return -1; #endif
//return -1;
} }
block[0] = dcdiff; //XXX: Must be > 0
/* Skip ? */ /* Skip ? */
run_diff = 0; run_diff = 0;
i = 0; i = 0;
@ -1851,6 +1868,7 @@ int vc9_decode_block(VC9Context *v, DCTELEM block[64], int n, int coded, int mqu
} }
//TODO AC Decoding //TODO AC Decoding
i = 63; //XXX: nothing done yet
not_coded: not_coded:
@ -1901,6 +1919,9 @@ static inline int vc9_coded_block_pred(MpegEncContext * s, int n, uint8_t **code
return pred; return pred;
} }
/** Decode one I-frame MB (in Simple/Main profile)
* @todo TODO: Extend to AP
*/
int vc9_decode_i_mb(VC9Context *v, DCTELEM block[6][64]) int vc9_decode_i_mb(VC9Context *v, DCTELEM block[6][64])
{ {
int i, cbp, val; int i, cbp, val;
@ -1931,6 +1952,10 @@ int vc9_decode_i_mb(VC9Context *v, DCTELEM block[6][64])
return 0; return 0;
} }
/** Decode one P-frame MB (in Simple/Main profile)
* @todo TODO: Extend to AP
* @fixme FIXME: DC value for inter blocks not set
*/
int vc9_decode_p_mb(VC9Context *v, DCTELEM block[6][64]) int vc9_decode_p_mb(VC9Context *v, DCTELEM block[6][64])
{ {
MpegEncContext *s = &v->s; MpegEncContext *s = &v->s;
@ -1951,6 +1976,8 @@ int vc9_decode_p_mb(VC9Context *v, DCTELEM block[6][64])
int index, index1; /* LUT indices */ int index, index1; /* LUT indices */
int val, sign; /* temp values */ int val, sign; /* temp values */
mquant = v->pq; /* Loosy initialization */
if (v->mv_type_mb_plane.is_raw) if (v->mv_type_mb_plane.is_raw)
v->mv_type_mb_plane.data[mb_offset] = get_bits(gb, 1); v->mv_type_mb_plane.data[mb_offset] = get_bits(gb, 1);
if (v->skip_mb_plane.is_raw) if (v->skip_mb_plane.is_raw)
@ -1965,11 +1992,19 @@ int vc9_decode_p_mb(VC9Context *v, DCTELEM block[6][64])
if (v->mv_mode == MV_PMODE_1MV || if (v->mv_mode == MV_PMODE_1MV ||
v->mv_mode == MV_PMODE_MIXED_MV) v->mv_mode == MV_PMODE_MIXED_MV)
hybrid_pred = get_bits(gb, 1); hybrid_pred = get_bits(gb, 1);
/* FIXME Set DC val for inter block ? */
if (s->mb_intra && !mb_has_coeffs) if (s->mb_intra && !mb_has_coeffs)
{ {
GET_MQUANT(); GET_MQUANT();
s->ac_pred = get_bits(gb, 1); s->ac_pred = get_bits(gb, 1);
/* XXX: how to handle cbp ? */ /* XXX: how to handle cbp ? */
cbp = 0;
for (i=0; i<6; i++)
{
s->coded_block[s->block_index[i]] = 0;
vc9_decode_block(v, block[i], i, 0, mquant);
}
return 0;
} }
else if (mb_has_coeffs) else if (mb_has_coeffs)
{ {
@ -1980,12 +2015,15 @@ int vc9_decode_p_mb(VC9Context *v, DCTELEM block[6][64])
else else
{ {
mquant = v->pq; mquant = v->pq;
/* XXX: How to handle cbp ? */ /* XXX: how to handle cbp ? */
/* XXX: how to set values for following predictions ? */
cbp = 0;
} }
if (!v->ttmbf) if (!v->ttmbf)
ttmb = get_vlc2(gb, vc9_ttmb_vlc[v->tt_index].table, ttmb = get_vlc2(gb, vc9_ttmb_vlc[v->tt_index].table,
VC9_TTMB_VLC_BITS, 12); VC9_TTMB_VLC_BITS, 12);
for (i=0; i<6; i++) for (i=0; i<6; i++)
{ {
val = ((cbp >> (5 - i)) & 1); val = ((cbp >> (5 - i)) & 1);
@ -2029,6 +2067,7 @@ int vc9_decode_p_mb(VC9Context *v, DCTELEM block[6][64])
if (v->mv_mode == MV_PMODE_MIXED_MV /* Hybrid pred */) if (v->mv_mode == MV_PMODE_MIXED_MV /* Hybrid pred */)
hybrid_pred = get_bits(gb, 1); hybrid_pred = get_bits(gb, 1);
GET_MQUANT(); GET_MQUANT();
if (s->mb_intra /* One of the 4 blocks is intra */ && if (s->mb_intra /* One of the 4 blocks is intra */ &&
index /* non-zero pred for that block */) index /* non-zero pred for that block */)
s->ac_pred = get_bits(gb, 1); s->ac_pred = get_bits(gb, 1);
@ -2041,12 +2080,15 @@ int vc9_decode_p_mb(VC9Context *v, DCTELEM block[6][64])
} }
else //Skipped MB else //Skipped MB
{ {
/* XXX: Skipped => cbp=0 and mquant doesn't matter ? */
for (i=0; i<4; i++) for (i=0; i<4; i++)
{ {
if (v->mv_mode == MV_PMODE_MIXED_MV /* Hybrid pred */) if (v->mv_mode == MV_PMODE_MIXED_MV /* Hybrid pred */)
hybrid_pred = get_bits(gb, 1); hybrid_pred = get_bits(gb, 1);
vc9_decode_block(v, block[i], i, 0 /*cbp[i]*/, mquant); //FIXME vc9_decode_block(v, block[i], i, 0, v->pq); //FIXME
} }
vc9_decode_block(v, block[4], 4, 0, v->pq); //FIXME
vc9_decode_block(v, block[5], 5, 0, v->pq); //FIXME
/* TODO: blah */ /* TODO: blah */
return 0; return 0;
} }
@ -2056,328 +2098,16 @@ int vc9_decode_p_mb(VC9Context *v, DCTELEM block[6][64])
return -1; return -1;
} }
int vc9_decode_b_mb(VC9Context *v, DCTELEM block[6][64]) /** Decode one B-frame MB (in Simple/Main profile)
{ * @todo TODO: Extend to AP
int i; * @warning XXX: Used for decoding BI MBs
//Decode CBP * @fixme FIXME: DC value for inter blocks not set
for (i=0; i<6; i++)
{
vc9_decode_block(v, block[i], i, 0 /*cbp[i]*/, v->pq /*Should be mquant*/); //FIXME
}
return 0;
}
static int standard_decode_mbs(VC9Context *v)
{
GetBitContext *gb = &v->s.gb;
MpegEncContext *s = &v->s;
/* Set transform type info depending on pq */
if (v->pq < 5)
{
v->tt_index = 0;
v->ttblk4x4 = 3;
}
else if (v->pq < 13)
{
v->tt_index = 1;
v->ttblk4x4 = 3;
}
else
{
v->tt_index = 2;
v->ttblk4x4 = 2;
}
if (s->pict_type != I_TYPE)
{
/* Select proper long MV range */
switch (v->mvrange)
{
case 1: v->k_x = 10; v->k_y = 9; break;
case 2: v->k_x = 12; v->k_y = 10; break;
case 3: v->k_x = 13; v->k_y = 11; break;
default: /*case 0 too */ v->k_x = 9; v->k_y = 8; break;
}
s->mspel = v->mv_mode & 1; //MV_PMODE is HPEL
v->k_x -= s->mspel;
v->k_y -= s->mspel;
}
for (s->mb_y=0; s->mb_y<s->mb_height; s->mb_y++)
{
for (s->mb_x=0; s->mb_x<s->mb_width; s->mb_x++)
{
//FIXME Get proper MB DCTELEM
//TODO Move out of the loop
switch (s->pict_type)
{
case I_TYPE: vc9_decode_i_mb(v, NULL); break;
case P_TYPE: vc9_decode_i_mb(v, NULL); break;
case BI_TYPE:
case B_TYPE: vc9_decode_i_mb(v, NULL); break;
}
}
//Add a check for overconsumption ?
}
return 0;
}
/**
* @def GET_CBPCY(table, bits)
* @brief Get the Coded Block Pattern for luma and chroma
* @param table VLC table to use (get_vlc2 second parameter)
* @param bits Average bitlength (third parameter to get_vlc2)
* @see 8.1.1.5, p(1)02-(1)03
*/
#define GET_CBPCY(table, bits) \
predicted_cbpcy = get_vlc2(gb, table, bits, 2); \
cbpcy[0] = (p_cbpcy[-1] == p_cbpcy[2]) \
? previous_cbpcy[1] : p_cbpcy[+2]; \
cbpcy[0] ^= ((predicted_cbpcy>>5)&0x01); \
cbpcy[1] = (p_cbpcy[2] == p_cbpcy[3]) ? cbpcy[0] : p_cbpcy[3]; \
cbpcy[1] ^= ((predicted_cbpcy>>4)&0x01); \
cbpcy[2] = (previous_cbpcy[1] == cbpcy[0]) \
? previous_cbpcy[3] : cbpcy[0]; \
cbpcy[2] ^= ((predicted_cbpcy>>3)&0x01); \
cbpcy[3] = (cbpcy[1] == cbpcy[0]) ? cbpcy[2] : cbpcy[1]; \
cbpcy[3] ^= ((predicted_cbpcy>>2)&0x01);
/** Decode all MBs for an I frame in Simple/Main profile
* @see 8.1, p100
* @todo TODO: Process the blocks
* @todo TODO: Use M$ MPEG-4 cbp prediction
*/
static int standard_decode_i_mbs(VC9Context *v)
{
GetBitContext *gb = &v->s.gb;
MpegEncContext *s = &v->s;
int mb_offset = 0; /* MB/Block Position info */
uint8_t cbpcy[4], previous_cbpcy[4], predicted_cbpcy,
*p_cbpcy /* Pointer to skip some math */;
/* Reset CBPCY predictors */
memset(v->previous_line_cbpcy, 0, s->mb_stride<<2);
/* Select ttmb table depending on pq */
if (v->pq < 5)
{
v->tt_index = 0;
v->ttblk4x4 = 3;
}
else if (v->pq < 13)
{
v->tt_index = 1;
v->ttblk4x4 = 3;
}
else
{
v->tt_index = 2;
v->ttblk4x4 = 2;
}
for (s->mb_y=0; s->mb_y<s->mb_height; s->mb_y++)
{
/* Init CBPCY for line */
*((uint32_t*)previous_cbpcy) = 0x00000000;
p_cbpcy = v->previous_line_cbpcy+4;
for (s->mb_x=0; s->mb_x<s->mb_width; s->mb_x++, p_cbpcy += 4)
{
/* Get CBPCY */
GET_CBPCY(ff_msmp4_mb_i_vlc.table, MB_INTRA_VLC_BITS);
s->ac_pred = get_bits(gb, 1);
/* TODO: Decode blocks from that mb wrt cbpcy */
/* Update for next block */
#if TRACE > 2
av_log(s->avctx, AV_LOG_DEBUG, "Block %4i: p_cbpcy=%i%i%i%i, previous_cbpcy=%i%i%i%i,"
" cbpcy=%i%i%i%i\n", mb_offset,
p_cbpcy[0], p_cbpcy[1], p_cbpcy[2], p_cbpcy[3],
previous_cbpcy[0], previous_cbpcy[1], previous_cbpcy[2], previous_cbpcy[3],
cbpcy[0], cbpcy[1], cbpcy[2], cbpcy[3]);
#endif
*((uint32_t*)p_cbpcy) = *((uint32_t*)previous_cbpcy);
*((uint32_t*)previous_cbpcy) = *((uint32_t*)cbpcy);
mb_offset++;
}
}
return 0;
}
/** Decode all MBs for an P frame in Simple/Main profile
* @see 8.1, p(1)15
* @todo TODO: Process the blocks
* @todo TODO: Use M$ MPEG-4 cbp prediction
*/
static int decode_p_mbs(VC9Context *v)
{
MpegEncContext *s = &v->s;
GetBitContext *gb = &v->s.gb;
int mb_offset = 0, i; /* MB/Block Position info */
uint8_t cbpcy[4], previous_cbpcy[4], predicted_cbpcy,
*p_cbpcy /* Pointer to skip some math */;
int hybrid_pred; /* Prediction types */
int mv_mode_bit = 0;
int mqdiff, mquant; /* MB quantization */
int ttmb; /* MB Transform type */
static const int size_table[6] = { 0, 2, 3, 4, 5, 8 },
offset_table[6] = { 0, 1, 3, 7, 15, 31 };
int mb_has_coeffs = 1; /* last_flag */
int dmv_x, dmv_y; /* Differential MV components */
int index, index1; /* LUT indices */
int val, sign; /* MVDATA temp values */
/* Select ttmb table depending on pq */
if (v->pq < 5)
{
v->tt_index = 0;
v->ttblk4x4 = 3;
}
else if (v->pq < 13)
{
v->tt_index = 1;
v->ttblk4x4 = 3;
}
else
{
v->tt_index = 2;
v->ttblk4x4 = 2;
}
/* Select proper long MV range */
switch (v->mvrange)
{
case 1: v->k_x = 10; v->k_y = 9; break;
case 2: v->k_x = 12; v->k_y = 10; break;
case 3: v->k_x = 13; v->k_y = 11; break;
default: /*case 0 too */ v->k_x = 9; v->k_y = 8; break;
}
s->mspel = v->mv_mode & 1; //MV_PMODE is HPEL
v->k_x -= s->mspel;
v->k_y -= s->mspel;
/* Reset CBPCY predictors */
memset(v->previous_line_cbpcy, 0, s->mb_stride<<2);
for (s->mb_y=0; s->mb_y<s->mb_height; s->mb_y++)
{
/* Init CBPCY for line */
*((uint32_t*)previous_cbpcy) = 0x00000000;
p_cbpcy = v->previous_line_cbpcy+4;
for (s->mb_x=0; s->mb_x<s->mb_width; s->mb_x++, p_cbpcy += 4)
{
if (v->mv_type_mb_plane.is_raw)
v->mv_type_mb_plane.data[mb_offset] = get_bits(gb, 1);
if (v->skip_mb_plane.is_raw)
v->skip_mb_plane.data[mb_offset] = get_bits(gb, 1);
if (!mv_mode_bit) /* 1MV mode */
{
if (!v->skip_mb_plane.data[mb_offset])
{
GET_MVDATA(dmv_x, dmv_y);
/* hybrid mv pred, 8.3.5.3.4 */
if (v->mv_mode == MV_PMODE_1MV ||
v->mv_mode == MV_PMODE_MIXED_MV)
hybrid_pred = get_bits(gb, 1);
if (s->mb_intra && !mb_has_coeffs)
{
GET_MQUANT();
s->ac_pred = get_bits(gb, 1);
}
else if (mb_has_coeffs)
{
if (s->mb_intra) s->ac_pred = get_bits(gb, 1);
predicted_cbpcy = get_vlc2(gb, v->cbpcy_vlc->table, VC9_CBPCY_P_VLC_BITS, 2);
GET_CBPCY(v->cbpcy_vlc->table, VC9_CBPCY_P_VLC_BITS);
GET_MQUANT();
}
if (!v->ttmbf)
ttmb = get_vlc2(gb, vc9_ttmb_vlc[v->tt_index].table,
VC9_TTMB_VLC_BITS, 12);
/* TODO: decode blocks from that mb wrt cbpcy */
}
else //Skipped
{
/* hybrid mv pred, 8.3.5.3.4 */
if (v->mv_mode == MV_PMODE_1MV ||
v->mv_mode == MV_PMODE_MIXED_MV)
hybrid_pred = get_bits(gb, 1);
}
} //1MV mode
else //4MV mode
{
if (!v->skip_mb_plane.data[mb_offset] /* unskipped MB */)
{
/* Get CBPCY */
GET_CBPCY(v->cbpcy_vlc->table, VC9_CBPCY_P_VLC_BITS);
for (i=0; i<4; i++) //For all 4 Y blocks
{
if (cbpcy[i] /* cbpcy set for this block */)
{
GET_MVDATA(dmv_x, dmv_y);
}
if (v->mv_mode == MV_PMODE_MIXED_MV /* Hybrid pred */)
hybrid_pred = get_bits(gb, 1);
GET_MQUANT();
if (s->mb_intra /* One of the 4 blocks is intra */ &&
index /* non-zero pred for that block */)
s->ac_pred = get_bits(gb, 1);
if (!v->ttmbf)
ttmb = get_vlc2(gb, vc9_ttmb_vlc[v->tt_index].table,
VC9_TTMB_VLC_BITS, 12);
/* TODO: Process blocks wrt cbpcy */
}
}
else //Skipped MB
{
for (i=0; i<4; i++) //All 4 Y blocks
{
if (v->mv_mode == MV_PMODE_MIXED_MV /* Hybrid pred */)
hybrid_pred = get_bits(gb, 1);
/* TODO: do something */
}
}
}
/* Update for next block */
#if TRACE > 2
av_log(s->avctx, AV_LOG_DEBUG, "Block %4i: p_cbpcy=%i%i%i%i, previous_cbpcy=%i%i%i%i,"
" cbpcy=%i%i%i%i\n", mb_offset,
p_cbpcy[0], p_cbpcy[1], p_cbpcy[2], p_cbpcy[3],
previous_cbpcy[0], previous_cbpcy[1], previous_cbpcy[2], previous_cbpcy[3],
cbpcy[0], cbpcy[1], cbpcy[2], cbpcy[3]);
#endif
*((uint32_t*)p_cbpcy) = *((uint32_t*)previous_cbpcy);
*((uint32_t*)previous_cbpcy) = *((uint32_t*)cbpcy);
mb_offset++;
}
}
return 0;
}
/** Decode all MBs for an P frame in Simple/Main profile
* @todo TODO: Process the blocks
* @todo TODO: Use M$ MPEG-4 cbp prediction
*/ */
static int decode_b_mbs(VC9Context *v) int vc9_decode_b_mb(VC9Context *v, DCTELEM block[6][64])
{ {
MpegEncContext *s = &v->s; MpegEncContext *s = &v->s;
GetBitContext *gb = &v->s.gb; GetBitContext *gb = &v->s.gb;
int mb_offset = 0, i /* MB / B postion information */; int mb_offset, i /* MB / B postion information */;
int b_mv_type = BMV_TYPE_BACKWARD; int b_mv_type = BMV_TYPE_BACKWARD;
int mquant, mqdiff; /* MB quant stuff */ int mquant, mqdiff; /* MB quant stuff */
int ttmb; /* MacroBlock transform type */ int ttmb; /* MacroBlock transform type */
@ -2386,44 +2116,11 @@ static int decode_b_mbs(VC9Context *v)
offset_table[6] = { 0, 1, 3, 7, 15, 31 }; offset_table[6] = { 0, 1, 3, 7, 15, 31 };
int mb_has_coeffs = 1; /* last_flag */ int mb_has_coeffs = 1; /* last_flag */
int dmv1_x, dmv1_y, dmv2_x, dmv2_y; /* Differential MV components */ int dmv1_x, dmv1_y, dmv2_x, dmv2_y; /* Differential MV components */
int k_x, k_y; /* Long MV fixed bitlength */
int hpel_flag; /* Some MB properties */
int index, index1; /* LUT indices */ int index, index1; /* LUT indices */
int val, sign; /* MVDATA temp values */ int val, sign; /* MVDATA temp values */
/* Select proper long MV range */ mb_offset = s->mb_width*s->mb_y + s->mb_x; //FIXME: arrays aren't using stride
switch (v->mvrange)
{
case 1: k_x = 10; k_y = 9; break;
case 2: k_x = 12; k_y = 10; break;
case 3: k_x = 13; k_y = 11; break;
default: /*case 0 too */ k_x = 9; k_y = 8; break;
}
hpel_flag = v->mv_mode & 1; //MV_PMODE is HPEL
k_x -= hpel_flag;
k_y -= hpel_flag;
/* Select ttmb table depending on pq */
if (v->pq < 5)
{
v->tt_index = 0;
v->ttblk4x4 = 3;
}
else if (v->pq < 13)
{
v->tt_index = 1;
v->ttblk4x4 = 3;
}
else
{
v->tt_index = 2;
v->ttblk4x4 = 2;
}
for (s->mb_y=0; s->mb_y<s->mb_height; s->mb_y++)
{
for (s->mb_x=0; s->mb_x<s->mb_width; s->mb_x++)
{
if (v->direct_mb_plane.is_raw) if (v->direct_mb_plane.is_raw)
v->direct_mb_plane.data[mb_offset] = get_bits(gb, 1); v->direct_mb_plane.data[mb_offset] = get_bits(gb, 1);
if (v->skip_mb_plane.is_raw) if (v->skip_mb_plane.is_raw)
@ -2462,6 +2159,7 @@ static int decode_b_mbs(VC9Context *v)
if (b_mv_type == BMV_TYPE_INTERPOLATED) if (b_mv_type == BMV_TYPE_INTERPOLATED)
{ {
GET_MVDATA(dmv2_x, dmv2_y); GET_MVDATA(dmv2_x, dmv2_y);
mquant = v->pq; //FIXME: initialization not necessary ?
} }
/* GET_MVDATA has reset some stuff */ /* GET_MVDATA has reset some stuff */
if (mb_has_coeffs /* b_mv2 == "last" */) if (mb_has_coeffs /* b_mv2 == "last" */)
@ -2472,6 +2170,7 @@ static int decode_b_mbs(VC9Context *v)
} }
} }
} }
//End1 //End1
if (v->ttmbf) if (v->ttmbf)
ttmb = get_vlc2(gb, vc9_ttmb_vlc[v->tt_index].table, ttmb = get_vlc2(gb, vc9_ttmb_vlc[v->tt_index].table,
@ -2480,11 +2179,67 @@ static int decode_b_mbs(VC9Context *v)
//End2 //End2
for (i=0; i<6; i++) for (i=0; i<6; i++)
{ {
/* FIXME: process the block */ vc9_decode_block(v, block[i], i, 0 /*cbp[i]*/, mquant); //FIXME
} }
return 0;
}
mb_offset++; /** Decode all MBs for an I frame in Simple/Main profile
* @todo TODO: Move out of the loop the picture type case?
(branch prediction should help there though)
*/
static int standard_decode_mbs(VC9Context *v)
{
MpegEncContext *s = &v->s;
/* Set transform type info depending on pq */
if (v->pq < 5)
{
v->tt_index = 0;
v->ttblk4x4 = 3;
} }
else if (v->pq < 13)
{
v->tt_index = 1;
v->ttblk4x4 = 3;
}
else
{
v->tt_index = 2;
v->ttblk4x4 = 2;
}
if (s->pict_type != I_TYPE)
{
/* Select proper long MV range */
switch (v->mvrange)
{
case 1: v->k_x = 10; v->k_y = 9; break;
case 2: v->k_x = 12; v->k_y = 10; break;
case 3: v->k_x = 13; v->k_y = 11; break;
default: /*case 0 too */ v->k_x = 9; v->k_y = 8; break;
}
s->mspel = v->mv_mode & 1; //MV_PMODE is HPEL
v->k_x -= s->mspel;
v->k_y -= s->mspel;
}
for (s->mb_y=0; s->mb_y<s->mb_height; s->mb_y++)
{
for (s->mb_x=0; s->mb_x<s->mb_width; s->mb_x++)
{
//FIXME Get proper MB DCTELEM
//TODO Move out of the loop
switch (s->pict_type)
{
case I_TYPE: vc9_decode_i_mb(v, s->block); break;
case P_TYPE: vc9_decode_p_mb(v, s->block); break;
case BI_TYPE:
case B_TYPE: vc9_decode_b_mb(v, s->block); break;
}
}
//Add a check for overconsumption ?
} }
return 0; return 0;
} }
@ -2612,7 +2367,7 @@ static int vc9_decode_frame(AVCodecContext *avctx,
{ {
VC9Context *v = avctx->priv_data; VC9Context *v = avctx->priv_data;
MpegEncContext *s = &v->s; MpegEncContext *s = &v->s;
int ret = FRAME_SKIPED, len, start_code; int ret = FRAME_SKIPED, len;
AVFrame *pict = data; AVFrame *pict = data;
uint8_t *tmp_buf; uint8_t *tmp_buf;
v->s.avctx = avctx; v->s.avctx = avctx;
@ -2782,14 +2537,7 @@ static int vc9_decode_frame(AVCodecContext *avctx,
else else
#endif #endif
{ {
switch(s->pict_type) ret = standard_decode_mbs(v);
{
case I_TYPE: ret = standard_decode_i_mbs(v); break;
case P_TYPE: ret = decode_p_mbs(v); break;
case B_TYPE:
case BI_TYPE: ret = decode_b_mbs(v); break;
default: ret = FRAME_SKIPED;
}
if (ret == FRAME_SKIPED) return buf_size; if (ret == FRAME_SKIPED) return buf_size;
} }

Loading…
Cancel
Save