Пример #1
0
int ff_vaapi_common_end_frame(MpegEncContext *s)
{
    struct vaapi_context * const vactx = s->avctx->hwaccel_context;
    int ret = -1;

    av_dlog(s->avctx, "ff_vaapi_common_end_frame()\n");

    if (commit_slices(vactx) < 0)
        goto done;
    if (vactx->n_slice_buf_ids > 0) {
        if (render_picture(vactx, ff_vaapi_get_surface_id(s->current_picture_ptr)) < 0)
            goto done;
        ff_draw_horiz_band(s, 0, s->avctx->height);
    }
    ret = 0;

done:
    destroy_buffers(vactx->display, &vactx->pic_param_buf_id, 1);
    destroy_buffers(vactx->display, &vactx->iq_matrix_buf_id, 1);
    destroy_buffers(vactx->display, &vactx->bitplane_buf_id, 1);
    destroy_buffers(vactx->display, vactx->slice_buf_ids, vactx->n_slice_buf_ids);
    av_freep(&vactx->slice_buf_ids);
    av_freep(&vactx->slice_params);
    vactx->n_slice_buf_ids     = 0;
    vactx->slice_buf_ids_alloc = 0;
    vactx->slice_count         = 0;
    vactx->slice_params_alloc  = 0;
    return ret;
}
Пример #2
0
/**
 * Complete frame/field rendering by passing any remaining blocks.
 * Normally ff_draw_horiz_band() is called for each slice, however,
 * some leftover blocks, for example from error_resilience(), may remain.
 * It should be safe to call the function a few times for the same field.
 */
void ff_xvmc_field_end(MpegEncContext *s)
{
    struct xvmc_pix_fmt *render = (struct xvmc_pix_fmt*)s->current_picture.data[2];
    assert(render);

    if (render->filled_mv_blocks_num > 0)
        ff_draw_horiz_band(s, 0, 0);
}
Пример #3
0
void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf,
                                    int buf_size, int slice_count)
{
    struct vdpau_render_state *render, *last, *next;
    int i;

    if (!s->current_picture_ptr) return;

    render = (struct vdpau_render_state *)s->current_picture_ptr->data[0];
    assert(render);

    /* fill VdpPictureInfoMPEG1Or2 struct */
    render->info.mpeg.picture_structure          = s->picture_structure;
    render->info.mpeg.picture_coding_type        = s->pict_type;
    render->info.mpeg.intra_dc_precision         = s->intra_dc_precision;
    render->info.mpeg.frame_pred_frame_dct       = s->frame_pred_frame_dct;
    render->info.mpeg.concealment_motion_vectors = s->concealment_motion_vectors;
    render->info.mpeg.intra_vlc_format           = s->intra_vlc_format;
    render->info.mpeg.alternate_scan             = s->alternate_scan;
    render->info.mpeg.q_scale_type               = s->q_scale_type;
    render->info.mpeg.top_field_first            = s->top_field_first;
    render->info.mpeg.full_pel_forward_vector    = s->full_pel[0]; // MPEG-1 only.  Set 0 for MPEG-2
    render->info.mpeg.full_pel_backward_vector   = s->full_pel[1]; // MPEG-1 only.  Set 0 for MPEG-2
    render->info.mpeg.f_code[0][0]               = s->mpeg_f_code[0][0]; // For MPEG-1 fill both horiz. & vert.
    render->info.mpeg.f_code[0][1]               = s->mpeg_f_code[0][1];
    render->info.mpeg.f_code[1][0]               = s->mpeg_f_code[1][0];
    render->info.mpeg.f_code[1][1]               = s->mpeg_f_code[1][1];
    for (i = 0; i < 64; ++i) {
        render->info.mpeg.intra_quantizer_matrix[i]     = s->intra_matrix[i];
        render->info.mpeg.non_intra_quantizer_matrix[i] = s->inter_matrix[i];
    }

    render->info.mpeg.forward_reference          = VDP_INVALID_HANDLE;
    render->info.mpeg.backward_reference         = VDP_INVALID_HANDLE;

    switch(s->pict_type){
    case  FF_B_TYPE:
        next = (struct vdpau_render_state *)s->next_picture.data[0];
        assert(next);
        render->info.mpeg.backward_reference     = next->surface;
        // no return here, going to set forward prediction
    case  FF_P_TYPE:
        last = (struct vdpau_render_state *)s->last_picture.data[0];
        if (!last) // FIXME: Does this test make sense?
            last = render; // predict second field from the first
        render->info.mpeg.forward_reference      = last->surface;
    }

    ff_vdpau_add_data_chunk(s, buf, buf_size);

    render->info.mpeg.slice_count                = slice_count;

    if (slice_count)
        ff_draw_horiz_band(s, 0, s->avctx->height);
    render->bitstream_buffers_used               = 0;
}
Пример #4
0
void XVMC_field_end(MpegEncContext *s){
xvmc_render_state_t * render;
    render = (xvmc_render_state_t*)s->current_picture.data[2];
    assert(render != NULL);

    if(render->filled_mv_blocks_num > 0){
//        printf("xvmcvideo.c: rendering %d left blocks after last slice!!!\n",render->filled_mv_blocks_num );
        ff_draw_horiz_band(s,0,0);
    }
}
Пример #5
0
void ff_vdpau_mpeg4_decode_picture(MpegEncContext *s, const uint8_t *buf,
                                   int buf_size)
{
    struct vdpau_render_state *render, *last, *next;
    int i;

    if (!s->current_picture_ptr) return;

    render = (struct vdpau_render_state *)s->current_picture_ptr->data[0];
    assert(render);

    /* fill VdpPictureInfoMPEG4Part2 struct */
    render->info.mpeg4.trd[0]                            = s->pp_time;
    render->info.mpeg4.trb[0]                            = s->pb_time;
    render->info.mpeg4.trd[1]                            = s->pp_field_time >> 1;
    render->info.mpeg4.trb[1]                            = s->pb_field_time >> 1;
    render->info.mpeg4.vop_time_increment_resolution     = s->avctx->time_base.den;
    render->info.mpeg4.vop_coding_type                   = 0;
    render->info.mpeg4.vop_fcode_forward                 = s->f_code;
    render->info.mpeg4.vop_fcode_backward                = s->b_code;
    render->info.mpeg4.resync_marker_disable             = !s->resync_marker;
    render->info.mpeg4.interlaced                        = !s->progressive_sequence;
    render->info.mpeg4.quant_type                        = s->mpeg_quant;
    render->info.mpeg4.quarter_sample                    = s->quarter_sample;
    render->info.mpeg4.short_video_header                = s->avctx->codec->id == CODEC_ID_H263;
    render->info.mpeg4.rounding_control                  = s->no_rounding;
    render->info.mpeg4.alternate_vertical_scan_flag      = s->alternate_scan;
    render->info.mpeg4.top_field_first                   = s->top_field_first;
    for (i = 0; i < 64; ++i) {
        render->info.mpeg4.intra_quantizer_matrix[i]     = s->intra_matrix[i];
        render->info.mpeg4.non_intra_quantizer_matrix[i] = s->inter_matrix[i];
    }
    render->info.mpeg4.forward_reference                 = VDP_INVALID_HANDLE;
    render->info.mpeg4.backward_reference                = VDP_INVALID_HANDLE;

    switch (s->pict_type) {
    case FF_B_TYPE:
        next = (struct vdpau_render_state *)s->next_picture.data[0];
        assert(next);
        render->info.mpeg4.backward_reference     = next->surface;
        render->info.mpeg4.vop_coding_type        = 2;
        // no break here, going to set forward prediction
    case FF_P_TYPE:
        last = (struct vdpau_render_state *)s->last_picture.data[0];
        assert(last);
        render->info.mpeg4.forward_reference      = last->surface;
    }

    ff_vdpau_add_data_chunk(s, buf, buf_size);

    ff_draw_horiz_band(s, 0, s->avctx->height);
    render->bitstream_buffers_used = 0;
}
Пример #6
0
void ff_vdpau_h264_picture_complete(MpegEncContext *s)
{
    H264Context *h = s->avctx->priv_data;
    struct vdpau_render_state *render;
    int i;

    render = (struct vdpau_render_state *)s->current_picture_ptr->data[0];
    assert(render);

    render->info.h264.slice_count = h->slice_num;
    if (render->info.h264.slice_count < 1)
        return;

    for (i = 0; i < 2; ++i) {
        int foc = s->current_picture_ptr->field_poc[i];
        if (foc == INT_MAX)
            foc = 0;
        render->info.h264.field_order_cnt[i] = foc;
    }

    render->info.h264.is_reference                           = (s->current_picture_ptr->reference & 3) ? VDP_TRUE : VDP_FALSE;
    render->info.h264.frame_num                              = h->frame_num;
    render->info.h264.field_pic_flag                         = s->picture_structure != PICT_FRAME;
    render->info.h264.bottom_field_flag                      = s->picture_structure == PICT_BOTTOM_FIELD;
    render->info.h264.num_ref_frames                         = h->sps.ref_frame_count;
    render->info.h264.mb_adaptive_frame_field_flag           = h->sps.mb_aff && !render->info.h264.field_pic_flag;
    render->info.h264.constrained_intra_pred_flag            = h->pps.constrained_intra_pred;
    render->info.h264.weighted_pred_flag                     = h->pps.weighted_pred;
    render->info.h264.weighted_bipred_idc                    = h->pps.weighted_bipred_idc;
    render->info.h264.frame_mbs_only_flag                    = h->sps.frame_mbs_only_flag;
    render->info.h264.transform_8x8_mode_flag                = h->pps.transform_8x8_mode;
    render->info.h264.chroma_qp_index_offset                 = h->pps.chroma_qp_index_offset[0];
    render->info.h264.second_chroma_qp_index_offset          = h->pps.chroma_qp_index_offset[1];
    render->info.h264.pic_init_qp_minus26                    = h->pps.init_qp - 26;
    render->info.h264.num_ref_idx_l0_active_minus1           = h->pps.ref_count[0] - 1;
    render->info.h264.num_ref_idx_l1_active_minus1           = h->pps.ref_count[1] - 1;
    render->info.h264.log2_max_frame_num_minus4              = h->sps.log2_max_frame_num - 4;
    render->info.h264.pic_order_cnt_type                     = h->sps.poc_type;
    render->info.h264.log2_max_pic_order_cnt_lsb_minus4      = h->sps.poc_type ? 0 : h->sps.log2_max_poc_lsb - 4;
    render->info.h264.delta_pic_order_always_zero_flag       = h->sps.delta_pic_order_always_zero_flag;
    render->info.h264.direct_8x8_inference_flag              = h->sps.direct_8x8_inference_flag;
    render->info.h264.entropy_coding_mode_flag               = h->pps.cabac;
    render->info.h264.pic_order_present_flag                 = h->pps.pic_order_present;
    render->info.h264.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
    render->info.h264.redundant_pic_cnt_present_flag         = h->pps.redundant_pic_cnt_present;
    memcpy(render->info.h264.scaling_lists_4x4, h->pps.scaling_matrix4, sizeof(render->info.h264.scaling_lists_4x4));
    memcpy(render->info.h264.scaling_lists_8x8, h->pps.scaling_matrix8, sizeof(render->info.h264.scaling_lists_8x8));

    ff_draw_horiz_band(s, 0, s->avctx->height);
    render->bitstream_buffers_used = 0;
}
Пример #7
0
int ff_vdpau_common_end_frame(AVCodecContext *avctx)
{
    MpegEncContext * const s = avctx->priv_data;
    AVVDPAUContext *hwctx = avctx->hwaccel_context;

    if (hwctx->bitstream_buffers_used) {
        VdpVideoSurface surf = ff_vdpau_get_surface_id(s->current_picture_ptr);

        hwctx->render(hwctx->decoder, surf, (void *)&hwctx->info,
                      hwctx->bitstream_buffers_used, hwctx->bitstream_buffers);

        ff_draw_horiz_band(s, 0, s->avctx->height);
        hwctx->bitstream_buffers_used = 0;
    }
    return 0;
}
Пример #8
0
static int decode_slice(MpegEncContext *s){
    const int part_mask= s->partitioned_frame ? (ER_AC_END|ER_AC_ERROR) : 0x7F;
    const int mb_size= 16>>s->avctx->lowres;
    s->last_resync_gb= s->gb;
    s->first_slice_line= 1;

    s->resync_mb_x= s->mb_x;
    s->resync_mb_y= s->mb_y;

    ff_set_qscale(s, s->qscale);

    if (s->avctx->hwaccel) {
        const uint8_t *start= s->gb.buffer + get_bits_count(&s->gb)/8;
        const uint8_t *end  = ff_h263_find_resync_marker(start + 1, s->gb.buffer_end);
        skip_bits_long(&s->gb, 8*(end - start));
        return s->avctx->hwaccel->decode_slice(s->avctx, start, end - start);
    }

    if(s->partitioned_frame){
        const int qscale= s->qscale;

        if(CONFIG_MPEG4_DECODER && s->codec_id==CODEC_ID_MPEG4){
            if(ff_mpeg4_decode_partitions(s) < 0)
                return -1;
        }

        /* restore variables which were modified */
        s->first_slice_line=1;
        s->mb_x= s->resync_mb_x;
        s->mb_y= s->resync_mb_y;
        ff_set_qscale(s, qscale);
    }

    for(; s->mb_y < s->mb_height; s->mb_y++) {
        /* per-row end of slice checks */
        if(s->msmpeg4_version){
            if(s->resync_mb_y + s->slice_height == s->mb_y){
                ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, ER_MB_END);

                return 0;
            }
        }

        if(s->msmpeg4_version==1){
            s->last_dc[0]=
            s->last_dc[1]=
            s->last_dc[2]= 128;
        }

        ff_init_block_index(s);
        for(; s->mb_x < s->mb_width; s->mb_x++) {
            int ret;

            ff_update_block_index(s);

            if(s->resync_mb_x == s->mb_x && s->resync_mb_y+1 == s->mb_y){
                s->first_slice_line=0;
            }

            /* DCT & quantize */

            s->mv_dir = MV_DIR_FORWARD;
            s->mv_type = MV_TYPE_16X16;
//            s->mb_skipped = 0;
//printf("%d %d %06X\n", ret, get_bits_count(&s->gb), show_bits(&s->gb, 24));
            ret= s->decode_mb(s, s->block);

            if (s->pict_type!=AV_PICTURE_TYPE_B)
                ff_h263_update_motion_val(s);

            if(ret<0){
                const int xy= s->mb_x + s->mb_y*s->mb_stride;
                if(ret==SLICE_END){
                    MPV_decode_mb(s, s->block);
                    if(s->loop_filter)
                        ff_h263_loop_filter(s);

//printf("%d %d %d %06X\n", s->mb_x, s->mb_y, s->gb.size*8 - get_bits_count(&s->gb), show_bits(&s->gb, 24));
                    ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_MB_END&part_mask);

                    s->padding_bug_score--;

                    if(++s->mb_x >= s->mb_width){
                        s->mb_x=0;
                        ff_draw_horiz_band(s, s->mb_y*mb_size, mb_size);
                        MPV_report_decode_progress(s);
                        s->mb_y++;
                    }
                    return 0;
                }else if(ret==SLICE_NOEND){
                    av_log(s->avctx, AV_LOG_ERROR, "Slice mismatch at MB: %d\n", xy);
                    ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x+1, s->mb_y, ER_MB_END&part_mask);
                    return -1;
                }
                av_log(s->avctx, AV_LOG_ERROR, "Error at MB: %d\n", xy);
                ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, ER_MB_ERROR&part_mask);

                return -1;
            }

            MPV_decode_mb(s, s->block);
            if(s->loop_filter)
                ff_h263_loop_filter(s);
        }

        ff_draw_horiz_band(s, s->mb_y*mb_size, mb_size);
        MPV_report_decode_progress(s);

        s->mb_x= 0;
    }

    assert(s->mb_x==0 && s->mb_y==s->mb_height);

    if(s->codec_id==CODEC_ID_MPEG4
       && (s->workaround_bugs&FF_BUG_AUTODETECT)
       && get_bits_left(&s->gb) >= 48
       && show_bits(&s->gb, 24)==0x4010
       && !s->data_partitioning)
        s->padding_bug_score+=32;

    /* try to detect the padding bug */
    if(      s->codec_id==CODEC_ID_MPEG4
       &&   (s->workaround_bugs&FF_BUG_AUTODETECT)
       &&    get_bits_left(&s->gb) >=0
       &&    get_bits_left(&s->gb) < 48
//       &&   !s->resync_marker
       &&   !s->data_partitioning){

        const int bits_count= get_bits_count(&s->gb);
        const int bits_left = s->gb.size_in_bits - bits_count;

        if(bits_left==0){
            s->padding_bug_score+=16;
        } else if(bits_left != 1){
            int v= show_bits(&s->gb, 8);
            v|= 0x7F >> (7-(bits_count&7));

            if(v==0x7F && bits_left<=8)
                s->padding_bug_score--;
            else if(v==0x7F && ((get_bits_count(&s->gb)+8)&8) && bits_left<=16)
                s->padding_bug_score+= 4;
            else
                s->padding_bug_score++;
        }
    }
