[FFmpeg-devel] [PATCH]VDPAU patch for VC1 decoding, round 1

Carl Eugen Hoyos cehoyos
Wed Jan 7 22:50:39 CET 2009


Hi!

Attached is the first version of the VDPAU patch to enable HW decoding of 
VC1 and WMV3.

Please comment, Carl Eugen
-------------- next part --------------
Index: libavcodec/vc1_parser.c
===================================================================
--- libavcodec/vc1_parser.c	(revision 16481)
+++ libavcodec/vc1_parser.c	(working copy)
@@ -109,7 +109,7 @@
 }
 
 AVCodecParser vc1_parser = {
-    { CODEC_ID_VC1 },
+    { CODEC_ID_VC1, CODEC_ID_VC1_VDPAU },
     sizeof(ParseContext1),
     NULL,
     vc1_parse,
Index: libavcodec/vdpau_internal.h
===================================================================
--- libavcodec/vdpau_internal.h	(revision 16481)
+++ libavcodec/vdpau_internal.h	(working copy)
@@ -26,9 +26,14 @@
 
 #include <stdint.h>
 #include "h264.h"
+#undef interlaced_dct
+#undef mb_intra
 
 void ff_VDPAU_h264_add_data_chunk(H264Context *h, const uint8_t *buf,
                                   int buf_size);
 void ff_VDPAU_h264_picture_complete(H264Context *h);
 
+void ff_VDPAU_vc1_decode_picture(MpegEncContext *s, const uint8_t *buf,
+                                 int buf_size);
+
 #endif /* AVCODEC_VDPAU_INTERNAL_H */
Index: libavcodec/Makefile
===================================================================
--- libavcodec/Makefile	(revision 16481)
+++ libavcodec/Makefile	(working copy)
@@ -214,6 +214,7 @@
 OBJS-$(CONFIG_ULTI_DECODER)            += ulti.o
 OBJS-$(CONFIG_VB_DECODER)              += vb.o
 OBJS-$(CONFIG_VC1_DECODER)             += vc1.o vc1data.o vc1dsp.o msmpeg4data.o h263dec.o h263.o intrax8.o intrax8dsp.o error_resilience.o mpegvideo.o
+OBJS-$(CONFIG_VC1_VDPAU_DECODER)       += vdpauvideo.o
 OBJS-$(CONFIG_VCR1_DECODER)            += vcr1.o
 OBJS-$(CONFIG_VCR1_ENCODER)            += vcr1.o
 OBJS-$(CONFIG_VMDAUDIO_DECODER)        += vmdav.o
@@ -237,6 +238,7 @@
 OBJS-$(CONFIG_WMV2_DECODER)            += wmv2dec.o wmv2.o msmpeg4.o msmpeg4data.o h263dec.o h263.o intrax8.o intrax8dsp.o mpeg12data.o mpegvideo.o error_resilience.o
 OBJS-$(CONFIG_WMV2_ENCODER)            += wmv2enc.o wmv2.o msmpeg4.o msmpeg4data.o mpegvideo_enc.o motion_est.o ratecontrol.o h263.o mpeg12data.o mpegvideo.o error_resilience.o
 OBJS-$(CONFIG_WMV3_DECODER)            += vc1.o vc1data.o vc1dsp.o msmpeg4data.o h263dec.o h263.o intrax8.o intrax8dsp.o error_resilience.o mpegvideo.o
+OBJS-$(CONFIG_WMV3_VDPAU_DECODER)      += vdpauvideo.o
 OBJS-$(CONFIG_WNV1_DECODER)            += wnv1.o
 OBJS-$(CONFIG_WS_SND1_DECODER)         += ws-snd1.o
 OBJS-$(CONFIG_XAN_DPCM_DECODER)        += dpcm.o
Index: libavcodec/vdpauvideo.c
===================================================================
--- libavcodec/vdpauvideo.c	(revision 16481)
+++ libavcodec/vdpauvideo.c	(working copy)
@@ -24,6 +24,7 @@
 #include <limits.h>
 #include "avcodec.h"
 #include "h264.h"
+#include "vc1.h"
 
 #undef NDEBUG
 #include <assert.h>
@@ -180,4 +181,97 @@
     render->bitstreamBuffersUsed = 0;
 }
 
