diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 24518479e8..f137a6e168 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -28,6 +28,7 @@ OBJS = allcodecs.o \ OBJS-$(CONFIG_AANDCT) += aandcttab.o OBJS-$(CONFIG_ENCODERS) += faandct.o jfdctfst.o jfdctint.o OBJS-$(CONFIG_DCT) += dct.o +OBJS-$(CONFIG_DXVA2) += dxva2.o FFT-OBJS-$(CONFIG_HARDCODED_TABLES) += cos_tables.o OBJS-$(CONFIG_FFT) += fft.o $(FFT-OBJS-yes) OBJS-$(CONFIG_GOLOMB) += golomb.o @@ -665,6 +666,7 @@ OBJS-$(HAVE_MMI) += ps2/dsputil_mmi.o \ OBJS-$(HAVE_VIS) += sparc/dsputil_vis.o \ sparc/simple_idct_vis.o \ +SKIPHEADERS-$(CONFIG_DXVA2) += dxva2_internal.h SKIPHEADERS-$(CONFIG_LIBDIRAC) += libdirac.h SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER) += libschroedinger.h SKIPHEADERS-$(CONFIG_VAAPI) += vaapi_internal.h diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c new file mode 100644 index 0000000000..3f14311c9a --- /dev/null +++ b/libavcodec/dxva2.c @@ -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; +} + diff --git a/libavcodec/dxva2_h264.c b/libavcodec/dxva2_h264.c index bc42bf77c0..d507becc41 100644 --- a/libavcodec/dxva2_h264.c +++ b/libavcodec/dxva2_h264.c @@ -20,10 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "dxva2.h" -#include "avcodec.h" - -#include "mpegvideo.h" +#include "dxva2_internal.h" #include "h264.h" #include "h264data.h" @@ -37,24 +34,6 @@ struct dxva2_picture_context { unsigned bitstream_size; }; -static void *ff_dxva2_get_surface(const Picture *picture) -{ - return picture->data[3]; -} -static 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; -} - static void fill_picture_entry(DXVA_PicEntry_H264 *pic, unsigned index, unsigned flag) { @@ -277,41 +256,6 @@ static void fill_slice_long(AVCodecContext *avctx, DXVA_Slice_H264_Long *slice, slice->slice_id = h->current_slice - 1; } -static 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; -} - static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, DXVA2_DecodeBufferDesc *bs, DXVA2_DecodeBufferDesc *sc) @@ -464,82 +408,6 @@ static int decode_slice(AVCodecContext *avctx, return 0; } -static 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; -} - static int end_frame(AVCodecContext *avctx) { H264Context *h = avctx->priv_data; diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h new file mode 100644 index 0000000000..a9be7a07e7 --- /dev/null +++ b/libavcodec/dxva2_internal.h @@ -0,0 +1,48 @@ +/* + * 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 + */ + +#ifndef AVCODEC_DXVA_INTERNAL_H +#define AVCODEC_DXVA_INTERNAL_H + +#include "dxva2.h" +#include "avcodec.h" +#include "mpegvideo.h" + +void *ff_dxva2_get_surface(const Picture *picture); + +unsigned ff_dxva2_get_surface_index(const struct dxva_context *, + const Picture *picture); + +int ff_dxva2_commit_buffer(AVCodecContext *, struct dxva_context *, + DXVA2_DecodeBufferDesc *, + unsigned type, const void *data, unsigned size, + unsigned mb_count); + + +int ff_dxva2_common_end_frame(AVCodecContext *, MpegEncContext *, + const void *pp, unsigned pp_size, + const void *qm, unsigned qm_size, + int (*commit_bs_si)(AVCodecContext *, + DXVA2_DecodeBufferDesc *bs, + DXVA2_DecodeBufferDesc *slice)); + +#endif /* AVCODEC_DXVA_INTERNAL_H */