History

H264 DXVA2 implementation

It allows VLD H264 decoding using DXVA2 (GPU assisted decoding API under VISTA and Windows 7). It is implemented by using AVHWAccel API. It has been tested successfully for some time in VLC using an nvidia card on Windows 7. To compile it, you need to have the system header dxva2api.h (either from microsoft or using http://downloads.videolan.org/pub/videolan/testing/contrib/dxva2api.h) The generated libavcodec.dll does not depend directly on any new lib as the necessary objects are given by the application using FFmpeg. Originally committed as revision 21353 to svn://svn.ffmpeg.org/ffmpeg/trunk

Laurent Aimar committed 16 years ago

Commit 92c6a091 parent 3d7b42f8 files · +637 −1Browse files

Unified · Split

8 files
  1. configure +5 −0
  2. libavcodec/Makefile +2 −1
  3. libavcodec/allcodecs.c +1 −0
  4. libavcodec/dxva2.h +68 −0
  5. libavcodec/dxva2_h264.c +553 −0
  6. libavcodec/mpegvideo.c +1 −0
  7. libavutil/pixdesc.c +6 −0
  8. libavutil/pixfmt.h +1 −0
configure+5−0
@@ -107,6 +107,7 @@ Configuration options: · 106 unmodified lines
107 --disable-rdft disable RDFT code107 --disable-rdft disable RDFT code
108 --disable-vaapi disable VAAPI code108 --disable-vaapi disable VAAPI code
109 --disable-vdpau disable VDPAU code109 --disable-vdpau disable VDPAU code
110 --disable-dxva2 disable DXVA2 code
110 --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary)111 --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary)
111 --enable-hardcoded-tables use hardcoded tables instead of runtime generation112 --enable-hardcoded-tables use hardcoded tables instead of runtime generation
112 --enable-memalign-hack emulate memalign, interferes with memory debuggers113 --enable-memalign-hack emulate memalign, interferes with memory debuggers
@@ -865,6 +866,7 @@ CONFIG_LIST=" · 752 unmodified lines
865 bzlib866 bzlib
866 dct867 dct
867 doc868 doc
869 dxva2
868 fastdiv870 fastdiv
869 ffmpeg871 ffmpeg
870 ffplay872 ffplay
@@ -1174,6 +1176,8 @@ h263_vaapi_hwaccel_select="vaapi h263_decoder" · 303 unmodified lines
1174h263i_decoder_select="h263_decoder"1176h263i_decoder_select="h263_decoder"
1175h263p_encoder_select="h263_encoder"1177h263p_encoder_select="h263_encoder"
1176h264_decoder_select="golomb"1178h264_decoder_select="golomb"
1179h264_dxva2_hwaccel_deps="dxva2api_h"
1180h264_dxva2_hwaccel_select="dxva2 h264_decoder"
1177h264_vaapi_hwaccel_deps="va_va_h"1181h264_vaapi_hwaccel_deps="va_va_h"
1178h264_vaapi_hwaccel_select="vaapi"1182h264_vaapi_hwaccel_select="vaapi"
1179h264_vdpau_decoder_deps="vdpau_vdpau_h vdpau_vdpau_x11_h"1183h264_vdpau_decoder_deps="vdpau_vdpau_h vdpau_vdpau_x11_h"
@@ -2399,6 +2403,7 @@ check_func_headers windows.h VirtualAlloc · 1219 unmodified lines
2399 2403
2400check_header conio.h2404check_header conio.h
2401check_header dlfcn.h2405check_header dlfcn.h
2406check_header dxva2api.h
2402check_header malloc.h2407check_header malloc.h
2403check_header poll.h2408check_header poll.h
2404check_header sys/mman.h2409check_header sys/mman.h
libavcodec/Makefile+2−1
@@ -3,7 +3,7 @@ include $(SUBDIR)../config.mak · 2 unmodified lines
3NAME = avcodec3NAME = avcodec
4FFLIBS = avutil4FFLIBS = avutil
5 5
6HEADERS = avcodec.h opt.h vaapi.h vdpau.h xvmc.h6HEADERS = avcodec.h dxva2.h opt.h vaapi.h vdpau.h xvmc.h
7 7
8OBJS = allcodecs.o \8OBJS = allcodecs.o \
9 audioconvert.o \9 audioconvert.o \
@@ -135,6 +135,7 @@ OBJS-$(CONFIG_H263_ENCODER) += mpegvideo_enc.o mpeg4video.o mpeg4vide · 125 unmodified lines
135OBJS-$(CONFIG_H264_DECODER) += h264.o h264idct.o h264pred.o h264_loopfilter.o h264_direct.o cabac.o \135OBJS-$(CONFIG_H264_DECODER) += h264.o h264idct.o h264pred.o h264_loopfilter.o h264_direct.o cabac.o \
136 h264_sei.o h264_ps.o h264_refs.o h264_cavlc.o h264_cabac.o\136 h264_sei.o h264_ps.o h264_refs.o h264_cavlc.o h264_cabac.o\
137 mpegvideo.o error_resilience.o137 mpegvideo.o error_resilience.o
138OBJS-$(CONFIG_H264_DXVA2_HWACCEL) += dxva2_h264.o
138OBJS-$(CONFIG_H264_ENCODER) += h264enc.o h264dspenc.o139OBJS-$(CONFIG_H264_ENCODER) += h264enc.o h264dspenc.o
139OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o140OBJS-$(CONFIG_H264_VAAPI_HWACCEL) += vaapi_h264.o
140OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o141OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o
libavcodec/allcodecs.c+1−0
@@ -55,6 +55,7 @@ void avcodec_register_all(void) · 54 unmodified lines
55 55
56 /* hardware accelerators */56 /* hardware accelerators */
57 REGISTER_HWACCEL (H263_VAAPI, h263_vaapi);57 REGISTER_HWACCEL (H263_VAAPI, h263_vaapi);
58 REGISTER_HWACCEL (H264_DXVA2, h264_dxva2);
58 REGISTER_HWACCEL (H264_VAAPI, h264_vaapi);59 REGISTER_HWACCEL (H264_VAAPI, h264_vaapi);
59 REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi);60 REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi);
60 REGISTER_HWACCEL (MPEG4_VAAPI, mpeg4_vaapi);61 REGISTER_HWACCEL (MPEG4_VAAPI, mpeg4_vaapi);
libavcodec/dxva2.h+68−0
@@ -0,0 +1,68 @@
1/*
2 * DXVA2 HW acceleration
3 *
4 * copyright (c) 2009 Laurent Aimar
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#ifndef AVCODEC_DXVA_H
24#define AVCODEC_DXVA_H
25
26#include <stdint.h>
27
28#include <dxva2api.h>
29
30/**
31 * This structure is used to provides the necessary configurations and data
32 * to the DXVA2 FFmpeg HWAccel implementation.
33 *
34 * The application must make it available as AVCodecContext.hwaccel_context.
35 */
36struct dxva_context {
37 /**
38 * DXVA2 decoder object
39 */
40 IDirectXVideoDecoder *decoder;
41
42 /**
43 * DXVA2 configuration used to create the decoder
44 */
45 const DXVA2_ConfigPictureDecode *cfg;
46
47 /**
48 * The number of surface in the surface array
49 */
50 unsigned surface_count;
51
52 /**
53 * The array of Direct3D surfaces used to create the decoder
54 */
55 LPDIRECT3DSURFACE9 *surface;
56
57 /**
58 * A bit field configuring the workarounds needed for using the decoder
59 */
60 uint64_t workaround;
61
62 /**
63 * Private to the FFmpeg AVHWAccel implementation
64 */
65 unsigned report_id;
66};
67
68#endif /* AVCODEC_DXVA_H */
libavcodec/dxva2_h264.c+553−0
@@ -0,0 +1,553 @@
1/*
2 * DXVA2 H264 HW acceleration.
3 *
4 * copyright (c) 2009 Laurent Aimar
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include "dxva2.h"
24#include "avcodec.h"
25
26#include "mpegvideo.h"
27#include "h264.h"
28#include "h264data.h"
29
30struct dxva2_picture_context {
31 DXVA_PicParams_H264 pp;
32 DXVA_Qmatrix_H264 qm;
33 unsigned slice_count;
34 DXVA_Slice_H264_Short slice_short[MAX_SLICES];
35 DXVA_Slice_H264_Long slice_long[MAX_SLICES];
36 const uint8_t *bitstream;
37 unsigned bitstream_size;
38};
39
40static void *get_surface(const Picture *picture)
41{
42 return picture->data[3];
43}
44static unsigned get_surface_index(const struct dxva_context *ctx,
45 const Picture *picture)
46{
47 void *surface = get_surface(picture);
48 unsigned i;
49
50 for (i = 0; i < ctx->surface_count; i++)
51 if (ctx->surface[i] == surface)
52 return i;
53
54 assert(0);
55 return 0;
56}
57
58static void fill_picture_entry(DXVA_PicEntry_H264 *pic,
59 unsigned index, unsigned flag)
60{
61 assert((index&0x7f) == index && (flag&0x01) == flag);
62 pic->bPicEntry = index | (flag << 7);
63}
64
65static void fill_picture_parameters(struct dxva_context *ctx, const H264Context *h,
66 DXVA_PicParams_H264 *pp)
67{
68 const MpegEncContext *s = &h->s;
69 const Picture *current_picture = s->current_picture_ptr;
70 int i;
71
72 memset(pp, 0, sizeof(*pp));
73 /* Configure current picture */
74 fill_picture_entry(&pp->CurrPic,
75 get_surface_index(ctx, current_picture),
76 s->picture_structure == PICT_BOTTOM_FIELD);
77 /* Configure the set of references */
78 pp->UsedForReferenceFlags = 0;
79 pp->NonExistingFrameFlags = 0;
80 for (i = 0; i < FF_ARRAY_ELEMS(pp->RefFrameList); i++) {
81 if (i < h->short_ref_count + h->long_ref_count) {
82 const Picture *r;
83 if (i < h->short_ref_count) {
84 r = h->short_ref[i];
85 assert(!r->long_ref);
86 } else {
87 r = h->long_ref[i - h->short_ref_count];
88 assert(r->long_ref);
89 }
90 fill_picture_entry(&pp->RefFrameList[i],
91 get_surface_index(ctx, r),
92 r->long_ref != 0);
93
94 if ((r->reference & PICT_TOP_FIELD) && r->field_poc[0] != INT_MAX)
95 pp->FieldOrderCntList[i][0] = r->field_poc[0];
96 if ((r->reference & PICT_BOTTOM_FIELD) && r->field_poc[1] != INT_MAX)
97 pp->FieldOrderCntList[i][1] = r->field_poc[1];
98
99 pp->FrameNumList[i] = r->long_ref ? r->pic_id : r->frame_num;
100 if (r->reference & PICT_TOP_FIELD)
101 pp->UsedForReferenceFlags |= 1 << (2*i + 0);
102 if (r->reference & PICT_BOTTOM_FIELD)
103 pp->UsedForReferenceFlags |= 1 << (2*i + 1);
104 } else {
105 pp->RefFrameList[i].bPicEntry = 0xff;
106 pp->FieldOrderCntList[i][0] = 0;
107 pp->FieldOrderCntList[i][1] = 0;
108 pp->FrameNumList[i] = 0;
109 }
110 }
111
112 pp->wFrameWidthInMbsMinus1 = s->mb_width - 1;
113 pp->wFrameHeightInMbsMinus1 = s->mb_height - 1;
114 pp->num_ref_frames = h->sps.ref_frame_count;
115
116 pp->wBitFields = ((s->picture_structure != PICT_FRAME) << 0) |
117 (h->sps.mb_aff << 1) |
118 (h->sps.residual_color_transform_flag << 2) |
119 /* sp_for_switch_flag (not implemented by FFmpeg) */
120 (0 << 3) |
121 (h->sps.chroma_format_idc << 4) |
122 ((h->nal_ref_idc != 0) << 6) |
123 (h->pps.constrained_intra_pred << 7) |
124 (h->pps.weighted_pred << 8) |
125 (h->pps.weighted_bipred_idc << 9) |
126 /* MbsConsecutiveFlag */
127 (1 << 11) |
128 (h->sps.frame_mbs_only_flag << 12) |
129 (h->pps.transform_8x8_mode << 13) |
130 ((h->sps.level_idc >= 31) << 14) |
131 /* IntraPicFlag (Modified if we detect a non
132 * intra slice in decode_slice) */
133 (1 << 15);
134
135 pp->bit_depth_luma_minus8 = h->sps.bit_depth_luma - 8;
136 pp->bit_depth_chroma_minus8 = h->sps.bit_depth_chroma - 8;
137 pp->Reserved16Bits = 3; /* FIXME is there a way to detect the right mode ? */
138 pp->StatusReportFeedbackNumber = 1 + ctx->report_id++;
139 pp->CurrFieldOrderCnt[0] = 0;
140 if ((s->picture_structure & PICT_TOP_FIELD) &&
141 current_picture->field_poc[0] != INT_MAX)
142 pp->CurrFieldOrderCnt[0] = current_picture->field_poc[0];
143 pp->CurrFieldOrderCnt[1] = 0;
144 if ((s->picture_structure & PICT_BOTTOM_FIELD) &&
145 current_picture->field_poc[1] != INT_MAX)
146 pp->CurrFieldOrderCnt[1] = current_picture->field_poc[1];
147 pp->pic_init_qs_minus26 = h->pps.init_qs - 26;
148 pp->chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0];
149 pp->second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1];
150 pp->ContinuationFlag = 1;
151 pp->pic_init_qp_minus26 = h->pps.init_qp - 26;
152 pp->num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1;
153 pp->num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1;
154 pp->Reserved8BitsA = 0;
155 pp->frame_num = h->frame_num;
156 pp->log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4;
157 pp->pic_order_cnt_type = h->sps.poc_type;
158 if (h->sps.poc_type == 0)
159 pp->log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4;
160 else if (h->sps.poc_type == 1)
161 pp->delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag;
162 pp->direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag;
163 pp->entropy_coding_mode_flag = h->pps.cabac;
164 pp->pic_order_present_flag = h->pps.pic_order_present;
165 pp->num_slice_groups_minus1 = h->pps.slice_group_count - 1;
166 pp->slice_group_map_type = h->pps.mb_slice_group_map_type;
167 pp->deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
168 pp->redundant_pic_cnt_present_flag= h->pps.redundant_pic_cnt_present;
169 pp->Reserved8BitsB = 0;
170 pp->slice_group_change_rate_minus1= 0; /* XXX not implemented by FFmpeg */
171 //pp->SliceGroupMap[810]; /* XXX not implemented by FFmpeg */
172}
173
174static void fill_scaling_lists(const H264Context *h, DXVA_Qmatrix_H264 *qm)
175{
176 unsigned i, j;
177 memset(qm, 0, sizeof(*qm));
178 for (i = 0; i < 6; i++)
179 for (j = 0; j < 16; j++)
180 qm->bScalingLists4x4[i][j] = h->pps.scaling_matrix4[i][zigzag_scan[j]];
181
182 for (i = 0; i < 2; i++)
183 for (j = 0; j < 64; j++)
184 qm->bScalingLists8x8[i][j] = h->pps.scaling_matrix8[i][ff_zigzag_direct[j]];
185}
186
187static int is_slice_short(struct dxva_context *ctx)
188{
189 assert(ctx->cfg->ConfigBitstreamRaw == 1 ||
190 ctx->cfg->ConfigBitstreamRaw == 2);
191 return ctx->cfg->ConfigBitstreamRaw == 2;
192}
193
194static void fill_slice_short(DXVA_Slice_H264_Short *slice,
195 unsigned position, unsigned size)
196{
197 memset(slice, 0, sizeof(*slice));
198 slice->BSNALunitDataLocation = position;
199 slice->SliceBytesInBuffer = size;
200 slice->wBadSliceChopping = 0;
201}
202
203static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice,
204 unsigned position, unsigned size)
205{
206 H264Context *h = avctx->priv_data; /* FIXME Can't use const because of get_bits_count */
207 struct dxva_context *ctx = avctx->hwaccel_context;
208 MpegEncContext *s = &h->s;
209 unsigned list;
210
211 memset(slice, 0, sizeof(*slice));
212 slice->BSNALunitDataLocation = position;
213 slice->SliceBytesInBuffer = size;
214 slice->wBadSliceChopping = 0;
215
216 slice->first_mb_in_slice = (s->mb_y >> FIELD_OR_MBAFF_PICTURE) * s->mb_width + s->mb_x;
217 slice->NumMbsForSlice = 0; /* XXX it is set once we have all slices */
218 slice->BitOffsetToSliceData = get_bits_count(&s->gb) + 8;
219 slice->slice_type = ff_h264_get_slice_type(h);
220 if (h->slice_type_fixed)
221 slice->slice_type += 5;
222 slice->luma_log2_weight_denom = h->luma_log2_weight_denom;
223 slice->chroma_log2_weight_denom = h->chroma_log2_weight_denom;
224 if (h->list_count > 0)
225 slice->num_ref_idx_l0_active_minus1 = h->ref_count[0] - 1;
226 if (h->list_count > 1)
227 slice->num_ref_idx_l1_active_minus1 = h->ref_count[1] - 1;
228 slice->slice_alpha_c0_offset_div2 = h->slice_alpha_c0_offset / 2;
229 slice->slice_beta_offset_div2 = h->slice_beta_offset / 2;
230 slice->Reserved8Bits = 0;
231
232 for (list = 0; list < 2; list++) {
233 unsigned i;
234 for (i = 0; i < FF_ARRAY_ELEMS(slice->RefPicList[list]); i++) {
235 if (list < h->list_count && i < h->ref_count[list]) {
236 const Picture *r = &h->ref_list[list][i];
237 unsigned plane;
238 fill_picture_entry(&slice->RefPicList[list][i],
239 get_surface_index(ctx, r),
240 r->reference == PICT_BOTTOM_FIELD);
241 for (plane = 0; plane < 3; plane++) {
242 int w, o;
243 if (plane == 0 && h->luma_weight_flag[list]) {
244 w = h->luma_weight[list][i];
245 o = h->luma_offset[list][i];
246 } else if (plane >= 1 && h->chroma_weight_flag[list]) {
247 w = h->chroma_weight[list][i][plane-1];
248 o = h->chroma_offset[list][i][plane-1];
249 } else {
250 w = 1 << (plane == 0 ? h->luma_log2_weight_denom :
251 h->chroma_log2_weight_denom);
252 o = 0;
253 }
254 slice->Weights[list][i][plane][0] = w;
255 slice->Weights[list][i][plane][1] = o;
256 }
257 } else {
258 unsigned plane;
259 slice->RefPicList[list][i].bPicEntry = 0xff;
260 for (plane = 0; plane < 3; plane++) {
261 slice->Weights[list][i][plane][0] = 0;
262 slice->Weights[list][i][plane][1] = 0;
263 }
264 }
265 }
266 }
267 slice->slice_qs_delta = 0; /* XXX not implemented by FFmpeg */
268 slice->slice_qp_delta = s->qscale - h->pps.init_qp;
269 slice->redundant_pic_cnt = h->redundant_pic_count;
270 if (h->slice_type == FF_B_TYPE)
271 slice->direct_spatial_mv_pred_flag = h->direct_spatial_mv_pred;
272 slice->cabac_init_idc = h->pps.cabac ? h->cabac_init_idc : 0;
273 if (h->deblocking_filter < 2)
274 slice->disable_deblocking_filter_idc = 1 - h->deblocking_filter;
275 else
276 slice->disable_deblocking_filter_idc = h->deblocking_filter;
277 slice->slice_id = h->current_slice - 1;
278}
279
280static int commit_buffer(AVCodecContext *avctx,
281 struct dxva_context *ctx,
282 DXVA2_DecodeBufferDesc *dsc,
283 unsigned type, const void *data, unsigned size,
284 unsigned mb_count)
285{
286 void *dxva_data;
287 unsigned dxva_size;
288 int result;
289
290 if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, type,
291 &dxva_data, &dxva_size))) {
292 av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %d\n", type);
293 return -1;
294 }
295 if (size <= dxva_size) {
296 memcpy(dxva_data, data, size);
297
298 memset(dsc, 0, sizeof(*dsc));
299 dsc->CompressedBufferType = type;
300 dsc->DataSize = size;
301 dsc->NumMBsInBuffer = mb_count;
302
303 result = 0;
304 } else {
305 av_log(avctx, AV_LOG_ERROR, "Buffer for type %d was too small\n", type);
306 result = -1;
307 }
308 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, type))) {
309 av_log(avctx, AV_LOG_ERROR, "Failed to release buffer type %d\n", type);
310 result = -1;
311 }
312 return result;
313}
314
315static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
316 struct dxva_context *ctx,
317 struct dxva2_picture_context *ctx_pic,
318 DXVA2_DecodeBufferDesc *bs,
319 DXVA2_DecodeBufferDesc *sc,
320 unsigned mb_count)
321{
322 DXVA_Slice_H264_Short *slice = NULL;
323 uint8_t *dxva_data, *current, *end;
324 unsigned dxva_size;
325 void *slice_data;
326 unsigned slice_size;
327 unsigned padding;
328 unsigned i;
329
330 /* Create an annex B bitstream buffer with only slice NAL and finalize slice */
331 if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder,
332 DXVA2_BitStreamDateBufferType,
333 &dxva_data, &dxva_size)))
334 return -1;
335 current = dxva_data;
336 end = dxva_data + dxva_size;
337
338 for (i = 0; i < ctx_pic->slice_count; i++) {
339 static const uint8_t start_code[] = { 0, 0, 1 };
340 static const unsigned start_code_size = sizeof(start_code);
341 unsigned position, size;
342
343 assert(offsetof(DXVA_Slice_H264_Short, BSNALunitDataLocation) ==
344 offsetof(DXVA_Slice_H264_Long, BSNALunitDataLocation));
345 assert(offsetof(DXVA_Slice_H264_Short, SliceBytesInBuffer) ==
346 offsetof(DXVA_Slice_H264_Long, SliceBytesInBuffer));
347
348 if (is_slice_short(ctx))
349 slice = &ctx_pic->slice_short[i];
350 else
351 slice = (DXVA_Slice_H264_Short*)&ctx_pic->slice_long[i];
352
353 position = slice->BSNALunitDataLocation;
354 size = slice->SliceBytesInBuffer;
355 if (start_code_size + size > end - current) {
356 av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream");
357 break;
358 }
359
360 slice->BSNALunitDataLocation = current - dxva_data;
361 slice->SliceBytesInBuffer = start_code_size + size;
362
363 if (!is_slice_short(ctx)) {
364 DXVA_Slice_H264_Long *slice_long = (DXVA_Slice_H264_Long*)slice;
365 if (i < ctx_pic->slice_count - 1)
366 slice_long->NumMbsForSlice =
367 slice_long[1].first_mb_in_slice - slice_long[0].first_mb_in_slice;
368 else
369 slice_long->NumMbsForSlice = mb_count - slice_long->first_mb_in_slice;
370 }
371
372 memcpy(current, start_code, start_code_size);
373 current += start_code_size;
374
375 memcpy(current, &ctx_pic->bitstream[position], size);
376 current += size;
377 }
378 padding = FFMIN(128 - ((current - dxva_data) & 127), end - current);
379 if (slice && padding > 0) {
380 memset(current, 0, padding);
381 current += padding;
382
383 slice->SliceBytesInBuffer += padding;
384 }
385 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder,
386 DXVA2_BitStreamDateBufferType)))
387 return -1;
388 if (i < ctx_pic->slice_count)
389 return -1;
390
391 memset(bs, 0, sizeof(*bs));
392 bs->CompressedBufferType = DXVA2_BitStreamDateBufferType;
393 bs->DataSize = current - dxva_data;
394 bs->NumMBsInBuffer = mb_count;
395
396 if (is_slice_short(ctx)) {
397 slice_data = ctx_pic->slice_short;
398 slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_short);
399 } else {
400 slice_data = ctx_pic->slice_long;
401 slice_size = ctx_pic->slice_count * sizeof(*ctx_pic->slice_long);
402 }
403 assert((bs->DataSize & 127) == 0);
404 return commit_buffer(avctx, ctx, sc,
405 DXVA2_SliceControlBufferType,
406 slice_data, slice_size, mb_count);
407}
408
409
410static int start_frame(AVCodecContext *avctx,
411 av_unused const uint8_t *buffer,
412 av_unused uint32_t size)
413{
414 const H264Context *h = avctx->priv_data;
415 struct dxva_context *ctx = avctx->hwaccel_context;
416 struct dxva2_picture_context *ctx_pic = h->s.current_picture_ptr->hwaccel_picture_private;
417
418 if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
419 return -1;
420 assert(ctx_pic);
421
422 /* Fill up DXVA_PicParams_H264 */
423 fill_picture_parameters(ctx, h, &ctx_pic->pp);
424
425 /* Fill up DXVA_Qmatrix_H264 */
426 fill_scaling_lists(h, &ctx_pic->qm);
427
428 ctx_pic->slice_count = 0;
429 ctx_pic->bitstream_size = 0;
430 ctx_pic->bitstream = NULL;
431 return 0;
432}
433
434static int decode_slice(AVCodecContext *avctx,
435 const uint8_t *buffer, uint32_t size)
436{
437 H264Context *h = avctx->priv_data; /* FIXME Can't use const because of get_bits_count */
438 struct dxva_context *ctx = avctx->hwaccel_context;
439 const Picture *current_picture = h->s.current_picture_ptr;
440 struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
441 unsigned position;
442
443 if (ctx_pic->slice_count >= MAX_SLICES)
444 return -1;
445
446 if (!ctx_pic->bitstream)
447 ctx_pic->bitstream = buffer;
448 ctx_pic->bitstream_size += size;
449
450 position = buffer - ctx_pic->bitstream;
451 if (is_slice_short(ctx))
452 fill_slice_short(&ctx_pic->slice_short[ctx_pic->slice_count],
453 position, size);
454 else
455 fill_slice_long(avctx, &ctx_pic->slice_long[ctx_pic->slice_count],
456 position, size);
457 ctx_pic->slice_count++;
458
459 if (h->slice_type != FF_I_TYPE && h->slice_type != FF_SI_TYPE)
460 ctx_pic->pp.wBitFields &= ~(1 << 15); /* Set IntraPicFlag to 0 */
461 return 0;
462}
463
464static int end_frame(AVCodecContext *avctx)
465{
466 H264Context *h = avctx->priv_data;
467 MpegEncContext *s = &h->s;
468 const unsigned mb_count = s->mb_width * s->mb_height;
469 struct dxva_context *ctx = avctx->hwaccel_context;
470 const Picture *current_picture = h->s.current_picture_ptr;
471 struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
472 unsigned buffer_count = 0;
473 DXVA2_DecodeBufferDesc buffer[4];
474 DXVA2_DecodeExecuteParams exec;
475 int result;
476
477 if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
478 return -1;
479
480 if (FAILED(IDirectXVideoDecoder_BeginFrame(ctx->decoder,
481 get_surface(current_picture),
482 NULL))) {
483 av_log(avctx, AV_LOG_ERROR, "Failed to begin frame\n");
484 return -1;
485 }
486
487 result = commit_buffer(avctx, ctx, &buffer[buffer_count],
488 DXVA2_PictureParametersBufferType,
489 &ctx_pic->pp, sizeof(ctx_pic->pp), 0);
490 if (result) {
491 av_log(avctx, AV_LOG_ERROR,
492 "Failed to add picture parameter buffer\n");
493 goto end;
494 }
495 buffer_count++;
496
497 result = commit_buffer(avctx, ctx, &buffer[buffer_count],
498 DXVA2_InverseQuantizationMatrixBufferType,
499 &ctx_pic->qm, sizeof(ctx_pic->qm), 0);
500 if (result) {
501 av_log(avctx, AV_LOG_ERROR,
502 "Failed to add inverse quantization matrix buffer\n");
503 goto end;
504 }
505 buffer_count++;
506
507 result = commit_bitstream_and_slice_buffer(avctx, ctx, ctx_pic,
508 &buffer[buffer_count + 0],
509 &buffer[buffer_count + 1],
510 mb_count);
511 if (result) {
512 av_log(avctx, AV_LOG_ERROR,
513 "Failed to add bitstream or slice control buffer\n");
514 goto end;
515 }
516 buffer_count += 2;
517
518 /* TODO Film Grain when possible */
519
520 assert(buffer_count == 4);
521
522 memset(&exec, 0, sizeof(exec));
523 exec.NumCompBuffers = buffer_count;
524 exec.pCompressedBuffers = buffer;
525 exec.pExtensionData = NULL;
526 if (FAILED(IDirectXVideoDecoder_Execute(ctx->decoder, &exec))) {
527 av_log(avctx, AV_LOG_ERROR, "Failed to execute\n");
528 result = -1;
529 }
530
531end:
532 if (FAILED(IDirectXVideoDecoder_EndFrame(ctx->decoder, NULL))) {
533 av_log(avctx, AV_LOG_ERROR, "Failed to end frame\n");
534 result = -1;
535 }
536
537 if (!result)
538 ff_draw_horiz_band(s, 0, s->avctx->height);
539 return result;
540}
541
542AVHWAccel h264_dxva2_hwaccel = {
543 .name = "h264_dxva2",
544 .type = CODEC_TYPE_VIDEO,
545 .id = CODEC_ID_H264,
546 .pix_fmt = PIX_FMT_DXVA2_VLD,
547 .capabilities = 0,
548 .start_frame = start_frame,
549 .decode_slice = decode_slice,
550 .end_frame = end_frame,
551 .priv_data_size = sizeof(struct dxva2_picture_context),
552};
553
libavcodec/mpegvideo.c+1−0
@@ -81,6 +81,7 @@ const enum PixelFormat ff_pixfmt_list_420[] = { · 80 unmodified lines
81};81};
82 82
83const enum PixelFormat ff_hwaccel_pixfmt_list_420[] = {83const enum PixelFormat ff_hwaccel_pixfmt_list_420[] = {
84 PIX_FMT_DXVA2_VLD,
84 PIX_FMT_VAAPI_VLD,85 PIX_FMT_VAAPI_VLD,
85 PIX_FMT_YUV420P,86 PIX_FMT_YUV420P,
86 PIX_FMT_NONE87 PIX_FMT_NONE
libavutil/pixdesc.c+6−0
@@ -646,6 +646,12 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[PIX_FMT_NB] = { · 645 unmodified lines
646 },646 },
647 .flags = PIX_FMT_BE,647 .flags = PIX_FMT_BE,
648 },648 },
649 [PIX_FMT_DXVA2_VLD] = {
650 .name = "dxva2_vld",
651 .log2_chroma_w = 1,
652 .log2_chroma_h = 1,
653 .flags = PIX_FMT_HWACCEL,
654 },
649};655};
650 656
651int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc)657int av_get_bits_per_pixel(const AVPixFmtDescriptor *pixdesc)
libavutil/pixfmt.h+1−0
@@ -126,6 +126,7 @@ enum PixelFormat { · 125 unmodified lines
126 PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian126 PIX_FMT_YUV444P16LE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
127 PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian127 PIX_FMT_YUV444P16BE, ///< planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), big-endian
128 PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers128 PIX_FMT_VDPAU_MPEG4, ///< MPEG4 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
129 PIX_FMT_DXVA2_VLD, ///< HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer
129 PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions130 PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
130};131};
131 132

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t