[FFmpeg-devel] [PATCH]VDPAU patch for MPEG1/2 decoding, round 3

Carl Eugen Hoyos cehoyos
Thu Jan 8 03:23:22 CET 2009


Hi!

Attached is an updated version of the VDPAU patch to allow hardware 
decoding of MPEG1/2 streams.

Please comment, Carl Eugen
-------------- next part --------------
Index: configure
===================================================================
--- configure	(revision 16489)
+++ configure	(working copy)
@@ -988,6 +988,7 @@
 mpeg1video_encoder_select="aandct"
 mpeg2video_encoder_select="aandct"
 mpeg4_encoder_select="aandct"
+mpeg_vdpau_decoder_deps="vdpau"
 mpeg_xvmc_decoder_deps="xvmc X11_extensions_XvMClib_h"
 msmpeg4v1_encoder_select="aandct"
 msmpeg4v2_encoder_select="aandct"
Index: libavcodec/vdpau_internal.h
===================================================================
--- libavcodec/vdpau_internal.h	(revision 16492)
+++ libavcodec/vdpau_internal.h	(working copy)
@@ -26,7 +26,13 @@
 
 #include <stdint.h>
 #include "h264.h"
+#undef interlaced_dct
+#undef mb_intra
 
+void ff_VDPAU_mpeg_field_start(MpegEncContext *s);
+void ff_VDPAU_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf,
+                                    int buf_size, int slice_count);
+
 void ff_vdpau_h264_add_data_chunk(H264Context *h, const uint8_t *buf,
                                   int buf_size);
 void ff_vdpau_h264_picture_complete(H264Context *h);
Index: libavcodec/Makefile
===================================================================
--- libavcodec/Makefile	(revision 16489)
+++ libavcodec/Makefile	(working copy)
@@ -131,6 +131,7 @@
 OBJS-$(CONFIG_MPC7_DECODER)            += mpc7.o mpc.o mpegaudiodec.o mpegaudiodecheader.o mpegaudio.o mpegaudiodata.o
 OBJS-$(CONFIG_MPC8_DECODER)            += mpc8.o mpc.o mpegaudiodec.o mpegaudiodecheader.o mpegaudio.o mpegaudiodata.o
 OBJS-$(CONFIG_MDEC_DECODER)            += mdec.o mpeg12.o mpeg12data.o mpegvideo.o error_resilience.o
+OBJS-$(CONFIG_MPEG_VDPAU_DECODER)      += vdpauvideo.o
 OBJS-$(CONFIG_MPEGVIDEO_DECODER)       += mpeg12.o mpeg12data.o mpegvideo.o error_resilience.o
 OBJS-$(CONFIG_MPEG1VIDEO_DECODER)      += mpeg12.o mpeg12data.o mpegvideo.o error_resilience.o
 OBJS-$(CONFIG_MPEG1VIDEO_ENCODER)      += mpeg12enc.o mpeg12data.o mpegvideo_enc.o motion_est.o ratecontrol.o mpeg12.o mpeg12data.o mpegvideo.o error_resilience.o
