From 736515f6ad2ba242579bad96476fcff1af1408cf Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sun, 7 Feb 2016 18:03:59 +0100 Subject: [PATCH] Add support for opening VA-API via DRM instead of X11. --- flags.cpp | 4 ++++ flags.h | 3 +++ h264encode.cpp | 55 +++++++++++++++++++++++++++++++++++--------------- h264encode.h | 3 ++- mixer.cpp | 5 +++-- 5 files changed, 51 insertions(+), 19 deletions(-) diff --git a/flags.cpp b/flags.cpp index 56ca799..21e71e9 100644 --- a/flags.cpp +++ b/flags.cpp @@ -10,6 +10,7 @@ void parse_flags(int argc, char * const argv[]) { static const option long_options[] = { { "num-cards", required_argument, 0, 'c' }, + { "va-display", required_argument, 0, 1000 }, { 0, 0, 0, 0 } }; for ( ;; ) { @@ -23,6 +24,9 @@ void parse_flags(int argc, char * const argv[]) case 'c': global_flags.num_cards = atoi(optarg); break; + case 1000: + global_flags.va_display = optarg; + break; default: fprintf(stderr, "Unknown option '%s'\n", argv[option_index]); exit(1); diff --git a/flags.h b/flags.h index bfb51da..52a9a50 100644 --- a/flags.h +++ b/flags.h @@ -1,8 +1,11 @@ #ifndef _FLAGS_H #define _FLAGS_H +#include + struct Flags { int num_cards = 2; + std::string va_display; }; extern Flags global_flags; diff --git a/h264encode.cpp b/h264encode.cpp index 78e3447..e8087ad 100644 --- a/h264encode.cpp +++ b/h264encode.cpp @@ -18,7 +18,9 @@ extern "C" { #include #include #include +#include #include +#include #include #include #include @@ -108,7 +110,7 @@ using namespace std; class H264EncoderImpl { public: - H264EncoderImpl(QSurface *surface, int width, int height, HTTPD *httpd); + H264EncoderImpl(QSurface *surface, const string &va_display, int width, int height, HTTPD *httpd); ~H264EncoderImpl(); void add_audio(int64_t pts, vector audio); bool begin_frame(GLuint *y_tex, GLuint *cbcr_tex); @@ -147,9 +149,9 @@ private: void slice_header(bitstream *bs); int build_packed_seq_buffer(unsigned char **header_buffer); int build_packed_slice_buffer(unsigned char **header_buffer); - int init_va(); + int init_va(const string &va_display); int deinit_va(); - VADisplay va_open_display(void); + VADisplay va_open_display(const string &va_display); void va_close_display(VADisplay va_dpy); int setup_encode(); int release_encode(); @@ -157,6 +159,8 @@ private: int update_RefPicList(int frame_type); bool is_shutdown = false; + bool use_drm; + int drm_fd = -1; thread encode_thread, storage_thread; @@ -831,14 +835,33 @@ static const char *rc_to_string(int rc_mode) } } -VADisplay H264EncoderImpl::va_open_display(void) +VADisplay H264EncoderImpl::va_open_display(const string &va_display) { - x11_display = XOpenDisplay(NULL); - if (!x11_display) { - fprintf(stderr, "error: can't connect to X server!\n"); - return NULL; - } - return vaGetDisplay(x11_display); + if (va_display.empty()) { + x11_display = XOpenDisplay(NULL); + if (!x11_display) { + fprintf(stderr, "error: can't connect to X server!\n"); + return NULL; + } + use_drm = false; + return vaGetDisplay(x11_display); + } else if (va_display[0] != '/') { + x11_display = XOpenDisplay(va_display.c_str()); + if (!x11_display) { + fprintf(stderr, "error: can't connect to X server!\n"); + return NULL; + } + use_drm = false; + return vaGetDisplay(x11_display); + } else { + drm_fd = open(va_display.c_str(), O_RDWR); + if (drm_fd == -1) { + perror(va_display.c_str()); + return NULL; + } + use_drm = true; + return vaGetDisplayDRM(drm_fd); + } } void H264EncoderImpl::va_close_display(VADisplay va_dpy) @@ -855,7 +878,7 @@ void H264EncoderImpl::va_close_display(VADisplay va_dpy) x11_display = NULL; } -int H264EncoderImpl::init_va() +int H264EncoderImpl::init_va(const string &va_display) { VAProfile profile_list[]={VAProfileH264High, VAProfileH264Main, VAProfileH264Baseline, VAProfileH264ConstrainedBaseline}; VAEntrypoint *entrypoints; @@ -865,7 +888,7 @@ int H264EncoderImpl::init_va() VAStatus va_status; unsigned int i; - va_dpy = va_open_display(); + va_dpy = va_open_display(va_display); va_status = vaInitialize(va_dpy, &major_ver, &minor_ver); CHECK_VASTATUS(va_status, "vaInitialize"); @@ -1606,7 +1629,7 @@ int H264EncoderImpl::deinit_va() } -H264EncoderImpl::H264EncoderImpl(QSurface *surface, int width, int height, HTTPD *httpd) +H264EncoderImpl::H264EncoderImpl(QSurface *surface, const string &va_display, int width, int height, HTTPD *httpd) : current_storage_frame(0), surface(surface), httpd(httpd) { AVCodec *codec_audio = avcodec_find_encoder(AUDIO_OUTPUT_CODEC); @@ -1629,7 +1652,7 @@ H264EncoderImpl::H264EncoderImpl(QSurface *surface, int width, int height, HTTPD //print_input(); - init_va(); + init_va(va_display); setup_encode(); // No frames are ready yet. @@ -1889,8 +1912,8 @@ void H264EncoderImpl::encode_frame(H264EncoderImpl::PendingFrame frame, int enco } // Proxy object. -H264Encoder::H264Encoder(QSurface *surface, int width, int height, HTTPD *httpd) - : impl(new H264EncoderImpl(surface, width, height, httpd)) {} +H264Encoder::H264Encoder(QSurface *surface, const string &va_display, int width, int height, HTTPD *httpd) + : impl(new H264EncoderImpl(surface, va_display, width, height, httpd)) {} // Must be defined here because unique_ptr<> destructor needs to know the impl. H264Encoder::~H264Encoder() {} diff --git a/h264encode.h b/h264encode.h index f0fcfae..0d70524 100644 --- a/h264encode.h +++ b/h264encode.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "ref_counted_frame.h" @@ -44,7 +45,7 @@ class QSurface; // .cpp file. class H264Encoder { public: - H264Encoder(QSurface *surface, int width, int height, HTTPD *httpd); + H264Encoder(QSurface *surface, const std::string &va_display, int width, int height, HTTPD *httpd); ~H264Encoder(); void add_audio(int64_t pts, std::vector audio); diff --git a/mixer.cpp b/mixer.cpp index 16a0754..b3950a1 100644 --- a/mixer.cpp +++ b/mixer.cpp @@ -30,6 +30,7 @@ #include "bmusb/bmusb.h" #include "context.h" #include "defs.h" +#include "flags.h" #include "h264encode.h" #include "pbo_frame_allocator.h" #include "ref_counted_gl_sync.h" @@ -132,7 +133,7 @@ Mixer::Mixer(const QSurfaceFormat &format, unsigned num_cards) display_chain->set_dither_bits(0); // Don't bother. display_chain->finalize(); - h264_encoder.reset(new H264Encoder(h264_encoder_surface, WIDTH, HEIGHT, &httpd)); + h264_encoder.reset(new H264Encoder(h264_encoder_surface, global_flags.va_display, WIDTH, HEIGHT, &httpd)); for (unsigned card_index = 0; card_index < num_cards; ++card_index) { printf("Configuring card %d...\n", card_index); @@ -675,7 +676,7 @@ void Mixer::thread_func() h264_encoder->shutdown(); httpd.close_output_file(); httpd.open_output_file(filename.c_str()); - h264_encoder.reset(new H264Encoder(h264_encoder_surface, WIDTH, HEIGHT, &httpd)); + h264_encoder.reset(new H264Encoder(h264_encoder_surface, global_flags.va_display, WIDTH, HEIGHT, &httpd)); } #if 0 -- 2.39.2