Skip to content

Commit

Permalink
Add VAAPI support.
Browse files Browse the repository at this point in the history
This seems to be pretty stable here although only tested using the xorg
edgers ubuntu PPA on an Intel i3 530.

- you must be using OpenGL to draw the main UI (otherwise initialisation
will fail).
- rendering is subclassed from the standard OpenGL video renderer, so
OSD, subtitles etc all work as expected.
- there is no deinterlacing support.
- picture adjustments will follow.
- there are some still frame issues with DVD playback.

I haven't yet found a file that VAAPI won't accelerate for H.264 and
MPEG2, including flawless playback of killa_sampla.

Refs #8593
  • Loading branch information
Mark Kendall committed Jun 18, 2011
1 parent 0e2c507 commit c4bc3e9
Show file tree
Hide file tree
Showing 14 changed files with 1,033 additions and 6 deletions.
17 changes: 17 additions & 0 deletions mythtv/configure
Expand Up @@ -122,6 +122,7 @@ Advanced options (experts only):
--disable-xv disable XVideo (X11 video output accel.)
--enable-vdpau enable NVidia VDPAU hardware acceleration.
--enable-crystalhd enable Broadcom CrystalHD hardware decoder support
--enablevaapi enable VAAPI hardware accelerated video decoding
--enable-dxva2 enable hardware accelerated decoding on windows
--disable-opengl-video disable OpenGL based video display
--disable-quartz-video disable Mac OS X CoreVideo based video display
Expand Down Expand Up @@ -1399,6 +1400,7 @@ USING_LIST='
dxva2
opengl
opengles
vaapi
vdpau
'

Expand Down Expand Up @@ -1775,6 +1777,7 @@ v4l1_deps="backend v4l2 linux_videodev_h"
vdpau_deps="opengl vdpau_vdpau_h vdpau_vdpau_x11_h"
xrandr_deps="x11"
xv_deps="x11"
vaapi_deps="x11 opengl"
asi_deps="backend"

<<BLOCKQUOTE
Expand Down Expand Up @@ -3635,6 +3638,9 @@ check_header sys/select.h
check_header termios.h
check_header vdpau/vdpau.h
check_header vdpau/vdpau_x11.h
check_header va/va.h
check_header va/va_x11.h
check_header va/va_glx.h

check_struct dxva2api.h DXVA_PictureParameters wDecodedPictureIndex

Expand Down Expand Up @@ -3914,6 +3920,16 @@ if enabled crystalhd; then
disable crystalhd;
fi

if enabled vaapi; then
enabled va_va_h && enabled va_va_glx_h && enabled va_va_x11_h || disable vaapi
if enabled vaapi; then
check_cpp_condition va/va.h "VA_VERSION_HEX >= 0x001F0000" ||
{ echolog "VAAPI requires libva >= 0.31.1" && disable vaapi; }
fi
else
disable vaapi
fi

if enabled dxva2; then
enabled dxva2api_h && enabled windows || disable dxva2
else
Expand Down Expand Up @@ -4473,6 +4489,7 @@ if enabled x11 ; then
echo "xrandr support ${xrandr-no}"
echo "xv support ${xv-no}"
echo "VDPAU support ${vdpau-no}"
echo "VAAPI support ${vaapi-no}"
echo "CrystalHD support ${crystalhd-no}"
fi
echo "OpenGL video ${opengl_video-no}"
Expand Down
63 changes: 63 additions & 0 deletions mythtv/libs/libmythtv/avformatdecoder.cpp
Expand Up @@ -53,6 +53,11 @@ extern "C" {
#include "videoout_d3d.h"
#endif

#ifdef USING_VAAPI
#include "videoout_openglvaapi.h"
#include "vaapicontext.h"
#endif // USING_VAAPI

extern "C" {
#include "libavutil/avutil.h"
#include "libavcodec/ac3_parser.h"
Expand Down Expand Up @@ -125,6 +130,7 @@ 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);
int get_avf_buffer_vaapi(struct AVCodecContext *c, AVFrame *pic);

static AVCodec *find_vdpau_decoder(AVCodec *c, enum CodecID id)
{
Expand Down Expand Up @@ -238,6 +244,11 @@ void AvFormatDecoder::GetDecoders(render_opts &opts)
(*opts.equiv_decoders)["dxva2"].append("dummy");
#endif

#ifdef USING_VAAPI
opts.decoders->append("vaapi");
(*opts.equiv_decoders)["vaapi"].append("dummy");
#endif

PrivateDecoder::GetDecoders(opts);
}

Expand Down Expand Up @@ -1270,6 +1281,13 @@ void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc,
enc->get_format = get_format_dxva2;
enc->release_buffer = release_avf_buffer;
}
else if (CODEC_IS_VAAPI(codec, enc))
{
enc->get_buffer = get_avf_buffer_vaapi;
enc->get_format = get_format_vaapi;
enc->release_buffer = release_avf_buffer;
enc->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD;
}
else if (codec && codec->capabilities & CODEC_CAP_DR1)
{
enc->flags |= CODEC_FLAG_EMU_EDGE;
Expand Down Expand Up @@ -1805,6 +1823,25 @@ int AvFormatDecoder::ScanStreams(bool novideo)
handled = true;
}
#endif // USING_VDPAU
#ifdef USING_VAAPI
MythCodecID vaapi_mcid;
PixelFormat pix_fmt = PIX_FMT_YUV420P;
vaapi_mcid = VideoOutputOpenGLVAAPI::GetBestSupportedCodec(
width, height, mpeg_version(enc->codec_id),
no_hardware_decoders, pix_fmt);

