yading@10: /* yading@10: * Video Acceleration API (video decoding) yading@10: * HW decode acceleration for MPEG-2, MPEG-4, H.264 and VC-1 yading@10: * yading@10: * Copyright (C) 2008-2009 Splitted-Desktop Systems yading@10: * yading@10: * This file is part of FFmpeg. yading@10: * yading@10: * FFmpeg is free software; you can redistribute it and/or yading@10: * modify it under the terms of the GNU Lesser General Public yading@10: * License as published by the Free Software Foundation; either yading@10: * version 2.1 of the License, or (at your option) any later version. yading@10: * yading@10: * FFmpeg is distributed in the hope that it will be useful, yading@10: * but WITHOUT ANY WARRANTY; without even the implied warranty of yading@10: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU yading@10: * Lesser General Public License for more details. yading@10: * yading@10: * You should have received a copy of the GNU Lesser General Public yading@10: * License along with FFmpeg; if not, write to the Free Software yading@10: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA yading@10: */ yading@10: yading@10: #include "h264.h" yading@10: #include "vaapi_internal.h" yading@10: yading@10: /** yading@10: * @addtogroup VAAPI_Decoding yading@10: * yading@10: * @{ yading@10: */ yading@10: yading@10: static void destroy_buffers(VADisplay display, VABufferID *buffers, unsigned int n_buffers) yading@10: { yading@10: unsigned int i; yading@10: for (i = 0; i < n_buffers; i++) { yading@10: if (buffers[i]) { yading@10: vaDestroyBuffer(display, buffers[i]); yading@10: buffers[i] = 0; yading@10: } yading@10: } yading@10: } yading@10: yading@10: int ff_vaapi_render_picture(struct vaapi_context *vactx, VASurfaceID surface) yading@10: { yading@10: VABufferID va_buffers[3]; yading@10: unsigned int n_va_buffers = 0; yading@10: yading@10: vaUnmapBuffer(vactx->display, vactx->pic_param_buf_id); yading@10: va_buffers[n_va_buffers++] = vactx->pic_param_buf_id; yading@10: yading@10: if (vactx->iq_matrix_buf_id) { yading@10: vaUnmapBuffer(vactx->display, vactx->iq_matrix_buf_id); yading@10: va_buffers[n_va_buffers++] = vactx->iq_matrix_buf_id; yading@10: } yading@10: yading@10: if (vactx->bitplane_buf_id) { yading@10: vaUnmapBuffer(vactx->display, vactx->bitplane_buf_id); yading@10: va_buffers[n_va_buffers++] = vactx->bitplane_buf_id; yading@10: } yading@10: yading@10: if (vaBeginPicture(vactx->display, vactx->context_id, yading@10: surface) != VA_STATUS_SUCCESS) yading@10: return -1; yading@10: yading@10: if (vaRenderPicture(vactx->display, vactx->context_id, yading@10: va_buffers, n_va_buffers) != VA_STATUS_SUCCESS) yading@10: return -1; yading@10: yading@10: if (vaRenderPicture(vactx->display, vactx->context_id, yading@10: vactx->slice_buf_ids, yading@10: vactx->n_slice_buf_ids) != VA_STATUS_SUCCESS) yading@10: return -1; yading@10: yading@10: if (vaEndPicture(vactx->display, vactx->context_id) != VA_STATUS_SUCCESS) yading@10: return -1; yading@10: yading@10: return 0; yading@10: } yading@10: yading@10: int ff_vaapi_commit_slices(struct vaapi_context *vactx) yading@10: { yading@10: VABufferID *slice_buf_ids; yading@10: VABufferID slice_param_buf_id, slice_data_buf_id; yading@10: yading@10: if (vactx->slice_count == 0) yading@10: return 0; yading@10: yading@10: slice_buf_ids = yading@10: av_fast_realloc(vactx->slice_buf_ids, yading@10: &vactx->slice_buf_ids_alloc, yading@10: (vactx->n_slice_buf_ids + 2) * sizeof(slice_buf_ids[0])); yading@10: if (!slice_buf_ids) yading@10: return -1; yading@10: vactx->slice_buf_ids = slice_buf_ids; yading@10: yading@10: slice_param_buf_id = 0; yading@10: if (vaCreateBuffer(vactx->display, vactx->context_id, yading@10: VASliceParameterBufferType, yading@10: vactx->slice_param_size, yading@10: vactx->slice_count, vactx->slice_params, yading@10: &slice_param_buf_id) != VA_STATUS_SUCCESS) yading@10: return -1; yading@10: vactx->slice_count = 0; yading@10: yading@10: slice_data_buf_id = 0; yading@10: if (vaCreateBuffer(vactx->display, vactx->context_id, yading@10: VASliceDataBufferType, yading@10: vactx->slice_data_size, yading@10: 1, (void *)vactx->slice_data, yading@10: &slice_data_buf_id) != VA_STATUS_SUCCESS) yading@10: return -1; yading@10: vactx->slice_data = NULL; yading@10: vactx->slice_data_size = 0; yading@10: yading@10: slice_buf_ids[vactx->n_slice_buf_ids++] = slice_param_buf_id; yading@10: slice_buf_ids[vactx->n_slice_buf_ids++] = slice_data_buf_id; yading@10: return 0; yading@10: } yading@10: yading@10: static void *alloc_buffer(struct vaapi_context *vactx, int type, unsigned int size, uint32_t *buf_id) yading@10: { yading@10: void *data = NULL; yading@10: yading@10: *buf_id = 0; yading@10: if (vaCreateBuffer(vactx->display, vactx->context_id, yading@10: type, size, 1, NULL, buf_id) == VA_STATUS_SUCCESS) yading@10: vaMapBuffer(vactx->display, *buf_id, &data); yading@10: yading@10: return data; yading@10: } yading@10: yading@10: void *ff_vaapi_alloc_pic_param(struct vaapi_context *vactx, unsigned int size) yading@10: { yading@10: return alloc_buffer(vactx, VAPictureParameterBufferType, size, &vactx->pic_param_buf_id); yading@10: } yading@10: yading@10: void *ff_vaapi_alloc_iq_matrix(struct vaapi_context *vactx, unsigned int size) yading@10: { yading@10: return alloc_buffer(vactx, VAIQMatrixBufferType, size, &vactx->iq_matrix_buf_id); yading@10: } yading@10: yading@10: uint8_t *ff_vaapi_alloc_bitplane(struct vaapi_context *vactx, uint32_t size) yading@10: { yading@10: return alloc_buffer(vactx, VABitPlaneBufferType, size, &vactx->bitplane_buf_id); yading@10: } yading@10: yading@10: VASliceParameterBufferBase *ff_vaapi_alloc_slice(struct vaapi_context *vactx, const uint8_t *buffer, uint32_t size) yading@10: { yading@10: uint8_t *slice_params; yading@10: VASliceParameterBufferBase *slice_param; yading@10: yading@10: if (!vactx->slice_data) yading@10: vactx->slice_data = buffer; yading@10: if (vactx->slice_data + vactx->slice_data_size != buffer) { yading@10: if (ff_vaapi_commit_slices(vactx) < 0) yading@10: return NULL; yading@10: vactx->slice_data = buffer; yading@10: } yading@10: yading@10: slice_params = yading@10: av_fast_realloc(vactx->slice_params, yading@10: &vactx->slice_params_alloc, yading@10: (vactx->slice_count + 1) * vactx->slice_param_size); yading@10: if (!slice_params) yading@10: return NULL; yading@10: vactx->slice_params = slice_params; yading@10: yading@10: slice_param = (VASliceParameterBufferBase *)(slice_params + vactx->slice_count * vactx->slice_param_size); yading@10: slice_param->slice_data_size = size; yading@10: slice_param->slice_data_offset = vactx->slice_data_size; yading@10: slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL; yading@10: yading@10: vactx->slice_count++; yading@10: vactx->slice_data_size += size; yading@10: return slice_param; yading@10: } yading@10: yading@10: void ff_vaapi_common_end_frame(AVCodecContext *avctx) yading@10: { yading@10: struct vaapi_context * const vactx = avctx->hwaccel_context; yading@10: yading@10: av_dlog(avctx, "ff_vaapi_common_end_frame()\n"); yading@10: yading@10: destroy_buffers(vactx->display, &vactx->pic_param_buf_id, 1); yading@10: destroy_buffers(vactx->display, &vactx->iq_matrix_buf_id, 1); yading@10: destroy_buffers(vactx->display, &vactx->bitplane_buf_id, 1); yading@10: destroy_buffers(vactx->display, vactx->slice_buf_ids, vactx->n_slice_buf_ids); yading@10: av_freep(&vactx->slice_buf_ids); yading@10: av_freep(&vactx->slice_params); yading@10: vactx->n_slice_buf_ids = 0; yading@10: vactx->slice_buf_ids_alloc = 0; yading@10: vactx->slice_count = 0; yading@10: vactx->slice_params_alloc = 0; yading@10: } yading@10: yading@10: int ff_vaapi_mpeg_end_frame(AVCodecContext *avctx) yading@10: { yading@10: struct vaapi_context * const vactx = avctx->hwaccel_context; yading@10: MpegEncContext *s = avctx->priv_data; yading@10: int ret; yading@10: yading@10: ret = ff_vaapi_commit_slices(vactx); yading@10: if (ret < 0) yading@10: goto finish; yading@10: yading@10: ret = ff_vaapi_render_picture(vactx, yading@10: ff_vaapi_get_surface_id(s->current_picture_ptr)); yading@10: if (ret < 0) yading@10: goto finish; yading@10: yading@10: ff_mpeg_draw_horiz_band(s, 0, s->avctx->height); yading@10: yading@10: finish: yading@10: ff_vaapi_common_end_frame(avctx); yading@10: return ret; yading@10: } yading@10: yading@10: /* @} */