1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * MPEG-4 Part 10 / AVC / H.264 HW decode acceleration through VDPAU 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (c) 2008 NVIDIA 5cabdff1aSopenharmony_ci * Copyright (c) 2013 Rémi Denis-Courmont 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * This file is part of FFmpeg. 8cabdff1aSopenharmony_ci * 9cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 10cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 11cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 12cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 13cabdff1aSopenharmony_ci * 14cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 15cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 16cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17cabdff1aSopenharmony_ci * Lesser General Public License for more details. 18cabdff1aSopenharmony_ci * 19cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 20cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software Foundation, 21cabdff1aSopenharmony_ci * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 22cabdff1aSopenharmony_ci */ 23cabdff1aSopenharmony_ci 24cabdff1aSopenharmony_ci#include <vdpau/vdpau.h> 25cabdff1aSopenharmony_ci 26cabdff1aSopenharmony_ci#include "avcodec.h" 27cabdff1aSopenharmony_ci#include "h264dec.h" 28cabdff1aSopenharmony_ci#include "h264_ps.h" 29cabdff1aSopenharmony_ci#include "hwconfig.h" 30cabdff1aSopenharmony_ci#include "mpegutils.h" 31cabdff1aSopenharmony_ci#include "vdpau.h" 32cabdff1aSopenharmony_ci#include "vdpau_internal.h" 33cabdff1aSopenharmony_ci 34cabdff1aSopenharmony_cistatic int32_t h264_foc(int foc) 35cabdff1aSopenharmony_ci{ 36cabdff1aSopenharmony_ci if (foc == INT_MAX) 37cabdff1aSopenharmony_ci foc = 0; 38cabdff1aSopenharmony_ci return foc; 39cabdff1aSopenharmony_ci} 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_cistatic void vdpau_h264_clear_rf(VdpReferenceFrameH264 *rf) 42cabdff1aSopenharmony_ci{ 43cabdff1aSopenharmony_ci rf->surface = VDP_INVALID_HANDLE; 44cabdff1aSopenharmony_ci rf->is_long_term = VDP_FALSE; 45cabdff1aSopenharmony_ci rf->top_is_reference = VDP_FALSE; 46cabdff1aSopenharmony_ci rf->bottom_is_reference = VDP_FALSE; 47cabdff1aSopenharmony_ci rf->field_order_cnt[0] = 0; 48cabdff1aSopenharmony_ci rf->field_order_cnt[1] = 0; 49cabdff1aSopenharmony_ci rf->frame_idx = 0; 50cabdff1aSopenharmony_ci} 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_cistatic void vdpau_h264_set_rf(VdpReferenceFrameH264 *rf, H264Picture *pic, 53cabdff1aSopenharmony_ci int pic_structure) 54cabdff1aSopenharmony_ci{ 55cabdff1aSopenharmony_ci VdpVideoSurface surface = ff_vdpau_get_surface_id(pic->f); 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_ci if (pic_structure == 0) 58cabdff1aSopenharmony_ci pic_structure = pic->reference; 59cabdff1aSopenharmony_ci 60cabdff1aSopenharmony_ci rf->surface = surface; 61cabdff1aSopenharmony_ci rf->is_long_term = pic->reference && pic->long_ref; 62cabdff1aSopenharmony_ci rf->top_is_reference = (pic_structure & PICT_TOP_FIELD) != 0; 63cabdff1aSopenharmony_ci rf->bottom_is_reference = (pic_structure & PICT_BOTTOM_FIELD) != 0; 64cabdff1aSopenharmony_ci rf->field_order_cnt[0] = h264_foc(pic->field_poc[0]); 65cabdff1aSopenharmony_ci rf->field_order_cnt[1] = h264_foc(pic->field_poc[1]); 66cabdff1aSopenharmony_ci rf->frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num; 67cabdff1aSopenharmony_ci} 68cabdff1aSopenharmony_ci 69cabdff1aSopenharmony_cistatic void vdpau_h264_set_reference_frames(AVCodecContext *avctx) 70cabdff1aSopenharmony_ci{ 71cabdff1aSopenharmony_ci H264Context * const h = avctx->priv_data; 72cabdff1aSopenharmony_ci struct vdpau_picture_context *pic_ctx = h->cur_pic_ptr->hwaccel_picture_private; 73cabdff1aSopenharmony_ci VdpPictureInfoH264 *info = &pic_ctx->info.h264; 74cabdff1aSopenharmony_ci int list; 75cabdff1aSopenharmony_ci 76cabdff1aSopenharmony_ci VdpReferenceFrameH264 *rf = &info->referenceFrames[0]; 77cabdff1aSopenharmony_ci#define H264_RF_COUNT FF_ARRAY_ELEMS(info->referenceFrames) 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_ci for (list = 0; list < 2; ++list) { 80cabdff1aSopenharmony_ci H264Picture **lp = list ? h->long_ref : h->short_ref; 81cabdff1aSopenharmony_ci int i, ls = list ? 16 : h->short_ref_count; 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci for (i = 0; i < ls; ++i) { 84cabdff1aSopenharmony_ci H264Picture *pic = lp[i]; 85cabdff1aSopenharmony_ci VdpReferenceFrameH264 *rf2; 86cabdff1aSopenharmony_ci VdpVideoSurface surface_ref; 87cabdff1aSopenharmony_ci int pic_frame_idx; 88cabdff1aSopenharmony_ci 89cabdff1aSopenharmony_ci if (!pic || !pic->reference) 90cabdff1aSopenharmony_ci continue; 91cabdff1aSopenharmony_ci pic_frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num; 92cabdff1aSopenharmony_ci surface_ref = ff_vdpau_get_surface_id(pic->f); 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ci rf2 = &info->referenceFrames[0]; 95cabdff1aSopenharmony_ci while (rf2 != rf) { 96cabdff1aSopenharmony_ci if ((rf2->surface == surface_ref) && 97cabdff1aSopenharmony_ci (rf2->is_long_term == pic->long_ref) && 98cabdff1aSopenharmony_ci (rf2->frame_idx == pic_frame_idx)) 99cabdff1aSopenharmony_ci break; 100cabdff1aSopenharmony_ci ++rf2; 101cabdff1aSopenharmony_ci } 102cabdff1aSopenharmony_ci if (rf2 != rf) { 103cabdff1aSopenharmony_ci rf2->top_is_reference |= (pic->reference & PICT_TOP_FIELD) ? VDP_TRUE : VDP_FALSE; 104cabdff1aSopenharmony_ci rf2->bottom_is_reference |= (pic->reference & PICT_BOTTOM_FIELD) ? VDP_TRUE : VDP_FALSE; 105cabdff1aSopenharmony_ci continue; 106cabdff1aSopenharmony_ci } 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci if (rf >= &info->referenceFrames[H264_RF_COUNT]) 109cabdff1aSopenharmony_ci continue; 110cabdff1aSopenharmony_ci 111cabdff1aSopenharmony_ci vdpau_h264_set_rf(rf, pic, pic->reference); 112cabdff1aSopenharmony_ci ++rf; 113cabdff1aSopenharmony_ci } 114cabdff1aSopenharmony_ci } 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci for (; rf < &info->referenceFrames[H264_RF_COUNT]; ++rf) 117cabdff1aSopenharmony_ci vdpau_h264_clear_rf(rf); 118cabdff1aSopenharmony_ci} 119cabdff1aSopenharmony_ci 120cabdff1aSopenharmony_cistatic int vdpau_h264_start_frame(AVCodecContext *avctx, 121cabdff1aSopenharmony_ci const uint8_t *buffer, uint32_t size) 122cabdff1aSopenharmony_ci{ 123cabdff1aSopenharmony_ci H264Context * const h = avctx->priv_data; 124cabdff1aSopenharmony_ci const PPS *pps = h->ps.pps; 125cabdff1aSopenharmony_ci const SPS *sps = h->ps.sps; 126cabdff1aSopenharmony_ci H264Picture *pic = h->cur_pic_ptr; 127cabdff1aSopenharmony_ci struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; 128cabdff1aSopenharmony_ci VdpPictureInfoH264 *info = &pic_ctx->info.h264; 129cabdff1aSopenharmony_ci#ifdef VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE 130cabdff1aSopenharmony_ci VdpPictureInfoH264Predictive *info2 = &pic_ctx->info.h264_predictive; 131cabdff1aSopenharmony_ci#endif 132cabdff1aSopenharmony_ci 133cabdff1aSopenharmony_ci /* init VdpPictureInfoH264 */ 134cabdff1aSopenharmony_ci info->slice_count = 0; 135cabdff1aSopenharmony_ci info->field_order_cnt[0] = h264_foc(pic->field_poc[0]); 136cabdff1aSopenharmony_ci info->field_order_cnt[1] = h264_foc(pic->field_poc[1]); 137cabdff1aSopenharmony_ci info->is_reference = h->nal_ref_idc != 0; 138cabdff1aSopenharmony_ci info->frame_num = h->poc.frame_num; 139cabdff1aSopenharmony_ci info->field_pic_flag = h->picture_structure != PICT_FRAME; 140cabdff1aSopenharmony_ci info->bottom_field_flag = h->picture_structure == PICT_BOTTOM_FIELD; 141cabdff1aSopenharmony_ci info->num_ref_frames = sps->ref_frame_count; 142cabdff1aSopenharmony_ci info->mb_adaptive_frame_field_flag = sps->mb_aff && !info->field_pic_flag; 143cabdff1aSopenharmony_ci info->constrained_intra_pred_flag = pps->constrained_intra_pred; 144cabdff1aSopenharmony_ci info->weighted_pred_flag = pps->weighted_pred; 145cabdff1aSopenharmony_ci info->weighted_bipred_idc = pps->weighted_bipred_idc; 146cabdff1aSopenharmony_ci info->frame_mbs_only_flag = sps->frame_mbs_only_flag; 147cabdff1aSopenharmony_ci info->transform_8x8_mode_flag = pps->transform_8x8_mode; 148cabdff1aSopenharmony_ci info->chroma_qp_index_offset = pps->chroma_qp_index_offset[0]; 149cabdff1aSopenharmony_ci info->second_chroma_qp_index_offset = pps->chroma_qp_index_offset[1]; 150cabdff1aSopenharmony_ci info->pic_init_qp_minus26 = pps->init_qp - 26; 151cabdff1aSopenharmony_ci info->num_ref_idx_l0_active_minus1 = pps->ref_count[0] - 1; 152cabdff1aSopenharmony_ci info->num_ref_idx_l1_active_minus1 = pps->ref_count[1] - 1; 153cabdff1aSopenharmony_ci info->log2_max_frame_num_minus4 = sps->log2_max_frame_num - 4; 154cabdff1aSopenharmony_ci info->pic_order_cnt_type = sps->poc_type; 155cabdff1aSopenharmony_ci info->log2_max_pic_order_cnt_lsb_minus4 = sps->poc_type ? 0 : sps->log2_max_poc_lsb - 4; 156cabdff1aSopenharmony_ci info->delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; 157cabdff1aSopenharmony_ci info->direct_8x8_inference_flag = sps->direct_8x8_inference_flag; 158cabdff1aSopenharmony_ci#ifdef VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE 159cabdff1aSopenharmony_ci info2->qpprime_y_zero_transform_bypass_flag = sps->transform_bypass; 160cabdff1aSopenharmony_ci info2->separate_colour_plane_flag = sps->residual_color_transform_flag; 161cabdff1aSopenharmony_ci#endif 162cabdff1aSopenharmony_ci info->entropy_coding_mode_flag = pps->cabac; 163cabdff1aSopenharmony_ci info->pic_order_present_flag = pps->pic_order_present; 164cabdff1aSopenharmony_ci info->deblocking_filter_control_present_flag = pps->deblocking_filter_parameters_present; 165cabdff1aSopenharmony_ci info->redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present; 166cabdff1aSopenharmony_ci 167cabdff1aSopenharmony_ci memcpy(info->scaling_lists_4x4, pps->scaling_matrix4, 168cabdff1aSopenharmony_ci sizeof(info->scaling_lists_4x4)); 169cabdff1aSopenharmony_ci memcpy(info->scaling_lists_8x8[0], pps->scaling_matrix8[0], 170cabdff1aSopenharmony_ci sizeof(info->scaling_lists_8x8[0])); 171cabdff1aSopenharmony_ci memcpy(info->scaling_lists_8x8[1], pps->scaling_matrix8[3], 172cabdff1aSopenharmony_ci sizeof(info->scaling_lists_8x8[1])); 173cabdff1aSopenharmony_ci 174cabdff1aSopenharmony_ci vdpau_h264_set_reference_frames(avctx); 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ci return ff_vdpau_common_start_frame(pic_ctx, buffer, size); 177cabdff1aSopenharmony_ci} 178cabdff1aSopenharmony_ci 179cabdff1aSopenharmony_cistatic const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 }; 180cabdff1aSopenharmony_ci 181cabdff1aSopenharmony_cistatic int vdpau_h264_decode_slice(AVCodecContext *avctx, 182cabdff1aSopenharmony_ci const uint8_t *buffer, uint32_t size) 183cabdff1aSopenharmony_ci{ 184cabdff1aSopenharmony_ci H264Context *h = avctx->priv_data; 185cabdff1aSopenharmony_ci H264Picture *pic = h->cur_pic_ptr; 186cabdff1aSopenharmony_ci struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; 187cabdff1aSopenharmony_ci int val; 188cabdff1aSopenharmony_ci 189cabdff1aSopenharmony_ci val = ff_vdpau_add_buffer(pic_ctx, start_code_prefix, 3); 190cabdff1aSopenharmony_ci if (val) 191cabdff1aSopenharmony_ci return val; 192cabdff1aSopenharmony_ci 193cabdff1aSopenharmony_ci val = ff_vdpau_add_buffer(pic_ctx, buffer, size); 194cabdff1aSopenharmony_ci if (val) 195cabdff1aSopenharmony_ci return val; 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci pic_ctx->info.h264.slice_count++; 198cabdff1aSopenharmony_ci return 0; 199cabdff1aSopenharmony_ci} 200cabdff1aSopenharmony_ci 201cabdff1aSopenharmony_cistatic int vdpau_h264_end_frame(AVCodecContext *avctx) 202cabdff1aSopenharmony_ci{ 203cabdff1aSopenharmony_ci H264Context *h = avctx->priv_data; 204cabdff1aSopenharmony_ci H264SliceContext *sl = &h->slice_ctx[0]; 205cabdff1aSopenharmony_ci H264Picture *pic = h->cur_pic_ptr; 206cabdff1aSopenharmony_ci struct vdpau_picture_context *pic_ctx = pic->hwaccel_picture_private; 207cabdff1aSopenharmony_ci int val; 208cabdff1aSopenharmony_ci 209cabdff1aSopenharmony_ci val = ff_vdpau_common_end_frame(avctx, pic->f, pic_ctx); 210cabdff1aSopenharmony_ci if (val < 0) 211cabdff1aSopenharmony_ci return val; 212cabdff1aSopenharmony_ci 213cabdff1aSopenharmony_ci ff_h264_draw_horiz_band(h, sl, 0, h->avctx->height); 214cabdff1aSopenharmony_ci return 0; 215cabdff1aSopenharmony_ci} 216cabdff1aSopenharmony_ci 217cabdff1aSopenharmony_cistatic int vdpau_h264_init(AVCodecContext *avctx) 218cabdff1aSopenharmony_ci{ 219cabdff1aSopenharmony_ci VdpDecoderProfile profile; 220cabdff1aSopenharmony_ci uint32_t level = avctx->level; 221cabdff1aSopenharmony_ci 222cabdff1aSopenharmony_ci switch (avctx->profile & ~FF_PROFILE_H264_INTRA) { 223cabdff1aSopenharmony_ci case FF_PROFILE_H264_BASELINE: 224cabdff1aSopenharmony_ci profile = VDP_DECODER_PROFILE_H264_BASELINE; 225cabdff1aSopenharmony_ci break; 226cabdff1aSopenharmony_ci case FF_PROFILE_H264_CONSTRAINED_BASELINE: 227cabdff1aSopenharmony_ci#ifdef VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE 228cabdff1aSopenharmony_ci profile = VDP_DECODER_PROFILE_H264_CONSTRAINED_BASELINE; 229cabdff1aSopenharmony_ci break; 230cabdff1aSopenharmony_ci#endif 231cabdff1aSopenharmony_ci case FF_PROFILE_H264_MAIN: 232cabdff1aSopenharmony_ci profile = VDP_DECODER_PROFILE_H264_MAIN; 233cabdff1aSopenharmony_ci break; 234cabdff1aSopenharmony_ci case FF_PROFILE_H264_HIGH: 235cabdff1aSopenharmony_ci profile = VDP_DECODER_PROFILE_H264_HIGH; 236cabdff1aSopenharmony_ci break; 237cabdff1aSopenharmony_ci#ifdef VDP_DECODER_PROFILE_H264_EXTENDED 238cabdff1aSopenharmony_ci case FF_PROFILE_H264_EXTENDED: 239cabdff1aSopenharmony_ci profile = VDP_DECODER_PROFILE_H264_EXTENDED; 240cabdff1aSopenharmony_ci break; 241cabdff1aSopenharmony_ci#endif 242cabdff1aSopenharmony_ci case FF_PROFILE_H264_HIGH_10: 243cabdff1aSopenharmony_ci /* XXX: High 10 can be treated as High so long as only 8 bits per 244cabdff1aSopenharmony_ci * format are supported. */ 245cabdff1aSopenharmony_ci profile = VDP_DECODER_PROFILE_H264_HIGH; 246cabdff1aSopenharmony_ci break; 247cabdff1aSopenharmony_ci#ifdef VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE 248cabdff1aSopenharmony_ci case FF_PROFILE_H264_HIGH_422: 249cabdff1aSopenharmony_ci case FF_PROFILE_H264_HIGH_444_PREDICTIVE: 250cabdff1aSopenharmony_ci case FF_PROFILE_H264_CAVLC_444: 251cabdff1aSopenharmony_ci profile = VDP_DECODER_PROFILE_H264_HIGH_444_PREDICTIVE; 252cabdff1aSopenharmony_ci break; 253cabdff1aSopenharmony_ci#endif 254cabdff1aSopenharmony_ci default: 255cabdff1aSopenharmony_ci return AVERROR(ENOTSUP); 256cabdff1aSopenharmony_ci } 257cabdff1aSopenharmony_ci 258cabdff1aSopenharmony_ci if ((avctx->profile & FF_PROFILE_H264_INTRA) && avctx->level == 11) 259cabdff1aSopenharmony_ci level = VDP_DECODER_LEVEL_H264_1b; 260cabdff1aSopenharmony_ci 261cabdff1aSopenharmony_ci return ff_vdpau_common_init(avctx, profile, level); 262cabdff1aSopenharmony_ci} 263cabdff1aSopenharmony_ci 264cabdff1aSopenharmony_ciconst AVHWAccel ff_h264_vdpau_hwaccel = { 265cabdff1aSopenharmony_ci .name = "h264_vdpau", 266cabdff1aSopenharmony_ci .type = AVMEDIA_TYPE_VIDEO, 267cabdff1aSopenharmony_ci .id = AV_CODEC_ID_H264, 268cabdff1aSopenharmony_ci .pix_fmt = AV_PIX_FMT_VDPAU, 269cabdff1aSopenharmony_ci .start_frame = vdpau_h264_start_frame, 270cabdff1aSopenharmony_ci .end_frame = vdpau_h264_end_frame, 271cabdff1aSopenharmony_ci .decode_slice = vdpau_h264_decode_slice, 272cabdff1aSopenharmony_ci .frame_priv_data_size = sizeof(struct vdpau_picture_context), 273cabdff1aSopenharmony_ci .init = vdpau_h264_init, 274cabdff1aSopenharmony_ci .uninit = ff_vdpau_common_uninit, 275cabdff1aSopenharmony_ci .frame_params = ff_vdpau_common_frame_params, 276cabdff1aSopenharmony_ci .priv_data_size = sizeof(VDPAUContext), 277cabdff1aSopenharmony_ci .caps_internal = HWACCEL_CAP_ASYNC_SAFE, 278cabdff1aSopenharmony_ci}; 279