Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
V
vlc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
videolan
vlc
Commits
d99478cb
Commit
d99478cb
authored
Jan 15, 2016
by
Steve Lhomme
Committed by
Jean-Baptiste Kempf
Jan 18, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chromecast: move the Chromecast communication in a control interface module
Signed-off-by:
Jean-Baptiste Kempf
<
jb@videolan.org
>
parent
80a1eb94
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
251 additions
and
182 deletions
+251
-182
modules/MODULES_LIST
modules/MODULES_LIST
+1
-0
modules/stream_out/Makefile.am
modules/stream_out/Makefile.am
+9
-4
modules/stream_out/chromecast/cast.cpp
modules/stream_out/chromecast/cast.cpp
+35
-167
modules/stream_out/chromecast/chromecast.h
modules/stream_out/chromecast/chromecast.h
+7
-2
modules/stream_out/chromecast/chromecast_ctrl.cpp
modules/stream_out/chromecast/chromecast_ctrl.cpp
+199
-9
No files found.
modules/MODULES_LIST
View file @
d99478cb
...
...
@@ -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
...
...
modules/stream_out/Makefile.am
View file @
d99478cb
...
...
@@ -80,18 +80,23 @@ SUFFIXES += .proto .pb.cc
%.pb.h %.pb.cc
:
%.proto
$(PROTOC)
--cpp_out
=
.
-I
$(srcdir)
$<
lib
stream_out
_chromecast_plugin_la_SOURCES
=
\
lib
ctrl
_chromecast_plugin_la_SOURCES
=
\
stream_out/chromecast/cast_channel.proto stream_out/chromecast/chromecast.h
\
stream_out/chromecast/c
ast.cpp stream_out/chromecast/c
hromecast_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
modules/stream_out/chromecast/cast.cpp
View file @
d99478cb
/*****************************************************************************
* cast.cpp: Chromecast module for vlc
* cast.cpp: Chromecast
sout
module for vlc
*****************************************************************************
* Copyright © 2014 VideoLAN
* Copyright © 2014
-2015
VideoLAN
*
* Authors: Adrien Maglo <magsoft@videolan.org>
* Jean-Baptiste Kempf <jb@videolan.org>
* Steve Lhomme <robux4@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
;
}
modules/stream_out/chromecast/chromecast.h
View file @
d99478cb
...
...
@@ -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
);
...
...
modules/stream_out/chromecast/chromecast_ctrl.cpp
View file @
d99478cb
...
...
@@ -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
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment