2 * This file is part of FFmpeg.
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <va/va_dec_vp8.h>
22 #include "hwaccel_internal.h"
23 #include "vaapi_decode.h"
26 static VASurfaceID
vaapi_vp8_surface_id(VP8Frame
*vf
)
29 return ff_vaapi_get_surface_id(vf
->tf
.f
);
31 return VA_INVALID_SURFACE
;
34 static int vaapi_vp8_start_frame(AVCodecContext
*avctx
,
35 av_unused
const uint8_t *buffer
,
36 av_unused
uint32_t size
)
38 const VP8Context
*s
= avctx
->priv_data
;
39 VAAPIDecodePicture
*pic
= s
->framep
[VP8_FRAME_CURRENT
]->hwaccel_picture_private
;
40 VAPictureParameterBufferVP8 pp
;
41 VAProbabilityDataBufferVP8 prob
;
42 VAIQMatrixBufferVP8 quant
;
45 pic
->output_surface
= vaapi_vp8_surface_id(s
->framep
[VP8_FRAME_CURRENT
]);
47 pp
= (VAPictureParameterBufferVP8
) {
48 .frame_width
= avctx
->width
,
49 .frame_height
= avctx
->height
,
51 .last_ref_frame
= vaapi_vp8_surface_id(s
->framep
[VP8_FRAME_PREVIOUS
]),
52 .golden_ref_frame
= vaapi_vp8_surface_id(s
->framep
[VP8_FRAME_GOLDEN
]),
53 .alt_ref_frame
= vaapi_vp8_surface_id(s
->framep
[VP8_FRAME_ALTREF
]),
54 .out_of_loop_frame
= VA_INVALID_SURFACE
,
57 .key_frame
= !s
->keyframe
,
58 .version
= s
->profile
,
60 .segmentation_enabled
= s
->segmentation
.enabled
,
61 .update_mb_segmentation_map
= s
->segmentation
.update_map
,
62 .update_segment_feature_data
= s
->segmentation
.update_feature_data
,
64 .filter_type
= s
->filter
.simple
,
65 .sharpness_level
= s
->filter
.sharpness
,
67 .loop_filter_adj_enable
= s
->lf_delta
.enabled
,
68 .mode_ref_lf_delta_update
= s
->lf_delta
.update
,
70 .sign_bias_golden
= s
->sign_bias
[VP8_FRAME_GOLDEN
],
71 .sign_bias_alternate
= s
->sign_bias
[VP8_FRAME_ALTREF
],
73 .mb_no_coeff_skip
= s
->mbskip_enabled
,
74 .loop_filter_disable
= s
->filter
.level
== 0,
77 .prob_skip_false
= s
->prob
->mbskip
,
78 .prob_intra
= s
->prob
->intra
,
79 .prob_last
= s
->prob
->last
,
80 .prob_gf
= s
->prob
->golden
,
83 for (i
= 0; i
< 3; i
++)
84 pp
.mb_segment_tree_probs
[i
] = s
->prob
->segmentid
[i
];
86 for (i
= 0; i
< 4; i
++) {
87 if (s
->segmentation
.enabled
) {
88 pp
.loop_filter_level
[i
] = s
->segmentation
.filter_level
[i
];
89 if (!s
->segmentation
.absolute_vals
)
90 pp
.loop_filter_level
[i
] += s
->filter
.level
;
92 pp
.loop_filter_level
[i
] = s
->filter
.level
;
94 pp
.loop_filter_level
[i
] = av_clip_uintp2(pp
.loop_filter_level
[i
], 6);
97 for (i
= 0; i
< 4; i
++) {
98 pp
.loop_filter_deltas_ref_frame
[i
] = s
->lf_delta
.ref
[i
];
99 pp
.loop_filter_deltas_mode
[i
] = s
->lf_delta
.mode
[i
+ 4];
103 static const uint8_t keyframe_y_mode_probs
[4] = {
106 static const uint8_t keyframe_uv_mode_probs
[3] = {
109 memcpy(pp
.y_mode_probs
, keyframe_y_mode_probs
, 4);
110 memcpy(pp
.uv_mode_probs
, keyframe_uv_mode_probs
, 3);
112 for (i
= 0; i
< 4; i
++)
113 pp
.y_mode_probs
[i
] = s
->prob
->pred16x16
[i
];
114 for (i
= 0; i
< 3; i
++)
115 pp
.uv_mode_probs
[i
] = s
->prob
->pred8x8c
[i
];
117 for (i
= 0; i
< 2; i
++)
118 for (j
= 0; j
< 19; j
++)
119 pp
.mv_probs
[i
][j
] = s
->prob
->mvc
[i
][j
];
121 pp
.bool_coder_ctx
.range
= s
->coder_state_at_header_end
.range
;
122 pp
.bool_coder_ctx
.value
= s
->coder_state_at_header_end
.value
;
123 pp
.bool_coder_ctx
.count
= s
->coder_state_at_header_end
.bit_count
;
125 err
= ff_vaapi_decode_make_param_buffer(avctx
, pic
,
126 VAPictureParameterBufferType
,
131 for (i
= 0; i
< 4; i
++) {
132 for (j
= 0; j
< 8; j
++) {
133 static const int coeff_bands_inverse
[8] = {
134 0, 1, 2, 3, 5, 6, 4, 15
136 int coeff_pos
= coeff_bands_inverse
[j
];
138 for (k
= 0; k
< 3; k
++) {
139 memcpy(prob
.dct_coeff_probs
[i
][j
][k
],
140 s
->prob
->token
[i
][coeff_pos
][k
], 11);
145 err
= ff_vaapi_decode_make_param_buffer(avctx
, pic
,
146 VAProbabilityBufferType
,
147 &prob
, sizeof(prob
));
151 for (i
= 0; i
< 4; i
++) {
152 int base_qi
= s
->segmentation
.base_quant
[i
];
153 if (!s
->segmentation
.absolute_vals
)
154 base_qi
+= s
->quant
.yac_qi
;
156 quant
.quantization_index
[i
][0] = av_clip_uintp2(base_qi
, 7);
157 quant
.quantization_index
[i
][1] = av_clip_uintp2(base_qi
+ s
->quant
.ydc_delta
, 7);
158 quant
.quantization_index
[i
][2] = av_clip_uintp2(base_qi
+ s
->quant
.y2dc_delta
, 7);
159 quant
.quantization_index
[i
][3] = av_clip_uintp2(base_qi
+ s
->quant
.y2ac_delta
, 7);
160 quant
.quantization_index
[i
][4] = av_clip_uintp2(base_qi
+ s
->quant
.uvdc_delta
, 7);
161 quant
.quantization_index
[i
][5] = av_clip_uintp2(base_qi
+ s
->quant
.uvac_delta
, 7);
164 err
= ff_vaapi_decode_make_param_buffer(avctx
, pic
,
165 VAIQMatrixBufferType
,
166 &quant
, sizeof(quant
));
173 ff_vaapi_decode_cancel(avctx
, pic
);
177 static int vaapi_vp8_end_frame(AVCodecContext
*avctx
)
179 const VP8Context
*s
= avctx
->priv_data
;
180 VAAPIDecodePicture
*pic
= s
->framep
[VP8_FRAME_CURRENT
]->hwaccel_picture_private
;
182 return ff_vaapi_decode_issue(avctx
, pic
);
185 static int vaapi_vp8_decode_slice(AVCodecContext
*avctx
,
186 const uint8_t *buffer
,
189 const VP8Context
*s
= avctx
->priv_data
;
190 VAAPIDecodePicture
*pic
= s
->framep
[VP8_FRAME_CURRENT
]->hwaccel_picture_private
;
191 VASliceParameterBufferVP8 sp
;
194 unsigned int header_size
= 3 + 7 * s
->keyframe
;
195 const uint8_t *data
= buffer
+ header_size
;
196 unsigned int data_size
= size
- header_size
;
198 sp
= (VASliceParameterBufferVP8
) {
199 .slice_data_size
= data_size
,
200 .slice_data_offset
= 0,
201 .slice_data_flag
= VA_SLICE_DATA_FLAG_ALL
,
203 .macroblock_offset
= (8 * (s
->coder_state_at_header_end
.input
- data
) -
204 s
->coder_state_at_header_end
.bit_count
- 8),
205 .num_of_partitions
= s
->num_coeff_partitions
+ 1,
208 sp
.partition_size
[0] = s
->header_partition_size
- ((sp
.macroblock_offset
+ 7) / 8);
209 for (i
= 0; i
< 8; i
++)
210 sp
.partition_size
[i
+1] = s
->coeff_partition_size
[i
];
212 err
= ff_vaapi_decode_make_slice_buffer(avctx
, pic
, &sp
, sizeof(sp
), data
, data_size
);
219 ff_vaapi_decode_cancel(avctx
, pic
);
223 const FFHWAccel ff_vp8_vaapi_hwaccel
= {
224 .p
.name
= "vp8_vaapi",
225 .p
.type
= AVMEDIA_TYPE_VIDEO
,
226 .p
.id
= AV_CODEC_ID_VP8
,
227 .p
.pix_fmt
= AV_PIX_FMT_VAAPI
,
228 .start_frame
= &vaapi_vp8_start_frame
,
229 .end_frame
= &vaapi_vp8_end_frame
,
230 .decode_slice
= &vaapi_vp8_decode_slice
,
231 .frame_priv_data_size
= sizeof(VAAPIDecodePicture
),
232 .init
= &ff_vaapi_decode_init
,
233 .uninit
= &ff_vaapi_decode_uninit
,
234 .frame_params
= &ff_vaapi_common_frame_params
,
235 .priv_data_size
= sizeof(VAAPIDecodeContext
),
236 .caps_internal
= HWACCEL_CAP_ASYNC_SAFE
,