1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * MPEG-2 HW decode acceleration through VA API 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * Copyright (C) 2008-2009 Splitted-Desktop Systems 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include "hwconfig.h" 24cabdff1aSopenharmony_ci#include "mpegutils.h" 25cabdff1aSopenharmony_ci#include "mpegvideo.h" 26cabdff1aSopenharmony_ci#include "mpegvideodec.h" 27cabdff1aSopenharmony_ci#include "vaapi_decode.h" 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci/** Reconstruct bitstream f_code */ 30cabdff1aSopenharmony_cistatic inline int mpeg2_get_f_code(const MpegEncContext *s) 31cabdff1aSopenharmony_ci{ 32cabdff1aSopenharmony_ci return (s->mpeg_f_code[0][0] << 12) | (s->mpeg_f_code[0][1] << 8) | 33cabdff1aSopenharmony_ci (s->mpeg_f_code[1][0] << 4) | s->mpeg_f_code[1][1]; 34cabdff1aSopenharmony_ci} 35cabdff1aSopenharmony_ci 36cabdff1aSopenharmony_ci/** Determine frame start: first field for field picture or frame picture */ 37cabdff1aSopenharmony_cistatic inline int mpeg2_get_is_frame_start(const MpegEncContext *s) 38cabdff1aSopenharmony_ci{ 39cabdff1aSopenharmony_ci return s->first_field || s->picture_structure == PICT_FRAME; 40cabdff1aSopenharmony_ci} 41cabdff1aSopenharmony_ci 42cabdff1aSopenharmony_cistatic int vaapi_mpeg2_start_frame(AVCodecContext *avctx, av_unused const uint8_t *buffer, av_unused uint32_t size) 43cabdff1aSopenharmony_ci{ 44cabdff1aSopenharmony_ci const MpegEncContext *s = avctx->priv_data; 45cabdff1aSopenharmony_ci VAAPIDecodePicture *pic = s->current_picture_ptr->hwaccel_picture_private; 46cabdff1aSopenharmony_ci VAPictureParameterBufferMPEG2 pic_param; 47cabdff1aSopenharmony_ci VAIQMatrixBufferMPEG2 iq_matrix; 48cabdff1aSopenharmony_ci int i, err; 49cabdff1aSopenharmony_ci 50cabdff1aSopenharmony_ci pic->output_surface = ff_vaapi_get_surface_id(s->current_picture_ptr->f); 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ci pic_param = (VAPictureParameterBufferMPEG2) { 53cabdff1aSopenharmony_ci .horizontal_size = s->width, 54cabdff1aSopenharmony_ci .vertical_size = s->height, 55cabdff1aSopenharmony_ci .forward_reference_picture = VA_INVALID_ID, 56cabdff1aSopenharmony_ci .backward_reference_picture = VA_INVALID_ID, 57cabdff1aSopenharmony_ci .picture_coding_type = s->pict_type, 58cabdff1aSopenharmony_ci .f_code = mpeg2_get_f_code(s), 59cabdff1aSopenharmony_ci .picture_coding_extension.bits = { 60cabdff1aSopenharmony_ci .intra_dc_precision = s->intra_dc_precision, 61cabdff1aSopenharmony_ci .picture_structure = s->picture_structure, 62cabdff1aSopenharmony_ci .top_field_first = s->top_field_first, 63cabdff1aSopenharmony_ci .frame_pred_frame_dct = s->frame_pred_frame_dct, 64cabdff1aSopenharmony_ci .concealment_motion_vectors = s->concealment_motion_vectors, 65cabdff1aSopenharmony_ci .q_scale_type = s->q_scale_type, 66cabdff1aSopenharmony_ci .intra_vlc_format = s->intra_vlc_format, 67cabdff1aSopenharmony_ci .alternate_scan = s->alternate_scan, 68cabdff1aSopenharmony_ci .repeat_first_field = s->repeat_first_field, 69cabdff1aSopenharmony_ci .progressive_frame = s->progressive_frame, 70cabdff1aSopenharmony_ci .is_first_field = mpeg2_get_is_frame_start(s), 71cabdff1aSopenharmony_ci }, 72cabdff1aSopenharmony_ci }; 73cabdff1aSopenharmony_ci 74cabdff1aSopenharmony_ci switch (s->pict_type) { 75cabdff1aSopenharmony_ci case AV_PICTURE_TYPE_B: 76cabdff1aSopenharmony_ci pic_param.backward_reference_picture = ff_vaapi_get_surface_id(s->next_picture.f); 77cabdff1aSopenharmony_ci // fall-through 78cabdff1aSopenharmony_ci case AV_PICTURE_TYPE_P: 79cabdff1aSopenharmony_ci pic_param.forward_reference_picture = ff_vaapi_get_surface_id(s->last_picture.f); 80cabdff1aSopenharmony_ci break; 81cabdff1aSopenharmony_ci } 82cabdff1aSopenharmony_ci 83cabdff1aSopenharmony_ci err = ff_vaapi_decode_make_param_buffer(avctx, pic, 84cabdff1aSopenharmony_ci VAPictureParameterBufferType, 85cabdff1aSopenharmony_ci &pic_param, sizeof(pic_param)); 86cabdff1aSopenharmony_ci if (err < 0) 87cabdff1aSopenharmony_ci goto fail; 88cabdff1aSopenharmony_ci 89cabdff1aSopenharmony_ci iq_matrix.load_intra_quantiser_matrix = 1; 90cabdff1aSopenharmony_ci iq_matrix.load_non_intra_quantiser_matrix = 1; 91cabdff1aSopenharmony_ci iq_matrix.load_chroma_intra_quantiser_matrix = 1; 92cabdff1aSopenharmony_ci iq_matrix.load_chroma_non_intra_quantiser_matrix = 1; 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ci for (i = 0; i < 64; i++) { 95cabdff1aSopenharmony_ci int n = s->idsp.idct_permutation[ff_zigzag_direct[i]]; 96cabdff1aSopenharmony_ci iq_matrix.intra_quantiser_matrix[i] = s->intra_matrix[n]; 97cabdff1aSopenharmony_ci iq_matrix.non_intra_quantiser_matrix[i] = s->inter_matrix[n]; 98cabdff1aSopenharmony_ci iq_matrix.chroma_intra_quantiser_matrix[i] = s->chroma_intra_matrix[n]; 99cabdff1aSopenharmony_ci iq_matrix.chroma_non_intra_quantiser_matrix[i] = s->chroma_inter_matrix[n]; 100cabdff1aSopenharmony_ci } 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci err = ff_vaapi_decode_make_param_buffer(avctx, pic, 103cabdff1aSopenharmony_ci VAIQMatrixBufferType, 104cabdff1aSopenharmony_ci &iq_matrix, sizeof(iq_matrix)); 105cabdff1aSopenharmony_ci if (err < 0) 106cabdff1aSopenharmony_ci goto fail; 107cabdff1aSopenharmony_ci 108cabdff1aSopenharmony_ci return 0; 109cabdff1aSopenharmony_ci 110cabdff1aSopenharmony_cifail: 111cabdff1aSopenharmony_ci ff_vaapi_decode_cancel(avctx, pic); 112cabdff1aSopenharmony_ci return err; 113cabdff1aSopenharmony_ci} 114cabdff1aSopenharmony_ci 115cabdff1aSopenharmony_cistatic int vaapi_mpeg2_end_frame(AVCodecContext *avctx) 116cabdff1aSopenharmony_ci{ 117cabdff1aSopenharmony_ci MpegEncContext *s = avctx->priv_data; 118cabdff1aSopenharmony_ci VAAPIDecodePicture *pic = s->current_picture_ptr->hwaccel_picture_private; 119cabdff1aSopenharmony_ci int ret; 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_ci ret = ff_vaapi_decode_issue(avctx, pic); 122cabdff1aSopenharmony_ci if (ret < 0) 123cabdff1aSopenharmony_ci goto fail; 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci ff_mpeg_draw_horiz_band(s, 0, s->avctx->height); 126cabdff1aSopenharmony_ci 127cabdff1aSopenharmony_cifail: 128cabdff1aSopenharmony_ci return ret; 129cabdff1aSopenharmony_ci} 130cabdff1aSopenharmony_ci 131cabdff1aSopenharmony_cistatic int vaapi_mpeg2_decode_slice(AVCodecContext *avctx, const uint8_t *buffer, uint32_t size) 132cabdff1aSopenharmony_ci{ 133cabdff1aSopenharmony_ci const MpegEncContext *s = avctx->priv_data; 134cabdff1aSopenharmony_ci VAAPIDecodePicture *pic = s->current_picture_ptr->hwaccel_picture_private; 135cabdff1aSopenharmony_ci VASliceParameterBufferMPEG2 slice_param; 136cabdff1aSopenharmony_ci GetBitContext gb; 137cabdff1aSopenharmony_ci uint32_t quantiser_scale_code, intra_slice_flag, macroblock_offset; 138cabdff1aSopenharmony_ci int err; 139cabdff1aSopenharmony_ci 140cabdff1aSopenharmony_ci /* Determine macroblock_offset */ 141cabdff1aSopenharmony_ci init_get_bits(&gb, buffer, 8 * size); 142cabdff1aSopenharmony_ci if (get_bits_long(&gb, 32) >> 8 != 1) /* start code */ 143cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 144cabdff1aSopenharmony_ci quantiser_scale_code = get_bits(&gb, 5); 145cabdff1aSopenharmony_ci intra_slice_flag = get_bits1(&gb); 146cabdff1aSopenharmony_ci if (intra_slice_flag) { 147cabdff1aSopenharmony_ci skip_bits(&gb, 8); 148cabdff1aSopenharmony_ci if (skip_1stop_8data_bits(&gb) < 0) 149cabdff1aSopenharmony_ci return AVERROR_INVALIDDATA; 150cabdff1aSopenharmony_ci } 151cabdff1aSopenharmony_ci macroblock_offset = get_bits_count(&gb); 152cabdff1aSopenharmony_ci 153cabdff1aSopenharmony_ci slice_param = (VASliceParameterBufferMPEG2) { 154cabdff1aSopenharmony_ci .slice_data_size = size, 155cabdff1aSopenharmony_ci .slice_data_offset = 0, 156cabdff1aSopenharmony_ci .slice_data_flag = VA_SLICE_DATA_FLAG_ALL, 157cabdff1aSopenharmony_ci .macroblock_offset = macroblock_offset, 158cabdff1aSopenharmony_ci .slice_horizontal_position = s->mb_x, 159cabdff1aSopenharmony_ci .slice_vertical_position = s->mb_y >> (s->picture_structure != PICT_FRAME), 160cabdff1aSopenharmony_ci .quantiser_scale_code = quantiser_scale_code, 161cabdff1aSopenharmony_ci .intra_slice_flag = intra_slice_flag, 162cabdff1aSopenharmony_ci }; 163cabdff1aSopenharmony_ci 164cabdff1aSopenharmony_ci err = ff_vaapi_decode_make_slice_buffer(avctx, pic, 165cabdff1aSopenharmony_ci &slice_param, sizeof(slice_param), 166cabdff1aSopenharmony_ci buffer, size); 167cabdff1aSopenharmony_ci if (err < 0) { 168cabdff1aSopenharmony_ci ff_vaapi_decode_cancel(avctx, pic); 169cabdff1aSopenharmony_ci return err; 170cabdff1aSopenharmony_ci } 171cabdff1aSopenharmony_ci 172cabdff1aSopenharmony_ci return 0; 173cabdff1aSopenharmony_ci} 174cabdff1aSopenharmony_ci 175cabdff1aSopenharmony_ciconst AVHWAccel ff_mpeg2_vaapi_hwaccel = { 176cabdff1aSopenharmony_ci .name = "mpeg2_vaapi", 177cabdff1aSopenharmony_ci .type = AVMEDIA_TYPE_VIDEO, 178cabdff1aSopenharmony_ci .id = AV_CODEC_ID_MPEG2VIDEO, 179cabdff1aSopenharmony_ci .pix_fmt = AV_PIX_FMT_VAAPI, 180cabdff1aSopenharmony_ci .start_frame = &vaapi_mpeg2_start_frame, 181cabdff1aSopenharmony_ci .end_frame = &vaapi_mpeg2_end_frame, 182cabdff1aSopenharmony_ci .decode_slice = &vaapi_mpeg2_decode_slice, 183cabdff1aSopenharmony_ci .frame_priv_data_size = sizeof(VAAPIDecodePicture), 184cabdff1aSopenharmony_ci .init = &ff_vaapi_decode_init, 185cabdff1aSopenharmony_ci .uninit = &ff_vaapi_decode_uninit, 186cabdff1aSopenharmony_ci .frame_params = &ff_vaapi_common_frame_params, 187cabdff1aSopenharmony_ci .priv_data_size = sizeof(VAAPIDecodeContext), 188cabdff1aSopenharmony_ci .caps_internal = HWACCEL_CAP_ASYNC_SAFE, 189cabdff1aSopenharmony_ci}; 190