]> git.sesse.net Git - ffmpeg/blob - libavcodec/dxva2_vc1.c
lavc: mark the old audio/video encoding API as deprecated
[ffmpeg] / libavcodec / dxva2_vc1.c
1 /*
2  * DXVA2 WMV3/VC-1 HW acceleration.
3  *
4  * copyright (c) 2010 Laurent Aimar
5  *
6  * This file is part of Libav.
7  *
8  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  */
22
23 #include "mpegutils.h"
24 #include "vc1.h"
25 #include "vc1data.h"
26
27 // The headers above may include w32threads.h, which uses the original
28 // _WIN32_WINNT define, while dxva2_internal.h redefines it to target a
29 // potentially newer version.
30 #include "dxva2_internal.h"
31
32 struct dxva2_picture_context {
33     DXVA_PictureParameters pp;
34     DXVA_SliceInfo         si;
35
36     const uint8_t          *bitstream;
37     unsigned               bitstream_size;
38 };
39
40 static void fill_picture_parameters(AVCodecContext *avctx,
41                                     AVDXVAContext *ctx, const VC1Context *v,
42                                     DXVA_PictureParameters *pp)
43 {
44     const MpegEncContext *s = &v->s;
45     const Picture *current_picture = s->current_picture_ptr;
46
47     memset(pp, 0, sizeof(*pp));
48     pp->wDecodedPictureIndex    =
49     pp->wDeblockedPictureIndex  = ff_dxva2_get_surface_index(avctx, ctx, current_picture->f);
50     if (s->pict_type != AV_PICTURE_TYPE_I && !v->bi_type)
51         pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->last_picture.f);
52     else
53         pp->wForwardRefPictureIndex = 0xffff;
54     if (s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type)
55         pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(avctx, ctx, s->next_picture.f);
56     else
57         pp->wBackwardRefPictureIndex = 0xffff;
58     if (v->profile == PROFILE_ADVANCED) {
59         /* It is the cropped width/height -1 of the frame */
60         pp->wPicWidthInMBminus1 = avctx->width  - 1;
61         pp->wPicHeightInMBminus1= avctx->height - 1;
62     } else {
63         /* It is the coded width/height in macroblock -1 of the frame */
64         pp->wPicWidthInMBminus1 = s->mb_width  - 1;
65         pp->wPicHeightInMBminus1= s->mb_height - 1;
66     }
67     pp->bMacroblockWidthMinus1  = 15;
68     pp->bMacroblockHeightMinus1 = 15;
69     pp->bBlockWidthMinus1       = 7;
70     pp->bBlockHeightMinus1      = 7;
71     pp->bBPPminus1              = 7;
72     if (s->picture_structure & PICT_TOP_FIELD)
73         pp->bPicStructure      |= 0x01;
74     if (s->picture_structure & PICT_BOTTOM_FIELD)
75         pp->bPicStructure      |= 0x02;
76     pp->bSecondField            = v->interlace && v->fcm != ILACE_FIELD && !s->first_field;
77     pp->bPicIntra               = s->pict_type == AV_PICTURE_TYPE_I || v->bi_type;
78     pp->bPicBackwardPrediction  = s->pict_type == AV_PICTURE_TYPE_B && !v->bi_type;
79     pp->bBidirectionalAveragingMode = (1                                           << 7) |
80                                       ((DXVA_CONTEXT_CFG_INTRARESID(avctx, ctx) != 0) << 6) |
81                                       ((DXVA_CONTEXT_CFG_RESIDACCEL(avctx, ctx) != 0) << 5) |
82                                       ((v->lumscale != 32 || v->lumshift != 0)     << 4) |
83                                       ((v->profile == PROFILE_ADVANCED)            << 3);
84     pp->bMVprecisionAndChromaRelation = ((v->mv_mode == MV_PMODE_1MV_HPEL_BILIN) << 3) |
85                                         (1                                       << 2) |
86                                         (0                                       << 1) |
87                                         (!s->quarter_sample                          );
88     pp->bChromaFormat           = v->chromaformat;
89     DXVA_CONTEXT_REPORT_ID(avctx, ctx)++;
90     if (DXVA_CONTEXT_REPORT_ID(avctx, ctx) >= (1 << 16))
91         DXVA_CONTEXT_REPORT_ID(avctx, ctx) = 1;
92     pp->bPicScanFixed           = DXVA_CONTEXT_REPORT_ID(avctx, ctx) >> 8;
93     pp->bPicScanMethod          = DXVA_CONTEXT_REPORT_ID(avctx, ctx) & 0xff;
94     pp->bPicReadbackRequests    = 0;
95     pp->bRcontrol               = v->rnd;
96     pp->bPicSpatialResid8       = (v->panscanflag  << 7) |
97                                   (v->refdist_flag << 6) |
98                                   (s->loop_filter  << 5) |
99                                   (v->fastuvmc     << 4) |
100                                   (v->extended_mv  << 3) |
101                                   (v->dquant       << 1) |
102                                   (v->vstransform      );
103     pp->bPicOverflowBlocks      = (v->quantizer_mode << 6) |
104                                   (v->multires       << 5) |
105                                   (v->resync_marker  << 4) |
106                                   (v->rangered       << 3) |
107                                   (s->max_b_frames       );
108     pp->bPicExtrapolation       = (!v->interlace || v->fcm == PROGRESSIVE) ? 1 : 2;
109     pp->bPicDeblocked           = ((!pp->bPicBackwardPrediction && v->overlap)        << 6) |
110                                   ((v->profile != PROFILE_ADVANCED && v->rangeredfrm) << 5) |
111                                   (s->loop_filter                                     << 1);
112     pp->bPicDeblockConfined     = (v->postprocflag             << 7) |
113                                   (v->broadcast                << 6) |
114                                   (v->interlace                << 5) |
115                                   (v->tfcntrflag               << 4) |
116                                   (v->finterpflag              << 3) |
117                                   ((s->pict_type != AV_PICTURE_TYPE_B) << 2) |
118                                   (v->psf                      << 1) |
119                                   (v->extended_dmv                 );
120     if (s->pict_type != AV_PICTURE_TYPE_I)
121         pp->bPic4MVallowed      = v->mv_mode == MV_PMODE_MIXED_MV ||
122                                   (v->mv_mode == MV_PMODE_INTENSITY_COMP &&
123                                    v->mv_mode2 == MV_PMODE_MIXED_MV);
124     if (v->profile == PROFILE_ADVANCED)
125         pp->bPicOBMC            = (v->range_mapy_flag  << 7) |
126                                   (v->range_mapy       << 4) |
127                                   (v->range_mapuv_flag << 3) |
128                                   (v->range_mapuv          );
129     pp->bPicBinPB               = 0;
130     pp->bMV_RPS                 = 0;
131     pp->bReservedBits           = 0;
132     if (s->picture_structure == PICT_FRAME) {
133         pp->wBitstreamFcodes        = v->lumscale;
134         pp->wBitstreamPCEelements   = v->lumshift;
135     } else {
136         /* Syntax: (top_field_param << 8) | bottom_field_param */
137         pp->wBitstreamFcodes        = (v->lumscale << 8) | v->lumscale;
138         pp->wBitstreamPCEelements   = (v->lumshift << 8) | v->lumshift;
139     }
140     pp->bBitstreamConcealmentNeed   = 0;
141     pp->bBitstreamConcealmentMethod = 0;
142 }
143
144 static void fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice,
145                        unsigned position, unsigned size)
146 {
147     const VC1Context *v = avctx->priv_data;
148     const MpegEncContext *s = &v->s;
149
150     memset(slice, 0, sizeof(*slice));
151     slice->wHorizontalPosition = 0;
152     slice->wVerticalPosition   = s->mb_y;
153     slice->dwSliceBitsInBuffer = 8 * size;
154     slice->dwSliceDataLocation = position;
155     slice->bStartCodeBitOffset = 0;
156     slice->bReservedBits       = 0;
157     slice->wMBbitOffset        = get_bits_count(&s->gb);
158     slice->wNumberMBsInSlice   = s->mb_width * s->mb_height; /* XXX We assume 1 slice */
159     slice->wQuantizerScaleCode = v->pq;
160     slice->wBadSliceChopping   = 0;
161 }
162
163 static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
164                                              DECODER_BUFFER_DESC *bs,
165                                              DECODER_BUFFER_DESC *sc)
166 {
167     const VC1Context *v = avctx->priv_data;
168     AVDXVAContext *ctx = avctx->hwaccel_context;
169     const MpegEncContext *s = &v->s;
170     struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private;
171
172     DXVA_SliceInfo *slice = &ctx_pic->si;
173
174     static const uint8_t start_code[] = { 0, 0, 1, 0x0d };
175     const unsigned start_code_size = avctx->codec_id == AV_CODEC_ID_VC1 ? sizeof(start_code) : 0;
176     const unsigned slice_size = slice->dwSliceBitsInBuffer / 8;
177     const unsigned padding = 128 - ((start_code_size + slice_size) & 127);
178     const unsigned data_size = start_code_size + slice_size + padding;
179
180     void     *dxva_data_ptr;
181     uint8_t  *dxva_data;
182     unsigned dxva_size;
183     int result;
184     unsigned type;
185
186 #if CONFIG_D3D11VA
187     if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
188         type = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM;
189         if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context,
190                                                        D3D11VA_CONTEXT(ctx)->decoder,
191                                                        type,
192                                                        &dxva_size, &dxva_data_ptr)))
193             return -1;
194     }
195 #endif
196 #if CONFIG_DXVA2
197     if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
198         type = DXVA2_BitStreamDateBufferType;
199         if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder,
200                                                   type,
201                                                   &dxva_data_ptr, &dxva_size)))
202             return -1;
203     }
204 #endif
205
206     dxva_data = dxva_data_ptr;
207     result = data_size <= dxva_size ? 0 : -1;
208     if (!result) {
209         if (start_code_size > 0)
210             memcpy(dxva_data, start_code, start_code_size);
211         memcpy(dxva_data + start_code_size,
212                ctx_pic->bitstream + slice->dwSliceDataLocation, slice_size);
213         if (padding > 0)
214             memset(dxva_data + start_code_size + slice_size, 0, padding);
215         slice->dwSliceBitsInBuffer = 8 * data_size;
216     }
217 #if CONFIG_D3D11VA
218     if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD)
219         if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type)))
220             return -1;
221 #endif
222 #if CONFIG_DXVA2
223     if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD)
224         if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type)))
225             return -1;
226 #endif
227     if (result)
228         return result;
229
230 #if CONFIG_D3D11VA
231     if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) {
232         D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = bs;
233         memset(dsc11, 0, sizeof(*dsc11));
234         dsc11->BufferType           = type;
235         dsc11->DataSize             = data_size;
236         dsc11->NumMBsInBuffer       = s->mb_width * s->mb_height;
237
238         type = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL;
239     }
240 #endif
241 #if CONFIG_DXVA2
242     if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
243         DXVA2_DecodeBufferDesc *dsc2 = bs;
244         memset(dsc2, 0, sizeof(*dsc2));
245         dsc2->CompressedBufferType = type;
246         dsc2->DataSize             = data_size;
247         dsc2->NumMBsInBuffer       = s->mb_width * s->mb_height;
248
249         type = DXVA2_SliceControlBufferType;
250     }
251 #endif
252     assert((data_size & 127) == 0);
253
254     return ff_dxva2_commit_buffer(avctx, ctx, sc,
255                                   type,
256                                   slice, sizeof(*slice), s->mb_width * s->mb_height);
257 }
258
259 static int dxva2_vc1_start_frame(AVCodecContext *avctx,
260                                  av_unused const uint8_t *buffer,
261                                  av_unused uint32_t size)
262 {
263     const VC1Context *v = avctx->priv_data;
264     AVDXVAContext *ctx = avctx->hwaccel_context;
265     struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private;
266
267     if (DXVA_CONTEXT_DECODER(avctx, ctx) == NULL ||
268         DXVA_CONTEXT_CFG(avctx, ctx) == NULL ||
269         DXVA_CONTEXT_COUNT(avctx, ctx) <= 0)
270         return -1;
271     assert(ctx_pic);
272
273     fill_picture_parameters(avctx, ctx, v, &ctx_pic->pp);
274
275     ctx_pic->bitstream_size = 0;
276     ctx_pic->bitstream      = NULL;
277     return 0;
278 }
279
280 static int dxva2_vc1_decode_slice(AVCodecContext *avctx,
281                                   const uint8_t *buffer,
282                                   uint32_t size)
283 {
284     const VC1Context *v = avctx->priv_data;
285     const Picture *current_picture = v->s.current_picture_ptr;
286     struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
287
288     if (ctx_pic->bitstream_size > 0)
289         return -1;
290
291     if (avctx->codec_id == AV_CODEC_ID_VC1 &&
292         size >= 4 && IS_MARKER(AV_RB32(buffer))) {
293         buffer += 4;
294         size   -= 4;
295     }
296
297     ctx_pic->bitstream_size = size;
298     ctx_pic->bitstream      = buffer;
299
300     fill_slice(avctx, &ctx_pic->si, 0, size);
301     return 0;
302 }
303
304 static int dxva2_vc1_end_frame(AVCodecContext *avctx)
305 {
306     VC1Context *v = avctx->priv_data;
307     struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private;
308     int ret;
309
310     if (ctx_pic->bitstream_size <= 0)
311         return -1;
312
313     ret = ff_dxva2_common_end_frame(avctx, v->s.current_picture_ptr->f,
314                                     &ctx_pic->pp, sizeof(ctx_pic->pp),
315                                     NULL, 0,
316                                     commit_bitstream_and_slice_buffer);
317     if (!ret)
318         ff_mpeg_draw_horiz_band(&v->s, 0, avctx->height);
319     return ret;
320 }
321
322 #if CONFIG_WMV3_DXVA2_HWACCEL
323 AVHWAccel ff_wmv3_dxva2_hwaccel = {
324     .name           = "wmv3_dxva2",
325     .type           = AVMEDIA_TYPE_VIDEO,
326     .id             = AV_CODEC_ID_WMV3,
327     .pix_fmt        = AV_PIX_FMT_DXVA2_VLD,
328     .start_frame    = dxva2_vc1_start_frame,
329     .decode_slice   = dxva2_vc1_decode_slice,
330     .end_frame      = dxva2_vc1_end_frame,
331     .frame_priv_data_size = sizeof(struct dxva2_picture_context),
332 };
333 #endif
334
335 #if CONFIG_VC1_DXVA2_HWACCEL
336 AVHWAccel ff_vc1_dxva2_hwaccel = {
337     .name           = "vc1_dxva2",
338     .type           = AVMEDIA_TYPE_VIDEO,
339     .id             = AV_CODEC_ID_VC1,
340     .pix_fmt        = AV_PIX_FMT_DXVA2_VLD,
341     .start_frame    = dxva2_vc1_start_frame,
342     .decode_slice   = dxva2_vc1_decode_slice,
343     .end_frame      = dxva2_vc1_end_frame,
344     .frame_priv_data_size = sizeof(struct dxva2_picture_context),
345 };
346 #endif
347
348 #if CONFIG_WMV3_D3D11VA_HWACCEL
349 AVHWAccel ff_wmv3_d3d11va_hwaccel = {
350     .name           = "wmv3_d3d11va",
351     .type           = AVMEDIA_TYPE_VIDEO,
352     .id             = AV_CODEC_ID_WMV3,
353     .pix_fmt        = AV_PIX_FMT_D3D11VA_VLD,
354     .start_frame    = dxva2_vc1_start_frame,
355     .decode_slice   = dxva2_vc1_decode_slice,
356     .end_frame      = dxva2_vc1_end_frame,
357     .frame_priv_data_size = sizeof(struct dxva2_picture_context),
358 };
359 #endif
360
361 #if CONFIG_VC1_D3D11VA_HWACCEL
362 AVHWAccel ff_vc1_d3d11va_hwaccel = {
363     .name           = "vc1_d3d11va",
364     .type           = AVMEDIA_TYPE_VIDEO,
365     .id             = AV_CODEC_ID_VC1,
366     .pix_fmt        = AV_PIX_FMT_D3D11VA_VLD,
367     .start_frame    = dxva2_vc1_start_frame,
368     .decode_slice   = dxva2_vc1_decode_slice,
369     .end_frame      = dxva2_vc1_end_frame,
370     .frame_priv_data_size = sizeof(struct dxva2_picture_context),
371 };
372 #endif