changeset 36322:d649e84ea8d5

Make VDPAU support work again with latest FFmpeg.
author reimar
date Sun, 11 Aug 2013 18:28:58 +0000
parents 9c5b06130385
children 335349ca2137
files etc/codecs.conf fmt-conversion.c libmpcodecs/img_format.h libmpcodecs/vd_ffmpeg.c libvo/vo_vdpau.c
diffstat 5 files changed, 81 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/etc/codecs.conf	Sat Aug 10 04:02:17 2013 +0000
+++ b/etc/codecs.conf	Sun Aug 11 18:28:58 2013 +0000
@@ -542,7 +542,7 @@
   fourcc m2v1,m1v1
   fourcc "m1v "
   driver ffmpeg
-  dll "mpegvideo_vdpau"
+  dll "mpegvideo"
   out VDPAU_MPEG1
   out VDPAU_MPEG2
 
@@ -1249,7 +1249,7 @@
   status buggy
   fourcc WMV3,wmv3
   driver ffmpeg
-  dll wmv3_vdpau
+  dll wmv3
   out VDPAU_WMV3
 
 videocodec ffwmv3crystalhd
@@ -1275,7 +1275,7 @@
   fourcc WVC1,wvc1,WMVA
   fourcc vc-1,VC-1
   driver ffmpeg
-  dll vc1_vdpau
+  dll vc1
   out VDPAU_VC1
 
 videocodec ffvc1crystalhd
@@ -1348,7 +1348,7 @@
   fourcc Q264,V264
   format 0x10000005
   driver ffmpeg
-  dll h264_vdpau
+  dll h264
   out VDPAU_H264
 
 videocodec ffh264crystalhd
@@ -1486,7 +1486,7 @@
   fourcc DreX,DM4V,LMP4,DP02
   fourcc QMP4
   driver ffmpeg
-  dll mpeg4_vdpau
+  dll mpeg4
   out VDPAU_MPEG4
 
 videocodec ffodivxcrystalhd
--- a/fmt-conversion.c	Sat Aug 10 04:02:17 2013 +0000
+++ b/fmt-conversion.c	Sun Aug 11 18:28:58 2013 +0000
@@ -137,12 +137,6 @@
 
     { IMGFMT_XVMC_MOCO_MPEG2, AV_PIX_FMT_XVMC_MPEG2_MC },
     { IMGFMT_XVMC_IDCT_MPEG2, AV_PIX_FMT_XVMC_MPEG2_IDCT },
-    { IMGFMT_VDPAU_MPEG1,     AV_PIX_FMT_VDPAU_MPEG1 },
-    { IMGFMT_VDPAU_MPEG2,     AV_PIX_FMT_VDPAU_MPEG2 },
-    { IMGFMT_VDPAU_H264,      AV_PIX_FMT_VDPAU_H264 },
-    { IMGFMT_VDPAU_WMV3,      AV_PIX_FMT_VDPAU_WMV3 },
-    { IMGFMT_VDPAU_VC1,       AV_PIX_FMT_VDPAU_VC1 },
-    { IMGFMT_VDPAU_MPEG4,     AV_PIX_FMT_VDPAU_MPEG4 },
     { 0,                      AV_PIX_FMT_NONE }
 };
 
@@ -150,6 +144,7 @@
 {
     int i;
     enum AVPixelFormat pix_fmt;
+    if (IMGFMT_IS_VDPAU(fmt)) return AV_PIX_FMT_VDPAU;
     for (i = 0; conversion_map[i].fmt; i++)
         if (conversion_map[i].fmt == fmt)
             break;
--- a/libmpcodecs/img_format.h	Sat Aug 10 04:02:17 2013 +0000
+++ b/libmpcodecs/img_format.h	Sun Aug 11 18:28:58 2013 +0000
@@ -296,6 +296,13 @@
     int timestamp; // pts, 90000 Hz counter based
 } vo_mpegpes_t;
 
