Skip to content
Permalink
Browse files

Add VAAPI support.

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
Mark Kendall committed Jun 18, 2011
1 parent 0e2c507 commit c4bc3e9eb9a8a082d243b9d091018e58072eb3b6
@@ -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
@@ -1399,6 +1400,7 @@ USING_LIST='
dxva2
opengl
opengles
vaapi
vdpau
'

@@ -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
@@ -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

@@ -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
@@ -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}"
@@ -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"
@@ -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)
{
@@ -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);
}

@@ -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;
@@ -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;
@@ -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)
@@ -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
@@ -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;
}

@@ -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);

0 comments on commit c4bc3e9

Please sign in to comment.
You can’t perform that action at this time.