Commit 5fb95aaf authored by Thomas Guillem's avatar Thomas Guillem

chromecast: add a stream out proxy

This new submodule wait for all tracks to be added into the last stream out
(the http one) before running a chromecast session.

This fixes chromecast timeout errors when the session was started during the
middle of a playback and when the http sout was still empty (because no video
IFrames were available for example).

This also fixes the "You can try increasing sout-mux-caching value" error (when
the timeout came from VLC and not the CC).
parent e26d4166
......@@ -71,6 +71,7 @@ struct sout_stream_sys_t
std::string sout;
const std::string default_muxer;
const std::string default_mime;
std::string mime;
intf_sys_t * const p_intf;
const bool b_supports_video;
......@@ -79,8 +80,10 @@ struct sout_stream_sys_t
sout_stream_id_sys_t *GetSubId( sout_stream_t*, sout_stream_id_sys_t* );
bool es_changed;
bool cc_has_input;
std::vector<sout_stream_id_sys_t*> streams;
std::vector<sout_stream_id_sys_t*> out_streams;
unsigned int out_streams_added;
unsigned int transcode_attempt_idx;
States previous_state;
......@@ -100,6 +103,7 @@ static const char DEFAULT_MUXER[] = "avformat{mux=matroska,options={live=1}}";
*****************************************************************************/
static int Open(vlc_object_t *);
static void Close(vlc_object_t *);
static int ProxyOpen(vlc_object_t *);
static const char *const ppsz_sout_options[] = {
"ip", "port", "http-port", "mux", "mime", "video", NULL
......@@ -182,6 +186,11 @@ vlc_module_begin ()
CONVERSION_QUALITY_TEXT, CONVERSION_QUALITY_LONGTEXT, false );
change_integer_list(conversion_quality_list, conversion_quality_list_text)
add_submodule()
/* sout proxy that start the cc input when all streams are loaded */
add_shortcut("chromecast-proxy")
set_capability("sout stream", 0)
set_callbacks(ProxyOpen, NULL)
vlc_module_end ()
......@@ -191,6 +200,72 @@ struct sout_stream_id_sys_t
sout_stream_id_sys_t *p_sub_id;
};
static sout_stream_id_sys_t *ProxyAdd(sout_stream_t *p_stream, const es_format_t *p_fmt)
{
sout_stream_sys_t *p_sys = p_stream->p_sys;
sout_stream_id_sys_t *id = sout_StreamIdAdd(p_stream->p_next, p_fmt);
if (id)
p_sys->out_streams_added++;
return id;
}
static void ProxyDel(sout_stream_t *p_stream, sout_stream_id_sys_t *id)
{
sout_stream_sys_t *p_sys = p_stream->p_sys;
p_sys->out_streams_added--;
return sout_StreamIdDel(p_stream->p_next, id);
}
static int ProxySend(sout_stream_t *p_stream, sout_stream_id_sys_t *id,
block_t *p_buffer)
{
sout_stream_sys_t *p_sys = p_stream->p_sys;
if (p_sys->cc_has_input || p_sys->out_streams_added >= p_sys->out_streams.size())
{
int ret = sout_StreamIdSend(p_stream->p_next, id, p_buffer);
if (ret == VLC_SUCCESS && !p_sys->cc_has_input)
{
/* Start the chromecast only when all streams are added into the
* last sout (the http one) */
p_sys->p_intf->setHasInput(p_sys->mime);
p_sys->cc_has_input = true;
}
return ret;
}
else
{
block_Release(p_buffer);
return VLC_SUCCESS;
}
}
static void ProxyFlush(sout_stream_t *p_stream, sout_stream_id_sys_t *id)
{
return sout_StreamFlush(p_stream->p_next, id);
}
static int ProxyControl(sout_stream_t *p_stream, int i_query, va_list args)
{
if (!p_stream->p_next->pf_control)
return VLC_EGENERIC;
return p_stream->p_next->pf_control(p_stream->p_next, i_query, args);
}
static int ProxyOpen(vlc_object_t *p_this)
{
sout_stream_t *p_stream = reinterpret_cast<sout_stream_t*>(p_this);
p_stream->p_sys = (sout_stream_sys_t *) var_InheritAddress(p_this, SOUT_CFG_PREFIX "sys");
if (p_stream->p_sys == NULL || p_stream->p_next == NULL)
return VLC_EGENERIC;
p_stream->pf_add = ProxyAdd;
p_stream->pf_del = ProxyDel;
p_stream->pf_send = ProxySend;
p_stream->pf_flush = ProxyFlush;
p_stream->pf_control = ProxyControl;
return VLC_SUCCESS;
}
/*****************************************************************************
* Sout callbacks
*****************************************************************************/
......@@ -322,6 +397,9 @@ bool sout_stream_sys_t::startSoutChain( sout_stream_t *p_stream )
}
msg_Dbg( p_stream, "Creating chain %s", sout.c_str() );
cc_has_input = false;
out_streams_added = 0;
p_out = sout_StreamChainNew( p_stream->p_sout, sout.c_str(), NULL, NULL);
if (p_out == NULL) {
msg_Dbg(p_stream, "could not create sout chain:%s", sout.c_str());
......@@ -508,7 +586,6 @@ bool sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream )
}
ssout << "}:";
}
std::string mime;
if ( !p_original_video && default_muxer == DEFAULT_MUXER )
mime = "audio/x-matroska";
else if ( i_codec_audio == VLC_CODEC_VORBIS &&
......@@ -518,18 +595,14 @@ bool sout_stream_sys_t::UpdateOutput( sout_stream_t *p_stream )
else
mime = default_mime;
ssout << "http{dst=:" << i_port << "/stream"
ssout << "chromecast-proxy:"
<< "http{dst=:" << i_port << "/stream"
<< ",mux=" << default_muxer
<< ",access=http{mime=" << mime << "}}";
sout = ssout.str();
if ( startSoutChain( p_stream ) )
{
/* tell the chromecast to load the content */
p_intf->setHasInput( mime );
}
else
if ( !startSoutChain( p_stream ) )
{
p_intf->requestPlayerStop();
......@@ -598,7 +671,11 @@ static int Send(sout_stream_t *p_stream, sout_stream_id_sys_t *id,
int ret = sout_StreamIdSend(p_sys->p_out, next_id, p_buffer);
if (ret != VLC_SUCCESS)
{
bool was_es_changed = p_sys->es_changed;
Del(p_stream, id);
p_sys->es_changed = was_es_changed;
}
return ret;
}
......@@ -712,6 +789,13 @@ static int Open(vlc_object_t *p_this)
if (unlikely(p_sys == NULL))
goto error;
/* prevent sout-mux-caching since chromecast-proxy is already doing it */
var_Create( p_stream->p_sout, "sout-mux-caching", VLC_VAR_INTEGER );
var_SetInteger( p_stream->p_sout, "sout-mux-caching", 0 );
var_Create( p_stream->p_sout, SOUT_CFG_PREFIX "sys", VLC_VAR_ADDRESS );
var_SetAddress( p_stream->p_sout, SOUT_CFG_PREFIX "sys", p_sys );
// Set the sout callbacks.
p_stream->pf_add = Add;
p_stream->pf_del = Del;
......@@ -743,6 +827,7 @@ static void Close(vlc_object_t *p_this)
{
sout_stream_t *p_stream = reinterpret_cast<sout_stream_t*>(p_this);
var_Destroy( p_stream->p_sout, SOUT_CFG_PREFIX "sys" );
delete p_stream->p_sys;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment