blob: fcdf4b2747f26135b8d4735b2c3467b52b533b7a
1 | /* |
2 | * MPEG-H Part 2 / HEVC / H.265 HW decode acceleration through VDPAU |
3 | * |
4 | * Copyright (c) 2013 Philip Langdale |
5 | * |
6 | * This file is part of FFmpeg. |
7 | * |
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. |
12 | * |
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. |
17 | * |
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 Foundation, |
20 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | */ |
22 | |
23 | #include <vdpau/vdpau.h> |
24 | |
25 | #include "avcodec.h" |
26 | #include "internal.h" |
27 | #include "hevc_data.h" |
28 | #include "hevcdec.h" |
29 | #include "hwaccel.h" |
30 | #include "vdpau.h" |
31 | #include "vdpau_internal.h" |
32 | |
33 | static int vdpau_hevc_start_frame(AVCodecContext *avctx, |
34 | const uint8_t *buffer, uint32_t size) |
35 | { |
36 | HEVCContext *h = avctx->priv_data; |
37 | HEVCFrame *pic = h->ref; |
38 | struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; |
39 | |
40 | VdpPictureInfoHEVC *info = &pic_ctx->info.hevc; |
41 | |
42 | const HEVCSPS *sps = h->ps.sps; |
43 | const HEVCPPS *pps = h->ps.pps; |
44 | const SliceHeader *sh = &h->sh; |
45 | const ScalingList *sl = pps->scaling_list_data_present_flag ? |
46 | &pps->scaling_list : &sps->scaling_list; |
47 | |
48 | /* init VdpPictureInfoHEVC */ |
49 | |
50 | /* SPS */ |
51 | info->chroma_format_idc = sps->chroma_format_idc; |
52 | info->separate_colour_plane_flag = sps->separate_colour_plane_flag; |
53 | info->pic_width_in_luma_samples = sps->width; |
54 | info->pic_height_in_luma_samples = sps->height; |
55 | info->bit_depth_luma_minus8 = sps->bit_depth - 8; |
56 | info->bit_depth_chroma_minus8 = sps->bit_depth - 8; |
57 | info->log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_poc_lsb - 4; |
58 | /* Provide the value corresponding to the nuh_temporal_id of the frame |
59 | to be decoded. */ |
60 | info->sps_max_dec_pic_buffering_minus1 = sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering - 1; |
61 | info->log2_min_luma_coding_block_size_minus3 = sps->log2_min_cb_size - 3; |
62 | info->log2_diff_max_min_luma_coding_block_size = sps->log2_diff_max_min_coding_block_size; |
63 | info->log2_min_transform_block_size_minus2 = sps->log2_min_tb_size - 2; |
64 | info->log2_diff_max_min_transform_block_size = sps->log2_max_trafo_size - sps->log2_min_tb_size; |
65 | info->max_transform_hierarchy_depth_inter = sps->max_transform_hierarchy_depth_inter; |
66 | info->max_transform_hierarchy_depth_intra = sps->max_transform_hierarchy_depth_intra; |
67 | info->scaling_list_enabled_flag = sps->scaling_list_enable_flag; |
68 | /* Scaling lists, in diagonal order, to be used for this frame. */ |
69 | for (size_t i = 0; i < 6; i++) { |
70 | for (size_t j = 0; j < 16; j++) { |
71 | /* Scaling List for 4x4 quantization matrix, |
72 | indexed as ScalingList4x4[matrixId][i]. */ |
73 | uint8_t pos = 4 * ff_hevc_diag_scan4x4_y[j] + ff_hevc_diag_scan4x4_x[j]; |
74 | info->ScalingList4x4[i][j] = sl->sl[0][i][pos]; |
75 | } |
76 | for (size_t j = 0; j < 64; j++) { |
77 | uint8_t pos = 8 * ff_hevc_diag_scan8x8_y[j] + ff_hevc_diag_scan8x8_x[j]; |
78 | /* Scaling List for 8x8 quantization matrix, |
79 | indexed as ScalingList8x8[matrixId][i]. */ |
80 | info->ScalingList8x8[i][j] = sl->sl[1][i][pos]; |
81 | /* Scaling List for 16x16 quantization matrix, |
82 | indexed as ScalingList16x16[matrixId][i]. */ |
83 | info->ScalingList16x16[i][j] = sl->sl[2][i][pos]; |
84 | if (i < 2) { |
85 | /* Scaling List for 32x32 quantization matrix, |
86 | indexed as ScalingList32x32[matrixId][i]. */ |
87 | info->ScalingList32x32[i][j] = sl->sl[3][i * 3][pos]; |
88 | } |
89 | } |
90 | /* Scaling List DC Coefficients for 16x16, |
91 | indexed as ScalingListDCCoeff16x16[matrixId]. */ |
92 | info->ScalingListDCCoeff16x16[i] = sl->sl_dc[0][i]; |
93 | if (i < 2) { |
94 | /* Scaling List DC Coefficients for 32x32, |
95 | indexed as ScalingListDCCoeff32x32[matrixId]. */ |
96 | info->ScalingListDCCoeff32x32[i] = sl->sl_dc[1][i * 3]; |
97 | } |
98 | } |
99 | info->amp_enabled_flag = sps->amp_enabled_flag; |
100 | info->sample_adaptive_offset_enabled_flag = sps->sao_enabled; |
101 | info->pcm_enabled_flag = sps->pcm_enabled_flag; |
102 | if (info->pcm_enabled_flag) { |
103 | /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */ |
104 | info->pcm_sample_bit_depth_luma_minus1 = sps->pcm.bit_depth - 1; |
105 | /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */ |
106 | info->pcm_sample_bit_depth_chroma_minus1 = sps->pcm.bit_depth_chroma - 1; |
107 | /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */ |
108 | info->log2_min_pcm_luma_coding_block_size_minus3 = sps->pcm.log2_min_pcm_cb_size - 3; |
109 | /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */ |
110 | info->log2_diff_max_min_pcm_luma_coding_block_size = sps->pcm.log2_max_pcm_cb_size - sps->pcm.log2_min_pcm_cb_size; |
111 | /* Only needs to be set if pcm_enabled_flag is set. Ignored otherwise. */ |
112 | info->pcm_loop_filter_disabled_flag = sps->pcm.loop_filter_disable_flag; |
113 | } |
114 | /* Per spec, when zero, assume short_term_ref_pic_set_sps_flag |
115 | is also zero. */ |
116 | info->num_short_term_ref_pic_sets = sps->nb_st_rps; |
117 | info->long_term_ref_pics_present_flag = sps->long_term_ref_pics_present_flag; |
118 | /* Only needed if long_term_ref_pics_present_flag is set. Ignored |
119 | otherwise. */ |
120 | info->num_long_term_ref_pics_sps = sps->num_long_term_ref_pics_sps; |
121 | info->sps_temporal_mvp_enabled_flag = sps->sps_temporal_mvp_enabled_flag; |
122 | info->strong_intra_smoothing_enabled_flag = sps->sps_strong_intra_smoothing_enable_flag; |
123 | |
124 | /* Copy the HEVC Picture Parameter Set bitstream fields. */ |
125 | info->dependent_slice_segments_enabled_flag = pps->dependent_slice_segments_enabled_flag; |
126 | info->output_flag_present_flag = pps->output_flag_present_flag; |
127 | info->num_extra_slice_header_bits = pps->num_extra_slice_header_bits; |
128 | info->sign_data_hiding_enabled_flag = pps->sign_data_hiding_flag; |
129 | info->cabac_init_present_flag = pps->cabac_init_present_flag; |
130 | info->num_ref_idx_l0_default_active_minus1 = pps->num_ref_idx_l0_default_active - 1; |
131 | info->num_ref_idx_l1_default_active_minus1 = pps->num_ref_idx_l1_default_active - 1; |
132 | info->init_qp_minus26 = pps->pic_init_qp_minus26; |
133 | info->constrained_intra_pred_flag = pps->constrained_intra_pred_flag; |
134 | info->transform_skip_enabled_flag = pps->transform_skip_enabled_flag; |
135 | info->cu_qp_delta_enabled_flag = pps->cu_qp_delta_enabled_flag; |
136 | /* Only needed if cu_qp_delta_enabled_flag is set. Ignored otherwise. */ |
137 | info->diff_cu_qp_delta_depth = pps->diff_cu_qp_delta_depth; |
138 | info->pps_cb_qp_offset = pps->cb_qp_offset; |
139 | info->pps_cr_qp_offset = pps->cr_qp_offset; |
140 | info->pps_slice_chroma_qp_offsets_present_flag = pps->pic_slice_level_chroma_qp_offsets_present_flag; |
141 | info->weighted_pred_flag = pps->weighted_pred_flag; |
142 | info->weighted_bipred_flag = pps->weighted_bipred_flag; |
143 | info->transquant_bypass_enabled_flag = pps->transquant_bypass_enable_flag; |
144 | info->tiles_enabled_flag = pps->tiles_enabled_flag; |
145 | info->entropy_coding_sync_enabled_flag = pps->entropy_coding_sync_enabled_flag; |
146 | if (info->tiles_enabled_flag) { |
147 | /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */ |
148 | info->num_tile_columns_minus1 = pps->num_tile_columns - 1; |
149 | /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */ |
150 | info->num_tile_rows_minus1 = pps->num_tile_rows - 1; |
151 | /* Only valid if tiles_enabled_flag is set. Ignored otherwise. */ |
152 | info->uniform_spacing_flag = pps->uniform_spacing_flag; |
153 | /* Only need to set 0..num_tile_columns_minus1. The struct |
154 | definition reserves up to the maximum of 20. Invalid values are |
155 | ignored. */ |
156 | for (ssize_t i = 0; i < pps->num_tile_columns; i++) { |
157 | info->column_width_minus1[i] = pps->column_width[i] - 1; |
158 | } |
159 | /* Only need to set 0..num_tile_rows_minus1. The struct |
160 | definition reserves up to the maximum of 22. Invalid values are |
161 | ignored.*/ |
162 | for (ssize_t i = 0; i < pps->num_tile_rows; i++) { |
163 | info->row_height_minus1[i] = pps->row_height[i] - 1; |
164 | } |
165 | /* Only needed if tiles_enabled_flag is set. Invalid values are |
166 | ignored. */ |
167 | info->loop_filter_across_tiles_enabled_flag = pps->loop_filter_across_tiles_enabled_flag; |
168 | } |
169 | info->pps_loop_filter_across_slices_enabled_flag = pps->seq_loop_filter_across_slices_enabled_flag; |
170 | info->deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; |
171 | /* Only valid if deblocking_filter_control_present_flag is set. Ignored |
172 | otherwise. */ |
173 | info->deblocking_filter_override_enabled_flag = pps->deblocking_filter_override_enabled_flag; |
174 | /* Only valid if deblocking_filter_control_present_flag is set. Ignored |
175 | otherwise. */ |
176 | info->pps_deblocking_filter_disabled_flag = pps->disable_dbf; |
177 | /* Only valid if deblocking_filter_control_present_flag is set and |
178 | pps_deblocking_filter_disabled_flag is not set. Ignored otherwise.*/ |
179 | info->pps_beta_offset_div2 = pps->beta_offset / 2; |
180 | /* Only valid if deblocking_filter_control_present_flag is set and |
181 | pps_deblocking_filter_disabled_flag is not set. Ignored otherwise. */ |
182 | info->pps_tc_offset_div2 = pps->tc_offset / 2; |
183 | info->lists_modification_present_flag = pps->lists_modification_present_flag; |
184 | info->log2_parallel_merge_level_minus2 = pps->log2_parallel_merge_level - 2; |
185 | info->slice_segment_header_extension_present_flag = pps->slice_header_extension_present_flag; |
186 | |
187 | /* Set to 1 if nal_unit_type is equal to IDR_W_RADL or IDR_N_LP. |
188 | Set to zero otherwise. */ |
189 | info->IDRPicFlag = IS_IDR(h); |
190 | /* Set to 1 if nal_unit_type in the range of BLA_W_LP to |
191 | RSV_IRAP_VCL23, inclusive. Set to zero otherwise.*/ |
192 | info->RAPPicFlag = IS_IRAP(h); |
193 | /* See section 7.4.7.1 of the specification. */ |
194 | info->CurrRpsIdx = sps->nb_st_rps; |
195 | if (sh->short_term_ref_pic_set_sps_flag == 1) { |
196 | for (size_t i = 0; i < sps->nb_st_rps; i++) { |
197 | if (sh->short_term_rps == &sps->st_rps[i]) { |
198 | info->CurrRpsIdx = i; |
199 | break; |
200 | } |
201 | } |
202 | } |
203 | /* See section 7.4.7.2 of the specification. */ |
204 | info->NumPocTotalCurr = ff_hevc_frame_nb_refs(h); |
205 | if (sh->short_term_ref_pic_set_sps_flag == 0 && sh->short_term_rps) { |
206 | /* Corresponds to specification field, NumDeltaPocs[RefRpsIdx]. |
207 | Only applicable when short_term_ref_pic_set_sps_flag == 0. |
208 | Implementations will ignore this value in other cases. See 7.4.8. */ |
209 | info->NumDeltaPocsOfRefRpsIdx = sh->short_term_rps->rps_idx_num_delta_pocs; |
210 | } |
211 | /* Section 7.6.3.1 of the H.265/HEVC Specification defines the syntax of |
212 | the slice_segment_header. This header contains information that |
213 | some VDPAU implementations may choose to skip. The VDPAU API |
214 | requires client applications to track the number of bits used in the |
215 | slice header for structures associated with short term and long term |
216 | reference pictures. First, VDPAU requires the number of bits used by |
217 | the short_term_ref_pic_set array in the slice_segment_header. */ |
218 | info->NumShortTermPictureSliceHeaderBits = sh->short_term_ref_pic_set_size; |
219 | /* Second, VDPAU requires the number of bits used for long term reference |
220 | pictures in the slice_segment_header. This is equal to the number |
221 | of bits used for the contents of the block beginning with |
222 | "if(long_term_ref_pics_present_flag)". */ |
223 | info->NumLongTermPictureSliceHeaderBits = sh->long_term_ref_pic_set_size; |
224 | |
225 | /* The value of PicOrderCntVal of the picture in the access unit |
226 | containing the SEI message. The picture being decoded. */ |
227 | info->CurrPicOrderCntVal = h->poc; |
228 | |
229 | /* Slice Decoding Process - Reference Picture Sets */ |
230 | for (size_t i = 0; i < 16; i++) { |
231 | info->RefPics[i] = VDP_INVALID_HANDLE; |
232 | info->PicOrderCntVal[i] = 0; |
233 | info->IsLongTerm[i] = 0; |
234 | } |
235 | for (size_t i = 0, j = 0; i < FF_ARRAY_ELEMS(h->DPB); i++) { |
236 | const HEVCFrame *frame = &h->DPB[i]; |
237 | if (frame != h->ref && (frame->flags & (HEVC_FRAME_FLAG_LONG_REF | |
238 | HEVC_FRAME_FLAG_SHORT_REF))) { |
239 | if (j > 15) { |
240 | av_log(avctx, AV_LOG_WARNING, |
241 | "VDPAU only supports up to 16 references in the DPB. " |
242 | "This frame may not be decoded correctly.\n"); |
243 | break; |
244 | } |
245 | /* Array of video reference surfaces. |
246 | Set any unused positions to VDP_INVALID_HANDLE. */ |
247 | info->RefPics[j] = ff_vdpau_get_surface_id(frame->frame); |
248 | /* Array of picture order counts. These correspond to positions |
249 | in the RefPics array. */ |
250 | info->PicOrderCntVal[j] = frame->poc; |
251 | /* Array used to specify whether a particular RefPic is |
252 | a long term reference. A value of "1" indicates a long-term |
253 | reference. */ |
254 | // XXX: Setting this caused glitches in the nvidia implementation |
255 | // Always setting it to zero, produces correct results |
256 | //info->IsLongTerm[j] = frame->flags & HEVC_FRAME_FLAG_LONG_REF; |
257 | info->IsLongTerm[j] = 0; |
258 | j++; |
259 | } |
260 | } |
261 | /* Copy of specification field, see Section 8.3.2 of the |
262 | H.265/HEVC Specification. */ |
263 | info->NumPocStCurrBefore = h->rps[ST_CURR_BEF].nb_refs; |
264 | if (info->NumPocStCurrBefore > 8) { |
265 | av_log(avctx, AV_LOG_WARNING, |
266 | "VDPAU only supports up to 8 references in StCurrBefore. " |
267 | "This frame may not be decoded correctly.\n"); |
268 | info->NumPocStCurrBefore = 8; |
269 | } |
270 | /* Copy of specification field, see Section 8.3.2 of the |
271 | H.265/HEVC Specification. */ |
272 | info->NumPocStCurrAfter = h->rps[ST_CURR_AFT].nb_refs; |
273 | if (info->NumPocStCurrAfter > 8) { |
274 | av_log(avctx, AV_LOG_WARNING, |
275 | "VDPAU only supports up to 8 references in StCurrAfter. " |
276 | "This frame may not be decoded correctly.\n"); |
277 | info->NumPocStCurrAfter = 8; |
278 | } |
279 | /* Copy of specification field, see Section 8.3.2 of the |
280 | H.265/HEVC Specification. */ |
281 | info->NumPocLtCurr = h->rps[LT_CURR].nb_refs; |
282 | if (info->NumPocLtCurr > 8) { |
283 | av_log(avctx, AV_LOG_WARNING, |
284 | "VDPAU only supports up to 8 references in LtCurr. " |
285 | "This frame may not be decoded correctly.\n"); |
286 | info->NumPocLtCurr = 8; |
287 | } |
288 | /* Reference Picture Set list, one of the short-term RPS. These |
289 | correspond to positions in the RefPics array. */ |
290 | for (ssize_t i = 0, j = 0; i < h->rps[ST_CURR_BEF].nb_refs; i++) { |
291 | HEVCFrame *frame = h->rps[ST_CURR_BEF].ref[i]; |
292 | if (frame) { |
293 | uint8_t found = 0; |
294 | uintptr_t id = ff_vdpau_get_surface_id(frame->frame); |
295 | for (size_t k = 0; k < 16; k++) { |
296 | if (id == info->RefPics[k]) { |
297 | info->RefPicSetStCurrBefore[j] = k; |
298 | j++; |
299 | found = 1; |
300 | break; |
301 | } |
302 | } |
303 | if (!found) { |
304 | av_log(avctx, AV_LOG_WARNING, "missing surface: %p\n", |
305 | (void *)id); |
306 | } |
307 | } else { |
308 | av_log(avctx, AV_LOG_WARNING, "missing STR Before frame: %zd\n", i); |
309 | } |
310 | } |
311 | /* Reference Picture Set list, one of the short-term RPS. These |
312 | correspond to positions in the RefPics array. */ |
313 | for (ssize_t i = 0, j = 0; i < h->rps[ST_CURR_AFT].nb_refs; i++) { |
314 | HEVCFrame *frame = h->rps[ST_CURR_AFT].ref[i]; |
315 | if (frame) { |
316 | uint8_t found = 0; |
317 | uintptr_t id = ff_vdpau_get_surface_id(frame->frame); |
318 | for (size_t k = 0; k < 16; k++) { |
319 | if (id == info->RefPics[k]) { |
320 | info->RefPicSetStCurrAfter[j] = k; |
321 | j++; |
322 | found = 1; |
323 | break; |
324 | } |
325 | } |
326 | if (!found) { |
327 | av_log(avctx, AV_LOG_WARNING, "missing surface: %p\n", |
328 | (void *)id); |
329 | } |
330 | } else { |
331 | av_log(avctx, AV_LOG_WARNING, "missing STR After frame: %zd\n", i); |
332 | } |
333 | } |
334 | /* Reference Picture Set list, one of the long-term RPS. These |
335 | correspond to positions in the RefPics array. */ |
336 | for (ssize_t i = 0, j = 0; i < h->rps[LT_CURR].nb_refs; i++) { |
337 | HEVCFrame *frame = h->rps[LT_CURR].ref[i]; |
338 | if (frame) { |
339 | uint8_t found = 0; |
340 | uintptr_t id = ff_vdpau_get_surface_id(frame->frame); |
341 | for (size_t k = 0; k < 16; k++) { |
342 | if (id == info->RefPics[k]) { |
343 | info->RefPicSetLtCurr[j] = k; |
344 | j++; |
345 | found = 1; |
346 | break; |
347 | } |
348 | } |
349 | if (!found) { |
350 | av_log(avctx, AV_LOG_WARNING, "missing surface: %p\n", |
351 | (void *)id); |
352 | } |
353 | } else { |
354 | av_log(avctx, AV_LOG_WARNING, "missing LTR frame: %zd\n", i); |
355 | } |
356 | } |
357 | |
358 | return ff_vdpau_common_start_frame(pic_ctx, buffer, size); |
359 | } |
360 | |
361 | static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 }; |
362 | |
363 | static int vdpau_hevc_decode_slice(AVCodecContext *avctx, |
364 | const uint8_t *buffer, uint32_t size) |
365 | { |
366 | HEVCContext *h = avctx->priv_data; |
367 | struct vdpau_picture_context *pic_ctx = h->ref->hwaccel_picture_private; |
368 | int val; |
369 | |
370 | val = ff_vdpau_add_buffer(pic_ctx, start_code_prefix, 3); |
371 | if (val) |
372 | return val; |
373 | |
374 | val = ff_vdpau_add_buffer(pic_ctx, buffer, size); |
375 | if (val) |
376 | return val; |
377 | |
378 | return 0; |
379 | } |
380 | |
381 | static int vdpau_hevc_end_frame(AVCodecContext *avctx) |
382 | { |
383 | HEVCContext *h = avctx->priv_data; |
384 | struct vdpau_picture_context *pic_ctx = h->ref->hwaccel_picture_private; |
385 | int val; |
386 | |
387 | val = ff_vdpau_common_end_frame(avctx, h->ref->frame, pic_ctx); |
388 | if (val < 0) |
389 | return val; |
390 | |
391 | return 0; |
392 | } |
393 | |
394 | static int vdpau_hevc_init(AVCodecContext *avctx) |
395 | { |
396 | VdpDecoderProfile profile; |
397 | uint32_t level = avctx->level; |
398 | |
399 | switch (avctx->profile) { |
400 | case FF_PROFILE_HEVC_MAIN: |
401 | profile = VDP_DECODER_PROFILE_HEVC_MAIN; |
402 | break; |
403 | case FF_PROFILE_HEVC_MAIN_10: |
404 | profile = VDP_DECODER_PROFILE_HEVC_MAIN_10; |
405 | break; |
406 | case FF_PROFILE_HEVC_MAIN_STILL_PICTURE: |
407 | profile = VDP_DECODER_PROFILE_HEVC_MAIN_STILL; |
408 | break; |
409 | default: |
410 | return AVERROR(ENOTSUP); |
411 | } |
412 | |
413 | return ff_vdpau_common_init(avctx, profile, level); |
414 | } |
415 | |
416 | AVHWAccel ff_hevc_vdpau_hwaccel = { |
417 | .name = "hevc_vdpau", |
418 | .type = AVMEDIA_TYPE_VIDEO, |
419 | .id = AV_CODEC_ID_HEVC, |
420 | .pix_fmt = AV_PIX_FMT_VDPAU, |
421 | .start_frame = vdpau_hevc_start_frame, |
422 | .end_frame = vdpau_hevc_end_frame, |
423 | .decode_slice = vdpau_hevc_decode_slice, |
424 | .frame_priv_data_size = sizeof(struct vdpau_picture_context), |
425 | .init = vdpau_hevc_init, |
426 | .uninit = ff_vdpau_common_uninit, |
427 | .priv_data_size = sizeof(VDPAUContext), |
428 | .caps_internal = HWACCEL_CAP_ASYNC_SAFE, |
429 | }; |
430 |