Index: libavcodec/vdpauvideo.c
===================================================================
--- libavcodec/vdpauvideo.c	(revision 16492)
+++ libavcodec/vdpauvideo.c	(working copy)
@@ -37,6 +37,79 @@
  * @{
  */
 
+void ff_vdpau_mpeg_field_start(MpegEncContext *s)
+{
+    struct vdpau_render_state * render, * last, * next;
+    int i;
+
+    render = (struct vdpau_render_state*)s->current_picture.data[0];
+    assert(render);
+
+    /* fill VdpPictureInfoMPEG1Or2 struct */
+    render->info.mpeg.picture_structure          = s->picture_structure;
+    render->info.mpeg.picture_coding_type        = s->pict_type;
+    render->info.mpeg.intra_dc_precision         = s->intra_dc_precision;
+    render->info.mpeg.frame_pred_frame_dct       = s->frame_pred_frame_dct;
+    render->info.mpeg.concealment_motion_vectors = s->concealment_motion_vectors;
+    render->info.mpeg.intra_vlc_format           = s->intra_vlc_format;
+    render->info.mpeg.alternate_scan             = s->alternate_scan;
+    render->info.mpeg.q_scale_type               = s->q_scale_type;
+    render->info.mpeg.top_field_first            = s->top_field_first;
+    render->info.mpeg.full_pel_forward_vector    = s->full_pel[0]; // MPEG-1 only.  Set 0 for MPEG-2
+    render->info.mpeg.full_pel_backward_vector   = s->full_pel[1]; // MPEG-1 only.  Set 0 for MPEG-2
+    render->info.mpeg.f_code[0][0]               = s->mpeg_f_code[0][0]; // For MPEG-1 fill both horiz. & vert.
+    render->info.mpeg.f_code[0][1]               = s->mpeg_f_code[0][1];
+    render->info.mpeg.f_code[1][0]               = s->mpeg_f_code[1][0];
+    render->info.mpeg.f_code[1][1]               = s->mpeg_f_code[1][1];
+    for (i = 0; i < 64; ++i) {
+        render->info.mpeg.intra_quantizer_matrix[i]     = s->intra_matrix[i];
+        render->info.mpeg.non_intra_quantizer_matrix[i] = s->inter_matrix[i];
+    }
+
+    render->info.mpeg.forward_reference  = VDP_INVALID_HANDLE;
+    render->info.mpeg.backward_reference = VDP_INVALID_HANDLE;
+
+    switch(s->pict_type){
+    case  FF_B_TYPE:
+        next = (struct vdpau_render_state*)s->next_picture.data[0];
+        assert(next);
+        render->info.mpeg.backward_reference = next->surface;
+        // no return 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.mpeg.forward_reference = last->surface;
+    }
+}
+
+void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf,
+                                    int buf_size, int slice_count)
+{
+    struct vdpau_render_state * render;
+
+    render = (struct vdpau_render_state*)s->current_picture_ptr->data[0];
+    assert(render);
+
+    render->bitstream_buffers= av_fast_realloc(
+        render->bitstream_buffers,
+        &render->bitstream_buffers_allocated,
+        sizeof(*render->bitstream_buffers)*(render->bitstream_buffers_used + 1)
+    );
+
+    render->bitstream_buffers[0].struct_version  = VDP_BITSTREAM_BUFFER_VERSION;
+    render->bitstream_buffers[0].bitstream_bytes = buf_size;
+    render->bitstream_buffers[0].bitstream       = buf;
+    render->bitstream_buffers_used               = 1;
+
+    render->info.mpeg.slice_count                = slice_count;
+
+    if (slice_count > 0) {
+        ff_draw_horiz_band(s, 0, s->avctx->height);
+    }
+    render->bitstream_buffers_used = 0;
+}
+
 static void vdpau_h264_set_reference_frames(H264Context *h)
 {
     MpegEncContext * s = &h->s;
Index: libavcodec/mpegvideo_parser.c
===================================================================
--- libavcodec/mpegvideo_parser.c	(revision 16489)
+++ libavcodec/mpegvideo_parser.c	(working copy)
@@ -174,7 +174,7 @@
 }
 
 AVCodecParser mpegvideo_parser = {
-    { CODEC_ID_MPEG1VIDEO, CODEC_ID_MPEG2VIDEO },
+    { CODEC_ID_MPEG1VIDEO, CODEC_ID_MPEG2VIDEO, CODEC_ID_MPEGVIDEO_VDPAU },
     sizeof(ParseContext1),
     NULL,
     mpegvideo_parse,
Index: libavcodec/vdpau.h
===================================================================
--- libavcodec/vdpau.h	(revision 16491)
+++ libavcodec/vdpau.h	(working copy)
@@ -70,6 +70,7 @@
 
     /** picture parameter information for all supported codecs */
     union VdpPictureInfo {
+        VdpPictureInfoMPEG1Or2 mpeg;
         VdpPictureInfoH264     h264;
     } info;
 
Index: libavcodec/mpeg12.c
===================================================================
--- libavcodec/mpeg12.c	(revision 16489)
+++ libavcodec/mpeg12.c	(working copy)
@@ -34,6 +34,7 @@
 #include "mpeg12data.h"
 #include "mpeg12decdata.h"
 #include "bytestream.h"
+#include "vdpau_internal.h"
 
 //#undef NDEBUG
 //#include <assert.h>
@@ -1218,7 +1219,12 @@
 
     if(avctx->xvmc_acceleration)
         return avctx->get_format(avctx,pixfmt_xvmc_mpg2_420);
-    else{
+    else if(avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU){
+        if(avctx->sub_id == 1)
+            return PIX_FMT_VDPAU_MPEG1;
+        else
+            return PIX_FMT_VDPAU_MPEG2;
+    }else{
         if(s->chroma_format <  2)
             return PIX_FMT_YUV420P;
         else if(s->chroma_format == 2)
@@ -1306,7 +1312,8 @@
 
         avctx->pix_fmt = mpeg_get_pixelformat(avctx);
         //until then pix_fmt may be changed right after codec init
-        if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT )
+        if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT ||
+            s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU )
             if( avctx->idct_algo == FF_IDCT_AUTO )
                 avctx->idct_algo = FF_IDCT_SIMPLE;
 
@@ -1650,6 +1657,9 @@
          XVMC_field_start(s,avctx);
 #endif
 
+    if (s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
+        ff_vdpau_mpeg_field_start(s);
+
     return 0;
 }
 
@@ -1926,6 +1936,7 @@
 
         s->current_picture_ptr->qscale_type= FF_QSCALE_TYPE_MPEG2;
 
+        if (!(s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU))
         ff_er_frame_end(s);
 
         MPV_frame_end(s);
@@ -2075,7 +2086,8 @@
 
     avctx->pix_fmt = mpeg_get_pixelformat(avctx);
 
-    if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT )
+    if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT ||
+        s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU )
         if( avctx->idct_algo == FF_IDCT_AUTO )
             avctx->idct_algo = FF_IDCT_SIMPLE;
 
