[vlc-devel] [PATCH 1/2] chromecast: move the Chromecast communication in a control interface module

Steve Lhomme robux4 at videolabs.io
Fri Jan 15 17:18:01 CET 2016


---
 modules/MODULES_LIST                              |   1 +
 modules/stream_out/Makefile.am                    |  13 +-
 modules/stream_out/chromecast/cast.cpp            | 202 ++++-----------------
 modules/stream_out/chromecast/chromecast.h        |   9 +-
 modules/stream_out/chromecast/chromecast_ctrl.cpp | 208 +++++++++++++++++++++-
 5 files changed, 251 insertions(+), 182 deletions(-)

diff --git a/modules/MODULES_LIST b/modules/MODULES_LIST
index 146fba5..442fc8a 100644
--- a/modules/MODULES_LIST
+++ b/modules/MODULES_LIST
@@ -85,6 +85,7 @@ $Id$
  * console_logger: Logger outputting in the terminal
  * croppadd: Crop/Padd image filter
  * crystalhd: crystalhd decoder
+ * ctrl_chromecast: Module to handle communication with Chromecast and redirect input playback
  * cvdsub: CVD subtitles decoder
  * cvpx_i420: filter to copy from OS X accelerated surfaces to CPU in YUV
  * d3d11_surface: Convert D3D11 GPU textures to YUV planes
diff --git a/modules/stream_out/Makefile.am b/modules/stream_out/Makefile.am
index 269354a..7e5d2b3 100644
--- a/modules/stream_out/Makefile.am
+++ b/modules/stream_out/Makefile.am
@@ -80,18 +80,23 @@ SUFFIXES += .proto .pb.cc
 %.pb.h %.pb.cc: %.proto
 	$(PROTOC) --cpp_out=. -I$(srcdir) $<
 
-libstream_out_chromecast_plugin_la_SOURCES = \
+libctrl_chromecast_plugin_la_SOURCES = \
     stream_out/chromecast/cast_channel.proto stream_out/chromecast/chromecast.h \
-    stream_out/chromecast/cast.cpp stream_out/chromecast/chromecast_ctrl.cpp \
+    stream_out/chromecast/chromecast_ctrl.cpp \
     misc/webservices/json.h misc/webservices/json.c
-nodist_libstream_out_chromecast_plugin_la_SOURCES = stream_out/chromecast/cast_channel.pb.cc
+nodist_libctrl_chromecast_plugin_la_SOURCES = stream_out/chromecast/cast_channel.pb.cc
+libctrl_chromecast_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -Istream_out/chromecast $(CHROMECAST_CFLAGS)
+libctrl_chromecast_plugin_la_LIBADD = $(CHROMECAST_LIBS) $(SOCKET_LIBS)
+CLEANFILES += $(nodist_libctrl_chromecast_plugin_la_SOURCES)
+
+libstream_out_chromecast_plugin_la_SOURCES = stream_out/chromecast/cast.cpp stream_out/chromecast/chromecast.h
 libstream_out_chromecast_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -Istream_out/chromecast $(CHROMECAST_CFLAGS)
 libstream_out_chromecast_plugin_la_LIBADD = $(CHROMECAST_LIBS) $(SOCKET_LIBS)
-CLEANFILES += $(nodist_libstream_out_chromecast_plugin_la_SOURCES)
 
 if ENABLE_SOUT
 if BUILD_CHROMECAST
 BUILT_SOURCES += stream_out/chromecast/cast_channel.pb.h
 sout_LTLIBRARIES += libstream_out_chromecast_plugin.la
+control_LTLIBRARIES += libctrl_chromecast_plugin.la
 endif
 endif