+void ff_VDPAU_vc1_decode_picture(MpegEncContext *s, const uint8_t *buf,
+                                 int buf_size)
+{
+    VC1Context *v = s->avctx->priv_data;
+    struct vdpau_render_state * render,* last, * next;
+
+    render = (struct vdpau_render_state*)s->current_picture.data[0];
+    assert(render);
+
+    /*  fill LvPictureInfoVC1 struct */
+    render->info.vc1.frame_coding_mode  = v->fcm;
+    render->info.vc1.postprocflag       = v->postprocflag;
+    render->info.vc1.pulldown           = v->broadcast;
+    render->info.vc1.interlace          = v->interlace;
+    render->info.vc1.tfcntrflag         = v->tfcntrflag;
+    render->info.vc1.finterpflag        = v->finterpflag;
+    render->info.vc1.psf                = v->psf;
+    render->info.vc1.dquant             = v->dquant;
+    render->info.vc1.panscan_flag       = v->panscanflag;
+    render->info.vc1.refdist_flag       = 0; //FIXME
+    render->info.vc1.quantizer          = v->quantizer_mode;
+    render->info.vc1.extended_mv        = v->extended_mv;
+    render->info.vc1.extended_dmv       = v->extended_dmv;
+    render->info.vc1.overlap            = v->overlap;
+    render->info.vc1.vstransform        = v->vstransform;
+    render->info.vc1.loopfilter         = v->s.loop_filter;
+    render->info.vc1.fastuvmc           = v->fastuvmc;
+    render->info.vc1.range_mapy_flag    = v->range_mapy_flag;
+    render->info.vc1.range_mapy         = v->range_mapy;
+    render->info.vc1.range_mapuv_flag   = v->range_mapuv_flag;
+    render->info.vc1.range_mapuv        = v->range_mapuv;
+    /* Specific to simple/main profile only */
+    render->info.vc1.multires           = v->multires;
+    render->info.vc1.syncmarker         = v->s.resync_marker;
+    render->info.vc1.rangered           = v->rangered;
+    render->info.vc1.maxbframes         = v->s.max_b_frames;
+    /* Presently, making these as 0 */
+    render->info.vc1.deblockEnable      = 0;
+    render->info.vc1.pquant             = 0;
+
+    render->info.vc1.forward_reference  = VDP_INVALID_HANDLE;
+    render->info.vc1.backward_reference = VDP_INVALID_HANDLE;
+
+    switch(s->pict_type){
+    case  FF_I_TYPE:
+        render->info.vc1.picture_type = 0;
+        break;
+    case  FF_B_TYPE:
+        if (v->bi_type)
+            render->info.vc1.picture_type = 4;
+        else
+            render->info.vc1.picture_type = 3;
+        break;
+    case  FF_P_TYPE:
+        render->info.vc1.picture_type = 1;
+        break;
+    case  FF_BI_TYPE:
+        render->info.vc1.picture_type = 4;
+        break;
+    }
+
+    switch(s->pict_type){
+    case  FF_B_TYPE:
+        next = (struct vdpau_render_state*)s->next_picture.data[0];
+        assert(next);
+        render->info.vc1.backward_reference = next->surface;
+        // no break here, going to set forward prediction
+    case  FF_P_TYPE:
+        last = (struct vdpau_render_state*)s->last_picture.data[0];
+        if (!last) // FIXME: Does this test make sense?
+            last = render; // predict second field from the first
+        render->info.vc1.forward_reference = last->surface;
+        break;
+    }
+
+    render->bitstreamBuffers= av_fast_realloc(
+        render->bitstreamBuffers,
+        &render->bitstreamBuffersAllocated,
+        sizeof(*render->bitstreamBuffers)*(render->bitstreamBuffersUsed + 1)
+    );
+
+    render->bitstreamBuffers[0].struct_version  = VDP_BITSTREAM_BUFFER_VERSION;
+    render->bitstreamBuffers[0].bitstream_bytes = buf_size;
+    render->bitstreamBuffers[0].bitstream       = buf;
+    render->bitstreamBuffersUsed                = 1;
+
+    // FIXME: I am not sure about how MPlayer calculates slice number.
+    render->info.vc1.slice_count                = 1;
+
+    ff_draw_horiz_band(s, 0, s->avctx->height);
+    render->bitstreamBuffersUsed = 0;
+}
+
 /* @}*/
