Browse code

Add VDPAU hardware accelerated decoding for MPEG1 and MPEG2 which can be used by video players.

Original patch by NVIDIA corporation.

Originally committed as revision 16628 to svn://svn.ffmpeg.org/ffmpeg/trunk

NVIDIA Corporation authored on 2009/01/16 11:14:07
Showing 9 changed files
... ...
@@ -993,6 +993,7 @@ mjpeg_encoder_select="aandct"
993 993
 mpeg1video_encoder_select="aandct"
994 994
 mpeg2video_encoder_select="aandct"
995 995
 mpeg4_encoder_select="aandct"
996
+mpeg_vdpau_decoder_deps="vdpau"
996 997
 mpeg_xvmc_decoder_deps="xvmc X11_extensions_XvMClib_h"
997 998
 msmpeg4v1_encoder_select="aandct"
998 999
 msmpeg4v2_encoder_select="aandct"
... ...
@@ -133,6 +133,7 @@ OBJS-$(CONFIG_MP3ON4_DECODER)          += mpegaudiodec.o mpegaudiodecheader.o mp
133 133
 OBJS-$(CONFIG_MPC7_DECODER)            += mpc7.o mpc.o mpegaudiodec.o mpegaudiodecheader.o mpegaudio.o mpegaudiodata.o
134 134
 OBJS-$(CONFIG_MPC8_DECODER)            += mpc8.o mpc.o mpegaudiodec.o mpegaudiodecheader.o mpegaudio.o mpegaudiodata.o
135 135
 OBJS-$(CONFIG_MDEC_DECODER)            += mdec.o mpeg12.o mpeg12data.o mpegvideo.o error_resilience.o
136
+OBJS-$(CONFIG_MPEG_VDPAU_DECODER)      += vdpauvideo.o mpeg12.o mpeg12data.o mpegvideo.o error_resilience.o
136 137
 OBJS-$(CONFIG_MPEGVIDEO_DECODER)       += mpeg12.o mpeg12data.o mpegvideo.o error_resilience.o
137 138
 OBJS-$(CONFIG_MPEG1VIDEO_DECODER)      += mpeg12.o mpeg12data.o mpegvideo.o error_resilience.o
138 139
 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
... ...
@@ -109,6 +109,7 @@ void avcodec_register_all(void)
109 109
     REGISTER_ENCDEC  (MPEG2VIDEO, mpeg2video);
110 110
     REGISTER_ENCDEC  (MPEG4, mpeg4);
111 111
     REGISTER_DECODER (MPEGVIDEO, mpegvideo);
112
+    REGISTER_DECODER (MPEG_VDPAU, mpeg_vdpau);
112 113
     REGISTER_ENCDEC  (MSMPEG4V1, msmpeg4v1);
113 114
     REGISTER_ENCDEC  (MSMPEG4V2, msmpeg4v2);
114 115
     REGISTER_ENCDEC  (MSMPEG4V3, msmpeg4v3);
... ...
@@ -267,6 +267,12 @@ static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
267 267
     [PIX_FMT_XVMC_MPEG2_IDCT] = {
268 268
         .name = "xvmcidct",
269 269
     },
270
+    [PIX_FMT_VDPAU_MPEG1] = {
271
+        .name = "vdpau_mpeg1",
272
+    },
273
+    [PIX_FMT_VDPAU_MPEG2] = {
274
+        .name = "vdpau_mpeg2",
275
+    },
270 276
     [PIX_FMT_VDPAU_H264] = {
271 277
         .name = "vdpau_h264",
272 278
     },
... ...
@@ -34,6 +34,7 @@
34 34
 #include "mpeg12data.h"
35 35
 #include "mpeg12decdata.h"
36 36
 #include "bytestream.h"
37
+#include "vdpau_internal.h"
37 38
 
38 39
 //#undef NDEBUG
39 40
 //#include <assert.h>
