[FFmpeg-devel] [PATCH] add code to make ffmpeg.exe can use dxva2 api

Wei Gao highgod0401 at gmail.com
Thu Dec 13 02:40:53 CET 2012


>From 8703b8e3bf9489b3081885a36014fa761a04522e Mon Sep 17 00:00:00 2001
From: highgod <highgod0401 at gmail.com>
Date: Wed, 12 Dec 2012 16:55:36 +0800
Subject: [PATCH] add code to make ffmpeg.exe can use dxva2 api

---
 cmdutils.c           |    4 +
 ffmpeg.c             |  194 ++++++++-
 ffmpeg.h             |    1 +
 ffmpeg_opt.c         |    6 +-
 libavcodec/Makefile  |    3 +-
 libavcodec/avcodec.h |    5 +-
 libavcodec/pthread.c |  279 ++++++++++++-
 libavcodec/thread.h  |    6 +
 libavcodec/utils.c   |   15 +
 libavcodec/vadxva2.c | 1084
++++++++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/vadxva2.h |  201 ++++++++++
 11 files changed, 1792 insertions(+), 6 deletions(-)
 create mode 100644 libavcodec/vadxva2.c
 create mode 100644 libavcodec/vadxva2.h

diff --git a/cmdutils.c b/cmdutils.c
index abe5601..75f7b8b 100644
--- a/cmdutils.c
+++ b/cmdutils.c
@@ -1651,6 +1651,10 @@ int codec_get_buffer(AVCodecContext *s, AVFrame
*frame)
         if ((ret = alloc_buffer(pool, s, &buf)) < 0)
             return ret;
     }
+ if(s->dxva2flg)
+ {
+ buf->refcount = 0;
+ }
     av_assert0(!buf->refcount);
     buf->refcount++;

diff --git a/ffmpeg.c b/ffmpeg.c
index 4b278a2..59ceaf6 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -104,11 +104,18 @@

 #include "libavutil/avassert.h"

+#if CONFIG_DXVA2
+
+#include "libavcodec/vadxva2.h"
+
+#endif
+
 const char program_name[] = "ffmpeg";
 const int program_birth_year = 2000;

 static FILE *vstats_file;

+#define HWACCEL_DELAY_RET 0x7FFFFFFF
 static void do_video_stats(OutputStream *ost, int frame_size);
 static int64_t getutime(void);

@@ -1574,10 +1581,39 @@ static int decode_video(InputStream *ist, AVPacket
*pkt, int *got_output)
     decoded_frame = ist->decoded_frame;
     pkt->dts  = av_rescale_q(ist->dts, AV_TIME_BASE_Q, ist->st->time_base);

+    #if CONFIG_DXVA2
+ if((ist->st->codec->nb_hw_delay_frames) && (pkt->data == NULL) &&
((ist->st->codec->codec_id== AV_CODEC_ID_WMV3))&&(ist->st->codec->dxva2flg))
+ {
+ void *temp_opaque = ist->st->codec->opaque;
+ int temp_fmt = ist->st->codec->pix_fmt;
+        ist->st->codec->pix_fmt = AV_PIX_FMT_YUV420P;
+ ist->st->codec->opaque = ist->st->codec->opaque_bak;
+ ret = codec_get_buffer(ist->st->codec,decoded_frame);
+ ist->st->codec->opaque = temp_opaque;
+ ist->st->codec->pix_fmt = temp_fmt;
+ ff_va_dxva2_t *dxva2 = ist->st->codec->opaque;
+ dxva2->d3ddata = dxva2->d3ddata_delay[DELAY_FRAMES_NUM -
ist->st->codec->nb_hw_delay_frames];
+ decoded_frame->coded_picture_number = ist->st->codec->frame_number++;
+ *got_output = 1;
+ ret = HWACCEL_DELAY_RET;
+ }
+ else
+ {
+    update_benchmark(NULL);
+    ret = avcodec_decode_video2(ist->st->codec,
+                                decoded_frame, got_output, pkt);
+    update_benchmark("decode_video %d.%d", ist->file_index,
ist->st->index);
+
+ }
+#else
+
     update_benchmark(NULL);
     ret = avcodec_decode_video2(ist->st->codec,
                                 decoded_frame, got_output, pkt);
     update_benchmark("decode_video %d.%d", ist->file_index,
ist->st->index);
+
+#endif
+
     if (!*got_output || ret < 0) {
         if (!pkt->size) {
             for (i = 0; i < ist->nb_filters; i++)
@@ -1585,7 +1621,38 @@ static int decode_video(InputStream *ist, AVPacket
*pkt, int *got_output)
         }
         return ret;
     }
+#if CONFIG_DXVA2
+
+ if(((ist->st->codec->codec_id==
AV_CODEC_ID_WMV3))&&(ist->st->codec->dxva2flg))
+ {
+ av_save_framepts_info(ist->st->codec->opaque,decoded_frame);
+ if(decoded_frame->coded_picture_number < DELAY_FRAMES_NUM)
+ {
+ *got_output = 0;
+ }
+ }
+ if (!*got_output || ret < 0) {
+        if (!pkt->size) {
+            for (i = 0; i < ist->nb_filters; i++)
+                av_buffersrc_add_ref(ist->filters[i]->filter, NULL, 0);
+        }
+        return ret;
+    }
+ /*add to test out put pkt format*/
+ if((*got_output)&&(ist->st->codec->opaque)&&(ist->st->codec->dxva2flg))
+ {
+
+ if(!av_extract_dxva2(
ist->st->codec->opaque,decoded_frame,ist->st->codec->codec_id))
+ {
+ av_log(NULL,AV_LOG_ERROR,"hb_va_extract Eorror\n");
+ }
+ FrameBuffer      *buf = decoded_frame->opaque;
+ buf->refcount = 1;
+ decoded_frame->format = ist->resample_pix_fmt;
+
+ }

+#endif
     if(ist->top_field_first>=0)
         decoded_frame->top_field_first = ist->top_field_first;

@@ -1649,11 +1716,17 @@ static int decode_video(InputStream *ist, AVPacket
*pkt, int *got_output)
                                         AV_PERM_READ | AV_PERM_PRESERVE,
                                         ist->st->codec->width,
ist->st->codec->height,
                                         ist->st->codec->pix_fmt);
-
+        if(ist->st->codec->dxva2flg)
+    {
+ fb->data[3] = NULL;
+    }
             avfilter_copy_frame_props(fb, decoded_frame);
             fb->buf->priv           = buf;
             fb->buf->free           = filter_release_buffer;
-
+        if((ist->st->codec->codec_id==
AV_CODEC_ID_H264)&&(ist->st->codec->dxva2flg))
+    {
+ (buf->refcount==0)?buf->refcount++:buf->refcount;
+    }
             av_assert0(buf->refcount>0);
             buf->refcount++;
             av_buffersrc_add_ref(ist->filters[i]->filter, fb,
@@ -1815,6 +1888,13 @@ static int output_packet(InputStream *ist, const
AVPacket *pkt)
             avpkt.data += ret;
             avpkt.size -= ret;
         }
+#if CONFIG_DXVA2
+
+ if((HWACCEL_DELAY_RET == ret))
+ {
+ break;
+ }
+#endif
         if (!got_output) {
             continue;
         }
@@ -1887,9 +1967,67 @@ static int init_input_stream(int ist_index, char
*error, int error_len)

         ist->dr1 = (codec->capabilities & CODEC_CAP_DR1) &&
!do_deinterlace;
         if (codec->type == AVMEDIA_TYPE_VIDEO && ist->dr1) {
+
+
+#if CONFIG_DXVA2
+ if(use_dxva2)
+ {
+    AVCodecContext *codecctx = ist->st->codec;
+ if( ( (codecctx->codec_id == AV_CODEC_ID_WMV3) || (codecctx->codec_id ==
AV_CODEC_ID_VC1) ||(codecctx->codec_id ==
 AV_CODEC_ID_H264)||(codecctx->codec_id == AV_CODEC_ID_MPEG2VIDEO)))
+ {
+ codecctx->pdxva2 = av_new_dxva2(codecctx->codec_id);
+ if(NULL == codecctx->pdxva2)
+ {
+ return 0;
+ }
+
+ int res = av_setup_dxva2(codecctx->pdxva2, &codecctx->hwaccel_context,
&codecctx->pix_fmt, codecctx->width,
codecctx->height,codec_get_buffer,codec_release_buffer);
+ if (res < 0)
+ {
+ av_log(NULL,AV_LOG_ERROR,"error DXVA setup %d\n", res);
+ return 1;
+ }
+
+ codecctx->opaque = codecctx->pdxva2;
+ codecctx->opaque_bak = &ist->buffer_pool;
+ codecctx->get_format = av_dxva2_get_format;
+ codecctx->get_buffer = av_dxva2_get_buffer;
+ codecctx->reget_buffer = av_dxva2_reget_buffer;
+ codecctx->release_buffer = av_dxva2_release_buffer;
+
+ if((codecctx->codec_id == AV_CODEC_ID_WMV3))
+ {
+ codecctx->nb_hw_delay_frames = DELAY_FRAMES_NUM;
+ }
+ codecctx->dxva2flg = use_dxva2;
+ }
+ else
+ {
+
+ ist->st->codec->nb_hw_delay_frames = 0;
+            ist->st->codec->get_buffer     = codec_get_buffer;
+            ist->st->codec->release_buffer = codec_release_buffer;
+            ist->st->codec->opaque         = &ist->buffer_pool;
+        }
+
+ }
+ else
+ {
+ AVCodecContext *codecctx = ist->st->codec;
+
+    ist->st->codec->nb_hw_delay_frames = 0;
+            ist->st->codec->get_buffer     = codec_get_buffer;
+            ist->st->codec->release_buffer = codec_release_buffer;
+ ist->st->codec->opaque         = &ist->buffer_pool;
+         }
+#else
+
+    ist->st->codec->nb_hw_delay_frames = 0;
             ist->st->codec->get_buffer     = codec_get_buffer;
             ist->st->codec->release_buffer = codec_release_buffer;
             ist->st->codec->opaque         = &ist->buffer_pool;
+
+#endif
         }

         if (!av_dict_get(ist->opts, "threads", NULL, 0))