diff --git a/modules/stream_out/chromecast/cast.cpp b/modules/stream_out/chromecast/cast.cpp
index 052b685..c97511a 100644
--- a/modules/stream_out/chromecast/cast.cpp
+++ b/modules/stream_out/chromecast/cast.cpp
@@ -1,10 +1,11 @@
 /*****************************************************************************
- * cast.cpp: Chromecast module for vlc
+ * cast.cpp: Chromecast sout module for vlc
  *****************************************************************************
- * Copyright © 2014 VideoLAN
+ * Copyright © 2014-2015 VideoLAN
  *
  * Authors: Adrien Maglo <magsoft at videolan.org>
  *          Jean-Baptiste Kempf <jb at videolan.org>
+ *          Steve Lhomme <robux4 at videolabs.io>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published by
@@ -31,17 +32,14 @@
 
 #include "chromecast.h"
 
-#include <errno.h>
-
 #include <vlc_sout.h>
-#include <vlc_threads.h>
 
 #include <cassert>
 
 struct sout_stream_sys_t
 {
-    sout_stream_sys_t(intf_sys_t *intf)
-        : p_out(NULL)
+    sout_stream_sys_t(intf_sys_t *intf, sout_stream_t *sout)
+        : p_out(sout)
         , p_intf(intf)
     {
         assert(p_intf != NULL);
@@ -49,17 +47,15 @@ struct sout_stream_sys_t
     
     ~sout_stream_sys_t()
     {
-        delete p_intf;
+        sout_StreamChainDelete(p_out, p_out);
     }
 
     vlc_thread_t chromecastThread;
 
-    sout_stream_t *p_out;
+    sout_stream_t * const p_out;
     intf_sys_t * const p_intf;
 };
 
-#define HTTP_PORT               8010
-
 #define SOUT_CFG_PREFIX "sout-chromecast-"
 
 /*****************************************************************************
@@ -69,18 +65,14 @@ static int Open(vlc_object_t *);
 static void Close(vlc_object_t *);
 static void Clean(sout_stream_t *p_stream);
 
-static void *chromecastThread(void *data);
-
 static const char *const ppsz_sout_options[] = {
-    "ip", "http-port", "mux", "mime", NULL
+    "http-port", "mux", "mime", NULL
 };
 
 /*****************************************************************************
  * Module descriptor
  *****************************************************************************/
 
-#define IP_TEXT N_("Chromecast IP address")
-#define IP_LONGTEXT N_("This sets the IP adress of the Chromecast receiver.")
 #define HTTP_PORT_TEXT N_("HTTP port")
 #define HTTP_PORT_LONGTEXT N_("This sets the HTTP port of the server " \
                               "used to stream the media to the Chromecast.")
@@ -99,7 +91,6 @@ vlc_module_begin ()
     set_subcategory(SUBCAT_SOUT_STREAM)
     set_callbacks(Open, Close)
 
-    add_string(SOUT_CFG_PREFIX "ip", "", IP_TEXT, IP_LONGTEXT, false)
     add_integer(SOUT_CFG_PREFIX "http-port", HTTP_PORT, HTTP_PORT_TEXT, HTTP_PORT_LONGTEXT, false)
     add_string(SOUT_CFG_PREFIX "mux", "mp4stream", MUX_TEXT, MUX_LONGTEXT, false)
     add_string(SOUT_CFG_PREFIX "mime", "video/mp4", MIME_TEXT, MIME_LONGTEXT, false)
