summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNVIDIA Corporation <>2009-01-20 09:28:36 +0000
committerCarl Eugen Hoyos <cehoyos@rainbow.studorg.tuwien.ac.at>2009-01-20 09:28:36 +0000
commitc5b42f4a80b6668cb10d87b065f4e95bea6311c0 (patch)
treea9d43915c23959cef8fa7898affc6088df9b3d7c
parent15a4e8b85a89b398be27decca61455f5b839c6c6 (diff)
Add VDPAU hardware accelerated decoding for WMV3 and VC1 which can
be used by video players. Original patch by NVIDIA corporation. Originally committed as revision 16699 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rwxr-xr-xconfigure2
-rw-r--r--libavcodec/Makefile2
-rw-r--r--libavcodec/allcodecs.c2
-rw-r--r--libavcodec/imgconvert.c6
-rw-r--r--libavcodec/vc1.c48
-rw-r--r--libavcodec/vdpau.h1
-rw-r--r--libavcodec/vdpau_internal.h3
-rw-r--r--libavcodec/vdpauvideo.c70
-rw-r--r--libavutil/avutil.h2
9 files changed, 136 insertions, 0 deletions
diff --git a/configure b/configure
index b80bb38436..54ecbfe129 100755
--- a/configure
+++ b/configure
@@ -1016,6 +1016,7 @@ svq3_decoder_suggest="zlib"
tiff_decoder_suggest="zlib"
tiff_encoder_suggest="zlib"
tscc_decoder_select="zlib"
+vc1_vdpau_decoder_deps="vdpau"
vorbis_decoder_select="fft mdct"
vorbis_encoder_select="fft mdct"
wmav1_decoder_select="fft mdct"
@@ -1024,6 +1025,7 @@ wmav2_decoder_select="fft mdct"
wmav2_encoder_select="fft mdct"
wmv1_encoder_select="aandct"
wmv2_encoder_select="aandct"
+wmv3_vdpau_decoder_deps="vdpau"
zlib_decoder_select="zlib"
zlib_encoder_select="zlib"
zmbv_decoder_select="zlib"
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index fa8b71bc73..9c487fb1af 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -218,6 +218,7 @@ OBJS-$(CONFIG_TXD_DECODER) += txd.o s3tc.o
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 vc1.o vc1data.o vc1dsp.o msmpeg4data.o h263dec.o h263.o intrax8.o intrax8dsp.o error_resilience.o mpegvideo.o
OBJS-$(CONFIG_VCR1_DECODER) += vcr1.o
OBJS-$(CONFIG_VCR1_ENCODER) += vcr1.o
OBJS-$(CONFIG_VMDAUDIO_DECODER) += vmdav.o
@@ -241,6 +242,7 @@ OBJS-$(CONFIG_WMV1_ENCODER) += mpegvideo_enc.o motion_est.o ratecontr
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 vc1.o vc1data.o vc1dsp.o msmpeg4data.o h263dec.o h263.o intrax8.o intrax8dsp.o error_resilience.o mpegvideo.o
OBJS-$(CONFIG_WNV1_DECODER) += wnv1.o
OBJS-$(CONFIG_WS_SND1_DECODER) += ws-snd1.o
OBJS-$(CONFIG_XAN_DPCM_DECODER) += dpcm.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 9121a6f7b5..f369c0a20e 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -157,6 +157,7 @@ void avcodec_register_all(void)
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);
@@ -169,6 +170,7 @@ void avcodec_register_all(void)
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);
diff --git a/libavcodec/imgconvert.c b/libavcodec/imgconvert.c
index 7c62b66db6..17c8473c3a 100644
--- a/libavcodec/imgconvert.c
+++ b/libavcodec/imgconvert.c
@@ -276,6 +276,12 @@ static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = {
[PIX_FMT_VDPAU_H264] = {
.name = "vdpau_h264",
},
+ [PIX_FMT_VDPAU_WMV3] = {
+ .name = "vdpau_wmv3",
+ },
+ [PIX_FMT_VDPAU_VC1] = {
+ .name = "vdpau_vc1",
+ },
[PIX_FMT_UYYVYY411] = {
.name = "uyyvyy411",
.nb_channels = 1,
diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c
index dee0adcd98..83022b49c8 100644
--- a/libavcodec/vc1.c
+++ b/libavcodec/vc1.c
@@ -35,6 +35,7 @@
#include "unary.h"
#include "simple_idct.h"
#include "mathops.h"
+#include "vdpau_internal.h"
#undef NDEBUG
#include <assert.h>
@@ -4130,6 +4131,7 @@ static int vc1_decode_frame(AVCodecContext *avctx,
MpegEncContext *s = &v->s;
AVFrame *pict = data;
uint8_t *buf2 = NULL;
+ const uint8_t *buf_vdpau = buf;
/* no supplementary picture */
if (buf_size == 0) {
@@ -4151,6 +4153,13 @@ static int vc1_decode_frame(AVCodecContext *avctx,
s->current_picture_ptr= &s->picture[i];
}
+ if (s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU){
+ if (v->profile < PROFILE_ADVANCED)
+ avctx->pix_fmt = PIX_FMT_VDPAU_WMV3;
+ else
+ avctx->pix_fmt = PIX_FMT_VDPAU_VC1;
+ }
+
//for advanced profile we may need to parse and unescape data
if (avctx->codec_id == CODEC_ID_VC1) {
int buf_size2 = 0;
@@ -4167,6 +4176,8 @@ static int vc1_decode_frame(AVCodecContext *avctx,
if(size <= 0) continue;
switch(AV_RB32(start)){
case VC1_CODE_FRAME:
+ if (s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
+ buf_vdpau = start;
buf_size2 = vc1_unescape_buffer(start + 4, size, buf2);
break;
case VC1_CODE_ENTRYPOINT: /* it should be before frame data */
@@ -4255,6 +4266,10 @@ static int vc1_decode_frame(AVCodecContext *avctx,
s->me.qpel_put= s->dsp.put_qpel_pixels_tab;
s->me.qpel_avg= s->dsp.avg_qpel_pixels_tab;
+ if ((CONFIG_VC1_VDPAU_DECODER || CONFIG_WMV3_VDPAU_DECODER)
+ &&s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_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;
@@ -4263,6 +4278,7 @@ static int vc1_decode_frame(AVCodecContext *avctx,
// if(get_bits_count(&s->gb) > buf_size * 8)
// return -1;
ff_er_frame_end(s);
+ }
MPV_frame_end(s);
@@ -4336,3 +4352,35 @@ AVCodec wmv3_decoder = {
NULL,
.long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9"),
};
+
+#if CONFIG_WMV3_VDPAU_DECODER
+AVCodec wmv3_vdpau_decoder = {
+ "wmv3_vdpau",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_WMV3,
+ 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 CONFIG_VC1_VDPAU_DECODER
+AVCodec vc1_vdpau_decoder = {
+ "vc1_vdpau",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_VC1,
+ 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
diff --git a/libavcodec/vdpau.h b/libavcodec/vdpau.h
index a28ad7fa82..3d74fdd47d 100644
--- a/libavcodec/vdpau.h
+++ b/libavcodec/vdpau.h
@@ -72,6 +72,7 @@ struct vdpau_render_state {
union VdpPictureInfo {
VdpPictureInfoMPEG1Or2 mpeg;
VdpPictureInfoH264 h264;
+ VdpPictureInfoVC1 vc1;
} info;
/** Describe size/location of the compressed video data. */
diff --git a/libavcodec/vdpau_internal.h b/libavcodec/vdpau_internal.h
index e957037a83..ce0e00a38a 100644
--- a/libavcodec/vdpau_internal.h
+++ b/libavcodec/vdpau_internal.h
@@ -36,4 +36,7 @@ void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf,
void ff_vdpau_h264_set_reference_frames(MpegEncContext *s);
void ff_vdpau_h264_picture_complete(MpegEncContext *s);
+void ff_vdpau_vc1_decode_picture(MpegEncContext *s, const uint8_t *buf,
+ int buf_size);
+
#endif /* AVCODEC_VDPAU_INTERNAL_H */
diff --git a/libavcodec/vdpauvideo.c b/libavcodec/vdpauvideo.c
index a7c604d1e2..8eb806a1a0 100644
--- a/libavcodec/vdpauvideo.c
+++ b/libavcodec/vdpauvideo.c
@@ -24,6 +24,7 @@
#include <limits.h>
#include "avcodec.h"
#include "h264.h"
+#include "vc1.h"
#undef NDEBUG
#include <assert.h>
@@ -232,4 +233,73 @@ void ff_vdpau_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf,
render->bitstream_buffers_used = 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 = v->refdist_flag;
+ 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;
+
+ render->info.vc1.deblockEnable = v->postprocflag & 1;
+ render->info.vc1.pquant = v->pq;
+
+ render->info.vc1.forward_reference = VDP_INVALID_HANDLE;
+ render->info.vc1.backward_reference = VDP_INVALID_HANDLE;
+
+ if (v->bi_type)
+ render->info.vc1.picture_type = 4;
+ else
+ render->info.vc1.picture_type = s->pict_type - 1 + s->pict_type / 3;
+
+ 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;
+ }
+
+ ff_vdpau_add_data_chunk(s, buf, buf_size);
+
+ render->info.vc1.slice_count = 1;
+
+ ff_draw_horiz_band(s, 0, s->avctx->height);
+ render->bitstream_buffers_used = 0;
+}
+
/* @}*/
diff --git a/libavutil/avutil.h b/libavutil/avutil.h
index fdbce40fae..b02790b4f2 100644
--- a/libavutil/avutil.h
+++ b/libavutil/avutil.h
@@ -124,6 +124,8 @@ enum PixelFormat {
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_VDPAU_WMV3,///< WMV3 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, ///< VC1 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
};