Index: libavcodec/vdpau.h
===================================================================
--- libavcodec/vdpau.h	(revision 16481)
+++ libavcodec/vdpau.h	(working copy)
@@ -71,6 +71,7 @@
     /** picture parameter information for all supported codecs */
     union VdpPictureInfo {
         VdpPictureInfoH264     h264;
+        VdpPictureInfoVC1       vc1;
     } info;
 
     /** Describe size/location of the compressed video data. */
Index: libavcodec/h263dec.c
===================================================================
--- libavcodec/h263dec.c	(revision 16481)
+++ libavcodec/h263dec.c	(working copy)
@@ -92,6 +92,8 @@
         break;
     case CODEC_ID_VC1:
     case CODEC_ID_WMV3:
+    case CODEC_ID_VC1_VDPAU:
+    case CODEC_ID_WMV3_VDPAU:
         s->h263_msmpeg4 = 1;
         s->h263_pred = 1;
         s->msmpeg4_version=6;
Index: libavcodec/allcodecs.c
===================================================================
--- libavcodec/allcodecs.c	(revision 16481)
+++ libavcodec/allcodecs.c	(working copy)
@@ -155,6 +155,7 @@
     REGISTER_DECODER (ULTI, ulti);
     REGISTER_DECODER (VB, vb);
     REGISTER_DECODER (VC1, vc1);
+    REGISTER_DECODER (VC1_VDPAU, vc1_vdpau);
     REGISTER_DECODER (VCR1, vcr1);
     REGISTER_DECODER (VMDVIDEO, vmdvideo);
     REGISTER_DECODER (VMNC, vmnc);
@@ -167,6 +168,7 @@
     REGISTER_ENCDEC  (WMV1, wmv1);
     REGISTER_ENCDEC  (WMV2, wmv2);
     REGISTER_DECODER (WMV3, wmv3);
+    REGISTER_DECODER (WMV3_VDPAU, wmv3_vdpau);
     REGISTER_DECODER (WNV1, wnv1);
     REGISTER_DECODER (XAN_WC3, xan_wc3);
     REGISTER_DECODER (XL, xl);
Index: libavcodec/avcodec.h
===================================================================
--- libavcodec/avcodec.h	(revision 16481)
+++ libavcodec/avcodec.h	(working copy)
@@ -193,6 +193,8 @@
 
     /* "codecs" for HW decoding with VDPAU */
     CODEC_ID_H264_VDPAU= 0x9000,
+    CODEC_ID_VC1_VDPAU,
+    CODEC_ID_WMV3_VDPAU,
 
     /* various PCM "codecs" */
     CODEC_ID_PCM_S16LE= 0x10000,
Index: libavcodec/imgconvert.c
===================================================================
--- libavcodec/imgconvert.c	(revision 16481)
+++ libavcodec/imgconvert.c	(working copy)
@@ -270,6 +270,12 @@
     [PIX_FMT_VDPAU_H264] = {
         .name = "vdpau_h264",
     },