@@ -155,105 +146,32 @@ static int Open(vlc_object_t *p_this)
 {
     sout_stream_t *p_stream = reinterpret_cast<sout_stream_t*>(p_this);
     sout_stream_sys_t *p_sys;
-    intf_sys_t *p_intf = new(std::nothrow) intf_sys_t(p_stream);
-    if (p_intf == NULL)
-        return VLC_ENOMEM;
-    p_sys = new(std::nothrow) sout_stream_sys_t(p_intf);
-    if (p_sys == NULL)
-    {
-        delete p_intf;
-        return VLC_ENOMEM;
-    }
-    p_stream->p_sys = p_sys;
+    intf_sys_t *p_intf = NULL;
+    char *psz_mux = NULL;
+    sout_stream_t *p_sout = NULL;
+    std::stringstream ss;
 
     config_ChainParse(p_stream, SOUT_CFG_PREFIX, ppsz_sout_options, p_stream->p_cfg);
 
-    char *psz_ipChromecast = var_GetNonEmptyString(p_stream, SOUT_CFG_PREFIX "ip");
-    if (psz_ipChromecast == NULL)
-    {
-        msg_Err(p_stream, "No Chromecast receiver IP provided");
-        Clean(p_stream);
-        return VLC_EGENERIC;
-    }
-
-    p_intf->i_sock_fd = p_intf->connectChromecast(psz_ipChromecast);
-    free(psz_ipChromecast);
-    if (p_intf->i_sock_fd < 0)
-    {
-        msg_Err(p_stream, "Could not connect the Chromecast");
-        Clean(p_stream);
-        return VLC_EGENERIC;
-    }
-    p_intf->setConnectionStatus(CHROMECAST_TLS_CONNECTED);
-
-    char psz_localIP[NI_MAXNUMERICHOST];
-    if (net_GetSockAddress(p_intf->i_sock_fd, psz_localIP, NULL))
-    {
-        msg_Err(p_this, "Cannot get local IP address");
-        Clean(p_stream);
-        return VLC_EGENERIC;
-    }
-    p_intf->serverIP = psz_localIP;
-
-    char *psz_mux = var_GetNonEmptyString(p_stream, SOUT_CFG_PREFIX "mux");
-    if (psz_mux == NULL)
-    {
-        Clean(p_stream);
-        return VLC_EGENERIC;
-    }
-    char *psz_chain = NULL;
-    int i_bytes = asprintf(&psz_chain, "http{dst=:%u/stream,mux=%s}",
-                           (unsigned)var_InheritInteger(p_stream, SOUT_CFG_PREFIX"http-port"),
-                           psz_mux);
-    free(psz_mux);
-    if (i_bytes < 0)
-    {
-        Clean(p_stream);
-        return VLC_EGENERIC;
-    }
-
-    p_sys->p_out = sout_StreamChainNew(p_stream->p_sout, psz_chain, NULL, NULL);
-    free(psz_chain);
-    if (p_sys->p_out == NULL)
+    psz_mux = var_GetNonEmptyString(p_stream, SOUT_CFG_PREFIX "mux");
+    if (psz_mux == NULL || !psz_mux[0])
     {
-        Clean(p_stream);
-        return VLC_EGENERIC;
+        goto error;
     }
 
-    // Start the Chromecast event thread.
-    if (vlc_clone(&p_sys->chromecastThread, chromecastThread, p_stream,
-                  VLC_THREAD_PRIORITY_LOW))
-    {
-        msg_Err(p_stream, "Could not start the Chromecast talking thread");
-        Clean(p_stream);
-        return VLC_EGENERIC;
-    }
+    ss << "http{dst=:" << var_InheritInteger(p_stream, SOUT_CFG_PREFIX "http-port") << "/stream"
+       << ",mux=" << psz_mux
+       << ",access=http}";
 
-    /* Ugly part:
-     * We want to be sure that the Chromecast receives the first data packet sent by
-     * the HTTP server. */
-
-    // Lock the sout thread until we have sent the media loading command to the Chromecast.
-    int i_ret = 0;
-    const mtime_t deadline = mdate() + 6 * CLOCK_FREQ;
-    vlc_mutex_lock(&p_intf->lock);
-    while (p_intf->getConnectionStatus() != CHROMECAST_MEDIA_LOAD_SENT)
-    {
-        i_ret = vlc_cond_timedwait(&p_intf->loadCommandCond, &p_intf->lock, deadline);
-        if (i_ret == ETIMEDOUT)
-        {
-            msg_Err(p_stream, "Timeout reached before sending the media loading command");
-            vlc_mutex_unlock(&p_intf->lock);
-            vlc_cancel(p_sys->chromecastThread);
-            Clean(p_stream);
-            return VLC_EGENERIC;
-        }
+    p_sout = sout_StreamChainNew( p_stream->p_sout, ss.str().c_str(), NULL, NULL);
+    if (p_sout == NULL) {
+        msg_Dbg(p_stream, "could not create sout chain:%s", ss.str().c_str());
+        goto error;
     }
-    vlc_mutex_unlock(&p_intf->lock);
 
-    /* Even uglier: sleep more to let to the Chromecast initiate the connection
-     * to the http server. */
-    msleep(2 * CLOCK_FREQ);
+    p_sys = new(std::nothrow) sout_stream_sys_t(p_intf, p_sout);
+    if (unlikely(p_sys == NULL))
+        goto error;
 
     // Set the sout callbacks.
     p_stream->pf_add     = Add;
@@ -262,9 +180,17 @@ static int Open(vlc_object_t *p_this)
     p_stream->pf_flush   = Flush;
     p_stream->pf_control = Control;
 
+    p_stream->p_sys = p_sys;
+    free(psz_mux);
+
     return VLC_SUCCESS;
-}
 
+error:
+    sout_StreamChainDelete(p_sout, p_sout);
+    free(psz_mux);
+    Clean(p_stream);
+    return VLC_EGENERIC;
+}
 
 /*****************************************************************************
  * Close: destroy interface
@@ -272,24 +198,6 @@ static int Open(vlc_object_t *p_this)
 static void Close(vlc_object_t *p_this)
 {
     sout_stream_t *p_stream = reinterpret_cast<sout_stream_t*>(p_this);
-    sout_stream_sys_t *p_sys = p_stream->p_sys;
-
-    vlc_cancel(p_sys->chromecastThread);
-    vlc_join(p_sys->chromecastThread, NULL);
-
-    switch (p_sys->p_intf->getConnectionStatus())
-    {
-    case CHROMECAST_MEDIA_LOAD_SENT:
-    case CHROMECAST_APP_STARTED:
-        // Generate the close messages.
-        p_sys->p_intf->msgReceiverClose(p_sys->p_intf->appTransportId);
-        // ft
-    case CHROMECAST_AUTHENTICATED:
-        p_sys->p_intf->msgReceiverClose(DEFAULT_CHOMECAST_RECEIVER);
-        // ft
-    default:
-        break;
-    }
 
     Clean(p_stream);
 }
@@ -300,46 +208,6 @@ static void Close(vlc_object_t *p_this)
  */
 static void Clean(sout_stream_t *p_stream)
 {
-    sout_stream_sys_t *p_sys = p_stream->p_sys;
-
-    if (p_sys->p_out)
-    {
-        sout_StreamChainDelete(p_sys->p_out, p_sys->p_out);
-    }
-
-    p_sys->p_intf->disconnectChromecast();
-
-    delete p_sys;
+    delete p_stream->p_sys;
 }
 