+struct vdpau_frame_data {
+    struct vdpau_render_state *render_state;
+    const void *info;
+    unsigned bitstream_buffers_used;
+    const void *bitstream_buffers;
+};
+
 const char *vo_format_name(int format);
 
 /**
--- a/libmpcodecs/vd_ffmpeg.c	Sat Aug 10 04:02:17 2013 +0000
+++ b/libmpcodecs/vd_ffmpeg.c	Sun Aug 11 18:28:58 2013 +0000
@@ -36,6 +36,10 @@
 
 #include "vd_internal.h"
 
+#if CONFIG_VDPAU
+#include "libavcodec/vdpau.h"
+#endif
+
 static const vd_info_t info = {
     "FFmpeg's libavcodec codec family",
     "ffmpeg",
@@ -201,19 +205,49 @@
     return CONTROL_UNKNOWN;
 }
 
+#if CONFIG_VDPAU
+static int vdpau_render_wrapper(AVCodecContext *s, AVFrame *f,
+    const VdpPictureInfo *info, uint32_t count, const VdpBitstreamBuffer *buffers)
+{
+    mp_image_t *mpi = f->opaque;
+    sh_video_t *sh = s->opaque;
+    struct vdpau_frame_data data;
+    uint8_t *planes[4] = {(void *)&data};
+    data.render_state = mpi->priv;
+    data.info = info;
+    data.bitstream_buffers_used = count;
+    data.bitstream_buffers = buffers;
+    mpcodecs_draw_slice(sh, planes, NULL, sh->disp_w, sh->disp_h, 0, 0);
+    return 0;
+}
+#endif
+
+static int pixfmt2imgfmt2(enum AVPixelFormat fmt, enum AVCodecID cid)
+{
+    if (fmt == AV_PIX_FMT_VDPAU)
+        switch (cid) {
+        case AV_CODEC_ID_H264:       return IMGFMT_VDPAU_H264;
+        case AV_CODEC_ID_MPEG1VIDEO: return IMGFMT_VDPAU_MPEG1;
+        case AV_CODEC_ID_MPEG2VIDEO: return IMGFMT_VDPAU_MPEG2;
+        case AV_CODEC_ID_MPEG4:      return IMGFMT_VDPAU_MPEG4;
+        case AV_CODEC_ID_WMV3:       return IMGFMT_VDPAU_WMV3;
+        case AV_CODEC_ID_VC1:        return IMGFMT_VDPAU_VC1;
+        }
+    return pixfmt2imgfmt(fmt);
+}
+
 static void set_format_params(struct AVCodecContext *avctx,
                               enum AVPixelFormat fmt)
 {
     int imgfmt;
     if (fmt == PIX_FMT_NONE)
         return;
-    imgfmt = pixfmt2imgfmt(fmt);
+    imgfmt = pixfmt2imgfmt2(fmt, avctx->codec_id);
     if (IMGFMT_IS_HWACCEL(imgfmt)) {
         sh_video_t *sh     = avctx->opaque;
         vd_ffmpeg_ctx *ctx = sh->context;
         ctx->do_dr1    = 1;
         ctx->nonref_dr = 0;
-        ctx->do_slices = 1;
         // HACK: FFmpeg thread handling is a major mess and
         // hinders any attempt to decide on hwaccel after the
         // codec is open. We really want this to change, so
@@ -223,9 +257,16 @@
         avctx->get_buffer      = get_buffer;
         avctx->release_buffer  = release_buffer;
         avctx->reget_buffer    = get_buffer;
-        avctx->draw_horiz_band = draw_slice;
         mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_XVMCAcceleratedMPEG2);
-        avctx->slice_flags = SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
+        if (IMGFMT_IS_VDPAU(imgfmt)) {
+            avctx->draw_horiz_band = NULL;
+            avctx->slice_flags = 0;
+            ctx->do_slices = 0;
+        } else {
+            avctx->draw_horiz_band = draw_slice;
+            avctx->slice_flags = SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD;
+            ctx->do_slices = 1;
+        }
     } else {
         avctx->slice_flags &= ~(SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD);
     }
@@ -459,6 +500,7 @@
             mp_msg(MSGT_DECVIDEO, MSGL_ERR, MSGTR_CantCloseCodec);
 
         av_freep(&avctx->extradata);
+        av_freep(&avctx->hwaccel_context);
         av_freep(&avctx->slice_offset);
     }
 
@@ -470,6 +512,7 @@
 static void draw_slice(struct AVCodecContext *s,
                         const AVFrame *src, int offset[4],
                         int y, int type, int height){
+    mp_image_t *mpi = src->opaque;
     sh_video_t *sh = s->opaque;
     uint8_t *source[MP_MAX_PLANES]= {src->data[0] + offset[0], src->data[1] + offset[1], src->data[2] + offset[2]};
     int strides[MP_MAX_PLANES] = {src->linesize[0], src->linesize[1], src->linesize[2]};
@@ -477,6 +520,10 @@
         mp_msg(MSGT_DECVIDEO, MSGL_FATAL, "BUG in FFmpeg, draw_slice called with NULL pointer!\n");
         return;
     }
+    if (IMGFMT_IS_VDPAU(mpi->imgfmt)) {
+        mp_msg(MSGT_DECVIDEO, MSGL_FATAL, "BUG in FFmpeg, draw_slice called for VDPAU!\n");
+        return;
+    }
     if (height < 0)
     {
         int i;
@@ -519,7 +566,7 @@
             sh->original_aspect = aspect;
         ctx->last_sample_aspect_ratio = avctx->sample_aspect_ratio;
         ctx->pix_fmt = pix_fmt;
-        ctx->best_csp = pixfmt2imgfmt(pix_fmt);
+        ctx->best_csp = pixfmt2imgfmt2(pix_fmt, avctx->codec_id);
     }
 }
 
@@ -644,6 +691,18 @@
     if(IMGFMT_IS_HWACCEL(mpi->imgfmt)) {
         avctx->draw_horiz_band= draw_slice;
     }
+#if CONFIG_VDPAU
+    if (IMGFMT_IS_VDPAU(mpi->imgfmt)) {
+        struct vdpau_render_state *render = mpi->priv;
+        AVVDPAUContext *vdpc;
+        avctx->draw_horiz_band= NULL;
+        if (!avctx->hwaccel_context)
+            avctx->hwaccel_context = av_alloc_vdpaucontext();
+        vdpc = avctx->hwaccel_context;
+        vdpc->render2 = vdpau_render_wrapper;
+        mpi->planes[3] = render->surface;
+    }
+#endif
 #if CONFIG_XVMC
     if(IMGFMT_IS_XVMC(mpi->imgfmt)) {
         struct xvmc_pix_fmt *render = mpi->priv; //same as data[2]
@@ -1000,7 +1059,7 @@
     int i;
 
     for(i=0;fmt[i]!=PIX_FMT_NONE;i++){
-        imgfmt = pixfmt2imgfmt(fmt[i]);
+        imgfmt = pixfmt2imgfmt2(fmt[i], avctx->codec_id);
         if(!IMGFMT_IS_HWACCEL(imgfmt)) continue;
         mp_msg(MSGT_DECVIDEO, MSGL_INFO, MSGTR_MPCODECS_TryingPixfmt, i);
         if(init_vo(sh, fmt[i]) >= 0) {
--- a/libvo/vo_vdpau.c	Sat Aug 10 04:02:17 2013 +0000
+++ b/libvo/vo_vdpau.c	Sun Aug 11 18:28:58 2013 +0000
@@ -1009,8 +1009,8 @@
                       int x, int y)
 {
     VdpStatus vdp_st;
-    struct vdpau_render_state *rndr = (struct vdpau_render_state *)image[0];
-    int max_refs = image_format == IMGFMT_VDPAU_H264 ? rndr->info.h264.num_ref_frames : 2;
+    struct vdpau_frame_data *rndr = (struct vdpau_frame_data *)image[0];
+    int max_refs = image_format == IMGFMT_VDPAU_H264 ? ((VdpPictureInfoH264 *)rndr->info)->num_ref_frames : 2;
 
     if (handle_preemption() < 0)
         return VO_TRUE;
@@ -1021,7 +1021,7 @@
         && !create_vdp_decoder(image_format, vid_width, vid_height, max_refs))
         return VO_FALSE;
 
-    vdp_st = vdp_decoder_render(decoder, rndr->surface, (void *)&rndr->info, rndr->bitstream_buffers_used, rndr->bitstream_buffers);
+    vdp_st = vdp_decoder_render(decoder, rndr->render_state->surface, rndr->info, rndr->bitstream_buffers_used, rndr->bitstream_buffers);
     CHECK_ST_WARNING("Failed VDPAU decoder rendering");
     return VO_TRUE;
 }