Mercurial > libavcodec.hg
diff dxva2.c @ 10980:9f771d4312ed libavcodec
Moved reusable functions from dxva2_h264.c to dxva2.c
author | fenrir |
---|---|
date | Sat, 23 Jan 2010 18:17:57 +0000 |
parents | dxva2_h264.c@776dba50775c |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dxva2.c Sat Jan 23 18:17:57 2010 +0000 @@ -0,0 +1,154 @@ +/* + * DXVA2 HW acceleration. + * + * copyright (c) 2010 Laurent Aimar + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "dxva2_internal.h" + +void *ff_dxva2_get_surface(const Picture *picture) +{ + return picture->data[3]; +} + +unsigned ff_dxva2_get_surface_index(const struct dxva_context *ctx, + const Picture *picture) +{ + void *surface = ff_dxva2_get_surface(picture); + unsigned i; + + for (i = 0; i < ctx->surface_count; i++) + if (ctx->surface[i] == surface) + return i; + + assert(0); + return 0; +} + +int ff_dxva2_commit_buffer(AVCodecContext *avctx, + struct dxva_context *ctx, + DXVA2_DecodeBufferDesc *dsc, + unsigned type, const void *data, unsigned size, + unsigned mb_count) +{ + void *dxva_data; + unsigned dxva_size; + int result; + + if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, type, + &dxva_data, &dxva_size))) { + av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %d\n", type); + return -1; + } + if (size <= dxva_size) { + memcpy(dxva_data, data, size); + + memset(dsc, 0, sizeof(*dsc)); + dsc->CompressedBufferType = type; + dsc->DataSize = size; + dsc->NumMBsInBuffer = mb_count; + + result = 0; + } else { + av_log(avctx, AV_LOG_ERROR, "Buffer for type %d was too small\n", type); + result = -1; + } + if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, type))) { + av_log(avctx, AV_LOG_ERROR, "Failed to release buffer type %d\n", type); + result = -1; + } + return result; +} + +int ff_dxva2_common_end_frame(AVCodecContext *avctx, MpegEncContext *s, + const void *pp, unsigned pp_size, + const void *qm, unsigned qm_size, + int (*commit_bs_si)(AVCodecContext *, + DXVA2_DecodeBufferDesc *bs, + DXVA2_DecodeBufferDesc *slice)) +{ + struct dxva_context *ctx = avctx->hwaccel_context; + unsigned buffer_count = 0; + DXVA2_DecodeBufferDesc buffer[4]; + DXVA2_DecodeExecuteParams exec; + int result; + + if (FAILED(IDirectXVideoDecoder_BeginFrame(ctx->decoder, + ff_dxva2_get_surface(s->current_picture_ptr), + NULL))) { + av_log(avctx, AV_LOG_ERROR, "Failed to begin frame\n"); + return -1; + } + + result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count], + DXVA2_PictureParametersBufferType, + pp, pp_size, 0); + if (result) { + av_log(avctx, AV_LOG_ERROR, + "Failed to add picture parameter buffer\n"); + goto end; + } + buffer_count++; + + if (qm_size > 0) { + result = ff_dxva2_commit_buffer(avctx, ctx, &buffer[buffer_count], + DXVA2_InverseQuantizationMatrixBufferType, + qm, qm_size, 0); + if (result) { + av_log(avctx, AV_LOG_ERROR, + "Failed to add inverse quantization matrix buffer\n"); + goto end; + } + buffer_count++; + } + + result = commit_bs_si(avctx, + &buffer[buffer_count + 0], + &buffer[buffer_count + 1]); + if (result) { + av_log(avctx, AV_LOG_ERROR, + "Failed to add bitstream or slice control buffer\n"); + goto end; + } + buffer_count += 2; + + /* TODO Film Grain when possible */ + + assert(buffer_count == 1 + (qm_size > 0) + 2); + + memset(&exec, 0, sizeof(exec)); + exec.NumCompBuffers = buffer_count; + exec.pCompressedBuffers = buffer; + exec.pExtensionData = NULL; + if (FAILED(IDirectXVideoDecoder_Execute(ctx->decoder, &exec))) { + av_log(avctx, AV_LOG_ERROR, "Failed to execute\n"); + result = -1; + } + +end: + if (FAILED(IDirectXVideoDecoder_EndFrame(ctx->decoder, NULL))) { + av_log(avctx, AV_LOG_ERROR, "Failed to end frame\n"); + result = -1; + } + + if (!result) + ff_draw_horiz_band(s, 0, s->avctx->height); + return result; +} +