-
-
-
-/*****************************************************************************
- * Chromecast thread
- *****************************************************************************/
-static void* chromecastThread(void* p_data)
-{
-    int canc = vlc_savecancel();
-    // Not cancellation-safe part.
-    sout_stream_t *p_stream = reinterpret_cast<sout_stream_t*>(p_data);
-    sout_stream_sys_t* p_sys = p_stream->p_sys;
-
-    p_sys->p_intf->msgAuth();
-    vlc_restorecancel(canc);
-
-    while (1)
-    {
-        p_sys->p_intf->handleMessages();
-
-        vlc_mutex_lock(&p_sys->p_intf->lock);
-        if ( p_sys->p_intf->getConnectionStatus() == CHROMECAST_CONNECTION_DEAD )
-        {
-            vlc_mutex_unlock(&p_sys->p_intf->lock);
-            break;
-        }
-        vlc_mutex_unlock(&p_sys->p_intf->lock);
-    }
-
-    return NULL;
-}
diff --git a/modules/stream_out/chromecast/chromecast.h b/modules/stream_out/chromecast/chromecast.h
index f39c7d2..759f011 100644
--- a/modules/stream_out/chromecast/chromecast.h
+++ b/modules/stream_out/chromecast/chromecast.h
@@ -30,10 +30,13 @@
 #define VLC_CHROMECAST_H
 
 #include <vlc_common.h>
+#include <vlc_interface.h>
 #include <vlc_plugin.h>
 #include <vlc_sout.h>
 #include <vlc_tls.h>
 
+#include <sstream>
+
 #include "cast_channel.pb.h"
 
 #define PACKET_HEADER_LEN 4
@@ -43,6 +46,7 @@ static const std::string DEFAULT_CHOMECAST_RECEIVER = "receiver-0";
 /* see https://developers.google.com/cast/docs/reference/messages */
 static const std::string NAMESPACE_MEDIA            = "urn:x-cast:com.google.cast.media";
 
+#define HTTP_PORT               8010
 
 // Status
 enum connection_status
