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 "libavutil/log.h"
24 #include "dxva2_internal.h"
25 #include "mpegutils.h"
27 #define MAX_SLICES 1024
28 struct dxva2_picture_context
{
29 DXVA_PictureParameters pp
;
32 DXVA_SliceInfo slice
[MAX_SLICES
];
34 const uint8_t *bitstream
;
35 unsigned bitstream_size
;
38 static void fill_picture_parameters(AVCodecContext
*avctx
,
39 struct dxva_context
*ctx
,
40 const struct MpegEncContext
*s
,
41 DXVA_PictureParameters
*pp
)
43 const Picture
*current_picture
= s
->current_picture_ptr
;
44 int is_field
= s
->picture_structure
!= PICT_FRAME
;
46 memset(pp
, 0, sizeof(*pp
));
47 pp
->wDecodedPictureIndex
= ff_dxva2_get_surface_index(ctx
, current_picture
->f
);
48 pp
->wDeblockedPictureIndex
= 0;
49 if (s
->pict_type
!= AV_PICTURE_TYPE_I
)
50 pp
->wForwardRefPictureIndex
= ff_dxva2_get_surface_index(ctx
, s
->last_picture
.f
);
52 pp
->wForwardRefPictureIndex
= 0xffff;
53 if (s
->pict_type
== AV_PICTURE_TYPE_B
)
54 pp
->wBackwardRefPictureIndex
= ff_dxva2_get_surface_index(ctx
, s
->next_picture
.f
);
56 pp
->wBackwardRefPictureIndex
= 0xffff;
57 pp
->wPicWidthInMBminus1
= s
->mb_width
- 1;
58 pp
->wPicHeightInMBminus1
= (s
->mb_height
>> is_field
) - 1;
59 pp
->bMacroblockWidthMinus1
= 15;
60 pp
->bMacroblockHeightMinus1
= 15;
61 pp
->bBlockWidthMinus1
= 7;
62 pp
->bBlockHeightMinus1
= 7;
64 pp
->bPicStructure
= s
->picture_structure
;
65 pp
->bSecondField
= is_field
&& !s
->first_field
;
66 pp
->bPicIntra
= s
->pict_type
== AV_PICTURE_TYPE_I
;
67 pp
->bPicBackwardPrediction
= s
->pict_type
== AV_PICTURE_TYPE_B
;
68 pp
->bBidirectionalAveragingMode
= 0;
69 pp
->bMVprecisionAndChromaRelation
= 0; /* FIXME */
70 pp
->bChromaFormat
= s
->chroma_format
;
71 pp
->bPicScanFixed
= 1;
72 pp
->bPicScanMethod
= s
->alternate_scan
? 1 : 0;
73 pp
->bPicReadbackRequests
= 0;
75 pp
->bPicSpatialResid8
= 0;
76 pp
->bPicOverflowBlocks
= 0;
77 pp
->bPicExtrapolation
= 0;
78 pp
->bPicDeblocked
= 0;
79 pp
->bPicDeblockConfined
= 0;
80 pp
->bPic4MVallowed
= 0;
84 pp
->bReservedBits
= 0;
85 pp
->wBitstreamFcodes
= (s
->mpeg_f_code
[0][0] << 12) |
86 (s
->mpeg_f_code
[0][1] << 8) |
87 (s
->mpeg_f_code
[1][0] << 4) |
88 (s
->mpeg_f_code
[1][1] );
89 pp
->wBitstreamPCEelements
= (s
->intra_dc_precision
<< 14) |
90 (s
->picture_structure
<< 12) |
91 (s
->top_field_first
<< 11) |
92 (s
->frame_pred_frame_dct
<< 10) |
93 (s
->concealment_motion_vectors
<< 9) |
94 (s
->q_scale_type
<< 8) |
95 (s
->intra_vlc_format
<< 7) |
96 (s
->alternate_scan
<< 6) |
97 (s
->repeat_first_field
<< 5) |
98 (s
->chroma_420_type
<< 4) |
99 (s
->progressive_frame
<< 3);
100 pp
->bBitstreamConcealmentNeed
= 0;
101 pp
->bBitstreamConcealmentMethod
= 0;
104 static void fill_quantization_matrices(AVCodecContext
*avctx
,
105 struct dxva_context
*ctx
,
106 const struct MpegEncContext
*s
,
107 DXVA_QmatrixData
*qm
)
110 for (i
= 0; i
< 4; i
++)
111 qm
->bNewQmatrix
[i
] = 1;
112 for (i
= 0; i
< 64; i
++) {
113 int n
= s
->idsp
.idct_permutation
[ff_zigzag_direct
[i
]];
114 qm
->Qmatrix
[0][i
] = s
->intra_matrix
[n
];
115 qm
->Qmatrix
[1][i
] = s
->inter_matrix
[n
];
116 qm
->Qmatrix
[2][i
] = s
->chroma_intra_matrix
[n
];
117 qm
->Qmatrix
[3][i
] = s
->chroma_inter_matrix
[n
];
121 static void fill_slice(AVCodecContext
*avctx
,
122 const struct MpegEncContext
*s
,
123 DXVA_SliceInfo
*slice
,
125 const uint8_t *buffer
, unsigned size
)
127 int is_field
= s
->picture_structure
!= PICT_FRAME
;
130 memset(slice
, 0, sizeof(*slice
));
131 slice
->wHorizontalPosition
= s
->mb_x
;
132 slice
->wVerticalPosition
= s
->mb_y
>> is_field
;
133 slice
->dwSliceBitsInBuffer
= 8 * size
;
134 slice
->dwSliceDataLocation
= position
;
135 slice
->bStartCodeBitOffset
= 0;
136 slice
->bReservedBits
= 0;
137 /* XXX We store the index of the first MB and it will be fixed later */
138 slice
->wNumberMBsInSlice
= (s
->mb_y
>> is_field
) * s
->mb_width
+ s
->mb_x
;
139 slice
->wBadSliceChopping
= 0;
141 init_get_bits(&gb
, &buffer
[4], 8 * (size
- 4));
143 slice
->wQuantizerScaleCode
= get_bits(&gb
, 5);
144 skip_1stop_8data_bits(&gb
);
146 slice
->wMBbitOffset
= 4 * 8 + get_bits_count(&gb
);
148 static int commit_bitstream_and_slice_buffer(AVCodecContext
*avctx
,
149 DXVA2_DecodeBufferDesc
*bs
,
150 DXVA2_DecodeBufferDesc
*sc
)
152 const struct MpegEncContext
*s
= avctx
->priv_data
;
153 struct dxva_context
*ctx
= avctx
->hwaccel_context
;
154 struct dxva2_picture_context
*ctx_pic
=
155 s
->current_picture_ptr
->hwaccel_picture_private
;
156 const int is_field
= s
->picture_structure
!= PICT_FRAME
;
157 const unsigned mb_count
= s
->mb_width
* (s
->mb_height
>> is_field
);
159 uint8_t *dxva_data
, *current
, *end
;
163 if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx
->decoder
,
164 DXVA2_BitStreamDateBufferType
,
165 &dxva_data_ptr
, &dxva_size
)))
168 dxva_data
= dxva_data_ptr
;
170 end
= dxva_data
+ dxva_size
;
172 for (i
= 0; i
< ctx_pic
->slice_count
; i
++) {
173 DXVA_SliceInfo
*slice
= &ctx_pic
->slice
[i
];
174 unsigned position
= slice
->dwSliceDataLocation
;
175 unsigned size
= slice
->dwSliceBitsInBuffer
/ 8;
176 if (size
> end
- current
) {
177 av_log(avctx
, AV_LOG_ERROR
, "Failed to build bitstream");
180 slice
->dwSliceDataLocation
= current
- dxva_data
;
182 if (i
< ctx_pic
->slice_count
- 1)
183 slice
->wNumberMBsInSlice
=
184 slice
[1].wNumberMBsInSlice
- slice
[0].wNumberMBsInSlice
;
186 slice
->wNumberMBsInSlice
=
187 mb_count
- slice
[0].wNumberMBsInSlice
;
189 memcpy(current
, &ctx_pic
->bitstream
[position
], size
);
192 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx
->decoder
,
193 DXVA2_BitStreamDateBufferType
)))
195 if (i
< ctx_pic
->slice_count
)
198 memset(bs
, 0, sizeof(*bs
));
199 bs
->CompressedBufferType
= DXVA2_BitStreamDateBufferType
;
200 bs
->DataSize
= current
- dxva_data
;
201 bs
->NumMBsInBuffer
= mb_count
;
203 return ff_dxva2_commit_buffer(avctx
, ctx
, sc
,
204 DXVA2_SliceControlBufferType
,
206 ctx_pic
->slice_count
* sizeof(*ctx_pic
->slice
),
210 static int dxva2_mpeg2_start_frame(AVCodecContext
*avctx
,
211 av_unused
const uint8_t *buffer
,
212 av_unused
uint32_t size
)
214 const struct MpegEncContext
*s
= avctx
->priv_data
;
215 struct dxva_context
*ctx
= avctx
->hwaccel_context
;
216 struct dxva2_picture_context
*ctx_pic
=
217 s
->current_picture_ptr
->hwaccel_picture_private
;
219 if (!ctx
->decoder
|| !ctx
->cfg
|| ctx
->surface_count
<= 0)
223 fill_picture_parameters(avctx
, ctx
, s
, &ctx_pic
->pp
);
224 fill_quantization_matrices(avctx
, ctx
, s
, &ctx_pic
->qm
);
226 ctx_pic
->slice_count
= 0;
227 ctx_pic
->bitstream_size
= 0;
228 ctx_pic
->bitstream
= NULL
;
232 static int dxva2_mpeg2_decode_slice(AVCodecContext
*avctx
,
233 const uint8_t *buffer
, uint32_t size
)
235 const struct MpegEncContext
*s
= avctx
->priv_data
;
236 struct dxva2_picture_context
*ctx_pic
=
237 s
->current_picture_ptr
->hwaccel_picture_private
;
240 if (ctx_pic
->slice_count
>= MAX_SLICES
) {
241 avpriv_request_sample(avctx
, "%d slices in dxva2",
242 ctx_pic
->slice_count
);
245 if (!ctx_pic
->bitstream
)
246 ctx_pic
->bitstream
= buffer
;
247 ctx_pic
->bitstream_size
+= size
;
249 position
= buffer
- ctx_pic
->bitstream
;
250 fill_slice(avctx
, s
, &ctx_pic
->slice
[ctx_pic
->slice_count
++], position
,
255 static int dxva2_mpeg2_end_frame(AVCodecContext
*avctx
)
257 struct MpegEncContext
*s
= avctx
->priv_data
;
258 struct dxva2_picture_context
*ctx_pic
=
259 s
->current_picture_ptr
->hwaccel_picture_private
;
262 if (ctx_pic
->slice_count
<= 0 || ctx_pic
->bitstream_size
<= 0)
264 ret
= ff_dxva2_common_end_frame(avctx
, s
->current_picture_ptr
->f
,
265 &ctx_pic
->pp
, sizeof(ctx_pic
->pp
),
266 &ctx_pic
->qm
, sizeof(ctx_pic
->qm
),
267 commit_bitstream_and_slice_buffer
);
269 ff_mpeg_draw_horiz_band(s
, 0, avctx
->height
);
273 AVHWAccel ff_mpeg2_dxva2_hwaccel
= {
274 .name
= "mpeg2_dxva2",
275 .type
= AVMEDIA_TYPE_VIDEO
,
276 .id
= AV_CODEC_ID_MPEG2VIDEO
,
277 .pix_fmt
= AV_PIX_FMT_DXVA2_VLD
,
278 .start_frame
= dxva2_mpeg2_start_frame
,
279 .decode_slice
= dxva2_mpeg2_decode_slice
,
280 .end_frame
= dxva2_mpeg2_end_frame
,
281 .frame_priv_data_size
= sizeof(struct dxva2_picture_context
),