Пример #9
0
/**
 * Synthesize the data needed by XvMC to render one macroblock of data.
 * Fill all relevant fields, if necessary do IDCT.
 */
void ff_xvmc_decode_mb(MpegEncContext *s)
{
    XvMCMacroBlock *mv_block;
    struct xvmc_pix_fmt *render;
    int i, cbp, blocks_per_mb;

    const int mb_xy = s->mb_y * s->mb_stride + s->mb_x;


    if (s->encoding) {
        av_log(s->avctx, AV_LOG_ERROR, "XVMC doesn't support encoding!!!\n");
        return;
    }

    // from MPV_decode_mb(), update DC predictors for P macroblocks
    if (!s->mb_intra) {
        s->last_dc[0] =
        s->last_dc[1] =
        s->last_dc[2] =  128 << s->intra_dc_precision;
    }

    // MC doesn't skip blocks
    s->mb_skipped = 0;


    // Do I need to export quant when I could not perform postprocessing?
    // Anyway, it doesn't hurt.
    s->current_picture.qscale_table[mb_xy] = s->qscale;

    // start of XVMC-specific code
    render = (struct xvmc_pix_fmt*)s->current_picture.data[2];
    assert(render);
    assert(render->xvmc_id == AV_XVMC_ID);
    assert(render->mv_blocks);

    // take the next free macroblock
    mv_block = &render->mv_blocks[render->start_mv_blocks_num +
                                  render->filled_mv_blocks_num];

    mv_block->x        = s->mb_x;
    mv_block->y        = s->mb_y;
    mv_block->dct_type = s->interlaced_dct; // XVMC_DCT_TYPE_FRAME/FIELD;
    if (s->mb_intra) {
        mv_block->macroblock_type = XVMC_MB_TYPE_INTRA; // no MC, all done
    } else {
        mv_block->macroblock_type = XVMC_MB_TYPE_PATTERN;

        if (s->mv_dir & MV_DIR_FORWARD) {
            mv_block->macroblock_type |= XVMC_MB_TYPE_MOTION_FORWARD;
            // PMV[n][dir][xy] = mv[dir][n][xy]
            mv_block->PMV[0][0][0] = s->mv[0][0][0];
            mv_block->PMV[0][0][1] = s->mv[0][0][1];
            mv_block->PMV[1][0][0] = s->mv[0][1][0];
            mv_block->PMV[1][0][1] = s->mv[0][1][1];
        }
        if (s->mv_dir & MV_DIR_BACKWARD) {
            mv_block->macroblock_type |= XVMC_MB_TYPE_MOTION_BACKWARD;
            mv_block->PMV[0][1][0] = s->mv[1][0][0];
            mv_block->PMV[0][1][1] = s->mv[1][0][1];
            mv_block->PMV[1][1][0] = s->mv[1][1][0];
            mv_block->PMV[1][1][1] = s->mv[1][1][1];
        }

        switch(s->mv_type) {
            case  MV_TYPE_16X16:
                mv_block->motion_type = XVMC_PREDICTION_FRAME;
                break;
            case  MV_TYPE_16X8:
                mv_block->motion_type = XVMC_PREDICTION_16x8;
                break;
            case  MV_TYPE_FIELD:
                mv_block->motion_type = XVMC_PREDICTION_FIELD;
                if (s->picture_structure == PICT_FRAME) {
                    mv_block->PMV[0][0][1] <<= 1;
                    mv_block->PMV[1][0][1] <<= 1;
                    mv_block->PMV[0][1][1] <<= 1;
                    mv_block->PMV[1][1][1] <<= 1;
                }
                break;
            case  MV_TYPE_DMV:
                mv_block->motion_type = XVMC_PREDICTION_DUAL_PRIME;
                if (s->picture_structure == PICT_FRAME) {

                    mv_block->PMV[0][0][0] = s->mv[0][0][0];      // top from top
                    mv_block->PMV[0][0][1] = s->mv[0][0][1] << 1;

                    mv_block->PMV[0][1][0] = s->mv[0][0][0];      // bottom from bottom
                    mv_block->PMV[0][1][1] = s->mv[0][0][1] << 1;

                    mv_block->PMV[1][0][0] = s->mv[0][2][0];      // dmv00, top from bottom
                    mv_block->PMV[1][0][1] = s->mv[0][2][1] << 1; // dmv01

                    mv_block->PMV[1][1][0] = s->mv[0][3][0];      // dmv10, bottom from top
                    mv_block->PMV[1][1][1] = s->mv[0][3][1] << 1; // dmv11

                } else {
                    mv_block->PMV[0][1][0] = s->mv[0][2][0];      // dmv00
                    mv_block->PMV[0][1][1] = s->mv[0][2][1];      // dmv01
                }
                break;
            default:
                assert(0);
        }

        mv_block->motion_vertical_field_select = 0;

        // set correct field references
        if (s->mv_type == MV_TYPE_FIELD || s->mv_type == MV_TYPE_16X8) {
            mv_block->motion_vertical_field_select |= s->field_select[0][0];
            mv_block->motion_vertical_field_select |= s->field_select[1][0] << 1;
            mv_block->motion_vertical_field_select |= s->field_select[0][1] << 2;
            mv_block->motion_vertical_field_select |= s->field_select[1][1] << 3;
        }
    } // !intra
    // time to handle data blocks
    mv_block->index = render->next_free_data_block_num;

    blocks_per_mb = 6;
    if (s->chroma_format >= 2) {
        blocks_per_mb = 4 + (1 << s->chroma_format);
    }

    // calculate cbp
    cbp = 0;
    for (i = 0; i < blocks_per_mb; i++) {
        cbp += cbp;
        if (s->block_last_index[i] >= 0)
            cbp++;
    }

    if (s->flags & CODEC_FLAG_GRAY) {
        if (s->mb_intra) {                                   // intra frames are always full chroma blocks
            for (i = 4; i < blocks_per_mb; i++) {
                memset(s->pblocks[i], 0, sizeof(*s->pblocks[i]));  // so we need to clear them
                if (!render->unsigned_intra)
                    *s->pblocks[i][0] = 1 << 10;
            }
        } else {
            cbp &= 0xf << (blocks_per_mb - 4);
            blocks_per_mb = 4;                               // luminance blocks only
        }
    }
    mv_block->coded_block_pattern = cbp;
    if (cbp == 0)
        mv_block->macroblock_type &= ~XVMC_MB_TYPE_PATTERN;

    for (i = 0; i < blocks_per_mb; i++) {
        if (s->block_last_index[i] >= 0) {
            // I do not have unsigned_intra MOCO to test, hope it is OK.
            if (s->mb_intra && (render->idct || !render->unsigned_intra))
                *s->pblocks[i][0] -= 1 << 10;
            if (!render->idct) {
                s->dsp.idct(*s->pblocks[i]);
                /* It is unclear if MC hardware requires pixel diff values to be
                 * in the range [-255;255]. TODO: Clipping if such hardware is
                 * ever found. As of now it would only be an unnecessary
                 * slowdown. */
            }
            // copy blocks only if the codec doesn't support pblocks reordering
            if (s->avctx->xvmc_acceleration == 1) {
                memcpy(&render->data_blocks[render->next_free_data_block_num*64],
                       s->pblocks[i], sizeof(*s->pblocks[i]));
            }
            render->next_free_data_block_num++;
        }
    }
    render->filled_mv_blocks_num++;

    assert(render->filled_mv_blocks_num     <= render->allocated_mv_blocks);
    assert(render->next_free_data_block_num <= render->allocated_data_blocks);
    /* The above conditions should not be able to fail as long as this function
     * is used and the following 'if ()' automatically calls a callback to free
     * blocks. */


    if (render->filled_mv_blocks_num == render->allocated_mv_blocks)
        ff_draw_horiz_band(s, 0, 0);
}
Пример #10
0
static int decode_slice(MpegEncContext *s){
    const int part_mask= s->partitioned_frame ? (AC_END|AC_ERROR) : 0x7F;
    s->last_resync_gb= s->gb;
    s->first_slice_line= 1;
        
    s->resync_mb_x= s->mb_x;
    s->resync_mb_y= s->mb_y;

    ff_set_qscale(s, s->qscale);
    
    if(s->partitioned_frame){
        const int qscale= s->qscale;

        if(s->codec_id==CODEC_ID_MPEG4){
            if(ff_mpeg4_decode_partitions(s) < 0)
                return -1; 
        }
        
        /* restore variables which were modified */
        s->first_slice_line=1;
        s->mb_x= s->resync_mb_x;
        s->mb_y= s->resync_mb_y;
        ff_set_qscale(s, qscale);
    }

    for(; s->mb_y < s->mb_height; s->mb_y++) {
        /* per-row end of slice checks */
        if(s->msmpeg4_version){
            if(s->resync_mb_y + s->slice_height == s->mb_y){
                ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_END);

                return 0;
            }
        }
        
        if(s->msmpeg4_version==1){
            s->last_dc[0]=
            s->last_dc[1]=
            s->last_dc[2]= 128;
        }
    
        ff_init_block_index(s);
        for(; s->mb_x < s->mb_width; s->mb_x++) {
            int ret;

            ff_update_block_index(s);

            if(s->resync_mb_x == s->mb_x && s->resync_mb_y+1 == s->mb_y){
                s->first_slice_line=0; 
            }

            /* DCT & quantize */
	    s->dsp.clear_blocks(s->block[0]);
            
            s->mv_dir = MV_DIR_FORWARD;
            s->mv_type = MV_TYPE_16X16;
//            s->mb_skiped = 0;
//printf("%d %d %06X\n", ret, get_bits_count(&s->gb), show_bits(&s->gb, 24));
            ret= s->decode_mb(s, s->block);

            if (s->pict_type!=B_TYPE)
                ff_h263_update_motion_val(s);

            if(ret<0){
                const int xy= s->mb_x + s->mb_y*s->mb_stride;
                if(ret==SLICE_END){
                    MPV_decode_mb(s, s->block);
                    if(s->loop_filter)
                        ff_h263_loop_filter(s);

//printf("%d %d %d %06X\n", s->mb_x, s->mb_y, s->gb.size*8 - get_bits_count(&s->gb), show_bits(&s->gb, 24));
                    ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);

                    s->padding_bug_score--;
                        
                    if(++s->mb_x >= s->mb_width){
                        s->mb_x=0;
                        ff_draw_horiz_band(s, s->mb_y*16, 16);
                        s->mb_y++;
                    }
                    return 0; 
                }else if(ret==SLICE_NOEND){
                    av_log(s->avctx, AV_LOG_ERROR, "Slice mismatch at MB: %d\n", xy);
                    ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x+1, s->mb_y, (AC_END|DC_END|MV_END)&part_mask);
                    return -1;
                }
                av_log(s->avctx, AV_LOG_ERROR, "Error at MB: %d\n", xy);
                ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x, s->mb_y, (AC_ERROR|DC_ERROR|MV_ERROR)&part_mask);
    
                return -1;
            }

            MPV_decode_mb(s, s->block);
            if(s->loop_filter)
                ff_h263_loop_filter(s);
        }
        
        ff_draw_horiz_band(s, s->mb_y*16, 16);
        
        s->mb_x= 0;
    }
    
    assert(s->mb_x==0 && s->mb_y==s->mb_height);

    /* try to detect the padding bug */
    if(      s->codec_id==CODEC_ID_MPEG4
       &&   (s->workaround_bugs&FF_BUG_AUTODETECT) 
       &&    s->gb.size_in_bits - get_bits_count(&s->gb) >=0
       &&    s->gb.size_in_bits - get_bits_count(&s->gb) < 48
//       &&   !s->resync_marker
       &&   !s->data_partitioning){
        
        const int bits_count= get_bits_count(&s->gb);
        const int bits_left = s->gb.size_in_bits - bits_count;
        
        if(bits_left==0){
            s->padding_bug_score+=16;
        }else if(bits_left>8){
            s->padding_bug_score++;
        } else if(bits_left != 1){
            int v= show_bits(&s->gb, 8);
            v|= 0x7F >> (7-(bits_count&7));

            if(v==0x7F)
                s->padding_bug_score--;
            else
                s->padding_bug_score++;            
        }                          
    }
