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; }
/** * 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); }
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; }
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); } }
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; }
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; }
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; }
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++; } }
/** * 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); }
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++; } }
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; }
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); }
/** 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; }
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; }
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; }