... ...
@@ -1218,7 +1219,12 @@ static enum PixelFormat mpeg_get_pixelformat(AVCodecContext *avctx){
1218 1218
 
1219 1219
     if(avctx->xvmc_acceleration)
1220 1220
         return avctx->get_format(avctx,pixfmt_xvmc_mpg2_420);
1221
-    else{
1221
+    else if(avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU){
1222
+        if(avctx->codec_id == CODEC_ID_MPEG1VIDEO)
1223
+            return PIX_FMT_VDPAU_MPEG1;
1224
+        else
1225
+            return PIX_FMT_VDPAU_MPEG2;
1226
+    }else{
1222 1227
         if(s->chroma_format <  2)
1223 1228
             return PIX_FMT_YUV420P;
1224 1229
         else if(s->chroma_format == 2)
... ...
@@ -1307,7 +1313,8 @@ static int mpeg_decode_postinit(AVCodecContext *avctx){
1307 1307
 
1308 1308
         avctx->pix_fmt = mpeg_get_pixelformat(avctx);
1309 1309
         //until then pix_fmt may be changed right after codec init
1310
-        if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT )
1310
+        if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT ||
1311
+            s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU )
1311 1312
             if( avctx->idct_algo == FF_IDCT_AUTO )
1312 1313
                 avctx->idct_algo = FF_IDCT_SIMPLE;
1313 1314
 
... ...
@@ -2076,7 +2083,8 @@ static int vcr2_init_sequence(AVCodecContext *avctx)
2076 2076
 
2077 2077
     avctx->pix_fmt = mpeg_get_pixelformat(avctx);
2078 2078
 
2079
-    if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT )
2079
+    if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT ||
2080
+        s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU )
2080 2081
         if( avctx->idct_algo == FF_IDCT_AUTO )
2081 2082
             avctx->idct_algo = FF_IDCT_SIMPLE;
2082 2083
 
... ...
@@ -2304,6 +2312,10 @@ static int decode_chunks(AVCodecContext *avctx,
2304 2304
                     for(i=0; i<s->slice_count; i++)
2305 2305
                         s2->error_count += s2->thread_context[i]->error_count;
2306 2306
                 }
