1/* 2 * VC-1 HW decode acceleration through VA API 3 * 4 * Copyright (C) 2008-2009 Splitted-Desktop Systems 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 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21 */ 22 23#include "vaapi_internal.h" 24#include "vc1.h" 25#include "vc1data.h" 26 27/** Translate FFmpeg MV modes to VA API */ 28static int get_VAMvModeVC1(enum MVModes mv_mode) 29{ 30 switch (mv_mode) { 31 case MV_PMODE_1MV_HPEL_BILIN: return VAMvMode1MvHalfPelBilinear; 32 case MV_PMODE_1MV: return VAMvMode1Mv; 33 case MV_PMODE_1MV_HPEL: return VAMvMode1MvHalfPel; 34 case MV_PMODE_MIXED_MV: return VAMvModeMixedMv; 35 case MV_PMODE_INTENSITY_COMP: return VAMvModeIntensityCompensation; 36 } 37 return 0; 38} 39 40/** Check whether the MVTYPEMB bitplane is present */ 41static inline int vc1_has_MVTYPEMB_bitplane(VC1Context *v) 42{ 43 if (v->mv_type_is_raw) 44 return 0; 45 return v->s.pict_type == AV_PICTURE_TYPE_P && 46 (v->mv_mode == MV_PMODE_MIXED_MV || 47 (v->mv_mode == MV_PMODE_INTENSITY_COMP && 48 v->mv_mode2 == MV_PMODE_MIXED_MV)); 49} 50 51/** Check whether the SKIPMB bitplane is present */ 52static inline int vc1_has_SKIPMB_bitplane(VC1Context *v) 53{ 54 if (v->skip_is_raw) 55 return 0; 56 return v->s.pict_type == AV_PICTURE_TYPE_P || 57 (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type); 58} 59 60/** Check whether the DIRECTMB bitplane is present */ 61static inline int vc1_has_DIRECTMB_bitplane(VC1Context *v) 62{ 63 if (v->dmb_is_raw) 64 return 0; 65 return v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type; 66} 67 68/** Check whether the ACPRED bitplane is present */ 69static inline int vc1_has_ACPRED_bitplane(VC1Context *v) 70{ 71 if (v->acpred_is_raw) 72 return 0; 73 return v->profile == PROFILE_ADVANCED && 74 (v->s.pict_type == AV_PICTURE_TYPE_I || 75 (v->s.pict_type == AV_PICTURE_TYPE_B && v->bi_type)); 76} 77 78/** Check whether the OVERFLAGS bitplane is present */ 79static inline int vc1_has_OVERFLAGS_bitplane(VC1Context *v) 80{ 81 if (v->overflg_is_raw) 82 return 0; 83 return v->profile == PROFILE_ADVANCED && 84 (v->s.pict_type == AV_PICTURE_TYPE_I || 85 (v->s.pict_type == AV_PICTURE_TYPE_B && v->bi_type)) && 86 (v->overlap && v->pq <= 8) && 87 v->condover == CONDOVER_SELECT; 88} 89 90/** Reconstruct bitstream PTYPE (7.1.1.4, index into Table-35) */ 91static int vc1_get_PTYPE(VC1Context *v) 92{ 93 MpegEncContext * const s = &v->s; 94 switch (s->pict_type) { 95 case AV_PICTURE_TYPE_I: return 0; 96 case AV_PICTURE_TYPE_P: return v->p_frame_skipped ? 4 : 1; 97 case AV_PICTURE_TYPE_B: return v->bi_type ? 3 : 2; 98 } 99 return 0; 100} 101 102/** Reconstruct bitstream MVMODE (7.1.1.32) */ 103static inline VAMvModeVC1 vc1_get_MVMODE(VC1Context *v) 104{ 105 if (v->s.pict_type == AV_PICTURE_TYPE_P || 106 (v->s.pict_type == AV_PICTURE_TYPE_B && !v->bi_type)) 107 return get_VAMvModeVC1(v->mv_mode); 108 return 0; 109} 110 111/** Reconstruct bitstream MVMODE2 (7.1.1.33) */ 112static inline VAMvModeVC1 vc1_get_MVMODE2(VC1Context *v) 113{ 114 if (v->s.pict_type == AV_PICTURE_TYPE_P && v->mv_mode == MV_PMODE_INTENSITY_COMP) 115 return get_VAMvModeVC1(v->mv_mode2); 116 return 0; 117} 118 119/** Reconstruct bitstream TTFRM (7.1.1.41, Table-53) */ 120static inline int vc1_get_TTFRM(VC1Context *v) 121{ 122 switch (v->ttfrm) { 123 case TT_8X8: return 0; 124 case TT_8X4: return 1; 125 case TT_4X8: return 2; 126 case TT_4X4: return 3; 127 } 128 return 0; 129} 130 131/** Pack FFmpeg bitplanes into a VABitPlaneBuffer element */ 132static inline void vc1_pack_bitplanes(uint8_t *bitplane, int n, const uint8_t *ff_bp[3], int x, int y, int stride) 133{ 134 const int bitplane_index = n / 2; 135 const int ff_bp_index = y * stride + x; 136 uint8_t v = 0; 137 if (ff_bp[0]) 138 v = ff_bp[0][ff_bp_index]; 139 if (ff_bp[1]) 140 v |= ff_bp[1][ff_bp_index] << 1; 141 if (ff_bp[2]) 142 v |= ff_bp[2][ff_bp_index] << 2; 143 bitplane[bitplane_index] = (bitplane[bitplane_index] << 4) | v; 144} 145 146static int vaapi_vc1_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) 147{ 148 VC1Context * const v = avctx->priv_data; 149 MpegEncContext * const s = &v->s; 150 struct vaapi_context * const vactx = avctx->hwaccel_context; 151 VAPictureParameterBufferVC1 *pic_param; 152 153 av_dlog(avctx, "vaapi_vc1_start_frame()\n"); 154 155 vactx->slice_param_size = sizeof(VASliceParameterBufferVC1); 156 157 /* Fill in VAPictureParameterBufferVC1 */ 158 pic_param = ff_vaapi_alloc_pic_param(vactx, sizeof(VAPictureParameterBufferVC1)); 159 if (!pic_param) 160 return -1; 161 pic_param->forward_reference_picture = VA_INVALID_ID; 162 pic_param->backward_reference_picture = VA_INVALID_ID; 163 pic_param->inloop_decoded_picture = VA_INVALID_ID; 164 pic_param->sequence_fields.value = 0; /* reset all bits */ 165 pic_param->sequence_fields.bits.pulldown = v->broadcast; 166 pic_param->sequence_fields.bits.interlace = v->interlace; 167 pic_param->sequence_fields.bits.tfcntrflag = v->tfcntrflag; 168 pic_param->sequence_fields.bits.finterpflag = v->finterpflag; 169 pic_param->sequence_fields.bits.psf = v->psf; 170 pic_param->sequence_fields.bits.multires = v->multires; 171 pic_param->sequence_fields.bits.overlap = v->overlap; 172 pic_param->sequence_fields.bits.syncmarker = v->resync_marker; 173 pic_param->sequence_fields.bits.rangered = v->rangered; 174 pic_param->sequence_fields.bits.max_b_frames = s->avctx->max_b_frames; 175#if VA_CHECK_VERSION(0,32,0) 176 pic_param->sequence_fields.bits.profile = v->profile; 177#endif 178 pic_param->coded_width = s->avctx->coded_width; 179 pic_param->coded_height = s->avctx->coded_height; 180 pic_param->entrypoint_fields.value = 0; /* reset all bits */ 181 pic_param->entrypoint_fields.bits.broken_link = v->broken_link; 182 pic_param->entrypoint_fields.bits.closed_entry = v->closed_entry; 183 pic_param->entrypoint_fields.bits.panscan_flag = v->panscanflag; 184 pic_param->entrypoint_fields.bits.loopfilter = s->loop_filter; 185 pic_param->conditional_overlap_flag = v->condover; 186 pic_param->fast_uvmc_flag = v->fastuvmc; 187 pic_param->range_mapping_fields.value = 0; /* reset all bits */ 188 pic_param->range_mapping_fields.bits.luma_flag = v->range_mapy_flag; 189 pic_param->range_mapping_fields.bits.luma = v->range_mapy; 190 pic_param->range_mapping_fields.bits.chroma_flag = v->range_mapuv_flag; 191 pic_param->range_mapping_fields.bits.chroma = v->range_mapuv; 192 pic_param->b_picture_fraction = v->bfraction_lut_index; 193 pic_param->cbp_table = v->cbpcy_vlc ? v->cbpcy_vlc - ff_vc1_cbpcy_p_vlc : 0; 194 pic_param->mb_mode_table = 0; /* XXX: interlaced frame */ 195 pic_param->range_reduction_frame = v->rangeredfrm; 196 pic_param->rounding_control = v->rnd; 197 pic_param->post_processing = v->postproc; 198 pic_param->picture_resolution_index = v->respic; 199 pic_param->luma_scale = v->lumscale; 200 pic_param->luma_shift = v->lumshift; 201 pic_param->picture_fields.value = 0; /* reset all bits */ 202 pic_param->picture_fields.bits.picture_type = vc1_get_PTYPE(v); 203 pic_param->picture_fields.bits.frame_coding_mode = v->fcm; 204 pic_param->picture_fields.bits.top_field_first = v->tff; 205 pic_param->picture_fields.bits.is_first_field = v->fcm == 0; /* XXX: interlaced frame */ 206 pic_param->picture_fields.bits.intensity_compensation = v->mv_mode == MV_PMODE_INTENSITY_COMP; 207 pic_param->raw_coding.value = 0; /* reset all bits */ 208 pic_param->raw_coding.flags.mv_type_mb = v->mv_type_is_raw; 209 pic_param->raw_coding.flags.direct_mb = v->dmb_is_raw; 210 pic_param->raw_coding.flags.skip_mb = v->skip_is_raw; 211 pic_param->raw_coding.flags.field_tx = 0; /* XXX: interlaced frame */ 212 pic_param->raw_coding.flags.forward_mb = 0; /* XXX: interlaced frame */ 213 pic_param->raw_coding.flags.ac_pred = v->acpred_is_raw; 214 pic_param->raw_coding.flags.overflags = v->overflg_is_raw; 215 pic_param->bitplane_present.value = 0; /* reset all bits */ 216 pic_param->bitplane_present.flags.bp_mv_type_mb = vc1_has_MVTYPEMB_bitplane(v); 217 pic_param->bitplane_present.flags.bp_direct_mb = vc1_has_DIRECTMB_bitplane(v); 218 pic_param->bitplane_present.flags.bp_skip_mb = vc1_has_SKIPMB_bitplane(v); 219 pic_param->bitplane_present.flags.bp_field_tx = 0; /* XXX: interlaced frame */ 220 pic_param->bitplane_present.flags.bp_forward_mb = 0; /* XXX: interlaced frame */ 221 pic_param->bitplane_present.flags.bp_ac_pred = vc1_has_ACPRED_bitplane(v); 222 pic_param->bitplane_present.flags.bp_overflags = vc1_has_OVERFLAGS_bitplane(v); 223 pic_param->reference_fields.value = 0; /* reset all bits */ 224 pic_param->reference_fields.bits.reference_distance_flag = v->refdist_flag; 225 pic_param->reference_fields.bits.reference_distance = 0; /* XXX: interlaced frame */ 226 pic_param->reference_fields.bits.num_reference_pictures = 0; /* XXX: interlaced frame */ 227 pic_param->reference_fields.bits.reference_field_pic_indicator = 0; /* XXX: interlaced frame */ 228 pic_param->mv_fields.value = 0; /* reset all bits */ 229 pic_param->mv_fields.bits.mv_mode = vc1_get_MVMODE(v); 230 pic_param->mv_fields.bits.mv_mode2 = vc1_get_MVMODE2(v); 231 pic_param->mv_fields.bits.mv_table = s->mv_table_index; 232 pic_param->mv_fields.bits.two_mv_block_pattern_table = 0; /* XXX: interlaced frame */ 233 pic_param->mv_fields.bits.four_mv_switch = 0; /* XXX: interlaced frame */ 234 pic_param->mv_fields.bits.four_mv_block_pattern_table = 0; /* XXX: interlaced frame */ 235 pic_param->mv_fields.bits.extended_mv_flag = v->extended_mv; 236 pic_param->mv_fields.bits.extended_mv_range = v->mvrange; 237 pic_param->mv_fields.bits.extended_dmv_flag = v->extended_dmv; 238 pic_param->mv_fields.bits.extended_dmv_range = 0; /* XXX: interlaced frame */ 239 pic_param->pic_quantizer_fields.value = 0; /* reset all bits */ 240 pic_param->pic_quantizer_fields.bits.dquant = v->dquant; 241 pic_param->pic_quantizer_fields.bits.quantizer = v->quantizer_mode; 242 pic_param->pic_quantizer_fields.bits.half_qp = v->halfpq; 243 pic_param->pic_quantizer_fields.bits.pic_quantizer_scale = v->pq; 244 pic_param->pic_quantizer_fields.bits.pic_quantizer_type = v->pquantizer; 245 pic_param->pic_quantizer_fields.bits.dq_frame = v->dquantfrm; 246 pic_param->pic_quantizer_fields.bits.dq_profile = v->dqprofile; 247 pic_param->pic_quantizer_fields.bits.dq_sb_edge = v->dqprofile == DQPROFILE_SINGLE_EDGE ? v->dqsbedge : 0; 248 pic_param->pic_quantizer_fields.bits.dq_db_edge = v->dqprofile == DQPROFILE_DOUBLE_EDGES ? v->dqsbedge : 0; 249 pic_param->pic_quantizer_fields.bits.dq_binary_level = v->dqbilevel; 250 pic_param->pic_quantizer_fields.bits.alt_pic_quantizer = v->altpq; 251 pic_param->transform_fields.value = 0; /* reset all bits */ 252 pic_param->transform_fields.bits.variable_sized_transform_flag = v->vstransform; 253 pic_param->transform_fields.bits.mb_level_transform_type_flag = v->ttmbf; 254 pic_param->transform_fields.bits.frame_level_transform_type = vc1_get_TTFRM(v); 255 pic_param->transform_fields.bits.transform_ac_codingset_idx1 = v->c_ac_table_index; 256 pic_param->transform_fields.bits.transform_ac_codingset_idx2 = v->y_ac_table_index; 257 pic_param->transform_fields.bits.intra_transform_dc_table = v->s.dc_table_index; 258 259 switch (s->pict_type) { 260 case AV_PICTURE_TYPE_B: 261 pic_param->backward_reference_picture = ff_vaapi_get_surface_id(s->next_picture.f); 262 // fall-through 263 case AV_PICTURE_TYPE_P: 264 pic_param->forward_reference_picture = ff_vaapi_get_surface_id(s->last_picture.f); 265 break; 266 } 267 268 if (pic_param->bitplane_present.value) { 269 uint8_t *bitplane; 270 const uint8_t *ff_bp[3]; 271 int x, y, n; 272 273 switch (s->pict_type) { 274 case AV_PICTURE_TYPE_P: 275 ff_bp[0] = pic_param->bitplane_present.flags.bp_direct_mb ? v->direct_mb_plane : NULL; 276 ff_bp[1] = pic_param->bitplane_present.flags.bp_skip_mb ? s->mbskip_table : NULL; 277 ff_bp[2] = pic_param->bitplane_present.flags.bp_mv_type_mb ? v->mv_type_mb_plane : NULL; 278 break; 279 case AV_PICTURE_TYPE_B: 280 if (!v->bi_type) { 281 ff_bp[0] = pic_param->bitplane_present.flags.bp_direct_mb ? v->direct_mb_plane : NULL; 282 ff_bp[1] = pic_param->bitplane_present.flags.bp_skip_mb ? s->mbskip_table : NULL; 283 ff_bp[2] = NULL; /* XXX: interlaced frame (FORWARD plane) */ 284 break; 285 } 286 /* fall-through (BI-type) */ 287 case AV_PICTURE_TYPE_I: 288 ff_bp[0] = NULL; /* XXX: interlaced frame (FIELDTX plane) */ 289 ff_bp[1] = pic_param->bitplane_present.flags.bp_ac_pred ? v->acpred_plane : NULL; 290 ff_bp[2] = pic_param->bitplane_present.flags.bp_overflags ? v->over_flags_plane : NULL; 291 break; 292 default: 293 ff_bp[0] = NULL; 294 ff_bp[1] = NULL; 295 ff_bp[2] = NULL; 296 break; 297 } 298 299 bitplane = ff_vaapi_alloc_bitplane(vactx, (s->mb_width * s->mb_height + 1) / 2); 300 if (!bitplane) 301 return -1; 302 303 n = 0; 304 for (y = 0; y < s->mb_height; y++) 305 for (x = 0; x < s->mb_width; x++, n++) 306 vc1_pack_bitplanes(bitplane, n, ff_bp, x, y, s->mb_stride); 307 if (n & 1) /* move last nibble to the high order */ 308 bitplane[n/2] <<= 4; 309 } 310 return 0; 311} 312 313static int vaapi_vc1_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) 314{ 315 VC1Context * const v = avctx->priv_data; 316 MpegEncContext * const s = &v->s; 317 VASliceParameterBufferVC1 *slice_param; 318 319 av_dlog(avctx, "vaapi_vc1_decode_slice(): buffer %p, size %d\n", buffer, size); 320 321 /* Current bit buffer is beyond any marker for VC-1, so skip it */ 322 if (avctx->codec_id == AV_CODEC_ID_VC1 && IS_MARKER(AV_RB32(buffer))) { 323 buffer += 4; 324 size -= 4; 325 } 326 327 /* Fill in VASliceParameterBufferVC1 */ 328 slice_param = (VASliceParameterBufferVC1 *)ff_vaapi_alloc_slice(avctx->hwaccel_context, buffer, size); 329 if (!slice_param) 330 return -1; 331 slice_param->macroblock_offset = get_bits_count(&s->gb); 332 slice_param->slice_vertical_position = s->mb_y; 333 return 0; 334} 335 336#if CONFIG_WMV3_VAAPI_HWACCEL 337AVHWAccel ff_wmv3_vaapi_hwaccel = { 338 .name = "wmv3_vaapi", 339 .type = AVMEDIA_TYPE_VIDEO, 340 .id = AV_CODEC_ID_WMV3, 341 .pix_fmt = AV_PIX_FMT_VAAPI_VLD, 342 .start_frame = vaapi_vc1_start_frame, 343 .end_frame = ff_vaapi_mpeg_end_frame, 344 .decode_slice = vaapi_vc1_decode_slice, 345}; 346#endif 347 348AVHWAccel ff_vc1_vaapi_hwaccel = { 349 .name = "vc1_vaapi", 350 .type = AVMEDIA_TYPE_VIDEO, 351 .id = AV_CODEC_ID_VC1, 352 .pix_fmt = AV_PIX_FMT_VAAPI_VLD, 353 .start_frame = vaapi_vc1_start_frame, 354 .end_frame = ff_vaapi_mpeg_end_frame, 355 .decode_slice = vaapi_vc1_decode_slice, 356}; 357