@@ -2967,6 +3105,51 @@ static int transcode_step(void)
     }

     ret = process_input(ist->file_index);
+
+    #if CONFIG_DXVA2
+ if(ret < 0)
+ {
+ //find video stream
+    InputStream *tempist;
+    int file_index = -1;
+    int64_t ipts_min = INT64_MAX;
+            for (int i = 0; i < nb_input_streams; i++)
+    {
+                int64_t ipts;
+                ist = input_streams[i];
+                ipts = ist->pts;
+                if (ist->discard)
+                {
+                    continue;
+                }
+                if (input_files[ist->file_index]->eof_reached)
+        {
+
+                    file_index = ist->file_index;
+                }
+             }
+ if(file_index >= 0)
+ {
+    for (int i = 0; i < input_files[file_index]->nb_streams; i++)
+                {
+                    tempist =
input_streams[input_files[file_index]->ist_index + i];
+                    if(tempist->st->codec->codec_type ==
AVMEDIA_TYPE_VIDEO)
+                    {
+                break;
+                    }
+            }
+    while(tempist->st->codec->nb_hw_delay_frames - 1)
+    {
+     output_packet(tempist, NULL);
+                                reap_filters();
+ tempist->st->codec->nb_hw_delay_frames--;
+    }
+ }
+
+
+ ost->finished = 1;
+ }
+#endif
     if (ret == AVERROR(EAGAIN)) {
         if (input_files[ist->file_index]->eagain)
             ost->unavailable = 1;
@@ -3095,6 +3278,13 @@ static int transcode(void)
             }
         }
     }
+#if CONFIG_DXVA2
+ if(use_dxva2)
+ {
+ av_release_dxva2();
+
+ }
+#endif
     return ret;
 }

diff --git a/ffmpeg.h b/ffmpeg.h
index d260222..2b818b7 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -392,6 +392,7 @@ extern const AVIOInterruptCB int_cb;

 extern const OptionDef options[];

+extern int use_dxva2;
 void term_init(void);
 void term_exit(void);

diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
index c846a10..e962b07 100644
--- a/ffmpeg_opt.c
+++ b/ffmpeg_opt.c
@@ -87,6 +87,8 @@ int stdin_interaction = 1;
 int frame_bits_per_raw_sample = 0;


+int use_dxva2 = 0;
+
 static int intra_only         = 0;
 static int file_overwrite     = 0;
 static int no_file_overwrite  = 0;
@@ -2521,7 +2523,9 @@ const OptionDef options[] = {
         "force data codec ('copy' to copy stream)", "codec" },
     { "dn", OPT_BOOL | OPT_VIDEO | OPT_OFFSET, { .off =
OFFSET(data_disable) },
         "disable data" },