if (vaapi_mcid >= video_codec_id)
{
enc->codec_id = (CodecID)myth2av_codecid(vaapi_mcid);
video_codec_id = vaapi_mcid;
handled = true;
if (!no_hardware_decoders &&
codec_is_vaapi(video_codec_id))
{
enc->pix_fmt = pix_fmt;
}
}
#endif // USING_VAAPI
#ifdef USING_DXVA2
MythCodecID dxva2_mcid;
PixelFormat pix_fmt = PIX_FMT_YUV420P;
Expand Down Expand Up @@ -2391,6 +2428,32 @@ int get_avf_buffer_dxva2(struct AVCodecContext *c, AVFrame *pic)
return 0;
}

int get_avf_buffer_vaapi(struct AVCodecContext *c, AVFrame *pic)
{
AvFormatDecoder *nd = (AvFormatDecoder *)(c->opaque);
VideoFrame *frame = nd->GetPlayer()->GetNextVideoFrame();

pic->data[0] = frame->buf;
pic->data[1] = NULL;
pic->data[2] = NULL;
pic->data[3] = NULL;
pic->linesize[0] = 0;
pic->linesize[1] = 0;
pic->linesize[2] = 0;
pic->linesize[3] = 0;
pic->opaque = frame;
pic->type = FF_BUFFER_TYPE_USER;
pic->age = 256 * 256 * 256 * 64;
frame->pix_fmt = c->pix_fmt;

#ifdef USING_VAAPI
if (nd->GetPlayer())
c->hwaccel_context = (vaapi_context*)nd->GetPlayer()->GetDecoderContext(frame->buf, pic->data[3]);
#endif

return 0;
}

void AvFormatDecoder::DecodeDTVCC(const uint8_t *buf, uint len)
{
if (!len)
Expand Down
5 changes: 5 additions & 0 deletions mythtv/libs/libmythtv/libmythtv.pro
Expand Up @@ -370,6 +370,11 @@ using_frontend {
using_opengl_video:HEADERS += openglvideo.h videoout_opengl.h
using_opengl_video:SOURCES += openglvideo.cpp videoout_opengl.cpp

using_vaapi: DEFINES += USING_VAAPI
using_vaapi: DEFINES += vaapicontext.h videoout_openglvaapi.h
using_vaapi: SOURCES += vaapicontext.cpp videoout_openglvaapi.cpp
using_vaapi: LIBS += -lva -lva-x11 -lva-glx

# Misc. frontend
HEADERS += DetectLetterbox.h
SOURCES += DetectLetterbox.cpp
Expand Down
4 changes: 2 additions & 2 deletions mythtv/libs/libmythtv/mythplayer.cpp
Expand Up @@ -1157,10 +1157,10 @@ void MythPlayer::DrawSlice(VideoFrame *frame, int x, int y, int w, int h)
videoOutput->DrawSlice(frame, x, y, w, h);
}

void* MythPlayer::GetDecoderContext(void)
void* MythPlayer::GetDecoderContext(unsigned char* buf, uint8_t*& id)
{
if (videoOutput)
return videoOutput->GetDecoderContext();
return videoOutput->GetDecoderContext(buf, id);
return NULL;
}

Expand Down
2 changes: 1 addition & 1 deletion mythtv/libs/libmythtv/mythplayer.h
Expand Up @@ -237,7 +237,7 @@ class MTV_PUBLIC MythPlayer
void DrawSlice(VideoFrame *frame, int x, int y, int w, int h);
/// Returns the stream decoder currently in use.
DecoderBase *GetDecoder(void) { return decoder; }
void *GetDecoderContext(void);
void *GetDecoderContext(unsigned char* buf, uint8_t*& id);

// Preview Image stuff
void SaveScreenshot(void);
Expand Down

0 comments on commit c4bc3e9

Please sign in to comment.