[FFmpeg-devel] [PATCH] libavcodec:add dxva2 decoder for h264, mpeg2, vc1.wmv3

Michael Niedermayer michaelni at gmx.at
Sat Mar 2 13:39:41 CET 2013


On Wed, Jan 23, 2013 at 04:15:44PM +0800, Wei Gao wrote:
> Hi,Hendrik
> 
> - The handling of the parser in the h264 part of check_format looks
> quite broken, i have no clue what its supposed to do? You have no data
> to parse there.
> 
> This parser, I reference vda process for h264 to check the format, I think
> it just get the H264Context, using av_parser_parse2, and then check the
> format.
> 
> - get_mpeg2_video_format assumes there always is extradata, which may
> not be the case, and should be checked.
> 
> I just check whether the extra data is exist. Also I want to ask a question
> that is the chroma_format always stored in the ext sequence header?
> 
> The attachment is the patch I modified.
> 
> Thanks
> 
> Best regards
[...]
> +static int get_buffer(struct AVCodecContext *avctx, AVFrame *pic)
> +{
> +    int ret;
> +    DXVA2_DecoderContext *ctx = (DXVA2_DecoderContext *)avctx->priv_data;
> +    dxva2_context *dxva2_ctx = &ctx->dxva2_ctx;
> +    avctx->pix_fmt = ctx->pix_fmt;
> +    ff_init_buffer_info(avctx, pic);
> +    if ((ret = ctx->get_buffer(avctx,pic)) < 0) {
> +        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
> +        return ret;
> +    }
> +    if (dxva2_ctx) {
> +        if (ff_get_dxva2_surface(dxva2_ctx, pic)) {
> +            av_log(NULL, AV_LOG_ERROR, "VaGrabSurface failed");
> +            return -1;
> +        }
> +        return 0;
> +    } else {

> +        av_log(NULL, AV_LOG_ERROR, "No dxva2 context, get buffer failed");

av_log() should have a context other than NULL to asscociate error
messages with the right thing


> +        return -1;

more specific error codes would be better


[...]
> +static int get_mpeg2_video_format(AVCodecContext *avctx)
> +{
> +    Mpeg1Context *s = avctx->priv_data;
> +    MpegEncContext *s2 = &s->mpeg_enc_ctx;
> +    const uint8_t *buf_ptr = avctx->extradata;
> +    const uint8_t *buf_end = avctx->extradata + avctx->extradata_size;
> +    int input_size;
> +    int format = -1;

> +    if (avctx->extradata) {
> +    for (;;) {

Indention is wrong


[...]
> diff --git a/libavcodec/dxva2_h264_dec.c b/libavcodec/dxva2_h264_dec.c
> new file mode 100644
> index 0000000..4fdc243
> --- /dev/null
> +++ b/libavcodec/dxva2_h264_dec.c
> @@ -0,0 +1,60 @@
> +/*
> + * Call hardware decode acceleration through dxva2 API for h264
> +
> + * Copyright (c) 2012 Wei Gao <weigao at multicorewareinc.com>
> + *
> + * 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_dec.h"
> +
> +extern AVCodec ff_h264_decoder, ff_h264_dxva2_decoder;
> +
> +static int h264_dxva2dec_decode(AVCodecContext *avctx, void *data, int *got_frame,
> +                                  AVPacket *avpkt)
> +{
> +    return ff_dxva2dec_decode(avctx,data,got_frame,avpkt,&ff_h264_decoder);
> +}
> +
> +static av_cold int h264_dxva2dec_close(AVCodecContext *avctx)
> +{
> +    return ff_dxva2dec_close(avctx,&ff_h264_decoder);
> +}
> +
> +static av_cold int h264_dxva2dec_init(AVCodecContext *avctx)
> +{
> +    return ff_dxva2dec_init(avctx,&ff_h264_dxva2_decoder,&ff_h264_decoder);
> +}
> +
> +static void h264_dxva2dec_flush(AVCodecContext *avctx)
> +{
> +    ff_dxva2dec_flush(avctx,&ff_h264_decoder);
> +}
> +
> +AVCodec ff_h264_dxva2_decoder = {
> +    .name           = "h264_dxva2",
> +    .type           = AVMEDIA_TYPE_VIDEO,
> +    .id             = AV_CODEC_ID_H264,
> +    .priv_data_size = sizeof(DXVA2_DecoderContext),
> +    .init           = h264_dxva2dec_init,
> +    .close          = h264_dxva2dec_close,
> +    .decode         = h264_dxva2dec_decode,
> +    .capabilities   = CODEC_CAP_DELAY,
> +    .flush          = h264_dxva2dec_flush,
> +    .long_name      = NULL_IF_CONFIG_SMALL("H.264 (DXVA2 acceleration)"),
> +};
> +
> +
> diff --git a/libavcodec/dxva2_mpeg2_dec.c b/libavcodec/dxva2_mpeg2_dec.c
> new file mode 100644
> index 0000000..18982b4
> --- /dev/null
> +++ b/libavcodec/dxva2_mpeg2_dec.c
> @@ -0,0 +1,58 @@
> + /*
> + * Call hardware decode acceleration through dxva2 API for mpeg2
> +
> + * Copyright (c) 2012 Wei Gao <weigao at multicorewareinc.com>
> + *
> + * 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_dec.h"
> +
> +extern AVCodec ff_mpeg2video_decoder, ff_mpeg2video_dxva2_decoder;
> +
> +static int mpeg2video_dxva2dec_decode(AVCodecContext *avctx, void *data, int *got_frame,
> +                                  AVPacket *avpkt)
> +{
> +    return ff_dxva2dec_decode(avctx,data,got_frame,avpkt,&ff_mpeg2video_decoder);
> +}
> +
> +static av_cold int mpeg2video_dxva2dec_close(AVCodecContext *avctx)
> +{
> +    return ff_dxva2dec_close(avctx,&ff_mpeg2video_decoder);
> +}
> +
> +static av_cold int mpeg2video_dxva2dec_init(AVCodecContext *avctx)
> +{
> +    return ff_dxva2dec_init(avctx,&ff_mpeg2video_dxva2_decoder,&ff_mpeg2video_decoder);
> +}
> +
> +static void mpeg2video_dxva2dec_flush(AVCodecContext *avctx)
> +{
> +    ff_dxva2dec_flush(avctx,&ff_mpeg2video_decoder);
> +}
> +
> +AVCodec ff_mpeg2video_dxva2_decoder = {
> +    .name           = "mpeg2video_dxva2",
> +    .type           = AVMEDIA_TYPE_VIDEO,
> +    .id             = AV_CODEC_ID_MPEG2VIDEO,
> +    .priv_data_size = sizeof(DXVA2_DecoderContext),
> +    .init           = mpeg2video_dxva2dec_init,
> +    .close          = mpeg2video_dxva2dec_close,
> +    .decode         = mpeg2video_dxva2dec_decode,
> +    .capabilities   = CODEC_CAP_DELAY,
> +    .flush          = mpeg2video_dxva2dec_flush,
> +    .long_name      = NULL_IF_CONFIG_SMALL("MPEG2 Video (DXVA2 acceleration)"),
> +};
> diff --git a/libavcodec/dxva2_vc1_dec.c b/libavcodec/dxva2_vc1_dec.c
> new file mode 100644
> index 0000000..06ad761
> --- /dev/null
> +++ b/libavcodec/dxva2_vc1_dec.c
> @@ -0,0 +1,58 @@
> + /*
> + * Call hardware decode acceleration through dxva2 API for vc1
> +
> + * Copyright (c) 2012 Wei Gao <weigao at multicorewareinc.com>
> + *
> + * 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_dec.h"
> +
> +extern AVCodec ff_vc1_decoder, ff_vc1_dxva2_decoder;
> +
> +static int vc1_dxva2dec_decode(AVCodecContext *avctx, void *data, int *got_frame,
> +                                  AVPacket *avpkt)
> +{
> +    return ff_dxva2dec_decode(avctx,data,got_frame,avpkt,&ff_vc1_decoder);
> +}
> +
> +static av_cold int vc1_dxva2dec_close(AVCodecContext *avctx)
> +{
> +    return ff_dxva2dec_close(avctx,&ff_vc1_decoder);
> +}
> +
> +static av_cold int vc1_dxva2dec_init(AVCodecContext *avctx)
> +{
> +    return ff_dxva2dec_init(avctx,&ff_vc1_dxva2_decoder,&ff_vc1_decoder);
> +}
> +
> +static void vc1_dxva2dec_flush(AVCodecContext *avctx)
> +{
> +    ff_dxva2dec_flush(avctx,&ff_vc1_decoder);
> +}
> +
> +AVCodec ff_vc1_dxva2_decoder = {
> +    .name           = "vc1_dxva2",
> +    .type           = AVMEDIA_TYPE_VIDEO,
> +    .id             = AV_CODEC_ID_VC1,
> +    .priv_data_size = sizeof(DXVA2_DecoderContext),
> +    .init           = vc1_dxva2dec_init,
> +    .close          = vc1_dxva2dec_close,
> +    .decode         = vc1_dxva2dec_decode,
> +    .capabilities   = CODEC_CAP_DELAY,
> +    .flush          = vc1_dxva2dec_flush,
> +    .long_name      = NULL_IF_CONFIG_SMALL("VC1 (DXVA2 acceleration)"),
> +};
> diff --git a/libavcodec/dxva2_wmv3_dec.c b/libavcodec/dxva2_wmv3_dec.c
> new file mode 100644
> index 0000000..5593cfc
> --- /dev/null
> +++ b/libavcodec/dxva2_wmv3_dec.c
> @@ -0,0 +1,60 @@
> +/*
> + * Call hardware decode acceleration through dxva2 API for wmv3
> +
> + * Copyright (c) 2012 Wei Gao <weigao at multicorewareinc.com>
> + *
> + * 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_dec.h"
> +
> +extern AVCodec ff_wmv3_decoder, ff_wmv3_dxva2_decoder;
> +
> +static int wmv3_dxva2dec_decode(AVCodecContext *avctx, void *data, int *got_frame,
> +                                  AVPacket *avpkt)
> +{
> +    return ff_dxva2dec_decode(avctx,data,got_frame,avpkt,&ff_wmv3_decoder);
> +}
> +
> +static av_cold int wmv3_dxva2dec_close(AVCodecContext *avctx)
> +{
> +    return ff_dxva2dec_close(avctx,&ff_wmv3_decoder);
> +}
> +
> +static av_cold int wmv3_dxva2dec_init(AVCodecContext *avctx)
> +{
> +    return ff_dxva2dec_init(avctx,&ff_wmv3_dxva2_decoder,&ff_wmv3_decoder);
> +}
> +
> +static void wmv3_dxva2dec_flush(AVCodecContext *avctx)
> +{
> +    ff_dxva2dec_flush(avctx,&ff_wmv3_decoder);
> +}

these are quite a few wraper functions. i suspect this can be
done without wraper functions, which should be simpler


[...]
> +/**
> +* It creates a Direct3D device usable for DXVA 2
> +*/
> +static int d3d_create_device(dxva2_context *va)
> +{
> +    typedef LPDIRECT3D9 (WINAPI *Create9func)(UINT SDKVersion);
> +    typedef HWND (WINAPI *PROCGETSHELLWND)(void);
> +    Create9func Create9 = (Create9func )GetProcAddress(va->hd3d9_dll, TEXT("Direct3DCreate9"));
> +    LPDIRECT3D9 d3dobj;
> +    D3DADAPTER_IDENTIFIER9 *d3dai = &va->d3dai;
> +    PROCGETSHELLWND GetShellWindow;
> +    HMODULE hUser32 = GetModuleHandle( "user32" );
> +    D3DPRESENT_PARAMETERS *d3dpp = &va->d3dpp;
> +    LPDIRECT3DDEVICE9 d3ddev;
> +    if (!Create9) {
> +        av_log(NULL, AV_LOG_ERROR, "Cannot locate reference to Direct3DCreate9 ABI in DLL");
> +        return -1;
> +    }
> +    d3dobj = Create9(D3D_SDK_VERSION);
> +    if (!d3dobj) {
> +        av_log(NULL, AV_LOG_ERROR, "Direct3DCreate9 failed");
> +        return -1;
> +    }
> +    va->d3dobj = d3dobj;
> +    if (FAILED(IDirect3D9_GetAdapterIdentifier(va->d3dobj,
> +        D3DADAPTER_DEFAULT, 0, d3dai))) {
> +            av_log(NULL, AV_LOG_WARNING, "IDirect3D9_GetAdapterIdentifier failed");
> +            ZeroMemory(d3dai, sizeof(*d3dai));
> +    }
> +    GetShellWindow = (PROCGETSHELLWND)
> +                     GetProcAddress( hUser32, "GetShellWindow" );

> +    ZeroMemory(d3dpp, sizeof(*d3dpp));
> +    d3dpp->Flags                              = D3DPRESENTFLAG_VIDEO;
> +    d3dpp->Windowed                     = TRUE;
> +    d3dpp->hDeviceWindow           = NULL;
> +    d3dpp->SwapEffect                   = D3DSWAPEFFECT_DISCARD;
> +    d3dpp->MultiSampleType         = D3DMULTISAMPLE_NONE;
> +    d3dpp->PresentationInterval     = D3DPRESENT_INTERVAL_DEFAULT;
> +    d3dpp->BackBufferCount         = 0;
> +    d3dpp->BackBufferFormat       = D3DFMT_X8R8G8B8;
> +    d3dpp->BackBufferWidth          = 0;
> +    d3dpp->BackBufferHeight         = 0;
> +    d3dpp->EnableAutoDepthStencil = FALSE;

its up to you if you vertically align "=" under each other or not in
your code but this really looks sloppy

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Let us carefully observe those good qualities wherein our enemies excel us
and endeavor to excel them, by avoiding what is faulty, and imitating what
is excellent in them. -- Plutarch
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20130302/2a3835b4/attachment.asc>


More information about the ffmpeg-devel mailing list