@@ -57,10 +61,10 @@ enum connection_status
 
 struct intf_sys_t
 {
-    intf_sys_t(sout_stream_t * const p_stream);
+    intf_sys_t(intf_thread_t * const intf);
     ~intf_sys_t();
 
-    sout_stream_t  * const p_stream;
+    intf_thread_t  * const p_stream;
     std::string    serverIP;
     std::string appTransportId;
 
@@ -70,6 +74,7 @@ struct intf_sys_t
 
     vlc_mutex_t  lock;
     vlc_cond_t   loadCommandCond;
+    vlc_thread_t chromecastThread;
 
     void msgAuth();
     void msgReceiverClose(std::string destinationId);
diff --git a/modules/stream_out/chromecast/chromecast_ctrl.cpp b/modules/stream_out/chromecast/chromecast_ctrl.cpp
index 96bb0fe..0439b73 100644
--- a/modules/stream_out/chromecast/chromecast_ctrl.cpp
+++ b/modules/stream_out/chromecast/chromecast_ctrl.cpp
@@ -32,9 +32,11 @@
 
 #include "chromecast.h"
 
-#include <vlc_sout.h>
+#include <vlc_playlist.h>
+#include <vlc_threads.h>
 
-#include <sstream>
+#include <cassert>
+#include <cerrno>
 #ifdef HAVE_POLL
 # include <poll.h>
 #endif
@@ -46,7 +48,7 @@
 // Media player Chromecast app id
 #define APP_ID "CC1AD845" // Default media player aka DEFAULT_MEDIA_RECEIVER_APPLICATION_ID
 
-#define CHROMECAST_CONTROL_PORT 8009
+static const int CHROMECAST_CONTROL_PORT = 8009;
 
 /* deadline regarding pings sent from receiver */
 #define PING_WAIT_TIME 6000
@@ -55,13 +57,176 @@
 #define PONG_WAIT_TIME 500
 #define PONG_WAIT_RETRIES 2
 
-#define SOUT_CFG_PREFIX "sout-chromecast-"
+#define CONTROL_CFG_PREFIX "chromecast-"
 
 static const std::string NAMESPACE_DEVICEAUTH       = "urn:x-cast:com.google.cast.tp.deviceauth";
 static const std::string NAMESPACE_CONNECTION       = "urn:x-cast:com.google.cast.tp.connection";
 static const std::string NAMESPACE_HEARTBEAT        = "urn:x-cast:com.google.cast.tp.heartbeat";
 static const std::string NAMESPACE_RECEIVER         = "urn:x-cast:com.google.cast.receiver";
 
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int Open(vlc_object_t *);
+static void Close(vlc_object_t *);
+static void Clean(intf_thread_t *);
+
+static void *ChromecastThread(void *data);
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+
+#define IP_TEXT N_("Chromecast IP address")
+#define IP_LONGTEXT N_("This sets the IP adress of the Chromecast receiver.")
+#define HTTP_PORT_TEXT N_("HTTP port")
+#define HTTP_PORT_LONGTEXT N_("This sets the HTTP port of the server " \
+                              "used to stream the media to the Chromecast.")
+#define MUXER_TEXT N_("Muxer")
+#define MUXER_LONGTEXT N_("This sets the muxer used to stream to the Chromecast.")
+#define MIME_TEXT N_("MIME content type")
+#define MIME_LONGTEXT N_("This sets the media MIME content type sent to the Chromecast.")
+
+vlc_module_begin ()
+    set_shortname( N_("Chromecast") )
+    set_category( CAT_INTERFACE )
+    set_subcategory( SUBCAT_INTERFACE_CONTROL )
+    set_description( N_("Chromecast interface") )
+    set_capability( "interface", 0 )
+    add_shortcut("chromecast")
+    add_string(CONTROL_CFG_PREFIX "addr", "", IP_TEXT, IP_LONGTEXT, false)
+    add_integer(CONTROL_CFG_PREFIX "http-port", HTTP_PORT, HTTP_PORT_TEXT, HTTP_PORT_LONGTEXT, false)
+    add_string(CONTROL_CFG_PREFIX "mime", "video/x-matroska", MIME_TEXT, MIME_LONGTEXT, false)
+    add_string(CONTROL_CFG_PREFIX "mux", "avformat{mux=matroska}", MUXER_TEXT, MUXER_LONGTEXT, false)
+    set_callbacks( Open, Close )
+
+vlc_module_end ()
+
+/*****************************************************************************
+ * Open: connect to the Chromecast and initialize the sout
+ *****************************************************************************/
+int Open(vlc_object_t *p_this)
+{
+    intf_thread_t *p_intf = reinterpret_cast<intf_thread_t*>(p_this);
+    intf_sys_t *p_sys = new(std::nothrow) intf_sys_t(p_intf);
+    if (unlikely(p_sys == NULL))
+        return VLC_ENOMEM;
+
+    char *psz_ipChromecast = var_InheritString(p_intf, CONTROL_CFG_PREFIX "addr");
+    if (psz_ipChromecast == NULL)
+    {
+        msg_Err(p_intf, "No Chromecast receiver IP provided");
+        Clean(p_intf);
+        return VLC_EGENERIC;
+    }
+
+    p_sys->i_sock_fd = p_sys->connectChromecast(psz_ipChromecast);
+    free(psz_ipChromecast);
+    if (p_sys->i_sock_fd < 0)
+    {
+        msg_Err(p_intf, "Could not connect the Chromecast");
+        Clean(p_intf);
+        return VLC_EGENERIC;
+    }
+    p_sys->setConnectionStatus(CHROMECAST_TLS_CONNECTED);
+
+    char psz_localIP[NI_MAXNUMERICHOST];
+    if (net_GetSockAddress(p_sys->i_sock_fd, psz_localIP, NULL))
+    {
+        msg_Err(p_this, "Cannot get local IP address");
+        Clean(p_intf);
+        return VLC_EGENERIC;
+    }
+    p_sys->serverIP = psz_localIP;
+
+    char *psz_mux = var_InheritString(p_intf, CONTROL_CFG_PREFIX "mux");
+    if (psz_mux == NULL)
+    {
+        Clean(p_intf);
+        return VLC_EGENERIC;
+    }
+
+    // Start the Chromecast event thread.
+    if (vlc_clone(&p_sys->chromecastThread, ChromecastThread, p_intf,
+                  VLC_THREAD_PRIORITY_LOW))
+    {
+        msg_Err(p_intf, "Could not start the Chromecast talking thread");
+        Clean(p_intf);
+        return VLC_EGENERIC;
+    }
+
+    /* Ugly part:
+     * We want to be sure that the Chromecast receives the first data packet sent by
+     * the HTTP server. */
+
+    // Lock the sout thread until we have sent the media loading command to the Chromecast.
+    int i_ret = 0;
+    const mtime_t deadline = mdate() + 6 * CLOCK_FREQ;
+    vlc_mutex_lock(&p_sys->lock);
+    while (p_sys->getConnectionStatus() != CHROMECAST_MEDIA_LOAD_SENT)
+    {
+        i_ret = vlc_cond_timedwait(&p_sys->loadCommandCond, &p_sys->lock, deadline);
+        if (i_ret == ETIMEDOUT)
+        {
+            msg_Err(p_intf, "Timeout reached before sending the media loading command");
+            vlc_mutex_unlock(&p_sys->lock);
+            vlc_cancel(p_sys->chromecastThread);
+            Clean(p_intf);
+            return VLC_EGENERIC;
+        }
+    }
+    vlc_mutex_unlock(&p_sys->lock);
+
+    /* Even uglier: sleep more to let to the Chromecast initiate the connection
+     * to the http server. */
+    msleep(2 * CLOCK_FREQ);
+
+    p_intf->p_sys = p_sys;
+
+    return VLC_SUCCESS;
+}
+
+
+/*****************************************************************************
+ * Close: destroy interface
+ *****************************************************************************/
+void Close(vlc_object_t *p_this)
+{
+    intf_thread_t *p_intf = reinterpret_cast<intf_thread_t*>(p_this);
+    intf_sys_t *p_sys = p_intf->p_sys;
+
+    vlc_cancel(p_sys->chromecastThread);
+    vlc_join(p_sys->chromecastThread, NULL);
+
+    switch (p_sys->getConnectionStatus())
+    {
+    case CHROMECAST_MEDIA_LOAD_SENT:
+    case CHROMECAST_APP_STARTED:
+        // Generate the close messages.
+        p_sys->msgReceiverClose(p_sys->appTransportId);
+        // ft
+    case CHROMECAST_AUTHENTICATED:
+        p_sys->msgReceiverClose(DEFAULT_CHOMECAST_RECEIVER);
+        // ft
+    default:
+        break;
+    }
+
+    Clean(p_intf);
+}
+
+/**
+ * @brief Clean and release the variables in a sout_stream_sys_t structure
+ */
+void Clean(intf_thread_t *p_stream)
+{
+    intf_sys_t *p_sys = p_stream->p_sys;
+
+    p_sys->disconnectChromecast();
+
+    delete p_sys;
+}
+
 /**
  * @brief Build a CastMessage to send to the Chromecast
  * @param namespace_ the message namespace
@@ -91,7 +256,7 @@ void intf_sys_t::buildMessage(const std::string & namespace_,
     sendMessage(msg);
 }
 
-intf_sys_t::intf_sys_t(sout_stream_t * const p_this)
+intf_sys_t::intf_sys_t(intf_thread_t * const p_this)
  : p_stream(p_this)
  , p_tls(NULL)
  , conn_status(CHROMECAST_DISCONNECTED)
@@ -163,7 +328,7 @@ void intf_sys_t::disconnectChromecast()
  * @return the number of bytes received of -1 on error
  */
 // Use here only C linkage and POD types as this function is a cancelation point.
