annotate ffmpeg/libavcodec/vdpau_h264.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * MPEG-4 Part 10 / AVC / H.264 HW decode acceleration through VDPAU
yading@10 3 *
yading@10 4 * Copyright (c) 2008 NVIDIA
yading@10 5 * Copyright (c) 2013 Rémi Denis-Courmont
yading@10 6 *
yading@10 7 * This file is part of FFmpeg.
yading@10 8 *
yading@10 9 * FFmpeg is free software; you can redistribute it and/or
yading@10 10 * modify it under the terms of the GNU Lesser General Public
yading@10 11 * License as published by the Free Software Foundation; either
yading@10 12 * version 2.1 of the License, or (at your option) any later version.
yading@10 13 *
yading@10 14 * FFmpeg is distributed in the hope that it will be useful,
yading@10 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 17 * Lesser General Public License for more details.
yading@10 18 *
yading@10 19 * You should have received a copy of the GNU Lesser General Public
yading@10 20 * License along with FFmpeg; if not, write to the Free Software Foundation,
yading@10 21 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 22 */
yading@10 23
yading@10 24 #include <vdpau/vdpau.h>
yading@10 25
yading@10 26 #include "avcodec.h"
yading@10 27 #include "h264.h"
yading@10 28 #include "vdpau.h"
yading@10 29 #include "vdpau_internal.h"
yading@10 30
yading@10 31 static int32_t h264_foc(int foc)
yading@10 32 {
yading@10 33 if (foc == INT_MAX)
yading@10 34 foc = 0;
yading@10 35 return foc;
yading@10 36 }
yading@10 37
yading@10 38 static void vdpau_h264_clear_rf(VdpReferenceFrameH264 *rf)
yading@10 39 {
yading@10 40 rf->surface = VDP_INVALID_HANDLE;
yading@10 41 rf->is_long_term = VDP_FALSE;
yading@10 42 rf->top_is_reference = VDP_FALSE;
yading@10 43 rf->bottom_is_reference = VDP_FALSE;
yading@10 44 rf->field_order_cnt[0] = 0;
yading@10 45 rf->field_order_cnt[1] = 0;
yading@10 46 rf->frame_idx = 0;
yading@10 47 }
yading@10 48
yading@10 49 static void vdpau_h264_set_rf(VdpReferenceFrameH264 *rf, Picture *pic,
yading@10 50 int pic_structure)
yading@10 51 {
yading@10 52 VdpVideoSurface surface = ff_vdpau_get_surface_id(pic);
yading@10 53
yading@10 54 if (pic_structure == 0)
yading@10 55 pic_structure = pic->reference;
yading@10 56
yading@10 57 rf->surface = surface;
yading@10 58 rf->is_long_term = pic->reference && pic->long_ref;
yading@10 59 rf->top_is_reference = (pic_structure & PICT_TOP_FIELD) != 0;
yading@10 60 rf->bottom_is_reference = (pic_structure & PICT_BOTTOM_FIELD) != 0;
yading@10 61 rf->field_order_cnt[0] = h264_foc(pic->field_poc[0]);
yading@10 62 rf->field_order_cnt[1] = h264_foc(pic->field_poc[1]);
yading@10 63 rf->frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num;
yading@10 64 }
yading@10 65
yading@10 66 static void vdpau_h264_set_reference_frames(AVCodecContext *avctx)
yading@10 67 {
yading@10 68 H264Context * const h = avctx->priv_data;
yading@10 69 AVVDPAUContext *hwctx = avctx->hwaccel_context;
yading@10 70 VdpPictureInfoH264 *info = &hwctx->info.h264;
yading@10 71 int list;
yading@10 72
yading@10 73 VdpReferenceFrameH264 *rf = &info->referenceFrames[0];
yading@10 74 #define H264_RF_COUNT FF_ARRAY_ELEMS(info->referenceFrames)
yading@10 75
yading@10 76 for (list = 0; list < 2; ++list) {
yading@10 77 Picture **lp = list ? h->long_ref : h->short_ref;
yading@10 78 int i, ls = list ? 16 : h->short_ref_count;
yading@10 79
yading@10 80 for (i = 0; i < ls; ++i) {
yading@10 81 Picture *pic = lp[i];
yading@10 82 VdpReferenceFrameH264 *rf2;
yading@10 83 VdpVideoSurface surface_ref;
yading@10 84 int pic_frame_idx;
yading@10 85
yading@10 86 if (!pic || !pic->reference)
yading@10 87 continue;
yading@10 88 pic_frame_idx = pic->long_ref ? pic->pic_id : pic->frame_num;
yading@10 89 surface_ref = ff_vdpau_get_surface_id(pic);
yading@10 90
yading@10 91 rf2 = &info->referenceFrames[0];
yading@10 92 while (rf2 != rf) {
yading@10 93 if ((rf2->surface == surface_ref) &&
yading@10 94 (rf2->is_long_term == pic->long_ref) &&
yading@10 95 (rf2->frame_idx == pic_frame_idx))
yading@10 96 break;
yading@10 97 ++rf2;
yading@10 98 }
yading@10 99 if (rf2 != rf) {
yading@10 100 rf2->top_is_reference |= (pic->reference & PICT_TOP_FIELD) ? VDP_TRUE : VDP_FALSE;
yading@10 101 rf2->bottom_is_reference |= (pic->reference & PICT_BOTTOM_FIELD) ? VDP_TRUE : VDP_FALSE;
yading@10 102 continue;
yading@10 103 }
yading@10 104
yading@10 105 if (rf >= &info->referenceFrames[H264_RF_COUNT])
yading@10 106 continue;
yading@10 107
yading@10 108 vdpau_h264_set_rf(rf, pic, pic->reference);
yading@10 109 ++rf;
yading@10 110 }
yading@10 111 }
yading@10 112
yading@10 113 for (; rf < &info->referenceFrames[H264_RF_COUNT]; ++rf)
yading@10 114 vdpau_h264_clear_rf(rf);
yading@10 115 }
yading@10 116
yading@10 117 static int vdpau_h264_start_frame(AVCodecContext *avctx,
yading@10 118 const uint8_t *buffer, uint32_t size)
yading@10 119 {
yading@10 120 H264Context * const h = avctx->priv_data;
yading@10 121 AVVDPAUContext *hwctx = avctx->hwaccel_context;
yading@10 122 VdpPictureInfoH264 *info = &hwctx->info.h264;
yading@10 123 Picture *pic = h->cur_pic_ptr;
yading@10 124
yading@10 125 /* init VdpPictureInfoH264 */
yading@10 126 info->slice_count = 0;
yading@10 127 info->field_order_cnt[0] = h264_foc(pic->field_poc[0]);
yading@10 128 info->field_order_cnt[1] = h264_foc(pic->field_poc[1]);
yading@10 129 info->is_reference = h->nal_ref_idc != 0;
yading@10 130 info->frame_num = h->frame_num;
yading@10 131 info->field_pic_flag = h->picture_structure != PICT_FRAME;
yading@10 132 info->bottom_field_flag = h->picture_structure == PICT_BOTTOM_FIELD;
yading@10 133 info->num_ref_frames = h->sps.ref_frame_count;
yading@10 134 info->mb_adaptive_frame_field_flag = h->sps.mb_aff && !info->field_pic_flag;
yading@10 135 info->constrained_intra_pred_flag = h->pps.constrained_intra_pred;
yading@10 136 info->weighted_pred_flag = h->pps.weighted_pred;
yading@10 137 info->weighted_bipred_idc = h->pps.weighted_bipred_idc;
yading@10 138 info->frame_mbs_only_flag = h->sps.frame_mbs_only_flag;
yading@10 139 info->transform_8x8_mode_flag = h->pps.transform_8x8_mode;
yading@10 140 info->chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0];
yading@10 141 info->second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1];
yading@10 142 info->pic_init_qp_minus26 = h->pps.init_qp - 26;
yading@10 143 info->num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1;
yading@10 144 info->num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1;
yading@10 145 info->log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4;
yading@10 146 info->pic_order_cnt_type = h->sps.poc_type;
yading@10 147 info->log2_max_pic_order_cnt_lsb_minus4 = h->sps.poc_type ? 0 : h->sps.log2_max_poc_lsb - 4;
yading@10 148 info->delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag;
yading@10 149 info->direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag;
yading@10 150 info->entropy_coding_mode_flag = h->pps.cabac;
yading@10 151 info->pic_order_present_flag = h->pps.pic_order_present;
yading@10 152 info->deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present;
yading@10 153 info->redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present;
yading@10 154
yading@10 155 memcpy(info->scaling_lists_4x4, h->pps.scaling_matrix4,
yading@10 156 sizeof(info->scaling_lists_4x4));
yading@10 157 memcpy(info->scaling_lists_8x8[0], h->pps.scaling_matrix8[0],
yading@10 158 sizeof(info->scaling_lists_8x8[0]));
yading@10 159 memcpy(info->scaling_lists_8x8[1], h->pps.scaling_matrix8[3],
yading@10 160 sizeof(info->scaling_lists_8x8[1]));
yading@10 161
yading@10 162 vdpau_h264_set_reference_frames(avctx);
yading@10 163
yading@10 164 return ff_vdpau_common_start_frame(avctx, buffer, size);
yading@10 165 }
yading@10 166
yading@10 167 static const uint8_t start_code_prefix[3] = { 0x00, 0x00, 0x01 };
yading@10 168
yading@10 169 static int vdpau_h264_decode_slice(AVCodecContext *avctx,
yading@10 170 const uint8_t *buffer, uint32_t size)
yading@10 171 {
yading@10 172 AVVDPAUContext *hwctx = avctx->hwaccel_context;
yading@10 173 int val;
yading@10 174
yading@10 175 val = ff_vdpau_add_buffer(avctx, start_code_prefix, 3);
yading@10 176 if (val)
yading@10 177 return val;
yading@10 178
yading@10 179 val = ff_vdpau_add_buffer(avctx, buffer, size);
yading@10 180 if (val)
yading@10 181 return val;
yading@10 182
yading@10 183 hwctx->info.h264.slice_count++;
yading@10 184 return 0;
yading@10 185 }
yading@10 186
yading@10 187 static int vdpau_h264_end_frame(AVCodecContext *avctx)
yading@10 188 {
yading@10 189 AVVDPAUContext *hwctx = avctx->hwaccel_context;
yading@10 190 H264Context *h = avctx->priv_data;
yading@10 191 VdpVideoSurface surf = ff_vdpau_get_surface_id(h->cur_pic_ptr);
yading@10 192
yading@10 193 hwctx->render(hwctx->decoder, surf, (void *)&hwctx->info,
yading@10 194 hwctx->bitstream_buffers_used, hwctx->bitstream_buffers);
yading@10 195
yading@10 196 ff_h264_draw_horiz_band(h, 0, h->avctx->height);
yading@10 197 hwctx->bitstream_buffers_used = 0;
yading@10 198
yading@10 199 return 0;
yading@10 200 }
yading@10 201
yading@10 202 AVHWAccel ff_h264_vdpau_hwaccel = {
yading@10 203 .name = "h264_vdpau",
yading@10 204 .type = AVMEDIA_TYPE_VIDEO,
yading@10 205 .id = AV_CODEC_ID_H264,
yading@10 206 .pix_fmt = AV_PIX_FMT_VDPAU,
yading@10 207 .start_frame = vdpau_h264_start_frame,
yading@10 208 .end_frame = vdpau_h264_end_frame,
yading@10 209 .decode_slice = vdpau_h264_decode_slice,
yading@10 210 };