[FFmpeg-devel] [PATCH]VDPAU patch for MPEG1/2 decoding, round 1
Carl Eugen Hoyos
cehoyos
Mon Jan 5 18:41:13 CET 2009
Hi!
Attached patch is a first version of the patch to support MPEG1 and MPEG2
hardware decoding with VDPAU.
There are still obvious issues:
I don't know how to cope with the ugliness in vdpau_internal.h, hints are
very appreciated.
I don't konw if mpeg_set_pixelformat() is the way to go, it seems to
change behaviour.
Tested with zelda\ first\ commercial.mpeg and dvb, V.VOB does not work (as
with the original NVIDIA patch).
Please comment, Carl Eugen
-------------- next part --------------
Index: configure
===================================================================
--- configure (revision 16437)
+++ configure (working copy)
@@ -982,6 +982,7 @@
ljpeg_encoder_select="aandct"
loco_decoder_select="golomb"
mjpeg_encoder_select="aandct"
+mpeg_vdpau_decoder_deps="vdpau"
mpeg1video_encoder_select="aandct"
mpeg2video_encoder_select="aandct"
mpeg4_encoder_select="aandct"
Index: libavcodec/vdpau_internal.h
===================================================================
--- libavcodec/vdpau_internal.h (revision 16437)
+++ libavcodec/vdpau_internal.h (working copy)
@@ -24,6 +24,14 @@
#ifndef AVCODEC_VDPAU_INTERNAL_H
#define AVCODEC_VDPAU_INTERNAL_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 16437)
+++ 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 16437)
+++ libavcodec/vdpauvideo.c (working copy)
@@ -37,6 +37,83 @@
* @{
*/
+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_I_TYPE:
+ return; // no prediction from other frames
+ 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;
+ return;
+ }
+ assert(0);
+}
+
+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->bitstreamBuffers= av_fast_realloc(
+ render->bitstreamBuffers,
+ &render->bitstreamBuffersAlloced,
+ 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;
+
+ render->info.mpeg.slice_count = slice_count;
+
+ if (slice_count > 0) {
+ ff_draw_horiz_band(s, 0, s->avctx->height);
+ }
+ render->bitstreamBuffersUsed = 0;
+}
+
static void VDPAU_h264_set_reference_frames(H264Context *h)
{
MpegEncContext * s = &h->s;
Index: libavcodec/mpegvideo_parser.c
===================================================================
--- libavcodec/mpegvideo_parser.c (revision 16437)
+++ 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/mpeg12.c
===================================================================
--- libavcodec/mpeg12.c (revision 16437)
+++ 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>
@@ -1212,6 +1213,28 @@
}
}
+static void mpeg_set_pixelformat(AVCodecContext *avctx){
+ Mpeg1Context *s1 = avctx->priv_data;
+ MpegEncContext *s = &s1->mpeg_enc_ctx;
+
+ if(avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU){
+ avctx->idct_algo = FF_IDCT_SIMPLE;
+ if(avctx->sub_id == 1)
+ avctx->pix_fmt = PIX_FMT_VDPAU_MPEG1;
+ else
+ avctx->pix_fmt = PIX_FMT_VDPAU_MPEG2;
+ }else if(avctx->xvmc_acceleration)
+ avctx->pix_fmt = avctx->get_format(avctx,pixfmt_xvmc_mpg2_420);
+ else{
+ if(s->chroma_format < 2)
+ avctx->pix_fmt = PIX_FMT_YUV420P; //avctx->get_format(avctx,pixfmt_yuv_420);
+ else if(s->chroma_format == 2)
+ avctx->pix_fmt = PIX_FMT_YUV422P; //avctx->get_format(avctx,pixfmt_yuv_422);
+ else if(s->chroma_format > 2)
+ avctx->pix_fmt = PIX_FMT_YUV444P; //avctx->get_format(avctx,pixfmt_yuv_444);
+ }
+}
+
/* Call this function when we know all parameters.
* It may be called in different places for MPEG-1 and MPEG-2. */
static int mpeg_decode_postinit(AVCodecContext *avctx){
@@ -1288,19 +1311,8 @@
}
}//MPEG-2
- if(avctx->xvmc_acceleration){
- avctx->pix_fmt = avctx->get_format(avctx,pixfmt_xvmc_mpg2_420);
- }else{
- if(s->chroma_format < 2){
- avctx->pix_fmt = PIX_FMT_YUV420P;
- }else
- if(s->chroma_format == 2){
- avctx->pix_fmt = PIX_FMT_YUV422P;
- }else
- if(s->chroma_format > 2){
- avctx->pix_fmt = PIX_FMT_YUV444P;
- }
- }
+ mpeg_set_pixelformat(avctx);
+
//until then pix_fmt may be changed right after codec init
if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT )
if( avctx->idct_algo == FF_IDCT_AUTO )
@@ -1646,6 +1658,9 @@
XVMC_field_start(s,avctx);
#endif
+ if (s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
+ ff_VDPAU_mpeg_field_start(s);
+
return 0;
}
@@ -1922,6 +1937,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);
@@ -2069,11 +2085,7 @@
avctx->has_b_frames= 0; //true?
s->low_delay= 1;
- if(avctx->xvmc_acceleration){
- avctx->pix_fmt = avctx->get_format(avctx,pixfmt_xvmc_mpg2_420);
- }else{
- avctx->pix_fmt = PIX_FMT_YUV420P;
- }
+ mpeg_set_pixelformat(avctx);
if( avctx->pix_fmt == PIX_FMT_XVMC_MPEG2_IDCT )
if( avctx->idct_algo == FF_IDCT_AUTO )
@@ -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 16437)
+++ 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/vdpau_render.h
===================================================================
--- libavcodec/vdpau_render.h (revision 16437)
+++ libavcodec/vdpau_render.h (working copy)
@@ -70,6 +70,7 @@
/** picture parameter information for all supported codecs */
union VdpPictureInfo {
+ VdpPictureInfoMPEG1Or2 mpeg;
VdpPictureInfoH264 h264;
} info;
Index: libavcodec/avcodec.h
===================================================================
--- libavcodec/avcodec.h (revision 16437)
+++ 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 16437)
+++ 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",
},
Index: libavutil/avutil.h
===================================================================
--- libavutil/avutil.h (revision 16437)
+++ 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_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
+ 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
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