-extern "C" int recvPacket(sout_stream_t *p_stream, bool &b_msgReceived,
+extern "C" int recvPacket(vlc_object_t *p_stream, bool &b_msgReceived,
                           uint32_t &i_payloadSize, int i_sock_fd, vlc_tls_t *p_tls,
                           unsigned *pi_received, uint8_t *p_data, bool *pb_pingTimeout,
                           int *pi_wait_delay, int *pi_wait_retries)
@@ -509,14 +674,14 @@ void intf_sys_t::msgReceiverLaunchApp()
 
 void intf_sys_t::msgPlayerLoad()
 {
-    char *psz_mime = var_GetNonEmptyString(p_stream, SOUT_CFG_PREFIX "mime");
+    char *psz_mime = var_InheritString(p_stream, CONTROL_CFG_PREFIX "mime");
     if (psz_mime == NULL)
         return;
 
     std::stringstream ss;
     ss << "{\"type\":\"LOAD\","
        <<  "\"media\":{\"contentId\":\"http://" << serverIP << ":"
-           << var_InheritInteger(p_stream, SOUT_CFG_PREFIX"http-port")
+           << var_InheritInteger(p_stream, CONTROL_CFG_PREFIX"http-port")
            << "/stream\","
        <<             "\"streamType\":\"LIVE\","
        <<             "\"contentType\":\"" << std::string(psz_mime) << "\"},"
@@ -555,6 +720,31 @@ int intf_sys_t::sendMessage(const castchannel::CastMessage &msg)
     return VLC_EGENERIC;
 }
 
+/*****************************************************************************
+ * Chromecast thread
+ *****************************************************************************/
+static void* ChromecastThread(void* p_data)
+{
+    int canc = vlc_savecancel();
+    // Not cancellation-safe part.
+    intf_thread_t *p_stream = reinterpret_cast<intf_thread_t*>(p_data);
+    intf_sys_t *p_sys = p_stream->p_sys;
+
+    p_sys->msgAuth();
+    vlc_restorecancel(canc);
+
+    while (1)
+    {
+        p_sys->handleMessages();
+
+        vlc_mutex_locker locker(&p_sys->lock);
+        if ( p_sys->getConnectionStatus() == CHROMECAST_CONNECTION_DEAD )
+            break;
+    }
+
+    return NULL;
+}
+
 void intf_sys_t::handleMessages()
 {
     unsigned i_received = 0;
@@ -566,7 +756,7 @@ void intf_sys_t::handleMessages()
 
     bool b_msgReceived = false;
     uint32_t i_payloadSize = 0;
-    int i_ret = recvPacket(p_stream, b_msgReceived, i_payloadSize, i_sock_fd,
+    int i_ret = recvPacket(VLC_OBJECT(p_stream), b_msgReceived, i_payloadSize, i_sock_fd,
                            p_tls, &i_received, p_packet, &b_pingTimeout,
                            &i_waitdelay, &i_retries);
 
-- 
2.6.0.windows.1



More information about the vlc-devel mailing list