2 * MPEG-2 HW acceleration.
4 * copyright (c) 2010 Laurent Aimar
6 * This file is part of Libav.
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.
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.
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
23 #include "dxva2_internal.h"
25 #define MAX_SLICES (SLICE_MAX_START_CODE - SLICE_MIN_START_CODE + 1)
26 struct dxva2_picture_context
{
27 DXVA_PictureParameters pp
;
30 DXVA_SliceInfo slice
[MAX_SLICES
];
32 const uint8_t *bitstream
;
33 unsigned bitstream_size
;
36 static void fill_picture_parameters(AVCodecContext
*avctx
,
37 struct dxva_context
*ctx
,
38 const struct MpegEncContext
*s
,
39 DXVA_PictureParameters
*pp
)
41 const Picture
*current_picture
= s
->current_picture_ptr
;
42 int is_field
= s
->picture_structure
!= PICT_FRAME
;
44 memset(pp
, 0, sizeof(*pp
));
45 pp
->wDecodedPictureIndex
= ff_dxva2_get_surface_index(ctx
, current_picture
);
46 pp
->wDeblockedPictureIndex
= 0;
47 if (s
->pict_type
!= AV_PICTURE_TYPE_I
)
48 pp
->wForwardRefPictureIndex
= ff_dxva2_get_surface_index(ctx
, &s
->last_picture
);
50 pp
->wForwardRefPictureIndex
= 0xffff;
51 if (s
->pict_type
== AV_PICTURE_TYPE_B
)
52 pp
->wBackwardRefPictureIndex
= ff_dxva2_get_surface_index(ctx
, &s
->next_picture
);
54 pp
->wBackwardRefPictureIndex
= 0xffff;
55 pp
->wPicWidthInMBminus1
= s
->mb_width
- 1;
56 pp
->wPicHeightInMBminus1
= (s
->mb_height
>> is_field
) - 1;
57 pp
->bMacroblockWidthMinus1
= 15;
58 pp
->bMacroblockHeightMinus1
= 15;
59 pp
->bBlockWidthMinus1
= 7;
60 pp
->bBlockHeightMinus1
= 7;
62 pp
->bPicStructure
= s
->picture_structure
;
63 pp
->bSecondField
= is_field
&& !s
->first_field
;
64 pp
->bPicIntra
= s
->pict_type
== AV_PICTURE_TYPE_I
;
65 pp
->bPicBackwardPrediction
= s
->pict_type
== AV_PICTURE_TYPE_B
;
66 pp
->bBidirectionalAveragingMode
= 0;
67 pp
->bMVprecisionAndChromaRelation
= 0; /* FIXME */
68 pp
->bChromaFormat
= s
->chroma_format
;
69 pp
->bPicScanFixed
= 1;
70 pp
->bPicScanMethod
= s
->alternate_scan
? 1 : 0;
71 pp
->bPicReadbackRequests
= 0;
73 pp
->bPicSpatialResid8
= 0;
74 pp
->bPicOverflowBlocks
= 0;
75 pp
->bPicExtrapolation
= 0;
76 pp
->bPicDeblocked
= 0;
77 pp
->bPicDeblockConfined
= 0;
78 pp
->bPic4MVallowed
= 0;
82 pp
->bReservedBits
= 0;
83 pp
->wBitstreamFcodes
= (s
->mpeg_f_code
[0][0] << 12) |
84 (s
->mpeg_f_code
[0][1] << 8) |
85 (s
->mpeg_f_code
[1][0] << 4) |
86 (s
->mpeg_f_code
[1][1] );
87 pp
->wBitstreamPCEelements
= (s
->intra_dc_precision
<< 14) |
88 (s
->picture_structure
<< 12) |
89 (s
->top_field_first
<< 11) |
90 (s
->frame_pred_frame_dct
<< 10) |
91 (s
->concealment_motion_vectors
<< 9) |
92 (s
->q_scale_type
<< 8) |
93 (s
->intra_vlc_format
<< 7) |
94 (s
->alternate_scan
<< 6) |
95 (s
->repeat_first_field
<< 5) |
96 (s
->chroma_420_type
<< 4) |
97 (s
->progressive_frame
<< 3);
98 pp
->bBitstreamConcealmentNeed
= 0;
99 pp
->bBitstreamConcealmentMethod
= 0;
102 static void fill_quantization_matrices(AVCodecContext
*avctx
,
103 struct dxva_context
*ctx
,
104 const struct MpegEncContext
*s
,
105 DXVA_QmatrixData
*qm
)
108 for (i
= 0; i
< 4; i
++)
109 qm
->bNewQmatrix
[i
] = 1;
110 for (i
= 0; i
< 64; i
++) {
111 int n
= s
->dsp
.idct_permutation
[ff_zigzag_direct
[i
]];
112 qm
->Qmatrix
[0][i
] = s
->intra_matrix
[n
];;
113 qm
->Qmatrix
[1][i
] = s
->inter_matrix
[n
];;
114 qm
->Qmatrix
[2][i
] = s
->chroma_intra_matrix
[n
];;
115 qm
->Qmatrix
[3][i
] = s
->chroma_inter_matrix
[n
];;
119 static void fill_slice(AVCodecContext
*avctx
,
120 const struct MpegEncContext
*s
,
121 DXVA_SliceInfo
*slice
,
123 const uint8_t *buffer
, unsigned size
)
125 int is_field
= s
->picture_structure
!= PICT_FRAME
;
128 memset(slice
, 0, sizeof(*slice
));
129 slice
->wHorizontalPosition
= s
->mb_x
;
130 slice
->wVerticalPosition
= s
->mb_y
>> is_field
;
131 slice
->dwSliceBitsInBuffer
= 8 * size
;
132 slice
->dwSliceDataLocation
= position
;
133 slice
->bStartCodeBitOffset
= 0;
134 slice
->bReservedBits
= 0;
135 /* XXX We store the index of the first MB and it will be fixed later */
136 slice
->wNumberMBsInSlice
= (s
->mb_y
>> is_field
) * s
->mb_width
+ s
->mb_x
;
137 slice
->wBadSliceChopping
= 0;
139 init_get_bits(&gb
, &buffer
[4], 8 * (size
- 4));
141 slice
->wQuantizerScaleCode
= get_bits(&gb
, 5);
142 while (get_bits1(&gb
))
145 slice
->wMBbitOffset
= 4 * 8 + get_bits_count(&gb
);
147 static int commit_bitstream_and_slice_buffer(AVCodecContext
*avctx
,
148 DXVA2_DecodeBufferDesc
*bs
,
149 DXVA2_DecodeBufferDesc
*sc
)
151 const struct MpegEncContext
*s
= avctx
->priv_data
;
152 struct dxva_context
*ctx
= avctx
->hwaccel_context
;
153 struct dxva2_picture_context
*ctx_pic
=
154 s
->current_picture_ptr
->f
.hwaccel_picture_private
;
155 const int is_field
= s
->picture_structure
!= PICT_FRAME
;
156 const unsigned mb_count
= s
->mb_width
* (s
->mb_height
>> is_field
);
157 uint8_t *dxva_data
, *current
, *end
;
161 if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx
->decoder
,
162 DXVA2_BitStreamDateBufferType
,
163 &dxva_data
, &dxva_size
)))
166 end
= dxva_data
+ dxva_size
;
168 for (i
= 0; i
< ctx_pic
->slice_count
; i
++) {
169 DXVA_SliceInfo
*slice
= &ctx_pic
->slice
[i
];
170 unsigned position
= slice
->dwSliceDataLocation
;
171 unsigned size
= slice
->dwSliceBitsInBuffer
/ 8;
172 if (size
> end
- current
) {
173 av_log(avctx
, AV_LOG_ERROR
, "Failed to build bitstream");
176 slice
->dwSliceDataLocation
= current
- dxva_data
;
178 if (i
< ctx_pic
->slice_count
- 1)
179 slice
->wNumberMBsInSlice
=
180 slice
[1].wNumberMBsInSlice
- slice
[0].wNumberMBsInSlice
;
182 slice
->wNumberMBsInSlice
=
183 mb_count
- slice
[0].wNumberMBsInSlice
;
185 memcpy(current
, &ctx_pic
->bitstream
[position
], size
);
188 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx
->decoder
,
189 DXVA2_BitStreamDateBufferType
)))
191 if (i
< ctx_pic
->slice_count
)
194 memset(bs
, 0, sizeof(*bs
));
195 bs
->CompressedBufferType
= DXVA2_BitStreamDateBufferType
;
196 bs
->DataSize
= current
- dxva_data
;
197 bs
->NumMBsInBuffer
= mb_count
;
199 return ff_dxva2_commit_buffer(avctx
, ctx
, sc
,
200 DXVA2_SliceControlBufferType
,
202 ctx_pic
->slice_count
* sizeof(*ctx_pic
->slice
),
206 static int start_frame(AVCodecContext
*avctx
,
207 av_unused
const uint8_t *buffer
,
208 av_unused
uint32_t size
)
210 const struct MpegEncContext
*s
= avctx
->priv_data
;
211 struct dxva_context
*ctx
= avctx
->hwaccel_context
;
212 struct dxva2_picture_context
*ctx_pic
=
213 s
->current_picture_ptr
->f
.hwaccel_picture_private
;
215 if (!ctx
->decoder
|| !ctx
->cfg
|| ctx
->surface_count
<= 0)
219 fill_picture_parameters(avctx
, ctx
, s
, &ctx_pic
->pp
);
220 fill_quantization_matrices(avctx
, ctx
, s
, &ctx_pic
->qm
);
222 ctx_pic
->slice_count
= 0;
223 ctx_pic
->bitstream_size
= 0;
224 ctx_pic
->bitstream
= NULL
;
228 static int decode_slice(AVCodecContext
*avctx
,
229 const uint8_t *buffer
, uint32_t size
)
231 const struct MpegEncContext
*s
= avctx
->priv_data
;
232 struct dxva2_picture_context
*ctx_pic
=
233 s
->current_picture_ptr
->f
.hwaccel_picture_private
;
236 if (ctx_pic
->slice_count
>= MAX_SLICES
)
239 if (!ctx_pic
->bitstream
)
240 ctx_pic
->bitstream
= buffer
;
241 ctx_pic
->bitstream_size
+= size
;
243 position
= buffer
- ctx_pic
->bitstream
;
244 fill_slice(avctx
, s
, &ctx_pic
->slice
[ctx_pic
->slice_count
++], position
,
249 static int end_frame(AVCodecContext
*avctx
)
251 struct MpegEncContext
*s
= avctx
->priv_data
;
252 struct dxva2_picture_context
*ctx_pic
=
253 s
->current_picture_ptr
->f
.hwaccel_picture_private
;
255 if (ctx_pic
->slice_count
<= 0 || ctx_pic
->bitstream_size
<= 0)
257 return ff_dxva2_common_end_frame(avctx
, s
,
258 &ctx_pic
->pp
, sizeof(ctx_pic
->pp
),
259 &ctx_pic
->qm
, sizeof(ctx_pic
->qm
),
260 commit_bitstream_and_slice_buffer
);
263 AVHWAccel ff_mpeg2_dxva2_hwaccel
= {
264 .name
= "mpeg2_dxva2",
265 .type
= AVMEDIA_TYPE_VIDEO
,
266 .id
= AV_CODEC_ID_MPEG2VIDEO
,
267 .pix_fmt
= AV_PIX_FMT_DXVA2_VLD
,
268 .start_frame
= start_frame
,
269 .decode_slice
= decode_slice
,
270 .end_frame
= end_frame
,
271 .priv_data_size
= sizeof(struct dxva2_picture_context
),