Пример #11
0
void ff_vdpau_vc1_decode_picture(MpegEncContext *s, const uint8_t *buf,
                                 int buf_size)
{
    VC1Context *v = s->avctx->priv_data;
    struct vdpau_render_state *render, *last, *next;

    render = (struct vdpau_render_state *)s->current_picture.data[0];
    assert(render);

    /*  fill LvPictureInfoVC1 struct */
    render->info.vc1.frame_coding_mode  = v->fcm;
    render->info.vc1.postprocflag       = v->postprocflag;
    render->info.vc1.pulldown           = v->broadcast;
    render->info.vc1.interlace          = v->interlace;
    render->info.vc1.tfcntrflag         = v->tfcntrflag;
    render->info.vc1.finterpflag        = v->finterpflag;
    render->info.vc1.psf                = v->psf;
    render->info.vc1.dquant             = v->dquant;
    render->info.vc1.panscan_flag       = v->panscanflag;
    render->info.vc1.refdist_flag       = v->refdist_flag;
    render->info.vc1.quantizer          = v->quantizer_mode;
    render->info.vc1.extended_mv        = v->extended_mv;
    render->info.vc1.extended_dmv       = v->extended_dmv;
    render->info.vc1.overlap            = v->overlap;
    render->info.vc1.vstransform        = v->vstransform;
    render->info.vc1.loopfilter         = v->s.loop_filter;
    render->info.vc1.fastuvmc           = v->fastuvmc;
    render->info.vc1.range_mapy_flag    = v->range_mapy_flag;
    render->info.vc1.range_mapy         = v->range_mapy;
    render->info.vc1.range_mapuv_flag   = v->range_mapuv_flag;
    render->info.vc1.range_mapuv        = v->range_mapuv;
    /* Specific to simple/main profile only */
    render->info.vc1.multires           = v->multires;
    render->info.vc1.syncmarker         = v->s.resync_marker;
    render->info.vc1.rangered           = v->rangered | (v->rangeredfrm << 1);
    render->info.vc1.maxbframes         = v->s.max_b_frames;

    render->info.vc1.deblockEnable      = v->postprocflag & 1;
    render->info.vc1.pquant             = v->pq;

    render->info.vc1.forward_reference  = VDP_INVALID_HANDLE;
    render->info.vc1.backward_reference = VDP_INVALID_HANDLE;

    if (v->bi_type)
        render->info.vc1.picture_type = 4;
    else
        render->info.vc1.picture_type = s->pict_type - 1 + s->pict_type / 3;

    switch(s->pict_type){
    case  FF_B_TYPE:
        next = (struct vdpau_render_state *)s->next_picture.data[0];
        assert(next);
        render->info.vc1.backward_reference = next->surface;
        // no break here, going to set forward prediction
    case  FF_P_TYPE:
        last = (struct vdpau_render_state *)s->last_picture.data[0];
        if (!last) // FIXME: Does this test make sense?
            last = render; // predict second field from the first
        render->info.vc1.forward_reference = last->surface;
    }

    ff_vdpau_add_data_chunk(s, buf, buf_size);

    render->info.vc1.slice_count          = 1;

    ff_draw_horiz_band(s, 0, s->avctx->height);
    render->bitstream_buffers_used        = 0;
}
Пример #12
0
void XVMC_decode_mb(MpegEncContext *s){
XvMCMacroBlock * mv_block;
xvmc_render_state_t * render;
int i,cbp,blocks_per_mb;

const int mb_xy = s->mb_y * s->mb_stride + s->mb_x;


    if(s->encoding){
        av_log(s->avctx, AV_LOG_ERROR, "XVMC doesn't support encoding!!!\n");
        return -1;
    }

   //from MPV_decode_mb(),
    /* update DC predictors for P macroblocks */
    if (!s->mb_intra) {
        s->last_dc[0] =
        s->last_dc[1] =
        s->last_dc[2] =  128 << s->intra_dc_precision;
    }

   //MC doesn't skip blocks
    s->mb_skipped = 0;


   // do I need to export quant when I could not perform postprocessing?
   // anyway, it doesn't hurrt
    s->current_picture.qscale_table[mb_xy] = s->qscale;

//START OF XVMC specific code
    render = (xvmc_render_state_t*)s->current_picture.data[2];
    assert(render!=NULL);
    assert(render->magic==MP_XVMC_RENDER_MAGIC);
    assert(render->mv_blocks);

    //take the next free macroblock
    mv_block = &render->mv_blocks[render->start_mv_blocks_num +
                                   render->filled_mv_blocks_num ];

// memset(mv_block,0,sizeof(XvMCMacroBlock));

    mv_block->x = s->mb_x;
    mv_block->y = s->mb_y;
    mv_block->dct_type = s->interlaced_dct;//XVMC_DCT_TYPE_FRAME/FIELD;
//    mv_block->motion_type = 0;  //zero to silense warnings
    if(s->mb_intra){
        mv_block->macroblock_type = XVMC_MB_TYPE_INTRA;//no MC, all done
    }else{
        mv_block->macroblock_type = XVMC_MB_TYPE_PATTERN;

        if(s->mv_dir & MV_DIR_FORWARD){
            mv_block->macroblock_type|= XVMC_MB_TYPE_MOTION_FORWARD;
            //pmv[n][dir][xy]=mv[dir][n][xy]
            mv_block->PMV[0][0][0] = s->mv[0][0][0];
            mv_block->PMV[0][0][1] = s->mv[0][0][1];
            mv_block->PMV[1][0][0] = s->mv[0][1][0];
            mv_block->PMV[1][0][1] = s->mv[0][1][1];
        }
        if(s->mv_dir & MV_DIR_BACKWARD){
            mv_block->macroblock_type|=XVMC_MB_TYPE_MOTION_BACKWARD;
            mv_block->PMV[0][1][0] = s->mv[1][0][0];
            mv_block->PMV[0][1][1] = s->mv[1][0][1];
            mv_block->PMV[1][1][0] = s->mv[1][1][0];
            mv_block->PMV[1][1][1] = s->mv[1][1][1];
        }

        switch(s->mv_type){
            case  MV_TYPE_16X16:
                mv_block->motion_type = XVMC_PREDICTION_FRAME;
                break;
            case  MV_TYPE_16X8:
                mv_block->motion_type = XVMC_PREDICTION_16x8;
                break;
            case  MV_TYPE_FIELD:
                mv_block->motion_type = XVMC_PREDICTION_FIELD;
                if(s->picture_structure == PICT_FRAME){
                    mv_block->PMV[0][0][1]<<=1;
                    mv_block->PMV[1][0][1]<<=1;
                    mv_block->PMV[0][1][1]<<=1;
                    mv_block->PMV[1][1][1]<<=1;
                }
                break;
            case  MV_TYPE_DMV:
                mv_block->motion_type = XVMC_PREDICTION_DUAL_PRIME;
                if(s->picture_structure == PICT_FRAME){

                    mv_block->PMV[0][0][0] = s->mv[0][0][0];//top from top
                    mv_block->PMV[0][0][1] = s->mv[0][0][1]<<1;

                    mv_block->PMV[0][1][0] = s->mv[0][0][0];//bottom from bottom
                    mv_block->PMV[0][1][1] = s->mv[0][0][1]<<1;

                    mv_block->PMV[1][0][0] = s->mv[0][2][0];//dmv00, top from bottom
                    mv_block->PMV[1][0][1] = s->mv[0][2][1]<<1;//dmv01

                    mv_block->PMV[1][1][0] = s->mv[0][3][0];//dmv10, bottom from top
                    mv_block->PMV[1][1][1] = s->mv[0][3][1]<<1;//dmv11

                }else{
                    mv_block->PMV[0][1][0] = s->mv[0][2][0];//dmv00
                    mv_block->PMV[0][1][1] = s->mv[0][2][1];//dmv01
                }
                break;
            default:
                assert(0);
        }

        mv_block->motion_vertical_field_select = 0;

//set correct field referenses
        if(s->mv_type == MV_TYPE_FIELD || s->mv_type == MV_TYPE_16X8){
            if( s->field_select[0][0] ) mv_block->motion_vertical_field_select|=1;
            if( s->field_select[1][0] ) mv_block->motion_vertical_field_select|=2;
            if( s->field_select[0][1] ) mv_block->motion_vertical_field_select|=4;
            if( s->field_select[1][1] ) mv_block->motion_vertical_field_select|=8;
        }
    }//!intra
//time to handle data blocks;
    mv_block->index = render->next_free_data_block_num;

    blocks_per_mb = 6;
    if( s->chroma_format >= 2){
        blocks_per_mb = 4 + (1 << (s->chroma_format));
    }

//  calculate cbp
    cbp = 0;
    for(i=0; i<blocks_per_mb; i++) {
        cbp+= cbp;
        if(s->block_last_index[i] >= 0)
            cbp++;
    }

    if(s->flags & CODEC_FLAG_GRAY){
        if(s->mb_intra){//intra frames are alwasy full chroma block
            for(i=4; i<blocks_per_mb; i++){
                memset(s->pblocks[i],0,sizeof(short)*8*8);//so we need to clear them
                if(!render->unsigned_intra)
                    s->pblocks[i][0] = 1<<10;
            }
        }else{
            cbp&= 0xf << (blocks_per_mb - 4);
            blocks_per_mb = 4;//Luminance blocks only
        }
    }
    mv_block->coded_block_pattern = cbp;
    if(cbp == 0)
        mv_block->macroblock_type &= ~XVMC_MB_TYPE_PATTERN;

    for(i=0; i<blocks_per_mb; i++){
        if(s->block_last_index[i] >= 0){
            // i do not have unsigned_intra MOCO to test, hope it is OK
            if( (s->mb_intra) && ( render->idct || (!render->idct && !render->unsigned_intra)) )
                s->pblocks[i][0]-=1<<10;
            if(!render->idct){
                s->dsp.idct(s->pblocks[i]);
                //!!TODO!clip!!!
            }
//copy blocks only if the codec doesn't support pblocks reordering
            if(s->avctx->xvmc_acceleration == 1){
                memcpy(&render->data_blocks[(render->next_free_data_block_num)*64],
                        s->pblocks[i],sizeof(short)*8*8);
            }else{
/*              if(s->pblocks[i] != &render->data_blocks[
                        (render->next_free_data_block_num)*64]){
                   printf("ERROR mb(%d,%d) s->pblocks[i]=%p data_block[]=%p\n",
                   s->mb_x,s->mb_y, s->pblocks[i],
                   &render->data_blocks[(render->next_free_data_block_num)*64]);
                }*/
            }
            render->next_free_data_block_num++;
        }
    }
    render->filled_mv_blocks_num++;

    assert(render->filled_mv_blocks_num <= render->total_number_of_mv_blocks);
    assert(render->next_free_data_block_num <= render->total_number_of_data_blocks);


    if(render->filled_mv_blocks_num >= render->total_number_of_mv_blocks)
        ff_draw_horiz_band(s,0,0);

// DumpRenderInfo(render);
// DumpMBlockInfo(mv_block);

}
Пример #13
0
/** End a hardware decoding based frame. */
static int end_frame(AVCodecContext *avctx)
{
  H264Context * const h = avctx->priv_data;
  MpegEncContext * const s = &h->s;
  struct xvba_render_state *render;
  XVBAPictureDescriptor *pic_descriptor;
  XVBAQuantMatrixAvc *iq_matrix;

  render = (struct xvba_render_state *)s->current_picture_ptr->data[0];
  assert(render);

  if (render->picture_descriptor == 0 || render->iq_matrix == 0)
    return -1;

  pic_descriptor = render->picture_descriptor;
  iq_matrix = render->iq_matrix;

  av_dlog(avctx, "end_frame()\n");

  /* Fill in Picture Parameters*/
  pic_descriptor->profile                                     = ff_xvba_translate_profile(avctx->profile);
  pic_descriptor->level                                       = avctx->level;
  pic_descriptor->width_in_mb                                 = s->mb_width;
  pic_descriptor->height_in_mb                                = s->mb_height;
  pic_descriptor->picture_structure                           = s->picture_structure;
  pic_descriptor->chroma_format                               = s->chroma_format ? s->chroma_format : 1;
  pic_descriptor->avc_intra_flag                              = (h->slice_type == FF_I_TYPE) ? 1 : 0;
  pic_descriptor->avc_reference                               = (s->current_picture_ptr->reference & 3) ? 1 : 0;

  pic_descriptor->avc_bit_depth_luma_minus8                   = h->sps.bit_depth_luma - 8;
  pic_descriptor->avc_bit_depth_chroma_minus8                 = h->sps.bit_depth_chroma - 8;
  pic_descriptor->avc_log2_max_frame_num_minus4               = h->sps.log2_max_frame_num -4;
  pic_descriptor->avc_pic_order_cnt_type                      = h->sps.poc_type;
  pic_descriptor->avc_log2_max_pic_order_cnt_lsb_minus4       = h->sps.log2_max_poc_lsb - 4;
  pic_descriptor->avc_num_ref_frames                          = h->sps.ref_frame_count;
  pic_descriptor->avc_reserved_8bit                           = 0;

  pic_descriptor->avc_num_slice_groups_minus1                 = h->pps.slice_group_count - 1;
  pic_descriptor->avc_num_ref_idx_l0_active_minus1            = h->pps.ref_count[0] - 1;
  pic_descriptor->avc_num_ref_idx_l1_active_minus1            = h->pps.ref_count[1] - 1;

  pic_descriptor->avc_pic_init_qp_minus26                     = h->pps.init_qp - 26;
  pic_descriptor->avc_pic_init_qs_minus26                     = h->pps.init_qs - 26;
  pic_descriptor->avc_chroma_qp_index_offset                  = h->pps.chroma_qp_index_offset[0];
  pic_descriptor->avc_second_chroma_qp_index_offset           = h->pps.chroma_qp_index_offset[1];
  pic_descriptor->avc_slice_group_change_rate_minus1          = 0; // not implemented in ffmpeg
  pic_descriptor->avc_reserved_16bit                          = 0; // must be 0
  memset(pic_descriptor->avc_field_order_cnt_list,0,sizeof(pic_descriptor->avc_field_order_cnt_list)); // must be 0
  memset(pic_descriptor->avc_slice_group_map,0,sizeof(pic_descriptor->avc_slice_group_map)); // must be 0

  // sps
  pic_descriptor->sps_info.avc.delta_pic_always_zero_flag     = h->sps.delta_pic_order_always_zero_flag;
  pic_descriptor->sps_info.avc.direct_8x8_inference_flag      = h->sps.direct_8x8_inference_flag;
  pic_descriptor->sps_info.avc.frame_mbs_only_flag            = h->sps.frame_mbs_only_flag;
  pic_descriptor->sps_info.avc.gaps_in_frame_num_value_allowed_flag = h->sps.gaps_in_frame_num_allowed_flag;
  pic_descriptor->sps_info.avc.mb_adaptive_frame_field_flag   = h->sps.mb_aff;
  pic_descriptor->sps_info.avc.residual_colour_transform_flag = h->sps.residual_color_transform_flag;
  pic_descriptor->sps_info.avc.xvba_avc_sps_reserved          = 0;

  // pps
  pic_descriptor->pps_info.avc.entropy_coding_mode_flag       = h->pps.cabac;
  pic_descriptor->pps_info.avc.pic_order_present_flag         = h->pps.pic_order_present;
  pic_descriptor->pps_info.avc.weighted_pred_flag             = h->pps.weighted_pred;
  pic_descriptor->pps_info.avc.weighted_bipred_idc            = h->pps.weighted_bipred_idc;
  pic_descriptor->pps_info.avc.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
  pic_descriptor->pps_info.avc.constrained_intra_pred_flag    = h->pps.constrained_intra_pred;
  pic_descriptor->pps_info.avc.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present;
  pic_descriptor->pps_info.avc.transform_8x8_mode_flag        = h->pps.transform_8x8_mode;
  pic_descriptor->pps_info.avc.xvba_avc_pps_reserved          = 0; // must be 0

  memcpy(iq_matrix->bScalingLists4x4, h->pps.scaling_matrix4, sizeof(iq_matrix->bScalingLists4x4));
  memcpy(iq_matrix->bScalingLists8x8, h->pps.scaling_matrix8, sizeof(iq_matrix->bScalingLists8x8));

  // Wait for an I-frame before start decoding. Workaround for ATI UVD and UVD+ GPUs
  if (!h->got_first_iframe) {
      if (h->slice_type != FF_I_TYPE && h->slice_type != FF_SI_TYPE)
          return -1;
      h->got_first_iframe = 1;
  }

  ff_draw_horiz_band(s, 0, s->avctx->height);

  return 0;
}
Пример #14
0
int ff_dxva2_common_end_frame(AVCodecContext *avctx, MpegEncContext *s,
                              const void *pp, unsigned pp_size,
                              const void *qm, unsigned qm_size,
                              int (*commit_bs_si)(AVCodecContext *,
                                                  DXVA2_DecodeBufferDesc *bs,
                                                  DXVA2_DecodeBufferDesc *slice))
{
    struct dxva_context *ctx = avctx->hwaccel_context;
    unsigned               buffer_count = 0;
    DXVA2_DecodeBufferDesc buffer[4];
    DXVA2_DecodeExecuteParams exec = { 0 };
    int      result;

    if (FAILED(IDirectXVideoDecoder_BeginFrame(ctx->decoder,
                                               ff_dxva2_get_surface(s->current_picture_ptr),
                                               NULL))) {
        av_log(avctx, AV_LOG_ERROR, "Failed to begin frame\n");
        return -1;
    }

    result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count],
                                    DXVA2_PictureParametersBufferType,
                                    pp, pp_size, 0);
    if (result) {
        av_log(avctx, AV_LOG_ERROR,
               "Failed to add picture parameter buffer\n");
        goto end;
    }
    buffer_count++;

    if (qm_size > 0) {
        result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count],
                                        DXVA2_InverseQuantizationMatrixBufferType,
                                        qm, qm_size, 0);
        if (result) {
            av_log(avctx, AV_LOG_ERROR,
                   "Failed to add inverse quantization matrix buffer\n");
            goto end;
        }
        buffer_count++;
    }

    result = commit_bs_si(avctx,
                          &buffer[buffer_count + 0],
                          &buffer[buffer_count + 1]);
    if (result) {
        av_log(avctx, AV_LOG_ERROR,
               "Failed to add bitstream or slice control buffer\n");
        goto end;
    }
    buffer_count += 2;

    /* TODO Film Grain when possible */

    assert(buffer_count == 1 + (qm_size > 0) + 2);

    exec.NumCompBuffers      = buffer_count;
    exec.pCompressedBuffers  = buffer;
    exec.pExtensionData      = NULL;
    if (FAILED(IDirectXVideoDecoder_Execute(ctx->decoder, &exec))) {
        av_log(avctx, AV_LOG_ERROR, "Failed to execute\n");
        result = -1;
    }

