diff options
Diffstat (limited to 'ffmpeg/libavcodec/dxva2_h264.c')
| -rw-r--r-- | ffmpeg/libavcodec/dxva2_h264.c | 452 |
1 files changed, 0 insertions, 452 deletions
diff --git a/ffmpeg/libavcodec/dxva2_h264.c b/ffmpeg/libavcodec/dxva2_h264.c deleted file mode 100644 index 1090502..0000000 --- a/ffmpeg/libavcodec/dxva2_h264.c +++ /dev/null @@ -1,452 +0,0 @@ -/* - * DXVA2 H264 HW acceleration. - * - * copyright (c) 2009 Laurent Aimar - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "dxva2_internal.h" -#include "h264.h" -#include "h264data.h" - -struct dxva2_picture_context { - DXVA_PicParams_H264 pp; - DXVA_Qmatrix_H264 qm; - unsigned slice_count; - DXVA_Slice_H264_Short slice_short[MAX_SLICES]; - DXVA_Slice_H264_Long slice_long[MAX_SLICES]; - const uint8_t *bitstream; - unsigned bitstream_size; -}; - -static void fill_picture_entry(DXVA_PicEntry_H264 *pic, - unsigned index, unsigned flag) -{ - assert((index&0x7f) == index && (flag&0x01) == flag); - pic->bPicEntry = index | (flag << 7); -} - -static void fill_picture_parameters(struct dxva_context *ctx, const H264Context *h, - DXVA_PicParams_H264 *pp) -{ - const Picture *current_picture = h->cur_pic_ptr; - int i, j; - - memset(pp, 0, sizeof(*pp)); - /* Configure current picture */ - fill_picture_entry(&pp->CurrPic, - ff_dxva2_get_surface_index(ctx, current_picture), - h->picture_structure == PICT_BOTTOM_FIELD); - /* Configure the set of references */ - pp->UsedForReferenceFlags = 0; - pp->NonExistingFrameFlags = 0; - for (i = 0, j = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) { - const Picture *r; - if (j < h->short_ref_count) { - r = h->short_ref[j++]; - } else { - r = NULL; - while (!r && j < h->short_ref_count + 16) - r = h->long_ref[j++ - h->short_ref_count]; - } - if (r) { - fill_picture_entry(&pp->RefFrameList[i], - ff_dxva2_get_surface_index(ctx, r), - r->long_ref != 0); - - if ((r->reference & PICT_TOP_FIELD) && r->field_poc[0] != INT_MAX) - pp->FieldOrderCntList[i][0] = r->field_poc[0]; - if ((r->reference & PICT_BOTTOM_FIELD) && r->field_poc[1] != INT_MAX) - pp->FieldOrderCntList[i][1] = r->field_poc[1]; - - pp->FrameNumList[i] = r->long_ref ? r->pic_id : r->frame_num; - if (r->reference & PICT_TOP_FIELD) - pp->UsedForReferenceFlags |= 1 << (2*i + 0); - if (r->reference & PICT_BOTTOM_FIELD) - pp->UsedForReferenceFlags |= 1 << (2*i + 1); - } else { - pp->RefFrameList[i].bPicEntry = 0xff; - pp->FieldOrderCntList[i][0] = 0; - pp->FieldOrderCntList[i][1] = 0; - pp->FrameNumList[i] = 0; - } - } - - pp->wFrameWidthInMbsMinus1 = h->mb_width - 1; - pp->wFrameHeightInMbsMinus1 = h->mb_height - 1; - pp->num_ref_frames = h->sps.ref_frame_count; - - pp->wBitFields = ((h->picture_structure != PICT_FRAME) << 0) | - ((h->sps.mb_aff && - (h->picture_structure == PICT_FRAME)) << 1) | - (h->sps.residual_color_transform_flag << 2) | - /* sp_for_switch_flag (not implemented by FFmpeg) */ - (0 << 3) | - (h->sps.chroma_format_idc << 4) | - ((h->nal_ref_idc != 0) << 6) | - (h->pps.constrained_intra_pred << 7) | - (h->pps.weighted_pred << 8) | - (h->pps.weighted_bipred_idc << 9) | - /* MbsConsecutiveFlag */ - (1 << 11) | - (h->sps.frame_mbs_only_flag << 12) | - (h->pps.transform_8x8_mode << 13) | - ((h->sps.level_idc >= 31) << 14) | - /* IntraPicFlag (Modified if we detect a non - * intra slice in dxva2_h264_decode_slice) */ - (1 << 15); - - pp->bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8; - pp->bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8; - if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) - pp->Reserved16Bits = 0; - else - pp->Reserved16Bits = 3; /* FIXME is there a way to detect the right mode ? */ - pp->StatusReportFeedbackNumber = 1 + ctx->report_id++; - pp->CurrFieldOrderCnt[0] = 0; - if ((h->picture_structure & PICT_TOP_FIELD) && - current_picture->field_poc[0] != INT_MAX) - pp->CurrFieldOrderCnt[0] = current_picture->field_poc[0]; - pp->CurrFieldOrderCnt[1] = 0; - if ((h->picture_structure & PICT_BOTTOM_FIELD) && - current_picture->field_poc[1] != INT_MAX) - pp->CurrFieldOrderCnt[1] = current_picture->field_poc[1]; - pp->pic_init_qs_minus26 = h->pps.init_qs - 26; - pp->chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; - pp->second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; - pp->ContinuationFlag = 1; - pp->pic_init_qp_minus26 = h->pps.init_qp - 26; - pp->num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1; - pp->num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1; - pp->Reserved8BitsA = 0; - pp->frame_num = h->frame_num; - pp->log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4; - pp->pic_order_cnt_type = h->sps.poc_type; - if (h->sps.poc_type == 0) - pp->log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4; - else if (h->sps.poc_type == 1) - pp->delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; - pp->direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; - pp->entropy_coding_mode_flag = h->pps.cabac; - pp->pic_order_present_flag = h->pps.pic_order_present; - pp->num_slice_groups_minus1 = h->pps.slice_group_count - 1; - pp->slice_group_map_type = h->pps.mb_slice_group_map_type; - pp->deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; - pp->redundant_pic_cnt_present_flag= h->pps.redundant_pic_cnt_present; - pp->Reserved8BitsB = 0; - pp->slice_group_change_rate_minus1= 0; /* XXX not implemented by FFmpeg */ - //pp->SliceGroupMap[810]; /* XXX not implemented by FFmpeg */ -} - -static void fill_scaling_lists(struct dxva_context *ctx, const H264Context *h, DXVA_Qmatrix_H264 *qm) -{ - unsigned i, j; - memset(qm, 0, sizeof(*qm)); - if (ctx->workaround & FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG) { - for (i = 0; i < 6; i++) - for (j = 0; j < 16; j++) - qm->bScalingLists4x4[i][j] = h->pps.scaling_matrix4[i][j]; - - for (i = 0; i < 64; i++) { - qm->bScalingLists8x8[0][i] = h->pps.scaling_matrix8[0][i]; - qm->bScalingLists8x8[1][i] = h->pps.scaling_matrix8[3][i]; - } - } else { - for (i = 0; i < 6; i++) - for (j = 0; j < 16; j++) - qm->bScalingLists4x4[i][j] = h->pps.scaling_matrix4[i][zigzag_scan[j]]; - - for (i = 0; i < 64; i++) { - qm->bScalingLists8x8[0][i] = h->pps.scaling_matrix8[0][ff_zigzag_direct[i]]; - qm->bScalingLists8x8[1][i] = h->pps.scaling_matrix8[3][ff_zigzag_direct[i]]; - } - } -} - -static int is_slice_short(struct dxva_context *ctx) -{ - assert(ctx->cfg->ConfigBitstreamRaw == 1 || - ctx->cfg->ConfigBitstreamRaw == 2); - return ctx->cfg->ConfigBitstreamRaw == 2; -} - -static void fill_slice_short(DXVA_Slice_H264_Short *slice, - unsigned position, unsigned size) -{ - memset(slice, 0, sizeof(*slice)); - slice->BSNALunitDataLocation = position; - slice->SliceBytesInBuffer = size; - slice->wBadSliceChopping = 0; -} - -static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, - unsigned position, unsigned size) -{ - const H264Context *h = avctx->priv_data; - struct dxva_context *ctx = avctx->hwaccel_context; - unsigned list; - - memset(slice, 0, sizeof(*slice)); - slice->BSNALunitDataLocation = position; - slice->SliceBytesInBuffer = size; - slice->wBadSliceChopping = 0; - - slice->first_mb_in_slice = (h->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) * h->mb_width + h->mb_x; - slice->NumMbsForSlice = 0; /* XXX it is set once we have all slices */ - slice->BitOffsetToSliceData = get_bits_count(&h->gb); - slice->slice_type = ff_h264_get_slice_type(h); - if (h->slice_type_fixed) - slice->slice_type += 5; - slice->luma_log2_weight_denom = h->luma_log2_weight_denom; - slice->chroma_log2_weight_denom = h->chroma_log2_weight_denom; - if (h->list_count > 0) - slice->num_ref_idx_l0_active_minus1 = h->ref_count[0] - 1; - if (h->list_count > 1) - slice->num_ref_idx_l1_active_minus1 = h->ref_count[1] - 1; - slice->slice_alpha_c0_offset_div2 = h->slice_alpha_c0_offset / 2 - 26; - slice->slice_beta_offset_div2 = h->slice_beta_offset / 2 - 26; - slice->Reserved8Bits = 0; - - for (list = 0; list < 2; list++) { - unsigned i; - for (i = 0; i < FF_ARRAY_ELEMS(slice->RefPicList[list]); i++) { - if (list < h->list_count && i < h->ref_count[list]) { - const Picture *r = &h->ref_list[list][i]; - unsigned plane; - fill_picture_entry(&slice->RefPicList[list][i], - ff_dxva2_get_surface_index(ctx, r), - r->reference == PICT_BOTTOM_FIELD); - for (plane = 0; plane < 3; plane++) { - int w, o; - if (plane == 0 && h->luma_weight_flag[list]) { - w = h->luma_weight[i][list][0]; - o = h->luma_weight[i][list][1]; - } else if (plane >= 1 && h->chroma_weight_flag[list]) { - w = h->chroma_weight[i][list][plane-1][0]; - o = h->chroma_weight[i][list][plane-1][1]; - } else { - w = 1 << (plane == 0 ? h->luma_log2_weight_denom : - h->chroma_log2_weight_denom); - o = 0; - } - slice->Weights[list][i][plane][0] = w; - slice->Weights[list][i][plane][1] = o; - } - } else { - unsigned plane; - slice->RefPicList[list][i].bPicEntry = 0xff; - for (plane = 0; plane < 3; plane++) { - slice->Weights[list][i][plane][0] = 0; - slice->Weights[list][i][plane][1] = 0; - } - } - } - } - slice->slice_qs_delta = 0; /* XXX not implemented by FFmpeg */ - slice->slice_qp_delta = h->qscale - h->pps.init_qp; - slice->redundant_pic_cnt = h->redundant_pic_count; - if (h->slice_type == AV_PICTURE_TYPE_B) - slice->direct_spatial_mv_pred_flag = h->direct_spatial_mv_pred; - slice->cabac_init_idc = h->pps.cabac ? h->cabac_init_idc : 0; - if (h->deblocking_filter < 2) - slice->disable_deblocking_filter_idc = 1 - h->deblocking_filter; - else - slice->disable_deblocking_filter_idc = h->deblocking_filter; - slice->slice_id = h->current_slice - 1; -} - -static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, - DXVA2_DecodeBufferDesc *bs, - DXVA2_DecodeBufferDesc *sc) -{ - const H264Context *h = avctx->priv_data; - const unsigned mb_count = h->mb_width * h->mb_height; - struct dxva_context *ctx = avctx->hwaccel_context; - const Picture *current_picture = h->cur_pic_ptr; - struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; - DXVA_Slice_H264_Short *slice = NULL; - uint8_t *dxva_data, *current, *end; - unsigned dxva_size; - void *slice_data; - unsigned slice_size; - unsigned padding; - unsigned i; - - /* Create an annex B bitstream buffer with only slice NAL and finalize slice */ - if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, - DXVA2_BitStreamDateBufferType, - (void **)&dxva_data, &dxva_size))) - return -1; - current = dxva_data; - end = dxva_data + dxva_size; - - for (i = 0; i < ctx_pic->slice_count; i++) { - static const uint8_t start_code[] = { 0, 0, 1 }; - static const unsigned start_code_size = sizeof(start_code); - unsigned position, size; - - assert(offsetof(DXVA_Slice_H264_Short, BSNALunitDataLocation) == - offsetof(DXVA_Slice_H264_Long, BSNALunitDataLocation)); - assert(offsetof(DXVA_Slice_H264_Short, SliceBytesInBuffer) == - offsetof(DXVA_Slice_H264_Long, SliceBytesInBuffer)); - - if (is_slice_short(ctx)) - slice = &ctx_pic->slice_short[i]; - else - slice = (DXVA_Slice_H264_Short*)&ctx_pic->slice_long[i]; - - position = slice->BSNALunitDataLocation; - size = slice->SliceBytesInBuffer; - if (start_code_size + size > end - current) { - av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream"); - break; - } - - slice->BSNALunitDataLocation = current - dxva_data; - slice->SliceBytesInBuffer = start_code_size + size; - - if (!is_slice_short(ctx)) { - DXVA_Slice_H264_Long *slice_long = (DXVA_Slice_H264_Long*)slice; - if (i < ctx_pic->slice_count - 1) - slice_long->NumMbsForSlice = - slice_long[1].first_mb_in_slice - slice_long[0].first_mb_in_slice; - else - slice_long->NumMbsForSlice = mb_count - slice_long->first_mb_in_slice; - } - - memcpy(current, start_code, start_code_size); - current += start_code_size; - - memcpy(current, &ctx_pic->bitstream[position], size); - current += size; - } - padding = FFMIN(128 - ((current - dxva_data) & 127), end - current); - if (slice && padding > 0) { - memset(current, 0, padding); - current += padding; - - slice->SliceBytesInBuffer += padding; - } - if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, - DXVA2_BitStreamDateBufferType))) - return -1; - if (i < ctx_pic->slice_count) - return -1; - - memset(bs, 0, sizeof(*bs)); - bs->CompressedBufferType = DXVA2_BitStreamDateBufferType; - bs->DataSize = current - dxva_data; - bs->NumMBsInBuffer = mb_count; - - if (is_slice_short(ctx)) { - slice_data = ctx_pic->slice_short; - slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short); - } else { - slice_data = ctx_pic->slice_long; - slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_long); - } - assert((bs->DataSize & 127) == 0); - return ff_dxva2_commit_buffer(avctx, ctx, sc, - DXVA2_SliceControlBufferType, - slice_data, slice_size, mb_count); -} - - -static int dxva2_h264_start_frame(AVCodecContext *avctx, - av_unused const uint8_t *buffer, - av_unused uint32_t size) -{ - const H264Context *h = avctx->priv_data; - struct dxva_context *ctx = avctx->hwaccel_context; - struct dxva2_picture_context *ctx_pic = h->cur_pic_ptr->hwaccel_picture_private; - - if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0) - return -1; - assert(ctx_pic); - - /* Fill up DXVA_PicParams_H264 */ - fill_picture_parameters(ctx, h, &ctx_pic->pp); - - /* Fill up DXVA_Qmatrix_H264 */ - fill_scaling_lists(ctx, h, &ctx_pic->qm); - - ctx_pic->slice_count = 0; - ctx_pic->bitstream_size = 0; - ctx_pic->bitstream = NULL; - return 0; -} - -static int dxva2_h264_decode_slice(AVCodecContext *avctx, - const uint8_t *buffer, - uint32_t size) -{ - const H264Context *h = avctx->priv_data; - struct dxva_context *ctx = avctx->hwaccel_context; - const Picture *current_picture = h->cur_pic_ptr; - struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private; - unsigned position; - - if (ctx_pic->slice_count >= MAX_SLICES) - return -1; - - if (!ctx_pic->bitstream) - ctx_pic->bitstream = buffer; - ctx_pic->bitstream_size += size; - - position = buffer - ctx_pic->bitstream; - if (is_slice_short(ctx)) - fill_slice_short(&ctx_pic->slice_short[ctx_pic->slice_count], - position, size); - else - fill_slice_long(avctx, &ctx_pic->slice_long[ctx_pic->slice_count], - position, size); - ctx_pic->slice_count++; - - if (h->slice_type != AV_PICTURE_TYPE_I && h->slice_type != AV_PICTURE_TYPE_SI) - ctx_pic->pp.wBitFields &= ~(1 << 15); /* Set IntraPicFlag to 0 */ - return 0; -} - -static int dxva2_h264_end_frame(AVCodecContext *avctx) -{ - H264Context *h = avctx->priv_data; - struct dxva2_picture_context *ctx_pic = - h->cur_pic_ptr->hwaccel_picture_private; - int ret; - - if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) - return -1; - ret = ff_dxva2_common_end_frame(avctx, h->cur_pic_ptr, - &ctx_pic->pp, sizeof(ctx_pic->pp), - &ctx_pic->qm, sizeof(ctx_pic->qm), - commit_bitstream_and_slice_buffer); - if (!ret) - ff_h264_draw_horiz_band(h, 0, h->avctx->height); - return ret; -} - -AVHWAccel ff_h264_dxva2_hwaccel = { - .name = "h264_dxva2", - .type = AVMEDIA_TYPE_VIDEO, - .id = AV_CODEC_ID_H264, - .pix_fmt = AV_PIX_FMT_DXVA2_VLD, - .start_frame = dxva2_h264_start_frame, - .decode_slice = dxva2_h264_decode_slice, - .end_frame = dxva2_h264_end_frame, - .priv_data_size = sizeof(struct dxva2_picture_context), -}; |