-
+#if CONFIG_DXVA2
+    { "dxva2", OPT_BOOL | OPT_EXPERT, {(void*)&use_dxva2},"use dxva2
hwaccel" },
+#endif
     { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, { .func_arg
= opt_default },
         "generic catch all option", "" },
     { NULL, },
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 0507028..3b479b0 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -12,6 +12,7 @@ HEADERS = avcodec.h
              \
           vdpau.h                                                       \
           version.h                                                     \
           xvmc.h                                                        \
+          vadxva2.h

 OBJS = allcodecs.o                                                      \
        audioconvert.o                                                   \
@@ -42,7 +43,7 @@ OBJS-$(CONFIG_AC3DSP)                  += ac3dsp.o
 OBJS-$(CONFIG_CRYSTALHD)               += crystalhd.o
 OBJS-$(CONFIG_DCT)                     += dct.o dct32_fixed.o dct32_float.o
 OBJS-$(CONFIG_DWT)                     += dwt.o snow.o
-OBJS-$(CONFIG_DXVA2)                   += dxva2.o
+OBJS-$(CONFIG_DXVA2)                   += dxva2.o vadxva2.o
 OBJS-$(CONFIG_ENCODERS)                += faandct.o jfdctfst.o jfdctint.o
 OBJS-$(CONFIG_ERROR_RESILIENCE)        += error_resilience.o
 FFT-OBJS-$(CONFIG_HARDCODED_TABLES)    += cos_tables.o cos_fixed_tables.o
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index e432040..1af8435 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1570,7 +1570,10 @@ typedef struct AVCodecContext {
      * - decoding: Set by user.
      */
     void *opaque;
-
+    void *opaque_bak;
+    void *pdxva2;
+    int dxva2flg;
+    uint8_t nb_hw_delay_frames;//add for wmv3 hwaccel
     /**
      * the average bitrate
      * - encoding: Set by user; unused for constant quantizer encoding.
diff --git a/libavcodec/pthread.c b/libavcodec/pthread.c
index ed6f0e1..91c1ec1 100644
--- a/libavcodec/pthread.c
+++ b/libavcodec/pthread.c
@@ -54,7 +54,11 @@
 #include "internal.h"
 #include "thread.h"
 #include "libavutil/common.h"
+#if CONFIG_DXVA2

+#include "vadxva2.h"
+
+#endif
 #if HAVE_PTHREADS
 #include <pthread.h>
 #elif HAVE_W32THREADS
@@ -104,6 +108,7 @@ typedef struct PerThreadContext {

     AVCodecContext *avctx;          ///< Context used to decode packets
passed to this thread.

+ int64_t        predts;          ///add for save pts for dxva2
     AVPacket       avpkt;           ///< Input packet (for decoding) or
output (for encoding).
     int            allocated_buf_size; ///< Size allocated for avpkt.data

@@ -318,6 +323,11 @@ static int thread_init(AVCodecContext *avctx)
             thread_count = avctx->thread_count = 1;
     }

+ if(avctx->dxva2flg)
+ {
+ thread_count = 1;
+ }
+
     if (thread_count <= 1) {
         avctx->active_thread_type = 0;
         return 0;
@@ -365,6 +375,37 @@ static int thread_init(AVCodecContext *avctx)
  * not provide an update_thread_context method, or if the codec returns
  * before calling it.
  */
+ #if CONFIG_DXVA2
+static attribute_align_arg void *frame_worker_thread_dxva2(void *arg)
+{
+ PerThreadContext *p = arg;
+    FrameThreadContext *fctx = p->parent;
+    AVCodecContext *avctx = p->avctx;
+    AVCodec *codec = avctx->codec;
+ pthread_mutex_lock(&p->mutex);
+ while(1)
+ {
+    int i;
+        if (p->state == STATE_INPUT_READY && !fctx->die) {
+
+            while (p->state == STATE_INPUT_READY)
+                pthread_cond_wait(&p->input_cond, &p->mutex);
+
+        }
+ if (fctx->die) break;
+
+ avcodec_get_frame_defaults(&p->frame);
+ p->result = avctx->codec->decode(avctx, &p->frame, &p->got_frame,
&p->avpkt);
+ pthread_mutex_lock(&p->mutex);
+ p->state = STATE_INPUT_READY;
+ pthread_cond_signal(&p->output_cond);
+ pthread_mutex_unlock(&p->mutex);
+
+ }
+ pthread_mutex_unlock(&p->mutex);
+ return NULL;
+}
+ #endif
 static attribute_align_arg void *frame_worker_thread(void *arg)
 {
     PerThreadContext *p = arg;
@@ -507,7 +548,52 @@ static int update_context_from_user(AVCodecContext
*dst, AVCodecContext *src)
     return 0;
 #undef copy_fields
 }
+#if CONFIG_DXVA2
+
+static int update_context_from_user_dxva2(AVCodecContext *dst,
AVCodecContext *src)
+{
+#define copy_fields(s, e) memcpy(&dst->s, &src->s, (char*)&dst->e -
(char*)&dst->s);
+    dst->flags          = src->flags;
+
+    dst->draw_horiz_band= src->draw_horiz_band;
+    dst->get_buffer     = src->get_buffer;
+    dst->release_buffer = src->release_buffer;

+    dst->opaque   = src->opaque;
+ dst->hwaccel_context = src->hwaccel_context;
+ dst->hwaccel = src->hwaccel;
+    dst->dsp_mask = src->dsp_mask;
+    dst->debug    = src->debug;
+    dst->debug_mv = src->debug_mv;
+
+
+    dst->slice_flags = src->slice_flags;
+    dst->flags2      = src->flags2;
+
+    copy_fields(skip_loop_filter, subtitle_header);
+
+    dst->frame_number     = src->frame_number;
+    dst->reordered_opaque = src->reordered_opaque;
+    dst->thread_safe_callbacks = src->thread_safe_callbacks;
+
+    if (src->slice_count && src->slice_offset) {
+        if (dst->slice_count < src->slice_count) {
+            int *tmp = av_realloc(dst->slice_offset, src->slice_count *
+                                  sizeof(*dst->slice_offset));
+            if (!tmp) {
+                av_free(dst->slice_offset);
+                return AVERROR(ENOMEM);
+            }
+            dst->slice_offset = tmp;
+        }
+        memcpy(dst->slice_offset, src->slice_offset,
+               src->slice_count * sizeof(*dst->slice_offset));
+    }
+    dst->slice_count = src->slice_count;
+    return 0;
+#undef copy_fields
+}
+#endif
 static void free_progress(AVFrame *f)
 {
     PerThreadContext *p = f->owner->thread_opaque;
@@ -601,6 +687,102 @@ static int submit_packet(PerThreadContext *p,
AVPacket *avpkt)
     return 0;
 }

+#if CONFIG_DXVA2
+
+static int submit_packet_dxva2(PerThreadContext *p, AVPacket *avpkt)
+{
+    FrameThreadContext *fctx = p->parent;
+    PerThreadContext *prev_thread = fctx->prev_thread;
+    AVCodec *codec = p->avctx->codec;
+    uint8_t *buf = p->avpkt.data;
+
+    if (!avpkt->size && !(codec->capabilities & CODEC_CAP_DELAY)) return 0;
+
+    pthread_mutex_lock(&p->mutex);
+    av_fast_malloc(&buf, &p->allocated_buf_size, avpkt->size +
FF_INPUT_BUFFER_PADDING_SIZE);
+    p->avpkt = *avpkt;
+    p->avpkt.data = buf;
+    memcpy(buf, avpkt->data, avpkt->size);
+    memset(buf + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
+    pthread_mutex_unlock(&p->mutex);
+    return 0;
+}
+#endif
+#if CONFIG_DXVA2
+
+int ff_thread_decode_frame_dxva2(AVCodecContext *avctx,
+                           AVFrame *picture, int *got_picture_ptr,
+                           AVPacket *avpkt)
+{
+ FrameThreadContext *fctx = avctx->thread_opaque;
+ PerThreadContext *p;
+ int err;
+    AVCodecContext Tempavctx;
+ p = &fctx->threads[0];
+
+ if (fctx->delaying && avpkt->size) {
+ if (p->state != STATE_INPUT_READY) {
+        pthread_mutex_lock(&p->progress_mutex);
+        while (p->state != STATE_INPUT_READY)
+        {
+            pthread_cond_wait(&p->output_cond, &p->progress_mutex);
+        }
+        pthread_mutex_unlock(&p->progress_mutex);
+    }
+ p->predts = avpkt->pts;
+        fctx->delaying = 0;
+ err = update_context_from_user_dxva2(p->avctx, avctx);
+    if (err) return err;
+    err = submit_packet_dxva2(p, avpkt);
+    if (err) return err;
+
+ pthread_mutex_lock(&p->progress_mutex);
+ p->state = STATE_SETUP_FINISHED;
+    pthread_cond_signal(&p->input_cond);
+    pthread_mutex_unlock(&p->progress_mutex);
+
+        *got_picture_ptr=0;
+        return avpkt->size;
+    }
+ else if(!fctx->delaying)
+ {
+
+    if (p->state != STATE_INPUT_READY) {
+        pthread_mutex_lock(&p->progress_mutex);
+        while (p->state != STATE_INPUT_READY)
+        {
+            pthread_cond_wait(&p->output_cond, &p->progress_mutex);
+        }
+        pthread_mutex_unlock(&p->progress_mutex);
+    }
+ *picture = p->frame;
+    *got_picture_ptr = p->got_frame;
+
+    picture->pkt_dts = p->predts;;
+ p->predts = p->avpkt.dts;;;
+    picture->sample_aspect_ratio = avctx->sample_aspect_ratio;
+    picture->width  = avctx->width;
+    picture->height = avctx->height;
+    picture->format = avctx->pix_fmt;
+ picture->pkt_pts  = &p->avpkt ? p->predts : AV_NOPTS_VALUE;
+
+
+    p->got_frame = 0;
+ update_context_from_thread(&Tempavctx, p->avctx, 1);
+ err = update_context_from_user_dxva2(p->avctx, avctx);
+    if (err) return err;
+    err = submit_packet_dxva2(p, avpkt);
+    if (err) return err;
+ update_context_from_thread(avctx,&Tempavctx, 1);
+ pthread_mutex_lock(&p->progress_mutex);
+ p->state = STATE_SETUP_FINISHED;
+    pthread_cond_signal(&p->input_cond);
+    pthread_mutex_unlock(&p->progress_mutex);
+ }
+ return (p->result >= 0) ? avpkt->size : p->result;
+
+}
+#endif
 int ff_thread_decode_frame(AVCodecContext *avctx,
                            AVFrame *picture, int *got_picture_ptr,
                            AVPacket *avpkt)
@@ -742,7 +924,66 @@ static void
park_frame_worker_threads(FrameThreadContext *fctx, int thread_count
         p->got_frame = 0;
     }
 }
+#if CONFIG_DXVA2
+
+static void frame_thread_free_dxva2(AVCodecContext *avctx, int
thread_count)
+{
+    FrameThreadContext *fctx = avctx->thread_opaque;
+    AVCodec *codec = avctx->codec;
+    int i;
+
+ park_frame_worker_threads(fctx, thread_count);
+
+
+    fctx->die = 1;
+
+    for (i = 0; i < thread_count; i++) {
+        PerThreadContext *p = &fctx->threads[i];
+
+        pthread_mutex_lock(&p->mutex);
+ p->state = STATE_SETUP_FINISHED;
+        pthread_cond_signal(&p->input_cond);
+        pthread_mutex_unlock(&p->mutex);
+
+        if (p->thread_init)
+            pthread_join(p->thread, NULL);
+
+        p->thread_init=0;
+
+        if (codec->close)
+            codec->close(p->avctx);
+
+        avctx->codec = NULL;
+
+        release_delayed_buffers(p);
+    }
+    for (i = 0; i < thread_count; i++) {
+        PerThreadContext *p = &fctx->threads[i];
+

+        avcodec_default_free_buffers(p->avctx);
+
+        pthread_mutex_destroy(&p->mutex);
+        pthread_mutex_destroy(&p->progress_mutex);
+        pthread_cond_destroy(&p->input_cond);
+        pthread_cond_destroy(&p->progress_cond);
+        pthread_cond_destroy(&p->output_cond);
+        av_freep(&p->avpkt.data);
+
+        if (i) {
+            av_freep(&p->avctx->priv_data);
+            av_freep(&p->avctx->internal);
+            av_freep(&p->avctx->slice_offset);
+        }
+
+        av_freep(&p->avctx);
+    }
+    av_freep(&fctx->threads);
+    pthread_mutex_destroy(&fctx->buffer_mutex);
+    av_freep(&avctx->thread_opaque);
+
+}
+#endif
 static void frame_thread_free(AVCodecContext *avctx, int thread_count)
 {
     FrameThreadContext *fctx = avctx->thread_opaque;
@@ -819,7 +1060,37 @@ static int frame_thread_init(AVCodecContext *avctx)
         else
             thread_count = avctx->thread_count = 1;
     }
-
+#if CONFIG_DXVA2
+ if((avctx->dxva2flg) && (avctx->codec_id == AV_CODEC_ID_H264))
+ {
+ thread_count = avctx->thread_count = 1;
+ avctx->thread_opaque = fctx = av_mallocz(sizeof(FrameThreadContext));
+ fctx->threads = av_mallocz(sizeof(PerThreadContext) * thread_count);
+                pthread_mutex_init(&fctx->buffer_mutex, NULL);
+ AVCodecContext *copy = av_malloc(sizeof(AVCodecContext));
+                PerThreadContext *p  = &fctx->threads[0];
+
+                pthread_mutex_init(&p->mutex, NULL);
+                pthread_mutex_init(&p->progress_mutex, NULL);
+                pthread_cond_init(&p->input_cond, NULL);
+                pthread_cond_init(&p->progress_cond, NULL);
+                pthread_cond_init(&p->output_cond, NULL);
+ *copy = *src;
+ fctx->delaying = 1;
+                p->parent = fctx;
+                p->avctx  = copy;
+
+                if (!copy)
+                {
+                    err = AVERROR(ENOMEM);
+                    goto error;
+                 }
+ p->state = STATE_INPUT_READY;
+ p->thread_init= !pthread_create(&p->thread, NULL,
frame_worker_thread_dxva2, p);
+                if(!p->thread_init)
+                goto error;
+    }
+#endif
     if (thread_count <= 1) {
         avctx->active_thread_type = 0;
         return 0;
@@ -1097,6 +1368,12 @@ void ff_thread_free(AVCodecContext *avctx)
 {
     if (avctx->active_thread_type&FF_THREAD_FRAME)
         frame_thread_free(avctx, avctx->thread_count);
+#if CONFIG_DXVA2
+ else if((avctx->dxva2flg) && (avctx->codec_type == AVMEDIA_TYPE_VIDEO))
+ {
+ frame_thread_free_dxva2(avctx, avctx->thread_count);
+ }
+#endif
     else
         thread_free(avctx);
 }
diff --git a/libavcodec/thread.h b/libavcodec/thread.h
index e838030..a74d55a 100644
--- a/libavcodec/thread.h
+++ b/libavcodec/thread.h
@@ -113,4 +113,10 @@ void ff_thread_release_buffer(AVCodecContext *avctx,
AVFrame *f);
 int ff_thread_init(AVCodecContext *s);
 void ff_thread_free(AVCodecContext *s);

+#if CONFIG_DXVA2
+int ff_thread_decode_frame_dxva2(AVCodecContext *avctx, AVFrame *picture,
+                           int *got_picture_ptr, AVPacket *avpkt);
+#endif
+
+
 #endif /* AVCODEC_THREAD_H */
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 0a0c446..1e38d36 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -1607,8 +1607,23 @@ int attribute_align_arg
avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
             ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,
                                          &tmp);
         else {
+#if CONFIG_DXVA2
+
+ if((avctx->dxva2flg)&&(avctx->codec_id == AV_CODEC_ID_H264))
+ {
+ ret = ff_thread_decode_frame_dxva2(avctx, picture, got_picture_ptr, &tmp);
+
+ }
+ else
+ {
             ret = avctx->codec->decode(avctx, picture, got_picture_ptr,
                                        &tmp);
+ }
+#else
+            ret = avctx->codec->decode(avctx, picture, got_picture_ptr,
+                                       &tmp);
+#endif
+
             picture->pkt_dts             = avpkt->dts;

             if(!avctx->has_b_frames){
diff --git a/libavcodec/vadxva2.c b/libavcodec/vadxva2.c
new file mode 100644
index 0000000..40ee4a3
--- /dev/null
+++ b/libavcodec/vadxva2.c
@@ -0,0 +1,1084 @@
+/*
+ * Call hardware decode acceleration through dxva2 API
+
+ * 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 "vadxva2.h"
+#include <dxgi.h>
+
+
+
+static uint8_t g_Index[BAK_BUF_NUM + 1] = {0};
+
+
+static ff_va_dxva2_t *g_dxva2 = NULL;
+
+
+
+/* XXX Prefered format must come first */
+static const d3d_format_t d3d_formats[] = {
+ { "YV12",   (D3DFORMAT)MAKEFOURCC('Y','V','1','2'),    PIX_FMT_YUV420P },
+ { "NV12",   (D3DFORMAT)MAKEFOURCC('N','V','1','2'),    PIX_FMT_NV12 },
+
+ { NULL, (D3DFORMAT)0, PIX_FMT_NONE }
+};
+
+static const GUID DXVA2_ModeMPEG2_MoComp = {
+ 0xe6a9f44b, 0x61b0,0x4563, {0x9e,0xa4,0x63,0xd2,0xa3,0xc6,0xfe,0x66}
+};
+static const GUID DXVA2_ModeMPEG2_IDCT = {
+ 0xbf22ad00, 0x03ea,0x4690, {0x80,0x77,0x47,0x33,0x46,0x20,0x9b,0x7e}
+};
+static const GUID DXVA2_ModeMPEG2_VLD = {
+ 0xee27417f, 0x5e28,0x4e65, {0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9}
+};
+static const GUID DXVA2_ModeMPEG2and1_VLD = {
+ 0x86695f12, 0x340e,0x4f04, {0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60}
+};
+static const GUID DXVA2_ModeMPEG1_VLD = {
+ 0x6f3ec719, 0x3735,0x42cc, {0x80,0x63,0x65,0xcc,0x3c,0xb3,0x66,0x16}
+};
+
+static const GUID DXVA2_ModeH264_A = {
+ 0x1b81be64, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA2_ModeH264_B = {
+ 0x1b81be65, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA2_ModeH264_C = {
+ 0x1b81be66, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA2_ModeH264_D = {
+ 0x1b81be67, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA2_ModeH264_E = {
+ 0x1b81be68, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA2_ModeH264_F = {
+ 0x1b81be69, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA_ModeH264_VLD_WithFMOASO_NoFGT = {
+ 0xd5f04ff9, 0x3418,0x45d8, {0x95,0x61,0x32,0xa7,0x6a,0xae,0x2d,0xdd}
+};
+static const GUID DXVADDI_Intel_ModeH264_A = {
+ 0x604F8E64, 0x4951,0x4c54, {0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6}
+};
+static const GUID DXVADDI_Intel_ModeH264_C = {
+ 0x604F8E66, 0x4951,0x4c54, {0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6}
+};
+static const GUID DXVADDI_Intel_ModeH264_E = { //
DXVA_Intel_H264_ClearVideo
+ 0x604F8E68, 0x4951,0x4c54, {0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6}
+};
+static const GUID DXVA2_ModeWMV8_A = {
+ 0x1b81be80, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA2_ModeWMV8_B = {
+ 0x1b81be81, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA2_ModeWMV9_A = {
+ 0x1b81be90, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA2_ModeWMV9_B = {
+ 0x1b81be91, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA2_ModeWMV9_C = {
+ 0x1b81be94, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+
+static const GUID DXVA2_ModeVC1_A = {
+ 0x1b81beA0, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA2_ModeVC1_B = {
+ 0x1b81beA1, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA2_ModeVC1_C = {
+ 0x1b81beA2, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+static const GUID DXVA2_ModeVC1_D = {
+ 0x1b81beA3, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+/* Conformity to the August 2010 update of the specification,
ModeVC1_VLD2010 */
+static const GUID DXVA2_ModeVC1_D2010 = {
+ 0x1b81beA4, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+
+static const GUID DXVA_NoEncrypt = {
+ 0x1b81bed0, 0xa0c7,0x11d3, {0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5}
+};
+
+static const GUID DXVA_Intel_VC1_ClearVideo = {
+ 0xBCC5DB6D, 0xA2B6,0x4AF0, {0xAC,0xE4,0xAD,0xB1,0xF7,0x87,0xBC,0x89}
+};
+
+static const GUID DXVA_nVidia_MPEG4_ASP = {
+ 0x9947EC6F, 0x689B,0x11DC, {0xA3,0x20,0x00,0x19,0xDB,0xBC,0x41,0x84}
+};
+static const GUID DXVA_ModeMPEG4pt2_VLD_Simple = {
+ 0xefd64d74, 0xc9e8,0x41d7, {0xa5,0xe9,0xe9,0xb0,0xe3,0x9f,0xa3,0x19}
+};
+static const GUID DXVA_ModeMPEG4pt2_VLD_AdvSimple_NoGMC = {
+ 0xed418a9f, 0x10d,0x4eda,  {0x9a,0xe3,0x9a,0x65,0x35,0x8d,0x8d,0x2e}
+};
+static const GUID DXVA_ModeMPEG4pt2_VLD_AdvSimple_GMC = {
+ 0xab998b5b, 0x4258,0x44a9, {0x9f,0xeb,0x94,0xe5,0x97,0xa6,0xba,0xae}
+};
+
+
+static const GUID IID_IDirectXVideoDecoderService = {
+ 0xfc51a551, 0xd5e7, 0x11d9, {0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02}
+};
+static const GUID IID_IDirectXVideoAccelerationService = {
+ 0xfc51a550, 0xd5e7, 0x11d9, {0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02}
+};
+
+/* XXX Prefered modes must come first */
+static const dxva2_mode_t dxva2_modes[] = {
+ { "MPEG-2 variable-length decoder",            &DXVA2_ModeMPEG2_VLD,
AV_CODEC_ID_MPEG2VIDEO },
+ { "MPEG-2 & MPEG-1 variable-length decoder",   &DXVA2_ModeMPEG2and1_VLD,
AV_CODEC_ID_MPEG2VIDEO },
+ { "MPEG-2 motion compensation",                &DXVA2_ModeMPEG2_MoComp,
 0 },
+ { "MPEG-2 inverse discrete cosine transform",  &DXVA2_ModeMPEG2_IDCT,
 0 },
+
+ { "MPEG-1 variable-length decoder",            &DXVA2_ModeMPEG1_VLD,
0 },
+
+ { "H.264 variable-length decoder, film grain technology",
     &DXVA2_ModeH264_F,                   AV_CODEC_ID_H264 },
+ { "H.264 variable-length decoder, no film grain technology",
      &DXVA2_ModeH264_E,                   AV_CODEC_ID_H264 },
+ { "H.264 variable-length decoder, no film grain technology (Intel
ClearVideo)",&DXVADDI_Intel_ModeH264_E,           AV_CODEC_ID_H264 },
+ { "H.264 variable-length decoder, no film grain technology, FMO/ASO",
     &DXVA_ModeH264_VLD_WithFMOASO_NoFGT, AV_CODEC_ID_H264 },
+ { "H.264 inverse discrete cosine transform, film grain technology",
     &DXVA2_ModeH264_D,                   0             },
+ { "H.264 inverse discrete cosine transform, no film grain technology",
      &DXVA2_ModeH264_C,                   0             },
+ { "H.264 inverse discrete cosine transform, no film grain technology
(Intel)", &DXVADDI_Intel_ModeH264_C,           0             },
+ { "H.264 motion compensation, film grain technology",
     &DXVA2_ModeH264_B,                   0             },
+ { "H.264 motion compensation, no film grain technology",
      &DXVA2_ModeH264_A,                   0             },
+ { "H.264 motion compensation, no film grain technology (Intel)",
      &DXVADDI_Intel_ModeH264_A,           0             },
+
+ { "Windows Media Video 8 motion compensation", &DXVA2_ModeWMV8_B, 0 },
+ { "Windows Media Video 8 post processing",     &DXVA2_ModeWMV8_A, 0 },
+
+ { "Windows Media Video 9 IDCT",                &DXVA2_ModeWMV9_C, 0 },
+ { "Windows Media Video 9 motion compensation", &DXVA2_ModeWMV9_B, 0 },
+ { "Windows Media Video 9 post processing",     &DXVA2_ModeWMV9_A, 0 },
+
+ { "VC-1 variable-length decoder",              &DXVA2_ModeVC1_D,
AV_CODEC_ID_VC1 },
+ { "VC-1 variable-length decoder",              &DXVA2_ModeVC1_D,
AV_CODEC_ID_WMV3 },
+ { "VC-1 variable-length decoder",              &DXVA2_ModeVC1_D2010,
AV_CODEC_ID_VC1 },
+ { "VC-1 variable-length decoder",              &DXVA2_ModeVC1_D2010,
AV_CODEC_ID_WMV3 },
+ { "VC-1 inverse discrete cosine transform",    &DXVA2_ModeVC1_C, 0 },
+ { "VC-1 motion compensation",                  &DXVA2_ModeVC1_B, 0 },
+ { "VC-1 post processing",                      &DXVA2_ModeVC1_A, 0 },
+
+ { "VC-1 variable-length decoder (Intel)",
 &DXVA_Intel_VC1_ClearVideo, 0 },
+
+ { "MPEG-4 Part 2 nVidia bitstream decoder",
                          &DXVA_nVidia_MPEG4_ASP,                 0 },
+ { "MPEG-4 Part 2 variable-length decoder, Simple Profile",
                           &DXVA_ModeMPEG4pt2_VLD_Simple,          0 },
+ { "MPEG-4 Part 2 variable-length decoder, Simple&Advanced Profile, no
global motion compensation",  &DXVA_ModeMPEG4pt2_VLD_AdvSimple_NoGMC, 0 },
+ { "MPEG-4 Part 2 variable-length decoder, Simple&Advanced Profile, global
motion compensation",     &DXVA_ModeMPEG4pt2_VLD_AdvSimple_GMC,   0 },
+
+ { NULL, NULL, 0 }
+};
+
+
+
+
+
+static const d3d_format_t *d3d_find_format(D3DFORMAT format)
+{
+ for (unsigned i = 0; d3d_formats[i].name; i++) {
+ if (d3d_formats[i].format == format)
+ return &d3d_formats[i];
+ }
+ return NULL;
+}
+static const dxva2_mode_t *dxva2_find_mode(const GUID *guid)
+{
+ for (unsigned i = 0; dxva2_modes[i].name; i++) {
+ if (IsEqualGUID(dxva2_modes[i].guid, guid))
+ return &dxva2_modes[i];
+ }
+ return NULL;
+}
+
+
+/**
+* It creates a Direct3D device usable for DXVA 2
+*/
+typedef HWND (WINAPI *PROCGETSHELLWND)();
+
+static int d3d_create_device(ff_va_dxva2_t *va)
+{
+ /* */
+ typedef LPDIRECT3D9 (WINAPI *Create9func)(UINT SDKVersion);
+ Create9func Create9 = (Create9func )GetProcAddress(va->hd3d9_dll,
TEXT("Direct3DCreate9"));
+
+ if (!Create9) {
+ av_log(NULL, AV_LOG_ERROR, "Cannot locate reference to Direct3DCreate9
ABI in DLL");
+ return -1;
+ }
+
+ /* */
+ LPDIRECT3D9 d3dobj;
+ d3dobj = Create9(D3D_SDK_VERSION);
+ if (!d3dobj) {
+ av_log(NULL, AV_LOG_ERROR, "Direct3DCreate9 failed");
+ return -1;
+ }
+ va->d3dobj = d3dobj;
+
+ /* */
+ D3DADAPTER_IDENTIFIER9 *d3dai = &va->d3dai;
+ if (FAILED(IDirect3D9_GetAdapterIdentifier(va->d3dobj,
+ D3DADAPTER_DEFAULT, 0, d3dai))) {
+ av_log(NULL, AV_LOG_WARNING, "IDirect3D9_GetAdapterIdentifier failed");
+ ZeroMemory(d3dai, sizeof(*d3dai));
+ }
+ PROCGETSHELLWND GetShellWindow;
+    HMODULE hUser32 = GetModuleHandle( "user32" );
+    GetShellWindow = (PROCGETSHELLWND)
+                     GetProcAddress( hUser32, "GetShellWindow" );
+ /* */
+ D3DPRESENT_PARAMETERS *d3dpp = &va->d3dpp;
+ 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;                  /* FIXME what to put
here */
+ d3dpp->BackBufferFormat       = D3DFMT_X8R8G8B8;    /* FIXME what to put
here */
+ d3dpp->BackBufferWidth        = 0;
+ d3dpp->BackBufferHeight       = 0;
+ d3dpp->EnableAutoDepthStencil = FALSE;
+
+ /* Direct3D needs a HWND to create a device, even without using ::Present
+ this HWND is used to alert Direct3D when there's a change of focus window.
+ For now, use GetShellWindow, as it looks harmless */
+ LPDIRECT3DDEVICE9 d3ddev;
+ if (FAILED(IDirect3D9_CreateDevice(d3dobj, D3DADAPTER_DEFAULT,
+ D3DDEVTYPE_HAL, GetShellWindow(),
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING |
+ D3DCREATE_MULTITHREADED,
+ d3dpp, &d3ddev))) {
+ av_log(NULL, AV_LOG_ERROR, "IDirect3D9_CreateDevice failed\n");
+ return -1;
+ }
+ va->d3ddev = d3ddev;
+
+ return 0;
+}
+
+/**
+* It releases a Direct3D device and its resources.
+*/
+static void d3d_destroy_device(ff_va_dxva2_t *va)
+{
+ if (va->d3ddev)
+ IDirect3DDevice9_Release(va->d3ddev);
+ if (va->d3dobj)
+ IDirect3D9_Release(va->d3dobj);
+}
+/**
+* It destroys a Direct3D device manager
+*/
+static void d3d_destroy_device_manager(ff_va_dxva2_t *va)
+{
+ if (va->devmng)
+ IDirect3DDeviceManager9_Release( va->devmng );
+}
+static void dx_destroy_video_service(ff_va_dxva2_t *va)
+{
+ if( va->device )
+        IDirect3DDeviceManager9_CloseDeviceHandle( va->devmng, va->device
);
+
+    if( va->vs )
+        IDirectXVideoDecoderService_Release( va->vs );
+}
+static void dx_destroy_video_decoder(ff_va_dxva2_t *va)
+{
+ if( va->decoder )
+        IDirectXVideoDecoder_Release( va->decoder );
+    va->decoder = NULL;
+
+    unsigned i;
+    for( i = 0; i< va->surface_count; i++ )
+        IDirect3DSurface9_Release( va->surface[i].d3d );
+    va->surface_count = 0;
+}
+
+static int dx_reset_video_decoder(ff_va_dxva2_t *va)
+{
+ av_log(NULL, AV_LOG_ERROR, "dx_reset_video_decoder unimplemented\n");
+ return -1;
+}
+static void close(ff_va_dxva2_t *external)
+{
+ ff_va_dxva2_t *va = external;
+
+ dx_destroy_video_decoder(va);
+ dx_destroy_video_service(va);
+ d3d_destroy_device_manager(va);
+ d3d_destroy_device(va);
+
+ if (va->hdxva2_dll)
+ FreeLibrary(va->hdxva2_dll);
+ if (va->hd3d9_dll)
+ FreeLibrary(va->hd3d9_dll);
+
+ av_free(va);
+}
+
+/**
+* Find the best suited decoder mode GUID and render format.
+*/
+
+static int dx_find_video_service_conversion(ff_va_dxva2_t *va, GUID
*input, D3DFORMAT *output)
+{
+ /* Retrieve supported modes from the decoder service */
+ UINT input_count = 0;
+ GUID *input_list = NULL;
+
+ if (FAILED(IDirectXVideoDecoderService_GetDecoderDeviceGuids( va->vs,
&input_count, &input_list ))) {
+ av_log(NULL, AV_LOG_ERROR,
"IDirectXVideoDecoderService_GetDecoderDeviceGuids failed\n");
+ return -1;
+ }
+ for (unsigned i = 0; i < input_count; i++) {
+ const GUID *g = &input_list[i];
+ const dxva2_mode_t *mode = dxva2_find_mode(g);
+ if (mode) {
+ av_log(NULL, AV_LOG_INFO, "- '%s' is supported by hardware\n",
mode->name);
+ } else {
+ av_log(NULL, AV_LOG_WARNING, "- Unknown GUID = %08X-%04x-%04x-XXXX\n",
+ (unsigned)g->Data1, g->Data2, g->Data3);
+ }
+ }
+
+ /* Try all supported mode by our priority */
+ for (unsigned i = 0; dxva2_modes[i].name; i++) {
+ const dxva2_mode_t *mode = &dxva2_modes[i];
+ if (!mode->codec || mode->codec != va->codec_id)
+ continue;
+
+ /* */
+ int is_suported = false;
+ for (unsigned count = 0; !is_suported && count < input_count; count++) {
+ const GUID *g = &input_list[count];
+ is_suported = IsEqualGUID(mode->guid, g) == 0;
+ }
+ if (!is_suported)
+ continue;
+
+ /* */
+ av_log(NULL, AV_LOG_INFO, "Trying to use '%s' as input\n", mode->name);
+ UINT      output_count = 0;
+ D3DFORMAT *output_list = NULL;
+
+ if (FAILED(IDirectXVideoDecoderService_GetDecoderRenderTargets( va->vs,
mode->guid, &output_count, &output_list )))
+ {
+ av_log(NULL, AV_LOG_INFO,
"IDirectXVideoDecoderService_GetDecoderRenderTargets failed,try others\n");
+ continue;
+ }
+ for (unsigned j = 0; j < output_count; j++)
+ {
+ const D3DFORMAT f = output_list[j];
+ const d3d_format_t *format = d3d_find_format(f);
+ if (format) {
+ av_log(NULL, AV_LOG_INFO, "%s is supported for output\n", format->name);
+ } else {
+ av_log(NULL, AV_LOG_INFO, "%d is supported for output (%4.4s)\n", f,
(const char*)&f);
+ }
+ }
+
+ /* */
+ for (unsigned j = 0; d3d_formats[j].name; j++)
+ {
+ const d3d_format_t *format = &d3d_formats[j];
+
+ /* */
+ int is_suported = false;
+ for (unsigned k = 0; !is_suported && k < output_count; k++) {
+ is_suported = format->format == output_list[k];
+ }
+ if (!is_suported)
+ continue;
+
+ /* We have our solution */
+ av_log(NULL, AV_LOG_INFO, "Using '%s' to decode to '%s'\n", mode->name,
format->name);
+ *input  = *mode->guid;
+ *output = format->format;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+
+/**
+* It creates a DirectX video service
+*/
+
+static int dx_create_video_service(ff_va_dxva2_t *va)
+{
+ typedef HRESULT (WINAPI *CreateVideoService_func)(IDirect3DDevice9 *,
+ REFIID riid,
+ void **ppService);
+ CreateVideoService_func CreateVideoService =
+ (CreateVideoService_func)GetProcAddress(va->hdxva2_dll,
+ TEXT("DXVA2CreateVideoService"));
+
+ if (!CreateVideoService)
+ {
+ av_log(NULL, AV_LOG_ERROR, "cannot load function\n");
+ return 4;
+ }
+ av_log(NULL, AV_LOG_INFO, "DXVA2CreateVideoService Success!\n");
+
+ HRESULT hr;
+
+ HANDLE device;
+
+
+    hr = IDirect3DDeviceManager9_OpenDeviceHandle( va->devmng, &device );
+
+ if (FAILED(hr)) {
+ av_log(NULL, AV_LOG_ERROR, "OpenDeviceHandle failed\n");
+ return -1;
+ }
+ va->device = device;
+
+ IDirectXVideoDecoderService *vs;
+
+    hr = IDirect3DDeviceManager9_GetVideoService( va->devmng, device,
&IID_IDirectXVideoDecoderService, &vs );
+ if (FAILED(hr))
+ {
+ av_log(NULL, AV_LOG_ERROR, "GetVideoService failed\n");
+ return -1;
+ }
+ va->vs = vs;
+
+ return 0;
+}
+
+
+/**
+* It creates a Direct3D device manager
+*/
+
+static int d3d_create_device_manager(ff_va_dxva2_t *va)
+{
+ typedef HRESULT (WINAPI *CreateDeviceManager9_func)(UINT *pResetToken,
IDirect3DDeviceManager9 **);
+ CreateDeviceManager9_func CreateDeviceManager9 =
+ (CreateDeviceManager9_func)GetProcAddress(va->hdxva2_dll,
TEXT("DXVA2CreateDirect3DDeviceManager9"));
+
+ if (!CreateDeviceManager9)
+ {
+ av_log(NULL, AV_LOG_ERROR, "cannot load function\n");
+ return -1;
+ }
+ av_log(NULL, AV_LOG_INFO, "OurDirect3DCreateDeviceManager9 Success!\n");
+
+ UINT token;
+ IDirect3DDeviceManager9 *devmng;
+ if (FAILED(CreateDeviceManager9(&token, &devmng)))
+ {
+ av_log(NULL, AV_LOG_ERROR, " OurDirect3DCreateDeviceManager9 failed\n");
+ return -1;
+ }
+
+ HRESULT hr = IDirect3DDeviceManager9_ResetDevice( devmng, va->d3ddev,
token );
+ if (FAILED(hr))
+ {
+ av_log(NULL, AV_LOG_ERROR, "IDirect3DDeviceManager9_ResetDevice failed:
%08x", (unsigned)hr);
+ return -1;
+ }
+
+ IDirect3DDeviceManager9_AddRef(devmng);
+ va->token  = token;
+ va->devmng = devmng;
+ av_log(NULL, AV_LOG_INFO, "obtained IDirect3DDeviceManager9\n");
+
+ return 0;
+}
+
+
+
+ff_va_dxva2_t *av_new_dxva2(int codec_id)
+{
+ ff_va_dxva2_t *va = (ff_va_dxva2_t *)calloc(1, sizeof(*va));
+ if (!va)
+ return NULL;
+
+ va->codec_id = codec_id;
+
+
+ /* Load dll*/
+ va->hd3d9_dll = LoadLibrary(TEXT("D3D9.DLL"));
+ if (!va->hd3d9_dll)
+ {
+ av_log(NULL, AV_LOG_ERROR, "cannot load d3d9.dll\n");
+ goto error;
+ }
+ va->hdxva2_dll = LoadLibrary(TEXT("DXVA2.DLL"));
+ if (!va->hdxva2_dll)
+ {
+ av_log(NULL, AV_LOG_ERROR, "cannot load dxva2.dll\n");
+ goto error;
+ }
+ av_log(NULL, AV_LOG_INFO, "DLLs loaded\n");
+
+ /* */
+ if (d3d_create_device(va))
+ {
+ av_log(NULL, AV_LOG_ERROR, "Failed to create Direct3D device\n");
+ goto error;
+ }
+ av_log(NULL, AV_LOG_INFO, "d3d_create_device succeed\n");
+
+ if (d3d_create_device_manager(va)) {
+ av_log(NULL, AV_LOG_ERROR, "d3d_create_device_manager failed\n");
+ goto error;
+ }
+
+ if (dx_create_video_service(va))
+ {
+ av_log(NULL, AV_LOG_ERROR, "dx_create_video_service failed\n");
+ goto error;
+ }
+
+ /* */
+ if (dx_find_video_service_conversion(va, &va->input, &va->render))
+ {
+ av_log(NULL, AV_LOG_ERROR, "dx_find_video_service_conversion failed\n");
+ goto error;
+ }
+
+ /* TODO print the hardware name/vendor for debugging purposes */
+ g_dxva2 = va;
+ return va;
+
+error:
+ close(va);
+ return NULL;
+}
+
+
+
+/**
+* It creates a DXVA2 decoder using the given video format
+*/
+static int dx_create_video_decoder(ff_va_dxva2_t *va,
+ int codec_id, const struct video_format_t *fmt)
+{
+ /* */
+ av_log(NULL, AV_LOG_INFO, "dx_create_video_decoder id %d %dx%d\n",
+ codec_id, fmt->i_width, fmt->i_height);
+
+ va->width  = fmt->i_width;
+ va->height = fmt->i_height;
+
+ /* Allocates all surfaces needed for the decoder */
+
+ va->surface_width  = (fmt->i_width  + 15) & ~15;
+ va->surface_height = (fmt->i_height + 15) & ~15;
+
+ switch (codec_id) {
+ case AV_CODEC_ID_H264:
+ va->surface_count = 16 + 1;
+ break;
+ default:
+
+ va->surface_count = BAK_BUF_NUM + 1;
+ break;
+ }
+ LPDIRECT3DSURFACE9 surface_list[VA_DXVA2_MAX_SURFACE_COUNT];
+
+
+ if (FAILED(IDirectXVideoDecoderService_CreateSurface( va->vs,
+
va->surface_width,
+
va->surface_height,
+
va->surface_count - 1,
+                                                           va->render,
+
D3DPOOL_DEFAULT,
+                                                           0,
+
DXVA2_VideoDecoderRenderTarget,
+                                                           surface_list,
NULL ))) {
+ av_log(NULL, AV_LOG_ERROR,
"IDirectXVideoAccelerationService_CreateSurface failed\n");
+ va->surface_count = 0;
+ return -1;
+ }
+ for (unsigned i = 0; i < va->surface_count; i++) {
+ ff_va_surface_t *surface = &va->surface[i];
+ surface->d3d = surface_list[i];
+ surface->refcount = 0;
+ surface->order = 0;
+ }
+ av_log(NULL, AV_LOG_INFO, "IDirectXVideoAccelerationService_CreateSurface
succeed with %d surfaces (%dx%d)\n",
+ va->surface_count, fmt->i_width, fmt->i_height);
+
+ /* */
+ DXVA2_VideoDesc dsc;
+ ZeroMemory(&dsc, sizeof(dsc));
+ dsc.SampleWidth     = fmt->i_width;
+ dsc.SampleHeight    = fmt->i_height;
+ dsc.Format          = va->render;
+ if (fmt->i_frame_rate > 0 && fmt->i_frame_rate_base > 0) {
+ dsc.InputSampleFreq.Numerator   = fmt->i_frame_rate;
+ dsc.InputSampleFreq.Denominator = fmt->i_frame_rate_base;
+ } else {
+ dsc.InputSampleFreq.Numerator   = 0;
+ dsc.InputSampleFreq.Denominator = 0;
+ }
+ dsc.OutputFrameFreq = dsc.InputSampleFreq;
+ dsc.UABProtectionLevel = FALSE;
+ dsc.Reserved = 0;
+
+ /* FIXME I am unsure we can let unknown everywhere */
+ DXVA2_ExtendedFormat *ext = &dsc.SampleFormat;
+ ext->SampleFormat = 0;//DXVA2_SampleUnknown;
+ ext->VideoChromaSubsampling = 0;//DXVA2_VideoChromaSubsampling_Unknown;
+ ext->NominalRange = 0;//DXVA2_NominalRange_Unknown;
+ ext->VideoTransferMatrix = 0;//DXVA2_VideoTransferMatrix_Unknown;
+ ext->VideoLighting = 0;//DXVA2_VideoLighting_Unknown;
+ ext->VideoPrimaries = 0;//DXVA2_VideoPrimaries_Unknown;
+ ext->VideoTransferFunction = 0;//DXVA2_VideoTransFunc_Unknown;
+
+ /* List all configurations available for the decoder */
+ UINT                      cfg_count = 0;
+ DXVA2_ConfigPictureDecode *cfg_list = NULL;
+
+ if (FAILED(IDirectXVideoDecoderService_GetDecoderConfigurations( va->vs,
&va->input, &dsc, NULL, &cfg_count, &cfg_list ))) {
+ av_log(NULL, AV_LOG_ERROR,
"IDirectXVideoDecoderService_GetDecoderConfigurations failed\n");
+ return -1;
+ }
+ av_log(NULL, AV_LOG_INFO, "we got %d decoder configurations\n",
cfg_count);
+
+ /* Select the best decoder configuration */
+ int cfg_score = 0;
+ for (unsigned i = 0; i < cfg_count; i++)
+ {
+ const DXVA2_ConfigPictureDecode *cfg = &cfg_list[i];
+
+ /* */
+ av_log(NULL, AV_LOG_INFO, "configuration[%d] ConfigBitstreamRaw %d\n",
+ i, cfg->ConfigBitstreamRaw);
+
+ /* */
+ int score;
+ if (cfg->ConfigBitstreamRaw == 1)
+ score = 1;
+ else if (codec_id == AV_CODEC_ID_H264 && cfg->ConfigBitstreamRaw == 2)
+ score = 2;
+ else
+ continue;
+ if (IsEqualGUID(&cfg->guidConfigBitstreamEncryption, &DXVA_NoEncrypt))
+ score += 16;
+
+ if (cfg_score < score)
+ {
+ va->cfg = *cfg;
+ cfg_score = score;
+ }
+ }
+ if (cfg_score <= 0)
+ {
+ av_log(NULL, AV_LOG_ERROR, "Failed to find a supported decoder
configuration\n");
+ return -1;
+ }
+
+ IDirectXVideoDecoder *decoder;
+
+ if (FAILED(IDirectXVideoDecoderService_CreateVideoDecoder( va->vs,
&va->input, &dsc, &va->cfg, surface_list, va->surface_count, &decoder )))
+ {
+ av_log(NULL, AV_LOG_ERROR,
"IDirectXVideoDecoderService_CreateVideoDecoder failed\n");
+ return -1;
+ }
+ va->decoder = decoder;
+ av_log(NULL, AV_LOG_INFO, "IDirectXVideoDecoderService_CreateVideoDecoder
succeed\n");
+ return 0;
+}
+
+
+static void dx_create_video_conversion(ff_va_dxva2_t *va)
+{
+ switch (va->render) {
+ case MAKEFOURCC('N','V','1','2'):
+ va->output = (D3DFORMAT)MAKEFOURCC('Y','V','1','2');
+ break;
+ default:
+ va->output = va->render;
+ break;
+ }
+}
+int av_setup_dxva2(ff_va_dxva2_t *external, void **hw, enum PixelFormat
*chroma,
+ int width, int height,void *get_buffer,void *release_buffer)
+{
+ ff_va_dxva2_t *va = external;
+
+ if (va->width == width && va->height == height && va->decoder)
+ goto ok;
+
+
+ /* */
+ dx_destroy_video_service(va);
+
+
+ *chroma = AV_PIX_FMT_NONE;
+ if (width <= 0 || height <= 0)
+ return -1;
+
+ struct video_format_t fmt;
+ memset(&fmt, 0, sizeof(fmt));
+ fmt.i_width = width;
+ fmt.i_height = height;
+ if (dx_create_video_decoder(va, va->codec_id, &fmt))
+ {
+ return -1;
+ }
+ /* */
+ va->hw.decoder = va->decoder;
+ va->hw.cfg = &va->cfg;
+ va->hw.surface_count = va->surface_count;
+ va->hw.surface = va->hw_surface;
+ for (unsigned i = 0; i < va->surface_count; i++)
+ va->hw.surface[i] = va->surface[i].d3d;
+
+ /* */
+ dx_create_video_conversion(va);
+
+ if(get_buffer)
+ {
+ va->get_buffer = get_buffer;
+ }
+ if(release_buffer)
+ {
+ va->release_buffer= release_buffer;
+ }
+
+
+ /* */
+ok:
+ *hw = &va->hw;
+ const d3d_format_t *output = d3d_find_format(va->output);
+ *chroma = output->codec;
+ return 0;
+}
+
+//hb_va_get
+static int get(ff_va_dxva2_t *external, AVFrame *ff,uint32_t codecid)
+{
+ ff_va_dxva2_t *va = external;
+ unsigned i, old;
+ for (i = 0, old = 0; i < va->surface_count; i++) {
+ ff_va_surface_t *surface = &va->surface[i];
+
+ if (!surface->refcount)
+ break;
+
+ if (surface->order < va->surface[old].order)
+ old = i;
+ }
+ if (i >= va->surface_count)
+ i = old;
+
+ ff_va_surface_t *surface = &va->surface[i];
+ if((AV_CODEC_ID_WMV3 == codecid))
+ {
+
+ g_Index[ff->coded_picture_number % (BAK_BUF_NUM + 1)] = i;
+
+ for(int j = 0;j < DELAY_FRAMES_NUM - 1;j++)
+ {
+ va->d3ddata_delay[j] = va->d3ddata_delay[j + 1];
+ }
+ va->d3ddata_delay[DELAY_FRAMES_NUM - 1] = (uint8_t *)(va->surface[i].d3d);
+
+ if(ff->coded_picture_number >= BAK_BUF_NUM - 1)
+ {
+ va->d3ddata = (uint8_t *)(va->surface[g_Index[(ff->coded_picture_number -
(BAK_BUF_NUM - 1))%(BAK_BUF_NUM + 1)]].d3d);
+ }
+ else
+ {
+ va->d3ddata = NULL;
+ }
+ }
+
+
+ surface->refcount = 1;
+ surface->order = va->surface_order++;
+
+ /* */
+ ff->data[3] = (uint8_t *)surface->d3d;
+
+ return 0;
+}
+
+
+static void Release(ff_va_dxva2_t *external, AVFrame *ff,uint32_t codecid)
+{
+ ff_va_dxva2_t *va = external;
+
+ LPDIRECT3DSURFACE9 d3d;
+ if((AV_CODEC_ID_WMV3 == codecid))
+ {
+ d3d = (LPDIRECT3DSURFACE9)(uintptr_t)va->d3ddata;
+ }
+ else
+ {
+ d3d = (LPDIRECT3DSURFACE9)(uintptr_t)ff->data[3];
+ }
+
+ if(NULL == d3d)
+ {
+ return;
+ }
+ for (unsigned i = 0; i < va->surface_count; i++) {
+ ff_va_surface_t *surface = &va->surface[i];
+
+ if (surface->d3d == d3d)
+ surface->refcount--;
+
+ }
+}
+
+int av_dxva2_get_buffer( struct AVCodecContext *p_context,
+ AVFrame *p_ff_pic )
+{
+
+ ff_va_dxva2_t *va = (ff_va_dxva2_t *)p_context->opaque;
+ p_ff_pic->opaque = NULL;
+ void *tempopaque = p_context->opaque;
+ int temppix_fmt = p_context->pix_fmt;
+ p_context->opaque = p_context->opaque_bak;
+ p_context->pix_fmt = AV_PIX_FMT_YUV420P;
+ if(va->get_buffer)
+ {
+ va->get_buffer(p_context,p_ff_pic);
+ }
+
+ p_context->opaque = tempopaque;
+ p_ff_pic->format = AV_PIX_FMT_YUV420P;
+
+
+ p_ff_pic->reordered_opaque = p_context->reordered_opaque;
+
+ enum PixelFormat chroma;
+ if( va )
+ {
+ if( av_setup_dxva2( va,
+ &p_context->hwaccel_context, &chroma,
+ p_context->width, p_context->height,NULL,NULL ) )
+ {
+ av_log(NULL, AV_LOG_ERROR, "ff_va_Setup failed" );
+ return -1;
+ }
+
+ p_ff_pic->type = FF_BUFFER_TYPE_USER;
+ if( get( va, p_ff_pic,p_context->codec_id) )
+ {
+ av_log(NULL, AV_LOG_ERROR, "VaGrabSurface failed" );
+ return -1;
+ }
+ return 0;
+ }
+ else
+ {
+ return avcodec_default_get_buffer( p_context, p_ff_pic );
+ }
+}
+
+
+int  av_dxva2_reget_buffer( struct AVCodecContext *p_context, AVFrame
*p_ff_pic )
+{
+ p_ff_pic->reordered_opaque = p_context->reordered_opaque;
+
+ /* We always use default reget function, it works perfectly fine */
+ return avcodec_default_reget_buffer( p_context, p_ff_pic );
+}
+
+void av_dxva2_release_buffer( struct AVCodecContext *p_context,
+ AVFrame *p_ff_pic )
+{
+ //av_log(NULL,AV_LOG_ERROR,"ffmpeg_ReleaseFrameBuf\n");
+ ff_va_dxva2_t *va = (ff_va_dxva2_t *)p_context->opaque;
+
+ if( va )
+ {
+ Release( va, p_ff_pic ,p_context->codec_id);
+ if(va->release_buffer)
+ {
+ va->release_buffer(p_context,p_ff_pic);
+ }
+
+// codec_release_buffer(p_context,p_ff_pic);
+ }
+ else if( !p_ff_pic->opaque )
+ {
+ /* We can end up here without the AVFrame being allocated by
+ * avcodec_default_get_buffer() if VA is used and the frame is
+ * released when the decoder is closed
+ */
+ if( p_ff_pic->type == FF_BUFFER_TYPE_INTERNAL )
+ avcodec_default_release_buffer( p_context, p_ff_pic );
+ }
+ for( int i = 0; i < 4; i++ )
+ p_ff_pic->data[i] = NULL;
+}
+
+enum PixelFormat av_dxva2_get_format( AVCodecContext *p_context,
+ const enum PixelFormat *pi_fmt )
+{
+ ff_va_dxva2_t *va = (ff_va_dxva2_t *)p_context->opaque;
+ /* Try too look for a supported hw acceleration */
+ for( int i = 0; pi_fmt[i] != AV_PIX_FMT_NONE; i++ )
+ {
+ static const char *ppsz_name[PIX_FMT_NB] = {NULL};
+ ppsz_name[AV_PIX_FMT_VDPAU_H264] = "PIX_FMT_VDPAU_H264";
+ ppsz_name[AV_PIX_FMT_VAAPI_IDCT] = "PIX_FMT_VAAPI_IDCT";
+ ppsz_name[AV_PIX_FMT_VAAPI_VLD] = "PIX_FMT_VAAPI_VLD";
+ ppsz_name[AV_PIX_FMT_VAAPI_MOCO] = "PIX_FMT_VAAPI_MOCO";
+ ppsz_name[AV_PIX_FMT_DXVA2_VLD] = "PIX_FMT_DXVA2_VLD";
+ ppsz_name[AV_PIX_FMT_YUYV422] = "PIX_FMT_YUYV422";
+ ppsz_name[AV_PIX_FMT_YUV420P] = "PIX_FMT_YUV420P";
+
+ av_log(p_context, AV_LOG_INFO, "Available decoder output format %d
(%s)\n", pi_fmt[i], ppsz_name[pi_fmt[i]] ? ppsz_name[pi_fmt[i]] : "Unknown"
);
+ if( pi_fmt[i] == AV_PIX_FMT_DXVA2_VLD )
+ {
+ av_log(p_context, AV_LOG_INFO, "Trying DXVA2\n" );
+ if( va )
+ {
+ p_context->draw_horiz_band = NULL;
+ p_context->opaque = va;
+ return pi_fmt[i];
+ }
+ }
+ }
+
+ /* Fallback to default behaviour */
+ return avcodec_default_get_format( p_context, pi_fmt );
+}
+
+
+static void ff_copy_from_nv12(uint8_t *src[2], size_t src_pitch[2],
unsigned width, unsigned height, AVFrame *ff )
+{
+ unsigned int i, j;
+ uint8_t *dstU, *dstV;
+ dstU = ff->data[1];
+ dstV = ff->data[2];
+ unsigned int heithtUV, widthUV;
+ heithtUV = height/2;
+ widthUV = width/2;
+
+ if(ff->linesize[1] != ff->linesize[2])
+ {
+ av_log(NULL,AV_LOG_ERROR,"ff->linesize[1] != ff->linesize[2] not 4:2:0
type\n");
+ }
+ for( i = 0; i<height; i++ ) //Y
+ {
+
+ memcpy( ff->data[0] + i * ff->linesize[0], src[0]+i*src_pitch[0], width );
+ }
+ for( i = 0; i<heithtUV; i++ )
+ {
+ for( j = 0; j<widthUV; j++ )
+ {
+ dstU[i*ff->linesize[1]+j] = *(src[1]+i*src_pitch[1]+2*j);
+ dstV[i*ff->linesize[2]+j] = *(src[1]+i*src_pitch[1]+2*j+1);
+ }
+ }
+}
+
+
+
+
+int av_extract_dxva2( ff_va_dxva2_t *dxva2,AVFrame *frame,uint32_t codecid)
+
+{
+
+ LPDIRECT3DSURFACE9 d3d;
+ D3DLOCKED_RECT lock;
+ if((AV_CODEC_ID_WMV3 == codecid))
+ {
+ d3d = (LPDIRECT3DSURFACE9)(uintptr_t)dxva2->d3ddata;
+ }
+ else
+ {
+ d3d = (LPDIRECT3DSURFACE9)(uintptr_t)frame->data[3];
+ }
+
+
+ if( FAILED( IDirect3DSurface9_LockRect( d3d, &lock,
NULL,D3DLOCK_READONLY)))
+ {
+ av_log(NULL, AV_LOG_ERROR, "Trying DXVA2\n" );
+ return FALSE;
+ }
+ if( dxva2->render == MAKEFOURCC( 'N', 'V', '1', '2' ))
+ {
+ uint8_t *plane[2] =
+ {
+ (uint8_t *)lock.pBits,
+ (uint8_t*)lock.pBits + lock.Pitch * dxva2->surface_height
+ };
+ size_t  pitch[2] =
+ {
+ lock.Pitch,
+ lock.Pitch,
+ };
+
+ ff_copy_from_nv12(plane, pitch, dxva2->width, dxva2->height, frame );
+
+
+ }
+ IDirect3DSurface9_UnlockRect( d3d );
+
+ return TRUE;
+}
+
+void av_save_framepts_info(ff_va_dxva2_t *dxva2,AVFrame *frame)
+{
+ int i;
+
+
+ for(i = 0;i < DELAY_FRAMES_NUM;i++)
+ {
+ dxva2->pts_delay[i] = dxva2->pts_delay[i + 1];
+ dxva2->pkt_pts_delay[i] = dxva2->pkt_pts_delay[i + 1];
+ dxva2->pkt_dts_delay[i] = dxva2->pkt_dts_delay[i + 1];
+ dxva2->best_effort_timestamp_delay[i] =
dxva2->best_effort_timestamp_delay[i + 1];
+ }
+ dxva2->pts_delay[DELAY_FRAMES_NUM] = frame->pts;
+ dxva2->pkt_pts_delay[DELAY_FRAMES_NUM] = frame->pkt_pts;
+ dxva2->pkt_dts_delay[DELAY_FRAMES_NUM] = frame->pkt_dts;
+ dxva2->best_effort_timestamp_delay[DELAY_FRAMES_NUM] =
frame->best_effort_timestamp;
+
+ frame->pts = dxva2->pts_delay[0];
+ frame->pkt_pts = dxva2->pkt_pts_delay[0];
+ frame->pkt_dts = dxva2->pkt_dts_delay[0];
+ frame->best_effort_timestamp = dxva2->best_effort_timestamp_delay[0];
+
+}
+
+void av_release_dxva2()
+{
+ if(g_dxva2)
+ {
+ close(g_dxva2);
+ }
+}
+
+
+
diff --git a/libavcodec/vadxva2.h b/libavcodec/vadxva2.h
new file mode 100644
index 0000000..70d3e53
--- /dev/null
+++ b/libavcodec/vadxva2.h
@@ -0,0 +1,201 @@
+/*
+ * Call hardware decode acceleration through dxva2 API
+
+ * 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
+ */
+
+#ifndef VA_DXVA2_H
+#define VA_DXVA2_H
+
+#define COBJMACROS
+#pragma once
+
+#include <windows.h>
+#include <d3d9.h>
+
+
+#include "avcodec.h"
+
+#include "dxva2.h"
+
+#ifndef false
+#define false FALSE
+#endif
+
+
+
+#define VA_DXVA2_MAX_SURFACE_COUNT (64)
+#define BAK_BUF_NUM 4
+
+#define DELAY_FRAMES_NUM (BAK_BUF_NUM - 1)
+
+typedef struct {
+ LPDIRECT3DSURFACE9 d3d;
+ int                refcount;
+ unsigned int       order;
+} ff_va_surface_t;
+
+typedef struct
+{
+ int          codec_id;
+ int          width;
+ int          height;
+
+ /* DLL */
+ HINSTANCE             hd3d9_dll;
+ HINSTANCE             hdxva2_dll;
+
+ /* Direct3D */
+
+ LPDIRECT3D9            d3dobj;
+ LPDIRECT3DDEVICE9      d3ddev;
+ D3DPRESENT_PARAMETERS  d3dpp;
+ D3DADAPTER_IDENTIFIER9 d3dai;
+
+ /* Device manager */
+ UINT                     token;
+ IDirect3DDeviceManager9  *devmng;
+ HANDLE                   device;
+
+ /* Video service */
+ IDirectXVideoDecoderService  *vs;
+ GUID                         input;
+ D3DFORMAT                    render;
+
+ /* Video decoder */
+ DXVA2_ConfigPictureDecode    cfg;
+ IDirectXVideoDecoder         *decoder;
+
+ /* Option conversion */
+ D3DFORMAT                    output;
+
+ /* */
+ struct dxva_context hw;
+
+ /* */
+ unsigned     surface_count;
+ unsigned     surface_order;
+ int          surface_width;
+ int          surface_height;
+
+ uint8_t *d3ddata;
+
+ uint8_t *d3ddata_delay[DELAY_FRAMES_NUM];
+
+ //save pts,pkt_pts,pkt_dts,best_effort_timestamp
+
+ int64_t best_effort_timestamp_delay[DELAY_FRAMES_NUM + 1];
+
+ int64_t pts_delay[DELAY_FRAMES_NUM + 1];
+
+ int64_t pkt_pts_delay[DELAY_FRAMES_NUM + 1];
+
+ int64_t pkt_dts_delay[DELAY_FRAMES_NUM + 1];
+
+ ff_va_surface_t surface[VA_DXVA2_MAX_SURFACE_COUNT];
+ LPDIRECT3DSURFACE9 hw_surface[VA_DXVA2_MAX_SURFACE_COUNT];
+ int interopflg;
+
+ int (*get_buffer)(struct AVCodecContext *c, AVFrame *pic);
+
+ void (*release_buffer)(struct AVCodecContext *c, AVFrame *pic);
+} ff_va_dxva2_t;
+
+
+typedef struct {
+ const char   *name;
+ D3DFORMAT    format;
+ enum PixelFormat  codec;
+
+
+} d3d_format_t;
+
+/**
+ * video format description
+ */
+struct video_format_t
+{
+    enum PixelFormat  i_chroma;            /**< picture chroma */
+
+    unsigned int i_width;                  /**< picture width */
+    unsigned int i_height;                 /**< picture height */
+    unsigned int i_x_offset;               /**< start offset of visible
area */
+    unsigned int i_y_offset;               /**< start offset of visible
area */
+    unsigned int i_visible_width;          /**< width of visible area */
+    unsigned int i_visible_height;         /**< height of visible area */
+
+    unsigned int i_bits_per_pixel;         /**< number of bits per pixel */
+
+    unsigned int i_sar_num;                /**< sample/pixel aspect ratio
*/
+    unsigned int i_sar_den;
+
+    unsigned int i_frame_rate;             /**< frame rate numerator */
+    unsigned int i_frame_rate_base;        /**< frame rate denominator */
+
+    uint32_t i_rmask, i_gmask, i_bmask;    /**< color masks for RGB chroma
*/
+    int i_rrshift, i_lrshift;
+    int i_rgshift, i_lgshift;
+    int i_rbshift, i_lbshift;
+};
+
+
+typedef struct {
+ const char   *name;
+ const GUID  *guid;
+ int          codec;
+} dxva2_mode_t;
+
+
+
+/** Timeout parameter passed to DtsProcOutput() in us */
+#define OUTPUT_PROC_TIMEOUT 50
+/** Step between fake timestamps passed to hardware in units of 100ns */
+#define TIMESTAMP_UNIT 100000
+/** Initial value in us of the wait in decode() */
+#define BASE_WAIT 10000
+/** Increment in us to adjust wait in decode() */
+#define WAIT_UNIT 1000
+
+
+/*****************************************************************************
+ * Module private data
+
****************************************************************************/
+
+
+ff_va_dxva2_t *av_new_dxva2(int codec_id);
+
+int av_setup_dxva2(ff_va_dxva2_t *external, void **hw, enum PixelFormat
*chroma,int width, int height, void *get_buffer,void *release_buffer);
+
+enum PixelFormat av_dxva2_get_format( AVCodecContext *p_context,const enum
PixelFormat *pi_fmt );
+
+int av_dxva2_get_buffer( struct AVCodecContext *p_context,AVFrame
*p_ff_pic );
+
+int av_dxva2_reget_buffer( struct AVCodecContext *p_context, AVFrame
*p_ff_pic );
+
+void av_dxva2_release_buffer( struct AVCodecContext *p_context,AVFrame
*p_ff_pic );
+
+int av_extract_dxva2( ff_va_dxva2_t *dxva2,AVFrame *frame,uint32_t
codecid);
+
+void av_save_framepts_info(ff_va_dxva2_t *dxva2,AVFrame *frame);
+
+void av_release_dxva2();
+
+#endif
+
+
-- 
1.7.11.msysgit.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-add-code-to-make-ffmpeg.exe-can-use-dxva2-api.patch
Type: application/octet-stream
Size: 64785 bytes
Desc: not available
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20121213/5a7eab2b/attachment.obj>


More information about the ffmpeg-devel mailing list