2 * MPEG-2 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 "config_components.h"
25 #include "libavutil/log.h"
27 #include "dxva2_internal.h"
28 #include "hwaccel_internal.h"
29 #include "mpegutils.h"
30 #include "mpegvideodec.h"
32 #define MAX_SLICES 1024
33 struct dxva2_picture_context
{
34 DXVA_PictureParameters pp
;
37 DXVA_SliceInfo slice
[MAX_SLICES
];
39 const uint8_t *bitstream
;
40 unsigned bitstream_size
;
43 void ff_dxva2_mpeg2_fill_picture_parameters(AVCodecContext
*avctx
,
45 DXVA_PictureParameters
*pp
)
47 const struct MpegEncContext
*s
= avctx
->priv_data
;
48 const MPVPicture
*current_picture
= s
->cur_pic
.ptr
;
49 int is_field
= s
->picture_structure
!= PICT_FRAME
;
51 memset(pp
, 0, sizeof(*pp
));
52 pp
->wDeblockedPictureIndex
= 0;
53 if (s
->pict_type
!= AV_PICTURE_TYPE_I
)
54 pp
->wForwardRefPictureIndex
= ff_dxva2_get_surface_index(avctx
, ctx
, s
->last_pic
.ptr
->f
, 0);
56 pp
->wForwardRefPictureIndex
= 0xffff;
57 if (s
->pict_type
== AV_PICTURE_TYPE_B
)
58 pp
->wBackwardRefPictureIndex
= ff_dxva2_get_surface_index(avctx
, ctx
, s
->next_pic
.ptr
->f
, 0);
60 pp
->wBackwardRefPictureIndex
= 0xffff;
61 pp
->wDecodedPictureIndex
= ff_dxva2_get_surface_index(avctx
, ctx
, current_picture
->f
, 1);
62 pp
->wPicWidthInMBminus1
= s
->mb_width
- 1;
63 pp
->wPicHeightInMBminus1
= (s
->mb_height
>> is_field
) - 1;
64 pp
->bMacroblockWidthMinus1
= 15;
65 pp
->bMacroblockHeightMinus1
= 15;
66 pp
->bBlockWidthMinus1
= 7;
67 pp
->bBlockHeightMinus1
= 7;
69 pp
->bPicStructure
= s
->picture_structure
;
70 pp
->bSecondField
= is_field
&& !s
->first_field
;
71 pp
->bPicIntra
= s
->pict_type
== AV_PICTURE_TYPE_I
;
72 pp
->bPicBackwardPrediction
= s
->pict_type
== AV_PICTURE_TYPE_B
;
73 pp
->bBidirectionalAveragingMode
= 0;
74 pp
->bMVprecisionAndChromaRelation
= 0; /* FIXME */
75 pp
->bChromaFormat
= s
->chroma_format
;
76 pp
->bPicScanFixed
= 1;
77 pp
->bPicScanMethod
= s
->alternate_scan
? 1 : 0;
78 pp
->bPicReadbackRequests
= 0;
80 pp
->bPicSpatialResid8
= 0;
81 pp
->bPicOverflowBlocks
= 0;
82 pp
->bPicExtrapolation
= 0;
83 pp
->bPicDeblocked
= 0;
84 pp
->bPicDeblockConfined
= 0;
85 pp
->bPic4MVallowed
= 0;
89 pp
->bReservedBits
= 0;
90 pp
->wBitstreamFcodes
= (s
->mpeg_f_code
[0][0] << 12) |
91 (s
->mpeg_f_code
[0][1] << 8) |
92 (s
->mpeg_f_code
[1][0] << 4) |
93 (s
->mpeg_f_code
[1][1] );
94 pp
->wBitstreamPCEelements
= (s
->intra_dc_precision
<< 14) |
95 (s
->picture_structure
<< 12) |
96 (s
->top_field_first
<< 11) |
97 (s
->frame_pred_frame_dct
<< 10) |
98 (s
->concealment_motion_vectors
<< 9) |
99 (s
->q_scale_type
<< 8) |
100 (s
->intra_vlc_format
<< 7) |
101 (s
->alternate_scan
<< 6) |
102 (s
->repeat_first_field
<< 5) |
103 (s
->chroma_420_type
<< 4) |
104 (s
->progressive_frame
<< 3);
105 pp
->bBitstreamConcealmentNeed
= 0;
106 pp
->bBitstreamConcealmentMethod
= 0;
109 void ff_dxva2_mpeg2_fill_quantization_matrices(AVCodecContext
*avctx
,
111 DXVA_QmatrixData
*qm
)
113 const struct MpegEncContext
*s
= avctx
->priv_data
;
115 for (i
= 0; i
< 4; i
++)
116 qm
->bNewQmatrix
[i
] = 1;
117 for (i
= 0; i
< 64; i
++) {
118 int n
= s
->idsp
.idct_permutation
[ff_zigzag_direct
[i
]];
119 qm
->Qmatrix
[0][i
] = s
->intra_matrix
[n
];
120 qm
->Qmatrix
[1][i
] = s
->inter_matrix
[n
];
121 qm
->Qmatrix
[2][i
] = s
->chroma_intra_matrix
[n
];
122 qm
->Qmatrix
[3][i
] = s
->chroma_inter_matrix
[n
];
126 void ff_dxva2_mpeg2_fill_slice(AVCodecContext
*avctx
,
127 DXVA_SliceInfo
*slice
,
129 const uint8_t *buffer
, unsigned size
)
131 const struct MpegEncContext
*s
= avctx
->priv_data
;
132 int is_field
= s
->picture_structure
!= PICT_FRAME
;
135 memset(slice
, 0, sizeof(*slice
));
136 slice
->wHorizontalPosition
= s
->mb_x
;
137 slice
->wVerticalPosition
= s
->mb_y
>> is_field
;
138 slice
->dwSliceBitsInBuffer
= 8 * size
;
139 slice
->dwSliceDataLocation
= position
;
140 slice
->bStartCodeBitOffset
= 0;
141 slice
->bReservedBits
= 0;
142 /* XXX We store the index of the first MB and it will be fixed later */
143 slice
->wNumberMBsInSlice
= (s
->mb_y
>> is_field
) * s
->mb_width
+ s
->mb_x
;
144 slice
->wBadSliceChopping
= 0;
146 init_get_bits(&gb
, &buffer
[4], 8 * (size
- 4));
148 slice
->wQuantizerScaleCode
= get_bits(&gb
, 5);
149 skip_1stop_8data_bits(&gb
);
151 slice
->wMBbitOffset
= 4 * 8 + get_bits_count(&gb
);
153 static int commit_bitstream_and_slice_buffer(AVCodecContext
*avctx
,
154 DECODER_BUFFER_DESC
*bs
,
155 DECODER_BUFFER_DESC
*sc
)
157 const struct MpegEncContext
*s
= avctx
->priv_data
;
158 AVDXVAContext
*ctx
= DXVA_CONTEXT(avctx
);
159 struct dxva2_picture_context
*ctx_pic
=
160 s
->cur_pic
.ptr
->hwaccel_picture_private
;
161 const int is_field
= s
->picture_structure
!= PICT_FRAME
;
162 const unsigned mb_count
= s
->mb_width
* (s
->mb_height
>> is_field
);
163 void *dxva_data_ptr
= NULL
;
164 uint8_t *dxva_data
, *current
, *end
;
170 if (ff_dxva2_is_d3d11(avctx
)) {
171 type
= D3D11_VIDEO_DECODER_BUFFER_BITSTREAM
;
172 if (FAILED(ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx
)->video_context
,
173 D3D11VA_CONTEXT(ctx
)->decoder
,
175 &dxva_size
, &dxva_data_ptr
)))
180 if (avctx
->pix_fmt
== AV_PIX_FMT_DXVA2_VLD
) {
181 type
= DXVA2_BitStreamDateBufferType
;
182 if (FAILED(IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx
)->decoder
,
184 &dxva_data_ptr
, &dxva_size
)))
192 dxva_data
= dxva_data_ptr
;
194 end
= dxva_data
+ dxva_size
;
196 for (i
= 0; i
< ctx_pic
->slice_count
; i
++) {
197 DXVA_SliceInfo
*slice
= &ctx_pic
->slice
[i
];
198 unsigned position
= slice
->dwSliceDataLocation
;
199 unsigned size
= slice
->dwSliceBitsInBuffer
/ 8;
200 if (size
> end
- current
) {
201 av_log(avctx
, AV_LOG_ERROR
, "Failed to build bitstream");
204 slice
->dwSliceDataLocation
= current
- dxva_data
;
206 if (i
< ctx_pic
->slice_count
- 1)
207 slice
->wNumberMBsInSlice
=
208 slice
[1].wNumberMBsInSlice
- slice
[0].wNumberMBsInSlice
;
210 slice
->wNumberMBsInSlice
=
211 mb_count
- slice
[0].wNumberMBsInSlice
;
213 memcpy(current
, &ctx_pic
->bitstream
[position
], size
);
217 if (ff_dxva2_is_d3d11(avctx
))
218 if (FAILED(ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx
)->video_context
, D3D11VA_CONTEXT(ctx
)->decoder
, type
)))
222 if (avctx
->pix_fmt
== AV_PIX_FMT_DXVA2_VLD
)
223 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx
)->decoder
, type
)))
226 if (i
< ctx_pic
->slice_count
)
230 if (ff_dxva2_is_d3d11(avctx
)) {
231 D3D11_VIDEO_DECODER_BUFFER_DESC
*dsc11
= bs
;
232 memset(dsc11
, 0, sizeof(*dsc11
));
233 dsc11
->BufferType
= type
;
234 dsc11
->DataSize
= current
- dxva_data
;
235 dsc11
->NumMBsInBuffer
= mb_count
;
237 type
= D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL
;
241 if (avctx
->pix_fmt
== AV_PIX_FMT_DXVA2_VLD
) {
242 DXVA2_DecodeBufferDesc
*dsc2
= bs
;
243 memset(dsc2
, 0, sizeof(*dsc2
));
244 dsc2
->CompressedBufferType
= type
;
245 dsc2
->DataSize
= current
- dxva_data
;
246 dsc2
->NumMBsInBuffer
= mb_count
;
248 type
= DXVA2_SliceControlBufferType
;
252 return ff_dxva2_commit_buffer(avctx
, ctx
, sc
,
255 ctx_pic
->slice_count
* sizeof(*ctx_pic
->slice
),
259 static int dxva2_mpeg2_start_frame(AVCodecContext
*avctx
,
260 av_unused
const uint8_t *buffer
,
261 av_unused
uint32_t size
)
263 const struct MpegEncContext
*s
= avctx
->priv_data
;
264 AVDXVAContext
*ctx
= DXVA_CONTEXT(avctx
);
265 struct dxva2_picture_context
*ctx_pic
=
266 s
->cur_pic
.ptr
->hwaccel_picture_private
;
268 if (!DXVA_CONTEXT_VALID(avctx
, ctx
))
272 ff_dxva2_mpeg2_fill_picture_parameters(avctx
, ctx
, &ctx_pic
->pp
);
273 ff_dxva2_mpeg2_fill_quantization_matrices(avctx
, ctx
, &ctx_pic
->qm
);
275 ctx_pic
->slice_count
= 0;
276 ctx_pic
->bitstream_size
= 0;
277 ctx_pic
->bitstream
= NULL
;
281 static int dxva2_mpeg2_decode_slice(AVCodecContext
*avctx
,
282 const uint8_t *buffer
, uint32_t size
)
284 const struct MpegEncContext
*s
= avctx
->priv_data
;
285 struct dxva2_picture_context
*ctx_pic
=
286 s
->cur_pic
.ptr
->hwaccel_picture_private
;
289 if (ctx_pic
->slice_count
>= MAX_SLICES
) {
290 avpriv_request_sample(avctx
, "%d slices in dxva2",
291 ctx_pic
->slice_count
);
294 if (!ctx_pic
->bitstream
)
295 ctx_pic
->bitstream
= buffer
;
296 ctx_pic
->bitstream_size
+= size
;
298 position
= buffer
- ctx_pic
->bitstream
;
299 ff_dxva2_mpeg2_fill_slice(avctx
, &ctx_pic
->slice
[ctx_pic
->slice_count
++], position
,
304 static int dxva2_mpeg2_end_frame(AVCodecContext
*avctx
)
306 struct MpegEncContext
*s
= avctx
->priv_data
;
307 struct dxva2_picture_context
*ctx_pic
=
308 s
->cur_pic
.ptr
->hwaccel_picture_private
;
311 if (ctx_pic
->slice_count
<= 0 || ctx_pic
->bitstream_size
<= 0)
313 ret
= ff_dxva2_common_end_frame(avctx
, s
->cur_pic
.ptr
->f
,
314 &ctx_pic
->pp
, sizeof(ctx_pic
->pp
),
315 &ctx_pic
->qm
, sizeof(ctx_pic
->qm
),
316 commit_bitstream_and_slice_buffer
);
318 ff_mpeg_draw_horiz_band(s
, 0, avctx
->height
);
322 #if CONFIG_MPEG2_DXVA2_HWACCEL
323 const FFHWAccel ff_mpeg2_dxva2_hwaccel
= {
324 .p
.name
= "mpeg2_dxva2",
325 .p
.type
= AVMEDIA_TYPE_VIDEO
,
326 .p
.id
= AV_CODEC_ID_MPEG2VIDEO
,
327 .p
.pix_fmt
= AV_PIX_FMT_DXVA2_VLD
,
328 .init
= ff_dxva2_decode_init
,
329 .uninit
= ff_dxva2_decode_uninit
,
330 .start_frame
= dxva2_mpeg2_start_frame
,
331 .decode_slice
= dxva2_mpeg2_decode_slice
,
332 .end_frame
= dxva2_mpeg2_end_frame
,
333 .frame_params
= ff_dxva2_common_frame_params
,
334 .frame_priv_data_size
= sizeof(struct dxva2_picture_context
),
335 .priv_data_size
= sizeof(FFDXVASharedContext
),
339 #if CONFIG_MPEG2_D3D11VA_HWACCEL
340 const FFHWAccel ff_mpeg2_d3d11va_hwaccel
= {
341 .p
.name
= "mpeg2_d3d11va",
342 .p
.type
= AVMEDIA_TYPE_VIDEO
,
343 .p
.id
= AV_CODEC_ID_MPEG2VIDEO
,
344 .p
.pix_fmt
= AV_PIX_FMT_D3D11VA_VLD
,
345 .init
= ff_dxva2_decode_init
,
346 .uninit
= ff_dxva2_decode_uninit
,
347 .start_frame
= dxva2_mpeg2_start_frame
,
348 .decode_slice
= dxva2_mpeg2_decode_slice
,
349 .end_frame
= dxva2_mpeg2_end_frame
,
350 .frame_params
= ff_dxva2_common_frame_params
,
351 .frame_priv_data_size
= sizeof(struct dxva2_picture_context
),
352 .priv_data_size
= sizeof(FFDXVASharedContext
),
356 #if CONFIG_MPEG2_D3D11VA2_HWACCEL
357 const FFHWAccel ff_mpeg2_d3d11va2_hwaccel
= {
358 .p
.name
= "mpeg2_d3d11va2",
359 .p
.type
= AVMEDIA_TYPE_VIDEO
,
360 .p
.id
= AV_CODEC_ID_MPEG2VIDEO
,
361 .p
.pix_fmt
= AV_PIX_FMT_D3D11
,
362 .init
= ff_dxva2_decode_init
,
363 .uninit
= ff_dxva2_decode_uninit
,
364 .start_frame
= dxva2_mpeg2_start_frame
,
365 .decode_slice
= dxva2_mpeg2_decode_slice
,
366 .end_frame
= dxva2_mpeg2_end_frame
,
367 .frame_params
= ff_dxva2_common_frame_params
,
368 .frame_priv_data_size
= sizeof(struct dxva2_picture_context
),
369 .priv_data_size
= sizeof(FFDXVASharedContext
),