2 * DXVA2 WMV3/VC-1 HW acceleration.
4 * copyright (c) 2010 Laurent Aimar
6 * This file is part of FFmpeg.
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.
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.
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
23 #include "dxva2_internal.h"
24 #include "mpegutils.h"
28 struct dxva2_picture_context
{
29 DXVA_PictureParameters pp
;
32 const uint8_t *bitstream
;
33 unsigned bitstream_size
;
36 static void fill_picture_parameters(AVCodecContext
*avctx
,
37 struct dxva_context
*ctx
, const VC1Context
*v
,
38 DXVA_PictureParameters
*pp
)
40 const MpegEncContext
*s
= &v
->s
;
41 const Picture
*current_picture
= s
->current_picture_ptr
;
44 // determine if intensity compensation is needed
45 if (s
->pict_type
== AV_PICTURE_TYPE_P
) {
46 if ((v
->fcm
== ILACE_FRAME
&& v
->intcomp
) || (v
->fcm
!= ILACE_FRAME
&& v
->mv_mode
== MV_PMODE_INTENSITY_COMP
)) {
47 if (v
->lumscale
!= 32 || v
->lumshift
!= 0 || (s
->picture_structure
!= PICT_FRAME
&& (v
->lumscale2
!= 32 || v
->lumshift2
!= 0)))
52 memset(pp
, 0, sizeof(*pp
));
53 pp
->wDecodedPictureIndex
=
54 pp
->wDeblockedPictureIndex
= ff_dxva2_get_surface_index(ctx
, current_picture
->f
);
55 if (s
->pict_type
!= AV_PICTURE_TYPE_I
&& !v
->bi_type
)
56 pp
->wForwardRefPictureIndex
= ff_dxva2_get_surface_index(ctx
, s
->last_picture
.f
);
58 pp
->wForwardRefPictureIndex
= 0xffff;
59 if (s
->pict_type
== AV_PICTURE_TYPE_B
&& !v
->bi_type
)
60 pp
->wBackwardRefPictureIndex
= ff_dxva2_get_surface_index(ctx
, s
->next_picture
.f
);
62 pp
->wBackwardRefPictureIndex
= 0xffff;
63 if (v
->profile
== PROFILE_ADVANCED
) {
64 /* It is the cropped width/height -1 of the frame */
65 pp
->wPicWidthInMBminus1
= avctx
->width
- 1;
66 pp
->wPicHeightInMBminus1
= avctx
->height
- 1;
68 /* It is the coded width/height in macroblock -1 of the frame */
69 pp
->wPicWidthInMBminus1
= s
->mb_width
- 1;
70 pp
->wPicHeightInMBminus1
= s
->mb_height
- 1;
72 pp
->bMacroblockWidthMinus1
= 15;
73 pp
->bMacroblockHeightMinus1
= 15;
74 pp
->bBlockWidthMinus1
= 7;
75 pp
->bBlockHeightMinus1
= 7;
77 if (s
->picture_structure
& PICT_TOP_FIELD
)
78 pp
->bPicStructure
|= 0x01;
79 if (s
->picture_structure
& PICT_BOTTOM_FIELD
)
80 pp
->bPicStructure
|= 0x02;
81 pp
->bSecondField
= v
->interlace
&& v
->fcm
== ILACE_FIELD
&& v
->second_field
;
82 pp
->bPicIntra
= s
->pict_type
== AV_PICTURE_TYPE_I
|| v
->bi_type
;
83 pp
->bPicBackwardPrediction
= s
->pict_type
== AV_PICTURE_TYPE_B
&& !v
->bi_type
;
84 pp
->bBidirectionalAveragingMode
= (1 << 7) |
85 ((ctx
->cfg
->ConfigIntraResidUnsigned
!= 0) << 6) |
86 ((ctx
->cfg
->ConfigResidDiffAccelerator
!= 0) << 5) |
88 ((v
->profile
== PROFILE_ADVANCED
) << 3);
89 pp
->bMVprecisionAndChromaRelation
= ((v
->mv_mode
== MV_PMODE_1MV_HPEL_BILIN
) << 3) |
92 (!s
->quarter_sample
);
93 pp
->bChromaFormat
= v
->chromaformat
;
95 if (ctx
->report_id
>= (1 << 16))
97 pp
->bPicScanFixed
= ctx
->report_id
>> 8;
98 pp
->bPicScanMethod
= ctx
->report_id
& 0xff;
99 pp
->bPicReadbackRequests
= 0;
100 pp
->bRcontrol
= v
->rnd
;
101 pp
->bPicSpatialResid8
= (v
->panscanflag
<< 7) |
102 (v
->refdist_flag
<< 6) |
103 (s
->loop_filter
<< 5) |
105 (v
->extended_mv
<< 3) |
108 pp
->bPicOverflowBlocks
= (v
->quantizer_mode
<< 6) |
110 (v
->resync_marker
<< 4) |
113 pp
->bPicExtrapolation
= (!v
->interlace
|| v
->fcm
== PROGRESSIVE
) ? 1 : 2;
114 pp
->bPicDeblocked
= ((!pp
->bPicBackwardPrediction
&& v
->overlap
) << 6) |
115 ((v
->profile
!= PROFILE_ADVANCED
&& v
->rangeredfrm
) << 5) |
116 (s
->loop_filter
<< 1);
117 pp
->bPicDeblockConfined
= (v
->postprocflag
<< 7) |
118 (v
->broadcast
<< 6) |
119 (v
->interlace
<< 5) |
120 (v
->tfcntrflag
<< 4) |
121 (v
->finterpflag
<< 3) |
122 ((s
->pict_type
!= AV_PICTURE_TYPE_B
) << 2) |
125 if (s
->pict_type
!= AV_PICTURE_TYPE_I
)
126 pp
->bPic4MVallowed
= v
->mv_mode
== MV_PMODE_MIXED_MV
||
127 (v
->mv_mode
== MV_PMODE_INTENSITY_COMP
&&
128 v
->mv_mode2
== MV_PMODE_MIXED_MV
);
129 if (v
->profile
== PROFILE_ADVANCED
)
130 pp
->bPicOBMC
= (v
->range_mapy_flag
<< 7) |
131 (v
->range_mapy
<< 4) |
132 (v
->range_mapuv_flag
<< 3) |
135 pp
->bMV_RPS
= (v
->fcm
== ILACE_FIELD
&& pp
->bPicBackwardPrediction
) ? v
->refdist
+ 9 : 0;
136 pp
->bReservedBits
= v
->pq
;
137 if (s
->picture_structure
== PICT_FRAME
) {
139 pp
->wBitstreamFcodes
= v
->lumscale
;
140 pp
->wBitstreamPCEelements
= v
->lumshift
;
142 pp
->wBitstreamFcodes
= 32;
143 pp
->wBitstreamPCEelements
= 0;
146 /* Syntax: (top_field_param << 8) | bottom_field_param */
148 pp
->wBitstreamFcodes
= (v
->lumscale
<< 8) | v
->lumscale2
;
149 pp
->wBitstreamPCEelements
= (v
->lumshift
<< 8) | v
->lumshift2
;
151 pp
->wBitstreamFcodes
= (32 << 8) | 32;
152 pp
->wBitstreamPCEelements
= 0;
155 pp
->bBitstreamConcealmentNeed
= 0;
156 pp
->bBitstreamConcealmentMethod
= 0;
159 static void fill_slice(AVCodecContext
*avctx
, DXVA_SliceInfo
*slice
,
160 unsigned position
, unsigned size
)
162 const VC1Context
*v
= avctx
->priv_data
;
163 const MpegEncContext
*s
= &v
->s
;
165 memset(slice
, 0, sizeof(*slice
));
166 slice
->wHorizontalPosition
= 0;
167 slice
->wVerticalPosition
= s
->mb_y
;
168 slice
->dwSliceBitsInBuffer
= 8 * size
;
169 slice
->dwSliceDataLocation
= position
;
170 slice
->bStartCodeBitOffset
= 0;
171 slice
->bReservedBits
= (s
->pict_type
== AV_PICTURE_TYPE_B
&& !v
->bi_type
) ? v
->bfraction_lut_index
+ 9 : 0;
172 slice
->wMBbitOffset
= v
->p_frame_skipped
? 0xffff : get_bits_count(&s
->gb
) + (avctx
->codec_id
== AV_CODEC_ID_VC1
? 32 : 0);
173 slice
->wNumberMBsInSlice
= s
->mb_width
* s
->mb_height
; /* XXX We assume 1 slice */
174 slice
->wQuantizerScaleCode
= v
->pq
;
175 slice
->wBadSliceChopping
= 0;
178 static int commit_bitstream_and_slice_buffer(AVCodecContext
*avctx
,
179 DXVA2_DecodeBufferDesc
*bs
,
180 DXVA2_DecodeBufferDesc
*sc
)
182 const VC1Context
*v
= avctx
->priv_data
;
183 struct dxva_context
*ctx
= avctx
->hwaccel_context
;
184 const MpegEncContext
*s
= &v
->s
;
185 struct dxva2_picture_context
*ctx_pic
= s
->current_picture_ptr
->hwaccel_picture_private
;
187 DXVA_SliceInfo
*slice
= &ctx_pic
->si
;
189 static const uint8_t start_code
[] = { 0, 0, 1, 0x0d };
190 const unsigned start_code_size
= avctx
->codec_id
== AV_CODEC_ID_VC1
? sizeof(start_code
) : 0;
191 const unsigned slice_size
= slice
->dwSliceBitsInBuffer
/ 8;
192 const unsigned padding
= 128 - ((start_code_size
+ slice_size
) & 127);
193 const unsigned data_size
= start_code_size
+ slice_size
+ padding
;
200 if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx
->decoder
,
201 DXVA2_BitStreamDateBufferType
,
202 &dxva_data_ptr
, &dxva_size
)))
205 dxva_data
= dxva_data_ptr
;
206 result
= data_size
<= dxva_size
? 0 : -1;
208 if (start_code_size
> 0) {
209 memcpy(dxva_data
, start_code
, start_code_size
);
213 memcpy(dxva_data
+ start_code_size
,
214 ctx_pic
->bitstream
+ slice
->dwSliceDataLocation
, slice_size
);
216 memset(dxva_data
+ start_code_size
+ slice_size
, 0, padding
);
217 slice
->dwSliceBitsInBuffer
= 8 * data_size
;
219 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx
->decoder
,
220 DXVA2_BitStreamDateBufferType
)))
225 memset(bs
, 0, sizeof(*bs
));
226 bs
->CompressedBufferType
= DXVA2_BitStreamDateBufferType
;
227 bs
->DataSize
= data_size
;
228 bs
->NumMBsInBuffer
= s
->mb_width
* s
->mb_height
;
229 assert((bs
->DataSize
& 127) == 0);
231 return ff_dxva2_commit_buffer(avctx
, ctx
, sc
,
232 DXVA2_SliceControlBufferType
,
233 slice
, sizeof(*slice
), bs
->NumMBsInBuffer
);
236 static int dxva2_vc1_start_frame(AVCodecContext
*avctx
,
237 av_unused
const uint8_t *buffer
,
238 av_unused
uint32_t size
)
240 const VC1Context
*v
= avctx
->priv_data
;
241 struct dxva_context
*ctx
= avctx
->hwaccel_context
;
242 struct dxva2_picture_context
*ctx_pic
= v
->s
.current_picture_ptr
->hwaccel_picture_private
;
244 if (!ctx
->decoder
|| !ctx
->cfg
|| ctx
->surface_count
<= 0)
248 fill_picture_parameters(avctx
, ctx
, v
, &ctx_pic
->pp
);
250 ctx_pic
->bitstream_size
= 0;
251 ctx_pic
->bitstream
= NULL
;
255 static int dxva2_vc1_decode_slice(AVCodecContext
*avctx
,
256 const uint8_t *buffer
,
259 const VC1Context
*v
= avctx
->priv_data
;
260 const Picture
*current_picture
= v
->s
.current_picture_ptr
;
261 struct dxva2_picture_context
*ctx_pic
= current_picture
->hwaccel_picture_private
;
263 if (ctx_pic
->bitstream_size
> 0)
266 if (avctx
->codec_id
== AV_CODEC_ID_VC1
&&
267 size
>= 4 && IS_MARKER(AV_RB32(buffer
))) {
272 ctx_pic
->bitstream_size
= size
;
273 ctx_pic
->bitstream
= buffer
;
275 fill_slice(avctx
, &ctx_pic
->si
, 0, size
);
279 static int dxva2_vc1_end_frame(AVCodecContext
*avctx
)
281 VC1Context
*v
= avctx
->priv_data
;
282 struct dxva2_picture_context
*ctx_pic
= v
->s
.current_picture_ptr
->hwaccel_picture_private
;
285 if (ctx_pic
->bitstream_size
<= 0)
288 ret
= ff_dxva2_common_end_frame(avctx
, v
->s
.current_picture_ptr
->f
,
289 &ctx_pic
->pp
, sizeof(ctx_pic
->pp
),
291 commit_bitstream_and_slice_buffer
);
293 ff_mpeg_draw_horiz_band(&v
->s
, 0, avctx
->height
);
297 #if CONFIG_WMV3_DXVA2_HWACCEL
298 AVHWAccel ff_wmv3_dxva2_hwaccel
= {
299 .name
= "wmv3_dxva2",
300 .type
= AVMEDIA_TYPE_VIDEO
,
301 .id
= AV_CODEC_ID_WMV3
,
302 .pix_fmt
= AV_PIX_FMT_DXVA2_VLD
,
303 .start_frame
= dxva2_vc1_start_frame
,
304 .decode_slice
= dxva2_vc1_decode_slice
,
305 .end_frame
= dxva2_vc1_end_frame
,
306 .frame_priv_data_size
= sizeof(struct dxva2_picture_context
),
310 AVHWAccel ff_vc1_dxva2_hwaccel
= {
312 .type
= AVMEDIA_TYPE_VIDEO
,
313 .id
= AV_CODEC_ID_VC1
,
314 .pix_fmt
= AV_PIX_FMT_DXVA2_VLD
,
315 .start_frame
= dxva2_vc1_start_frame
,
316 .decode_slice
= dxva2_vc1_decode_slice
,
317 .end_frame
= dxva2_vc1_end_frame
,
318 .frame_priv_data_size
= sizeof(struct dxva2_picture_context
),