+    [PIX_FMT_VDPAU_VC1_MAIN] = {
+        .name = "vdpau_vc1_main",
+    },
+    [PIX_FMT_VDPAU_VC1_ADVANCED] = {
+        .name = "vdpau_vc1_advanced",
+    },
     [PIX_FMT_UYYVYY411] = {
         .name = "uyyvyy411",
         .nb_channels = 1,
Index: libavcodec/vc1.c
===================================================================
--- libavcodec/vc1.c	(revision 16481)
+++ libavcodec/vc1.c	(working copy)
@@ -34,6 +34,7 @@
 #include "msmpeg4data.h"
 #include "unary.h"
 #include "simple_idct.h"
+#include "vdpau_internal.h"
 
 #undef NDEBUG
 #include <assert.h>
@@ -3996,7 +3997,8 @@
 
     avctx->coded_width = avctx->width;
     avctx->coded_height = avctx->height;
-    if (avctx->codec_id == CODEC_ID_WMV3)
+    if (avctx->codec_id == CODEC_ID_WMV3
+        || avctx->codec_id == CODEC_ID_WMV3_VDPAU)
     {
         int count = 0;
 
@@ -4111,6 +4113,7 @@
     MpegEncContext *s = &v->s;
     AVFrame *pict = data;
     uint8_t *buf2 = NULL;
+    const uint8_t *buf_vdpau = buf;
 
     /* no supplementary picture */
     if (buf_size == 0) {
@@ -4132,8 +4135,18 @@
         s->current_picture_ptr= &s->picture[i];
     }
 
+    // pxt_fmt calculation for VDPAU.
+    if (avctx->codec_id == CODEC_ID_VC1_VDPAU
+        || avctx->codec_id == CODEC_ID_WMV3_VDPAU){
+        if (v->profile < PROFILE_ADVANCED)
+            avctx->pix_fmt = PIX_FMT_VDPAU_VC1_MAIN;
+        else
+            avctx->pix_fmt = PIX_FMT_VDPAU_VC1_ADVANCED;
+    }
+
     //for advanced profile we may need to parse and unescape data
-    if (avctx->codec_id == CODEC_ID_VC1) {
+    if (avctx->codec_id == CODEC_ID_VC1
+        || avctx->codec_id == CODEC_ID_VC1_VDPAU) {
         int buf_size2 = 0;
         buf2 = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
 
@@ -4148,6 +4161,9 @@
                 if(size <= 0) continue;
                 switch(AV_RB32(start)){
                 case VC1_CODE_FRAME:
+                    if (avctx->codec_id == CODEC_ID_VC1_VDPAU
+                        || avctx->codec_id == CODEC_ID_WMV3_VDPAU)
+                        buf_vdpau = start;
                     buf_size2 = vc1_unescape_buffer(start + 4, size, buf2);
                     break;
                 case VC1_CODE_ENTRYPOINT: /* it should be before frame data */
@@ -4236,6 +4252,10 @@
     s->me.qpel_put= s->dsp.put_qpel_pixels_tab;
     s->me.qpel_avg= s->dsp.avg_qpel_pixels_tab;
 
+    if (avctx->codec_id == CODEC_ID_VC1_VDPAU
+        || avctx->codec_id == CODEC_ID_WMV3_VDPAU)
+        ff_VDPAU_vc1_decode_picture(s, buf_vdpau, (buf + buf_size) - buf_vdpau);
+    else {
     ff_er_frame_start(s);
 
     v->bits = buf_size * 8;
@@ -4244,6 +4264,7 @@
 //  if(get_bits_count(&s->gb) > buf_size * 8)
 //      return -1;
     ff_er_frame_end(s);
+    }
 
     MPV_frame_end(s);
 
@@ -4317,3 +4338,35 @@
     NULL,
     .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9"),
 };
+
+#if ENABLE_WMV3_VDPAU_DECODER
+AVCodec wmv3_vdpau_decoder = {
+    "wmv3_vdpau",
+    CODEC_TYPE_VIDEO,
+    CODEC_ID_WMV3_VDPAU,
+    sizeof(VC1Context),
+    vc1_decode_init,
+    NULL,
+    vc1_decode_end,
+    vc1_decode_frame,
+    CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_HWACCEL_VDPAU,
+    NULL,
+    .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9 VDPAU"),
+};
+#endif
+
+#if ENABLE_VC1_VDPAU_DECODER
+AVCodec vc1_vdpau_decoder = {
+    "vc1_vdpau",
+    CODEC_TYPE_VIDEO,
+    CODEC_ID_VC1_VDPAU,
+    sizeof(VC1Context),
+    vc1_decode_init,
+    NULL,
+    vc1_decode_end,
+    vc1_decode_frame,
+    CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_HWACCEL_VDPAU,
+    NULL,
+    .long_name = NULL_IF_CONFIG_SMALL("SMPTE VC-1 VDPAU"),
+};
+#endif
Index: libavutil/avutil.h
===================================================================
--- libavutil/avutil.h	(revision 16481)
+++ libavutil/avutil.h	(working copy)
@@ -122,6 +122,8 @@
     PIX_FMT_YUVJ440P,  ///< Planar YUV 4:4:0 full scale (jpeg)
     PIX_FMT_YUVA420P,  ///< Planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
     PIX_FMT_VDPAU_H264,///< H264 HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+    PIX_FMT_VDPAU_VC1_MAIN,///< VC1 main profile HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
+    PIX_FMT_VDPAU_VC1_ADVANCED,///< VC1 advanced profile HW decoding with VDPAU, data[0] contains a vdpau_render_state struct which contains the bitstream of the slices as well as various fields extracted from headers
     PIX_FMT_NB,        ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
 };
 



More information about the ffmpeg-devel mailing list