@@ -2303,6 +2315,10 @@
                     for(i=0; i<s->slice_count; i++)
                         s2->error_count += s2->thread_context[i]->error_count;
                 }
+
+                if (avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
+                    ff_vdpau_mpeg_picture_complete(s2, buf, buf_size, s->slice_count);
+
                 if (slice_end(avctx, picture)) {
                     if(s2->last_picture_ptr || s2->low_delay) //FIXME merge with the stuff in mpeg_decode_slice
                         *data_size = sizeof(AVPicture);
@@ -2388,6 +2404,11 @@
                     return -1;
                 }
 
+                if (avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) {
+                    s->slice_count++;
+                    break;                
+                }
+
                 if(avctx->thread_count > 1){
                     int threshold= (s2->mb_height*s->slice_count + avctx->thread_count/2) / avctx->thread_count;
                     if(threshold <= mb_y){
@@ -2507,3 +2528,20 @@
 };
 
 #endif
+
+#ifdef CONFIG_MPEG_VDPAU_DECODER
+AVCodec mpeg_vdpau_decoder = {
+    "mpegvideo_vdpau",
+    CODEC_TYPE_VIDEO,
+    CODEC_ID_MPEGVIDEO_VDPAU,
+    sizeof(Mpeg1Context),
+    mpeg_decode_init,
+    NULL,
+    mpeg_decode_end,
+    mpeg_decode_frame,
+    CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_HWACCEL_VDPAU | CODEC_CAP_DELAY,
+    .flush= ff_mpeg_flush,
+    .long_name = NULL_IF_CONFIG_SMALL("MPEG-1/2 video (VDPAU acceleration)"),
+};
+#endif
+
Index: libavcodec/allcodecs.c
===================================================================
--- libavcodec/allcodecs.c	(revision 16489)
+++ libavcodec/allcodecs.c	(working copy)
@@ -104,6 +104,7 @@
     REGISTER_DECODER (MJPEGB, mjpegb);
     REGISTER_DECODER (MMVIDEO, mmvideo);
     REGISTER_DECODER (MOTIONPIXELS, motionpixels);
+    REGISTER_DECODER (MPEG_VDPAU, mpeg_vdpau);
     REGISTER_DECODER (MPEG_XVMC, mpeg_xvmc);
     REGISTER_ENCDEC  (MPEG1VIDEO, mpeg1video);
     REGISTER_ENCDEC  (MPEG2VIDEO, mpeg2video);
Index: libavcodec/avcodec.h
===================================================================
--- libavcodec/avcodec.h	(revision 16489)
+++ libavcodec/avcodec.h	(working copy)
@@ -193,6 +193,7 @@
 
     /* "codecs" for HW decoding with VDPAU */
     CODEC_ID_H264_VDPAU= 0x9000,
+    CODEC_ID_MPEGVIDEO_VDPAU,
 
     /* various PCM "codecs" */
     CODEC_ID_PCM_S16LE= 0x10000,
Index: libavcodec/imgconvert.c
===================================================================
--- libavcodec/imgconvert.c	(revision 16489)
+++ libavcodec/imgconvert.c	(working copy)
@@ -267,6 +267,12 @@
     [PIX_FMT_XVMC_MPEG2_IDCT] = {
         .name = "xvmcidct",
     },
+    [PIX_FMT_VDPAU_MPEG1] = {
+        .name = "vdpau_mpeg1",
+    },
+    [PIX_FMT_VDPAU_MPEG2] = {
+        .name = "vdpau_mpeg2",
+    },
     [PIX_FMT_VDPAU_H264] = {
         .name = "vdpau_h264",
     },



More information about the ffmpeg-devel mailing list