<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">p.MsoNormal,p.MsoNoSpacing{margin:0}</style>
</head>
<body><div><br></div>
<div>On Mon, Nov 26, 2018, at 16:15, Shaleen Jain wrote:<br></div>
<blockquote type="cite"><div>On Mon, 2018-11-26 at 15:48 +0100, Thomas Guillem wrote:<br></div>
<blockquote type="cite" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-color:rgb(114, 159, 207);border-left-style:solid;border-left-width:2px;padding-left:1ex;"><pre>Hello Shaleen,<br></pre><pre>Sorry for the very late review.<br></pre><pre><br></pre><pre>On Tue, Oct 23, 2018, at 07:51, Shaleen Jain wrote:<br></pre><blockquote type="cite" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-color:rgb(114, 159, 207);border-left-style:solid;border-left-width:2px;padding-left:1ex;"><pre>Add support for casting to a DLNA Media Renderers<br></pre><pre>which implement the AVTransport service with the<br></pre><pre>initial support of the default media format.<br></pre><pre>---<br></pre><pre> NEWS | 1 +<br></pre><pre> modules/MODULES_LIST | 1 +<br></pre><pre> modules/services_discovery/Makefile.am | 5 +-<br></pre><pre> modules/services_discovery/upnp.cpp | 54 ++<br></pre><pre> modules/services_discovery/upnp.hpp | 1 +<br></pre><pre> modules/stream_out/dlna/dlna.cpp | 886 ++++++++++++++++++++++++<br></pre><pre> modules/stream_out/dlna/dlna.hpp | 60 ++<br></pre><pre> modules/stream_out/dlna/dlna_common.hpp | 56 ++<br></pre><pre> 8 files changed, 1063 insertions(+), 1 deletion(-)<br></pre><pre> create mode 100644 modules/stream_out/dlna/dlna.cpp<br></pre><pre> create mode 100644 modules/stream_out/dlna/dlna.hpp<br></pre><pre> create mode 100644 modules/stream_out/dlna/dlna_common.hpp<br></pre><pre><br></pre><pre>diff --git a/NEWS b/NEWS<br></pre><pre>index 3054bb84a7..7fe0c4d39b 100644<br></pre><pre>--- a/NEWS<br></pre><pre>+++ b/NEWS<br></pre><pre>@@ -40,6 +40,7 @@ Video output:<br></pre><pre> Stream output:<br></pre><pre> * New SDI output with improved audio and ancillary support.<br></pre><pre> Candidate for deprecation of decklink vout/aout modules.<br></pre><pre>+ * Support for DLNA/UPNP renderers<br></pre><pre> <br></pre><pre> macOS:<br></pre><pre> * Remove Growl notification support<br></pre><pre>diff --git a/modules/MODULES_LIST b/modules/MODULES_LIST<br></pre><pre>index 79161ae3ed..65815ed22e 100644<br></pre><pre>--- a/modules/MODULES_LIST<br></pre><pre>+++ b/modules/MODULES_LIST<br></pre><pre>@@ -377,6 +377,7 @@ $Id$<br></pre><pre> * stream_out_delay: introduce delay in an ES when streaming<br></pre><pre> * stream_out_description: helper module for RTSP vod<br></pre><pre> * stream_out_display: displays a stream output chain<br></pre><pre>+ * stream_out_dlna: DLNA streaming output module<br></pre><pre> * stream_out_dummy: dummy stream out chain module<br></pre><pre> * stream_out_duplicate: duplicates a stream output chain<br></pre><pre> * stream_out_es: stream out module outputing ES<br></pre><pre>diff --git a/modules/services_discovery/Makefile.am b/modules/<br></pre><pre>services_discovery/Makefile.am<br></pre><pre>index f63df23b32..1b59cb1e4f 100644<br></pre><pre>--- a/modules/services_discovery/Makefile.am<br></pre><pre>+++ b/modules/services_discovery/Makefile.am<br></pre><pre>@@ -28,7 +28,10 @@ sd_LTLIBRARIES += $(LTLIBmtp)<br></pre><pre> <br></pre><pre> libupnp_plugin_la_SOURCES = services_discovery/upnp.cpp <br></pre><pre>services_discovery/upnp.hpp \<br></pre><pre> services_discovery/upnp-wrapper.hpp \<br></pre><pre>- services_discovery/upnp-wrapper.cpp<br></pre><pre>+ services_discovery/upnp-wrapper.cpp \<br></pre><pre>+ stream_out/dlna/dlna_common.hpp \<br></pre><pre>+ stream_out/dlna/dlna.hpp \<br></pre><pre>+ stream_out/dlna/dlna.cpp<br></pre><pre> libupnp_plugin_la_CXXFLAGS = $(AM_CXXFLAGS) $(UPNP_CFLAGS)<br></pre><pre> libupnp_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(sddir)'<br></pre><pre> libupnp_plugin_la_LIBADD = $(UPNP_LIBS)<br></pre><pre>diff --git a/modules/services_discovery/upnp.cpp b/modules/<br></pre><pre>services_discovery/upnp.cpp<br></pre><pre>index c1c2b947b2..bf025a6393 100644<br></pre><pre>--- a/modules/services_discovery/upnp.cpp<br></pre><pre>+++ b/modules/services_discovery/upnp.cpp<br></pre><pre>@@ -54,6 +54,40 @@ const char* SATIP_SERVER_DEVICE_TYPE = <br></pre><pre>"urn:ses-com:device:SatIPServer:1";<br></pre><pre> #define UPNP_SEARCH_TIMEOUT_SECONDS 15<br></pre><pre> #define SATIP_CHANNEL_LIST N_("SAT>IP channel list")<br></pre><pre> #define SATIP_CHANNEL_LIST_URL N_("Custom SAT>IP channel list URL")<br></pre><pre>+<br></pre><pre>+#define HTTP_PORT 7070<br></pre><pre>+<br></pre><pre>+#define HTTP_PORT_TEXT N_("HTTP port")<br></pre><pre>+#define HTTP_PORT_LONGTEXT N_("This sets the HTTP port of the local <br></pre><pre>server used to stream the media to the UPnP Renderer.")<br></pre><pre>+#define HAS_VIDEO_TEXT N_("Video")<br></pre><pre>+#define HAS_VIDEO_LONGTEXT N_("The UPnP Renderer can receive video.")<br></pre><pre>+<br></pre><pre>+#define PERF_TEXT N_( "Performance warning" )<br></pre><pre>+#define PERF_LONGTEXT N_( "Display a performance warning when <br></pre><pre>transcoding" )<br></pre><pre>+#define CONVERSION_QUALITY_TEXT N_( "Conversion quality" )<br></pre><pre>+#define CONVERSION_QUALITY_LONGTEXT N_( "Change this option to increase <br></pre><pre>conversion speed or quality." )<br></pre><pre>+<br></pre><pre>+#define IP_ADDR_TEXT N_("IP Address")<br></pre><pre>+#define IP_ADDR_LONGTEXT N_("IP Address of the UPnP Renderer.")<br></pre><pre>+#define PORT_TEXT N_("UPnP Renderer port")<br></pre><pre>+#define PORT_LONGTEXT N_("The port used to talk to the UPnP Renderer.")<br></pre><pre>+#define BASE_URL_TEXT N_("base URL")<br></pre><pre>+#define BASE_URL_LONGTEXT N_("The base Url relative to which all other <br></pre><pre>UPnP operations must be called")<br></pre><pre>+#define URL_TEXT N_("description URL")<br></pre><pre>+#define URL_LONGTEXT N_("The Url used to get the xml descriptor of the <br></pre><pre>UPnP Renderer")<br></pre><pre>+<br></pre><pre>+#if defined (__ANDROID__) || defined (__arm__) || (defined <br></pre><pre>(TARGET_OS_IPHONE) && TARGET_OS_IPHONE)<br></pre><pre>+# define CONVERSION_QUALITY_DEFAULT CONVERSION_QUALITY_LOW<br></pre><pre>+#else<br></pre><pre>+# define CONVERSION_QUALITY_DEFAULT CONVERSION_QUALITY_MEDIUM<br></pre><pre>+#endif<br></pre><pre>+static const char *const conversion_quality_list_text[] = {<br></pre><pre>+ N_( "High (high quality and high bandwidth)" ),<br></pre><pre>+ N_( "Medium (medium quality and medium bandwidth)" ),<br></pre><pre>+ N_( "Low (low quality and low bandwidth)" ),<br></pre><pre>+ N_( "Low CPU (low quality but high bandwidth)" ),<br></pre><pre>+};<br></pre><pre>+<br></pre><pre> static const char *const ppsz_satip_channel_lists[] = {<br></pre><pre> "Auto", "ASTRA_19_2E", "ASTRA_28_2E", "ASTRA_23_5E", "MasterList", <br></pre><pre>"ServerList", "CustomList"<br></pre><pre> };<br></pre><pre>@@ -147,6 +181,26 @@ vlc_module_begin()<br></pre><pre> <br></pre><pre> VLC_RD_PROBE_SUBMODULE<br></pre><pre> <br></pre><pre>+ add_submodule()<br></pre><pre>+ set_shortname("dlna")<br></pre><pre>+ set_description(N_("UPnP/DLNA stream output"))<br></pre><pre>+ set_capability("sout stream", 0)<br></pre><pre>+ add_shortcut("dlna")<br></pre><pre>+ set_category(CAT_SOUT)<br></pre><pre>+ set_subcategory(SUBCAT_SOUT_STREAM)<br></pre><pre>+ set_callbacks(DLNA::OpenSout, DLNA::CloseSout)<br></pre><pre>+<br></pre><pre>+ add_string(SOUT_CFG_PREFIX "ip", NULL, IP_ADDR_TEXT, <br></pre><pre>IP_ADDR_LONGTEXT, false)<br></pre><pre>+ add_integer(SOUT_CFG_PREFIX "port", NULL, PORT_TEXT, <br></pre><pre>PORT_LONGTEXT, false)<br></pre><pre>+ add_integer(SOUT_CFG_PREFIX "http-port", HTTP_PORT, <br></pre><pre>HTTP_PORT_TEXT, HTTP_PORT_LONGTEXT, false)<br></pre><pre>+ add_bool(SOUT_CFG_PREFIX "video", true, HAS_VIDEO_TEXT, <br></pre><pre>HAS_VIDEO_LONGTEXT, false)<br></pre><pre>+ add_string(SOUT_CFG_PREFIX "base_url", NULL, BASE_URL_TEXT, <br></pre><pre>BASE_URL_LONGTEXT, false)<br></pre><pre>+ add_string(SOUT_CFG_PREFIX "url", NULL, URL_TEXT, URL_LONGTEXT, <br></pre><pre>false)<br></pre><pre>+ add_integer(SOUT_CFG_PREFIX "show-perf-warning", 1, PERF_TEXT, <br></pre><pre>PERF_LONGTEXT, true )<br></pre><pre>+ change_private()<br></pre><pre>+ add_integer(SOUT_CFG_PREFIX "conversion-quality", <br></pre><pre>CONVERSION_QUALITY_DEFAULT,<br></pre><pre>+ CONVERSION_QUALITY_TEXT, <br></pre><pre>CONVERSION_QUALITY_LONGTEXT, false );<br></pre><pre>+ change_integer_list(conversion_quality_list, <br></pre><pre>conversion_quality_list_text)<br></pre><pre> vlc_module_end()<br></pre></blockquote><pre><br></pre><pre>These options could be merged with the chromecast.<br></pre></blockquote><div><br></div>
<div>Do you mean by having the same prefix as that of the chromecast ones?<br></div>
<div><br></div>
<blockquote type="cite" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-color:rgb(114, 159, 207);border-left-style:solid;border-left-width:2px;padding-left:1ex;"><blockquote type="cite" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-color:rgb(114, 159, 207);border-left-style:solid;border-left-width:2px;padding-left:1ex;"><pre> <br></pre><pre> /*<br></pre><pre>diff --git a/modules/services_discovery/upnp.hpp b/modules/<br></pre><pre>services_discovery/upnp.hpp<br></pre><pre>index 5a0de1f284..3b2e80b209 100644<br></pre><pre>--- a/modules/services_discovery/upnp.hpp<br></pre><pre>+++ b/modules/services_discovery/upnp.hpp<br></pre><pre>@@ -33,6 +33,7 @@<br></pre><pre> #endif<br></pre><pre> <br></pre><pre> #include "upnp-wrapper.hpp"<br></pre><pre>+#include "../stream_out/dlna/dlna_common.hpp"<br></pre><pre> <br></pre><pre> #include <vlc_url.h><br></pre><pre> #include <vlc_interrupt.h><br></pre><pre>diff --git a/modules/stream_out/dlna/dlna.cpp b/modules/stream_out/dlna/<br></pre><pre>dlna.cpp<br></pre><pre>new file mode 100644<br></pre><pre>index 0000000000..e0c266d8e3<br></pre><pre>--- /dev/null<br></pre><pre>+++ b/modules/stream_out/dlna/dlna.cpp<br></pre><pre>@@ -0,0 +1,886 @@<br></pre><pre>+/<br></pre><pre>*****************************************************************************<br></pre><pre>+ * dlna.cpp : DLNA/UPNP (renderer) sout module<br></pre><pre>+ <br></pre><pre>*****************************************************************************<br></pre><pre>+ * Copyright (C) 2004-2018 VLC authors and VideoLAN<br></pre><pre>+ *<br></pre><pre>+ * Authors: William Ung <<br></pre><div><a href="mailto:william1.ung@epitech.eu"></a><br></div>
<pre><a href="mailto:william1.ung@epitech.eu">william1.ung@epitech.eu</a><br></pre><div><a href="mailto:william1.ung@epitech.eu"></a><br></div>
<pre>><br></pre><pre>+ * Shaleen Jain <<br></pre><div><a href="mailto:shaleen@jain.sh"></a><br></div>
<pre><a href="mailto:shaleen@jain.sh">shaleen@jain.sh</a><br></pre><div><a href="mailto:shaleen@jain.sh"></a><br></div>
<pre>><br></pre><pre>+ *<br></pre><pre>+ * This program is free software; you can redistribute it and/or modify <br></pre><pre>it<br></pre><pre>+ * under the terms of the GNU Lesser General Public License as <br></pre><pre>published by<br></pre><pre>+ * the Free Software Foundation; either version 2.1 of the License, or<br></pre><pre>+ * (at your option) any later version.<br></pre><pre>+ *<br></pre><pre>+ * This program is distributed in the hope that it will be useful,<br></pre><pre>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br></pre><pre>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br></pre><pre>+ * GNU Lesser General Public License for more details.<br></pre><pre>+ *<br></pre><pre>+ * You should have received a copy of the GNU Lesser General Public <br></pre><pre>License<br></pre><pre>+ * along with this program; if not, write to the Free Software <br></pre><pre>Foundation,<br></pre><pre>+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.<br></pre><pre>+ <br></pre><pre>*****************************************************************************/<br></pre><pre>+<br></pre><pre>+#ifdef HAVE_CONFIG_H<br></pre><pre>+# include "config.h"<br></pre><pre>+#endif<br></pre><pre>+<br></pre><pre>+#include "dlna.hpp"<br></pre><pre>+<br></pre><pre>+#include <vector><br></pre><pre>+#include <string><br></pre><pre>+#include <sstream><br></pre><pre>+<br></pre><pre>+#include <vlc_dialog.h><br></pre><pre>+#include <vlc_rand.h><br></pre><pre>+#include <vlc_sout.h><br></pre><pre>+<br></pre><pre>+static const char* AV_TRANSPORT_SERVICE_TYPE = <br></pre><pre>"urn:schemas-upnp-org:service:AVTransport:1";<br></pre><pre>+static const char* CONNECTION_MANAGER_SERVICE_TYPE = <br></pre><pre>"urn:schemas-upnp-org:service:ConnectionManager:1";<br></pre><pre>+<br></pre><pre>+static const char *const ppsz_sout_options[] = {<br></pre><pre>+ "ip", "port", "http-port", "video", "base_url", "url", NULL<br></pre><pre>+};<br></pre><pre>+<br></pre><pre>+namespace DLNA<br></pre><pre>+{<br></pre><pre>+<br></pre><pre>+struct sout_stream_id_sys_t<br></pre><pre>+{<br></pre><pre>+ es_format_t fmt;<br></pre><pre>+ sout_stream_id_sys_t *p_sub_id;<br></pre><pre>+};<br></pre><pre>+<br></pre><pre>+struct sout_stream_sys_t<br></pre><pre>+{<br></pre><pre>+ sout_stream_sys_t(int http_port, bool supports_video)<br></pre><pre>+ : p_out( NULL )<br></pre><pre>+ , es_changed( true )<br></pre><pre>+ , b_supports_video( supports_video )<br></pre><pre>+ , perf_warning_shown( false )<br></pre><pre>+ , venc_opt_idx ( -1 )<br></pre><pre>+ , http_port( http_port )<br></pre><pre>+ {<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ std::shared_ptr<MediaRenderer> renderer;<br></pre><pre>+ UpnpInstanceWrapper *p_upnp;<br></pre><pre>+<br></pre><pre>+ bool canDecodeAudio( vlc_fourcc_t i_codec ) const;<br></pre><pre>+ bool canDecodeVideo( vlc_fourcc_t i_codec ) const;<br></pre><pre>+ bool startSoutChain( sout_stream_t* p_stream,<br></pre><pre>+ const std::vector<sout_stream_id_sys_t*> <br></pre><pre>&new_streams,<br></pre><pre>+ const std::string &sout );<br></pre><pre>+ void stopSoutChain( sout_stream_t* p_stream );<br></pre><pre>+ sout_stream_id_sys_t *GetSubId( sout_stream_t *p_stream,<br></pre><pre>+ sout_stream_id_sys_t *id,<br></pre><pre>+ bool update = true );<br></pre><pre>+<br></pre><pre>+ sout_stream_t *p_out;<br></pre><pre>+ bool es_changed;<br></pre><pre>+ bool b_supports_video;<br></pre><pre>+ bool perf_warning_shown;<br></pre><pre>+ int venc_opt_idx;<br></pre><pre>+ int http_port;<br></pre><pre>+ std::vector<sout_stream_id_sys_t*> streams;<br></pre><pre>+ std::vector<sout_stream_id_sys_t*> out_streams;<br></pre><pre>+<br></pre><pre>+private:<br></pre><pre>+ std::string GetVencOption( sout_stream_t *, vlc_fourcc_t *,<br></pre><pre>+ const video_format_t *, int );<br></pre><pre>+ std::string GetAcodecOption( sout_stream_t *, vlc_fourcc_t *, const <br></pre><pre>audio_format_t *, int );<br></pre><pre>+ std::string GetVcodecOption( sout_stream_t *, vlc_fourcc_t *, const <br></pre><pre>video_format_t *, int );<br></pre><pre>+ int UpdateOutput( sout_stream_t *p_stream );<br></pre><pre>+<br></pre><pre>+};<br></pre><pre>+<br></pre><pre>+char *getServerIPAddress() {<br></pre><pre>+ char *ip = NULL;<br></pre><pre>+#ifdef UPNP_ENABLE_IPV6<br></pre><pre>+#ifdef _WIN32<br></pre><pre>+ IP_ADAPTER_UNICAST_ADDRESS *p_best_ip = NULL;<br></pre><pre>+ wchar_t psz_uri[32];<br></pre><pre>+ DWORD strSize;<br></pre><pre>+ IP_ADAPTER_ADDRESSES *p_adapter, *addresses;<br></pre><pre>+<br></pre><pre>+ addresses = ListAdapters();<br></pre><pre>+ if (addresses == NULL)<br></pre><pre>+ return NULL;<br></pre><pre>+<br></pre><pre>+ p_adapter = addresses;<br></pre><pre>+ while (p_adapter != NULL)<br></pre><pre>+ {<br></pre><pre>+ if (isAdapterSuitable(p_adapter, false))<br></pre><pre>+ {<br></pre><pre>+ IP_ADAPTER_UNICAST_ADDRESS *p_unicast = p_adapter-<br></pre><blockquote type="cite" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-color:rgb(114, 159, 207);border-left-style:solid;border-left-width:2px;padding-left:1ex;"><pre>FirstUnicastAddress;<br></pre></blockquote><pre>+ while (p_unicast != NULL)<br></pre><pre>+ {<br></pre><pre>+ strSize = sizeof( psz_uri ) / sizeof( wchar_t );<br></pre><pre>+ if( WSAAddressToString( p_unicast->Address.lpSockaddr,<br></pre><pre>+ p_unicast-<br></pre><blockquote type="cite" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-color:rgb(114, 159, 207);border-left-style:solid;border-left-width:2px;padding-left:1ex;"><pre>Address.iSockaddrLength,<br></pre></blockquote><pre>+ NULL, psz_uri, &strSize ) == <br></pre><pre>0 )<br></pre><pre>+ {<br></pre><pre>+ if ( p_best_ip == NULL ||<br></pre><pre>+ p_best_ip->ValidLifetime > p_unicast-<br></pre><blockquote type="cite" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-color:rgb(114, 159, 207);border-left-style:solid;border-left-width:2px;padding-left:1ex;"><pre>ValidLifetime )<br></pre></blockquote><pre>+ {<br></pre><pre>+ p_best_ip = p_unicast;<br></pre><pre>+ }<br></pre><pre>+ }<br></pre><pre>+ p_unicast = p_unicast->Next;<br></pre><pre>+ }<br></pre><pre>+ }<br></pre><pre>+ p_adapter = p_adapter->Next;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ if (p_best_ip != NULL)<br></pre><pre>+ {<br></pre><pre>+ strSize = sizeof( psz_uri ) / sizeof( wchar_t );<br></pre><pre>+ WSAAddressToString( p_best_ip->Address.lpSockaddr,<br></pre><pre>+ p_best_ip->Address.iSockaddrLength,<br></pre><pre>+ NULL, psz_uri, &strSize );<br></pre><pre>+ free(addresses);<br></pre><pre>+ return FromWide( psz_uri );<br></pre><pre>+ }<br></pre><pre>+ free(addresses);<br></pre><pre>+ return NULL;<br></pre><pre>+#endif /* _WIN32 */<br></pre><pre>+#else /* UPNP_ENABLE_IPV6 */<br></pre><pre>+ ip = getIpv4ForMulticast();<br></pre><pre>+#endif /* UPNP_ENABLE_IPV6 */<br></pre><pre>+ if (ip == NULL)<br></pre><pre>+ {<br></pre><pre>+ ip = UpnpGetServerIpAddress();<br></pre><pre>+ }<br></pre><pre>+ return ip;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+bool sout_stream_sys_t::canDecodeAudio(vlc_fourcc_t i_codec) const<br></pre><pre>+{<br></pre><pre>+ return i_codec == VLC_CODEC_MP4A;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+bool sout_stream_sys_t::canDecodeVideo(vlc_fourcc_t i_codec) const<br></pre><pre>+{<br></pre><pre>+ return i_codec == VLC_CODEC_H264;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+bool sout_stream_sys_t::startSoutChain(sout_stream_t *p_stream,<br></pre><pre>+ const <br></pre><pre>std::vector<sout_stream_id_sys_t*> &new_streams,<br></pre><pre>+ const std::string &sout)<br></pre><pre>+{<br></pre><pre>+ msg_Dbg( p_stream, "Creating chain %s", sout.c_str() );<br></pre><pre>+ out_streams = new_streams;<br></pre><pre>+<br></pre><pre>+ p_out = sout_StreamChainNew( p_stream->p_sout, sout.c_str(), NULL, <br></pre><pre>NULL);<br></pre><pre>+ if (p_out == NULL) {<br></pre><pre>+ msg_Err(p_stream, "could not create sout chain:%s", <br></pre><pre>sout.c_str());<br></pre><pre>+ out_streams.clear();<br></pre><pre>+ return false;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ /* check the streams we can actually add */<br></pre><pre>+ for (std::vector<sout_stream_id_sys_t*>::iterator it = <br></pre><pre>out_streams.begin();<br></pre><pre>+ it != out_streams.end(); )<br></pre><pre>+ {<br></pre><pre>+ sout_stream_id_sys_t *p_sys_id = *it;<br></pre><pre>+ p_sys_id->p_sub_id = static_cast<sout_stream_id_sys_t *>(<br></pre><pre>+ sout_StreamIdAdd( p_out, &p_sys_id->fmt ) );<br></pre><pre>+ if ( p_sys_id->p_sub_id == NULL )<br></pre><pre>+ {<br></pre><pre>+ msg_Err( p_stream, "can't handle %4.4s stream",<br></pre><pre>+ (char *)&p_sys_id->fmt.i_codec );<br></pre><pre>+ es_format_Clean( &p_sys_id->fmt );<br></pre><pre>+ it = out_streams.erase( it );<br></pre><pre>+ }<br></pre><pre>+ else<br></pre><pre>+ ++it;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ if (out_streams.empty())<br></pre><pre>+ {<br></pre><pre>+ stopSoutChain( p_stream );<br></pre><pre>+ return false;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ return true;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+void sout_stream_sys_t::stopSoutChain(sout_stream_t *p_stream)<br></pre><pre>+{<br></pre><pre>+ (void) p_stream;<br></pre><pre>+<br></pre><pre>+ for ( size_t i = 0; i < out_streams.size(); i++ )<br></pre><pre>+ {<br></pre><pre>+ sout_StreamIdDel( p_out, out_streams[i]->p_sub_id );<br></pre><pre>+ out_streams[i]->p_sub_id = NULL;<br></pre><pre>+ }<br></pre><pre>+ out_streams.clear();<br></pre><pre>+ sout_StreamChainDelete( p_out, NULL );<br></pre><pre>+ p_out = NULL;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+sout_stream_id_sys_t *sout_stream_sys_t::GetSubId( sout_stream_t <br></pre><pre>*p_stream,<br></pre><pre>+ sout_stream_id_sys_t <br></pre><pre>*id,<br></pre><pre>+ bool update)<br></pre><pre>+{<br></pre><pre>+ assert( p_stream->p_sys == this );<br></pre><pre>+<br></pre><pre>+ if ( update && UpdateOutput( p_stream ) != VLC_SUCCESS )<br></pre><pre>+ return NULL;<br></pre><pre>+<br></pre><pre>+ for (size_t i = 0; i < out_streams.size(); ++i)<br></pre><pre>+ {<br></pre><pre>+ if ( id == (sout_stream_id_sys_t*) out_streams[i] )<br></pre><pre>+ return out_streams[i]->p_sub_id;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ msg_Err( p_stream, "unknown stream ID" );<br></pre><pre>+ return NULL;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+static std::string GetVencQSVH264Option( sout_stream_t * /* p_stream <br></pre><pre>*/,<br></pre><pre>+ const video_format_t * /* <br></pre><pre>p_vid */,<br></pre><pre>+ int i_quality )<br></pre><pre>+{<br></pre><pre>+ std::stringstream ssout;<br></pre><pre>+ static const char video_target_usage_quality[] = "quality";<br></pre><pre>+ static const char video_target_usage_balanced[] = "balanced";<br></pre><pre>+ static const char video_target_usage_speed[] = "speed";<br></pre><pre>+ static const char video_bitrate_high[] = "vb=8000000";<br></pre><pre>+ static const char video_bitrate_low[] = "vb=3000000";<br></pre><pre>+ const char *psz_video_target_usage;<br></pre><pre>+ const char *psz_video_bitrate;<br></pre><pre>+<br></pre><pre>+ switch ( i_quality )<br></pre><pre>+ {<br></pre><pre>+ case CONVERSION_QUALITY_HIGH:<br></pre><pre>+ psz_video_target_usage = video_target_usage_quality;<br></pre><pre>+ psz_video_bitrate = video_bitrate_high;<br></pre><pre>+ break;<br></pre><pre>+ case CONVERSION_QUALITY_MEDIUM:<br></pre><pre>+ psz_video_target_usage = video_target_usage_balanced;<br></pre><pre>+ psz_video_bitrate = video_bitrate_high;<br></pre><pre>+ break;<br></pre><pre>+ case CONVERSION_QUALITY_LOW:<br></pre><pre>+ psz_video_target_usage = video_target_usage_balanced;<br></pre><pre>+ psz_video_bitrate = video_bitrate_low;<br></pre><pre>+ break;<br></pre><pre>+ default:<br></pre><pre>+ case CONVERSION_QUALITY_LOWCPU:<br></pre><pre>+ psz_video_target_usage = video_target_usage_speed;<br></pre><pre>+ psz_video_bitrate = video_bitrate_low;<br></pre><pre>+ break;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ ssout << "venc=qsv{target-usage=" << psz_video_target_usage <<<br></pre><pre>+ "}," << psz_video_bitrate;<br></pre><pre>+ return ssout.str();<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+static std::string GetVencX264Option( sout_stream_t * /* p_stream */,<br></pre><pre>+ const video_format_t *p_vid,<br></pre><pre>+ int i_quality )<br></pre><pre>+{<br></pre><pre>+ std::stringstream ssout;<br></pre><pre>+ static const char video_x264_preset_veryfast[] = "veryfast";<br></pre><pre>+ static const char video_x264_preset_ultrafast[] = "ultrafast";<br></pre><pre>+ const char *psz_video_x264_preset;<br></pre><pre>+ unsigned i_video_x264_crf_hd, i_video_x264_crf_720p;<br></pre><pre>+<br></pre><pre>+ switch ( i_quality )<br></pre><pre>+ {<br></pre><pre>+ case CONVERSION_QUALITY_HIGH:<br></pre><pre>+ i_video_x264_crf_hd = i_video_x264_crf_720p = 21;<br></pre><pre>+ psz_video_x264_preset = video_x264_preset_veryfast;<br></pre><pre>+ break;<br></pre><pre>+ case CONVERSION_QUALITY_MEDIUM:<br></pre><pre>+ i_video_x264_crf_hd = 23;<br></pre><pre>+ i_video_x264_crf_720p = 21;<br></pre><pre>+ psz_video_x264_preset = video_x264_preset_veryfast;<br></pre><pre>+ break;<br></pre><pre>+ case CONVERSION_QUALITY_LOW:<br></pre><pre>+ i_video_x264_crf_hd = i_video_x264_crf_720p = 23;<br></pre><pre>+ psz_video_x264_preset = video_x264_preset_veryfast;<br></pre><pre>+ break;<br></pre><pre>+ default:<br></pre><pre>+ case CONVERSION_QUALITY_LOWCPU:<br></pre><pre>+ i_video_x264_crf_hd = i_video_x264_crf_720p = 23;<br></pre><pre>+ psz_video_x264_preset = video_x264_preset_ultrafast;<br></pre><pre>+ break;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ const bool b_hdres = p_vid->i_height == 0 || p_vid->i_height >= <br></pre><pre>800;<br></pre><pre>+ unsigned i_video_x264_crf = b_hdres ? i_video_x264_crf_hd : <br></pre><pre>i_video_x264_crf_720p;<br></pre><pre>+<br></pre><pre>+ ssout << "venc=x264{preset=" << psz_video_x264_preset<br></pre><pre>+ << ",crf=" << i_video_x264_crf << "}";<br></pre><pre>+ return ssout.str();<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+#ifdef __APPLE__<br></pre><pre>+static std::string GetVencAvcodecVTOption( sout_stream_t * /* p_stream <br></pre><pre>*/,<br></pre><pre>+ const video_format_t * <br></pre><pre>p_vid,<br></pre><pre>+ int i_quality )<br></pre><pre>+{<br></pre><pre>+ std::stringstream ssout;<br></pre><pre>+ ssout << <br></pre><pre>"venc=avcodec{codec=h264_videotoolbox,options{realtime=1}}";<br></pre><pre>+ switch( i_quality )<br></pre><pre>+ {<br></pre><pre>+ /* Here, performances issues won't come from videotoolbox but <br></pre><pre>from<br></pre><pre>+ * some old chromecast devices */<br></pre><pre>+<br></pre><pre>+ case CONVERSION_QUALITY_HIGH:<br></pre><pre>+ break;<br></pre><pre>+ case CONVERSION_QUALITY_MEDIUM:<br></pre><pre>+ ssout << ",vb=8000000";<br></pre><pre>+ break;<br></pre><pre>+ case CONVERSION_QUALITY_LOW:<br></pre><pre>+ case CONVERSION_QUALITY_LOWCPU:<br></pre><pre>+ ssout << ",vb=3000000";<br></pre><pre>+ break;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ return ssout.str();<br></pre><pre>+}<br></pre><pre>+#endif<br></pre><pre>+<br></pre><pre>+static struct<br></pre><pre>+{<br></pre><pre>+ vlc_fourcc_t fcc;<br></pre><pre>+ std::string (*get_opt)( sout_stream_t *, const video_format_t *, <br></pre><pre>int);<br></pre><pre>+} venc_opt_list[] = {<br></pre><pre>+#ifdef __APPLE__<br></pre><pre>+ { .fcc = VLC_CODEC_H264, .get_opt = GetVencAvcodecVTOption },<br></pre><pre>+#endif<br></pre><pre>+ { .fcc = VLC_CODEC_H264, .get_opt = GetVencQSVH264Option },<br></pre><pre>+ { .fcc = VLC_CODEC_H264, .get_opt = GetVencX264Option },<br></pre><pre>+ { .fcc = VLC_CODEC_H264, .get_opt = NULL },<br></pre><pre>+};<br></pre><pre>+<br></pre><pre>+std::string<br></pre><pre>+sout_stream_sys_t::GetVencOption( sout_stream_t *p_stream, vlc_fourcc_t <br></pre><pre>*p_codec_video,<br></pre><pre>+ const video_format_t *p_vid, int <br></pre><pre>i_quality )<br></pre><pre>+{<br></pre><pre>+ for( size_t i = (venc_opt_idx == -1 ? 0 : venc_opt_idx);<br></pre><pre>+ i < ARRAY_SIZE(venc_opt_list); ++i )<br></pre><pre>+ {<br></pre><pre>+ std::stringstream ssout, ssvenc;<br></pre><pre>+ char fourcc[5];<br></pre><pre>+ ssvenc << "vcodec=";<br></pre><pre>+ vlc_fourcc_to_char( venc_opt_list[i].fcc, fourcc );<br></pre><pre>+ fourcc[4] = '\0';<br></pre><pre>+ ssvenc << fourcc << ',';<br></pre><pre>+<br></pre><pre>+ if( venc_opt_list[i].get_opt != NULL )<br></pre><pre>+ ssvenc << venc_opt_list[i].get_opt( p_stream, p_vid, <br></pre><pre>i_quality ) << ',';<br></pre><pre>+<br></pre><pre>+ if( venc_opt_list[i].get_opt == NULL<br></pre><pre>+ || ( venc_opt_idx != -1 && (unsigned) venc_opt_idx == i) )<br></pre><pre>+ {<br></pre><pre>+ venc_opt_idx = i;<br></pre><pre>+ *p_codec_video = venc_opt_list[i].fcc;<br></pre><pre>+ return ssvenc.str();<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ /* Test if a module can encode with the specified options / <br></pre><pre>fmt_video. */<br></pre><pre>+ ssout << "transcode{" << ssvenc.str() << "}:dummy";<br></pre><pre>+<br></pre><pre>+ sout_stream_t *p_sout_test =<br></pre><pre>+ sout_StreamChainNew( p_stream->p_sout, ssout.str().c_str(), <br></pre><pre>NULL, NULL );<br></pre><pre>+<br></pre><pre>+ if( p_sout_test != NULL )<br></pre><pre>+ {<br></pre><pre>+ p_sout_test->obj.flags |= OBJECT_FLAGS_QUIET|<br></pre><pre>OBJECT_FLAGS_NOINTERACT;<br></pre><pre>+<br></pre><pre>+ es_format_t fmt;<br></pre><pre>+ es_format_InitFromVideo( &fmt, p_vid );<br></pre><pre>+ fmt.i_codec = fmt.video.i_chroma = VLC_CODEC_I420;<br></pre><pre>+<br></pre><pre>+ /* Test the maximum size/fps we will encode */<br></pre><pre>+ fmt.video.i_visible_width = fmt.video.i_width = 1920;<br></pre><pre>+ fmt.video.i_visible_height = fmt.video.i_height = 1080;<br></pre><pre>+ fmt.video.i_frame_rate = 30;<br></pre><pre>+ fmt.video.i_frame_rate_base = 1;<br></pre><pre>+<br></pre><pre>+ void *id = sout_StreamIdAdd( p_sout_test, &fmt );<br></pre><pre>+<br></pre><pre>+ es_format_Clean( &fmt );<br></pre><pre>+ const bool success = id != NULL;<br></pre><pre>+<br></pre><pre>+ if( id )<br></pre><pre>+ sout_StreamIdDel( p_sout_test, id );<br></pre><pre>+ sout_StreamChainDelete( p_sout_test, NULL );<br></pre><pre>+<br></pre><pre>+ if( success )<br></pre><pre>+ {<br></pre><pre>+ venc_opt_idx = i;<br></pre><pre>+ *p_codec_video = venc_opt_list[i].fcc;<br></pre><pre>+ return ssvenc.str();<br></pre><pre>+ }<br></pre><pre>+ }<br></pre><pre>+ }<br></pre><pre>+ vlc_assert_unreachable();<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+std::string<br></pre><pre>+sout_stream_sys_t::GetVcodecOption( sout_stream_t *p_stream, <br></pre><pre>vlc_fourcc_t *p_codec_video,<br></pre><pre>+ const video_format_t *p_vid, int <br></pre><pre>i_quality )<br></pre><pre>+{<br></pre><pre>+ std::stringstream ssout;<br></pre><pre>+ static const char video_maxres_hd[] = <br></pre><pre>"maxwidth=1920,maxheight=1080";<br></pre><pre>+ static const char video_maxres_720p[] = <br></pre><pre>"maxwidth=1280,maxheight=720";<br></pre><pre>+<br></pre><pre>+ ssout << GetVencOption( p_stream, p_codec_video, p_vid, <br></pre><pre>i_quality );<br></pre><pre>+<br></pre><pre>+ switch ( i_quality )<br></pre><pre>+ {<br></pre><pre>+ case CONVERSION_QUALITY_HIGH:<br></pre><pre>+ case CONVERSION_QUALITY_MEDIUM:<br></pre><pre>+ ssout << ( ( p_vid->i_width > 1920 ) ? "width=1920," : "" ) <br></pre><pre><< video_maxres_hd << ',';<br></pre><pre>+ break;<br></pre><pre>+ default:<br></pre><pre>+ ssout << ( ( p_vid->i_width > 1280 ) ? "width=1280," : "" ) <br></pre><pre><< video_maxres_720p << ',';<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ if( p_vid->i_frame_rate == 0 || p_vid->i_frame_rate_base == 0<br></pre><pre>+ || ( p_vid->i_frame_rate / p_vid->i_frame_rate_base ) > 30 )<br></pre><pre>+ {<br></pre><pre>+ /* Even force 24fps if the frame rate is unknown */<br></pre><pre>+ msg_Warn( p_stream, "lowering frame rate to 24fps" );<br></pre><pre>+ ssout << "fps=24,";<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ msg_Dbg( p_stream, "Converting video to %.4s", (const <br></pre><pre>char*)p_codec_video );<br></pre><pre>+<br></pre><pre>+ return ssout.str();<br></pre><pre>+}<br></pre></blockquote><pre><br></pre><pre>GetVencOption() and hardware specific encoder functions are the same than the chromecast ones, right ?<br></pre><pre>They should be factorized. I'm afraid we'll forget to check for upnp when we do a fix on the chromecast sout (or vice-versa).<br></pre><pre><br></pre><pre>The functions could be moved on a separate file, like stream_out/renderer_common.c/.h<br></pre><pre><br></pre></blockquote><pre><br></pre><pre>There is a slight difference, only H264 encoders are used and the VP8 encoder option is removed.<br></pre><pre><br></pre><pre>Maybe only refactor the individual encoder option functions and have different GetVencOption()<br></pre><pre>or maybe just the venc_opt_list struct.<br></pre></blockquote><div><br></div>
<div>I would see something like that:<br></div>
<div><br></div>
<div>char *vlc_sout_renderer_GetEncOption(sout_stream_t *stream, vlc_fourcc_t fourcc);<br></div>
<div><br></div>
<div>Renderer module will call this function for each encoding codec: H264,VPX,MP3,AAC.<br></div>
<div>Chromecast won't call it for AAC, by upnp and maybe airplay will.<br></div>
<div><br></div>
<div>For H264, this function should return the good encoder string: x264,qsv,vt or mediacodec.<br></div>
<div><br></div>
<blockquote type="cite"><pre><br></pre><pre><br></pre><blockquote type="cite" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-color:rgb(114, 159, 207);border-left-style:solid;border-left-width:2px;padding-left:1ex;"><blockquote type="cite" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-color:rgb(114, 159, 207);border-left-style:solid;border-left-width:2px;padding-left:1ex;"><pre>+<br></pre><pre>+std::string<br></pre><pre>+sout_stream_sys_t::GetAcodecOption( sout_stream_t *p_stream, <br></pre><pre>vlc_fourcc_t *p_codec_audio,<br></pre><pre>+ const audio_format_t *p_aud, int <br></pre><pre>i_quality )<br></pre><pre>+{<br></pre><pre>+ VLC_UNUSED(p_aud);<br></pre><pre>+ VLC_UNUSED(i_quality);<br></pre><pre>+ std::stringstream ssout;<br></pre><pre>+<br></pre><pre>+ msg_Dbg( p_stream, "Converting audio to %.4s", (const <br></pre><pre>char*)p_codec_audio );<br></pre><pre>+<br></pre><pre>+ ssout << "acodec=";<br></pre><pre>+ char fourcc[5];<br></pre><pre>+ vlc_fourcc_to_char( *p_codec_audio, fourcc );<br></pre><pre>+ fourcc[4] = '\0';<br></pre><pre>+ ssout << fourcc << ',';<br></pre><pre>+<br></pre><pre>+ return ssout.str();<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+int sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream )<br></pre><pre>+{<br></pre><pre>+ assert( p_stream->p_sys == this );<br></pre><pre>+<br></pre><pre>+ if ( !es_changed )<br></pre><pre>+ return VLC_SUCCESS;<br></pre><pre>+<br></pre><pre>+ es_changed = false;<br></pre><pre>+<br></pre><pre>+ bool canRemux = true;<br></pre><pre>+ // To keep track of which stream needs transcoding if at all.<br></pre><pre>+ vlc_fourcc_t i_codec_video = 0, i_codec_audio = 0;<br></pre><pre>+ const es_format_t *p_original_audio = NULL;<br></pre><pre>+ const es_format_t *p_original_video = NULL;<br></pre><pre>+ std::vector<sout_stream_id_sys_t*> new_streams;<br></pre><pre>+<br></pre><pre>+ for (sout_stream_id_sys_t *stream : streams)<br></pre><pre>+ {<br></pre><pre>+ const es_format_t *p_es = &stream->fmt;<br></pre><pre>+ if (p_es->i_cat == AUDIO_ES)<br></pre><pre>+ {<br></pre><pre>+ if (!canDecodeAudio( p_es->i_codec ))<br></pre><pre>+ {<br></pre><pre>+ msg_Dbg( p_stream, "can't remux audio track %d codec <br></pre><pre>%4.4s",<br></pre><pre>+ p_es->i_id, (const char*)&p_es->i_codec );<br></pre><pre>+ p_original_audio = p_es;<br></pre><pre>+ canRemux = false;<br></pre><pre>+ }<br></pre><pre>+ else if (i_codec_audio == 0)<br></pre><pre>+ {<br></pre><pre>+ i_codec_audio = p_es->i_codec;<br></pre><pre>+ }<br></pre><pre>+ new_streams.push_back(stream);<br></pre><pre>+ }<br></pre><pre>+ else if (b_supports_video && p_es->i_cat == VIDEO_ES)<br></pre><pre>+ {<br></pre><pre>+ if (!canDecodeVideo( p_es->i_codec ))<br></pre><pre>+ {<br></pre><pre>+ msg_Dbg( p_stream, "can't remux video track %d codec <br></pre><pre>%4.4s",<br></pre><pre>+ p_es->i_id, (const char*)&p_es->i_codec );<br></pre><pre>+ p_original_video = p_es;<br></pre><pre>+ canRemux = false;<br></pre><pre>+ }<br></pre><pre>+ else if (i_codec_video == 0)<br></pre><pre>+ {<br></pre><pre>+ i_codec_video = p_es->i_codec;<br></pre><pre>+ }<br></pre><pre>+ new_streams.push_back(stream);<br></pre><pre>+ }<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ if (new_streams.empty())<br></pre><pre>+ return VLC_SUCCESS;<br></pre><pre>+<br></pre><pre>+ std::ostringstream ssout;<br></pre><pre>+ if ( !canRemux )<br></pre><pre>+ {<br></pre><pre>+ if ( !perf_warning_shown && i_codec_video == 0 && <br></pre><pre>p_original_video<br></pre><pre>+ && var_InheritInteger( p_stream, SOUT_CFG_PREFIX "show-perf-<br></pre><pre>warning" ) )<br></pre><pre>+ {<br></pre><pre>+ int res = vlc_dialog_wait_question( p_stream,<br></pre><pre>+ VLC_DIALOG_QUESTION_WARNING,<br></pre><pre>+ _("Cancel"), _("OK"), _("Ok, Don't warn me <br></pre><pre>again"),<br></pre><pre>+ _("Performance warning"),<br></pre><pre>+ _("Casting this video requires conversion. "<br></pre><pre>+ "This conversion can use all the available <br></pre><pre>power and "<br></pre><pre>+ "could quickly drain your battery." ) );<br></pre><pre>+ if ( res <= 0 )<br></pre><pre>+ return false;<br></pre><pre>+ perf_warning_shown = true;<br></pre><pre>+ if ( res == 2 )<br></pre><pre>+ config_PutInt(SOUT_CFG_PREFIX "show-perf-warning", 0 );<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ const int i_quality = var_InheritInteger( p_stream, <br></pre><pre>SOUT_CFG_PREFIX "conversion-quality" );<br></pre><pre>+<br></pre><pre>+ /* TODO: provide audio samplerate and channels */<br></pre><pre>+ ssout << "transcode{";<br></pre><pre>+ if ( i_codec_audio == 0 && p_original_audio )<br></pre><pre>+ {<br></pre><pre>+ i_codec_audio = VLC_CODEC_MP4A;<br></pre><pre>+ ssout << GetAcodecOption( p_stream, &i_codec_audio,<br></pre><pre>+ &p_original_audio->audio, <br></pre><pre>i_quality );<br></pre><pre>+ }<br></pre><pre>+ if ( i_codec_video == 0 && p_original_video )<br></pre><pre>+ {<br></pre><pre>+ i_codec_video = VLC_CODEC_H264;<br></pre><pre>+ ssout << GetVcodecOption( p_stream, &i_codec_video,<br></pre><pre>+ &p_original_video->video, <br></pre><pre>i_quality );<br></pre><pre>+ }<br></pre><pre>+ ssout << "}:";<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ std::ostringstream ss;<br></pre><pre>+ ss << "/dlna"<br></pre><pre>+ << "/" << vlc_tick_now()<br></pre><pre>+ << "/" << static_cast<uint64_t>( vlc_mrand48() )<br></pre><pre>+ << "/stream";<br></pre><pre>+ std::string root_url = ss.str();<br></pre><pre>+<br></pre><pre>+ ssout << "http{dst=:" << http_port << root_url<br></pre><pre>+ << ",mux=" << "mp4stream"<br></pre><pre>+ << ",access=http{mime=" << "video/mp4" << "}}";<br></pre><pre>+<br></pre><pre>+ char *ip = getServerIPAddress();<br></pre><pre>+ if (ip == NULL)<br></pre><pre>+ {<br></pre><pre>+ msg_Err(p_stream, "could not get the local ip address");<br></pre><pre>+ return VLC_EGENERIC;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ char *uri;<br></pre><pre>+ if (asprintf(&uri, "<br></pre><div><a href="http://%s:%d%s"></a><br></div>
<pre><a href="http://%s:%d%s">http://%s:%d%s</a><br></pre><div><a href="http://%s:%d%s"></a><br></div>
<pre>", ip, http_port, <br></pre><pre>root_url.c_str()) < 0) {<br></pre><pre>+ return VLC_ENOMEM;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ if ( !startSoutChain( p_stream, new_streams, ssout.str() ) )<br></pre><pre>+ return VLC_EGENERIC;<br></pre><pre>+<br></pre><pre>+ msg_Dbg(p_stream, "AVTransportURI: %s", uri);<br></pre><pre>+ renderer->Stop();<br></pre><pre>+ renderer->SetAVTransportURI(uri);<br></pre><pre>+ renderer->Play("1");<br></pre><pre>+<br></pre><pre>+ free(uri);<br></pre><pre>+ return VLC_SUCCESS;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+char *MediaRenderer::getServiceURL(const char* type, const char <br></pre><pre>*service)<br></pre><pre>+{<br></pre><pre>+ IXML_Document *p_description_doc = NULL;<br></pre><pre>+ if (UpnpDownloadXmlDoc(device_url.c_str(), &p_description_doc) != <br></pre><pre>UPNP_E_SUCCESS)<br></pre><pre>+ return NULL;<br></pre><pre>+<br></pre><pre>+ IXML_NodeList* p_device_list = <br></pre><pre>ixmlDocument_getElementsByTagName( p_description_doc, "device");<br></pre><pre>+ free(p_description_doc);<br></pre><pre>+ if ( !p_device_list )<br></pre><pre>+ return NULL;<br></pre><pre>+<br></pre><pre>+ for (unsigned int i = 0; i < ixmlNodeList_length(p_device_list); +<br></pre><pre>+i)<br></pre><pre>+ {<br></pre><pre>+ IXML_Element* p_device_element = ( IXML_Element* ) <br></pre><pre>ixmlNodeList_item( p_device_list, i );<br></pre><pre>+ if( !p_device_element )<br></pre><pre>+ continue;<br></pre><pre>+<br></pre><pre>+ IXML_NodeList* p_service_list = <br></pre><pre>ixmlElement_getElementsByTagName( p_device_element, "service" );<br></pre><pre>+ if ( !p_service_list )<br></pre><pre>+ continue;<br></pre><pre>+ for ( unsigned int j = 0; j < <br></pre><pre>ixmlNodeList_length( p_service_list ); j++ )<br></pre><pre>+ {<br></pre><pre>+ IXML_Element* p_service_element = <br></pre><pre>(IXML_Element*)ixmlNodeList_item( p_service_list, j );<br></pre><pre>+<br></pre><pre>+ const char* psz_service_type = <br></pre><pre>xml_getChildElementValue( p_service_element, "serviceType" );<br></pre><pre>+ if ( !psz_service_type || !strstr(psz_service_type, type))<br></pre><pre>+ continue;<br></pre><pre>+ const char* psz_control_url = <br></pre><pre>xml_getChildElementValue( p_service_element,<br></pre><pre>+ <br></pre><pre>service );<br></pre><pre>+ if ( !psz_control_url )<br></pre><pre>+ continue;<br></pre><pre>+<br></pre><pre>+ char* psz_url = ( char* ) malloc( base_url.length() + <br></pre><pre>strlen( psz_control_url ) + 1 );<br></pre><pre>+ if ( psz_url && UpnpResolveURL( base_url.c_str(), <br></pre><pre>psz_control_url, psz_url ) == UPNP_E_SUCCESS )<br></pre><pre>+ return psz_url;<br></pre><pre>+ return NULL;<br></pre><pre>+ }<br></pre><pre>+ }<br></pre><pre>+ return NULL;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+/**<br></pre><pre>+ * Send an action to the control url of the service specified.<br></pre><pre>+ *<br></pre><pre>+ * \return the response as a IXML document or NULL for failure<br></pre><pre>+ **/<br></pre><pre>+IXML_Document *MediaRenderer::SendAction(const char* action_name,const <br></pre><pre>char *service_type,<br></pre><pre>+ std::list<std::pair<const char*, const char*>> <br></pre><pre>arguments)<br></pre><pre>+{<br></pre><pre>+ /* Create action */<br></pre><pre>+ IXML_Document *action = UpnpMakeAction(action_name, service_type, <br></pre><pre>0, NULL);<br></pre><pre>+<br></pre><pre>+ /* Add argument to action */<br></pre><pre>+ for (std::pair<const char*, const char*> arg : arguments) {<br></pre><pre>+ const char *arg_name, *arg_val;<br></pre><pre>+ arg_name = arg.first;<br></pre><pre>+ arg_val = arg.second;<br></pre><pre>+ UpnpAddToAction(&action, action_name, service_type, arg_name, <br></pre><pre>arg_val);<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ /* Get the controlURL of the service */<br></pre><pre>+ char *control_url = getServiceURL(service_type, "controlURL");<br></pre><pre>+<br></pre><pre>+ /* Send action */<br></pre><pre>+ IXML_Document *response = NULL;<br></pre><pre>+ int ret = UpnpSendAction(handle, control_url, service_type,<br></pre><pre>+ NULL, action, &response);<br></pre><pre>+<br></pre><pre>+ /* Free action */<br></pre><pre>+ if (action) ixmlDocument_free(action);<br></pre><pre>+ if (control_url) free(control_url);<br></pre><pre>+<br></pre><pre>+ if (ret != UPNP_E_SUCCESS) {<br></pre><pre>+ msg_Err(parent, "Unable to send action: %s (%d: %s) response: <br></pre><pre>%s",<br></pre><pre>+ action_name, ret, UpnpGetErrorMessage(ret), <br></pre><pre>ixmlPrintDocument(response));<br></pre><pre>+ if (response) ixmlDocument_free(response);<br></pre><pre>+ return NULL;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ return response;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+int MediaRenderer::Play(const char *speed)<br></pre><pre>+{<br></pre><pre>+ std::list<std::pair<const char*, const char*>> arg_list;<br></pre><pre>+ arg_list.push_back(std::make_pair("InstanceID", "0"));<br></pre><pre>+ arg_list.push_back(std::make_pair("Speed", speed));<br></pre><pre>+<br></pre><pre>+ IXML_Document *p_response = SendAction("Play", <br></pre><pre>AV_TRANSPORT_SERVICE_TYPE, arg_list);<br></pre><pre>+ if(!p_response)<br></pre><pre>+ {<br></pre><pre>+ return VLC_EGENERIC;<br></pre><pre>+ }<br></pre><pre>+ ixmlDocument_free(p_response);<br></pre><pre>+ return VLC_SUCCESS;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+int MediaRenderer::Stop()<br></pre><pre>+{<br></pre><pre>+ std::list<std::pair<const char*, const char*>> arg_list;<br></pre><pre>+ arg_list.push_back(std::make_pair("InstanceID", "0"));<br></pre><pre>+<br></pre><pre>+ IXML_Document *p_response = SendAction("Stop", <br></pre><pre>AV_TRANSPORT_SERVICE_TYPE, arg_list);<br></pre><pre>+ if(!p_response)<br></pre><pre>+ {<br></pre><pre>+ return VLC_EGENERIC;<br></pre><pre>+ }<br></pre><pre>+ ixmlDocument_free(p_response);<br></pre><pre>+ return VLC_SUCCESS;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+int MediaRenderer::SetAVTransportURI(const char* uri)<br></pre><pre>+{<br></pre><pre>+ std::list<std::pair<const char*, const char*>> arg_list;<br></pre><pre>+ arg_list.push_back(std::make_pair("InstanceID", "0"));<br></pre><pre>+ arg_list.push_back(std::make_pair("CurrentURI", uri));<br></pre><pre>+ arg_list.push_back(std::make_pair("CurrentURIMetaData", "")); // <br></pre><pre>NOT_IMPLEMENTED<br></pre><pre>+<br></pre><pre>+ IXML_Document *p_response = SendAction("SetAVTransportURI",<br></pre><pre>+ AV_TRANSPORT_SERVICE_TYPE, <br></pre><pre>arg_list);<br></pre><pre>+ if(!p_response)<br></pre><pre>+ {<br></pre><pre>+ return VLC_EGENERIC;<br></pre><pre>+ }<br></pre><pre>+ ixmlDocument_free(p_response);<br></pre><pre>+ return VLC_SUCCESS;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+static void *Add(sout_stream_t *p_stream, const es_format_t *p_fmt)<br></pre><pre>+{<br></pre><pre>+ sout_stream_sys_t *p_sys = static_cast<sout_stream_sys_t <br></pre><pre>*>( p_stream->p_sys );<br></pre><pre>+<br></pre><pre>+ if (!p_sys->b_supports_video)<br></pre><pre>+ {<br></pre><pre>+ if (p_fmt->i_cat != AUDIO_ES)<br></pre><pre>+ return NULL;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ sout_stream_id_sys_t *p_sys_id = (sout_stream_id_sys_t <br></pre><pre>*)malloc(sizeof(sout_stream_id_sys_t));<br></pre><pre>+ if(p_sys_id != NULL)<br></pre><pre>+ {<br></pre><pre>+ es_format_Copy(&p_sys_id->fmt, p_fmt);<br></pre><pre>+ p_sys_id->p_sub_id = NULL;<br></pre><pre>+ p_sys->streams.push_back(p_sys_id);<br></pre><pre>+ p_sys->es_changed = true;<br></pre><pre>+ }<br></pre><pre>+ return p_sys_id;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+static int Send(sout_stream_t *p_stream, void *id,<br></pre><pre>+ block_t *p_buffer)<br></pre><pre>+{<br></pre><pre>+ sout_stream_sys_t *p_sys = static_cast<sout_stream_sys_t <br></pre><pre>*>( p_stream->p_sys );<br></pre><pre>+ sout_stream_id_sys_t *id_sys = <br></pre><pre>static_cast<sout_stream_id_sys_t*>( id );<br></pre><pre>+<br></pre><pre>+ id_sys = p_sys->GetSubId( p_stream, id_sys );<br></pre><pre>+ if ( id_sys == NULL )<br></pre><pre>+ return VLC_EGENERIC;<br></pre><pre>+<br></pre><pre>+ return sout_StreamIdSend(p_sys->p_out, id_sys, p_buffer);<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+static void Flush( sout_stream_t *p_stream, void *id )<br></pre><pre>+{<br></pre><pre>+ sout_stream_sys_t *p_sys = static_cast<sout_stream_sys_t <br></pre><pre>*>( p_stream->p_sys );<br></pre><pre>+ sout_stream_id_sys_t *id_sys = <br></pre><pre>static_cast<sout_stream_id_sys_t*>( id );<br></pre><pre>+<br></pre><pre>+ id_sys = p_sys->GetSubId( p_stream, id_sys, false );<br></pre><pre>+ if ( id_sys == NULL )<br></pre><pre>+ return;<br></pre><pre>+<br></pre><pre>+ sout_StreamFlush( p_sys->p_out, id_sys );<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+static void Del(sout_stream_t *p_stream, void *_id)<br></pre><pre>+{<br></pre><pre>+ sout_stream_sys_t *p_sys = static_cast<sout_stream_sys_t <br></pre><pre>*>( p_stream->p_sys );<br></pre><pre>+ sout_stream_id_sys_t *id = static_cast<sout_stream_id_sys_t <br></pre><pre>*>( _id );<br></pre><pre>+<br></pre><pre>+ for (std::vector<sout_stream_id_sys_t*>::iterator it = p_sys-<br></pre><blockquote type="cite" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-color:rgb(114, 159, 207);border-left-style:solid;border-left-width:2px;padding-left:1ex;"><pre>streams.begin();<br></pre></blockquote><pre>+ it != p_sys->streams.end(); )<br></pre><pre>+ {<br></pre><pre>+ sout_stream_id_sys_t *p_sys_id = *it;<br></pre><pre>+ if ( p_sys_id == id )<br></pre><pre>+ {<br></pre><pre>+ if ( p_sys_id->p_sub_id != NULL )<br></pre><pre>+ {<br></pre><pre>+ sout_StreamIdDel( p_sys->p_out, p_sys_id->p_sub_id );<br></pre><pre>+ for (std::vector<sout_stream_id_sys_t*>::iterator <br></pre><pre>out_it = p_sys->out_streams.begin();<br></pre><pre>+ out_it != p_sys->out_streams.end(); )<br></pre><pre>+ {<br></pre><pre>+ if (*out_it == id)<br></pre><pre>+ {<br></pre><pre>+ p_sys->out_streams.erase(out_it);<br></pre><pre>+ break;<br></pre><pre>+ }<br></pre><pre>+ out_it++;<br></pre><pre>+ }<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ es_format_Clean( &p_sys_id->fmt );<br></pre><pre>+ free( p_sys_id );<br></pre><pre>+ p_sys->streams.erase( it );<br></pre><pre>+ break;<br></pre><pre>+ }<br></pre><pre>+ it++;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ if (p_sys->out_streams.empty())<br></pre><pre>+ {<br></pre><pre>+ p_sys->stopSoutChain(p_stream);<br></pre><pre>+ p_sys->renderer->Stop();<br></pre><pre>+ }<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+int OpenSout( vlc_object_t *p_this )<br></pre><pre>+{<br></pre><pre>+ sout_stream_t *p_stream = reinterpret_cast<sout_stream_t*>(p_this);<br></pre><pre>+ sout_stream_sys_t *p_sys = NULL;<br></pre><pre>+<br></pre><pre>+ config_ChainParse(p_stream, SOUT_CFG_PREFIX, ppsz_sout_options, <br></pre><pre>p_stream->p_cfg);<br></pre><pre>+<br></pre><pre>+ int http_port = var_InheritInteger(p_stream, SOUT_CFG_PREFIX "http-<br></pre><pre>port");<br></pre><pre>+ bool b_supports_video = var_GetBool(p_stream, SOUT_CFG_PREFIX <br></pre><pre>"video");<br></pre><pre>+ char *base_url = var_GetNonEmptyString(p_stream, SOUT_CFG_PREFIX <br></pre><pre>"base_url");<br></pre><pre>+ char *device_url = var_GetNonEmptyString(p_stream, SOUT_CFG_PREFIX <br></pre><pre>"url");<br></pre><pre>+ if ( device_url == NULL)<br></pre><pre>+ {<br></pre><pre>+ msg_Err( p_stream, "missing Url" );<br></pre><pre>+ goto error;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ try {<br></pre><pre>+ p_sys = new sout_stream_sys_t(http_port, b_supports_video);<br></pre><pre>+ }<br></pre><pre>+ catch ( const std::exception& ex ) {<br></pre><pre>+ msg_Err( p_stream, "Failed to instantiate sout_stream_sys_t: <br></pre><pre>%s", ex.what() );<br></pre><pre>+ return VLC_EGENERIC;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ p_sys->p_upnp = UpnpInstanceWrapper::get( p_this );<br></pre><pre>+ if ( !p_sys->p_upnp )<br></pre><pre>+ goto error;<br></pre><pre>+ try {<br></pre><pre>+ p_sys->renderer = std::make_shared<MediaRenderer>(p_stream,<br></pre><pre>+ p_sys->p_upnp, base_url, device_url);<br></pre><pre>+ }<br></pre><pre>+ catch ( const std::bad_alloc& ) {<br></pre><pre>+ msg_Err( p_stream, "Failed to create a MediaRenderer");<br></pre><pre>+ p_sys->p_upnp->release();<br></pre><pre>+ goto error;<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ p_stream->pf_add = Add;<br></pre><pre>+ p_stream->pf_del = Del;<br></pre><pre>+ p_stream->pf_send = Send;<br></pre><pre>+ p_stream->pf_flush = Flush;<br></pre><pre>+<br></pre><pre>+ p_stream->p_sys = p_sys;<br></pre><pre>+<br></pre><pre>+ free(base_url);<br></pre><pre>+ free(device_url);<br></pre><pre>+<br></pre><pre>+ return VLC_SUCCESS;<br></pre><pre>+<br></pre><pre>+error:<br></pre><pre>+ free(base_url);<br></pre><pre>+ free(device_url);<br></pre><pre>+ delete p_sys;<br></pre><pre>+ return VLC_EGENERIC;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+void CloseSout( vlc_object_t *p_this)<br></pre><pre>+{<br></pre><pre>+ sout_stream_t *p_stream = <br></pre><pre>reinterpret_cast<sout_stream_t*>( p_this );<br></pre><pre>+ sout_stream_sys_t *p_sys = static_cast<sout_stream_sys_t <br></pre><pre>*>( p_stream->p_sys );<br></pre><pre>+<br></pre><pre>+ p_sys->p_upnp->release();<br></pre><pre>+ delete p_sys;<br></pre><pre>+}<br></pre><pre>+<br></pre><pre>+}<br></pre><pre>diff --git a/modules/stream_out/dlna/dlna.hpp b/modules/stream_out/dlna/<br></pre><pre>dlna.hpp<br></pre><pre>new file mode 100644<br></pre><pre>index 0000000000..59ff3d6c8d<br></pre><pre>--- /dev/null<br></pre><pre>+++ b/modules/stream_out/dlna/dlna.hpp<br></pre><pre>@@ -0,0 +1,60 @@<br></pre><pre>+/<br></pre><pre>*****************************************************************************<br></pre><pre>+ * dlna.hpp : DLNA/UPNP (renderer) sout module header<br></pre><pre>+ <br></pre><pre>*****************************************************************************<br></pre><pre>+ * Copyright (C) 2004-2018 VLC authors and VideoLAN<br></pre><pre>+ *<br></pre><pre>+ * Authors: William Ung <<br></pre><div><a href="mailto:william1.ung@epitech.eu"></a><br></div>
<pre><a href="mailto:william1.ung@epitech.eu">william1.ung@epitech.eu</a><br></pre><div><a href="mailto:william1.ung@epitech.eu"></a><br></div>
<pre>><br></pre><pre>+ * Shaleen Jain <<br></pre><div><a href="mailto:shaleen@jain.sh"></a><br></div>
<pre><a href="mailto:shaleen@jain.sh">shaleen@jain.sh</a><br></pre><div><a href="mailto:shaleen@jain.sh"></a><br></div>
<pre>><br></pre><pre>+ *<br></pre><pre>+ * This program is free software; you can redistribute it and/or modify <br></pre><pre>it<br></pre><pre>+ * under the terms of the GNU Lesser General Public License as <br></pre><pre>published by<br></pre><pre>+ * the Free Software Foundation; either version 2.1 of the License, or<br></pre><pre>+ * (at your option) any later version.<br></pre><pre>+ *<br></pre><pre>+ * This program is distributed in the hope that it will be useful,<br></pre><pre>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br></pre><pre>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br></pre><pre>+ * GNU Lesser General Public License for more details.<br></pre><pre>+ *<br></pre><pre>+ * You should have received a copy of the GNU Lesser General Public <br></pre><pre>License<br></pre><pre>+ * along with this program; if not, write to the Free Software <br></pre><pre>Foundation,<br></pre><pre>+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.<br></pre><pre>+ <br></pre><pre>*****************************************************************************/<br></pre><pre>+<br></pre><pre>+#ifndef DLNA_H<br></pre><pre>+#define DLNA_H<br></pre><pre>+<br></pre><pre>+#include "../../services_discovery/upnp-wrapper.hpp"<br></pre><pre>+#include "dlna_common.hpp"<br></pre><pre>+<br></pre><pre>+namespace DLNA<br></pre><pre>+{<br></pre><pre>+<br></pre><pre>+class MediaRenderer<br></pre><pre>+{<br></pre><pre>+public:<br></pre><pre>+ MediaRenderer(sout_stream_t *p_stream, UpnpInstanceWrapper *upnp,<br></pre><pre>+ std::string base_url, std::string device_url)<br></pre><pre>+ : parent(p_stream)<br></pre><pre>+ , base_url(base_url)<br></pre><pre>+ , device_url(device_url)<br></pre><pre>+ , handle(upnp->handle())<br></pre><pre>+ {<br></pre><pre>+ }<br></pre><pre>+<br></pre><pre>+ sout_stream_t *parent;<br></pre><pre>+ std::string base_url;<br></pre><pre>+ std::string device_url;<br></pre><pre>+ UpnpClient_Handle handle;<br></pre><pre>+<br></pre><pre>+ char *getServiceURL(const char* type, const char* service);<br></pre><pre>+ IXML_Document *SendAction(const char* action_name, const char <br></pre><pre>*service_type,<br></pre><pre>+ std::list<std::pair<const char*, const char*>> <br></pre><pre>arguments);<br></pre><pre>+<br></pre><pre>+ int Play(const char *speed);<br></pre><pre>+ int Stop();<br></pre><pre>+ int SetAVTransportURI(const char* uri);<br></pre><pre>+};<br></pre><pre>+<br></pre><pre>+}<br></pre><pre>+#endif /* DLNA_H */<br></pre><pre>diff --git a/modules/stream_out/dlna/dlna_common.hpp b/modules/<br></pre><pre>stream_out/dlna/dlna_common.hpp<br></pre><pre>new file mode 100644<br></pre><pre>index 0000000000..a09283255e<br></pre><pre>--- /dev/null<br></pre><pre>+++ b/modules/stream_out/dlna/dlna_common.hpp<br></pre><pre>@@ -0,0 +1,56 @@<br></pre><pre>+/<br></pre><pre>*****************************************************************************<br></pre><pre>+ * dlna.hpp : DLNA/UPNP (renderer) sout module header<br></pre><pre>+ <br></pre><pre>*****************************************************************************<br></pre><pre>+ * Copyright (C) 2004-2018 VLC authors and VideoLAN<br></pre><pre>+ *<br></pre><pre>+ * Authors: William Ung <<br></pre><div><a href="mailto:william1.ung@epitech.eu"></a><br></div>
<pre><a href="mailto:william1.ung@epitech.eu">william1.ung@epitech.eu</a><br></pre><div><a href="mailto:william1.ung@epitech.eu"></a><br></div>
<pre>><br></pre><pre>+ * Shaleen Jain <<br></pre><div><a href="mailto:shaleen@jain.sh"></a><br></div>
<pre><a href="mailto:shaleen@jain.sh">shaleen@jain.sh</a><br></pre><div><a href="mailto:shaleen@jain.sh"></a><br></div>
<pre>><br></pre><pre>+ *<br></pre><pre>+ * This program is free software; you can redistribute it and/or modify <br></pre><pre>it<br></pre><pre>+ * under the terms of the GNU Lesser General Public License as <br></pre><pre>published by<br></pre><pre>+ * the Free Software Foundation; either version 2.1 of the License, or<br></pre><pre>+ * (at your option) any later version.<br></pre><pre>+ *<br></pre><pre>+ * This program is distributed in the hope that it will be useful,<br></pre><pre>+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br></pre><pre>+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br></pre><pre>+ * GNU Lesser General Public License for more details.<br></pre><pre>+ *<br></pre><pre>+ * You should have received a copy of the GNU Lesser General Public <br></pre><pre>License<br></pre><pre>+ * along with this program; if not, write to the Free Software <br></pre><pre>Foundation,<br></pre><pre>+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.<br></pre><pre>+ <br></pre><pre>*****************************************************************************/<br></pre><pre>+<br></pre><pre>+#ifndef DLNA_COMMON_H<br></pre><pre>+#define DLNA_COMMON_H<br></pre><pre>+<br></pre><pre>+#include <list><br></pre><pre>+<br></pre><pre>+#include <vlc_common.h><br></pre><pre>+#include <vlc_fourcc.h><br></pre><pre>+<br></pre><pre>+enum {<br></pre><pre>+ CONVERSION_QUALITY_HIGH = 0,<br></pre><pre>+ CONVERSION_QUALITY_MEDIUM = 1,<br></pre><pre>+ CONVERSION_QUALITY_LOW = 2,<br></pre><pre>+ CONVERSION_QUALITY_LOWCPU = 3,<br></pre><pre>+};<br></pre><pre>+<br></pre><pre>+static const int conversion_quality_list[] = {<br></pre><pre>+ CONVERSION_QUALITY_HIGH,<br></pre><pre>+ CONVERSION_QUALITY_MEDIUM,<br></pre><pre>+ CONVERSION_QUALITY_LOW,<br></pre><pre>+ CONVERSION_QUALITY_LOWCPU,<br></pre><pre>+};<br></pre><pre>+<br></pre><pre>+#define SOUT_CFG_PREFIX "sout-dlna-"<br></pre><pre>+<br></pre><pre>+namespace DLNA<br></pre><pre>+{<br></pre><pre>+<br></pre><pre>+/* module callbacks */<br></pre><pre>+int OpenSout(vlc_object_t *);<br></pre><pre>+void CloseSout(vlc_object_t *);<br></pre><pre>+<br></pre><pre>+}<br></pre><pre>+#endif /* DLNA_COMMON_H */<br></pre><pre>-- <br></pre><pre>2.19.1<br></pre><pre><br></pre><pre>_______________________________________________<br></pre><pre>vlc-devel mailing list<br></pre><pre>To unsubscribe or modify your subscription options:<br></pre><div><a href="https://mailman.videolan.org/listinfo/vlc-devel"></a><br></div>
<pre><a href="https://mailman.videolan.org/listinfo/vlc-devel">https://mailman.videolan.org/listinfo/vlc-devel</a><br></pre><div><a href="https://mailman.videolan.org/listinfo/vlc-devel"></a><br></div>
<pre><br></pre></blockquote><pre><br></pre><pre>_______________________________________________<br></pre><pre>vlc-devel mailing list<br></pre><pre>To unsubscribe or modify your subscription options:<br></pre><div><a href="https://mailman.videolan.org/listinfo/vlc-devel"></a><br></div>
<pre><a href="https://mailman.videolan.org/listinfo/vlc-devel">https://mailman.videolan.org/listinfo/vlc-devel</a><br></pre><div><a href="https://mailman.videolan.org/listinfo/vlc-devel"></a><br></div>
</blockquote><div><div><span></span><br></div>
<pre><span>-- </span><br></pre><div style="width:71ch;"><span>Regards,</span><br></div>
<div style="width:71ch;"><span>Shaleen Jain</span><br></div>
<div><span></span><br></div>
</div>
<div><u>_______________________________________________</u><br></div>
<div>vlc-devel mailing list<br></div>
<div>To unsubscribe or modify your subscription options:<br></div>
<div><a href="https://mailman.videolan.org/listinfo/vlc-devel">https://mailman.videolan.org/listinfo/vlc-devel</a><br></div>
</blockquote><div><br></div>
</body>
</html>