end:
    if (FAILED(IDirectXVideoDecoder_EndFrame(ctx->decoder, NULL))) {
        av_log(avctx, AV_LOG_ERROR, "Failed to end frame\n");
        result = -1;
    }

    if (!result)
        ff_draw_horiz_band(s, 0, s->avctx->height);
    return result;
}
Пример #15
0
static int decode_slice(MpegEncContext *s){
    const int part_mask= s->partitioned_frame ? (AC_END|AC_ERROR) : 0x7F;
    const int mb_size= 16>>s->avctx->lowres;
    s->last_resync_gb= s->gb;
    s->first_slice_line= 1;

    s->resync_mb_x= s->mb_x;
    s->resync_mb_y= s->mb_y;

    ff_set_qscale(s, s->qscale);

    if(s->partitioned_frame){
        const int qscale= s->qscale;

        /* restore variables which were modified */
        s->first_slice_line=1;
        s->mb_x= s->resync_mb_x;
        s->mb_y= s->resync_mb_y;
        ff_set_qscale(s, qscale);
    }

    for(; s->mb_y < s->mb_height; s->mb_y++) {
        /* per-row end of slice checks */
        ff_init_block_index(s);
        for(; s->mb_x < s->mb_width; s->mb_x++) {
            int ret;

            ff_update_block_index(s);

            if(s->resync_mb_x == s->mb_x && s->resync_mb_y+1 == s->mb_y){
                s->first_slice_line=0;
            }

            /* DCT & quantize */

            s->mv_dir = MV_DIR_FORWARD;
            s->mv_type = MV_TYPE_16X16;
//            s->mb_skipped = 0;
//printf("%d %d %06X\n", ret, get_bits_count(&s->gb), show_bits(&s->gb, 24));
            ret= s->decode_mb(s, s->block);

            if (s->pict_type!=FF_B_TYPE)
                ff_h263_update_motion_val(s);

            if(ret<0){
                const int xy= s->mb_x + s->mb_y*s->mb_stride;
                if(ret==SLICE_END){
                    MPV_decode_mb(s, s->block);

                    if(++s->mb_x >= s->mb_width){
                        s->mb_x=0;
                        ff_draw_horiz_band(s, s->mb_y*mb_size, mb_size);
                        s->mb_y++;
                    }
                    return 0;
                }else if(ret==SLICE_NOEND){
                    av_log(s->avctx, AV_LOG_ERROR, "Slice mismatch at MB: %d\n", xy);
                    return -1;
                }
                return -1;
            }

            MPV_decode_mb(s, s->block);
        }

        ff_draw_horiz_band(s, s->mb_y*mb_size, mb_size);

        s->mb_x= 0;
    }
    return -1;
}