Commit a8fc6814 authored by Frediano Ziglio's avatar Frediano Ziglio

Initial public commit

parents
*~
*.o
*.la
*.lo
*.tar.bz2
*.tar.gz
.*.sw?
.deps
.dirstamp
.libs
Makefile
Makefile.in
/aclocal.m4
/autom4te.cache
/build-aux/
/config.h
/config.h.in
/config.log
/config.status
/configure
/INSTALL
/stamp-h1
/spice-streaming-agent.spec
/spice-streaming-agent.pc
/data/spice-streaming.desktop
/libtool
/m4/libtool.m4
/m4/ltoptions.m4
/m4/ltsugar.m4
/m4/ltversion.m4
/m4/lt~obsolete.m4
TO BE DEFINED
A Proprietary Red Hat License
Copyright Red Hat Inc.
This software follows a GridSDK sample program by NVidia.
Please see LICENSE_NVIDIA for GridSDK.
Exact License is TBD.
NULL =
SUBDIRS = \
include/spice-streaming-agent \
src \
$(NULL)
# this will start the program for each user session
xdgautostartdir = $(sysconfdir)/xdg/autostart
xdgautostart_DATA = $(top_srcdir)/data/spice-streaming.desktop
# this will start the program for the login session
gdmautostartdir = $(datadir)/gdm/greeter/autostart
gdmautostart_DATA = $(top_srcdir)/data/spice-streaming.desktop
pkgconfigdir = $(datadir)/pkgconfig
pkgconfig_DATA = spice-streaming-agent.pc
EXTRA_DIST = \
spice-streaming-agent.spec \
spice-streaming-agent.pc \
LICENSE \
data/spice-streaming.desktop \
$(NULL)
Introduction
============
The SPICE Streaming Agent is a guest-side daemon which captures the
guest X.Org output, encodes it to H.264 using hardware encoding (NVIDIA-only at
the moment), and forwards the resulting stream to the host to be sent through
SPICE.
Virtual Machine Configuration
=============================
In order to set up streaming, qemu needs to expose a
`com.redhat.stream.0` virtio port, associated with a
corresponding Spice port.
Using virt-manager
------------------
In the hardware details, click on "Add Hardware", then select
"Channel". Add a "Spice port" device type with the
"com.redhat.stream.0" name. You also need to set "Channel" to
"com.redhat.stream.0"
Using libvirt
-------------
[source,xml]
<devices>
<channel type='spiceport'>
<source channel='com.redhat.stream.0'/>
<target type='virtio' name='com.redhat.stream.0'/>
</channel>
</devices>
Using QEMU
----------
[source,sh]
-device virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel1,id=channel1,name=com.redhat.stream.0 -chardev spiceport,name=com.redhat.stream.0,id=charchannel1
NVIDIA-specific Configuration
=============================
In order to use NVIDIA hardware-accelerated encoding, you will need to
configure the virtual machine to use mdev/vfio. An NVIDIA card has to be listed
in lspci output on the guest.
The guest also needs to have the NVIDIA proprietary drivers installed and in
use.
AC_PREREQ([2.57])
AC_INIT(spice-streaming-agent, 0.1,
[spice-devel@lists.freedesktop.org])
AM_CONFIG_HEADER([config.h])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip subdir-objects])
AM_MAINTAINER_MODE
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
AC_PROG_CC
AC_PROG_CC_C99
if test x"$ac_cv_prog_cc_c99" = xno; then
AC_MSG_ERROR([C99 compiler is required.])
fi
AC_PROG_CXX
AX_CXX_COMPILE_STDCXX_11
AC_PROG_INSTALL
AC_CANONICAL_HOST
LT_INIT([disable-static])
AM_PROG_CC_C_O
AC_C_BIGENDIAN
PKG_PROG_PKG_CONFIG
dnl =========================================================================
dnl Check deps
SPICE_PROTOCOL_MIN_VER=0.12.14
PKG_CHECK_MODULES([SPICE_PROTOCOL], [spice-protocol >= $SPICE_PROTOCOL_MIN_VER])
AC_SUBST([SPICE_PROTOCOL_MIN_VER])
SAVE_CFLAGS="$CFLAGS"
CFLAGS="$SPICE_PROTOCOL_CFLAGS $CFLAGS"
AC_CHECK_HEADER([spice/stream-device.h],,[AC_MSG_ERROR([Could not locate spice-protocol stream-device.h header])])
CFLAGS="$SAVE_CFLAGS"
PKG_CHECK_MODULES(X11, x11)
PKG_CHECK_MODULES(XFIXES, xfixes)
AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
AC_MSG_CHECKING([for jpeglib.h])
AC_TRY_CPP(
[#include <stdio.h>
#undef PACKAGE
#undef VERSION
#undef HAVE_STDLIB_H
#include <jpeglib.h>],
JPEG_LIBS='-ljpeg'
AC_MSG_RESULT($jpeg_ok),
AC_MSG_ERROR([jpeglib.h not found])),
AC_MSG_ERROR([libjpeg not found]))
AC_SUBST(JPEG_LIBS)
dnl ===========================================================================
dnl check compiler flags
SPICE_COMPILE_WARNINGS
LIBVIRT_LINKER_RELRO
LIBVIRT_LINKER_NO_INDIRECT
AC_SUBST(WARN_CFLAGS)
AC_SUBST(WARN_CXXFLAGS)
dnl =========================================================================
dnl -fvisibility stuff
have_gcc4=no
AC_MSG_CHECKING(for -fvisibility)
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
#if defined(__GNUC__) && (__GNUC__ >= 4)
#else
error Need GCC 4.0 for visibility
#endif
int main () { return 0; }
])], have_gcc4=yes)
if test "x$have_gcc4" = "xyes" && test ! "$os_win32" = "yes" ; then
VISIBILITY_HIDDEN_CFLAGS="-fvisibility=hidden"
fi
AC_MSG_RESULT($have_gcc4)
AC_SUBST(VISIBILITY_HIDDEN_CFLAGS)
AC_DEFINE_DIR([BINDIR], [bindir], [Where data are placed to.])
AC_OUTPUT([
spice-streaming-agent.spec
data/spice-streaming.desktop
Makefile
src/Makefile
src/unittests/Makefile
include/spice-streaming-agent/Makefile
spice-streaming-agent.pc
])
dnl ==========================================================================
AC_MSG_NOTICE([
SPICE streaming agent $VERSION
==============================
prefix: ${prefix}
C compiler: ${CC}
C++ compiler: ${CXX}
Now type 'make' to build $PACKAGE
])
ACTION=="add", SUBSYSTEM=="virtio-ports", ENV{DEVLINKS}=="/dev/virtio-ports/com.redhat.stream.0", MODE="0666"
[Desktop Entry]
Name=SPICE Streaming Agent
Comment=Agent for Streaming the framebuffer to Spice
Exec=@BINDIR@/spice-streaming-agent
#TryExec=/usr/bin/spice-streaming-agent
Terminal=false
Type=Application
Categories=
X-GNOME-Autostart-Phase=Application
NULL =
public_includedir = $(includedir)/spice-streaming-agent
public_include_HEADERS = \
frame-capture.hpp \
plugin.hpp \
$(NULL)
/* Common interface for all streaming / capture cards
* used by SPICE streaming-agent.
*
* \copyright
* Copyright 2016-2017 Red Hat Inc. All rights reserved.
*/
#ifndef SPICE_STREAMING_AGENT_FRAME_CAPTURE_HPP
#define SPICE_STREAMING_AGENT_FRAME_CAPTURE_HPP
#include <cstdio>
#include <spice/enums.h>
namespace SpiceStreamingAgent {
struct FrameSize
{
unsigned width;
unsigned height;
};
struct FrameInfo
{
FrameSize size;
/*! Memory buffer, valid till next frame is read */
const void *buffer;
size_t buffer_size;
/*! Start of a new stream */
bool stream_start;
};
/*!
* Pure base class implementing the frame capture
*/
class FrameCapture
{
public:
virtual ~FrameCapture()=default;
/*! Grab a frame
* This function will wait for next frame.
* Capture is started if needed.
*/
virtual FrameInfo CaptureFrame()=0;
/*! Reset capturing
* This will reset to beginning state
*/
virtual void Reset()=0;
/*!
* Get video codec used to encode last frame
*/
virtual SpiceVideoCodecType VideoCodecType() const=0;
protected:
FrameCapture()=default;
FrameCapture(const FrameCapture&)=delete;
void operator=(const FrameCapture&)=delete;
};
}
#endif // SPICE_STREAMING_AGENT_FRAME_CAPTURE_HPP
/* Plugin interface for all streaming / capture cards
* used by SPICE streaming-agent.
*
* \copyright
* Copyright 2017 Red Hat Inc. All rights reserved.
*/
#ifndef SPICE_STREAMING_AGENT_PLUGIN_HPP
#define SPICE_STREAMING_AGENT_PLUGIN_HPP
#include <spice/enums.h>
/*!
* \file
* \brief Plugin interface
*
* Each module loaded by the agent should implement one or more
* Plugins and register them.
*/
namespace SpiceStreamingAgent {
class FrameCapture;
/*!
* Plugin version, only using few bits, schema is 0xMMmm
* where MM is major and mm is the minor, can be easily expanded
* using more bits in the future
*/
enum Constants : unsigned { PluginVersion = 0x100u };
enum Ranks : unsigned {
/// this plugin should not be used
DontUse = 0,
/// use plugin only as a fallback
FallBackMin = 1,
/// plugin supports encoding in software
SoftwareMin = 0x40000000,
/// plugin supports encoding in hardware
HardwareMin = 0x80000000,
/// plugin provides access to specific card hardware not only for compression
SpecificHardwareMin = 0xC0000000
};
/*!
* Configuration option.
* An array of these will be passed to the plugin.
* Simply a couple name and value passed as string.
* For instance "framerate" and "20".
*/
struct ConfigureOption
{
const char *name;
const char *value;
};
/*!
* Interface a plugin should implement and register to the Agent.
*
* A plugin module can register multiple Plugin interfaces to handle
* multiple codecs. In this case each Plugin will report data for a
* specific codec.
*/
class Plugin
{
public:
/*!
* Allows to free the plugin when not needed
*/
virtual ~Plugin() {};
/*!
* Request an object for getting frames.
* Plugin should return proper object or nullptr if not possible
* to initialize.
* Plugin can also raise std::runtime_error which will be logged.
*/
virtual FrameCapture *CreateCapture()=0;
/*!
* Request to rank the plugin.
* See Ranks enumeration for details on ranges.
* \return Ranks::DontUse if not possible to use the plugin, this
* is necessary as the condition for capturing frames can change
* from the time the plugin decided to register and now.
*/
virtual unsigned Rank()=0;
/*!
* Get video codec used to encode last frame
*/
virtual SpiceVideoCodecType VideoCodecType() const=0;
};
/*!
* Interface the plugin should use to interact with the agent.
* The agent will pass it to the entry point.
* Exporting functions from an executable in Windows OS is not easy
* and a standard way to do it so better to implement the interface
* that way for compatibility.
*/
class Agent
{
public:
/*!
* Get agent version.
* Plugin should check the version for compatibility before doing
* everything.
* \return version specified like PluginVersion
*/
virtual unsigned Version() const=0;
/*!
* Check if a given plugin version is compatible with this agent
* \return true is compatible
*/
virtual bool PluginVersionIsCompatible(unsigned pluginVersion) const=0;
/*!
* Register a plugin in the system.
*/
virtual void Register(Plugin& plugin)=0;
/*!
* Get options array.
* Array is terminated with {nullptr, nullptr}.
* Never nullptr.
* \todo passing options to entry point instead?
*/
virtual const ConfigureOption* Options() const=0;
};
typedef bool PluginInitFunc(SpiceStreamingAgent::Agent* agent);
}
#ifndef SPICE_STREAMING_AGENT_PROGRAM
/*!
* Plugin main entry point.
* Plugins should check if the version of the agent is compatible.
* If is compatible should register itself to the agent and return
* true.
* If is not compatible can decide to stay in memory or not returning
* true (do not unload) or false (safe to unload). This is necessary
* if the plugin uses some library which are not safe to be unloaded.
* This public interface is also designed to avoid exporting data from
* the plugin which could be a problem in some systems.
* \return true if plugin should stay loaded, false otherwise
*/
extern "C" SpiceStreamingAgent::PluginInitFunc spice_streaming_agent_plugin_init;
#endif
#endif // SPICE_STREAMING_AGENT_PLUGIN_HPP
dnl @synopsis AC_DEFINE_DIR(VARNAME, DIR [, DESCRIPTION])
dnl
dnl This macro sets VARNAME to the expansion of the DIR variable,
dnl taking care of fixing up ${prefix} and such.
dnl
dnl VARNAME is then offered as both an output variable and a C
dnl preprocessor symbol.
dnl
dnl Example:
dnl
dnl AC_DEFINE_DIR([DATADIR], [datadir], [Where data are placed to.])
dnl
dnl @category Misc
dnl @author Stepan Kasal <kasal@ucw.cz>
dnl @author Andreas Schwab <schwab@suse.de>
dnl @author Guido U. Draheim <guidod@gmx.de>
dnl @author Alexandre Oliva
dnl @version 2006-10-13
dnl @license AllPermissive
AC_DEFUN([AC_DEFINE_DIR], [
prefix_NONE=
exec_prefix_NONE=
test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix
test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix
dnl In Autoconf 2.60, ${datadir} refers to ${datarootdir}, which in turn
dnl refers to ${prefix}. Thus we have to use `eval' twice.
eval ac_define_dir="\"[$]$2\""
eval ac_define_dir="\"$ac_define_dir\""
AC_SUBST($1, "$ac_define_dir")
AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3])
test "$prefix_NONE" && prefix=NONE
test "$exec_prefix_NONE" && exec_prefix=NONE
])
# manywarnings.m4 serial 8
dnl Copyright (C) 2008-2016 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl From Simon Josefsson
# gl_MANYWARN_COMPLEMENT(OUTVAR, LISTVAR, REMOVEVAR)
# --------------------------------------------------
# Copy LISTVAR to OUTVAR except for the entries in REMOVEVAR.
# Elements separated by whitespace. In set logic terms, the function
# does OUTVAR = LISTVAR \ REMOVEVAR.
AC_DEFUN([gl_MANYWARN_COMPLEMENT],
[
gl_warn_set=
set x $2; shift
for gl_warn_item
do
case " $3 " in
*" $gl_warn_item "*)
;;
*)
gl_warn_set="$gl_warn_set $gl_warn_item"
;;
esac
done
$1=$gl_warn_set
])
# gl_MANYWARN_ALL_GCC(VARIABLE)
# -----------------------------
# Add all documented GCC warning parameters to variable VARIABLE.
# Note that you need to test them using gl_WARN_ADD if you want to
# make sure your gcc understands it.
AC_DEFUN([gl_MANYWARN_ALL_GCC],
[
dnl First, check for some issues that only occur when combining multiple
dnl gcc warning categories.
AC_REQUIRE([AC_PROG_CC])
if test -n "$GCC"; then
dnl Check if -W -Werror -Wno-missing-field-initializers is supported
dnl with the current $CC $CFLAGS $CPPFLAGS.
AC_MSG_CHECKING([whether -Wno-missing-field-initializers is supported])
AC_CACHE_VAL([gl_cv_cc_nomfi_supported], [
gl_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -W -Werror -Wno-missing-field-initializers"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[]], [[]])],
[gl_cv_cc_nomfi_supported=yes],
[gl_cv_cc_nomfi_supported=no])
CFLAGS="$gl_save_CFLAGS"])
AC_MSG_RESULT([$gl_cv_cc_nomfi_supported])
if test "$gl_cv_cc_nomfi_supported" = yes; then
dnl Now check whether -Wno-missing-field-initializers is needed
dnl for the { 0, } construct.
AC_MSG_CHECKING([whether -Wno-missing-field-initializers is needed])
AC_CACHE_VAL([gl_cv_cc_nomfi_needed], [
gl_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -W -Werror"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM(
[[int f (void)
{
typedef struct { int a; int b; } s_t;
s_t s1 = { 0, };
return s1.b;
}
]],
[[]])],
[gl_cv_cc_nomfi_needed=no],
[gl_cv_cc_nomfi_needed=yes])
CFLAGS="$gl_save_CFLAGS"
])
AC_MSG_RESULT([$gl_cv_cc_nomfi_needed])
fi
dnl Next, check if -Werror -Wuninitialized is useful with the
dnl user's choice of $CFLAGS; some versions of gcc warn that it
dnl has no effect if -O is not also used
AC_MSG_CHECKING([whether -Wuninitialized is supported])
AC_CACHE_VAL([gl_cv_cc_uninitialized_supported], [
gl_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Werror -Wuninitialized"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[]], [[]])],
[gl_cv_cc_uninitialized_supported=yes],
[gl_cv_cc_uninitialized_supported=no])
CFLAGS="$gl_save_CFLAGS"])
AC_MSG_RESULT([$gl_cv_cc_uninitialized_supported])
fi
# List all gcc warning categories.
# To compare this list to your installed GCC's, run this Bash command:
#
# comm -3 \
# <(sed -n 's/^ *\(-[^ ]*\) .*/\1/p' manywarnings.m4 | sort) \
# <(gcc --help=warnings | sed -n 's/^ \(-[^ ]*\) .*/\1/p' | sort |
# grep -v -x -f <(
# awk '/^[^#]/ {print $1}' ../build-aux/gcc-warning.spec))
gl_manywarn_set=
for gl_manywarn_item in \
-fno-common \
-W \
-Wabi \
-Waddress \
-Waggressive-loop-optimizations \
-Wall \
-Wattributes \
-Wbad-function-cast \
-Wbool-compare \
-Wbuiltin-macro-redefined \
-Wcast-align \
-Wchar-subscripts \
-Wchkp \
-Wclobbered \
-Wcomment \
-Wcomments \
-Wcoverage-mismatch \
-Wcpp \
-Wdate-time \
-Wdeprecated \
-Wdeprecated-declarations \
-Wdesignated-init \
-Wdisabled-optimization \
-Wdiscarded-array-qualifiers \
-Wdiscarded-qualifiers \
-Wdiv-by-zero \
-Wdouble-promotion \
-Wduplicated-cond \
-Wempty-body \
-Wendif-labels \
-Wenum-compare \
-Wextra \
-Wformat-contains-nul \
-Wformat-extra-args \
-Wformat-nonliteral \
-Wformat-security \
-Wformat-signedness \
-Wformat-y2k \
-Wformat-zero-length \
-Wframe-address \
-Wfree-nonheap-object \
-Whsa \
-Wignored-attributes \
-Wignored-qualifiers \
-Wimplicit \
-Wimplicit-function-declaration \
-Wimplicit-int \
-Wincompatible-pointer-types \
-Winit-self \
-Winline \
-Wint-conversion \
-Wint-to-pointer-cast \
-Winvalid-memory-model \
-Winvalid-pch \
-Wjump-misses-init \
-Wlogical-not-parentheses \
-Wlogical-op \
-Wmain \
-Wmaybe-uninitialized \
-Wmemset-transposed-args \
-Wmisleading-indentation \
-Wmissing-braces \
-Wmissing-declarations \
-Wmissing-field-initializers \
-Wmissing-include-dirs \
-Wmissing-parameter-type \
-Wmissing-prototypes \
-Wmultichar \
-Wnarrowing \
-Wnested-externs \
-Wnonnull \
-Wnonnull-compare \
-Wnull-dereference \
-Wodr \
-Wold-style-declaration \
-Wold-style-definition \
-Wopenmp-simd \
-Woverflow \
-Woverlength-strings \
-Woverride-init \
-Wpacked \
-Wpacked-bitfield-compat \
-Wparentheses \
-Wpointer-arith \
-Wpointer-sign \
-Wpointer-to-int-cast \
-Wpragmas \
-Wreturn-local-addr \
-Wreturn-type \
-Wscalar-storage-order \
-Wsequence-point \
-Wshadow \
-Wshift-count-negative \
-Wshift-count-overflow \
-Wshift-negative-value \
-Wsizeof-array-argument \
-Wsizeof-pointer-memaccess \
-Wstack-protector \
-Wstrict-aliasing \
-Wstrict-overflow \
-Wstrict-prototypes \
-Wsuggest-attribute=const \
-Wsuggest-attribute=format \
-Wsuggest-attribute=noreturn \
-Wsuggest-attribute=pure \
-Wsuggest-final-methods \
-Wsuggest-final-types \
-Wswitch \
-Wswitch-bool \
-Wswitch-default \
-Wsync-nand \
-Wsystem-headers \
-Wtautological-compare \
-Wtrampolines \
-Wtrigraphs \
-Wtype-limits \
-Wuninitialized \
-Wunknown-pragmas \
-Wunsafe-loop-optimizations \
-Wunused \
-Wunused-but-set-parameter \
-Wunused-but-set-variable \
-Wunused-function \
-Wunused-label \
-Wunused-local-typedefs \
-Wunused-macros \
-Wunused-parameter \
-Wunused-result \
-Wunused-value \
-Wunused-variable \
-Wvarargs \
-Wvariadic-macros \
-Wvector-operation-performance \
-Wvla \
-Wvolatile-register-var \
-Wwrite-strings \
\
; do
gl_manywarn_set="$gl_manywarn_set $gl_manywarn_item"
done
# gcc --help=warnings outputs an unusual form for these options; list
# them here so that the above 'comm' command doesn't report a false match.
gl_manywarn_set="$gl_manywarn_set -Warray-bounds=2"
gl_manywarn_set="$gl_manywarn_set -Wnormalized=nfc"
gl_manywarn_set="$gl_manywarn_set -Wshift-overflow=2"
gl_manywarn_set="$gl_manywarn_set -Wunused-const-variable=2"
# These are needed for older GCC versions.
if test -n "$GCC"; then
case `($CC --version) 2>/dev/null` in
'gcc (GCC) '[[0-3]].* | \
'gcc (GCC) '4.[[0-7]].*)
gl_manywarn_set="$gl_manywarn_set -fdiagnostics-show-option"
gl_manywarn_set="$gl_manywarn_set -funit-at-a-time"
;;
esac
fi
# Disable specific options as needed.
if test "$gl_cv_cc_nomfi_needed" = yes; then