vlc->table = &table_data[table_offs[num]];
vlc->table_allocated = table_offs[num + 1] - table_offs[num];
- init_vlc_sparse(vlc, FFMIN(maxbits, 9), realsize,
- bits2, 1, 1,
- cw, 2, 2,
- syms, 2, 2, INIT_VLC_USE_NEW_STATIC);
+ ff_init_vlc_sparse(vlc, FFMIN(maxbits, 9), realsize,
+ bits2, 1, 1,
+ cw, 2, 2,
+ syms, 2, 2, INIT_VLC_USE_NEW_STATIC);
}
/**
{
int flags = modulo_three_table[code];
- decode_coeff( dst+0, (flags >> 6) , 3, gb, vlc, q);
+ decode_coeff( dst+0*4+0, (flags >> 6) , 3, gb, vlc, q);
if(is_block2){
- decode_coeff(dst+8, (flags >> 4) & 3, 2, gb, vlc, q);
- decode_coeff(dst+1, (flags >> 2) & 3, 2, gb, vlc, q);
+ decode_coeff(dst+1*4+0, (flags >> 4) & 3, 2, gb, vlc, q);
+ decode_coeff(dst+0*4+1, (flags >> 2) & 3, 2, gb, vlc, q);
}else{
- decode_coeff(dst+1, (flags >> 4) & 3, 2, gb, vlc, q);
- decode_coeff(dst+8, (flags >> 2) & 3, 2, gb, vlc, q);
+ decode_coeff(dst+0*4+1, (flags >> 4) & 3, 2, gb, vlc, q);
+ decode_coeff(dst+1*4+0, (flags >> 2) & 3, 2, gb, vlc, q);
}
- decode_coeff( dst+9, (flags >> 0) & 3, 2, gb, vlc, q);
+ decode_coeff( dst+1*4+1, (flags >> 0) & 3, 2, gb, vlc, q);
}
/**
decode_coeff(dst, coeff, 3, gb, vlc, q);
}
-static inline void decode_subblock3(DCTELEM *dst, int code, const int is_block2, GetBitContext *gb, VLC *vlc,
+static inline void decode_subblock3(DCTELEM *dst, int code, GetBitContext *gb, VLC *vlc,
int q_dc, int q_ac1, int q_ac2)
{
int flags = modulo_three_table[code];
- decode_coeff( dst+0, (flags >> 6) , 3, gb, vlc, q_dc);
- if(is_block2){
- decode_coeff(dst+8, (flags >> 4) & 3, 2, gb, vlc, q_ac1);
- decode_coeff(dst+1, (flags >> 2) & 3, 2, gb, vlc, q_ac1);
- }else{
- decode_coeff(dst+1, (flags >> 4) & 3, 2, gb, vlc, q_ac1);
- decode_coeff(dst+8, (flags >> 2) & 3, 2, gb, vlc, q_ac1);
- }
- decode_coeff( dst+9, (flags >> 0) & 3, 2, gb, vlc, q_ac2);
+ decode_coeff(dst+0*4+0, (flags >> 6) , 3, gb, vlc, q_dc);
+ decode_coeff(dst+0*4+1, (flags >> 4) & 3, 2, gb, vlc, q_ac1);
+ decode_coeff(dst+1*4+0, (flags >> 2) & 3, 2, gb, vlc, q_ac1);
+ decode_coeff(dst+1*4+1, (flags >> 0) & 3, 2, gb, vlc, q_ac2);
}
/**
* o--o
*/
-static inline int rv34_decode_block(DCTELEM *dst, GetBitContext *gb, RV34VLC *rvlc, int fc, int sc, int q_dc, int q_ac1, int q_ac2)
+static int rv34_decode_block(DCTELEM *dst, GetBitContext *gb, RV34VLC *rvlc, int fc, int sc, int q_dc, int q_ac1, int q_ac2)
{
int code, pattern, has_ac = 1;
code >>= 3;
if (modulo_three_table[code] & 0x3F) {
- decode_subblock3(dst, code, 0, gb, &rvlc->coefficient, q_dc, q_ac1, q_ac2);
+ decode_subblock3(dst, code, gb, &rvlc->coefficient, q_dc, q_ac1, q_ac2);
} else {
decode_subblock1(dst, code, gb, &rvlc->coefficient, q_dc);
if (!pattern)
if(pattern & 4){
code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2);
- decode_subblock(dst + 2, code, 0, gb, &rvlc->coefficient, q_ac2);
+ decode_subblock(dst + 4*0+2, code, 0, gb, &rvlc->coefficient, q_ac2);
}
if(pattern & 2){ // Looks like coefficients 1 and 2 are swapped for this block
code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2);
- decode_subblock(dst + 8*2, code, 1, gb, &rvlc->coefficient, q_ac2);
+ decode_subblock(dst + 4*2+0, code, 1, gb, &rvlc->coefficient, q_ac2);
}
if(pattern & 1){
code = get_vlc2(gb, rvlc->third_pattern[sc].table, 9, 2);
- decode_subblock(dst + 8*2+2, code, 0, gb, &rvlc->coefficient, q_ac2);
+ decode_subblock(dst + 4*2+2, code, 0, gb, &rvlc->coefficient, q_ac2);
}
- return has_ac || pattern;
+ return has_ac | pattern;
}
/**
int A[2] = {0}, B[2], C[2];
int i, j;
int mx, my;
- int avail_index = avail_indexes[subblock_no];
+ int* avail = r->avail_cache + avail_indexes[subblock_no];
int c_off = part_sizes_w[block_type];
mv_pos += (subblock_no & 1) + (subblock_no >> 1)*s->b8_stride;
if(subblock_no == 3)
c_off = -1;
- if(r->avail_cache[avail_index - 1]){
+ if(avail[-1]){
A[0] = s->current_picture_ptr->f.motion_val[0][mv_pos-1][0];
A[1] = s->current_picture_ptr->f.motion_val[0][mv_pos-1][1];
}
- if(r->avail_cache[avail_index - 4]){
+ if(avail[-4]){
B[0] = s->current_picture_ptr->f.motion_val[0][mv_pos-s->b8_stride][0];
B[1] = s->current_picture_ptr->f.motion_val[0][mv_pos-s->b8_stride][1];
}else{
B[0] = A[0];
B[1] = A[1];
}
- if(!r->avail_cache[avail_index - 4 + c_off]){
- if(r->avail_cache[avail_index - 4] && (r->avail_cache[avail_index - 1] || r->rv30)){
+ if(!avail[c_off-4]){
+ if(avail[-4] && (avail[-1] || r->rv30)){
C[0] = s->current_picture_ptr->f.motion_val[0][mv_pos-s->b8_stride-1][0];
C[1] = s->current_picture_ptr->f.motion_val[0][mv_pos-s->b8_stride-1][1];
}else{
*/
static int calc_add_mv(RV34DecContext *r, int dir, int val)
{
- int mul = dir ? -r->weight2 : r->weight1;
+ int mul = dir ? -r->mv_weight2 : r->mv_weight1;
return (val * mul + 0x2000) >> 14;
}
MpegEncContext *s = &r->s;
int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
int mv_pos = s->mb_x * 2 + s->mb_y * 2 * s->b8_stride;
- int A[2], B[2], C[2];
+ int A[2] = { 0 }, B[2] = { 0 }, C[2] = { 0 };
int has_A = 0, has_B = 0, has_C = 0;
int mx, my;
int i, j;
const int mask = dir ? MB_TYPE_L1 : MB_TYPE_L0;
int type = cur_pic->f.mb_type[mb_pos];
- memset(A, 0, sizeof(A));
- memset(B, 0, sizeof(B));
- memset(C, 0, sizeof(C));
if((r->avail_cache[6-1] & type) & mask){
A[0] = cur_pic->f.motion_val[dir][mv_pos - 1][0];
A[1] = cur_pic->f.motion_val[dir][mv_pos - 1][1];
int A[2] = {0}, B[2], C[2];
int i, j, k;
int mx, my;
- int avail_index = avail_indexes[0];
+ int* avail = r->avail_cache + avail_indexes[0];
- if(r->avail_cache[avail_index - 1]){
+ if(avail[-1]){
A[0] = s->current_picture_ptr->f.motion_val[0][mv_pos - 1][0];
A[1] = s->current_picture_ptr->f.motion_val[0][mv_pos - 1][1];
}
- if(r->avail_cache[avail_index - 4]){
+ if(avail[-4]){
B[0] = s->current_picture_ptr->f.motion_val[0][mv_pos - s->b8_stride][0];
B[1] = s->current_picture_ptr->f.motion_val[0][mv_pos - s->b8_stride][1];
}else{
B[0] = A[0];
B[1] = A[1];
}
- if(!r->avail_cache[avail_index - 4 + 2]){
- if(r->avail_cache[avail_index - 4] && (r->avail_cache[avail_index - 1])){
+ if(!avail[-4 + 2]){
+ if(avail[-4] && (avail[-1])){
C[0] = s->current_picture_ptr->f.motion_val[0][mv_pos - s->b8_stride - 1][0];
C[1] = s->current_picture_ptr->f.motion_val[0][mv_pos - s->b8_stride - 1][1];
}else{
if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME)) {
/* wait for the referenced mb row to be finished */
- int mb_row = FFMIN(s->mb_height - 1,
- s->mb_y + ((yoff + my + 5 + 8 * height) >> 4));
+ int mb_row = s->mb_y + ((yoff + my + 5 + 8 * height) >> 4);
AVFrame *f = dir ? &s->next_picture_ptr->f : &s->last_picture_ptr->f;
ff_thread_await_progress(f, mb_row, 0);
}
static void rv4_weight(RV34DecContext *r)
{
- r->rdsp.rv40_weight_pixels_tab[0](r->s.dest[0],
- r->tmp_b_block_y[0],
- r->tmp_b_block_y[1],
- r->weight1,
- r->weight2,
- r->s.linesize);
- r->rdsp.rv40_weight_pixels_tab[1](r->s.dest[1],
- r->tmp_b_block_uv[0],
- r->tmp_b_block_uv[2],
- r->weight1,
- r->weight2,
- r->s.uvlinesize);
- r->rdsp.rv40_weight_pixels_tab[1](r->s.dest[2],
- r->tmp_b_block_uv[1],
- r->tmp_b_block_uv[3],
- r->weight1,
- r->weight2,
- r->s.uvlinesize);
+ r->rdsp.rv40_weight_pixels_tab[r->scaled_weight][0](r->s.dest[0],
+ r->tmp_b_block_y[0],
+ r->tmp_b_block_y[1],
+ r->weight1,
+ r->weight2,
+ r->s.linesize);
+ r->rdsp.rv40_weight_pixels_tab[r->scaled_weight][1](r->s.dest[1],
+ r->tmp_b_block_uv[0],
+ r->tmp_b_block_uv[2],
+ r->weight1,
+ r->weight2,
+ r->s.uvlinesize);
+ r->rdsp.rv40_weight_pixels_tab[r->scaled_weight][1](r->s.dest[2],
+ r->tmp_b_block_uv[1],
+ r->tmp_b_block_uv[3],
+ r->weight1,
+ r->weight2,
+ r->s.uvlinesize);
}
static void rv34_mc_2mv(RV34DecContext *r, const int block_type)
return itype;
}
+static inline void rv34_process_block(RV34DecContext *r,
+ uint8_t *pdst, int stride,
+ int fc, int sc, int q_dc, int q_ac)
+{
+ MpegEncContext *s = &r->s;
+ DCTELEM *ptr = s->block[0];
+ int has_ac = rv34_decode_block(ptr, &s->gb, r->cur_vlcs,
+ fc, sc, q_dc, q_ac, q_ac);
+ if(has_ac){
+ r->rdsp.rv34_idct_add(pdst, stride, ptr);
+ }else{
+ r->rdsp.rv34_idct_dc_add(pdst, stride, ptr[0]);
+ ptr[0] = 0;
+ }
+}
+
static void rv34_output_i16x16(RV34DecContext *r, int8_t *intra_types, int cbp)
{
- LOCAL_ALIGNED_16(DCTELEM, block16, [64]);
+ LOCAL_ALIGNED_16(DCTELEM, block16, [16]);
MpegEncContext *s = &r->s;
- DSPContext *dsp = &s->dsp;
GetBitContext *gb = &s->gb;
int q_dc = rv34_qscale_tab[ r->luma_dc_quant_i[s->qscale] ],
q_ac = rv34_qscale_tab[s->qscale];
uint8_t *dst = s->dest[0];
DCTELEM *ptr = s->block[0];
- int avail[6*8] = {0};
int i, j, itype, has_ac;
- memset(block16, 0, 64 * sizeof(*block16));
-
- // Set neighbour information.
- if(r->avail_cache[1])
- avail[0] = 1;
- if(r->avail_cache[2])
- avail[1] = avail[2] = 1;
- if(r->avail_cache[3])
- avail[3] = avail[4] = 1;
- if(r->avail_cache[4])
- avail[5] = 1;
- if(r->avail_cache[5])
- avail[8] = avail[16] = 1;
- if(r->avail_cache[9])
- avail[24] = avail[32] = 1;
+ memset(block16, 0, 16 * sizeof(*block16));
has_ac = rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac);
if(has_ac)
- r->rdsp.rv34_inv_transform_tab[1](block16);
+ r->rdsp.rv34_inv_transform(block16);
else
- r->rdsp.rv34_inv_transform_dc_tab[1](block16);
+ r->rdsp.rv34_inv_transform_dc(block16);
itype = ittrans16[intra_types[0]];
itype = adjust_pred16(itype, r->avail_cache[6-4], r->avail_cache[6-1]);
r->h.pred16x16[itype](dst, s->linesize);
- dsp->clear_block(ptr);
for(j = 0; j < 4; j++){
for(i = 0; i < 4; i++, cbp >>= 1){
- int dc = block16[i + j*8];
+ int dc = block16[i + j*4];
if(cbp & 1){
has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac);
if(has_ac){
ptr[0] = dc;
r->rdsp.rv34_idct_add(dst+4*i, s->linesize, ptr);
- dsp->clear_block(ptr);
}else
r->rdsp.rv34_idct_dc_add(dst+4*i, s->linesize, dc);
}
if(!(cbp & 1)) continue;
pdst = dst + (i&1)*4 + (i&2)*2*s->uvlinesize;
- has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->chroma_vlc, 1, q_dc, q_ac, q_ac);
- if(has_ac){
- r->rdsp.rv34_idct_add(pdst, s->uvlinesize, ptr);
- dsp->clear_block(ptr);
- }else{
- r->rdsp.rv34_idct_dc_add(pdst, s->uvlinesize, ptr[0]);
- ptr[0] = 0;
- }
+ rv34_process_block(r, pdst, s->uvlinesize,
+ r->chroma_vlc, 1, q_dc, q_ac);
}
}
}
static void rv34_output_intra(RV34DecContext *r, int8_t *intra_types, int cbp)
{
MpegEncContext *s = &r->s;
- DSPContext *dsp = &s->dsp;
- GetBitContext *gb = &s->gb;
- DCTELEM *ptr = s->block[0];
uint8_t *dst = s->dest[0];
int avail[6*8] = {0};
int i, j, k;
- int idx, has_ac;
- int q_ac, q_dc;
+ int idx, q_ac, q_dc;
// Set neighbour information.
if(r->avail_cache[1])
avail[idx] = 1;
if(!(cbp & 1)) continue;
- has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac);
- if(has_ac){
- r->rdsp.rv34_idct_add(dst, s->linesize, ptr);
- dsp->clear_block(ptr);
- }else{
- r->rdsp.rv34_idct_dc_add(dst, s->linesize, ptr[0]);
- ptr[0] = 0;
- }
+ rv34_process_block(r, dst, s->linesize,
+ r->luma_vlc, 0, q_ac, q_ac);
}
dst += s->linesize * 4 - 4*4;
intra_types += r->intra_types_stride;
if(!(cbp&1)) continue;
- has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->chroma_vlc, 1, q_dc, q_ac, q_ac);
- if(has_ac){
- r->rdsp.rv34_idct_add(dst + 4*i, s->uvlinesize, ptr);
- dsp->clear_block(ptr);
- }
- else {
- r->rdsp.rv34_idct_dc_add(dst + 4*i, s->uvlinesize, ptr[0]);
- ptr[0] = 0;
- }
+ rv34_process_block(r, dst + 4*i, s->uvlinesize,
+ r->chroma_vlc, 1, q_dc, q_ac);
}
dst += 4*s->uvlinesize;
}
}
-/**
- * mask for retrieving all bits in coded block pattern
- * corresponding to one 8x8 block
- */
-#define LUMA_CBP_BLOCK_MASK 0x33
-
-#define U_CBP_MASK 0x0F0000
-#define V_CBP_MASK 0xF00000
-
-/** @} */ // recons group
-
-
-static void rv34_apply_differences(RV34DecContext *r, int cbp)
-{
- static const int shifts[4] = { 0, 2, 8, 10 };
- MpegEncContext *s = &r->s;
- int i;
-
- for(i = 0; i < 4; i++)
- if((cbp & (LUMA_CBP_BLOCK_MASK << shifts[i])) || r->block_type == RV34_MB_P_MIX16x16)
- s->dsp.add_pixels_clamped(s->block[i], s->dest[0] + (i & 1)*8 + (i&2)*4*s->linesize, s->linesize);
- if(cbp & U_CBP_MASK)
- s->dsp.add_pixels_clamped(s->block[4], s->dest[1], s->uvlinesize);
- if(cbp & V_CBP_MASK)
- s->dsp.add_pixels_clamped(s->block[5], s->dest[2], s->uvlinesize);
-}
-
static int is_mv_diff_gt_3(int16_t (*motion_val)[2], int step)
{
int d;
static int rv34_decode_inter_macroblock(RV34DecContext *r, int8_t *intra_types)
{
- MpegEncContext *s = &r->s;
- GetBitContext *gb = &s->gb;
+ MpegEncContext *s = &r->s;
+ GetBitContext *gb = &s->gb;
+ uint8_t *dst = s->dest[0];
+ DCTELEM *ptr = s->block[0];
+ int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
int cbp, cbp2;
int q_dc, q_ac, has_ac;
- int i, blknum, blkoff;
- LOCAL_ALIGNED_16(DCTELEM, block16, [64]);
+ int i, j;
int dist;
- int mb_pos = s->mb_x + s->mb_y * s->mb_stride;
// Calculate which neighbours are available. Maybe it's worth optimizing too.
memset(r->avail_cache, 0, sizeof(r->avail_cache));
}
if(r->is16){
- int luma_dc_quant = r->block_type == RV34_MB_P_MIX16x16
- ? r->luma_dc_quant_p[s->qscale]
- : r->luma_dc_quant_i[s->qscale];
- q_dc = rv34_qscale_tab[luma_dc_quant];
+ // Only for RV34_MB_P_MIX16x16
+ LOCAL_ALIGNED_16(DCTELEM, block16, [16]);
+ memset(block16, 0, 16 * sizeof(*block16));
+ q_dc = rv34_qscale_tab[ r->luma_dc_quant_p[s->qscale] ];
q_ac = rv34_qscale_tab[s->qscale];
- s->dsp.clear_block(block16);
if (rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac))
- r->rdsp.rv34_inv_transform_tab[1](block16);
+ r->rdsp.rv34_inv_transform(block16);
else
- r->rdsp.rv34_inv_transform_dc_tab[1](block16);
+ r->rdsp.rv34_inv_transform_dc(block16);
q_ac = rv34_qscale_tab[s->qscale];
- for(i = 0; i < 16; i++, cbp >>= 1){
- DCTELEM *ptr;
- blknum = ((i & 2) >> 1) + ((i & 8) >> 2);
- blkoff = ((i & 1) << 2) + ((i & 4) << 3);
- ptr = s->block[blknum] + blkoff;
- if(cbp & 1)
- has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac);
- else
- has_ac = 0;
- ptr[0] = block16[(i & 3) | ((i & 0xC) << 1)];
- if(has_ac)
- r->rdsp.rv34_inv_transform_tab[0](ptr);
- else
- r->rdsp.rv34_inv_transform_dc_tab[0](ptr);
+
+ for(j = 0; j < 4; j++){
+ for(i = 0; i < 4; i++, cbp >>= 1){
+ int dc = block16[i + j*4];
+
+ if(cbp & 1){
+ has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac);
+ }else
+ has_ac = 0;
+
+ if(has_ac){
+ ptr[0] = dc;
+ r->rdsp.rv34_idct_add(dst+4*i, s->linesize, ptr);
+ }else
+ r->rdsp.rv34_idct_dc_add(dst+4*i, s->linesize, dc);
+ }
+
+ dst += 4*s->linesize;
}
+
+ r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 1);
}else{
q_ac = rv34_qscale_tab[s->qscale];
- for(i = 0; i < 16; i++, cbp >>= 1){
- DCTELEM *ptr;
- if(!(cbp & 1)) continue;
- blknum = ((i & 2) >> 1) + ((i & 8) >> 2);
- blkoff = ((i & 1) << 2) + ((i & 4) << 3);
- ptr = s->block[blknum] + blkoff;
- has_ac = rv34_decode_block(ptr, gb, r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac);
- if(has_ac)
- r->rdsp.rv34_inv_transform_tab[0](ptr);
- else
- r->rdsp.rv34_inv_transform_dc_tab[0](ptr);
+
+ for(j = 0; j < 4; j++){
+ for(i = 0; i < 4; i++, cbp >>= 1){
+ if(!(cbp & 1)) continue;
+
+ rv34_process_block(r, dst + 4*i, s->linesize,
+ r->luma_vlc, 0, q_ac, q_ac);
+ }
+ dst += 4*s->linesize;
}
}
- if(r->block_type == RV34_MB_P_MIX16x16)
- r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 1);
+
q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]];
q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]];
- for(; i < 24; i++, cbp >>= 1){
- DCTELEM *ptr;
- if(!(cbp & 1)) continue;
- blknum = ((i & 4) >> 2) + 4;
- blkoff = ((i & 1) << 2) + ((i & 2) << 4);
- ptr = s->block[blknum] + blkoff;
- if (rv34_decode_block(ptr, gb, r->cur_vlcs, r->chroma_vlc, 1, q_dc, q_ac, q_ac))
- r->rdsp.rv34_inv_transform_tab[0](ptr);
- else
- r->rdsp.rv34_inv_transform_dc_tab[0](ptr);
+
+ for(j = 1; j < 3; j++){
+ dst = s->dest[j];
+ for(i = 0; i < 4; i++, cbp >>= 1){
+ uint8_t *pdst;
+ if(!(cbp & 1)) continue;
+ pdst = dst + (i&1)*4 + (i&2)*2*s->uvlinesize;
+
+ rv34_process_block(r, pdst, s->uvlinesize,
+ r->chroma_vlc, 1, q_dc, q_ac);
+ }
}
- rv34_apply_differences(r, cbp2);
return 0;
}
return 0;
}
+
+static void rv34_decoder_free(RV34DecContext *r)
+{
+ av_freep(&r->intra_types_hist);
+ r->intra_types = NULL;
+ av_freep(&r->tmp_b_block_base);
+ av_freep(&r->mb_type);
+ av_freep(&r->cbp_luma);
+ av_freep(&r->cbp_chroma);
+ av_freep(&r->deblock_coefs);
+}
+
+
+static int rv34_decoder_alloc(RV34DecContext *r)
+{
+ r->intra_types_stride = r->s.mb_width * 4 + 4;
+
+ r->cbp_chroma = av_malloc(r->s.mb_stride * r->s.mb_height *
+ sizeof(*r->cbp_chroma));
+ r->cbp_luma = av_malloc(r->s.mb_stride * r->s.mb_height *
+ sizeof(*r->cbp_luma));
+ r->deblock_coefs = av_malloc(r->s.mb_stride * r->s.mb_height *
+ sizeof(*r->deblock_coefs));
+ r->intra_types_hist = av_malloc(r->intra_types_stride * 4 * 2 *
+ sizeof(*r->intra_types_hist));
+ r->mb_type = av_mallocz(r->s.mb_stride * r->s.mb_height *
+ sizeof(*r->mb_type));
+
+ if (!(r->cbp_chroma && r->cbp_luma && r->deblock_coefs &&
+ r->intra_types_hist && r->mb_type)) {
+ rv34_decoder_free(r);
+ return AVERROR(ENOMEM);
+ }
+
+ r->intra_types = r->intra_types_hist + r->intra_types_stride * 4;
+
+ return 0;
+}
+
+
+static int rv34_decoder_realloc(RV34DecContext *r)
+{
+ rv34_decoder_free(r);
+ return rv34_decoder_alloc(r);
+}
+
+
static int rv34_decode_slice(RV34DecContext *r, int end, const uint8_t* buf, int buf_size)
{
MpegEncContext *s = &r->s;
GetBitContext *gb = &s->gb;
- int mb_pos;
+ int mb_pos, slice_type;
int res;
init_get_bits(&r->s.gb, buf, buf_size*8);
return -1;
}
- if ((s->mb_x == 0 && s->mb_y == 0) || s->current_picture_ptr==NULL) {
- if(s->width != r->si.width || s->height != r->si.height){
- av_log(s->avctx, AV_LOG_DEBUG, "Changing dimensions to %dx%d\n", r->si.width,r->si.height);
- MPV_common_end(s);
- s->width = r->si.width;
- s->height = r->si.height;
- avcodec_set_dimensions(s->avctx, s->width, s->height);
- if(MPV_common_init(s) < 0)
- return -1;
- r->intra_types_stride = s->mb_width*4 + 4;
- r->intra_types_hist = av_realloc(r->intra_types_hist, r->intra_types_stride * 4 * 2 * sizeof(*r->intra_types_hist));
- r->intra_types = r->intra_types_hist + r->intra_types_stride * 4;
- r->mb_type = av_realloc(r->mb_type, r->s.mb_stride * r->s.mb_height * sizeof(*r->mb_type));
- r->cbp_luma = av_realloc(r->cbp_luma, r->s.mb_stride * r->s.mb_height * sizeof(*r->cbp_luma));
- r->cbp_chroma = av_realloc(r->cbp_chroma, r->s.mb_stride * r->s.mb_height * sizeof(*r->cbp_chroma));
- r->deblock_coefs = av_realloc(r->deblock_coefs, r->s.mb_stride * r->s.mb_height * sizeof(*r->deblock_coefs));
- av_freep(&r->tmp_b_block_base);
- }
- s->pict_type = r->si.type ? r->si.type : AV_PICTURE_TYPE_I;
- if(MPV_frame_start(s, s->avctx) < 0)
- return -1;
- ff_er_frame_start(s);
- if (!r->tmp_b_block_base) {
- int i;
-
- r->tmp_b_block_base = av_malloc(s->linesize * 48);
- for (i = 0; i < 2; i++)
- r->tmp_b_block_y[i] = r->tmp_b_block_base + i * 16 * s->linesize;
- for (i = 0; i < 4; i++)
- r->tmp_b_block_uv[i] = r->tmp_b_block_base + 32 * s->linesize
- + (i >> 1) * 8 * s->uvlinesize + (i & 1) * 16;
- }
- r->cur_pts = r->si.pts;
- if(s->pict_type != AV_PICTURE_TYPE_B){
- r->last_pts = r->next_pts;
- r->next_pts = r->cur_pts;
- }else{
- int refdist = GET_PTS_DIFF(r->next_pts, r->last_pts);
- int dist0 = GET_PTS_DIFF(r->cur_pts, r->last_pts);
- int dist1 = GET_PTS_DIFF(r->next_pts, r->cur_pts);
-
- if(!refdist){
- r->weight1 = r->weight2 = 8192;
- }else{
- r->weight1 = (dist0 << 14) / refdist;
- r->weight2 = (dist1 << 14) / refdist;
- }
- }
- s->mb_x = s->mb_y = 0;
- ff_thread_finish_setup(s->avctx);
- } else {
- int slice_type = r->si.type ? r->si.type : AV_PICTURE_TYPE_I;
-
- if (slice_type != s->pict_type) {
- av_log(s->avctx, AV_LOG_ERROR, "Slice type mismatch\n");
- return AVERROR_INVALIDDATA;
- }
+ slice_type = r->si.type ? r->si.type : AV_PICTURE_TYPE_I;
+ if (slice_type != s->pict_type) {
+ av_log(s->avctx, AV_LOG_ERROR, "Slice type mismatch\n");
+ return AVERROR_INVALIDDATA;
}
r->si.end = end;
ff_init_block_index(s);
while(!check_slice_end(r, s)) {
ff_update_block_index(s);
- s->dsp.clear_blocks(s->block[0]);
if(r->si.type)
res = rv34_decode_inter_macroblock(r, r->intra_types + s->mb_x * 4 + 4);
{
RV34DecContext *r = avctx->priv_data;
MpegEncContext *s = &r->s;
+ int ret;
- MPV_decode_defaults(s);
+ ff_MPV_decode_defaults(s);
s->avctx = avctx;
s->out_format = FMT_H263;
s->codec_id = avctx->codec_id;
avctx->has_b_frames = 1;
s->low_delay = 0;
- if (MPV_common_init(s) < 0)
- return -1;
+ if ((ret = ff_MPV_common_init(s)) < 0)
+ return ret;
- ff_h264_pred_init(&r->h, CODEC_ID_RV40, 8, 1);
+ ff_h264_pred_init(&r->h, AV_CODEC_ID_RV40, 8, 1);
#if CONFIG_RV30_DECODER
- if (avctx->codec_id == CODEC_ID_RV30)
+ if (avctx->codec_id == AV_CODEC_ID_RV30)
ff_rv30dsp_init(&r->rdsp, &r->s.dsp);
#endif
#if CONFIG_RV40_DECODER
- if (avctx->codec_id == CODEC_ID_RV40)
+ if (avctx->codec_id == AV_CODEC_ID_RV40)
ff_rv40dsp_init(&r->rdsp, &r->s.dsp);
#endif
- r->intra_types_stride = 4*s->mb_stride + 4;
- r->intra_types_hist = av_malloc(r->intra_types_stride * 4 * 2 * sizeof(*r->intra_types_hist));
- r->intra_types = r->intra_types_hist + r->intra_types_stride * 4;
-
- r->mb_type = av_mallocz(r->s.mb_stride * r->s.mb_height * sizeof(*r->mb_type));
-
- r->cbp_luma = av_malloc(r->s.mb_stride * r->s.mb_height * sizeof(*r->cbp_luma));
- r->cbp_chroma = av_malloc(r->s.mb_stride * r->s.mb_height * sizeof(*r->cbp_chroma));
- r->deblock_coefs = av_malloc(r->s.mb_stride * r->s.mb_height * sizeof(*r->deblock_coefs));
+ if ((ret = rv34_decoder_alloc(r)) < 0)
+ return ret;
if(!intra_vlcs[0].cbppattern[0].bits)
rv34_init_tables();
int ff_rv34_decode_init_thread_copy(AVCodecContext *avctx)
{
+ int err;
RV34DecContext *r = avctx->priv_data;
r->s.avctx = avctx;
if (avctx->internal->is_copy) {
- r->cbp_chroma = av_malloc(r->s.mb_stride * r->s.mb_height *
- sizeof(*r->cbp_chroma));
- r->cbp_luma = av_malloc(r->s.mb_stride * r->s.mb_height *
- sizeof(*r->cbp_luma));
- r->deblock_coefs = av_malloc(r->s.mb_stride * r->s.mb_height *
- sizeof(*r->deblock_coefs));
- r->intra_types_hist = av_malloc(r->intra_types_stride * 4 * 2 *
- sizeof(*r->intra_types_hist));
- r->mb_type = av_malloc(r->s.mb_stride * r->s.mb_height *
- sizeof(*r->mb_type));
-
- if (!(r->cbp_chroma && r->cbp_luma && r->deblock_coefs &&
- r->intra_types_hist && r->mb_type)) {
- av_freep(&r->cbp_chroma);
- av_freep(&r->cbp_luma);
- av_freep(&r->deblock_coefs);
- av_freep(&r->intra_types_hist);
- av_freep(&r->mb_type);
- r->intra_types = NULL;
- return AVERROR(ENOMEM);
- }
-
- r->intra_types = r->intra_types_hist + r->intra_types_stride * 4;
r->tmp_b_block_base = NULL;
-
- memset(r->mb_type, 0, r->s.mb_stride * r->s.mb_height *
- sizeof(*r->mb_type));
-
- MPV_common_init(&r->s);
+ if ((err = ff_MPV_common_init(&r->s)) < 0)
+ return err;
+ if ((err = rv34_decoder_alloc(r)) < 0)
+ return err;
}
return 0;
}
if (dst == src || !s1->context_initialized)
return 0;
+ if (s->height != s1->height || s->width != s1->width) {
+ ff_MPV_common_end(s);
+ s->height = s1->height;
+ s->width = s1->width;
+ if ((err = ff_MPV_common_init(s)) < 0)
+ return err;
+ if ((err = rv34_decoder_realloc(r)) < 0)
+ return err;
+ }
+
if ((err = ff_mpeg_update_thread_context(dst, src)))
return err;
memset(&r->si, 0, sizeof(r->si));
- /* necessary since it is it the condition checked for in decode_slice
- * to call MPV_frame_start. cmp. comment at the end of decode_frame */
- s->current_picture_ptr = NULL;
-
return 0;
}
else return AV_RL32(buf + n*8 - 4) == 1 ? AV_RL32(buf + n*8) : AV_RB32(buf + n*8);
}
+static int finish_frame(AVCodecContext *avctx, AVFrame *pict)
+{
+ RV34DecContext *r = avctx->priv_data;
+ MpegEncContext *s = &r->s;
+ int got_picture = 0;
+
+ ff_er_frame_end(s);
+ ff_MPV_frame_end(s);
+ s->mb_num_left = 0;
+
+ if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME))
+ ff_thread_report_progress(&s->current_picture_ptr->f, INT_MAX, 0);
+
+ if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) {
+ *pict = s->current_picture_ptr->f;
+ got_picture = 1;
+ } else if (s->last_picture_ptr != NULL) {
+ *pict = s->last_picture_ptr->f;
+ got_picture = 1;
+ }
+ if (got_picture)
+ ff_print_debug_info(s, pict);
+
+ return got_picture;
+}
+
int ff_rv34_decode_frame(AVCodecContext *avctx,
- void *data, int *data_size,
+ void *data, int *got_picture_ptr,
AVPacket *avpkt)
{
const uint8_t *buf = avpkt->data;
if (buf_size == 0) {
/* special case for last picture */
if (s->low_delay==0 && s->next_picture_ptr) {
- *pict = *(AVFrame*)s->next_picture_ptr;
+ *pict = s->next_picture_ptr->f;
s->next_picture_ptr = NULL;
- *data_size = sizeof(AVFrame);
+ *got_picture_ptr = 1;
}
return 0;
}
if(get_slice_offset(avctx, slices_hdr, 0) < 0 ||
get_slice_offset(avctx, slices_hdr, 0) > buf_size){
av_log(avctx, AV_LOG_ERROR, "Slice offset is invalid\n");
- return -1;
+ return AVERROR_INVALIDDATA;
}
init_get_bits(&s->gb, buf+get_slice_offset(avctx, slices_hdr, 0), (buf_size-get_slice_offset(avctx, slices_hdr, 0))*8);
if(r->parse_slice_header(r, &r->s.gb, &si) < 0 || si.start){
av_log(avctx, AV_LOG_ERROR, "First slice header is incorrect\n");
- return -1;
+ return AVERROR_INVALIDDATA;
+ }
+ if ((!s->last_picture_ptr || !s->last_picture_ptr->f.data[0]) &&
+ si.type == AV_PICTURE_TYPE_B) {
+ av_log(avctx, AV_LOG_ERROR, "Invalid decoder state: B-frame without "
+ "reference data.\n");
+ return AVERROR_INVALIDDATA;
}
- if ((!s->last_picture_ptr || !s->last_picture_ptr->f.data[0]) && si.type == AV_PICTURE_TYPE_B)
- return -1;
if( (avctx->skip_frame >= AVDISCARD_NONREF && si.type==AV_PICTURE_TYPE_B)
|| (avctx->skip_frame >= AVDISCARD_NONKEY && si.type!=AV_PICTURE_TYPE_I)
|| avctx->skip_frame >= AVDISCARD_ALL)
return avpkt->size;
+ /* first slice */
+ if (si.start == 0) {
+ if (s->mb_num_left > 0) {
+ av_log(avctx, AV_LOG_ERROR, "New frame but still %d MB left.",
+ s->mb_num_left);
+ ff_er_frame_end(s);
+ ff_MPV_frame_end(s);
+ }
+
+ if (s->width != si.width || s->height != si.height) {
+ int err;
+
+ if (HAVE_THREADS &&
+ (s->avctx->active_thread_type & FF_THREAD_FRAME)) {
+ av_log_missing_feature(s->avctx, "Width/height changing with "
+ "frame threading is", 0);
+ return AVERROR_PATCHWELCOME;
+ }
+
+ av_log(s->avctx, AV_LOG_WARNING, "Changing dimensions to %dx%d\n",
+ si.width, si.height);
+ ff_MPV_common_end(s);
+ s->width = si.width;
+ s->height = si.height;
+ avcodec_set_dimensions(s->avctx, s->width, s->height);
+ if ((err = ff_MPV_common_init(s)) < 0)
+ return err;
+ if ((err = rv34_decoder_realloc(r)) < 0)
+ return err;
+ }
+ s->pict_type = si.type ? si.type : AV_PICTURE_TYPE_I;
+ if (ff_MPV_frame_start(s, s->avctx) < 0)
+ return -1;
+ ff_er_frame_start(s);
+ if (!r->tmp_b_block_base) {
+ int i;
+
+ r->tmp_b_block_base = av_malloc(s->linesize * 48);
+ for (i = 0; i < 2; i++)
+ r->tmp_b_block_y[i] = r->tmp_b_block_base
+ + i * 16 * s->linesize;
+ for (i = 0; i < 4; i++)
+ r->tmp_b_block_uv[i] = r->tmp_b_block_base + 32 * s->linesize
+ + (i >> 1) * 8 * s->uvlinesize
+ + (i & 1) * 16;
+ }
+ r->cur_pts = si.pts;
+ if (s->pict_type != AV_PICTURE_TYPE_B) {
+ r->last_pts = r->next_pts;
+ r->next_pts = r->cur_pts;
+ } else {
+ int refdist = GET_PTS_DIFF(r->next_pts, r->last_pts);
+ int dist0 = GET_PTS_DIFF(r->cur_pts, r->last_pts);
+ int dist1 = GET_PTS_DIFF(r->next_pts, r->cur_pts);
+
+ if(!refdist){
+ r->mv_weight1 = r->mv_weight2 = r->weight1 = r->weight2 = 8192;
+ r->scaled_weight = 0;
+ }else{
+ r->mv_weight1 = (dist0 << 14) / refdist;
+ r->mv_weight2 = (dist1 << 14) / refdist;
+ if((r->mv_weight1|r->mv_weight2) & 511){
+ r->weight1 = r->mv_weight1;
+ r->weight2 = r->mv_weight2;
+ r->scaled_weight = 0;
+ }else{
+ r->weight1 = r->mv_weight1 >> 9;
+ r->weight2 = r->mv_weight2 >> 9;
+ r->scaled_weight = 1;
+ }
+ }
+ }
+ s->mb_x = s->mb_y = 0;
+ ff_thread_finish_setup(s->avctx);
+ } else if (HAVE_THREADS &&
+ (s->avctx->active_thread_type & FF_THREAD_FRAME)) {
+ av_log(s->avctx, AV_LOG_ERROR, "Decoder needs full frames in frame "
+ "multithreading mode (start MB is %d).\n", si.start);
+ return AVERROR_INVALIDDATA;
+ }
+
for(i = 0; i < slice_count; i++){
int offset = get_slice_offset(avctx, slices_hdr, i);
int size;
}
r->si.end = s->mb_width * s->mb_height;
+ s->mb_num_left = r->s.mb_x + r->s.mb_y*r->s.mb_width - r->si.start;
+
if(i+1 < slice_count){
if (get_slice_offset(avctx, slices_hdr, i+1) < 0 ||
get_slice_offset(avctx, slices_hdr, i+1) > buf_size) {
break;
}
last = rv34_decode_slice(r, r->si.end, buf + offset, size);
- s->mb_num_left = r->s.mb_x + r->s.mb_y*r->s.mb_width - r->si.start;
if(last)
break;
}
- if(last && s->current_picture_ptr){
- if(r->loop_filter)
- r->loop_filter(r, s->mb_height - 1);
- if (HAVE_THREADS && (s->avctx->active_thread_type & FF_THREAD_FRAME))
- ff_thread_report_progress(&s->current_picture_ptr->f,
- s->mb_height - 1, 0);
- ff_er_frame_end(s);
- MPV_frame_end(s);
- if (s->pict_type == AV_PICTURE_TYPE_B || s->low_delay) {
- *pict = *(AVFrame*)s->current_picture_ptr;
- } else if (s->last_picture_ptr != NULL) {
- *pict = *(AVFrame*)s->last_picture_ptr;
- }
-
- if(s->last_picture_ptr || s->low_delay){
- *data_size = sizeof(AVFrame);
- ff_print_debug_info(s, pict);
+ if (s->current_picture_ptr) {
+ if (last) {
+ if(r->loop_filter)
+ r->loop_filter(r, s->mb_height - 1);
+
+ *got_picture_ptr = finish_frame(avctx, pict);
+ } else if (HAVE_THREADS &&
+ (s->avctx->active_thread_type & FF_THREAD_FRAME)) {
+ av_log(avctx, AV_LOG_INFO, "marking unfished frame as finished\n");
+ /* always mark the current frame as finished, frame-mt supports
+ * only complete frames */
+ ff_er_frame_end(s);
+ ff_MPV_frame_end(s);
+ s->mb_num_left = 0;
+ ff_thread_report_progress(&s->current_picture_ptr->f, INT_MAX, 0);
+ return AVERROR_INVALIDDATA;
}
- s->current_picture_ptr = NULL; //so we can detect if frame_end wasnt called (find some nicer solution...)
}
+
return avpkt->size;
}
{
RV34DecContext *r = avctx->priv_data;
- MPV_common_end(&r->s);
-
- av_freep(&r->intra_types_hist);
- r->intra_types = NULL;
- av_freep(&r->tmp_b_block_base);
- av_freep(&r->mb_type);
- av_freep(&r->cbp_luma);
- av_freep(&r->cbp_chroma);
- av_freep(&r->deblock_coefs);
+ ff_MPV_common_end(&r->s);
+ rv34_decoder_free(r);
return 0;
}