diff --git a/mythtv/configure b/mythtv/configure index facea94..37c3942 100755 --- a/mythtv/configure +++ b/mythtv/configure @@ -1000,6 +1000,7 @@ HAVE_LIST=" termios_h threads winsock2_h + vdpau yasm " @@ -1121,13 +1122,17 @@ dxa_decoder_deps="zlib" eac3_decoder_deps="gpl" flashsv_decoder_deps="zlib" flashsv_encoder_deps="zlib" +h264_vdpau_decoder_deps="vdpau" mlp_decoder_deps="mlp_parser" mpeg_dvdv_decoder_deps="dvdv" +mpeg_vdpau_decoder_deps="vdpau" mpeg_xvmc_decoder_deps="xvmc" mpeg_xvmc_vld_decoder_deps="xvmc_vld" png_decoder_deps="zlib" png_encoder_deps="zlib" snow_decoder_deps="disabled_in_mythtv" +vc1_vdpau_decoder_deps="vdpau" +wmv3_vdpau_decoder_deps="vdpau" zmbv_decoder_deps="zlib" zmbv_encoder_deps="zlib" @@ -1214,6 +1219,7 @@ opengl_video_deps="opengl xv" opengl_vsync_deps="opengl" qtwebkit_deps="QtWebKit_QWebView" v4l_deps="backend" +vdpau_deps="vdpau_vdpau_h" xrandr_deps="x11" xv_deps="x11" xvmc_deps="xv X11_extensions_XvMClib_h" @@ -1327,6 +1333,7 @@ enable mheg enable opengl enable qtwebkit enable v4l +enable vdpau enable x11 enable xrandr enable xv @@ -3011,6 +3018,7 @@ fi enabled xvmc_pro && enable xvmc_vld +check_header vdpau/vdpau.h # Can only do Mac accel on Mac platform enabled dvdv && test $target_os = darwin || disable dvdv diff --git a/mythtv/libs/libavcodec/allcodecs.c b/mythtv/libs/libavcodec/allcodecs.c index 393646b..45c59f7 100644 --- a/mythtv/libs/libavcodec/allcodecs.c +++ b/mythtv/libs/libavcodec/allcodecs.c @@ -97,6 +97,7 @@ void avcodec_register_all(void) REGISTER_DECODER (H263I, h263i); REGISTER_ENCODER (H263P, h263p); REGISTER_DECODER (H264, h264); + REGISTER_DECODER (H264_VDPAU, h264_vdpau); REGISTER_ENCDEC (HUFFYUV, huffyuv); REGISTER_DECODER (IDCIN, idcin); REGISTER_DECODER (INDEO2, indeo2); @@ -113,6 +114,7 @@ void avcodec_register_all(void) REGISTER_DECODER (MMVIDEO, mmvideo); REGISTER_DECODER (MOTIONPIXELS, motionpixels); REGISTER_DECODER (MPEG_DVDV, mpeg_dvdv); + REGISTER_DECODER (MPEG_VDPAU, mpeg_vdpau); REGISTER_DECODER (MPEG_XVMC, mpeg_xvmc); REGISTER_DECODER (MPEG_XVMC_VLD, mpeg_xvmc_vld); REGISTER_ENCDEC (MPEG1VIDEO, mpeg1video); @@ -163,6 +165,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); @@ -175,6 +178,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/mythtv/libs/libavcodec/avcodec.h b/mythtv/libs/libavcodec/avcodec.h index 673c3fe..c37e544 100644 --- a/mythtv/libs/libavcodec/avcodec.h +++ b/mythtv/libs/libavcodec/avcodec.h @@ -191,6 +191,10 @@ enum CodecID { CODEC_ID_CMV, CODEC_ID_MOTIONPIXELS, CODEC_ID_TGV, + CODEC_ID_MPEGVIDEO_VDPAU, + CODEC_ID_H264_VDPAU, + CODEC_ID_VC1_VDPAU, + CODEC_ID_WMV3_VDPAU, /* various PCM "codecs" */ CODEC_ID_PCM_S16LE= 0x10000, @@ -514,6 +518,8 @@ typedef struct RcOverride{ * This can be used to prevent truncation of the last audio samples. */ #define CODEC_CAP_SMALL_LAST_FRAME 0x0040 +/* Codec can export data for HW decoding (VDPAU). */ +#define CODEC_CAP_HWACCEL_VDPAU 0x0080 //The following defines may change, don't expect compatibility if you use them. #define MB_TYPE_INTRA4x4 0x0001 @@ -1761,6 +1767,13 @@ typedef struct AVCodecContext { int xvmc_acceleration; /** + * VDPAU Acceleration + * - encoding: forbidden + * - decoding: set by decoder + */ + int vdpau_acceleration; + + /** * macroblock decision mode * - encoding: Set by user. * - decoding: unused diff --git a/mythtv/libs/libavcodec/h263dec.c b/mythtv/libs/libavcodec/h263dec.c index de1f146..f5c496c 100644 --- a/mythtv/libs/libavcodec/h263dec.c +++ b/mythtv/libs/libavcodec/h263dec.c @@ -92,6 +92,8 @@ av_cold int ff_h263_decode_init(AVCodecContext *avctx) break; case CODEC_ID_VC1: case CODEC_ID_WMV3: + case CODEC_ID_VC1_VDPAU: + case CODEC_ID_WMV3_VDPAU: s->h263_msmpeg4 = 1; s->h263_pred = 1; s->msmpeg4_version=6; diff --git a/mythtv/libs/libavcodec/h264.c b/mythtv/libs/libavcodec/h264.c index 9777851..d49ca5b 100644 --- a/mythtv/libs/libavcodec/h264.c +++ b/mythtv/libs/libavcodec/h264.c @@ -72,6 +72,10 @@ static VLC run7_vlc; static VLC_TYPE run7_vlc_table[96][2]; static const int run7_vlc_table_size = 96; +extern int VDPAU_h264_set_reference_frames(H264Context *h); +extern int VDPAU_h264_picture_complete(H264Context *h, const uint8_t *buf, int buf_size); +extern void VDPAU_h264_set_reference_frames_count(H264Context *h); + static void svq3_luma_dc_dequant_idct_c(DCTELEM *block, int qp); static void svq3_add_idct_c(uint8_t *dst, DCTELEM *block, int stride, int qp, int dc); static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize); @@ -101,6 +105,16 @@ static const int left_block_options[4][8]={ {0,2,0,2,7,10,7,10} }; +static const enum PixelFormat pixfmt_vdpau_h264_baseline_420[] = { + PIX_FMT_VDPAU_H264_BASELINE, + PIX_FMT_NONE}; +static const enum PixelFormat pixfmt_vdpau_h264_main_420[] = { + PIX_FMT_VDPAU_H264_MAIN, + PIX_FMT_NONE}; +static const enum PixelFormat pixfmt_vdpau_h264_high_420[] = { + PIX_FMT_VDPAU_H264_HIGH, + PIX_FMT_NONE}; + static void fill_caches(H264Context *h, int mb_type, int for_deblock){ MpegEncContext * const s = &h->s; const int mb_xy= h->mb_xy; @@ -2198,10 +2212,8 @@ static av_cold int decode_init(AVCodecContext *avctx){ s->quarter_sample = 1; s->low_delay= 1; - if(avctx->codec_id == CODEC_ID_SVQ3) - avctx->pix_fmt= PIX_FMT_YUVJ420P; - else - avctx->pix_fmt= PIX_FMT_YUV420P; + // Set in decode_postinit() once initial parsing is complete + avctx->pix_fmt = PIX_FMT_NONE; decode_init_vlc(); @@ -2219,10 +2231,43 @@ static av_cold int decode_init(AVCodecContext *avctx){ return 0; } +static int decode_postinit(H264Context *h, SPS *sps){ + AVCodecContext * const avctx= h->s.avctx; + + if (avctx->pix_fmt != PIX_FMT_NONE){ + return 0; + } + + if (avctx->vdpau_acceleration) { + if(h->s.chroma_format >= 2) { + return -2; + } + if (sps->profile_idc == 66) { + avctx->pix_fmt = avctx->get_format(avctx, pixfmt_vdpau_h264_baseline_420); + } else if (sps->profile_idc == 77) { + avctx->pix_fmt = avctx->get_format(avctx, pixfmt_vdpau_h264_main_420); + } else if (sps->profile_idc == 100) { + avctx->pix_fmt = avctx->get_format(avctx, pixfmt_vdpau_h264_high_420); + } else { + return -2; + } + } else if (avctx->codec_id == CODEC_ID_SVQ3) { + avctx->pix_fmt= PIX_FMT_YUVJ420P; + } else { + avctx->pix_fmt= PIX_FMT_YUV420P; + } + + return 0; +} + static int frame_start(H264Context *h){ MpegEncContext * const s = &h->s; int i; +#ifdef HAVE_VDPAU + VDPAU_h264_set_reference_frames_count(h); +#endif + if(MPV_frame_start(s, s->avctx) < 0) return -1; ff_er_frame_start(s); @@ -7102,6 +7147,10 @@ static inline int decode_seq_parameter_set(H264Context *h){ ((const char*[]){"Gray","420","422","444"})[sps->chroma_format_idc] ); } + + if (decode_postinit(h, sps) < 0) + return -1; + return 0; } @@ -7234,7 +7283,9 @@ static void execute_decode_slices(H264Context *h, int context_count){ H264Context *hx; int i; - if(context_count == 1) { + if(avctx->vdpau_acceleration) { + return; + } else if(context_count == 1) { decode_slice(avctx, h); } else { for(i = 1; i < context_count; i++) { @@ -7558,12 +7609,25 @@ static int decode_frame(AVCodecContext *avctx, h->prev_frame_num_offset= h->frame_num_offset; h->prev_frame_num= h->frame_num; + +#ifdef HAVE_VDPAU + if (avctx->vdpau_acceleration) { + VDPAU_h264_set_reference_frames(h); + } +#endif + if(!s->dropable) { h->prev_poc_msb= h->poc_msb; h->prev_poc_lsb= h->poc_lsb; execute_ref_pic_marking(h, h->mmco, h->mmco_index); } +#ifdef HAVE_VDPAU + if (avctx->vdpau_acceleration) { + VDPAU_h264_picture_complete(h, buf, buf_size); + } +#endif + /* * FIXME: Error handling code does not seem to support interlaced * when slices span multiple rows @@ -7576,8 +7640,11 @@ static int decode_frame(AVCodecContext *avctx, * past end by one (callers fault) and resync_mb_y != 0 * causes problems for the first MB line, too. */ - if (!FIELD_PICTURE) - ff_er_frame_end(s); +#ifdef HAVE_VDPAU + if (!avctx->vdpau_acceleration) +#endif + if (!FIELD_PICTURE) + ff_er_frame_end(s); MPV_frame_end(s); @@ -7890,4 +7957,35 @@ AVCodec h264_decoder = { .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"), }; +#ifdef HAVE_VDPAU +static av_cold int h264_vdpau_decode_init(AVCodecContext *avctx){ + if( avctx->thread_count > 1) + return -1; + if( !(avctx->slice_flags & SLICE_FLAG_CODED_ORDER) ) + return -1; + if( !(avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD) ){ + dprintf(avctx, "h264.c: VDPAU decoder does not set SLICE_FLAG_ALLOW_FIELD\n"); + } + decode_init(avctx); + + avctx->vdpau_acceleration = 1; + + return 0; +} + +AVCodec h264_vdpau_decoder = { + "h264_vdpau", + CODEC_TYPE_VIDEO, + CODEC_ID_H264_VDPAU, + sizeof(H264Context), + h264_vdpau_decode_init, + NULL, + decode_end, + decode_frame, + CODEC_CAP_DR1 | CODEC_CAP_DELAY | CODEC_CAP_HWACCEL_VDPAU, + .flush= flush_dpb, + .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (VDPAU acceleration)"), +}; +#endif + #include "svq3.c" diff --git a/mythtv/libs/libavcodec/imgconvert.c b/mythtv/libs/libavcodec/imgconvert.c index 63c59d4..80df7f6 100644 --- a/mythtv/libs/libavcodec/imgconvert.c +++ b/mythtv/libs/libavcodec/imgconvert.c @@ -266,6 +266,33 @@ static const PixFmtInfo pix_fmt_info[PIX_FMT_NB] = { [PIX_FMT_XVMC_MPEG2_IDCT] = { .name = "xvmcidct", }, + [PIX_FMT_VDPAU_MPEG1] = { + .name = "vdpau_mpeg1", + }, + [PIX_FMT_VDPAU_MPEG2_SIMPLE] = { + .name = "vdpau_mpeg2_simple", + }, + [PIX_FMT_VDPAU_MPEG2_MAIN] = { + .name = "vdpau_mpeg2_main", + }, + [PIX_FMT_VDPAU_H264_BASELINE] = { + .name = "vdpau_h264_baseline", + }, + [PIX_FMT_VDPAU_H264_MAIN] = { + .name = "vdpau_h264_main", + }, + [PIX_FMT_VDPAU_H264_HIGH] = { + .name = "vdpau_h264_high", + }, + [PIX_FMT_VDPAU_VC1_SIMPLE] = { + .name = "vdpau_vc1_simple", + }, + [PIX_FMT_VDPAU_VC1_MAIN] = { + .name = "vdpau_vc1_main", + }, + [PIX_FMT_VDPAU_VC1_ADVANCED] = { + .name = "vdpau_vc1_advanced", + }, [PIX_FMT_UYYVYY411] = { .name = "uyyvyy411", .nb_channels = 1, diff --git a/mythtv/libs/libavcodec/libavcodec.pro b/mythtv/libs/libavcodec/libavcodec.pro index 13d1e2b..55222ce 100644 --- a/mythtv/libs/libavcodec/libavcodec.pro +++ b/mythtv/libs/libavcodec/libavcodec.pro @@ -421,6 +421,8 @@ using_dvdv { DEFINES += HAVE_DVDV } +contains( HAVE_VDPAU, yes ) { SOURCES *= vdpauvideo.c } + !contains( CONFIG_SWSCALER, yes ) { SOURCES *= imgresample.c } contains( HAVE_GPROF, yes ) { diff --git a/mythtv/libs/libavcodec/mpeg12.c b/mythtv/libs/libavcodec/mpeg12.c index 19ee213..d55bd21 100644 --- a/mythtv/libs/libavcodec/mpeg12.c +++ b/mythtv/libs/libavcodec/mpeg12.c @@ -84,10 +84,22 @@ extern void DVDV_init_block(MpegEncContext *s); extern void DVDV_decode_mb(MpegEncContext *s); #endif +extern int VDPAU_mpeg_field_start(MpegEncContext *s); +extern void VDPAU_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf, int buf_size, int slice_count); + static const enum PixelFormat pixfmt_xvmc_mpg2_420[] = { PIX_FMT_XVMC_MPEG2_IDCT, PIX_FMT_XVMC_MPEG2_MC, PIX_FMT_NONE}; +static const enum PixelFormat pixfmt_vdpau_mpg1_420[] = { + PIX_FMT_VDPAU_MPEG1, + PIX_FMT_NONE}; +static const enum PixelFormat pixfmt_vdpau_mpg2simple_420[] = { + PIX_FMT_VDPAU_MPEG2_SIMPLE, + PIX_FMT_NONE}; +static const enum PixelFormat pixfmt_vdpau_mpg2main_420[] = { + PIX_FMT_VDPAU_MPEG2_MAIN, + PIX_FMT_NONE}; uint8_t ff_mpeg12_static_rl_table_store[2][2][2*MAX_RUN + MAX_LEVEL + 3]; @@ -1431,7 +1443,23 @@ static int mpeg_decode_postinit(AVCodecContext *avctx){ } }//MPEG-2 - if(avctx->xvmc_acceleration){ + if(avctx->vdpau_acceleration){ + if(s->chroma_format >= 2){ + return -2; + } + if(avctx->sub_id == 1){ + avctx->pix_fmt = avctx->get_format(avctx,pixfmt_vdpau_mpg1_420); + }else{ + if(avctx->profile == 5){ + avctx->pix_fmt = avctx->get_format(avctx,pixfmt_vdpau_mpg2simple_420); + }else + if(avctx->profile == 4){ + avctx->pix_fmt = avctx->get_format(avctx,pixfmt_vdpau_mpg2main_420); + }else{ + return -2; + } + } + }else if(avctx->xvmc_acceleration){ avctx->pix_fmt = avctx->get_format(avctx,pixfmt_xvmc_mpg2_420); }else{ if(s->chroma_format < 2){ @@ -1788,6 +1816,11 @@ static int mpeg_field_start(MpegEncContext *s){ XVMC_VLD_field_start(s, avctx); #endif +#ifdef HAVE_VDPAU + if(s->avctx->vdpau_acceleration) + VDPAU_mpeg_field_start(s); +#endif + return 0; } @@ -2090,7 +2123,10 @@ static int slice_end(AVCodecContext *avctx, AVFrame *pict) s->current_picture_ptr->qscale_type= FF_QSCALE_TYPE_MPEG2; - ff_er_frame_end(s); +#ifdef HAVE_VDPAU + if(!s->avctx->vdpau_acceleration) +#endif + ff_er_frame_end(s); MPV_frame_end(s); @@ -2237,7 +2273,23 @@ static int vcr2_init_sequence(AVCodecContext *avctx) avctx->has_b_frames= 0; //true? s->low_delay= 1; - if(avctx->xvmc_acceleration){ + if(avctx->vdpau_acceleration){ + if(s->chroma_format >= 2){ + return -2; + } + if(avctx->sub_id == 1){ + avctx->pix_fmt = avctx->get_format(avctx,pixfmt_vdpau_mpg1_420); + }else{ + if(avctx->profile == 5){ + avctx->pix_fmt = avctx->get_format(avctx,pixfmt_vdpau_mpg2simple_420); + }else + if(avctx->profile == 4){ + avctx->pix_fmt = avctx->get_format(avctx,pixfmt_vdpau_mpg2main_420); + }else{ + return -2; + } + } + }else if(avctx->xvmc_acceleration){ avctx->pix_fmt = avctx->get_format(avctx,pixfmt_xvmc_mpg2_420); }else{ avctx->pix_fmt = PIX_FMT_YUV420P; @@ -2562,6 +2614,14 @@ static int decode_chunks(AVCodecContext *avctx, for(i=0; islice_count; i++) s2->error_count += s2->thread_context[i]->error_count; } + +#ifdef HAVE_VDPAU + if (avctx->vdpau_acceleration) { + /* Fills mpeg12 picture informations before returing from libavcodec. */ + VDPAU_mpeg_picture_complete(s2, buf, buf_size, s->slice_count); + } +#endif + 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); @@ -2640,6 +2700,11 @@ static int decode_chunks(AVCodecContext *avctx, return -1; } + if (avctx->vdpau_acceleration) { + 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){ @@ -2830,3 +2895,35 @@ AVCodec mpeg_dvdv_decoder = { #endif +#ifdef HAVE_VDPAU +static av_cold int mpeg_vdpau_decode_init(AVCodecContext *avctx){ + if( avctx->thread_count > 1) + return -1; + if( !(avctx->slice_flags & SLICE_FLAG_CODED_ORDER) ) + return -1; + if( !(avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD) ){ + dprintf(avctx, "mpeg12.c: VDPAU decoder does not set SLICE_FLAG_ALLOW_FIELD\n"); + } + mpeg_decode_init(avctx); + + // Set in mpeg_decode_postinit() once initial parsing is complete + avctx->pix_fmt = PIX_FMT_NONE; + avctx->vdpau_acceleration = 1; + + return 0; +} + +AVCodec mpeg_vdpau_decoder = { + "mpegvideo_vdpau", + CODEC_TYPE_VIDEO, + CODEC_ID_MPEGVIDEO_VDPAU, + sizeof(Mpeg1Context), + mpeg_vdpau_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 diff --git a/mythtv/libs/libavcodec/mpegvideo.c b/mythtv/libs/libavcodec/mpegvideo.c index 97cc79b..98d2ebb 100644 --- a/mythtv/libs/libavcodec/mpegvideo.c +++ b/mythtv/libs/libavcodec/mpegvideo.c @@ -58,6 +58,7 @@ extern int XVMC_field_start(MpegEncContext*s, AVCodecContext *avctx); extern void XVMC_field_end(MpegEncContext *s); extern void XVMC_decode_mb(MpegEncContext *s); +extern int VDPAU_mpeg_field_start(MpegEncContext *s); /* enable all paranoid tests for rounding, overflows, etc... */ //#define PARANOID @@ -969,6 +970,10 @@ void MPV_frame_end(MpegEncContext *s) XVMC_field_end(s); }else #endif +#ifdef HAVE_VDPAU + if(s->avctx->vdpau_acceleration){ + }else +#endif if(s->unrestricted_mv && s->current_picture.reference && !s->intra_only && !(s->flags&CODEC_FLAG_EMU_EDGE)) { s->dsp.draw_edges(s->current_picture.data[0], s->linesize , s->h_edge_pos , s->v_edge_pos , EDGE_WIDTH ); s->dsp.draw_edges(s->current_picture.data[1], s->uvlinesize, s->h_edge_pos>>1, s->v_edge_pos>>1, EDGE_WIDTH/2); diff --git a/mythtv/libs/libavcodec/utils.c b/mythtv/libs/libavcodec/utils.c index 475414d..967afc7 100644 --- a/mythtv/libs/libavcodec/utils.c +++ b/mythtv/libs/libavcodec/utils.c @@ -647,6 +647,7 @@ static const AVOption options[]={ {"context", "context model", OFFSET(context_model), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E}, {"slice_flags", NULL, OFFSET(slice_flags), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX}, {"xvmc_acceleration", NULL, OFFSET(xvmc_acceleration), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX}, +{"vdpau_acceleration", NULL, OFFSET(vdpau_acceleration), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX}, {"mbd", "macroblock decision algorithm (high quality mode)", OFFSET(mb_decision), FF_OPT_TYPE_INT, DEFAULT, INT_MIN, INT_MAX, V|E, "mbd"}, {"simple", "use mbcmp (default)", 0, FF_OPT_TYPE_CONST, FF_MB_DECISION_SIMPLE, INT_MIN, INT_MAX, V|E, "mbd"}, {"bits", "use fewest bits", 0, FF_OPT_TYPE_CONST, FF_MB_DECISION_BITS, INT_MIN, INT_MAX, V|E, "mbd"}, diff --git a/mythtv/libs/libavcodec/vc1.c b/mythtv/libs/libavcodec/vc1.c index 9dd6ba8..276ed63 100644 --- a/mythtv/libs/libavcodec/vc1.c +++ b/mythtv/libs/libavcodec/vc1.c @@ -41,8 +41,22 @@ #define MB_INTRA_VLC_BITS 9 #define DC_VLC_BITS 9 #define AC_VLC_BITS 9 + +extern int VDPAU_vc1_decode_picture(MpegEncContext *s, AVCodecContext *avctx, VC1Context *v, const uint8_t *buf, int buf_size); + static const uint16_t table_mb_intra[64][2]; +#ifdef HAVE_VDPAU +static const enum PixelFormat pixfmt_vdpau_vc1_simple_420[] = { + PIX_FMT_VDPAU_VC1_SIMPLE, + PIX_FMT_NONE}; +static const enum PixelFormat pixfmt_vdpau_vc1_main_420[] = { + PIX_FMT_VDPAU_VC1_MAIN, + PIX_FMT_NONE}; +static const enum PixelFormat pixfmt_vdpau_vc1_advanced_420[] = { + PIX_FMT_VDPAU_VC1_ADVANCED, + PIX_FMT_NONE}; +#endif /** * Init VC-1 specific tables and VC1Context members @@ -828,6 +842,29 @@ static void vc1_mc_4mv_chroma(VC1Context *v) } } +#ifdef HAVE_VDPAU +static int decode_postinit(VC1Context *v, AVCodecContext *avctx) +{ + if (avctx->pix_fmt != PIX_FMT_NONE){ + return 0; + } + + if (avctx->vdpau_acceleration) { // VC1 + if (v->profile == 0) { + avctx->pix_fmt = avctx->get_format(avctx, pixfmt_vdpau_vc1_simple_420); + } else if (v->profile == 1) { + avctx->pix_fmt = avctx->get_format(avctx, pixfmt_vdpau_vc1_main_420); + } else if (v->profile == 3) { + avctx->pix_fmt = avctx->get_format(avctx, pixfmt_vdpau_vc1_advanced_420); + } else { + return -2; + } + } + + return 0; +} +#endif + static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb); /** @@ -1005,8 +1042,24 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb) if(get_bits1(gb)) { //Display Info - decoding is not affected by it int w, h, ar = 0; av_log(v->s.avctx, AV_LOG_DEBUG, "Display extended info:\n"); - v->s.avctx->width = v->s.width = w = get_bits(gb, 14) + 1; - v->s.avctx->height = v->s.height = h = get_bits(gb, 14) + 1; + // FIXME: The w/h parsed here are the *display* width/height, not the + // coded width/height. Ideally, we should make the commented + // assignments below, but that causes problems: + // * The SW decoder in this file experiences errors, because it + // assumes these assigned values are the coded size: + // [vc1 @ 0x86f2130]concealing 150 DC, 150 AC, 150 MV errors + // * VDPAU also assumes these are the coded size, since this is the + // only size passed to vo_vdpau.c:config(). This causes errors + // during the decode process. + // However, simply removing these assignments is not the complete fix, + // because without them, the stream is displayed at its coded size, + // not this requested display size. Ideally, setting: + // sample_aspect_ratio = (AVRational){w, h} + // in the case when ar is not present/set would persuade other modules + // to scale to this requested size. However, sample_aspect_ratio + // appears to be completely ignored elsewhere. + /*v->s.avctx->width = v->s.width =*/ w = get_bits(gb, 14) + 1; + /*v->s.avctx->height = v->s.height =*/ h = get_bits(gb, 14) + 1; av_log(v->s.avctx, AV_LOG_DEBUG, "Display dimensions: %ix%i\n", w, h); if(get_bits1(gb)) ar = get_bits(gb, 4); @@ -1057,13 +1110,13 @@ static int decode_sequence_header_adv(VC1Context *v, GetBitContext *gb) static int decode_entry_point(AVCodecContext *avctx, GetBitContext *gb) { VC1Context *v = avctx->priv_data; - int i, blink, clentry, refdist; + int i, blink, clentry; av_log(avctx, AV_LOG_DEBUG, "Entry point: %08X\n", show_bits_long(gb, 32)); blink = get_bits1(gb); // broken link clentry = get_bits1(gb); // closed entry v->panscanflag = get_bits1(gb); - refdist = get_bits1(gb); // refdist flag + v->refdist_flag = get_bits1(gb); v->s.loop_filter = get_bits1(gb); v->fastuvmc = get_bits1(gb); v->extended_mv = get_bits1(gb); @@ -1084,20 +1137,22 @@ static int decode_entry_point(AVCodecContext *avctx, GetBitContext *gb) } if(v->extended_mv) v->extended_dmv = get_bits1(gb); - if(get_bits1(gb)) { + v->range_mapy_flag = get_bits1(gb); + if(v->range_mapy_flag) { av_log(avctx, AV_LOG_ERROR, "Luma scaling is not supported, expect wrong picture\n"); - skip_bits(gb, 3); // Y range, ignored for now + v->range_mapy = get_bits(gb, 3); } - if(get_bits1(gb)) { + v->range_mapuv_flag = get_bits1(gb); + if(v->range_mapuv_flag) { av_log(avctx, AV_LOG_ERROR, "Chroma scaling is not supported, expect wrong picture\n"); - skip_bits(gb, 3); // UV range, ignored for now + v->range_mapuv = get_bits(gb, 3); } av_log(avctx, AV_LOG_DEBUG, "Entry point info:\n" "BrokenLink=%i, ClosedEntry=%i, PanscanFlag=%i\n" "RefDist=%i, Postproc=%i, FastUVMC=%i, ExtMV=%i\n" "DQuant=%i, VSTransform=%i, Overlap=%i, Qmode=%i\n", - blink, clentry, v->panscanflag, refdist, v->s.loop_filter, + blink, clentry, v->panscanflag, v->refdist_flag, v->s.loop_filter, v->fastuvmc, v->extended_mv, v->dquant, v->vstransform, v->overlap, v->quantizer_mode); return 0; @@ -1395,6 +1450,9 @@ static int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) if(v->s.pict_type == FF_I_TYPE || v->s.pict_type == FF_P_TYPE) v->use_ic = 0; + if(v->postprocflag) + v->postproc = get_bits(gb, 2); + switch(v->s.pict_type) { case FF_I_TYPE: case FF_BI_TYPE: @@ -1414,8 +1472,6 @@ static int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) } break; case FF_P_TYPE: - if(v->postprocflag) - v->postproc = get_bits1(gb); if (v->extended_mv) v->mvrange = get_unary(gb, 0, 3); else v->mvrange = 0; v->k_x = v->mvrange + 9 + (v->mvrange >> 1); //k_x can be 9 10 12 13 @@ -1505,8 +1561,6 @@ static int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) } break; case FF_B_TYPE: - if(v->postprocflag) - v->postproc = get_bits1(gb); if (v->extended_mv) v->mvrange = get_unary(gb, 0, 3); else v->mvrange = 0; v->k_x = v->mvrange + 9 + (v->mvrange >> 1); //k_x can be 9 10 12 13 @@ -3994,7 +4048,7 @@ static av_cold int vc1_decode_init(AVCodecContext *avctx) avctx->coded_width = avctx->width; avctx->coded_height = avctx->height; - if (avctx->codec_id == CODEC_ID_WMV3) + if ((avctx->codec_id == CODEC_ID_WMV3) || (avctx->codec_id == CODEC_ID_WMV3_VDPAU)) { int count = 0; @@ -4109,6 +4163,9 @@ static int vc1_decode_frame(AVCodecContext *avctx, MpegEncContext *s = &v->s; AVFrame *pict = data; uint8_t *buf2 = NULL; +#ifdef HAVE_VDPAU + const uint8_t *buf_vdpau = buf; +#endif /* no supplementary picture */ if (buf_size == 0) { @@ -4130,8 +4187,14 @@ static int vc1_decode_frame(AVCodecContext *avctx, s->current_picture_ptr= &s->picture[i]; } +#ifdef HAVE_VDPAU + // pxt_fmt calculation for VDPAU. + if (decode_postinit(v, avctx) < 0) + return -1; +#endif + //for advanced profile we may need to parse and unescape data - if (avctx->codec_id == CODEC_ID_VC1) { + if ((avctx->codec_id == CODEC_ID_VC1) || (avctx->codec_id == CODEC_ID_VC1_VDPAU)) { int buf_size2 = 0; buf2 = av_mallocz(buf_size + FF_INPUT_BUFFER_PADDING_SIZE); @@ -4146,6 +4209,9 @@ static int vc1_decode_frame(AVCodecContext *avctx, if(size <= 0) continue; switch(AV_RB32(start)){ case VC1_CODE_FRAME: +#ifdef HAVE_VDPAU + buf_vdpau = start; +#endif buf_size2 = vc1_unescape_buffer(start + 4, size, buf2); break; case VC1_CODE_ENTRYPOINT: /* it should be before frame data */ @@ -4231,17 +4297,36 @@ static int vc1_decode_frame(AVCodecContext *avctx, return -1; } +#ifdef HAVE_VDPAU + // MPV_frame_start() calls to get_buffer/videoSurfaces. Now we call + // VDPAU_vc1_field_start where picture-parameters are filled. + // VDPAU_vc1_picture_complete calls to vdpau_decoder_render. + + if (avctx->vdpau_acceleration) { + if (VDPAU_vc1_decode_picture(s, avctx, v, buf_vdpau, (buf + buf_size) - buf_vdpau) < 0) { + av_free(buf2); + return -1; + } + } +#endif + s->me.qpel_put= s->dsp.put_qpel_pixels_tab; s->me.qpel_avg= s->dsp.avg_qpel_pixels_tab; - ff_er_frame_start(s); +#ifdef HAVE_VDPAU + if (!avctx->vdpau_acceleration) { +#endif + ff_er_frame_start(s); - v->bits = buf_size * 8; - vc1_decode_blocks(v); + v->bits = buf_size * 8; + vc1_decode_blocks(v); //av_log(s->avctx, AV_LOG_INFO, "Consumed %i/%i bits\n", get_bits_count(&s->gb), buf_size*8); // if(get_bits_count(&s->gb) > buf_size * 8) // return -1; - ff_er_frame_end(s); + ff_er_frame_end(s); +#ifdef HAVE_VDPAU + } +#endif MPV_frame_end(s); @@ -4315,3 +4400,48 @@ AVCodec wmv3_decoder = { NULL, .long_name = NULL_IF_CONFIG_SMALL("Windows Media Video 9"), }; + +#ifdef HAVE_VDPAU +static av_cold int vc1_vdpau_decode_init(AVCodecContext *avctx){ + if( avctx->thread_count > 1) + return -1; + if( !(avctx->slice_flags & SLICE_FLAG_CODED_ORDER) ) + return -1; + if( !(avctx->slice_flags & SLICE_FLAG_ALLOW_FIELD) ){ + dprintf(avctx, "vc1.c: VDPAU decoder does not set SLICE_FLAG_ALLOW_FIELD\n"); + } + avctx->vdpau_acceleration = 1; + vc1_decode_init(avctx); + avctx->pix_fmt = PIX_FMT_NONE; + + return 0; +} + +AVCodec wmv3_vdpau_decoder = { + "wmv3_vdpau", + CODEC_TYPE_VIDEO, + CODEC_ID_WMV3_VDPAU, + sizeof(VC1Context), + vc1_vdpau_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"), +}; + +AVCodec vc1_vdpau_decoder = { + "vc1_vdpau", + CODEC_TYPE_VIDEO, + CODEC_ID_VC1_VDPAU, + sizeof(VC1Context), + vc1_vdpau_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/mythtv/libs/libavcodec/vc1.h b/mythtv/libs/libavcodec/vc1.h index 4cd7bb1..e99d1a7 100644 --- a/mythtv/libs/libavcodec/vc1.h +++ b/mythtv/libs/libavcodec/vc1.h @@ -180,6 +180,7 @@ typedef struct VC1Context{ int interlace; ///< Progressive/interlaced (RPTFTM syntax element) int tfcntrflag; ///< TFCNTR present int panscanflag; ///< NUMPANSCANWIN, TOPLEFT{X,Y}, BOTRIGHT{X,Y} present + int refdist_flag; ///< int extended_dmv; ///< Additional extended dmv range at P/B frame-level int color_prim; ///< 8bits, chroma coordinates of the color primaries int transfer_char; ///< 8bits, Opto-electronic transfer characteristics diff --git a/mythtv/libs/libavcodec/vdpau_render.h b/mythtv/libs/libavcodec/vdpau_render.h new file mode 100644 index 0000000..d6296cb --- /dev/null +++ b/mythtv/libs/libavcodec/vdpau_render.h @@ -0,0 +1,30 @@ +#ifndef FFMPEG_VDPAU_RENDER_H +#define FFMPEG_VDPAU_RENDER_H + +#include "vdpau/vdpau.h" +#include "vdpau/vdpau_x11.h" + +//the surface is used for render. +#define MP_VDPAU_STATE_USED_FOR_RENDER 1 +//the surface is needed for reference/prediction, codec manipulates this. +#define MP_VDPAU_STATE_USED_FOR_REFERENCE 2 + +#define MP_VDPAU_RENDER_MAGIC 0x1DC8E14B + +typedef struct { + int magic; + + VdpVideoSurface surface; //used as rendered surface, never changed. + + int state; // Holds MP_VDPAU_STATE_* values + + union _VdpPictureInfo { + VdpPictureInfoMPEG1Or2 mpeg; + VdpPictureInfoH264 h264; + VdpPictureInfoVC1 vc1; + } info; + + VdpBitstreamBuffer bitstreamBuffer; +} vdpau_render_state_t; + +#endif /* FFMPEG_VDPAU_RENDER_H */ diff --git a/mythtv/libs/libavcodec/vdpauvideo.c b/mythtv/libs/libavcodec/vdpauvideo.c new file mode 100644 index 0000000..6009068 --- /dev/null +++ b/mythtv/libs/libavcodec/vdpauvideo.c @@ -0,0 +1,346 @@ +#include + +//avcodec include +#include "avcodec.h" +#include "dsputil.h" +#include "mpegvideo.h" +#include "h264.h" +#include "vc1.h" + +#undef NDEBUG +#include + +#include "vdpau_render.h" + +#define ARSIZE(_x_) (sizeof(_x_) / sizeof((_x_)[0])) + +uint32_t num_reference_surfaces; + +int VDPAU_mpeg_field_start(MpegEncContext *s) +{ + vdpau_render_state_t * render,* last, * next; + int i; + + render = (vdpau_render_state_t*)s->current_picture.data[2]; + assert(render != NULL); + if (render == NULL) { + return -1; //make sure that this is render packet + } + + /* 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 0; // no prediction from other frames + case FF_B_TYPE: + next = (vdpau_render_state_t*)s->next_picture.data[2]; + assert(next!=NULL); + if (next == NULL) { + return -1; + } + render->info.mpeg.backward_reference = next->surface; + // no return here, going to set forward prediction + case FF_P_TYPE: + last = (vdpau_render_state_t*)s->last_picture.data[2]; + if (last == NULL) { // FIXME: Does this test make sense? + last = render; // predict second field from the first + } + render->info.mpeg.forward_reference = last->surface; + return 0; + } + + return -1; +} + +int VDPAU_mpeg_picture_complete(MpegEncContext *s, const uint8_t *buf, int buf_size, int slice_count) +{ + vdpau_render_state_t * render; + + render = (vdpau_render_state_t*)s->current_picture_ptr->data[2]; + assert(render != NULL); + if (render == NULL) { + return -1; // make sure that this is render packet + } + + render->bitstreamBuffer.struct_version = VDP_BITSTREAM_BUFFER_VERSION; + render->bitstreamBuffer.bitstream_bytes = buf_size; + render->bitstreamBuffer.bitstream = buf; + render->info.mpeg.slice_count = slice_count; + + if (slice_count > 0) { + ff_draw_horiz_band(s, 0, s->avctx->height); + } + + return 0; +} + +int VDPAU_h264_set_reference_frames(H264Context *h) +{ + MpegEncContext * s = &h->s; + vdpau_render_state_t * render, * render_ref; + VdpReferenceFrameH264 * rf, * rf2; + Picture * pic; + int i, list; + + render = (vdpau_render_state_t*)s->current_picture_ptr->data[2]; + assert(render != NULL); + if (render == NULL) + return -1; //make sure that this is render packet + + rf = &render->info.h264.referenceFrames[0]; +#define H264_RF_COUNT ARSIZE(render->info.h264.referenceFrames) + + for (list = 0; list < 2; ++list) { + Picture **lp = list ? h->long_ref : h->short_ref; + int ls = list ? h->long_ref_count : h->short_ref_count; + + for (i = 0; i < ls; ++i) { + pic = lp[i]; + if (!pic || !pic->reference) { + continue; + } + + render_ref = (vdpau_render_state_t*)pic->data[2]; + assert(render_ref != NULL); + if (render_ref == NULL) + return -1; //make sure that this is render packet + + rf2 = &render->info.h264.referenceFrames[0]; + while (rf2 != rf) { + if ( + (rf2->surface == render_ref->surface) + && (rf2->is_long_term == pic->long_ref) + && (rf2->frame_idx == pic->frame_num) + ) { + break; + } + ++rf2; + } + if (rf2 != rf) { + rf2->top_is_reference |= (pic->reference & PICT_TOP_FIELD) ? VDP_TRUE : VDP_FALSE; + rf2->bottom_is_reference |= (pic->reference & PICT_BOTTOM_FIELD) ? VDP_TRUE : VDP_FALSE; + continue; + } + + if (rf >= &render->info.h264.referenceFrames[H264_RF_COUNT]) { + continue; + } + + rf->surface = render_ref->surface; + rf->is_long_term = pic->long_ref; + rf->top_is_reference = (pic->reference & PICT_TOP_FIELD) ? VDP_TRUE : VDP_FALSE; + rf->bottom_is_reference = (pic->reference & PICT_BOTTOM_FIELD) ? VDP_TRUE : VDP_FALSE; + rf->field_order_cnt[0] = pic->field_poc[0]; + rf->field_order_cnt[1] = pic->field_poc[1]; + rf->frame_idx = pic->frame_num; + + ++rf; + } + } + + for (; rf < &render->info.h264.referenceFrames[H264_RF_COUNT]; ++rf) { + rf->surface = VDP_INVALID_HANDLE; + rf->is_long_term = 0; + rf->top_is_reference = 0; + rf->bottom_is_reference = 0; + rf->field_order_cnt[0] = 0; + rf->field_order_cnt[1] = 0; + rf->frame_idx = 0; + } + + return 0; +} + +int VDPAU_h264_picture_complete(H264Context *h, const uint8_t *buf, int buf_size) +{ + MpegEncContext * s = &h->s; + vdpau_render_state_t * render; + int i; + + render = (vdpau_render_state_t*)s->current_picture_ptr->data[2]; + assert(render != NULL); + if (render == NULL) + return -1; //make sure that this is render packet + + render->info.h264.slice_count = h->slice_num; + + if (render->info.h264.slice_count < 1) + return 0; + + for (int i = 0; i < 2; ++i) { + int foc = s->current_picture_ptr->field_poc[i]; + if (foc == INT_MAX) { + foc = 0; + } + render->info.h264.field_order_cnt[i] = foc; + } + + render->info.h264.is_reference = s->current_picture_ptr->reference ? VDP_TRUE : VDP_FALSE; + render->info.h264.frame_num = h->frame_num; + render->info.h264.field_pic_flag = (s->picture_structure != PICT_FRAME) ? 1 : 0; + render->info.h264.bottom_field_flag = (s->picture_structure == PICT_BOTTOM_FIELD) ? 1 : 0; + render->info.h264.num_ref_frames = h->sps.ref_frame_count; + render->info.h264.mb_adaptive_frame_field_flag = h->sps.mb_aff; + render->info.h264.constrained_intra_pred_flag = h->pps.constrained_intra_pred; + render->info.h264.weighted_pred_flag = h->pps.weighted_pred; + render->info.h264.weighted_bipred_idc = h->pps.weighted_bipred_idc; + render->info.h264.frame_mbs_only_flag = h->sps.frame_mbs_only_flag; + render->info.h264.transform_8x8_mode_flag = h->pps.transform_8x8_mode; + render->info.h264.chroma_qp_index_offset = h->pps.chroma_qp_index_offset[0]; + render->info.h264.second_chroma_qp_index_offset = h->pps.chroma_qp_index_offset[1]; + render->info.h264.pic_init_qp_minus26 = h->pps.init_qp - 26; + render->info.h264.num_ref_idx_l0_active_minus1 = h->pps.ref_count[0] - 1; + render->info.h264.num_ref_idx_l1_active_minus1 = h->pps.ref_count[1] - 1; + render->info.h264.log2_max_frame_num_minus4 = h->sps.log2_max_frame_num - 4; + render->info.h264.pic_order_cnt_type = h->sps.poc_type; + render->info.h264.log2_max_pic_order_cnt_lsb_minus4 = h->sps.log2_max_poc_lsb - 4; + render->info.h264.delta_pic_order_always_zero_flag = h->sps.delta_pic_order_always_zero_flag; + render->info.h264.direct_8x8_inference_flag = h->sps.direct_8x8_inference_flag; + render->info.h264.entropy_coding_mode_flag = h->pps.cabac; + render->info.h264.pic_order_present_flag = h->pps.pic_order_present; + render->info.h264.deblocking_filter_control_present_flag = h->pps.deblocking_filter_parameters_present; + render->info.h264.redundant_pic_cnt_present_flag = h->pps.redundant_pic_cnt_present; + memcpy(render->info.h264.scaling_lists_4x4, h->pps.scaling_matrix4, sizeof(render->info.h264.scaling_lists_4x4)); + memcpy(render->info.h264.scaling_lists_8x8, h->pps.scaling_matrix8, sizeof(render->info.h264.scaling_lists_8x8)); + + render->bitstreamBuffer.struct_version = VDP_BITSTREAM_BUFFER_VERSION; + render->bitstreamBuffer.bitstream_bytes = buf_size; + render->bitstreamBuffer.bitstream = buf; + + ff_draw_horiz_band(s, 0, s->avctx->height); + + return 0; +} + +void VDPAU_h264_set_reference_frames_count(H264Context *h) +{ + num_reference_surfaces = h->sps.ref_frame_count; +} + +#undef printf + +int VDPAU_vc1_decode_picture(MpegEncContext *s, AVCodecContext *avctx, VC1Context *v, const uint8_t *buf, int buf_size) +{ + // VC1Context *v = avctx->priv_data; + vdpau_render_state_t * render,* last, * next; + + render = (vdpau_render_state_t*)s->current_picture.data[2]; + assert(render != NULL); + if (render == NULL) { + return -1; //make sure that this is render packet + } + memset(&(render->info), 0 , sizeof(VdpPictureInfoVC1)); + memset(&(render->bitstreamBuffer), 0, sizeof(VdpBitstreamBuffer)); + + /* 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; + /* Presently, making these as 0 */ + render->info.vc1.deblockEnable = 0; + render->info.vc1.pquant = 0; + + render->info.vc1.forward_reference = VDP_INVALID_HANDLE; + render->info.vc1.backward_reference = VDP_INVALID_HANDLE; + + switch(s->pict_type){ + case FF_I_TYPE: + render->info.vc1.picture_type = 0; + break; + case FF_B_TYPE: + if (v->bi_type) { + render->info.vc1.picture_type = 4; + } + else { + render->info.vc1.picture_type = 3; + } + break; + case FF_P_TYPE: + render->info.vc1.picture_type = 1; + break; + case FF_BI_TYPE: + render->info.vc1.picture_type = 4; + break; + default: + return -1; + } + + switch(s->pict_type){ + case FF_I_TYPE: + case FF_BI_TYPE: + break; + case FF_B_TYPE: + next = (vdpau_render_state_t*)s->next_picture.data[2]; + assert(next!=NULL); + if (next == NULL) { + return -1; + } + render->info.vc1.backward_reference = next->surface; + // no break here, going to set forward prediction + case FF_P_TYPE: + last = (vdpau_render_state_t*)s->last_picture.data[2]; + if (last == NULL) { // FIXME: Does this test make sense? + last = render; // predict second field from the first + } + render->info.vc1.forward_reference = last->surface; + break; + default: + return -1; + } + + render->bitstreamBuffer.struct_version = VDP_BITSTREAM_BUFFER_VERSION; + render->bitstreamBuffer.bitstream_bytes = buf_size; + render->bitstreamBuffer.bitstream = buf; + // FIXME: I am not sure about how MPlayer calculates slice number. + render->info.vc1.slice_count = 1; + + ff_draw_horiz_band(s, 0, s->avctx->height); + + return 0; +} + diff --git a/mythtv/libs/libavutil/avutil.h b/mythtv/libs/libavutil/avutil.h index 03c5520..65ea42b 100644 --- a/mythtv/libs/libavutil/avutil.h +++ b/mythtv/libs/libavutil/avutil.h @@ -121,6 +121,15 @@ enum PixelFormat { PIX_FMT_YUV440P, ///< Planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples) 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_MPEG1, ///< VDPAU acceleration via common packet passing(vdpau_remder.h) + PIX_FMT_VDPAU_MPEG2_SIMPLE, ///< VDPAU acceleration via common packet passing(vdpau_remder.h) + PIX_FMT_VDPAU_MPEG2_MAIN, ///< VDPAU acceleration via common packet passing(vdpau_remder.h) + PIX_FMT_VDPAU_H264_BASELINE,///< VDPAU acceleration via common packet passing(vdpau_remder.h) + PIX_FMT_VDPAU_H264_MAIN, ///< VDPAU acceleration via common packet passing(vdpau_remder.h) + PIX_FMT_VDPAU_H264_HIGH, ///< VDPAU acceleration via common packet passing(vdpau_remder.h) + PIX_FMT_VDPAU_VC1_SIMPLE, ///< VDPAU acceleration via common packet passing(vdpau_remder.h) + PIX_FMT_VDPAU_VC1_MAIN, ///< VDPAU acceleration via common packet passing(vdpau_remder.h) + PIX_FMT_VDPAU_VC1_ADVANCED, ///< VDPAU acceleration via common packet passing(vdpau_remder.h) 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 };