Skip to content

Commit

Permalink
Windows: Add DXVA2 hardware decoding support.
Browse files Browse the repository at this point in the history
- You will need to download the dxva2api.h from the VLC website, install it in an appropriate include path and re-run configure with --enable-dxva2
- Enable Windows Hardware Acceleration decoder support in the display profile of your choice.
- This is alpha quality at best and this version has only been tested on Vista with an NVidia 9400M chipset (MacBook in bootcamp).
- There is no deinterlacing or other video processing support at this time.
- It is largely stable with MPEG2, H.264 and VC1 support all working though there will be fixes required for certain chipsets and codecs (just as for VDPAU).
- Most stability issues appear to be unrelated to DXVA2 and are general issues with this windows build.

- There is significant picture breakup when starting playback and occasional glitches at other times.

If you are going to test (especially if using the new windows build script), please compile a debug build so we can iron out all of the outstanding issues as quickly as possible.
  • Loading branch information
mark-kendall committed Mar 4, 2011
1 parent e26b681 commit 69fefe5
Show file tree
Hide file tree
Showing 5 changed files with 286 additions and 34 deletions.
64 changes: 64 additions & 0 deletions mythtv/libs/libmythtv/avformatdecoder.cpp
Expand Up @@ -48,6 +48,10 @@ extern "C" {
}
#endif // USING_VDPAU

#ifdef USING_DXVA2
#include "videoout_d3d.h"
#endif

extern "C" {
#include "libavutil/avutil.h"
#include "libavcodec/ac3_parser.h"
Expand Down Expand Up @@ -103,6 +107,7 @@ int get_avf_buffer_vdpau(struct AVCodecContext *c, AVFrame *pic);
void release_avf_buffer_vdpau(struct AVCodecContext *c, AVFrame *pic);
void render_slice_vdpau(struct AVCodecContext *s, const AVFrame *src,
int offset[4], int y, int type, int height);
int get_avf_buffer_dxva2(struct AVCodecContext *c, AVFrame *pic);

static AVCodec *find_vdpau_decoder(AVCodec *c, enum CodecID id)
{
Expand Down Expand Up @@ -208,6 +213,10 @@ void AvFormatDecoder::GetDecoders(render_opts &opts)
opts.decoders->append("vdpau");
(*opts.equiv_decoders)["vdpau"].append("dummy");
#endif
#ifdef USING_DXVA2
opts.decoders->append("dxva2");
(*opts.equiv_decoders)["dxva2"].append("dummy");
#endif

PrivateDecoder::GetDecoders(opts);
}
Expand Down Expand Up @@ -1249,6 +1258,12 @@ void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc,
enc->draw_horiz_band = render_slice_vdpau;
enc->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
}
else if (CODEC_IS_DXVA2(codec, enc))
{
enc->get_buffer = get_avf_buffer_dxva2;
enc->get_format = get_format_dxva2;
enc->release_buffer = release_avf_buffer;
}
else if (codec && codec->capabilities & CODEC_CAP_DR1)
{
enc->flags |= CODEC_FLAG_EMU_EDGE;
Expand Down Expand Up @@ -1778,6 +1793,25 @@ int AvFormatDecoder::ScanStreams(bool novideo)
handled = true;
}
#endif // USING_VDPAU
#ifdef USING_DXVA2
MythCodecID dxva2_mcid;
PixelFormat pix_fmt = PIX_FMT_YUV420P;
dxva2_mcid = VideoOutputD3D::GetBestSupportedCodec(
width, height, mpeg_version(enc->codec_id),
no_hardware_decoders, pix_fmt);

if (dxva2_mcid >= video_codec_id)
{
enc->codec_id = (CodecID)myth2av_codecid(dxva2_mcid);
video_codec_id = dxva2_mcid;
handled = true;
if (!no_hardware_decoders &&
codec_is_dxva2(video_codec_id))
{
enc->pix_fmt = pix_fmt;
}
}
#endif // USING_DXVA2
}

if (!handled)
Expand Down Expand Up @@ -2300,6 +2334,36 @@ void render_slice_vdpau(struct AVCodecContext *s, const AVFrame *src,
}
}

int get_avf_buffer_dxva2(struct AVCodecContext *c, AVFrame *pic)
{
AvFormatDecoder *nd = (AvFormatDecoder *)(c->opaque);
VideoFrame *frame = nd->GetPlayer()->GetNextVideoFrame();
for (int i = 0; i < 4; i++)
{
pic->data[i] = NULL;
pic->linesize[i] = 0;
}
pic->reordered_opaque = c->reordered_opaque;
pic->opaque = frame;
pic->type = FF_BUFFER_TYPE_USER;
pic->age = 256 * 256 * 256 *64;
frame->pix_fmt = c->pix_fmt;

#ifdef USING_DXVA2
if (nd->GetPlayer()->getVideoOutput())
{
VideoOutputD3D *vo =
dynamic_cast<VideoOutputD3D*>(nd->GetPlayer()->getVideoOutput());
if (vo)
c->hwaccel_context = (dxva_context*)vo->GetDXVA2Decoder();
pic->data[0] = (uint8_t*)frame->buf;
pic->data[3] = (uint8_t*)frame->buf;
}
#endif

return 0;
}

void AvFormatDecoder::DecodeDTVCC(const uint8_t *buf, uint len)
{
if (!len)
Expand Down
4 changes: 4 additions & 0 deletions mythtv/libs/libmythtv/libmythtv.pro
Expand Up @@ -581,6 +581,10 @@ mingw {
SOURCES -= NuppelVideoRecorder.cpp
SOURCES += videoout_d3d.cpp

using_dxva2: DEFINES += USING_DXVA2
using_dxva2: HEADERS += dxva2decoder.h
using_dxva2: SOURCES += dxva2decoder.cpp

LIBS += -lws2_32
}

Expand Down
7 changes: 7 additions & 0 deletions mythtv/libs/libmythtv/videodisplayprofile.cpp
Expand Up @@ -639,6 +639,7 @@ QString VideoDisplayProfile::GetDecoderName(const QString &decoder)
dec_name["ffmpeg"] = QObject::tr("Standard");
dec_name["macaccel"] = QObject::tr("Mac hardware acceleration");
dec_name["vdpau"] = QObject::tr("NVidia VDPAU acceleration");
dec_name["dxva2"] = QObject::tr("Windows hardware acceleration");
}

QString ret = decoder;
Expand Down Expand Up @@ -673,6 +674,12 @@ QString VideoDisplayProfile::GetDecoderHelp(QString decoder)
"VDPAU will attempt to use the graphics hardware to "
"accelerate video decoding and playback.");

if (decoder == "dxva2")
msg += QObject::tr(
"DXVA2 will use the graphics hardware to "
"accelerate video decoding and playback "
"(requires Windows Vista or later).");

return msg;
}

Expand Down

0 comments on commit 69fefe5

Please sign in to comment.