2307
+
2308
+                if (avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
2309
+                    ff_vdpau_mpeg_picture_complete(s2, buf, buf_size, s->slice_count);
2310
+
2307 2311
                 if (slice_end(avctx, picture)) {
2308 2312
                     if(s2->last_picture_ptr || s2->low_delay) //FIXME merge with the stuff in mpeg_decode_slice
2309 2313
                         *data_size = sizeof(AVPicture);
... ...
@@ -2389,6 +2401,11 @@ static int decode_chunks(AVCodecContext *avctx,
2389 2389
                     return -1;
2390 2390
                 }
2391 2391
 
2392
+                if (avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU) {
2393
+                    s->slice_count++;
2394
+                    break;
2395
+                }
2396
+
2392 2397
                 if(avctx->thread_count > 1){
2393 2398
                     int threshold= (s2->mb_height*s->slice_count + avctx->thread_count/2) / avctx->thread_count;
2394 2399
                     if(threshold <= mb_y){
... ...
@@ -2508,3 +2525,20 @@ AVCodec mpeg_xvmc_decoder = {
2508 2508
 };
2509 2509
 
2510 2510
 #endif
2511
+
2512
+#if CONFIG_MPEG_VDPAU_DECODER
2513
+AVCodec mpeg_vdpau_decoder = {
2514
+    "mpegvideo_vdpau",
2515
+    CODEC_TYPE_VIDEO,
2516
+    CODEC_ID_MPEG2VIDEO,
2517
+    sizeof(Mpeg1Context),
2518
+    mpeg_decode_init,
2519
+    NULL,
2520
+    mpeg_decode_end,
2521
+    mpeg_decode_frame,
2522
+    CODEC_CAP_DR1 | CODEC_CAP_TRUNCATED | CODEC_CAP_HWACCEL_VDPAU | CODEC_CAP_DELAY,
2523
+    .flush= ff_mpeg_flush,
2524
+    .long_name = NULL_IF_CONFIG_SMALL("MPEG-1/2 video (VDPAU acceleration)"),
2525
+};
2526
+#endif
2527
+
... ...
@@ -70,6 +70,7 @@ struct vdpau_render_state {
70 70
 
71 71
     /** picture parameter information for all supported codecs */
72 72
     union VdpPictureInfo {
73
+        VdpPictureInfoMPEG1Or2 mpeg;
73 74
         VdpPictureInfoH264     h264;
74 75
     } info;
75 76
 
... ...
@@ -29,6 +29,10 @@
29 29
 
30 30
 void ff_vdpau_add_data_chunk(MpegEncContext *s, const uint8_t *buf,
31 31
                              int buf_size);
32
+
33
+void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf,
34
+                                    int buf_size, int slice_count);
35
+
32 36
 void ff_vdpau_h264_set_reference_frames(MpegEncContext *s);
33 37
 void ff_vdpau_h264_picture_complete(MpegEncContext *s);
34 38
 
... ...
@@ -177,4 +177,59 @@ void ff_vdpau_h264_picture_complete(MpegEncContext *s)
177 177
     render->bitstream_buffers_used = 0;
178 178
 }
179 179
 
180
+void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf,
181
+                                    int buf_size, int slice_count)
182
+{
183
+    struct vdpau_render_state * render, * last, * next;
184
+    int i;
185
+
186
+    render = (struct vdpau_render_state*)s->current_picture_ptr->data[0];
187
+    assert(render);
188
+
189
+    /* fill VdpPictureInfoMPEG1Or2 struct */
190
+    render->info.mpeg.picture_structure          = s->picture_structure;
191
+    render->info.mpeg.picture_coding_type        = s->pict_type;
192
+    render->info.mpeg.intra_dc_precision         = s->intra_dc_precision;
193
+    render->info.mpeg.frame_pred_frame_dct       = s->frame_pred_frame_dct;
194
+    render->info.mpeg.concealment_motion_vectors = s->concealment_motion_vectors;
195
+    render->info.mpeg.intra_vlc_format           = s->intra_vlc_format;
196
+    render->info.mpeg.alternate_scan             = s->alternate_scan;
197
+    render->info.mpeg.q_scale_type               = s->q_scale_type;
198
+    render->info.mpeg.top_field_first            = s->top_field_first;
199
+    render->info.mpeg.full_pel_forward_vector    = s->full_pel[0]; // MPEG-1 only.  Set 0 for MPEG-2
200
+    render->info.mpeg.full_pel_backward_vector   = s->full_pel[1]; // MPEG-1 only.  Set 0 for MPEG-2
201
+    render->info.mpeg.f_code[0][0]               = s->mpeg_f_code[0][0]; // For MPEG-1 fill both horiz. & vert.
202
+    render->info.mpeg.f_code[0][1]               = s->mpeg_f_code[0][1];
203
+    render->info.mpeg.f_code[1][0]               = s->mpeg_f_code[1][0];
204
+    render->info.mpeg.f_code[1][1]               = s->mpeg_f_code[1][1];
205
+    for (i = 0; i < 64; ++i) {
206
+        render->info.mpeg.intra_quantizer_matrix[i]     = s->intra_matrix[i];
207
+        render->info.mpeg.non_intra_quantizer_matrix[i] = s->inter_matrix[i];
208
+    }
209
+
210
+    render->info.mpeg.forward_reference          = VDP_INVALID_HANDLE;
211
+    render->info.mpeg.backward_reference         = VDP_INVALID_HANDLE;
212
+
213
+    switch(s->pict_type){
214
+    case  FF_B_TYPE:
215
+        next = (struct vdpau_render_state*)s->next_picture.data[0];
216
+        assert(next);
217
+        render->info.mpeg.backward_reference     = next->surface;
218
+        // no return here, going to set forward prediction
219
+    case  FF_P_TYPE:
220
+        last = (struct vdpau_render_state*)s->last_picture.data[0];
221
+        if (!last) // FIXME: Does this test make sense?
222
+            last = render; // predict second field from the first
223
+        render->info.mpeg.forward_reference      = last->surface;
224
+    }
225
+
226
+    ff_vdpau_add_data_chunk(s, buf, buf_size);
227
+
228
+    render->info.mpeg.slice_count                = slice_count;
229
+
230
+    if (slice_count)
231
+        ff_draw_horiz_band(s, 0, s->avctx->height);
232
+    render->bitstream_buffers_used               = 0;
233
+}
234
+
180 235
 /* @}*/
... ...
@@ -122,6 +122,8 @@ enum PixelFormat {
122 122
     PIX_FMT_YUVJ440P,  ///< Planar YUV 4:4:0 full scale (jpeg)
123 123
     PIX_FMT_YUVA420P,  ///< Planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
124 124
     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
125
+    PIX_FMT_VDPAU_MPEG1,///< MPEG1 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
126
+    PIX_FMT_VDPAU_MPEG2,///< MPEG2 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
125 127
     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
126 128
 };
127 129