1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * This file is part of FFmpeg. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cabdff1aSopenharmony_ci * Lesser General Public License for more details. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 17cabdff1aSopenharmony_ci */ 18cabdff1aSopenharmony_ci 19cabdff1aSopenharmony_ci#include <va/va.h> 20cabdff1aSopenharmony_ci#include <va/va_dec_vp8.h> 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci#include "hwconfig.h" 23cabdff1aSopenharmony_ci#include "vaapi_decode.h" 24cabdff1aSopenharmony_ci#include "vp8.h" 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_cistatic VASurfaceID vaapi_vp8_surface_id(VP8Frame *vf) 27cabdff1aSopenharmony_ci{ 28cabdff1aSopenharmony_ci if (vf) 29cabdff1aSopenharmony_ci return ff_vaapi_get_surface_id(vf->tf.f); 30cabdff1aSopenharmony_ci else 31cabdff1aSopenharmony_ci return VA_INVALID_SURFACE; 32cabdff1aSopenharmony_ci} 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_cistatic int vaapi_vp8_start_frame(AVCodecContext *avctx, 35cabdff1aSopenharmony_ci av_unused const uint8_t *buffer, 36cabdff1aSopenharmony_ci av_unused uint32_t size) 37cabdff1aSopenharmony_ci{ 38cabdff1aSopenharmony_ci const VP8Context *s = avctx->priv_data; 39cabdff1aSopenharmony_ci VAAPIDecodePicture *pic = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; 40cabdff1aSopenharmony_ci VAPictureParameterBufferVP8 pp; 41cabdff1aSopenharmony_ci VAProbabilityDataBufferVP8 prob; 42cabdff1aSopenharmony_ci VAIQMatrixBufferVP8 quant; 43cabdff1aSopenharmony_ci int err, i, j, k; 44cabdff1aSopenharmony_ci 45cabdff1aSopenharmony_ci pic->output_surface = vaapi_vp8_surface_id(s->framep[VP56_FRAME_CURRENT]); 46cabdff1aSopenharmony_ci 47cabdff1aSopenharmony_ci pp = (VAPictureParameterBufferVP8) { 48cabdff1aSopenharmony_ci .frame_width = avctx->width, 49cabdff1aSopenharmony_ci .frame_height = avctx->height, 50cabdff1aSopenharmony_ci 51cabdff1aSopenharmony_ci .last_ref_frame = vaapi_vp8_surface_id(s->framep[VP56_FRAME_PREVIOUS]), 52cabdff1aSopenharmony_ci .golden_ref_frame = vaapi_vp8_surface_id(s->framep[VP56_FRAME_GOLDEN]), 53cabdff1aSopenharmony_ci .alt_ref_frame = vaapi_vp8_surface_id(s->framep[VP56_FRAME_GOLDEN2]), 54cabdff1aSopenharmony_ci .out_of_loop_frame = VA_INVALID_SURFACE, 55cabdff1aSopenharmony_ci 56cabdff1aSopenharmony_ci .pic_fields.bits = { 57cabdff1aSopenharmony_ci .key_frame = !s->keyframe, 58cabdff1aSopenharmony_ci .version = s->profile, 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci .segmentation_enabled = s->segmentation.enabled, 61cabdff1aSopenharmony_ci .update_mb_segmentation_map = s->segmentation.update_map, 62cabdff1aSopenharmony_ci .update_segment_feature_data = s->segmentation.update_feature_data, 63cabdff1aSopenharmony_ci 64cabdff1aSopenharmony_ci .filter_type = s->filter.simple, 65cabdff1aSopenharmony_ci .sharpness_level = s->filter.sharpness, 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci .loop_filter_adj_enable = s->lf_delta.enabled, 68cabdff1aSopenharmony_ci .mode_ref_lf_delta_update = s->lf_delta.update, 69cabdff1aSopenharmony_ci 70cabdff1aSopenharmony_ci .sign_bias_golden = s->sign_bias[VP56_FRAME_GOLDEN], 71cabdff1aSopenharmony_ci .sign_bias_alternate = s->sign_bias[VP56_FRAME_GOLDEN2], 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci .mb_no_coeff_skip = s->mbskip_enabled, 74cabdff1aSopenharmony_ci .loop_filter_disable = s->filter.level == 0, 75cabdff1aSopenharmony_ci }, 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci .prob_skip_false = s->prob->mbskip, 78cabdff1aSopenharmony_ci .prob_intra = s->prob->intra, 79cabdff1aSopenharmony_ci .prob_last = s->prob->last, 80cabdff1aSopenharmony_ci .prob_gf = s->prob->golden, 81cabdff1aSopenharmony_ci }; 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) 84cabdff1aSopenharmony_ci pp.mb_segment_tree_probs[i] = s->prob->segmentid[i]; 85cabdff1aSopenharmony_ci 86cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 87cabdff1aSopenharmony_ci if (s->segmentation.enabled) { 88cabdff1aSopenharmony_ci pp.loop_filter_level[i] = s->segmentation.filter_level[i]; 89cabdff1aSopenharmony_ci if (!s->segmentation.absolute_vals) 90cabdff1aSopenharmony_ci pp.loop_filter_level[i] += s->filter.level; 91cabdff1aSopenharmony_ci } else { 92cabdff1aSopenharmony_ci pp.loop_filter_level[i] = s->filter.level; 93cabdff1aSopenharmony_ci } 94cabdff1aSopenharmony_ci pp.loop_filter_level[i] = av_clip_uintp2(pp.loop_filter_level[i], 6); 95cabdff1aSopenharmony_ci } 96cabdff1aSopenharmony_ci 97cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 98cabdff1aSopenharmony_ci pp.loop_filter_deltas_ref_frame[i] = s->lf_delta.ref[i]; 99cabdff1aSopenharmony_ci pp.loop_filter_deltas_mode[i] = s->lf_delta.mode[i + 4]; 100cabdff1aSopenharmony_ci } 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci if (s->keyframe) { 103cabdff1aSopenharmony_ci static const uint8_t keyframe_y_mode_probs[4] = { 104cabdff1aSopenharmony_ci 145, 156, 163, 128 105cabdff1aSopenharmony_ci }; 106cabdff1aSopenharmony_ci static const uint8_t keyframe_uv_mode_probs[3] = { 107cabdff1aSopenharmony_ci 142, 114, 183 108cabdff1aSopenharmony_ci }; 109cabdff1aSopenharmony_ci memcpy(pp.y_mode_probs, keyframe_y_mode_probs, 4); 110cabdff1aSopenharmony_ci memcpy(pp.uv_mode_probs, keyframe_uv_mode_probs, 3); 111cabdff1aSopenharmony_ci } else { 112cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) 113cabdff1aSopenharmony_ci pp.y_mode_probs[i] = s->prob->pred16x16[i]; 114cabdff1aSopenharmony_ci for (i = 0; i < 3; i++) 115cabdff1aSopenharmony_ci pp.uv_mode_probs[i] = s->prob->pred8x8c[i]; 116cabdff1aSopenharmony_ci } 117cabdff1aSopenharmony_ci for (i = 0; i < 2; i++) 118cabdff1aSopenharmony_ci for (j = 0; j < 19; j++) 119cabdff1aSopenharmony_ci pp.mv_probs[i][j] = s->prob->mvc[i][j]; 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_ci pp.bool_coder_ctx.range = s->coder_state_at_header_end.range; 122cabdff1aSopenharmony_ci pp.bool_coder_ctx.value = s->coder_state_at_header_end.value; 123cabdff1aSopenharmony_ci pp.bool_coder_ctx.count = s->coder_state_at_header_end.bit_count; 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci err = ff_vaapi_decode_make_param_buffer(avctx, pic, 126cabdff1aSopenharmony_ci VAPictureParameterBufferType, 127cabdff1aSopenharmony_ci &pp, sizeof(pp)); 128cabdff1aSopenharmony_ci if (err < 0) 129cabdff1aSopenharmony_ci goto fail; 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 132cabdff1aSopenharmony_ci for (j = 0; j < 8; j++) { 133cabdff1aSopenharmony_ci static const int coeff_bands_inverse[8] = { 134cabdff1aSopenharmony_ci 0, 1, 2, 3, 5, 6, 4, 15 135cabdff1aSopenharmony_ci }; 136cabdff1aSopenharmony_ci int coeff_pos = coeff_bands_inverse[j]; 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci for (k = 0; k < 3; k++) { 139cabdff1aSopenharmony_ci memcpy(prob.dct_coeff_probs[i][j][k], 140cabdff1aSopenharmony_ci s->prob->token[i][coeff_pos][k], 11); 141cabdff1aSopenharmony_ci } 142cabdff1aSopenharmony_ci } 143cabdff1aSopenharmony_ci } 144cabdff1aSopenharmony_ci 145cabdff1aSopenharmony_ci err = ff_vaapi_decode_make_param_buffer(avctx, pic, 146cabdff1aSopenharmony_ci VAProbabilityBufferType, 147cabdff1aSopenharmony_ci &prob, sizeof(prob)); 148cabdff1aSopenharmony_ci if (err < 0) 149cabdff1aSopenharmony_ci goto fail; 150cabdff1aSopenharmony_ci 151cabdff1aSopenharmony_ci for (i = 0; i < 4; i++) { 152cabdff1aSopenharmony_ci int base_qi = s->segmentation.base_quant[i]; 153cabdff1aSopenharmony_ci if (!s->segmentation.absolute_vals) 154cabdff1aSopenharmony_ci base_qi += s->quant.yac_qi; 155cabdff1aSopenharmony_ci 156cabdff1aSopenharmony_ci quant.quantization_index[i][0] = av_clip_uintp2(base_qi, 7); 157cabdff1aSopenharmony_ci quant.quantization_index[i][1] = av_clip_uintp2(base_qi + s->quant.ydc_delta, 7); 158cabdff1aSopenharmony_ci quant.quantization_index[i][2] = av_clip_uintp2(base_qi + s->quant.y2dc_delta, 7); 159cabdff1aSopenharmony_ci quant.quantization_index[i][3] = av_clip_uintp2(base_qi + s->quant.y2ac_delta, 7); 160cabdff1aSopenharmony_ci quant.quantization_index[i][4] = av_clip_uintp2(base_qi + s->quant.uvdc_delta, 7); 161cabdff1aSopenharmony_ci quant.quantization_index[i][5] = av_clip_uintp2(base_qi + s->quant.uvac_delta, 7); 162cabdff1aSopenharmony_ci } 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_ci err = ff_vaapi_decode_make_param_buffer(avctx, pic, 165cabdff1aSopenharmony_ci VAIQMatrixBufferType, 166cabdff1aSopenharmony_ci &quant, sizeof(quant)); 167cabdff1aSopenharmony_ci if (err < 0) 168cabdff1aSopenharmony_ci goto fail; 169cabdff1aSopenharmony_ci 170cabdff1aSopenharmony_ci return 0; 171cabdff1aSopenharmony_ci 172cabdff1aSopenharmony_cifail: 173cabdff1aSopenharmony_ci ff_vaapi_decode_cancel(avctx, pic); 174cabdff1aSopenharmony_ci return err; 175cabdff1aSopenharmony_ci} 176cabdff1aSopenharmony_ci 177cabdff1aSopenharmony_cistatic int vaapi_vp8_end_frame(AVCodecContext *avctx) 178cabdff1aSopenharmony_ci{ 179cabdff1aSopenharmony_ci const VP8Context *s = avctx->priv_data; 180cabdff1aSopenharmony_ci VAAPIDecodePicture *pic = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; 181cabdff1aSopenharmony_ci 182cabdff1aSopenharmony_ci return ff_vaapi_decode_issue(avctx, pic); 183cabdff1aSopenharmony_ci} 184cabdff1aSopenharmony_ci 185cabdff1aSopenharmony_cistatic int vaapi_vp8_decode_slice(AVCodecContext *avctx, 186cabdff1aSopenharmony_ci const uint8_t *buffer, 187cabdff1aSopenharmony_ci uint32_t size) 188cabdff1aSopenharmony_ci{ 189cabdff1aSopenharmony_ci const VP8Context *s = avctx->priv_data; 190cabdff1aSopenharmony_ci VAAPIDecodePicture *pic = s->framep[VP56_FRAME_CURRENT]->hwaccel_picture_private; 191cabdff1aSopenharmony_ci VASliceParameterBufferVP8 sp; 192cabdff1aSopenharmony_ci int err, i; 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_ci unsigned int header_size = 3 + 7 * s->keyframe; 195cabdff1aSopenharmony_ci const uint8_t *data = buffer + header_size; 196cabdff1aSopenharmony_ci unsigned int data_size = size - header_size; 197cabdff1aSopenharmony_ci 198cabdff1aSopenharmony_ci sp = (VASliceParameterBufferVP8) { 199cabdff1aSopenharmony_ci .slice_data_size = data_size, 200cabdff1aSopenharmony_ci .slice_data_offset = 0, 201cabdff1aSopenharmony_ci .slice_data_flag = VA_SLICE_DATA_FLAG_ALL, 202cabdff1aSopenharmony_ci 203cabdff1aSopenharmony_ci .macroblock_offset = (8 * (s->coder_state_at_header_end.input - data) - 204cabdff1aSopenharmony_ci s->coder_state_at_header_end.bit_count - 8), 205cabdff1aSopenharmony_ci .num_of_partitions = s->num_coeff_partitions + 1, 206cabdff1aSopenharmony_ci }; 207cabdff1aSopenharmony_ci 208cabdff1aSopenharmony_ci sp.partition_size[0] = s->header_partition_size - ((sp.macroblock_offset + 7) / 8); 209cabdff1aSopenharmony_ci for (i = 0; i < 8; i++) 210cabdff1aSopenharmony_ci sp.partition_size[i+1] = s->coeff_partition_size[i]; 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci err = ff_vaapi_decode_make_slice_buffer(avctx, pic, &sp, sizeof(sp), data, data_size); 213cabdff1aSopenharmony_ci if (err) 214cabdff1aSopenharmony_ci goto fail; 215cabdff1aSopenharmony_ci 216cabdff1aSopenharmony_ci return 0; 217cabdff1aSopenharmony_ci 218cabdff1aSopenharmony_cifail: 219cabdff1aSopenharmony_ci ff_vaapi_decode_cancel(avctx, pic); 220cabdff1aSopenharmony_ci return err; 221cabdff1aSopenharmony_ci} 222cabdff1aSopenharmony_ci 223cabdff1aSopenharmony_ciconst AVHWAccel ff_vp8_vaapi_hwaccel = { 224cabdff1aSopenharmony_ci .name = "vp8_vaapi", 225cabdff1aSopenharmony_ci .type = AVMEDIA_TYPE_VIDEO, 226cabdff1aSopenharmony_ci .id = AV_CODEC_ID_VP8, 227cabdff1aSopenharmony_ci .pix_fmt = AV_PIX_FMT_VAAPI, 228cabdff1aSopenharmony_ci .start_frame = &vaapi_vp8_start_frame, 229cabdff1aSopenharmony_ci .end_frame = &vaapi_vp8_end_frame, 230cabdff1aSopenharmony_ci .decode_slice = &vaapi_vp8_decode_slice, 231cabdff1aSopenharmony_ci .frame_priv_data_size = sizeof(VAAPIDecodePicture), 232cabdff1aSopenharmony_ci .init = &ff_vaapi_decode_init, 233cabdff1aSopenharmony_ci .uninit = &ff_vaapi_decode_uninit, 234cabdff1aSopenharmony_ci .frame_params = &ff_vaapi_common_frame_params, 235cabdff1aSopenharmony_ci .priv_data_size = sizeof(VAAPIDecodeContext), 236cabdff1aSopenharmony_ci .caps_internal = HWACCEL_CAP_ASYNC_SAFE, 237cabdff1aSopenharmony_ci}; 238