---
libavcodec/Makefile | 12 +-
libavcodec/dxva2.c | 174 -------------
libavcodec/dxva2_h264.c | 475 ------------------------------------
libavcodec/dxva2_hevc.c | 381 -----------------------------
libavcodec/dxva2_internal.h | 56 -----
libavcodec/dxva2_mpeg2.c | 283 ---------------------
libavcodec/dxva2_vc1.c | 297 ----------------------
libavcodec/dxva_h264_template.c | 475 ++++++++++++++++++++++++++++++++++++
libavcodec/dxva_hevc_template.c | 381 +++++++++++++++++++++++++++++
libavcodec/dxva_internal_template.h | 56 +++++
libavcodec/dxva_mpeg2_template.c | 283 +++++++++++++++++++++
libavcodec/dxva_template.c | 174 +++++++++++++
libavcodec/dxva_vc1_template.c | 297 ++++++++++++++++++++++
13 files changed, 1672 insertions(+), 1672 deletions(-)
delete mode 100644 libavcodec/dxva2.c
delete mode 100644 libavcodec/dxva2_h264.c
delete mode 100644 libavcodec/dxva2_hevc.c
delete mode 100644 libavcodec/dxva2_internal.h
delete mode 100644 libavcodec/dxva2_mpeg2.c
delete mode 100644 libavcodec/dxva2_vc1.c
create mode 100644 libavcodec/dxva_h264_template.c
create mode 100644 libavcodec/dxva_hevc_template.c
create mode 100644 libavcodec/dxva_internal_template.h
create mode 100644 libavcodec/dxva_mpeg2_template.c
create mode 100644 libavcodec/dxva_template.c
create mode 100644 libavcodec/dxva_vc1_template.c
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index fc8c6e9..0937af9 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -557,25 +557,25 @@ OBJS-$(CONFIG_ADPCM_YAMAHA_DECODER) += adpcm.o
adpcm_data.o
OBJS-$(CONFIG_ADPCM_YAMAHA_ENCODER) += adpcmenc.o adpcm_data.o
# hardware accelerators
-OBJS-$(CONFIG_DXVA2) += dxva2.o
+OBJS-$(CONFIG_DXVA2) += dxva_template.o
OBJS-$(CONFIG_VAAPI) += vaapi.o
OBJS-$(CONFIG_VDA) += vda.o
OBJS-$(CONFIG_VDPAU) += vdpau.o
OBJS-$(CONFIG_H263_VAAPI_HWACCEL) += vaapi_mpeg4.o
OBJS-$(CONFIG_H263_VDPAU_HWACCEL) += vdpau_mpeg4.o
-OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
+OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva_h264_template.o
OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
OBJS-$(CONFIG_H264_VDA_HWACCEL) += vda_h264.o
OBJS-$(CONFIG_H264_VDPAU_HWACCEL) += vdpau_h264.o
-OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva2_hevc.o
+OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL) += dxva_hevc_template.o
OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL) += vdpau_mpeg12.o
-OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva2_mpeg2.o
+OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL) += dxva_mpeg2_template.o
OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL) += vaapi_mpeg2.o
OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL) += vdpau_mpeg12.o
OBJS-$(CONFIG_MPEG4_VAAPI_HWACCEL) += vaapi_mpeg4.o
OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL) += vdpau_mpeg4.o
-OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva2_vc1.o
+OBJS-$(CONFIG_VC1_DXVA2_HWACCEL) += dxva_vc1_template.o
OBJS-$(CONFIG_VC1_VAAPI_HWACCEL) += vaapi_vc1.o
OBJS-$(CONFIG_VC1_VDPAU_HWACCEL) += vdpau_vc1.o
@@ -723,7 +723,7 @@ SKIPHEADERS += %_tablegen.h
\
tableprint.h \
$(ARCH)/vp56_arith.h \
-SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal.h
+SKIPHEADERS-$(CONFIG_DXVA2) += dxva2.h dxva2_internal_template.h
SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h
SKIPHEADERS-$(CONFIG_MPEG_XVMC_DECODER) += xvmc.h
SKIPHEADERS-$(CONFIG_QSV) += qsv.h qsv_internal.h
diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
deleted file mode 100644
index 9ee22c8..0000000
--- a/libavcodec/dxva2.c
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * DXVA2 HW acceleration.
- *
- * copyright (c) 2010 Laurent Aimar
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <assert.h>
-#include <string.h>
-
-#include "libavutil/log.h"
-#include "libavutil/time.h"
-
-#include "avcodec.h"
-#include "mpegvideo.h"
-#include "dxva2_internal.h"
-
-void *ff_dxva2_get_surface(const AVFrame *frame)
-{
- return frame->data[3];
-}
-
-unsigned ff_dxva2_get_surface_index(const struct dxva_context *ctx,
- const AVFrame *frame)
-{
- void *surface = ff_dxva2_get_surface(frame);
- unsigned i;
-
- for (i = 0; i < ctx->surface_count; i++)
- if (ctx->surface[i] == surface)
- return i;
-
- assert(0);
- return 0;
-}
-
-int ff_dxva2_commit_buffer(AVCodecContext *avctx,
- struct dxva_context *ctx,
- DXVA2_DecodeBufferDesc *dsc,
- unsigned type, const void *data, unsigned size,
- unsigned mb_count)
-{
- void *dxva_data;
- unsigned dxva_size;
- int result;
- HRESULT hr;
-
- hr = IDirectXVideoDecoder_GetBuffer(ctx->decoder, type,
- &dxva_data, &dxva_size);
- if (FAILED(hr)) {
- av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %u: 0x%lx\n",
- type, hr);
- return -1;
- }
- if (size <= dxva_size) {
- memcpy(dxva_data, data, size);
-
- memset(dsc, 0, sizeof(*dsc));
- dsc->CompressedBufferType = type;
- dsc->DataSize = size;
- dsc->NumMBsInBuffer = mb_count;
-
- result = 0;
- } else {
- av_log(avctx, AV_LOG_ERROR, "Buffer for type %u was too small\n",
type);
- result = -1;
- }
-
- hr = IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, type);
- if (FAILED(hr)) {
- av_log(avctx, AV_LOG_ERROR,
- "Failed to release buffer type %u: 0x%lx\n",
- type, hr);
- result = -1;
- }
- return result;
-}
-
-int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
- 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, runs = 0;
- HRESULT hr;
-
- do {
- hr = IDirectXVideoDecoder_BeginFrame(ctx->decoder,
- ff_dxva2_get_surface(frame),
- NULL);
- if (hr == E_PENDING)
- av_usleep(2000);
- } while (hr == E_PENDING && ++runs < 50);
-
- if (FAILED(hr)) {
- av_log(avctx, AV_LOG_ERROR, "Failed to begin frame: 0x%lx\n", hr);
- 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;
- hr = IDirectXVideoDecoder_Execute(ctx->decoder, &exec);
- if (FAILED(hr)) {
- av_log(avctx, AV_LOG_ERROR, "Failed to execute: 0x%lx\n", hr);
- result = -1;
- }
-
-end:
- hr = IDirectXVideoDecoder_EndFrame(ctx->decoder, NULL);
- if (FAILED(hr)) {
- av_log(avctx, AV_LOG_ERROR, "Failed to end frame: 0x%lx\n", hr);
- result = -1;
- }
-
- return result;
-}
diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c
deleted file mode 100644
index a5e9705..0000000
--- a/libavcodec/dxva2_h264.c
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * DXVA2 H264 HW acceleration.
- *
- * copyright (c) 2009 Laurent Aimar
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; 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"
-#include "mpegutils.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 H264Picture *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->f),
- 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 H264Picture *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->f),
- 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 Libav) */
- (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 if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO)
- pp->Reserved16Bits = 0x34c;
- 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 Libav */
- //pp->SliceGroupMap[810]; /* XXX not implemented by Libav */
-}
-
-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 int get_refpic_index(const DXVA_PicParams_H264 *pp, int surface_index)
-{
- int i;
- for (i = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) {
- if ((pp->RefFrameList[i].bPicEntry & 0x7f) == surface_index)
- return i;
- }
- return 0x7f;
-}
-
-static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice,
- const DXVA_PicParams_H264 *pp, unsigned position,
unsigned size)
-{
- const H264Context *h = avctx->priv_data;
- H264SliceContext *sl = &h->slice_ctx[0];
- 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 = (sl->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) *
h->mb_width + sl->mb_x;
- slice->NumMbsForSlice = 0; /* XXX it is set once we have all slices
*/
- slice->BitOffsetToSliceData = get_bits_count(&sl->gb);
- slice->slice_type = ff_h264_get_slice_type(sl);
- if (sl->slice_type_fixed)
- slice->slice_type += 5;
- slice->luma_log2_weight_denom = sl->luma_log2_weight_denom;
- slice->chroma_log2_weight_denom = sl->chroma_log2_weight_denom;
- if (sl->list_count > 0)
- slice->num_ref_idx_l0_active_minus1 = sl->ref_count[0] - 1;
- if (sl->list_count > 1)
- slice->num_ref_idx_l1_active_minus1 = sl->ref_count[1] - 1;
- slice->slice_alpha_c0_offset_div2 = sl->slice_alpha_c0_offset / 2;
- slice->slice_beta_offset_div2 = sl->slice_beta_offset / 2;
- slice->Reserved8Bits = 0;
-
- for (list = 0; list < 2; list++) {
- unsigned i;
- for (i = 0; i < FF_ARRAY_ELEMS(slice->RefPicList[list]); i++) {
- if (list < sl->list_count && i < sl->ref_count[list]) {
- const H264Picture *r = sl->ref_list[list][i].parent;
- unsigned plane;
- unsigned index;
- if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO)
- index = ff_dxva2_get_surface_index(ctx, r->f);
- else
- index = get_refpic_index(pp,
ff_dxva2_get_surface_index(ctx, r->f));
- fill_picture_entry(&slice->RefPicList[list][i], index,
- r->reference == PICT_BOTTOM_FIELD);
- for (plane = 0; plane < 3; plane++) {
- int w, o;
- if (plane == 0 && sl->luma_weight_flag[list]) {
- w = sl->luma_weight[i][list][0];
- o = sl->luma_weight[i][list][1];
- } else if (plane >= 1 && sl->chroma_weight_flag[list]) {
- w = sl->chroma_weight[i][list][plane-1][0];
- o = sl->chroma_weight[i][list][plane-1][1];
- } else {
- w = 1 << (plane == 0 ? sl->luma_log2_weight_denom :
- sl->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 Libav */
- slice->slice_qp_delta = sl->qscale - h->pps.init_qp;
- slice->redundant_pic_cnt = sl->redundant_pic_count;
- if (sl->slice_type == AV_PICTURE_TYPE_B)
- slice->direct_spatial_mv_pred_flag = sl->direct_spatial_mv_pred;
- slice->cabac_init_idc = h->pps.cabac ? sl->cabac_init_idc : 0;
- if (sl->deblocking_filter < 2)
- slice->disable_deblocking_filter_idc = 1 - sl->deblocking_filter;
- else
- slice->disable_deblocking_filter_idc = sl->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 H264Picture *current_picture = h->cur_pic_ptr;
- struct dxva2_picture_context *ctx_pic =
current_picture->hwaccel_picture_private;
- DXVA_Slice_H264_Short *slice = NULL;
- void *dxva_data_ptr;
- 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,
- &dxva_data_ptr, &dxva_size)))
- return -1;
-
- dxva_data = dxva_data_ptr;
- 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;
- const H264SliceContext *sl = &h->slice_ctx[0];
- struct dxva_context *ctx = avctx->hwaccel_context;
- const H264Picture *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],
- &ctx_pic->pp, position, size);
- ctx_pic->slice_count++;
-
- if (sl->slice_type != AV_PICTURE_TYPE_I && sl->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;
- H264SliceContext *sl = &h->slice_ctx[0];
- 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->f,
- &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, sl, 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,
- .frame_priv_data_size = sizeof(struct dxva2_picture_context),
-};
diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c
deleted file mode 100644
index 257bee7..0000000
--- a/libavcodec/dxva2_hevc.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * DXVA2 HEVC HW acceleration.
- *
- * copyright (c) 2014 - 2015 Hendrik Leppkes
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/avassert.h"
-
-#include "dxva2_internal.h"
-#include "hevc.h"
-
-#define MAX_SLICES 256
-
-struct hevc_dxva2_picture_context {
- DXVA_PicParams_HEVC pp;
- DXVA_Qmatrix_HEVC qm;
- unsigned slice_count;
- DXVA_Slice_HEVC_Short slice_short[MAX_SLICES];
- const uint8_t *bitstream;
- unsigned bitstream_size;
-};
-
-static void fill_picture_entry(DXVA_PicEntry_HEVC *pic,
- unsigned index, unsigned flag)
-{
- av_assert0((index & 0x7f) == index && (flag & 0x01) == flag);
- pic->bPicEntry = index | (flag << 7);
-}
-
-static int get_refpic_index(const DXVA_PicParams_HEVC *pp, int surface_index)
-{
- int i;
- for (i = 0; i < FF_ARRAY_ELEMS(pp->RefPicList); i++) {
- if ((pp->RefPicList[i].bPicEntry & 0x7f) == surface_index)
- return i;
- }
- return 0xff;
-}
-
-static void fill_picture_parameters(struct dxva_context *ctx, const
HEVCContext *h,
- DXVA_PicParams_HEVC *pp)
-{
- const HEVCFrame *current_picture = h->ref;
- int i, j, k;
-
- memset(pp, 0, sizeof(*pp));
-
- pp->PicWidthInMinCbsY = h->sps->min_cb_width;
- pp->PicHeightInMinCbsY = h->sps->min_cb_height;
-
- pp->wFormatAndSequenceInfoFlags = (h->sps->chroma_format_idc <<
0) |
- (h->sps->separate_colour_plane_flag <<
2) |
- ((h->sps->bit_depth - 8) <<
3) |
- ((h->sps->bit_depth - 8) <<
6) |
- ((h->sps->log2_max_poc_lsb - 4) <<
9) |
- (0 <<
13) |
- (0 <<
14) |
- (0 <<
15);
-
- fill_picture_entry(&pp->CurrPic, ff_dxva2_get_surface_index(ctx,
current_picture->frame), 0);
-
- pp->sps_max_dec_pic_buffering_minus1 =
h->sps->temporal_layer[h->sps->max_sub_layers - 1].max_dec_pic_buffering - 1;
- pp->log2_min_luma_coding_block_size_minus3 = h->sps->log2_min_cb_size -
3;
- pp->log2_diff_max_min_luma_coding_block_size =
h->sps->log2_diff_max_min_coding_block_size;
- pp->log2_min_transform_block_size_minus2 = h->sps->log2_min_tb_size -
2;
- pp->log2_diff_max_min_transform_block_size = h->sps->log2_max_trafo_size
- h->sps->log2_min_tb_size;
- pp->max_transform_hierarchy_depth_inter =
h->sps->max_transform_hierarchy_depth_inter;
- pp->max_transform_hierarchy_depth_intra =
h->sps->max_transform_hierarchy_depth_intra;
- pp->num_short_term_ref_pic_sets = h->sps->nb_st_rps;
- pp->num_long_term_ref_pics_sps =
h->sps->num_long_term_ref_pics_sps;
-
- pp->num_ref_idx_l0_default_active_minus1 =
h->pps->num_ref_idx_l0_default_active - 1;
- pp->num_ref_idx_l1_default_active_minus1 =
h->pps->num_ref_idx_l1_default_active - 1;
- pp->init_qp_minus26 = h->pps->pic_init_qp_minus26;
-
- if (h->sh.short_term_ref_pic_set_sps_flag == 0 && h->sh.short_term_rps) {
- pp->ucNumDeltaPocsOfRefRpsIdx =
h->sh.short_term_rps->num_delta_pocs;
- pp->wNumBitsForShortTermRPSInSlice =
h->sh.short_term_ref_pic_set_size;
- }
-
- pp->dwCodingParamToolFlags = (h->sps->scaling_list_enable_flag
<< 0) |
- (h->sps->amp_enabled_flag
<< 1) |
- (h->sps->sao_enabled
<< 2) |
- (h->sps->pcm_enabled_flag
<< 3) |
- ((h->sps->pcm_enabled_flag ?
(h->sps->pcm.bit_depth - 1) : 0) << 4) |
- ((h->sps->pcm_enabled_flag ?
(h->sps->pcm.bit_depth_chroma - 1) : 0) << 8) |
- ((h->sps->pcm_enabled_flag ?
(h->sps->pcm.log2_min_pcm_cb_size - 3) : 0) << 12) |
- ((h->sps->pcm_enabled_flag ?
(h->sps->pcm.log2_max_pcm_cb_size - h->sps->pcm.log2_min_pcm_cb_size) : 0) <<
14) |
- (h->sps->pcm.loop_filter_disable_flag
<< 16) |
- (h->sps->long_term_ref_pics_present_flag
<< 17) |
- (h->sps->sps_temporal_mvp_enabled_flag
<< 18) |
-
(h->sps->sps_strong_intra_smoothing_enable_flag << 19) |
-
(h->pps->dependent_slice_segments_enabled_flag << 20) |
- (h->pps->output_flag_present_flag
<< 21) |
- (h->pps->num_extra_slice_header_bits
<< 22) |
- (h->pps->sign_data_hiding_flag
<< 25) |
- (h->pps->cabac_init_present_flag
<< 26) |
- (0
<< 27);
-
- pp->dwCodingSettingPicturePropertyFlags =
(h->pps->constrained_intra_pred_flag << 0) |
-
(h->pps->transform_skip_enabled_flag << 1) |
-
(h->pps->cu_qp_delta_enabled_flag << 2) |
-
(h->pps->pic_slice_level_chroma_qp_offsets_present_flag << 3) |
- (h->pps->weighted_pred_flag
<< 4) |
- (h->pps->weighted_bipred_flag
<< 5) |
-
(h->pps->transquant_bypass_enable_flag << 6) |
- (h->pps->tiles_enabled_flag
<< 7) |
-
(h->pps->entropy_coding_sync_enabled_flag << 8) |
- (h->pps->uniform_spacing_flag
<< 9) |
- ((h->pps->tiles_enabled_flag ?
h->pps->loop_filter_across_tiles_enabled_flag : 0) << 10) |
-
(h->pps->seq_loop_filter_across_slices_enabled_flag << 11) |
-
(h->pps->deblocking_filter_override_enabled_flag << 12) |
- (h->pps->disable_dbf
<< 13) |
-
(h->pps->lists_modification_present_flag << 14) |
-
(h->pps->slice_header_extension_present_flag << 15) |
- (IS_IRAP(h)
<< 16) |
- (IS_IDR(h)
<< 17) |
- /* IntraPicFlag */
- (IS_IRAP(h)
<< 18) |
- (0
<< 19);
- pp->pps_cb_qp_offset = h->pps->cb_qp_offset;
- pp->pps_cr_qp_offset = h->pps->cr_qp_offset;
- if (h->pps->tiles_enabled_flag) {
- pp->num_tile_columns_minus1 = h->pps->num_tile_columns - 1;
- pp->num_tile_rows_minus1 = h->pps->num_tile_rows - 1;
-
- if (!h->pps->uniform_spacing_flag) {
- for (i = 0; i < h->pps->num_tile_columns; i++)
- pp->column_width_minus1[i] = h->pps->column_width[i] - 1;
-
- for (i = 0; i < h->pps->num_tile_rows; i++)
- pp->row_height_minus1[i] = h->pps->row_height[i] - 1;
- }
- }
-
- pp->diff_cu_qp_delta_depth = h->pps->diff_cu_qp_delta_depth;
- pp->pps_beta_offset_div2 = h->pps->beta_offset / 2;
- pp->pps_tc_offset_div2 = h->pps->tc_offset / 2;
- pp->log2_parallel_merge_level_minus2 = h->pps->log2_parallel_merge_level -
2;
- pp->CurrPicOrderCntVal = h->poc;
-
- // empty the lists
- memset(&pp->RefPicList, 0xff, sizeof(pp->RefPicList));
- memset(&pp->RefPicSetStCurrBefore, 0xff,
sizeof(pp->RefPicSetStCurrBefore));
- memset(&pp->RefPicSetStCurrAfter, 0xff, sizeof(pp->RefPicSetStCurrAfter));
- memset(&pp->RefPicSetLtCurr, 0xff, sizeof(pp->RefPicSetLtCurr));
-
- // fill RefPicList from the DPB
- for (i = 0, j = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) {
- const HEVCFrame *frame = &h->DPB[i];
- if (frame != current_picture && (frame->flags &
(HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) {
- fill_picture_entry(&pp->RefPicList[j],
ff_dxva2_get_surface_index(ctx, frame->frame), !!(frame->flags &
HEVC_FRAME_FLAG_LONG_REF));
- pp->PicOrderCntValList[j] = frame->poc;
- j++;
- }
- }
-
- #define DO_REF_LIST(ref_idx, ref_list) { \
- const RefPicList *rpl = &h->rps[ref_idx]; \
- av_assert0(rpl->nb_refs <= FF_ARRAY_ELEMS(pp->ref_list)); \
- for (j = 0, k = 0; j < rpl->nb_refs; j++) { \
- if (rpl->ref[j]) { \
- pp->ref_list[k] = get_refpic_index(pp,
ff_dxva2_get_surface_index(ctx, rpl->ref[j]->frame)); \
- k++; \
- } \
- } \
- }
-
- // Fill short term and long term lists
- DO_REF_LIST(ST_CURR_BEF, RefPicSetStCurrBefore);
- DO_REF_LIST(ST_CURR_AFT, RefPicSetStCurrAfter);
- DO_REF_LIST(LT_CURR, RefPicSetLtCurr);
-
- pp->StatusReportFeedbackNumber = 1 + ctx->report_id++;
-}
-
-static void fill_scaling_lists(struct dxva_context *ctx, const HEVCContext *h,
DXVA_Qmatrix_HEVC *qm)
-{
- unsigned i, j, pos;
- const ScalingList *sl = h->pps->scaling_list_data_present_flag ?
- &h->pps->scaling_list : &h->sps->scaling_list;
-
- memset(qm, 0, sizeof(*qm));
- for (i = 0; i < 6; i++) {
- for (j = 0; j < 16; j++) {
- pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j];
- qm->ucScalingLists0[i][j] = sl->sl[0][i][pos];
- }
-
- for (j = 0; j < 64; j++) {
- pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j];
- qm->ucScalingLists1[i][j] = sl->sl[1][i][pos];
- qm->ucScalingLists2[i][j] = sl->sl[2][i][pos];
-
- if (i < 2)
- qm->ucScalingLists3[i][j] = sl->sl[3][i][pos];
- }
-
- qm->ucScalingListDCCoefSizeID2[i] = sl->sl_dc[0][i];
- if (i < 2)
- qm->ucScalingListDCCoefSizeID3[i] = sl->sl_dc[1][i];
- }
-}
-
-static void fill_slice_short(DXVA_Slice_HEVC_Short *slice,
- unsigned position, unsigned size)
-{
- memset(slice, 0, sizeof(*slice));
- slice->BSNALunitDataLocation = position;
- slice->SliceBytesInBuffer = size;
- slice->wBadSliceChopping = 0;
-}
-
-static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
- DXVA2_DecodeBufferDesc *bs,
- DXVA2_DecodeBufferDesc *sc)
-{
- const HEVCContext *h = avctx->priv_data;
- struct dxva_context *ctx = avctx->hwaccel_context;
- const HEVCFrame *current_picture = h->ref;
- struct hevc_dxva2_picture_context *ctx_pic =
current_picture->hwaccel_picture_private;
- DXVA_Slice_HEVC_Short *slice = NULL;
- void *dxva_data_ptr;
- 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,
- &dxva_data_ptr, &dxva_size)))
- return -1;
-
- dxva_data = dxva_data_ptr;
- 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;
-
- slice = &ctx_pic->slice_short[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;
-
- 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 = 0;
-
- slice_data = ctx_pic->slice_short;
- slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short);
-
- av_assert0((bs->DataSize & 127) == 0);
- return ff_dxva2_commit_buffer(avctx, ctx, sc,
- DXVA2_SliceControlBufferType,
- slice_data, slice_size, 0);
-}
-
-
-static int dxva2_hevc_start_frame(AVCodecContext *avctx,
- av_unused const uint8_t *buffer,
- av_unused uint32_t size)
-{
- const HEVCContext *h = avctx->priv_data;
- struct dxva_context *ctx = avctx->hwaccel_context;
- struct hevc_dxva2_picture_context *ctx_pic =
h->ref->hwaccel_picture_private;
-
- if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
- return -1;
- av_assert0(ctx_pic);
-
- /* Fill up DXVA_PicParams_HEVC */
- fill_picture_parameters(ctx, h, &ctx_pic->pp);
-
- /* Fill up DXVA_Qmatrix_HEVC */
- 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_hevc_decode_slice(AVCodecContext *avctx,
- const uint8_t *buffer,
- uint32_t size)
-{
- const HEVCContext *h = avctx->priv_data;
- const HEVCFrame *current_picture = h->ref;
- struct hevc_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;
- fill_slice_short(&ctx_pic->slice_short[ctx_pic->slice_count], position,
size);
- ctx_pic->slice_count++;
-
- return 0;
-}
-
-static int dxva2_hevc_end_frame(AVCodecContext *avctx)
-{
- HEVCContext *h = avctx->priv_data;
- struct hevc_dxva2_picture_context *ctx_pic =
h->ref->hwaccel_picture_private;
- int scale = ctx_pic->pp.dwCodingParamToolFlags & 1;
- int ret;
-
- if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
- return -1;
-
- ret = ff_dxva2_common_end_frame(avctx, h->ref->frame,
- &ctx_pic->pp, sizeof(ctx_pic->pp),
- scale ? &ctx_pic->qm : NULL, scale ?
sizeof(ctx_pic->qm) : 0,
- commit_bitstream_and_slice_buffer);
- return ret;
-}
-
-AVHWAccel ff_hevc_dxva2_hwaccel = {
- .name = "hevc_dxva2",
- .type = AVMEDIA_TYPE_VIDEO,
- .id = AV_CODEC_ID_HEVC,
- .pix_fmt = AV_PIX_FMT_DXVA2_VLD,
- .start_frame = dxva2_hevc_start_frame,
- .decode_slice = dxva2_hevc_decode_slice,
- .end_frame = dxva2_hevc_end_frame,
- .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context),
-};
diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h
deleted file mode 100644
index b775e6c..0000000
--- a/libavcodec/dxva2_internal.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * DXVA2 HW acceleration
- *
- * copyright (c) 2010 Laurent Aimar
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVCODEC_DXVA_INTERNAL_H
-#define AVCODEC_DXVA_INTERNAL_H
-
-#define COBJMACROS
-
-#include "config.h"
-
-#include "dxva2.h"
-#if HAVE_DXVA_H
-#include <dxva.h>
-#endif
-
-#include "avcodec.h"
-#include "mpegvideo.h"
-
-void *ff_dxva2_get_surface(const AVFrame *frame);
-
-unsigned ff_dxva2_get_surface_index(const struct dxva_context *,
- const AVFrame *frame);
-
-int ff_dxva2_commit_buffer(AVCodecContext *, struct dxva_context *,
- DXVA2_DecodeBufferDesc *,
- unsigned type, const void *data, unsigned size,
- unsigned mb_count);
-
-
-int ff_dxva2_common_end_frame(AVCodecContext *, AVFrame *,
- const void *pp, unsigned pp_size,
- const void *qm, unsigned qm_size,
- int (*commit_bs_si)(AVCodecContext *,
- DXVA2_DecodeBufferDesc *bs,
- DXVA2_DecodeBufferDesc
*slice));
-
-#endif /* AVCODEC_DXVA_INTERNAL_H */
diff --git a/libavcodec/dxva2_mpeg2.c b/libavcodec/dxva2_mpeg2.c
deleted file mode 100644
index 65624e3..0000000
--- a/libavcodec/dxva2_mpeg2.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * MPEG-2 HW acceleration.
- *
- * copyright (c) 2010 Laurent Aimar
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavutil/log.h"
-#include "dxva2_internal.h"
-#include "mpegutils.h"
-
-#define MAX_SLICES 1024
-struct dxva2_picture_context {
- DXVA_PictureParameters pp;
- DXVA_QmatrixData qm;
- unsigned slice_count;
- DXVA_SliceInfo slice[MAX_SLICES];
-
- const uint8_t *bitstream;
- unsigned bitstream_size;
-};
-
-static void fill_picture_parameters(AVCodecContext *avctx,
- struct dxva_context *ctx,
- const struct MpegEncContext *s,
- DXVA_PictureParameters *pp)
-{
- const Picture *current_picture = s->current_picture_ptr;
- int is_field = s->picture_structure != PICT_FRAME;
-
- memset(pp, 0, sizeof(*pp));
- pp->wDecodedPictureIndex = ff_dxva2_get_surface_index(ctx,
current_picture->f);
- pp->wDeblockedPictureIndex = 0;
- if (s->pict_type != AV_PICTURE_TYPE_I)
- pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx,
s->last_picture.f);
- else
- pp->wForwardRefPictureIndex = 0xffff;
- if (s->pict_type == AV_PICTURE_TYPE_B)
- pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx,
s->next_picture.f);
- else
- pp->wBackwardRefPictureIndex = 0xffff;
- pp->wPicWidthInMBminus1 = s->mb_width - 1;
- pp->wPicHeightInMBminus1 = (s->mb_height >> is_field) - 1;
- pp->bMacroblockWidthMinus1 = 15;
- pp->bMacroblockHeightMinus1 = 15;
- pp->bBlockWidthMinus1 = 7;
- pp->bBlockHeightMinus1 = 7;
- pp->bBPPminus1 = 7;
- pp->bPicStructure = s->picture_structure;
- pp->bSecondField = is_field && !s->first_field;
- pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I;
- pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B;
- pp->bBidirectionalAveragingMode = 0;
- pp->bMVprecisionAndChromaRelation= 0; /* FIXME */
- pp->bChromaFormat = s->chroma_format;
- pp->bPicScanFixed = 1;
- pp->bPicScanMethod = s->alternate_scan ? 1 : 0;
- pp->bPicReadbackRequests = 0;
- pp->bRcontrol = 0;
- pp->bPicSpatialResid8 = 0;
- pp->bPicOverflowBlocks = 0;
- pp->bPicExtrapolation = 0;
- pp->bPicDeblocked = 0;
- pp->bPicDeblockConfined = 0;
- pp->bPic4MVallowed = 0;
- pp->bPicOBMC = 0;
- pp->bPicBinPB = 0;
- pp->bMV_RPS = 0;
- pp->bReservedBits = 0;
- pp->wBitstreamFcodes = (s->mpeg_f_code[0][0] << 12) |
- (s->mpeg_f_code[0][1] << 8) |
- (s->mpeg_f_code[1][0] << 4) |
- (s->mpeg_f_code[1][1] );
- pp->wBitstreamPCEelements = (s->intra_dc_precision << 14) |
- (s->picture_structure << 12) |
- (s->top_field_first << 11) |
- (s->frame_pred_frame_dct << 10) |
- (s->concealment_motion_vectors << 9) |
- (s->q_scale_type << 8) |
- (s->intra_vlc_format << 7) |
- (s->alternate_scan << 6) |
- (s->repeat_first_field << 5) |
- (s->chroma_420_type << 4) |
- (s->progressive_frame << 3);
- pp->bBitstreamConcealmentNeed = 0;
- pp->bBitstreamConcealmentMethod = 0;
-}
-
-static void fill_quantization_matrices(AVCodecContext *avctx,
- struct dxva_context *ctx,
- const struct MpegEncContext *s,
- DXVA_QmatrixData *qm)
-{
- int i;
- for (i = 0; i < 4; i++)
- qm->bNewQmatrix[i] = 1;
- for (i = 0; i < 64; i++) {
- int n = s->idsp.idct_permutation[ff_zigzag_direct[i]];
- qm->Qmatrix[0][i] = s->intra_matrix[n];;
- qm->Qmatrix[1][i] = s->inter_matrix[n];;
- qm->Qmatrix[2][i] = s->chroma_intra_matrix[n];;
- qm->Qmatrix[3][i] = s->chroma_inter_matrix[n];;
- }
-}
-
-static void fill_slice(AVCodecContext *avctx,
- const struct MpegEncContext *s,
- DXVA_SliceInfo *slice,
- unsigned position,
- const uint8_t *buffer, unsigned size)
-{
- int is_field = s->picture_structure != PICT_FRAME;
- GetBitContext gb;
-
- memset(slice, 0, sizeof(*slice));
- slice->wHorizontalPosition = s->mb_x;
- slice->wVerticalPosition = s->mb_y >> is_field;
- slice->dwSliceBitsInBuffer = 8 * size;
- slice->dwSliceDataLocation = position;
- slice->bStartCodeBitOffset = 0;
- slice->bReservedBits = 0;
- /* XXX We store the index of the first MB and it will be fixed later */
- slice->wNumberMBsInSlice = (s->mb_y >> is_field) * s->mb_width + s->mb_x;
- slice->wBadSliceChopping = 0;
-
- init_get_bits(&gb, &buffer[4], 8 * (size - 4));
-
- slice->wQuantizerScaleCode = get_bits(&gb, 5);
- while (get_bits1(&gb))
- skip_bits(&gb, 8);
-
- slice->wMBbitOffset = 4 * 8 + get_bits_count(&gb);
-}
-static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
- DXVA2_DecodeBufferDesc *bs,
- DXVA2_DecodeBufferDesc *sc)
-{
- const struct MpegEncContext *s = avctx->priv_data;
- struct dxva_context *ctx = avctx->hwaccel_context;
- struct dxva2_picture_context *ctx_pic =
- s->current_picture_ptr->hwaccel_picture_private;
- const int is_field = s->picture_structure != PICT_FRAME;
- const unsigned mb_count = s->mb_width * (s->mb_height >> is_field);
- void *dxva_data_ptr;
- uint8_t *dxva_data, *current, *end;
- unsigned dxva_size;
- unsigned i;
-
- if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder,
- DXVA2_BitStreamDateBufferType,
- &dxva_data_ptr, &dxva_size)))
- return -1;
-
- dxva_data = dxva_data_ptr;
- current = dxva_data;
- end = dxva_data + dxva_size;
-
- for (i = 0; i < ctx_pic->slice_count; i++) {
- DXVA_SliceInfo *slice = &ctx_pic->slice[i];
- unsigned position = slice->dwSliceDataLocation;
- unsigned size = slice->dwSliceBitsInBuffer / 8;
- if (size > end - current) {
- av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream");
- break;
- }
- slice->dwSliceDataLocation = current - dxva_data;
-
- if (i < ctx_pic->slice_count - 1)
- slice->wNumberMBsInSlice =
- slice[1].wNumberMBsInSlice - slice[0].wNumberMBsInSlice;
- else
- slice->wNumberMBsInSlice =
- mb_count - slice[0].wNumberMBsInSlice;
-
- memcpy(current, &ctx_pic->bitstream[position], size);
- current += size;
- }
- 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;
-
- return ff_dxva2_commit_buffer(avctx, ctx, sc,
- DXVA2_SliceControlBufferType,
- ctx_pic->slice,
- ctx_pic->slice_count *
sizeof(*ctx_pic->slice),
- mb_count);
-}
-
-static int dxva2_mpeg2_start_frame(AVCodecContext *avctx,
- av_unused const uint8_t *buffer,
- av_unused uint32_t size)
-{
- const struct MpegEncContext *s = avctx->priv_data;
- struct dxva_context *ctx = avctx->hwaccel_context;
- struct dxva2_picture_context *ctx_pic =
- s->current_picture_ptr->hwaccel_picture_private;
-
- if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
- return -1;
- assert(ctx_pic);
-
- fill_picture_parameters(avctx, ctx, s, &ctx_pic->pp);
- fill_quantization_matrices(avctx, ctx, s, &ctx_pic->qm);
-
- ctx_pic->slice_count = 0;
- ctx_pic->bitstream_size = 0;
- ctx_pic->bitstream = NULL;
- return 0;
-}
-
-static int dxva2_mpeg2_decode_slice(AVCodecContext *avctx,
- const uint8_t *buffer, uint32_t size)
-{
- const struct MpegEncContext *s = avctx->priv_data;
- struct dxva2_picture_context *ctx_pic =
- s->current_picture_ptr->hwaccel_picture_private;
- unsigned position;
-
- if (ctx_pic->slice_count >= MAX_SLICES) {
- avpriv_request_sample(avctx, "%d slices in dxva2",
- ctx_pic->slice_count);
- return -1;
- }
- if (!ctx_pic->bitstream)
- ctx_pic->bitstream = buffer;
- ctx_pic->bitstream_size += size;
-
- position = buffer - ctx_pic->bitstream;
- fill_slice(avctx, s, &ctx_pic->slice[ctx_pic->slice_count++], position,
- buffer, size);
- return 0;
-}
-
-static int dxva2_mpeg2_end_frame(AVCodecContext *avctx)
-{
- struct MpegEncContext *s = avctx->priv_data;
- struct dxva2_picture_context *ctx_pic =
- s->current_picture_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, s->current_picture_ptr->f,
- &ctx_pic->pp, sizeof(ctx_pic->pp),
- &ctx_pic->qm, sizeof(ctx_pic->qm),
- commit_bitstream_and_slice_buffer);
- if (!ret)
- ff_mpeg_draw_horiz_band(s, 0, avctx->height);
- return ret;
-}
-
-AVHWAccel ff_mpeg2_dxva2_hwaccel = {
- .name = "mpeg2_dxva2",
- .type = AVMEDIA_TYPE_VIDEO,
- .id = AV_CODEC_ID_MPEG2VIDEO,
- .pix_fmt = AV_PIX_FMT_DXVA2_VLD,
- .start_frame = dxva2_mpeg2_start_frame,
- .decode_slice = dxva2_mpeg2_decode_slice,
- .end_frame = dxva2_mpeg2_end_frame,
- .frame_priv_data_size = sizeof(struct dxva2_picture_context),
-};
diff --git a/libavcodec/dxva2_vc1.c b/libavcodec/dxva2_vc1.c
deleted file mode 100644
index 1524b51..0000000
--- a/libavcodec/dxva2_vc1.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * DXVA2 WMV3/VC-1 HW acceleration.
- *
- * copyright (c) 2010 Laurent Aimar
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "dxva2_internal.h"
-#include "mpegutils.h"
-#include "vc1.h"
-#include "vc1data.h"
-
-struct dxva2_picture_context {
- DXVA_PictureParameters pp;
- DXVA_SliceInfo si;
-
- const uint8_t *bitstream;
- unsigned bitstream_size;
-};
-
-static void fill_picture_parameters(AVCodecContext *avctx,
- struct dxva_context *ctx, const VC1Context
*v,
- DXVA_PictureParameters *pp)
-{
- const MpegEncContext *s = &v->s;
- const Picture *current_picture = s->current_picture_ptr;
-
- memset(pp, 0, sizeof(*pp));
- pp->wDecodedPictureIndex =
- pp->wDeblockedPictureIndex = ff_dxva2_get_surface_index(ctx,
current_picture->f);
- if (s->pict_type != AV_PICTURE_TYPE_I && !v->bi_type)
- pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx,
s->last_picture.f);
- else
- pp->wForwardRefPictureIndex = 0xffff;
- if (s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type)
- pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx,
s->next_picture.f);
- else
- pp->wBackwardRefPictureIndex = 0xffff;
- if (v->profile == PROFILE_ADVANCED) {
- /* It is the cropped width/height -1 of the frame */
- pp->wPicWidthInMBminus1 = avctx->width - 1;
- pp->wPicHeightInMBminus1= avctx->height - 1;
- } else {
- /* It is the coded width/height in macroblock -1 of the frame */
- pp->wPicWidthInMBminus1 = s->mb_width - 1;
- pp->wPicHeightInMBminus1= s->mb_height - 1;
- }
- pp->bMacroblockWidthMinus1 = 15;
- pp->bMacroblockHeightMinus1 = 15;
- pp->bBlockWidthMinus1 = 7;
- pp->bBlockHeightMinus1 = 7;
- pp->bBPPminus1 = 7;
- if (s->picture_structure & PICT_TOP_FIELD)
- pp->bPicStructure |= 0x01;
- if (s->picture_structure & PICT_BOTTOM_FIELD)
- pp->bPicStructure |= 0x02;
- pp->bSecondField = v->interlace && v->fcm != ILACE_FIELD &&
!s->first_field;
- pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I ||
v->bi_type;
- pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B &&
!v->bi_type;
- pp->bBidirectionalAveragingMode = (1
<< 7) |
- ((ctx->cfg->ConfigIntraResidUnsigned !=
0) << 6) |
- ((ctx->cfg->ConfigResidDiffAccelerator
!= 0) << 5) |
- ((v->lumscale != 32 || v->lumshift != 0)
<< 4) |
- ((v->profile == PROFILE_ADVANCED)
<< 3);
- pp->bMVprecisionAndChromaRelation = ((v->mv_mode ==
MV_PMODE_1MV_HPEL_BILIN) << 3) |
- (1
<< 2) |
- (0
<< 1) |
- (!s->quarter_sample
);
- pp->bChromaFormat = v->chromaformat;
- ctx->report_id++;
- if (ctx->report_id >= (1 << 16))
- ctx->report_id = 1;
- pp->bPicScanFixed = ctx->report_id >> 8;
- pp->bPicScanMethod = ctx->report_id & 0xff;
- pp->bPicReadbackRequests = 0;
- pp->bRcontrol = v->rnd;
- pp->bPicSpatialResid8 = (v->panscanflag << 7) |
- (v->refdist_flag << 6) |
- (s->loop_filter << 5) |
- (v->fastuvmc << 4) |
- (v->extended_mv << 3) |
- (v->dquant << 1) |
- (v->vstransform );
- pp->bPicOverflowBlocks = (v->quantizer_mode << 6) |
- (v->multires << 5) |
- (v->resync_marker << 4) |
- (v->rangered << 3) |
- (s->max_b_frames );
- pp->bPicExtrapolation = (!v->interlace || v->fcm == PROGRESSIVE) ? 1
: 2;
- pp->bPicDeblocked = ((!pp->bPicBackwardPrediction && v->overlap)
<< 6) |
- ((v->profile != PROFILE_ADVANCED &&
v->rangeredfrm) << 5) |
- (s->loop_filter
<< 1);
- pp->bPicDeblockConfined = (v->postprocflag << 7) |
- (v->broadcast << 6) |
- (v->interlace << 5) |
- (v->tfcntrflag << 4) |
- (v->finterpflag << 3) |
- ((s->pict_type != AV_PICTURE_TYPE_B) << 2) |
- (v->psf << 1) |
- (v->extended_dmv );
- if (s->pict_type != AV_PICTURE_TYPE_I)
- pp->bPic4MVallowed = v->mv_mode == MV_PMODE_MIXED_MV ||
- (v->mv_mode == MV_PMODE_INTENSITY_COMP &&
- v->mv_mode2 == MV_PMODE_MIXED_MV);
- if (v->profile == PROFILE_ADVANCED)
- pp->bPicOBMC = (v->range_mapy_flag << 7) |
- (v->range_mapy << 4) |
- (v->range_mapuv_flag << 3) |
- (v->range_mapuv );
- pp->bPicBinPB = 0;
- pp->bMV_RPS = 0;
- pp->bReservedBits = 0;
- if (s->picture_structure == PICT_FRAME) {
- pp->wBitstreamFcodes = v->lumscale;
- pp->wBitstreamPCEelements = v->lumshift;
- } else {
- /* Syntax: (top_field_param << 8) | bottom_field_param */
- pp->wBitstreamFcodes = (v->lumscale << 8) | v->lumscale;
- pp->wBitstreamPCEelements = (v->lumshift << 8) | v->lumshift;
- }
- pp->bBitstreamConcealmentNeed = 0;
- pp->bBitstreamConcealmentMethod = 0;
-}
-
-static void fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice,
- unsigned position, unsigned size)
-{
- const VC1Context *v = avctx->priv_data;
- const MpegEncContext *s = &v->s;
-
- memset(slice, 0, sizeof(*slice));
- slice->wHorizontalPosition = 0;
- slice->wVerticalPosition = s->mb_y;
- slice->dwSliceBitsInBuffer = 8 * size;
- slice->dwSliceDataLocation = position;
- slice->bStartCodeBitOffset = 0;
- slice->bReservedBits = 0;
- slice->wMBbitOffset = get_bits_count(&s->gb);
- slice->wNumberMBsInSlice = s->mb_width * s->mb_height; /* XXX We assume
1 slice */
- slice->wQuantizerScaleCode = v->pq;
- slice->wBadSliceChopping = 0;
-}
-
-static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
- DXVA2_DecodeBufferDesc *bs,
- DXVA2_DecodeBufferDesc *sc)
-{
- const VC1Context *v = avctx->priv_data;
- struct dxva_context *ctx = avctx->hwaccel_context;
- const MpegEncContext *s = &v->s;
- struct dxva2_picture_context *ctx_pic =
s->current_picture_ptr->hwaccel_picture_private;
-
- DXVA_SliceInfo *slice = &ctx_pic->si;
-
- static const uint8_t start_code[] = { 0, 0, 1, 0x0d };
- const unsigned start_code_size = avctx->codec_id == AV_CODEC_ID_VC1 ?
sizeof(start_code) : 0;
- const unsigned slice_size = slice->dwSliceBitsInBuffer / 8;
- const unsigned padding = 128 - ((start_code_size + slice_size) & 127);
- const unsigned data_size = start_code_size + slice_size + padding;
-
- void *dxva_data_ptr;
- uint8_t *dxva_data;
- unsigned dxva_size;
- int result;
-
- if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder,
- DXVA2_BitStreamDateBufferType,
- &dxva_data_ptr, &dxva_size)))
- return -1;
-
- dxva_data = dxva_data_ptr;
- result = data_size <= dxva_size ? 0 : -1;
- if (!result) {
- if (start_code_size > 0)
- memcpy(dxva_data, start_code, start_code_size);
- memcpy(dxva_data + start_code_size,
- ctx_pic->bitstream + slice->dwSliceDataLocation, slice_size);
- if (padding > 0)
- memset(dxva_data + start_code_size + slice_size, 0, padding);
- slice->dwSliceBitsInBuffer = 8 * data_size;
- }
- if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder,
-
DXVA2_BitStreamDateBufferType)))
- return -1;
- if (result)
- return result;
-
- memset(bs, 0, sizeof(*bs));
- bs->CompressedBufferType = DXVA2_BitStreamDateBufferType;
- bs->DataSize = data_size;
- bs->NumMBsInBuffer = s->mb_width * s->mb_height;
- assert((bs->DataSize & 127) == 0);
-
- return ff_dxva2_commit_buffer(avctx, ctx, sc,
- DXVA2_SliceControlBufferType,
- slice, sizeof(*slice), bs->NumMBsInBuffer);
-}
-
-static int dxva2_vc1_start_frame(AVCodecContext *avctx,
- av_unused const uint8_t *buffer,
- av_unused uint32_t size)
-{
- const VC1Context *v = avctx->priv_data;
- struct dxva_context *ctx = avctx->hwaccel_context;
- struct dxva2_picture_context *ctx_pic =
v->s.current_picture_ptr->hwaccel_picture_private;
-
- if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
- return -1;
- assert(ctx_pic);
-
- fill_picture_parameters(avctx, ctx, v, &ctx_pic->pp);
-
- ctx_pic->bitstream_size = 0;
- ctx_pic->bitstream = NULL;
- return 0;
-}
-
-static int dxva2_vc1_decode_slice(AVCodecContext *avctx,
- const uint8_t *buffer,
- uint32_t size)
-{
- const VC1Context *v = avctx->priv_data;
- const Picture *current_picture = v->s.current_picture_ptr;
- struct dxva2_picture_context *ctx_pic =
current_picture->hwaccel_picture_private;
-
- if (ctx_pic->bitstream_size > 0)
- return -1;
-
- if (avctx->codec_id == AV_CODEC_ID_VC1 &&
- size >= 4 && IS_MARKER(AV_RB32(buffer))) {
- buffer += 4;
- size -= 4;
- }
-
- ctx_pic->bitstream_size = size;
- ctx_pic->bitstream = buffer;
-
- fill_slice(avctx, &ctx_pic->si, 0, size);
- return 0;
-}
-
-static int dxva2_vc1_end_frame(AVCodecContext *avctx)
-{
- VC1Context *v = avctx->priv_data;
- struct dxva2_picture_context *ctx_pic =
v->s.current_picture_ptr->hwaccel_picture_private;
- int ret;
-
- if (ctx_pic->bitstream_size <= 0)
- return -1;
-
- ret = ff_dxva2_common_end_frame(avctx, v->s.current_picture_ptr->f,
- &ctx_pic->pp, sizeof(ctx_pic->pp),
- NULL, 0,
- commit_bitstream_and_slice_buffer);
- if (!ret)
- ff_mpeg_draw_horiz_band(&v->s, 0, avctx->height);
- return ret;
-}
-
-#if CONFIG_WMV3_DXVA2_HWACCEL
-AVHWAccel ff_wmv3_dxva2_hwaccel = {
- .name = "wmv3_dxva2",
- .type = AVMEDIA_TYPE_VIDEO,
- .id = AV_CODEC_ID_WMV3,
- .pix_fmt = AV_PIX_FMT_DXVA2_VLD,
- .start_frame = dxva2_vc1_start_frame,
- .decode_slice = dxva2_vc1_decode_slice,
- .end_frame = dxva2_vc1_end_frame,
- .frame_priv_data_size = sizeof(struct dxva2_picture_context),
-};
-#endif
-
-AVHWAccel ff_vc1_dxva2_hwaccel = {
- .name = "vc1_dxva2",
- .type = AVMEDIA_TYPE_VIDEO,
- .id = AV_CODEC_ID_VC1,
- .pix_fmt = AV_PIX_FMT_DXVA2_VLD,
- .start_frame = dxva2_vc1_start_frame,
- .decode_slice = dxva2_vc1_decode_slice,
- .end_frame = dxva2_vc1_end_frame,
- .frame_priv_data_size = sizeof(struct dxva2_picture_context),
-};
diff --git a/libavcodec/dxva_h264_template.c b/libavcodec/dxva_h264_template.c
new file mode 100644
index 0000000..78c0f71
--- /dev/null
+++ b/libavcodec/dxva_h264_template.c
@@ -0,0 +1,475 @@
+/*
+ * DXVA2 H264 HW acceleration.
+ *
+ * copyright (c) 2009 Laurent Aimar
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "dxva_internal_template.h"
+#include "h264.h"
+#include "h264data.h"
+#include "mpegutils.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 H264Picture *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->f),
+ 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 H264Picture *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->f),
+ 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 Libav) */
+ (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 if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO)
+ pp->Reserved16Bits = 0x34c;
+ 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 Libav */
+ //pp->SliceGroupMap[810]; /* XXX not implemented by Libav */
+}
+
+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 int get_refpic_index(const DXVA_PicParams_H264 *pp, int surface_index)
+{
+ int i;
+ for (i = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) {
+ if ((pp->RefFrameList[i].bPicEntry & 0x7f) == surface_index)
+ return i;
+ }
+ return 0x7f;
+}
+
+static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice,
+ const DXVA_PicParams_H264 *pp, unsigned position,
unsigned size)
+{
+ const H264Context *h = avctx->priv_data;
+ H264SliceContext *sl = &h->slice_ctx[0];
+ 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 = (sl->mb_y >> FIELD_OR_MBAFF_PICTURE(h)) *
h->mb_width + sl->mb_x;
+ slice->NumMbsForSlice = 0; /* XXX it is set once we have all slices
*/
+ slice->BitOffsetToSliceData = get_bits_count(&sl->gb);
+ slice->slice_type = ff_h264_get_slice_type(sl);
+ if (sl->slice_type_fixed)
+ slice->slice_type += 5;
+ slice->luma_log2_weight_denom = sl->luma_log2_weight_denom;
+ slice->chroma_log2_weight_denom = sl->chroma_log2_weight_denom;
+ if (sl->list_count > 0)
+ slice->num_ref_idx_l0_active_minus1 = sl->ref_count[0] - 1;
+ if (sl->list_count > 1)
+ slice->num_ref_idx_l1_active_minus1 = sl->ref_count[1] - 1;
+ slice->slice_alpha_c0_offset_div2 = sl->slice_alpha_c0_offset / 2;
+ slice->slice_beta_offset_div2 = sl->slice_beta_offset / 2;
+ slice->Reserved8Bits = 0;
+
+ for (list = 0; list < 2; list++) {
+ unsigned i;
+ for (i = 0; i < FF_ARRAY_ELEMS(slice->RefPicList[list]); i++) {
+ if (list < sl->list_count && i < sl->ref_count[list]) {
+ const H264Picture *r = sl->ref_list[list][i].parent;
+ unsigned plane;
+ unsigned index;
+ if (ctx->workaround & FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO)
+ index = ff_dxva2_get_surface_index(ctx, r->f);
+ else
+ index = get_refpic_index(pp,
ff_dxva2_get_surface_index(ctx, r->f));
+ fill_picture_entry(&slice->RefPicList[list][i], index,
+ r->reference == PICT_BOTTOM_FIELD);
+ for (plane = 0; plane < 3; plane++) {
+ int w, o;
+ if (plane == 0 && sl->luma_weight_flag[list]) {
+ w = sl->luma_weight[i][list][0];
+ o = sl->luma_weight[i][list][1];
+ } else if (plane >= 1 && sl->chroma_weight_flag[list]) {
+ w = sl->chroma_weight[i][list][plane-1][0];
+ o = sl->chroma_weight[i][list][plane-1][1];
+ } else {
+ w = 1 << (plane == 0 ? sl->luma_log2_weight_denom :
+ sl->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 Libav */
+ slice->slice_qp_delta = sl->qscale - h->pps.init_qp;
+ slice->redundant_pic_cnt = sl->redundant_pic_count;
+ if (sl->slice_type == AV_PICTURE_TYPE_B)
+ slice->direct_spatial_mv_pred_flag = sl->direct_spatial_mv_pred;
+ slice->cabac_init_idc = h->pps.cabac ? sl->cabac_init_idc : 0;
+ if (sl->deblocking_filter < 2)
+ slice->disable_deblocking_filter_idc = 1 - sl->deblocking_filter;
+ else
+ slice->disable_deblocking_filter_idc = sl->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 H264Picture *current_picture = h->cur_pic_ptr;
+ struct dxva2_picture_context *ctx_pic =
current_picture->hwaccel_picture_private;
+ DXVA_Slice_H264_Short *slice = NULL;
+ void *dxva_data_ptr;
+ 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,
+ &dxva_data_ptr, &dxva_size)))
+ return -1;
+
+ dxva_data = dxva_data_ptr;
+ 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;
+ const H264SliceContext *sl = &h->slice_ctx[0];
+ struct dxva_context *ctx = avctx->hwaccel_context;
+ const H264Picture *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],
+ &ctx_pic->pp, position, size);
+ ctx_pic->slice_count++;
+
+ if (sl->slice_type != AV_PICTURE_TYPE_I && sl->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;
+ H264SliceContext *sl = &h->slice_ctx[0];
+ 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->f,
+ &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, sl, 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,
+ .frame_priv_data_size = sizeof(struct dxva2_picture_context),
+};
diff --git a/libavcodec/dxva_hevc_template.c b/libavcodec/dxva_hevc_template.c
new file mode 100644
index 0000000..932eb50
--- /dev/null
+++ b/libavcodec/dxva_hevc_template.c
@@ -0,0 +1,381 @@
+/*
+ * DXVA2 HEVC HW acceleration.
+ *
+ * copyright (c) 2014 - 2015 Hendrik Leppkes
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/avassert.h"
+
+#include "dxva_internal_template.h"
+#include "hevc.h"
+
+#define MAX_SLICES 256
+
+struct hevc_dxva2_picture_context {
+ DXVA_PicParams_HEVC pp;
+ DXVA_Qmatrix_HEVC qm;
+ unsigned slice_count;
+ DXVA_Slice_HEVC_Short slice_short[MAX_SLICES];
+ const uint8_t *bitstream;
+ unsigned bitstream_size;
+};
+
+static void fill_picture_entry(DXVA_PicEntry_HEVC *pic,
+ unsigned index, unsigned flag)
+{
+ av_assert0((index & 0x7f) == index && (flag & 0x01) == flag);
+ pic->bPicEntry = index | (flag << 7);
+}
+
+static int get_refpic_index(const DXVA_PicParams_HEVC *pp, int surface_index)
+{
+ int i;
+ for (i = 0; i < FF_ARRAY_ELEMS(pp->RefPicList); i++) {
+ if ((pp->RefPicList[i].bPicEntry & 0x7f) == surface_index)
+ return i;
+ }
+ return 0xff;
+}
+
+static void fill_picture_parameters(struct dxva_context *ctx, const
HEVCContext *h,
+ DXVA_PicParams_HEVC *pp)
+{
+ const HEVCFrame *current_picture = h->ref;
+ int i, j, k;
+
+ memset(pp, 0, sizeof(*pp));
+
+ pp->PicWidthInMinCbsY = h->sps->min_cb_width;
+ pp->PicHeightInMinCbsY = h->sps->min_cb_height;
+
+ pp->wFormatAndSequenceInfoFlags = (h->sps->chroma_format_idc <<
0) |
+ (h->sps->separate_colour_plane_flag <<
2) |
+ ((h->sps->bit_depth - 8) <<
3) |
+ ((h->sps->bit_depth - 8) <<
6) |
+ ((h->sps->log2_max_poc_lsb - 4) <<
9) |
+ (0 <<
13) |
+ (0 <<
14) |
+ (0 <<
15);
+
+ fill_picture_entry(&pp->CurrPic, ff_dxva2_get_surface_index(ctx,
current_picture->frame), 0);
+
+ pp->sps_max_dec_pic_buffering_minus1 =
h->sps->temporal_layer[h->sps->max_sub_layers - 1].max_dec_pic_buffering - 1;
+ pp->log2_min_luma_coding_block_size_minus3 = h->sps->log2_min_cb_size -
3;
+ pp->log2_diff_max_min_luma_coding_block_size =
h->sps->log2_diff_max_min_coding_block_size;
+ pp->log2_min_transform_block_size_minus2 = h->sps->log2_min_tb_size -
2;
+ pp->log2_diff_max_min_transform_block_size = h->sps->log2_max_trafo_size
- h->sps->log2_min_tb_size;
+ pp->max_transform_hierarchy_depth_inter =
h->sps->max_transform_hierarchy_depth_inter;
+ pp->max_transform_hierarchy_depth_intra =
h->sps->max_transform_hierarchy_depth_intra;
+ pp->num_short_term_ref_pic_sets = h->sps->nb_st_rps;
+ pp->num_long_term_ref_pics_sps =
h->sps->num_long_term_ref_pics_sps;
+
+ pp->num_ref_idx_l0_default_active_minus1 =
h->pps->num_ref_idx_l0_default_active - 1;
+ pp->num_ref_idx_l1_default_active_minus1 =
h->pps->num_ref_idx_l1_default_active - 1;
+ pp->init_qp_minus26 = h->pps->pic_init_qp_minus26;
+
+ if (h->sh.short_term_ref_pic_set_sps_flag == 0 && h->sh.short_term_rps) {
+ pp->ucNumDeltaPocsOfRefRpsIdx =
h->sh.short_term_rps->num_delta_pocs;
+ pp->wNumBitsForShortTermRPSInSlice =
h->sh.short_term_ref_pic_set_size;
+ }
+
+ pp->dwCodingParamToolFlags = (h->sps->scaling_list_enable_flag
<< 0) |
+ (h->sps->amp_enabled_flag
<< 1) |
+ (h->sps->sao_enabled
<< 2) |
+ (h->sps->pcm_enabled_flag
<< 3) |
+ ((h->sps->pcm_enabled_flag ?
(h->sps->pcm.bit_depth - 1) : 0) << 4) |
+ ((h->sps->pcm_enabled_flag ?
(h->sps->pcm.bit_depth_chroma - 1) : 0) << 8) |
+ ((h->sps->pcm_enabled_flag ?
(h->sps->pcm.log2_min_pcm_cb_size - 3) : 0) << 12) |
+ ((h->sps->pcm_enabled_flag ?
(h->sps->pcm.log2_max_pcm_cb_size - h->sps->pcm.log2_min_pcm_cb_size) : 0) <<
14) |
+ (h->sps->pcm.loop_filter_disable_flag
<< 16) |
+ (h->sps->long_term_ref_pics_present_flag
<< 17) |
+ (h->sps->sps_temporal_mvp_enabled_flag
<< 18) |
+
(h->sps->sps_strong_intra_smoothing_enable_flag << 19) |
+
(h->pps->dependent_slice_segments_enabled_flag << 20) |
+ (h->pps->output_flag_present_flag
<< 21) |
+ (h->pps->num_extra_slice_header_bits
<< 22) |
+ (h->pps->sign_data_hiding_flag
<< 25) |
+ (h->pps->cabac_init_present_flag
<< 26) |
+ (0
<< 27);
+
+ pp->dwCodingSettingPicturePropertyFlags =
(h->pps->constrained_intra_pred_flag << 0) |
+
(h->pps->transform_skip_enabled_flag << 1) |
+
(h->pps->cu_qp_delta_enabled_flag << 2) |
+
(h->pps->pic_slice_level_chroma_qp_offsets_present_flag << 3) |
+ (h->pps->weighted_pred_flag
<< 4) |
+ (h->pps->weighted_bipred_flag
<< 5) |
+
(h->pps->transquant_bypass_enable_flag << 6) |
+ (h->pps->tiles_enabled_flag
<< 7) |
+
(h->pps->entropy_coding_sync_enabled_flag << 8) |
+ (h->pps->uniform_spacing_flag
<< 9) |
+ ((h->pps->tiles_enabled_flag ?
h->pps->loop_filter_across_tiles_enabled_flag : 0) << 10) |
+
(h->pps->seq_loop_filter_across_slices_enabled_flag << 11) |
+
(h->pps->deblocking_filter_override_enabled_flag << 12) |
+ (h->pps->disable_dbf
<< 13) |
+
(h->pps->lists_modification_present_flag << 14) |
+
(h->pps->slice_header_extension_present_flag << 15) |
+ (IS_IRAP(h)
<< 16) |
+ (IS_IDR(h)
<< 17) |
+ /* IntraPicFlag */
+ (IS_IRAP(h)
<< 18) |
+ (0
<< 19);
+ pp->pps_cb_qp_offset = h->pps->cb_qp_offset;
+ pp->pps_cr_qp_offset = h->pps->cr_qp_offset;
+ if (h->pps->tiles_enabled_flag) {
+ pp->num_tile_columns_minus1 = h->pps->num_tile_columns - 1;
+ pp->num_tile_rows_minus1 = h->pps->num_tile_rows - 1;
+
+ if (!h->pps->uniform_spacing_flag) {
+ for (i = 0; i < h->pps->num_tile_columns; i++)
+ pp->column_width_minus1[i] = h->pps->column_width[i] - 1;
+
+ for (i = 0; i < h->pps->num_tile_rows; i++)
+ pp->row_height_minus1[i] = h->pps->row_height[i] - 1;
+ }
+ }
+
+ pp->diff_cu_qp_delta_depth = h->pps->diff_cu_qp_delta_depth;
+ pp->pps_beta_offset_div2 = h->pps->beta_offset / 2;
+ pp->pps_tc_offset_div2 = h->pps->tc_offset / 2;
+ pp->log2_parallel_merge_level_minus2 = h->pps->log2_parallel_merge_level -
2;
+ pp->CurrPicOrderCntVal = h->poc;
+
+ // empty the lists
+ memset(&pp->RefPicList, 0xff, sizeof(pp->RefPicList));
+ memset(&pp->RefPicSetStCurrBefore, 0xff,
sizeof(pp->RefPicSetStCurrBefore));
+ memset(&pp->RefPicSetStCurrAfter, 0xff, sizeof(pp->RefPicSetStCurrAfter));
+ memset(&pp->RefPicSetLtCurr, 0xff, sizeof(pp->RefPicSetLtCurr));
+
+ // fill RefPicList from the DPB
+ for (i = 0, j = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) {
+ const HEVCFrame *frame = &h->DPB[i];
+ if (frame != current_picture && (frame->flags &
(HEVC_FRAME_FLAG_LONG_REF | HEVC_FRAME_FLAG_SHORT_REF))) {
+ fill_picture_entry(&pp->RefPicList[j],
ff_dxva2_get_surface_index(ctx, frame->frame), !!(frame->flags &
HEVC_FRAME_FLAG_LONG_REF));
+ pp->PicOrderCntValList[j] = frame->poc;
+ j++;
+ }
+ }
+
+ #define DO_REF_LIST(ref_idx, ref_list) { \
+ const RefPicList *rpl = &h->rps[ref_idx]; \
+ av_assert0(rpl->nb_refs <= FF_ARRAY_ELEMS(pp->ref_list)); \
+ for (j = 0, k = 0; j < rpl->nb_refs; j++) { \
+ if (rpl->ref[j]) { \
+ pp->ref_list[k] = get_refpic_index(pp,
ff_dxva2_get_surface_index(ctx, rpl->ref[j]->frame)); \
+ k++; \
+ } \
+ } \
+ }
+
+ // Fill short term and long term lists
+ DO_REF_LIST(ST_CURR_BEF, RefPicSetStCurrBefore);
+ DO_REF_LIST(ST_CURR_AFT, RefPicSetStCurrAfter);
+ DO_REF_LIST(LT_CURR, RefPicSetLtCurr);
+
+ pp->StatusReportFeedbackNumber = 1 + ctx->report_id++;
+}
+
+static void fill_scaling_lists(struct dxva_context *ctx, const HEVCContext *h,
DXVA_Qmatrix_HEVC *qm)
+{
+ unsigned i, j, pos;
+ const ScalingList *sl = h->pps->scaling_list_data_present_flag ?
+ &h->pps->scaling_list : &h->sps->scaling_list;
+
+ memset(qm, 0, sizeof(*qm));
+ for (i = 0; i < 6; i++) {
+ for (j = 0; j < 16; j++) {
+ pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j];
+ qm->ucScalingLists0[i][j] = sl->sl[0][i][pos];
+ }
+
+ for (j = 0; j < 64; j++) {
+ pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j];
+ qm->ucScalingLists1[i][j] = sl->sl[1][i][pos];
+ qm->ucScalingLists2[i][j] = sl->sl[2][i][pos];
+
+ if (i < 2)
+ qm->ucScalingLists3[i][j] = sl->sl[3][i][pos];
+ }
+
+ qm->ucScalingListDCCoefSizeID2[i] = sl->sl_dc[0][i];
+ if (i < 2)
+ qm->ucScalingListDCCoefSizeID3[i] = sl->sl_dc[1][i];
+ }
+}
+
+static void fill_slice_short(DXVA_Slice_HEVC_Short *slice,
+ unsigned position, unsigned size)
+{
+ memset(slice, 0, sizeof(*slice));
+ slice->BSNALunitDataLocation = position;
+ slice->SliceBytesInBuffer = size;
+ slice->wBadSliceChopping = 0;
+}
+
+static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
+ DXVA2_DecodeBufferDesc *bs,
+ DXVA2_DecodeBufferDesc *sc)
+{
+ const HEVCContext *h = avctx->priv_data;
+ struct dxva_context *ctx = avctx->hwaccel_context;
+ const HEVCFrame *current_picture = h->ref;
+ struct hevc_dxva2_picture_context *ctx_pic =
current_picture->hwaccel_picture_private;
+ DXVA_Slice_HEVC_Short *slice = NULL;
+ void *dxva_data_ptr;
+ 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,
+ &dxva_data_ptr, &dxva_size)))
+ return -1;
+
+ dxva_data = dxva_data_ptr;
+ 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;
+
+ slice = &ctx_pic->slice_short[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;
+
+ 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 = 0;
+
+ slice_data = ctx_pic->slice_short;
+ slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short);
+
+ av_assert0((bs->DataSize & 127) == 0);
+ return ff_dxva2_commit_buffer(avctx, ctx, sc,
+ DXVA2_SliceControlBufferType,
+ slice_data, slice_size, 0);
+}
+
+
+static int dxva2_hevc_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const HEVCContext *h = avctx->priv_data;
+ struct dxva_context *ctx = avctx->hwaccel_context;
+ struct hevc_dxva2_picture_context *ctx_pic =
h->ref->hwaccel_picture_private;
+
+ if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
+ return -1;
+ av_assert0(ctx_pic);
+
+ /* Fill up DXVA_PicParams_HEVC */
+ fill_picture_parameters(ctx, h, &ctx_pic->pp);
+
+ /* Fill up DXVA_Qmatrix_HEVC */
+ 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_hevc_decode_slice(AVCodecContext *avctx,
+ const uint8_t *buffer,
+ uint32_t size)
+{
+ const HEVCContext *h = avctx->priv_data;
+ const HEVCFrame *current_picture = h->ref;
+ struct hevc_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;
+ fill_slice_short(&ctx_pic->slice_short[ctx_pic->slice_count], position,
size);
+ ctx_pic->slice_count++;
+
+ return 0;
+}
+
+static int dxva2_hevc_end_frame(AVCodecContext *avctx)
+{
+ HEVCContext *h = avctx->priv_data;
+ struct hevc_dxva2_picture_context *ctx_pic =
h->ref->hwaccel_picture_private;
+ int scale = ctx_pic->pp.dwCodingParamToolFlags & 1;
+ int ret;
+
+ if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
+ return -1;
+
+ ret = ff_dxva2_common_end_frame(avctx, h->ref->frame,
+ &ctx_pic->pp, sizeof(ctx_pic->pp),
+ scale ? &ctx_pic->qm : NULL, scale ?
sizeof(ctx_pic->qm) : 0,
+ commit_bitstream_and_slice_buffer);
+ return ret;
+}
+
+AVHWAccel ff_hevc_dxva2_hwaccel = {
+ .name = "hevc_dxva2",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_HEVC,
+ .pix_fmt = AV_PIX_FMT_DXVA2_VLD,
+ .start_frame = dxva2_hevc_start_frame,
+ .decode_slice = dxva2_hevc_decode_slice,
+ .end_frame = dxva2_hevc_end_frame,
+ .frame_priv_data_size = sizeof(struct hevc_dxva2_picture_context),
+};
diff --git a/libavcodec/dxva_internal_template.h
b/libavcodec/dxva_internal_template.h
new file mode 100644
index 0000000..7f19b7c
--- /dev/null
+++ b/libavcodec/dxva_internal_template.h
@@ -0,0 +1,56 @@
+/*
+ * DXVA2 HW acceleration
+ *
+ * copyright (c) 2010 Laurent Aimar
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVCODEC_DXVA_INTERNAL_TEMPLATE_H
+#define AVCODEC_DXVA_INTERNAL_TEMPLATE_H
+
+#define COBJMACROS
+
+#include "config.h"
+
+#include "dxva2.h"
+#if HAVE_DXVA_H
+#include <dxva.h>
+#endif
+
+#include "avcodec.h"
+#include "mpegvideo.h"
+
+void *ff_dxva2_get_surface(const AVFrame *frame);
+
+unsigned ff_dxva2_get_surface_index(const struct dxva_context *,
+ const AVFrame *frame);
+
+int ff_dxva2_commit_buffer(AVCodecContext *, struct dxva_context *,
+ DXVA2_DecodeBufferDesc *,
+ unsigned type, const void *data, unsigned size,
+ unsigned mb_count);
+
+
+int ff_dxva2_common_end_frame(AVCodecContext *, AVFrame *,
+ const void *pp, unsigned pp_size,
+ const void *qm, unsigned qm_size,
+ int (*commit_bs_si)(AVCodecContext *,
+ DXVA2_DecodeBufferDesc *bs,
+ DXVA2_DecodeBufferDesc
*slice));
+
+#endif /* AVCODEC_DXVA_INTERNAL_TEMPLATE_H */
diff --git a/libavcodec/dxva_mpeg2_template.c b/libavcodec/dxva_mpeg2_template.c
new file mode 100644
index 0000000..a77a9ee
--- /dev/null
+++ b/libavcodec/dxva_mpeg2_template.c
@@ -0,0 +1,283 @@
+/*
+ * MPEG-2 HW acceleration.
+ *
+ * copyright (c) 2010 Laurent Aimar
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/log.h"
+#include "dxva_internal_template.h"
+#include "mpegutils.h"
+
+#define MAX_SLICES 1024
+struct dxva2_picture_context {
+ DXVA_PictureParameters pp;
+ DXVA_QmatrixData qm;
+ unsigned slice_count;
+ DXVA_SliceInfo slice[MAX_SLICES];
+
+ const uint8_t *bitstream;
+ unsigned bitstream_size;
+};
+
+static void fill_picture_parameters(AVCodecContext *avctx,
+ struct dxva_context *ctx,
+ const struct MpegEncContext *s,
+ DXVA_PictureParameters *pp)
+{
+ const Picture *current_picture = s->current_picture_ptr;
+ int is_field = s->picture_structure != PICT_FRAME;
+
+ memset(pp, 0, sizeof(*pp));
+ pp->wDecodedPictureIndex = ff_dxva2_get_surface_index(ctx,
current_picture->f);
+ pp->wDeblockedPictureIndex = 0;
+ if (s->pict_type != AV_PICTURE_TYPE_I)
+ pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx,
s->last_picture.f);
+ else
+ pp->wForwardRefPictureIndex = 0xffff;
+ if (s->pict_type == AV_PICTURE_TYPE_B)
+ pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx,
s->next_picture.f);
+ else
+ pp->wBackwardRefPictureIndex = 0xffff;
+ pp->wPicWidthInMBminus1 = s->mb_width - 1;
+ pp->wPicHeightInMBminus1 = (s->mb_height >> is_field) - 1;
+ pp->bMacroblockWidthMinus1 = 15;
+ pp->bMacroblockHeightMinus1 = 15;
+ pp->bBlockWidthMinus1 = 7;
+ pp->bBlockHeightMinus1 = 7;
+ pp->bBPPminus1 = 7;
+ pp->bPicStructure = s->picture_structure;
+ pp->bSecondField = is_field && !s->first_field;
+ pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I;
+ pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B;
+ pp->bBidirectionalAveragingMode = 0;
+ pp->bMVprecisionAndChromaRelation= 0; /* FIXME */
+ pp->bChromaFormat = s->chroma_format;
+ pp->bPicScanFixed = 1;
+ pp->bPicScanMethod = s->alternate_scan ? 1 : 0;
+ pp->bPicReadbackRequests = 0;
+ pp->bRcontrol = 0;
+ pp->bPicSpatialResid8 = 0;
+ pp->bPicOverflowBlocks = 0;
+ pp->bPicExtrapolation = 0;
+ pp->bPicDeblocked = 0;
+ pp->bPicDeblockConfined = 0;
+ pp->bPic4MVallowed = 0;
+ pp->bPicOBMC = 0;
+ pp->bPicBinPB = 0;
+ pp->bMV_RPS = 0;
+ pp->bReservedBits = 0;
+ pp->wBitstreamFcodes = (s->mpeg_f_code[0][0] << 12) |
+ (s->mpeg_f_code[0][1] << 8) |
+ (s->mpeg_f_code[1][0] << 4) |
+ (s->mpeg_f_code[1][1] );
+ pp->wBitstreamPCEelements = (s->intra_dc_precision << 14) |
+ (s->picture_structure << 12) |
+ (s->top_field_first << 11) |
+ (s->frame_pred_frame_dct << 10) |
+ (s->concealment_motion_vectors << 9) |
+ (s->q_scale_type << 8) |
+ (s->intra_vlc_format << 7) |
+ (s->alternate_scan << 6) |
+ (s->repeat_first_field << 5) |
+ (s->chroma_420_type << 4) |
+ (s->progressive_frame << 3);
+ pp->bBitstreamConcealmentNeed = 0;
+ pp->bBitstreamConcealmentMethod = 0;
+}
+
+static void fill_quantization_matrices(AVCodecContext *avctx,
+ struct dxva_context *ctx,
+ const struct MpegEncContext *s,
+ DXVA_QmatrixData *qm)
+{
+ int i;
+ for (i = 0; i < 4; i++)
+ qm->bNewQmatrix[i] = 1;
+ for (i = 0; i < 64; i++) {
+ int n = s->idsp.idct_permutation[ff_zigzag_direct[i]];
+ qm->Qmatrix[0][i] = s->intra_matrix[n];;
+ qm->Qmatrix[1][i] = s->inter_matrix[n];;
+ qm->Qmatrix[2][i] = s->chroma_intra_matrix[n];;
+ qm->Qmatrix[3][i] = s->chroma_inter_matrix[n];;
+ }
+}
+
+static void fill_slice(AVCodecContext *avctx,
+ const struct MpegEncContext *s,
+ DXVA_SliceInfo *slice,
+ unsigned position,
+ const uint8_t *buffer, unsigned size)
+{
+ int is_field = s->picture_structure != PICT_FRAME;
+ GetBitContext gb;
+
+ memset(slice, 0, sizeof(*slice));
+ slice->wHorizontalPosition = s->mb_x;
+ slice->wVerticalPosition = s->mb_y >> is_field;
+ slice->dwSliceBitsInBuffer = 8 * size;
+ slice->dwSliceDataLocation = position;
+ slice->bStartCodeBitOffset = 0;
+ slice->bReservedBits = 0;
+ /* XXX We store the index of the first MB and it will be fixed later */
+ slice->wNumberMBsInSlice = (s->mb_y >> is_field) * s->mb_width + s->mb_x;
+ slice->wBadSliceChopping = 0;
+
+ init_get_bits(&gb, &buffer[4], 8 * (size - 4));
+
+ slice->wQuantizerScaleCode = get_bits(&gb, 5);
+ while (get_bits1(&gb))
+ skip_bits(&gb, 8);
+
+ slice->wMBbitOffset = 4 * 8 + get_bits_count(&gb);
+}
+static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
+ DXVA2_DecodeBufferDesc *bs,
+ DXVA2_DecodeBufferDesc *sc)
+{
+ const struct MpegEncContext *s = avctx->priv_data;
+ struct dxva_context *ctx = avctx->hwaccel_context;
+ struct dxva2_picture_context *ctx_pic =
+ s->current_picture_ptr->hwaccel_picture_private;
+ const int is_field = s->picture_structure != PICT_FRAME;
+ const unsigned mb_count = s->mb_width * (s->mb_height >> is_field);
+ void *dxva_data_ptr;
+ uint8_t *dxva_data, *current, *end;
+ unsigned dxva_size;
+ unsigned i;
+
+ if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder,
+ DXVA2_BitStreamDateBufferType,
+ &dxva_data_ptr, &dxva_size)))
+ return -1;
+
+ dxva_data = dxva_data_ptr;
+ current = dxva_data;
+ end = dxva_data + dxva_size;
+
+ for (i = 0; i < ctx_pic->slice_count; i++) {
+ DXVA_SliceInfo *slice = &ctx_pic->slice[i];
+ unsigned position = slice->dwSliceDataLocation;
+ unsigned size = slice->dwSliceBitsInBuffer / 8;
+ if (size > end - current) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream");
+ break;
+ }
+ slice->dwSliceDataLocation = current - dxva_data;
+
+ if (i < ctx_pic->slice_count - 1)
+ slice->wNumberMBsInSlice =
+ slice[1].wNumberMBsInSlice - slice[0].wNumberMBsInSlice;
+ else
+ slice->wNumberMBsInSlice =
+ mb_count - slice[0].wNumberMBsInSlice;
+
+ memcpy(current, &ctx_pic->bitstream[position], size);
+ current += size;
+ }
+ 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;
+
+ return ff_dxva2_commit_buffer(avctx, ctx, sc,
+ DXVA2_SliceControlBufferType,
+ ctx_pic->slice,
+ ctx_pic->slice_count *
sizeof(*ctx_pic->slice),
+ mb_count);
+}
+
+static int dxva2_mpeg2_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const struct MpegEncContext *s = avctx->priv_data;
+ struct dxva_context *ctx = avctx->hwaccel_context;
+ struct dxva2_picture_context *ctx_pic =
+ s->current_picture_ptr->hwaccel_picture_private;
+
+ if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
+ return -1;
+ assert(ctx_pic);
+
+ fill_picture_parameters(avctx, ctx, s, &ctx_pic->pp);
+ fill_quantization_matrices(avctx, ctx, s, &ctx_pic->qm);
+
+ ctx_pic->slice_count = 0;
+ ctx_pic->bitstream_size = 0;
+ ctx_pic->bitstream = NULL;
+ return 0;
+}
+
+static int dxva2_mpeg2_decode_slice(AVCodecContext *avctx,
+ const uint8_t *buffer, uint32_t size)
+{
+ const struct MpegEncContext *s = avctx->priv_data;
+ struct dxva2_picture_context *ctx_pic =
+ s->current_picture_ptr->hwaccel_picture_private;
+ unsigned position;
+
+ if (ctx_pic->slice_count >= MAX_SLICES) {
+ avpriv_request_sample(avctx, "%d slices in dxva2",
+ ctx_pic->slice_count);
+ return -1;
+ }
+ if (!ctx_pic->bitstream)
+ ctx_pic->bitstream = buffer;
+ ctx_pic->bitstream_size += size;
+
+ position = buffer - ctx_pic->bitstream;
+ fill_slice(avctx, s, &ctx_pic->slice[ctx_pic->slice_count++], position,
+ buffer, size);
+ return 0;
+}
+
+static int dxva2_mpeg2_end_frame(AVCodecContext *avctx)
+{
+ struct MpegEncContext *s = avctx->priv_data;
+ struct dxva2_picture_context *ctx_pic =
+ s->current_picture_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, s->current_picture_ptr->f,
+ &ctx_pic->pp, sizeof(ctx_pic->pp),
+ &ctx_pic->qm, sizeof(ctx_pic->qm),
+ commit_bitstream_and_slice_buffer);
+ if (!ret)
+ ff_mpeg_draw_horiz_band(s, 0, avctx->height);
+ return ret;
+}
+
+AVHWAccel ff_mpeg2_dxva2_hwaccel = {
+ .name = "mpeg2_dxva2",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_MPEG2VIDEO,
+ .pix_fmt = AV_PIX_FMT_DXVA2_VLD,
+ .start_frame = dxva2_mpeg2_start_frame,
+ .decode_slice = dxva2_mpeg2_decode_slice,
+ .end_frame = dxva2_mpeg2_end_frame,
+ .frame_priv_data_size = sizeof(struct dxva2_picture_context),
+};
diff --git a/libavcodec/dxva_template.c b/libavcodec/dxva_template.c
new file mode 100644
index 0000000..2504b3c
--- /dev/null
+++ b/libavcodec/dxva_template.c
@@ -0,0 +1,174 @@
+/*
+ * DXVA2 HW acceleration.
+ *
+ * copyright (c) 2010 Laurent Aimar
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "libavutil/log.h"
+#include "libavutil/time.h"
+
+#include "avcodec.h"
+#include "mpegvideo.h"
+#include "dxva_internal_template.h"
+
+void *ff_dxva2_get_surface(const AVFrame *frame)
+{
+ return frame->data[3];
+}
+
+unsigned ff_dxva2_get_surface_index(const struct dxva_context *ctx,
+ const AVFrame *frame)
+{
+ void *surface = ff_dxva2_get_surface(frame);
+ unsigned i;
+
+ for (i = 0; i < ctx->surface_count; i++)
+ if (ctx->surface[i] == surface)
+ return i;
+
+ assert(0);
+ return 0;
+}
+
+int ff_dxva2_commit_buffer(AVCodecContext *avctx,
+ struct dxva_context *ctx,
+ DXVA2_DecodeBufferDesc *dsc,
+ unsigned type, const void *data, unsigned size,
+ unsigned mb_count)
+{
+ void *dxva_data;
+ unsigned dxva_size;
+ int result;
+ HRESULT hr;
+
+ hr = IDirectXVideoDecoder_GetBuffer(ctx->decoder, type,
+ &dxva_data, &dxva_size);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %u: 0x%lx\n",
+ type, hr);
+ return -1;
+ }
+ if (size <= dxva_size) {
+ memcpy(dxva_data, data, size);
+
+ memset(dsc, 0, sizeof(*dsc));
+ dsc->CompressedBufferType = type;
+ dsc->DataSize = size;
+ dsc->NumMBsInBuffer = mb_count;
+
+ result = 0;
+ } else {
+ av_log(avctx, AV_LOG_ERROR, "Buffer for type %u was too small\n",
type);
+ result = -1;
+ }
+
+ hr = IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, type);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Failed to release buffer type %u: 0x%lx\n",
+ type, hr);
+ result = -1;
+ }
+ return result;
+}
+
+int ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame,
+ 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, runs = 0;
+ HRESULT hr;
+
+ do {
+ hr = IDirectXVideoDecoder_BeginFrame(ctx->decoder,
+ ff_dxva2_get_surface(frame),
+ NULL);
+ if (hr == E_PENDING)
+ av_usleep(2000);
+ } while (hr == E_PENDING && ++runs < 50);
+
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to begin frame: 0x%lx\n", hr);
+ 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;
+ hr = IDirectXVideoDecoder_Execute(ctx->decoder, &exec);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to execute: 0x%lx\n", hr);
+ result = -1;
+ }
+
+end:
+ hr = IDirectXVideoDecoder_EndFrame(ctx->decoder, NULL);
+ if (FAILED(hr)) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to end frame: 0x%lx\n", hr);
+ result = -1;
+ }
+
+ return result;
+}
diff --git a/libavcodec/dxva_vc1_template.c b/libavcodec/dxva_vc1_template.c
new file mode 100644
index 0000000..a2049ac
--- /dev/null
+++ b/libavcodec/dxva_vc1_template.c
@@ -0,0 +1,297 @@
+/*
+ * DXVA2 WMV3/VC-1 HW acceleration.
+ *
+ * copyright (c) 2010 Laurent Aimar
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "dxva_internal_template.h"
+#include "mpegutils.h"
+#include "vc1.h"
+#include "vc1data.h"
+
+struct dxva2_picture_context {
+ DXVA_PictureParameters pp;
+ DXVA_SliceInfo si;
+
+ const uint8_t *bitstream;
+ unsigned bitstream_size;
+};
+
+static void fill_picture_parameters(AVCodecContext *avctx,
+ struct dxva_context *ctx, const VC1Context
*v,
+ DXVA_PictureParameters *pp)
+{
+ const MpegEncContext *s = &v->s;
+ const Picture *current_picture = s->current_picture_ptr;
+
+ memset(pp, 0, sizeof(*pp));
+ pp->wDecodedPictureIndex =
+ pp->wDeblockedPictureIndex = ff_dxva2_get_surface_index(ctx,
current_picture->f);
+ if (s->pict_type != AV_PICTURE_TYPE_I && !v->bi_type)
+ pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx,
s->last_picture.f);
+ else
+ pp->wForwardRefPictureIndex = 0xffff;
+ if (s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type)
+ pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx,
s->next_picture.f);
+ else
+ pp->wBackwardRefPictureIndex = 0xffff;
+ if (v->profile == PROFILE_ADVANCED) {
+ /* It is the cropped width/height -1 of the frame */
+ pp->wPicWidthInMBminus1 = avctx->width - 1;
+ pp->wPicHeightInMBminus1= avctx->height - 1;
+ } else {
+ /* It is the coded width/height in macroblock -1 of the frame */
+ pp->wPicWidthInMBminus1 = s->mb_width - 1;
+ pp->wPicHeightInMBminus1= s->mb_height - 1;
+ }
+ pp->bMacroblockWidthMinus1 = 15;
+ pp->bMacroblockHeightMinus1 = 15;
+ pp->bBlockWidthMinus1 = 7;
+ pp->bBlockHeightMinus1 = 7;
+ pp->bBPPminus1 = 7;
+ if (s->picture_structure & PICT_TOP_FIELD)
+ pp->bPicStructure |= 0x01;
+ if (s->picture_structure & PICT_BOTTOM_FIELD)
+ pp->bPicStructure |= 0x02;
+ pp->bSecondField = v->interlace && v->fcm != ILACE_FIELD &&
!s->first_field;
+ pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I ||
v->bi_type;
+ pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B &&
!v->bi_type;
+ pp->bBidirectionalAveragingMode = (1
<< 7) |
+ ((ctx->cfg->ConfigIntraResidUnsigned !=
0) << 6) |
+ ((ctx->cfg->ConfigResidDiffAccelerator
!= 0) << 5) |
+ ((v->lumscale != 32 || v->lumshift != 0)
<< 4) |
+ ((v->profile == PROFILE_ADVANCED)
<< 3);
+ pp->bMVprecisionAndChromaRelation = ((v->mv_mode ==
MV_PMODE_1MV_HPEL_BILIN) << 3) |
+ (1
<< 2) |
+ (0
<< 1) |
+ (!s->quarter_sample
);
+ pp->bChromaFormat = v->chromaformat;
+ ctx->report_id++;
+ if (ctx->report_id >= (1 << 16))
+ ctx->report_id = 1;
+ pp->bPicScanFixed = ctx->report_id >> 8;
+ pp->bPicScanMethod = ctx->report_id & 0xff;
+ pp->bPicReadbackRequests = 0;
+ pp->bRcontrol = v->rnd;
+ pp->bPicSpatialResid8 = (v->panscanflag << 7) |
+ (v->refdist_flag << 6) |
+ (s->loop_filter << 5) |
+ (v->fastuvmc << 4) |
+ (v->extended_mv << 3) |
+ (v->dquant << 1) |
+ (v->vstransform );
+ pp->bPicOverflowBlocks = (v->quantizer_mode << 6) |
+ (v->multires << 5) |
+ (v->resync_marker << 4) |
+ (v->rangered << 3) |
+ (s->max_b_frames );
+ pp->bPicExtrapolation = (!v->interlace || v->fcm == PROGRESSIVE) ? 1
: 2;
+ pp->bPicDeblocked = ((!pp->bPicBackwardPrediction && v->overlap)
<< 6) |
+ ((v->profile != PROFILE_ADVANCED &&
v->rangeredfrm) << 5) |
+ (s->loop_filter
<< 1);
+ pp->bPicDeblockConfined = (v->postprocflag << 7) |
+ (v->broadcast << 6) |
+ (v->interlace << 5) |
+ (v->tfcntrflag << 4) |
+ (v->finterpflag << 3) |
+ ((s->pict_type != AV_PICTURE_TYPE_B) << 2) |
+ (v->psf << 1) |
+ (v->extended_dmv );
+ if (s->pict_type != AV_PICTURE_TYPE_I)
+ pp->bPic4MVallowed = v->mv_mode == MV_PMODE_MIXED_MV ||
+ (v->mv_mode == MV_PMODE_INTENSITY_COMP &&
+ v->mv_mode2 == MV_PMODE_MIXED_MV);
+ if (v->profile == PROFILE_ADVANCED)
+ pp->bPicOBMC = (v->range_mapy_flag << 7) |
+ (v->range_mapy << 4) |
+ (v->range_mapuv_flag << 3) |
+ (v->range_mapuv );
+ pp->bPicBinPB = 0;
+ pp->bMV_RPS = 0;
+ pp->bReservedBits = 0;
+ if (s->picture_structure == PICT_FRAME) {
+ pp->wBitstreamFcodes = v->lumscale;
+ pp->wBitstreamPCEelements = v->lumshift;
+ } else {
+ /* Syntax: (top_field_param << 8) | bottom_field_param */
+ pp->wBitstreamFcodes = (v->lumscale << 8) | v->lumscale;
+ pp->wBitstreamPCEelements = (v->lumshift << 8) | v->lumshift;
+ }
+ pp->bBitstreamConcealmentNeed = 0;
+ pp->bBitstreamConcealmentMethod = 0;
+}
+
+static void fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice,
+ unsigned position, unsigned size)
+{
+ const VC1Context *v = avctx->priv_data;
+ const MpegEncContext *s = &v->s;
+
+ memset(slice, 0, sizeof(*slice));
+ slice->wHorizontalPosition = 0;
+ slice->wVerticalPosition = s->mb_y;
+ slice->dwSliceBitsInBuffer = 8 * size;
+ slice->dwSliceDataLocation = position;
+ slice->bStartCodeBitOffset = 0;
+ slice->bReservedBits = 0;
+ slice->wMBbitOffset = get_bits_count(&s->gb);
+ slice->wNumberMBsInSlice = s->mb_width * s->mb_height; /* XXX We assume
1 slice */
+ slice->wQuantizerScaleCode = v->pq;
+ slice->wBadSliceChopping = 0;
+}
+
+static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
+ DXVA2_DecodeBufferDesc *bs,
+ DXVA2_DecodeBufferDesc *sc)
+{
+ const VC1Context *v = avctx->priv_data;
+ struct dxva_context *ctx = avctx->hwaccel_context;
+ const MpegEncContext *s = &v->s;
+ struct dxva2_picture_context *ctx_pic =
s->current_picture_ptr->hwaccel_picture_private;
+
+ DXVA_SliceInfo *slice = &ctx_pic->si;
+
+ static const uint8_t start_code[] = { 0, 0, 1, 0x0d };
+ const unsigned start_code_size = avctx->codec_id == AV_CODEC_ID_VC1 ?
sizeof(start_code) : 0;
+ const unsigned slice_size = slice->dwSliceBitsInBuffer / 8;
+ const unsigned padding = 128 - ((start_code_size + slice_size) & 127);
+ const unsigned data_size = start_code_size + slice_size + padding;
+
+ void *dxva_data_ptr;
+ uint8_t *dxva_data;
+ unsigned dxva_size;
+ int result;
+
+ if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder,
+ DXVA2_BitStreamDateBufferType,
+ &dxva_data_ptr, &dxva_size)))
+ return -1;
+
+ dxva_data = dxva_data_ptr;
+ result = data_size <= dxva_size ? 0 : -1;
+ if (!result) {
+ if (start_code_size > 0)
+ memcpy(dxva_data, start_code, start_code_size);
+ memcpy(dxva_data + start_code_size,
+ ctx_pic->bitstream + slice->dwSliceDataLocation, slice_size);
+ if (padding > 0)
+ memset(dxva_data + start_code_size + slice_size, 0, padding);
+ slice->dwSliceBitsInBuffer = 8 * data_size;
+ }
+ if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder,
+
DXVA2_BitStreamDateBufferType)))
+ return -1;
+ if (result)
+ return result;
+
+ memset(bs, 0, sizeof(*bs));
+ bs->CompressedBufferType = DXVA2_BitStreamDateBufferType;
+ bs->DataSize = data_size;
+ bs->NumMBsInBuffer = s->mb_width * s->mb_height;
+ assert((bs->DataSize & 127) == 0);
+
+ return ff_dxva2_commit_buffer(avctx, ctx, sc,
+ DXVA2_SliceControlBufferType,
+ slice, sizeof(*slice), bs->NumMBsInBuffer);
+}
+
+static int dxva2_vc1_start_frame(AVCodecContext *avctx,
+ av_unused const uint8_t *buffer,
+ av_unused uint32_t size)
+{
+ const VC1Context *v = avctx->priv_data;
+ struct dxva_context *ctx = avctx->hwaccel_context;
+ struct dxva2_picture_context *ctx_pic =
v->s.current_picture_ptr->hwaccel_picture_private;
+
+ if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
+ return -1;
+ assert(ctx_pic);
+
+ fill_picture_parameters(avctx, ctx, v, &ctx_pic->pp);
+
+ ctx_pic->bitstream_size = 0;
+ ctx_pic->bitstream = NULL;
+ return 0;
+}
+
+static int dxva2_vc1_decode_slice(AVCodecContext *avctx,
+ const uint8_t *buffer,
+ uint32_t size)
+{
+ const VC1Context *v = avctx->priv_data;
+ const Picture *current_picture = v->s.current_picture_ptr;
+ struct dxva2_picture_context *ctx_pic =
current_picture->hwaccel_picture_private;
+
+ if (ctx_pic->bitstream_size > 0)
+ return -1;
+
+ if (avctx->codec_id == AV_CODEC_ID_VC1 &&
+ size >= 4 && IS_MARKER(AV_RB32(buffer))) {
+ buffer += 4;
+ size -= 4;
+ }
+
+ ctx_pic->bitstream_size = size;
+ ctx_pic->bitstream = buffer;
+
+ fill_slice(avctx, &ctx_pic->si, 0, size);
+ return 0;
+}
+
+static int dxva2_vc1_end_frame(AVCodecContext *avctx)
+{
+ VC1Context *v = avctx->priv_data;
+ struct dxva2_picture_context *ctx_pic =
v->s.current_picture_ptr->hwaccel_picture_private;
+ int ret;
+
+ if (ctx_pic->bitstream_size <= 0)
+ return -1;
+
+ ret = ff_dxva2_common_end_frame(avctx, v->s.current_picture_ptr->f,
+ &ctx_pic->pp, sizeof(ctx_pic->pp),
+ NULL, 0,
+ commit_bitstream_and_slice_buffer);
+ if (!ret)
+ ff_mpeg_draw_horiz_band(&v->s, 0, avctx->height);
+ return ret;
+}
+
+#if CONFIG_WMV3_DXVA2_HWACCEL
+AVHWAccel ff_wmv3_dxva2_hwaccel = {
+ .name = "wmv3_dxva2",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_WMV3,
+ .pix_fmt = AV_PIX_FMT_DXVA2_VLD,
+ .start_frame = dxva2_vc1_start_frame,
+ .decode_slice = dxva2_vc1_decode_slice,
+ .end_frame = dxva2_vc1_end_frame,
+ .frame_priv_data_size = sizeof(struct dxva2_picture_context),
+};
+#endif
+
+AVHWAccel ff_vc1_dxva2_hwaccel = {
+ .name = "vc1_dxva2",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_VC1,
+ .pix_fmt = AV_PIX_FMT_DXVA2_VLD,
+ .start_frame = dxva2_vc1_start_frame,
+ .decode_slice = dxva2_vc1_decode_slice,
+ .end_frame = dxva2_vc1_end_frame,
+ .frame_priv_data_size = sizeof(struct dxva2_picture_context),
+};
--
2.4.0
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel