diff --git a/testing/gerbera/0001-Remove-IN-and-OUT-dropped-upstream.patch b/testing/gerbera/0001-Remove-IN-and-OUT-dropped-upstream.patch
new file mode 100644
index 0000000000000000000000000000000000000000..4b34fe0942a9f52d63eecf9611e0540be0b718d6
--- /dev/null
+++ b/testing/gerbera/0001-Remove-IN-and-OUT-dropped-upstream.patch
@@ -0,0 +1,777 @@
+From a4870cbdbcbbd835b10ea6f464c981f01da0b542 Mon Sep 17 00:00:00 2001
+From: Ian Whyman <ian@gerbera.io>
+Date: Tue, 24 Dec 2019 16:18:32 +0000
+Subject: [PATCH] Remove IN and OUT (dropped upstream)
+
+---
+ src/buffered_io_handler.cc       |  2 +-
+ src/curl_io_handler.cc           |  2 +-
+ src/device_description_handler.h |  4 ++--
+ src/fd_io_handler.cc             |  8 ++++----
+ src/fd_io_handler.h              |  8 ++++----
+ src/file_io_handler.cc           |  8 ++++----
+ src/file_io_handler.h            |  8 ++++----
+ src/file_request_handler.cc      |  6 +++---
+ src/file_request_handler.h       |  8 ++++----
+ src/io_handler.cc                | 26 +++++++++++++-------------
+ src/io_handler_buffer_helper.cc  |  6 +++---
+ src/mem_io_handler.cc            |  6 +++---
+ src/mem_io_handler.h             |  6 +++---
+ src/metadata/taglib_handler.cc   |  2 +-
+ src/process_io_handler.cc        |  8 ++++----
+ src/process_io_handler.h         |  8 ++++----
+ src/request_handler.h            |  4 ++--
+ src/serve_request_handler.cc     |  8 ++++----
+ src/serve_request_handler.h      |  8 ++++----
+ src/server.cc                    | 24 ++++++++++++------------
+ src/url_request_handler.cc       |  8 ++++----
+ src/url_request_handler.h        |  8 ++++----
+ src/util/headers.h               |  2 +-
+ src/web_request_handler.cc       | 10 +++++-----
+ src/web_request_handler.h        | 10 +++++-----
+ 25 files changed, 99 insertions(+), 99 deletions(-)
+
+diff --git a/src/buffered_io_handler.cc b/src/buffered_io_handler.cc
+index 6ff7a79e..f7d0c663 100644
+--- a/src/buffered_io_handler.cc
++++ b/src/buffered_io_handler.cc
+@@ -51,7 +51,7 @@ BufferedIOHandler::BufferedIOHandler(Ref<IOHandler> underlyingHandler, size_t bu
+     //seekEnabled = true;
+ }
+ 
+-void BufferedIOHandler::open(IN enum UpnpOpenFileMode mode)
++void BufferedIOHandler::open(enum UpnpOpenFileMode mode)
+ {
+     // do the open here instead of threadProc() because it may throw an exception
+     underlyingHandler->open(mode);
+diff --git a/src/curl_io_handler.cc b/src/curl_io_handler.cc
+index 4f79b7ea..80399bbc 100644
+--- a/src/curl_io_handler.cc
++++ b/src/curl_io_handler.cc
+@@ -57,7 +57,7 @@ CurlIOHandler::CurlIOHandler(String URL, CURL* curl_handle, size_t bufSize, size
+     seekEnabled = true;
+ }
+ 
+-void CurlIOHandler::open(IN enum UpnpOpenFileMode mode)
++void CurlIOHandler::open(enum UpnpOpenFileMode mode)
+ {
+     if (curl_handle == nullptr) {
+         curl_handle = curl_easy_init();
+diff --git a/src/device_description_handler.h b/src/device_description_handler.h
+index 934dc0ae..863912b5 100644
+--- a/src/device_description_handler.h
++++ b/src/device_description_handler.h
+@@ -31,8 +31,8 @@ class DeviceDescriptionHandler : public RequestHandler {
+ public:
+     explicit DeviceDescriptionHandler(UpnpXMLBuilder* xmlBuilder);
+ 
+-    void getInfo(IN const char *filename, OUT UpnpFileInfo *info) override;
+-    zmm::Ref<IOHandler> open(IN const char* filename, IN enum UpnpOpenFileMode mode, IN zmm::String range) override;
++    void getInfo(const char *filename, UpnpFileInfo *info) override;
++    zmm::Ref<IOHandler> open(const char* filename, enum UpnpOpenFileMode mode, zmm::String range) override;
+ 
+ protected:
+     UpnpXMLBuilder* xmlBuilder;
+diff --git a/src/fd_io_handler.cc b/src/fd_io_handler.cc
+index 63f69c4d..f8d35d1d 100644
+--- a/src/fd_io_handler.cc
++++ b/src/fd_io_handler.cc
+@@ -72,7 +72,7 @@ void FDIOHandler::closeOther(Ref<IOHandler> other)
+     this->other = other;
+ }
+ 
+-void FDIOHandler::open(IN enum UpnpOpenFileMode mode)
++void FDIOHandler::open(enum UpnpOpenFileMode mode)
+ {
+ 
+     if (fd != -1) {
+@@ -96,7 +96,7 @@ void FDIOHandler::open(IN enum UpnpOpenFileMode mode)
+     }
+ }
+ 
+-size_t FDIOHandler::read(OUT char* buf, IN size_t length)
++size_t FDIOHandler::read(char* buf, size_t length)
+ {
+     size_t ret = 0;
+ 
+@@ -105,7 +105,7 @@ size_t FDIOHandler::read(OUT char* buf, IN size_t length)
+     return ret;
+ }
+ 
+-size_t FDIOHandler::write(IN char* buf, IN size_t length)
++size_t FDIOHandler::write(char* buf, size_t length)
+ {
+     size_t ret = 0;
+ 
+@@ -114,7 +114,7 @@ size_t FDIOHandler::write(IN char* buf, IN size_t length)
+     return ret;
+ }
+ 
+-void FDIOHandler::seek(IN off_t offset, IN int whence)
++void FDIOHandler::seek(off_t offset, int whence)
+ {
+     if (lseek(fd, offset, whence) != 0) {
+         throw _Exception(_("fseek failed"));
+diff --git a/src/fd_io_handler.h b/src/fd_io_handler.h
+index b8401110..dbd25c3b 100644
+--- a/src/fd_io_handler.h
++++ b/src/fd_io_handler.h
+@@ -59,18 +59,18 @@ public:
+     void closeOther(zmm::Ref<IOHandler> other);
+ 
+     /// \brief Opens file for reading (writing is not supported)
+-    void open(IN enum UpnpOpenFileMode mode) override;
++    void open(enum UpnpOpenFileMode mode) override;
+ 
+     /// \brief Reads a previously opened file sequentially.
+     /// \param buf Data from the file will be copied into this buffer.
+     /// \param length Number of bytes to be copied into the buffer.
+-    size_t read(OUT char* buf, IN size_t length) override;
++    size_t read(char* buf, size_t length) override;
+ 
+     /// \brief Writes to a previously opened file.
+     /// \param buf Data from the buffer will be written to the file.
+     /// \param length Number of bytes to be written from the buffer.
+     /// \return number of bytes written.
+-    size_t write(OUT char* buf, IN size_t length) override;
++    size_t write(char* buf, size_t length) override;
+ 
+     /// \brief Performs seek on an open file.
+     /// \param offset Number of bytes to move in the file. For seeking forwards
+@@ -79,7 +79,7 @@ public:
+     /// \param whence The position to move relative to. SEEK_CUR to move relative
+     /// to current position, SEEK_END to move relative to the end of file,
+     /// SEEK_SET to specify an absolute offset.
+-    void seek(IN off_t offset, IN int whence) override;
++    void seek(off_t offset, int whence) override;
+ 
+     /// \brief Close a previously opened file.
+     void close() override;
+diff --git a/src/file_io_handler.cc b/src/file_io_handler.cc
+index 6889ada2..4940c951 100644
+--- a/src/file_io_handler.cc
++++ b/src/file_io_handler.cc
+@@ -45,7 +45,7 @@ FileIOHandler::FileIOHandler(String filename)
+ {
+ }
+ 
+-void FileIOHandler::open(IN enum UpnpOpenFileMode mode)
++void FileIOHandler::open(enum UpnpOpenFileMode mode)
+ {
+     if (mode == UPNP_READ) {
+         f = fopen(filename.c_str(), "rb");
+@@ -61,7 +61,7 @@ void FileIOHandler::open(IN enum UpnpOpenFileMode mode)
+     }
+ }
+ 
+-size_t FileIOHandler::read(OUT char* buf, IN size_t length)
++size_t FileIOHandler::read(char* buf, size_t length)
+ {
+     size_t ret = 0;
+ 
+@@ -77,7 +77,7 @@ size_t FileIOHandler::read(OUT char* buf, IN size_t length)
+     return ret;
+ }
+ 
+-size_t FileIOHandler::write(IN char* buf, IN size_t length)
++size_t FileIOHandler::write(char* buf, size_t length)
+ {
+     size_t ret = 0;
+ 
+@@ -86,7 +86,7 @@ size_t FileIOHandler::write(IN char* buf, IN size_t length)
+     return ret;
+ }
+ 
+-void FileIOHandler::seek(IN off_t offset, IN int whence)
++void FileIOHandler::seek(off_t offset, int whence)
+ {
+     if (fseeko(f, offset, whence) != 0) {
+         throw _Exception(_("fseek failed"));
+diff --git a/src/file_io_handler.h b/src/file_io_handler.h
+index aa3f116d..f6895f60 100644
+--- a/src/file_io_handler.h
++++ b/src/file_io_handler.h
+@@ -49,18 +49,18 @@ public:
+     explicit FileIOHandler(zmm::String filename);
+ 
+     /// \brief Opens file for reading (writing is not supported)
+-    void open(IN enum UpnpOpenFileMode mode) override;
++    void open(enum UpnpOpenFileMode mode) override;
+ 
+     /// \brief Reads a previously opened file sequentially.
+     /// \param buf Data from the file will be copied into this buffer.
+     /// \param length Number of bytes to be copied into the buffer.
+-    size_t read(OUT char* buf, IN size_t length) override;
++    size_t read(char* buf, size_t length) override;
+ 
+     /// \brief Writes to a previously opened file.
+     /// \param buf Data from the buffer will be written to the file.
+     /// \param length Number of bytes to be written from the buffer.
+     /// \return number of bytes written.
+-    size_t write(OUT char* buf, IN size_t length) override;
++    size_t write(char* buf, size_t length) override;
+ 
+     /// \brief Performs seek on an open file.
+     /// \param offset Number of bytes to move in the file. For seeking forwards
+@@ -69,7 +69,7 @@ public:
+     /// \param whence The position to move relative to. SEEK_CUR to move relative
+     /// to current position, SEEK_END to move relative to the end of file,
+     /// SEEK_SET to specify an absolute offset.
+-    void seek(IN off_t offset, IN int whence) override;
++    void seek(off_t offset, int whence) override;
+ 
+     /// \brief Close a previously opened file.
+     void close() override;
+diff --git a/src/file_request_handler.cc b/src/file_request_handler.cc
+index c4b82ccb..0ada9461 100644
+--- a/src/file_request_handler.cc
++++ b/src/file_request_handler.cc
+@@ -52,7 +52,7 @@ FileRequestHandler::FileRequestHandler(UpnpXMLBuilder* xmlBuilder)
+     : RequestHandler()
+     , xmlBuilder(xmlBuilder) {};
+ 
+-void FileRequestHandler::getInfo(IN const char* filename, OUT UpnpFileInfo* info)
++void FileRequestHandler::getInfo(const char* filename, UpnpFileInfo* info)
+ {
+     Headers headers;
+     log_debug("start\n");
+@@ -278,8 +278,8 @@ void FileRequestHandler::getInfo(IN const char* filename, OUT UpnpFileInfo* info
+     log_debug("web_get_info(): end\n");
+ }
+ 
+-Ref<IOHandler> FileRequestHandler::open(IN const char* filename,
+-    IN enum UpnpOpenFileMode mode, IN zmm::String range)
++Ref<IOHandler> FileRequestHandler::open(const char* filename,
++    enum UpnpOpenFileMode mode, zmm::String range)
+ {
+     log_debug("start\n");
+ 
+diff --git a/src/file_request_handler.h b/src/file_request_handler.h
+index fdb1b7e9..6526712c 100644
+--- a/src/file_request_handler.h
++++ b/src/file_request_handler.h
+@@ -44,11 +44,11 @@ protected:
+ public:
+     explicit FileRequestHandler(UpnpXMLBuilder* xmlBuilder);
+ 
+-    virtual void getInfo(IN const char *filename, OUT UpnpFileInfo *info);
++    virtual void getInfo(const char *filename, UpnpFileInfo *info);
+     virtual zmm::Ref<IOHandler> open(
+-        IN const char* filename,
+-        IN enum UpnpOpenFileMode mode,
+-        IN zmm::String range);
++        const char* filename,
++        enum UpnpOpenFileMode mode,
++        zmm::String range);
+ };
+ 
+ #endif // __FILE_REQUEST_HANDLER_H__
+diff --git a/src/io_handler.cc b/src/io_handler.cc
+index 3b774c73..b3c4aedb 100644
+--- a/src/io_handler.cc
++++ b/src/io_handler.cc
+@@ -42,8 +42,8 @@ IOHandler::IOHandler()
+ {
+ }
+ 
+-/// \fn static UpnpWebFileHandle web_open(IN const char *filename,
+-///                                       IN enum UpnpOpenFileMode mode)
++/// \fn static UpnpWebFileHandle web_open(const char *filename,
++///                                       enum UpnpOpenFileMode mode)
+ /// \brief Opens a file for the web server.
+ /// \param filename Name of the file to open.
+ /// \param mode in which the file will be opened (we only support UPNP_READ)
+@@ -52,12 +52,12 @@ IOHandler::IOHandler()
+ ///
+ /// \retval UpnpWebFileHandle A valid file handle.
+ /// \retval NULL Error.
+-void IOHandler::open(IN enum UpnpOpenFileMode mode)
++void IOHandler::open(enum UpnpOpenFileMode mode)
+ {
+ }
+ 
+-/// \fn static int web_read (IN UpnpWebFileHandle f, OUT char *buf,
+-///                          IN size_t length)
++/// \fn static int web_read (UpnpWebFileHandle f, char *buf,
++///                          size_t length)
+ /// \brief Reads a previously opened file sequentially.
+ /// \param f Handle of the file.
+ /// \param buf  This buffer will be filled by fread.
+@@ -69,13 +69,13 @@ void IOHandler::open(IN enum UpnpOpenFileMode mode)
+ ///
+ /// \retval 0   EOF encountered.
+ /// \retval -1  Error.
+-size_t IOHandler::read(OUT char* buf, IN size_t length)
++size_t IOHandler::read(char* buf, size_t length)
+ {
+     return -1;
+ }
+ 
+-/// \fn static int web_write (IN UpnpWebFileHandle f,IN char *buf,
+-///                           IN size_t length)
++/// \fn static int web_write (UpnpWebFileHandle f,char *buf,
++///                           size_t length)
+ /// \brief Writes to a previously opened file sequentially.
+ /// \param f Handle of the file.
+ /// \param buf This buffer will be filled by fwrite.
+@@ -90,13 +90,13 @@ size_t IOHandler::read(OUT char* buf, IN size_t length)
+ /// \retval Actual number of bytes written.
+ ///
+ /// \warning Currently this function is not supported.
+-size_t IOHandler::write(IN char* buf, IN size_t length)
++size_t IOHandler::write(char* buf, size_t length)
+ {
+     return 0;
+ }
+ 
+-/// \fn static int web_seek (IN UpnpWebFileHandle f, IN long offset,
+-///                   IN int origin)
++/// \fn static int web_seek (UpnpWebFileHandle f, long offset,
++///                   int origin)
+ /// \brief Performs a seek on an open file.
+ /// \param f Handle of the file.
+ /// \param offset Number of bytes to move in the file. For seeking forwards
+@@ -109,11 +109,11 @@ size_t IOHandler::write(IN char* buf, IN size_t length)
+ /// This function is called by the web server to perform seek on an a file.
+ ///
+ /// \retval 0 On success, non-zero value on error.
+-void IOHandler::seek(IN off_t offset, IN int whence)
++void IOHandler::seek(off_t offset, int whence)
+ {
+ }
+ 
+-/// \fn static int web_close (IN UpnpWebFileHandle f)
++/// \fn static int web_close (UpnpWebFileHandle f)
+ /// \brief Closes a previously opened file.
+ /// \param f Handle of the file.
+ ///
+diff --git a/src/io_handler_buffer_helper.cc b/src/io_handler_buffer_helper.cc
+index d86a4daf..89d22a71 100644
+--- a/src/io_handler_buffer_helper.cc
++++ b/src/io_handler_buffer_helper.cc
+@@ -60,7 +60,7 @@ IOHandlerBufferHelper::IOHandlerBufferHelper(size_t bufSize, size_t initialFillS
+     doSeek = false;
+ }
+ 
+-void IOHandlerBufferHelper::open(IN enum UpnpOpenFileMode mode)
++void IOHandlerBufferHelper::open(enum UpnpOpenFileMode mode)
+ {
+     if (isOpen)
+         throw _Exception(_("tried to reopen an open IOHandlerBufferHelper"));
+@@ -78,7 +78,7 @@ IOHandlerBufferHelper::~IOHandlerBufferHelper()
+         close();
+ }
+ 
+-size_t IOHandlerBufferHelper::read(OUT char* buf, IN size_t length)
++size_t IOHandlerBufferHelper::read(char* buf, size_t length)
+ {
+     // check read on closed BufferedIOHandler
+     assert(isOpen);
+@@ -142,7 +142,7 @@ size_t IOHandlerBufferHelper::read(OUT char* buf, IN size_t length)
+     return didRead;
+ }
+ 
+-void IOHandlerBufferHelper::seek(IN off_t offset, IN int whence)
++void IOHandlerBufferHelper::seek(off_t offset, int whence)
+ {
+     log_debug("seek called: %lld %d\n", offset, whence);
+     if (!seekEnabled)
+diff --git a/src/mem_io_handler.cc b/src/mem_io_handler.cc
+index 31028d56..3a87be82 100644
+--- a/src/mem_io_handler.cc
++++ b/src/mem_io_handler.cc
+@@ -69,12 +69,12 @@ MemIOHandler::~MemIOHandler()
+     FREE(buffer);
+ }
+ 
+-void MemIOHandler::open(IN enum UpnpOpenFileMode mode)
++void MemIOHandler::open(enum UpnpOpenFileMode mode)
+ {
+     pos = 0;
+ }
+ 
+-size_t MemIOHandler::read(OUT char* buf, IN size_t length)
++size_t MemIOHandler::read(char* buf, size_t length)
+ {
+     size_t ret = 0;
+ 
+@@ -98,7 +98,7 @@ size_t MemIOHandler::read(OUT char* buf, IN size_t length)
+     return ret;
+ }
+ 
+-void MemIOHandler::seek(IN off_t offset, IN int whence)
++void MemIOHandler::seek(off_t offset, int whence)
+ {
+     if (whence == SEEK_SET) {
+         // offset must be positive when SEEK_SET is used
+diff --git a/src/mem_io_handler.h b/src/mem_io_handler.h
+index beab8983..d2311dc9 100644
+--- a/src/mem_io_handler.h
++++ b/src/mem_io_handler.h
+@@ -53,9 +53,9 @@ public:
+     virtual ~MemIOHandler();
+ 
+     ///
+-    void open(IN enum UpnpOpenFileMode mode) override;
+-    size_t read(OUT char* buf, IN size_t length) override;
+-    void seek(IN off_t offset, IN int whence) override;
++    void open(enum UpnpOpenFileMode mode) override;
++    size_t read(char* buf, size_t length) override;
++    void seek(off_t offset, int whence) override;
+ };
+ 
+ #endif // __MEM_IO_HANDLER_H__
+diff --git a/src/metadata/taglib_handler.cc b/src/metadata/taglib_handler.cc
+index 0aa12edc..365e2f3c 100644
+--- a/src/metadata/taglib_handler.cc
++++ b/src/metadata/taglib_handler.cc
+@@ -276,7 +276,7 @@ void TagLibHandler::addArtworkResource(Ref<CdsItem> item, String art_mimetype)
+     }
+ }
+ 
+-Ref<IOHandler> TagLibHandler::serveContent(IN Ref<CdsItem> item, IN int resNum, OUT off_t* data_size)
++Ref<IOHandler> TagLibHandler::serveContent(Ref<CdsItem> item, int resNum, off_t* data_size)
+ {
+     Ref<Dictionary> mappings = ConfigManager::getInstance()->getDictionaryOption(CFG_IMPORT_MAPPINGS_MIMETYPE_TO_CONTENTTYPE_LIST);
+     String content_type = mappings->get(item->getMimeType());
+diff --git a/src/process_io_handler.cc b/src/process_io_handler.cc
+index 681c0921..c4f9ce27 100644
+--- a/src/process_io_handler.cc
++++ b/src/process_io_handler.cc
+@@ -153,7 +153,7 @@ ProcessIOHandler::ProcessIOHandler(String filename,
+     registerAll();
+ }
+ 
+-void ProcessIOHandler::open(IN enum UpnpOpenFileMode mode)
++void ProcessIOHandler::open(enum UpnpOpenFileMode mode)
+ {
+     if ((main_proc != nullptr) && ((!main_proc->isAlive() || abort()))) {
+         killall();
+@@ -180,7 +180,7 @@ void ProcessIOHandler::open(IN enum UpnpOpenFileMode mode)
+     }
+ }
+ 
+-size_t ProcessIOHandler::read(OUT char* buf, IN size_t length)
++size_t ProcessIOHandler::read(char* buf, size_t length)
+ {
+     fd_set readSet;
+     struct timeval timeout;
+@@ -279,7 +279,7 @@ size_t ProcessIOHandler::read(OUT char* buf, IN size_t length)
+     return num_bytes;
+ }
+ 
+-size_t ProcessIOHandler::write(IN char* buf, IN size_t length)
++size_t ProcessIOHandler::write(char* buf, size_t length)
+ {
+     fd_set writeSet;
+     struct timeval timeout;
+@@ -370,7 +370,7 @@ size_t ProcessIOHandler::write(IN char* buf, IN size_t length)
+     return num_bytes;
+ }
+ 
+-void ProcessIOHandler::seek(IN off_t offset, IN int whence)
++void ProcessIOHandler::seek(off_t offset, int whence)
+ {
+     // we know we can not seek in a fifo, but the PS3 asks for a hack...
+     if (!ignore_seek)
+diff --git a/src/process_io_handler.h b/src/process_io_handler.h
+index 3fbf2bd8..75a004c5 100644
+--- a/src/process_io_handler.h
++++ b/src/process_io_handler.h
+@@ -62,18 +62,18 @@ public:
+         bool ignoreSeek = false);
+ 
+     /// \brief Opens file for reading (writing is not supported)
+-    void open(IN enum UpnpOpenFileMode mode) override;
++    void open(enum UpnpOpenFileMode mode) override;
+ 
+     /// \brief Reads a previously opened file sequentially.
+     /// \param buf Data from the file will be copied into this buffer.
+     /// \param length Number of bytes to be copied into the buffer.
+-    size_t read(OUT char* buf, IN size_t length) override;
++    size_t read(char* buf, size_t length) override;
+ 
+     /// \brief Writes to a previously opened file.
+     /// \param buf Data from the buffer will be written to the file.
+     /// \param length Number of bytes to be written from the buffer.
+     /// \return number of bytes written.
+-    size_t write(OUT char* buf, IN size_t length) override;
++    size_t write(char* buf, size_t length) override;
+ 
+     /// \brief Performs seek on an open file.
+     /// \param offset Number of bytes to move in the file. For seeking forwards
+@@ -82,7 +82,7 @@ public:
+     /// \param whence The position to move relative to. SEEK_CUR to move relative
+     /// to current position, SEEK_END to move relative to the end of file,
+     /// SEEK_SET to specify an absolute offset.
+-    void seek(IN off_t offset, IN int whence) override;
++    void seek(off_t offset, int whence) override;
+ 
+     /// \brief Close a previously opened file and kills the kill_pid process
+     void close() override;
+diff --git a/src/request_handler.h b/src/request_handler.h
+index 3e274624..616cbae5 100644
+--- a/src/request_handler.h
++++ b/src/request_handler.h
+@@ -38,9 +38,9 @@
+ 
+ class RequestHandler : public zmm::Object {
+ public:
+-    virtual void getInfo(IN const char *filename, OUT UpnpFileInfo *info) = 0;
++    virtual void getInfo(const char *filename, UpnpFileInfo *info) = 0;
+ 
+-    virtual zmm::Ref<IOHandler> open(IN const char* filename, IN enum UpnpOpenFileMode mode, IN zmm::String range) = 0;
++    virtual zmm::Ref<IOHandler> open(const char* filename, enum UpnpOpenFileMode mode, zmm::String range) = 0;
+ 
+     /// \brief Splits the url into a path and parameters string.
+     /// Only '?' and '/' separators are allowed, otherwise an exception will
+diff --git a/src/serve_request_handler.cc b/src/serve_request_handler.cc
+index 94eefb44..abb005f1 100644
+--- a/src/serve_request_handler.cc
++++ b/src/serve_request_handler.cc
+@@ -44,7 +44,7 @@ ServeRequestHandler::ServeRequestHandler()
+ }
+ 
+ /// \todo clean up the fix for internal items
+-void ServeRequestHandler::getInfo(IN const char *filename, OUT UpnpFileInfo *info)
++void ServeRequestHandler::getInfo(const char *filename, UpnpFileInfo *info)
+ {
+     struct stat statbuf;
+     int ret = 0;
+@@ -100,9 +100,9 @@ void ServeRequestHandler::getInfo(IN const char *filename, OUT UpnpFileInfo *inf
+     }
+ }
+ 
+-Ref<IOHandler> ServeRequestHandler::open(IN const char* filename,
+-    IN enum UpnpOpenFileMode mode,
+-    IN zmm::String range)
++Ref<IOHandler> ServeRequestHandler::open(const char* filename,
++    enum UpnpOpenFileMode mode,
++    zmm::String range)
+ {
+     struct stat statbuf;
+     int ret = 0;
+diff --git a/src/serve_request_handler.h b/src/serve_request_handler.h
+index 3f799d8e..dce399a3 100644
+--- a/src/serve_request_handler.h
++++ b/src/serve_request_handler.h
+@@ -39,10 +39,10 @@
+ class ServeRequestHandler : public RequestHandler {
+ public:
+     ServeRequestHandler();
+-    virtual void getInfo(IN const char *filename, OUT UpnpFileInfo *info);
+-    virtual zmm::Ref<IOHandler> open(IN const char* filename,
+-        IN enum UpnpOpenFileMode mode,
+-        IN zmm::String range);
++    virtual void getInfo(const char *filename, UpnpFileInfo *info);
++    virtual zmm::Ref<IOHandler> open(const char* filename,
++        enum UpnpOpenFileMode mode,
++        zmm::String range);
+ };
+ 
+ #endif // __SERVE_REQUEST_HANDLER_H__
+diff --git a/src/server.cc b/src/server.cc
+index acbeed68..4caef731 100644
+--- a/src/server.cc
++++ b/src/server.cc
+@@ -453,9 +453,9 @@ int Server::registerVirtualDirCallbacks()
+ {
+     log_debug("Setting UpnpVirtualDir GetInfoCallback\n");
+ #ifdef UPNP_HAS_REQUEST_COOKIES
+-    int ret = UpnpVirtualDir_set_GetInfoCallback([](IN const char* filename, OUT UpnpFileInfo* info, const void* cookie, OUT const void** requestCookie) -> int {
++    int ret = UpnpVirtualDir_set_GetInfoCallback([](const char* filename, UpnpFileInfo* info, const void* cookie, const void** requestCookie) -> int {
+ #else
+-    int ret = UpnpVirtualDir_set_GetInfoCallback([](IN const char* filename, OUT UpnpFileInfo* info, const void* cookie) -> int {
++    int ret = UpnpVirtualDir_set_GetInfoCallback([](const char* filename, UpnpFileInfo* info, const void* cookie) -> int {
+ #endif
+         try {
+             Ref<RequestHandler> reqHandler = static_cast<const Server *>(cookie)->createRequestHandler(filename);
+@@ -475,9 +475,9 @@ int Server::registerVirtualDirCallbacks()
+ 
+     log_debug("Setting UpnpVirtualDir OpenCallback\n");
+ #ifdef UPNP_HAS_REQUEST_COOKIES
+-    ret = UpnpVirtualDir_set_OpenCallback([](IN const char* filename, IN enum UpnpOpenFileMode mode, IN const void* cookie, IN const void* requestCookie) -> UpnpWebFileHandle {
++    ret = UpnpVirtualDir_set_OpenCallback([](const char* filename, enum UpnpOpenFileMode mode, const void* cookie, const void* requestCookie) -> UpnpWebFileHandle {
+ #else
+-    ret = UpnpVirtualDir_set_OpenCallback([](IN const char* filename, IN enum UpnpOpenFileMode mode, IN const void* cookie) -> UpnpWebFileHandle {
++    ret = UpnpVirtualDir_set_OpenCallback([](const char* filename, enum UpnpOpenFileMode mode, const void* cookie) -> UpnpWebFileHandle {
+ #endif
+         String link = urlUnescape(zmm::String::copy(filename));
+ 
+@@ -502,9 +502,9 @@ int Server::registerVirtualDirCallbacks()
+ 
+     log_debug("Setting UpnpVirtualDir ReadCallback\n");
+ #ifdef UPNP_HAS_REQUEST_COOKIES
+-    ret = UpnpVirtualDir_set_ReadCallback([](IN UpnpWebFileHandle f, OUT char* buf, IN size_t length, IN const void* cookie, IN const void* requestCookie) -> int {
++    ret = UpnpVirtualDir_set_ReadCallback([](UpnpWebFileHandle f, char* buf, size_t length, const void* cookie, const void* requestCookie) -> int {
+ #else
+-    ret = UpnpVirtualDir_set_ReadCallback([](IN UpnpWebFileHandle f, OUT char* buf, IN size_t length, IN const void* cookie) -> int {
++    ret = UpnpVirtualDir_set_ReadCallback([](UpnpWebFileHandle f, char* buf, size_t length, const void* cookie) -> int {
+ #endif
+         //log_debug("%p read(%d)\n", f, length);
+         if (static_cast<const Server*>(cookie)->getShutdownStatus())
+@@ -518,9 +518,9 @@ int Server::registerVirtualDirCallbacks()
+ 
+     log_debug("Setting UpnpVirtualDir WriteCallback\n");
+ #ifdef UPNP_HAS_REQUEST_COOKIES
+-    ret = UpnpVirtualDir_set_WriteCallback([](IN UpnpWebFileHandle f, IN char* buf, IN size_t length, IN const void* cookie, IN const void* requestCookie) -> int {
++    ret = UpnpVirtualDir_set_WriteCallback([](UpnpWebFileHandle f, char* buf, size_t length, const void* cookie, const void* requestCookie) -> int {
+ #else
+-    ret = UpnpVirtualDir_set_WriteCallback([](IN UpnpWebFileHandle f, IN char* buf, IN size_t length, IN const void* cookie) -> int {
++    ret = UpnpVirtualDir_set_WriteCallback([](UpnpWebFileHandle f, char* buf, size_t length, const void* cookie) -> int {
+ #endif
+         //log_debug("%p write(%d)\n", f, length);
+         return 0;
+@@ -530,9 +530,9 @@ int Server::registerVirtualDirCallbacks()
+ 
+     log_debug("Setting UpnpVirtualDir SeekCallback\n");
+ #ifdef UPNP_HAS_REQUEST_COOKIES
+-    ret = UpnpVirtualDir_set_SeekCallback([](IN UpnpWebFileHandle f, IN off_t offset, IN int whence, IN const void* cookie, IN const void* requestCookie) -> int {
++    ret = UpnpVirtualDir_set_SeekCallback([](UpnpWebFileHandle f, off_t offset, int whence, const void* cookie, const void* requestCookie) -> int {
+ #else
+-    ret = UpnpVirtualDir_set_SeekCallback([](IN UpnpWebFileHandle f, IN off_t offset, IN int whence, IN const void* cookie) -> int {
++    ret = UpnpVirtualDir_set_SeekCallback([](UpnpWebFileHandle f, off_t offset, int whence, const void* cookie) -> int {
+ #endif
+         //log_debug("%p seek(%d, %d)\n", f, offset, whence);
+         try {
+@@ -551,9 +551,9 @@ int Server::registerVirtualDirCallbacks()
+ 
+     log_debug("Setting UpnpVirtualDir CloseCallback\n");
+ #ifdef UPNP_HAS_REQUEST_COOKIES
+-    UpnpVirtualDir_set_CloseCallback([](IN UpnpWebFileHandle f, IN const void* cookie, IN const void* requestCookie) -> int {
++    UpnpVirtualDir_set_CloseCallback([](UpnpWebFileHandle f, const void* cookie, const void* requestCookie) -> int {
+ #else
+-    UpnpVirtualDir_set_CloseCallback([](IN UpnpWebFileHandle f, IN const void* cookie) -> int {
++    UpnpVirtualDir_set_CloseCallback([](UpnpWebFileHandle f, const void* cookie) -> int {
+ #endif
+         //log_debug("%p close()\n", f);
+         Ref<IOHandler> handler((IOHandler*)f);
+diff --git a/src/url_request_handler.cc b/src/url_request_handler.cc
+index aeadfc8a..3193c782 100644
+--- a/src/url_request_handler.cc
++++ b/src/url_request_handler.cc
+@@ -58,7 +58,7 @@ URLRequestHandler::URLRequestHandler()
+ {
+ }
+ 
+-void URLRequestHandler::getInfo(IN const char *filename, OUT UpnpFileInfo *info)
++void URLRequestHandler::getInfo(const char *filename, UpnpFileInfo *info)
+ {
+     log_debug("start\n");
+ 
+@@ -154,9 +154,9 @@ void URLRequestHandler::getInfo(IN const char *filename, OUT UpnpFileInfo *info)
+     /// \todo transcoding for get_info
+ }
+ 
+-Ref<IOHandler> URLRequestHandler::open(IN const char* filename,
+-    IN enum UpnpOpenFileMode mode,
+-    IN String range)
++Ref<IOHandler> URLRequestHandler::open(const char* filename,
++    enum UpnpOpenFileMode mode,
++    String range)
+ {
+     int objectID;
+     String mimeType;
+diff --git a/src/url_request_handler.h b/src/url_request_handler.h
+index 8125b56b..52d75302 100644
+--- a/src/url_request_handler.h
++++ b/src/url_request_handler.h
+@@ -39,10 +39,10 @@
+ class URLRequestHandler : public RequestHandler {
+ public:
+     URLRequestHandler();
+-    virtual void getInfo(IN const char *filename, OUT UpnpFileInfo *info);
+-    virtual zmm::Ref<IOHandler> open(IN const char* filename,
+-        IN enum UpnpOpenFileMode mode,
+-        IN zmm::String range);
++    virtual void getInfo(const char *filename, UpnpFileInfo *info);
++    virtual zmm::Ref<IOHandler> open(const char* filename,
++        enum UpnpOpenFileMode mode,
++        zmm::String range);
+ };
+ 
+ #endif // __URL_REQUEST_HANDLER_H__
+diff --git a/src/util/headers.h b/src/util/headers.h
+index 97915cc6..6374c7a8 100644
+--- a/src/util/headers.h
++++ b/src/util/headers.h
+@@ -37,7 +37,7 @@ class Headers {
+ public:
+     void addHeader(zmm::String header, zmm::String value);
+     void addHeader(const std::string& header, const std::string& value);
+-    void writeHeaders(IN UpnpFileInfo *fileInfo) const;
++    void writeHeaders(UpnpFileInfo *fileInfo) const;
+ 
+ private:
+     std::unique_ptr<std::map<std::string, std::string>> headers;
+diff --git a/src/web_request_handler.cc b/src/web_request_handler.cc
+index 070f9bf1..8683b928 100644
+--- a/src/web_request_handler.cc
++++ b/src/web_request_handler.cc
+@@ -89,7 +89,7 @@ String WebRequestHandler::renderXMLHeader()
+     return _("<?xml version=\"1.0\" encoding=\"") + DEFAULT_INTERNAL_CHARSET + "\"?>\n";
+ }
+ 
+-void WebRequestHandler::getInfo(IN const char *filename, OUT UpnpFileInfo *info)
++void WebRequestHandler::getInfo(const char *filename, UpnpFileInfo *info)
+ {
+     this->filename = filename;
+ 
+@@ -122,7 +122,7 @@ void WebRequestHandler::getInfo(IN const char *filename, OUT UpnpFileInfo *info)
+     headers.writeHeaders(info);
+ }
+ 
+-Ref<IOHandler> WebRequestHandler::open(IN enum UpnpOpenFileMode mode)
++Ref<IOHandler> WebRequestHandler::open(enum UpnpOpenFileMode mode)
+ {
+     root = Ref<Element>(new Element(_("root")));
+ 
+@@ -219,9 +219,9 @@ Ref<IOHandler> WebRequestHandler::open(IN enum UpnpOpenFileMode mode)
+     return RefCast(io_handler, IOHandler);
+ }
+ 
+-Ref<IOHandler> WebRequestHandler::open(IN const char* filename,
+-    IN enum UpnpOpenFileMode mode,
+-    IN String range)
++Ref<IOHandler> WebRequestHandler::open(const char* filename,
++    enum UpnpOpenFileMode mode,
++    String range)
+ {
+     this->filename = filename;
+     this->mode = mode;
+diff --git a/src/web_request_handler.h b/src/web_request_handler.h
+index 42a38060..b9069884 100644
+--- a/src/web_request_handler.h
++++ b/src/web_request_handler.h
+@@ -101,7 +101,7 @@ protected:
+     /// \brief Prepares the output buffer and calls the process function.
+     /// \return IOHandler
+     /// \todo Genych, chto tut proishodit, ya tolkom che to ne wrubaus??
+-    zmm::Ref<IOHandler> open(IN enum UpnpOpenFileMode mode);
++    zmm::Ref<IOHandler> open(enum UpnpOpenFileMode mode);
+ 
+     /// \brief add the ui update ids from the given session as xml tags to the given root element
+     /// \param root the xml element to add the elements to
+@@ -135,15 +135,15 @@ public:
+     /// dynamic XML) we do not know the size of the data. This is of course different
+     /// for the FileRequestHandler, where we can check the file and return all
+     /// information about it.
+-    void getInfo(IN const char *filename, OUT UpnpFileInfo *info) override;
++    void getInfo(const char *filename, UpnpFileInfo *info) override;
+ 
+     /// \brief Decodes the parameters from the filename (URL) and calls the internal open() function.
+     /// \param filename The requested URL
+     /// \param mode either UPNP_READ or UPNP_WRITE
+     /// \return the appropriate IOHandler for the request.
+-    zmm::Ref<IOHandler> open(IN const char* filename,
+-        IN enum UpnpOpenFileMode mode,
+-        IN zmm::String range) override;
++    zmm::Ref<IOHandler> open(const char* filename,
++        enum UpnpOpenFileMode mode,
++        zmm::String range) override;
+ 
+     /// \brief This method must be overridden by the subclasses that actually process the given request.
+     virtual void process() = 0;
+-- 
+2.26.2
+
diff --git a/testing/gerbera/APKBUILD b/testing/gerbera/APKBUILD
new file mode 100644
index 0000000000000000000000000000000000000000..4a6ac19cf8fb43c112576a5300cccba6ded3b4fe
--- /dev/null
+++ b/testing/gerbera/APKBUILD
@@ -0,0 +1,113 @@
+# Contributor: Mike Crute <mike@crute.us>
+# Maintainer: Mike Crute <mike@crute.us>
+pkgname=gerbera
+pkgver=1.4.0
+pkgrel=0
+pkgdesc="A UPnP Media Server"
+url="https://gerbera.io"
+arch="all"
+license="GPL-2.0-or-later"
+makedepends="
+	cmake
+	curl-dev
+	duktape-dev
+	e2fsprogs-dev
+	exiv2-dev
+	ffmpeg-dev
+	ffmpegthumbnailer-dev
+	file-dev
+	fmt-dev
+	gnu-libiconv-dev
+	inotify-tools-dev
+	libexif-dev
+	libmatroska-dev
+	libupnp-dev
+	pugixml-dev
+	spdlog-dev
+	sqlite-dev
+	taglib-dev
+	zlib-dev
+	"
+checkdepends="
+	gtest-dev
+	gmock
+	"
+install="$pkgname.pre-install $pkgname.post-deinstall"
+subpackages="$pkgname-doc"
+pkgusers="$pkgname"
+pkggroups="$pkgname"
+#
+# Patches
+#
+# disable-git-test.patch:
+#	Patch removes check for git info in server version output. This assumes
+#	that the binary was built within a git repo which is not the case for
+#	releases. This test will never work for us.
+#
+# 0001-Remove-IN-and-OUT-dropped-upstream.patch: (Drop for release after 1.4.0)
+#	Removes IN and OUT macros defined by older versions of libupnp. This
+#	was fixed in upstream shortly after the 1.4.0 release. We can drop this
+#	patch after the next upstream gerbera release.
+#
+# upnp-updates.patch: (Drop for release after 1.4.0)
+#	Disables some tests that don't work with the latest version of libupnp.
+#	Upstream has very seriously overhauled these tests and there's noting
+#	feasible to pull forward. We can drop this patch after the next
+#	upstream gerbera release.
+#
+source="gerbera-$pkgver.tar.gz::https://github.com/gerbera/gerbera/archive/v$pkgver.tar.gz
+	disable-git-test.patch
+	0001-Remove-IN-and-OUT-dropped-upstream.patch
+	upnp-updates.patch
+	$pkgname.initd
+	$pkgname.confd"
+
+build() {
+	cmake -B build \
+		-Wno-dev \
+		-DCMAKE_BUILD_TYPE=None \
+		-DCMAKE_INSTALL_PREFIX=/usr \
+		-DWITH_SYSTEMD=0 \
+		-DWITH_TESTS=1 \
+		-DWITH_JS=1 \
+		-DWITH_CURL=1 \
+		-DWITH_TAGLIB=1 \
+		-DWITH_MAGIC=1 \
+		-DWITH_MATROSKA=1 \
+		-DWITH_AVCODEC=1 \
+		-DWITH_EXIF=1 \
+		-DWITH_EXIV2=1 \
+		-DWITH_FFMPEGTHUMBNAILER=1 \
+		-DWITH_INOTIFY=1
+
+	make -C build
+}
+
+check() {
+	make -C build test
+}
+
+package() {
+	make -C build DESTDIR="$pkgdir" install
+
+	"$builddir/build"/gerbera --create-config > config.xml
+	sed -i 's#<home>.*#<home>/var/lib/gerbera</home>#' config.xml
+
+	install -dm750 -o $pkgusers -g $pkggroups \
+		"$pkgdir/var/lib/$pkgname" \
+		"$pkgdir/var/log/$pkgname" \
+		"$pkgdir/etc/$pkgname"
+	install -m755 -D "$srcdir/$pkgname.initd" \
+		"$pkgdir/etc/init.d/$pkgname"
+	install -m644 -D "$srcdir/$pkgname.confd" \
+		"$pkgdir/etc/conf.d/$pkgname"
+	install -m644 -D "config.xml" \
+		"$pkgdir/etc/$pkgname/config.xml"
+}
+
+sha512sums="989716bc60bc7e171448e18aff58d8f17dbbed28ca31cfeaa7dc0e6f1cb646da88041deff6481e15ba398090a01f07e00f74b12e84c423b7ca5b82eb97b918cd  gerbera-1.4.0.tar.gz
+9037fbdc18b7af1492352abccaacca39193b16332040b02b72513ce31e47fbd56220b6c0c62a207e04fd56c4d15d5bd92910506968a4d70a66e133ba49eaeeaa  disable-git-test.patch
+47e1953c49ceae3eeaea50b4ecd2bf44d4da2286c315a3bdbfcbe7e7fc8500e2f27438acebe16f6a72a0c97efd7b8a1b185282d73b12e730e1a8fbec19c18046  0001-Remove-IN-and-OUT-dropped-upstream.patch
+e134dee2080c21a39120999d215b0ec36890bed9283a1460d9750e2b21908b3283db09d33c5ff445ae779559b5486f8c81c590c1dbde77ae3d5bb900d694d17f  upnp-updates.patch
+8ae265dd283705802d138dc014d592362b0b95030eee0999bfcf6058fa656f215a5dc11e2b548459300750be0f9e6c3d0f5047714a6fc16eeb430c40aff8d35b  gerbera.initd
+392d7e964b0328778847f871e88ffd475ddac99b6cf8c8ded4825eb2f970e084db692552790a1b30ff96f59eabcd9fff50164d9dedf328badab95a1cec833c02  gerbera.confd"
diff --git a/testing/gerbera/disable-git-test.patch b/testing/gerbera/disable-git-test.patch
new file mode 100644
index 0000000000000000000000000000000000000000..3a2bc2f4240373f290003ebd19d178f70b3c7153
--- /dev/null
+++ b/testing/gerbera/disable-git-test.patch
@@ -0,0 +1,11 @@
+--- a/test/test_server/test_main.cc.orig
++++ b/test/test_server/test_main.cc
+@@ -48,7 +48,7 @@
+   ASSERT_THAT(output.c_str(), HasSubstr(expectedOutput.c_str()));
+ }
+ 
+-TEST_F(ServerTest, ServerOutputsCompileInformationIncludingGit) {
++TEST_F(ServerTest, DISABLED_ServerOutputsCompileInformationIncludingGit) {
+   std::stringstream ss;
+   ss << CMAKE_BINARY_DIR << DIR_SEPARATOR << "gerbera --compile-info 2>&1";
+   std::string cmd = ss.str();
diff --git a/testing/gerbera/gerbera.confd b/testing/gerbera/gerbera.confd
new file mode 100644
index 0000000000000000000000000000000000000000..a8fbc699553b08517ba13af1fa2ab1f75b319002
--- /dev/null
+++ b/testing/gerbera/gerbera.confd
@@ -0,0 +1,27 @@
+# /etc/conf.d/gerbera
+
+# Enable debug log output.
+#DEBUG=no
+
+# Interface to bind to, for example eth0, this can be specified instead of the
+# IP address.
+#BIND_INTERFACE=eth0
+
+# Specify the server port that will be used for the web user interface, for
+# serving media and for UPnP requests, minimum allowed value is 49152. If this
+# option is omitted a default port will be chosen, however, in this case it is
+# possible that the port will change upon server restart.
+#BIND_PORT=49152
+
+# The server will bind to the given IP address, currently we can not bind to
+# multiple interfaces so binding to 0.0.0.0 is not be possible.
+#BIND_IP=0.0.0.0
+
+# The location of the config file
+#CONFIG="/etc/gerbera/config.xml"
+
+# Specify the user/group gerbera should run as
+#G_USER="gerbera"
+#G_GROUP="gerbera"
+
+# vim: ft=gentoo-conf-d
diff --git a/testing/gerbera/gerbera.initd b/testing/gerbera/gerbera.initd
new file mode 100644
index 0000000000000000000000000000000000000000..8356a0a2122f6726c7f2e4c04904b9f0cf8ae446
--- /dev/null
+++ b/testing/gerbera/gerbera.initd
@@ -0,0 +1,34 @@
+#!/sbin/openrc-run
+
+name="Gerbera"
+configfile="${CONFIG:-/etc/gerbera/config.xml}"
+start_stop_daemon_args="--user ${G_USER:-gerbera} --group ${j_GROUP:-gerbera}"
+pidfile="/run/gerbera/gerbera.pid"
+command=/usr/bin/gerbera
+command_args="-c $configfile -l /var/log/gerbera/gerbera.log"
+command_background=true
+
+depend() {
+	need net
+}
+
+start_pre() {
+	if ! [ -f "${configfile}" ]; then
+		/usr/sbin/gerbera --create-config > "${configfile}"
+	fi
+	if yesno "${DEBUG}"; then
+		command_args="$command_args -D"
+	fi
+	if [ ! -z "${BIND_INTERFACE}" ]; then
+		command_args="$command_args -e ${BIND_INTERFACE}"
+	fi
+	if [ ! -z "${BIND_PORT}" ]; then
+		command_args="$command_args -p ${BIND_PORT}"
+	fi
+	if [ ! -z "${BIND_IP}" ]; then
+		command_args="$command_args -i ${BIND_IP}"
+	fi
+	
+	checkpath --owner ${G_USER:-gerbera}:${G_GROUP:-gerbera} \
+		--directory ${pidfile%/*}
+}
diff --git a/testing/gerbera/gerbera.post-deinstall b/testing/gerbera/gerbera.post-deinstall
new file mode 100644
index 0000000000000000000000000000000000000000..febefd4b9cd46ba62123d91dcb211c39412fef21
--- /dev/null
+++ b/testing/gerbera/gerbera.post-deinstall
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+deluser gerbera 2>/dev/null
+delgroup gerbera 2>/dev/null
+
+exit 0
diff --git a/testing/gerbera/gerbera.pre-install b/testing/gerbera/gerbera.pre-install
new file mode 100644
index 0000000000000000000000000000000000000000..e99c58b9597819f7dea33707d83cfe5149a903ce
--- /dev/null
+++ b/testing/gerbera/gerbera.pre-install
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+addgroup -S gerbera 2>/dev/null
+adduser -S -D -H -h /var/run/gerbera -s /sbin/nologin -G gerbera \
+	-g gerbera gerbera 2>/dev/null
+
+exit 0
diff --git a/testing/gerbera/upnp-updates.patch b/testing/gerbera/upnp-updates.patch
new file mode 100644
index 0000000000000000000000000000000000000000..4cc06cfeadf3a4bf1666683d64626cf0ff37e2e9
--- /dev/null
+++ b/testing/gerbera/upnp-updates.patch
@@ -0,0 +1,54 @@
+--- a/src/util/headers.cc
++++ b/src/util/headers.cc
+@@ -81,7 +81,7 @@
+ {
+ #ifdef UPNP_HAS_EXTRA_HEADERS_LIST
+     if (headers != nullptr) {
+-        auto head = const_cast<list_head*>(UpnpFileInfo_get_ExtraHeadersList(fileInfo));
++        auto head = const_cast<UpnpListHead*>(UpnpFileInfo_get_ExtraHeadersList(fileInfo));
+         for (auto iter : *headers) {
+             UpnpExtraHeaders* h = UpnpExtraHeaders_new();
+             UpnpExtraHeaders_set_resp(h, formatHeader(iter, false).c_str());
+--- a/test/test_handler/test_http_protocol_helper.cc
++++ b/test/test_handler/test_http_protocol_helper.cc
+@@ -27,9 +27,9 @@
+       std::string out;
+
+       UpnpExtraHeaders* extra;
+-      list_head* pos;
+-      auto head = const_cast<list_head*>(UpnpFileInfo_get_ExtraHeadersList(info));
+-      list_for_each(pos, head) {
++      UpnpListHead* pos;
++      auto head = const_cast<UpnpListHead*>(UpnpFileInfo_get_ExtraHeadersList(info));
++      for (pos = UpnpListBegin(head); pos != UpnpListEnd(head); pos = UpnpListNext(head, pos)) {
+           extra = (UpnpExtraHeaders *)pos;
+           out += UpnpExtraHeaders_get_resp(extra);
+           out += "\r\n";
+@@ -61,7 +61,7 @@
+   EXPECT_STREQ(GET_HEADERS(info), "Content-Disposition: attachment; filename=\"file.mp3\"\r\n");
+ }
+
+-TEST_F(HeadersHelperTest, MultipleHeaders) {
++TEST_F(HeadersHelperTest, DISABLED_MultipleHeaders) {
+   std::string header = "Content-Disposition";
+   std::string value = "attachment; filename=\"file.mp3\"";
+   std::string header2 = "Accept-Ranges";
+@@ -74,7 +74,7 @@
+   EXPECT_STREQ(GET_HEADERS(info), "Content-Disposition: attachment; filename=\"file.mp3\"\r\nAccept-Ranges: bytes\r\n");
+ }
+
+-TEST_F(HeadersHelperTest, MultipleHeadersSingleCarriageNewLine) {
++TEST_F(HeadersHelperTest, DISABLED_MultipleHeadersSingleCarriageNewLine) {
+   std::string header = "Content-Disposition";
+   std::string value = "attachment; filename=\"file.mp3\"";
+   std::string header2 = "Accept-Ranges";
+@@ -87,7 +87,7 @@
+   EXPECT_STREQ(GET_HEADERS(info), "Content-Disposition: attachment; filename=\"file.mp3\"\r\nAccept-Ranges: bytes\r\n");
+ }
+
+-TEST_F(HeadersHelperTest, MultiBothCarriageNewLine) {
++TEST_F(HeadersHelperTest, DISABLED_MultiBothCarriageNewLine) {
+     std::string header = "Content-Disposition";
+     std::string value = "attachment; filename=\"file.mp3\"\r\n";
+     std::string header2 = "Accept-Ranges";
+