Commit 5725edf9 authored by Mirsal Ennaime's avatar Mirsal Ennaime

upnp sd: Add support for Samsung devices' subtitles extensions

 * Request the sec:CaptionInfo and sec:CaptionInfoEx DIDL attributes
 * If one of the two caption attributes are present, build and add an
   input-slave option string which forces the subtitle demux
 * Add the sub-track-id option to input items with subtitles
   so the subtitles are immediately visible
parent 41271ce9
......@@ -791,7 +791,8 @@ bool MediaServer::_fetchContents( Container* p_parent, int i_offset )
IXML_Document* p_response = _browseAction( p_parent->getObjectID(),
"BrowseDirectChildren",
"*", /* Filter */
"id,dc:title,res," /* Filter */
"sec:CaptionInfo,sec:CaptionInfoEx",
psz_starting_index, /* StartingIndex */
"0", /* RequestedCount */
"" /* SortCriteria */
......@@ -874,6 +875,13 @@ bool MediaServer::_fetchContents( Container* p_parent, int i_offset )
if ( !title )
continue;
const char* psz_subtitles = xml_getChildElementValue( itemElement,
"sec:CaptionInfo" );
if ( !psz_subtitles )
psz_subtitles = xml_getChildElementValue( itemElement,
"sec:CaptionInfoEx" );
/* Try to extract all resources in DIDL */
IXML_NodeList* p_resource_list = ixmlDocument_getElementsByTagName( (IXML_Document*) itemElement, "res" );
if ( p_resource_list )
......@@ -897,7 +905,8 @@ bool MediaServer::_fetchContents( Container* p_parent, int i_offset )
i_minutes*60 +
i_seconds );
}
Item* item = new Item( p_parent, objectID, title, psz_resource_url, i_duration );
Item* item = new Item( p_parent, objectID, title, psz_resource_url, psz_subtitles, i_duration );
p_parent->addItem( item );
}
ixmlNodeList_free( p_resource_list );
......@@ -975,14 +984,32 @@ void MediaServer::_buildPlaylist( Container* p_parent, input_item_node_t *p_inpu
{
Item* p_item = p_parent->getItem( i );
char **ppsz_opts = NULL;
char *psz_input_slave = p_item->buildInputSlaveOption();
if( psz_input_slave )
{
ppsz_opts = (char**)malloc( 2 * sizeof( char* ) );
ppsz_opts[0] = psz_input_slave;
ppsz_opts[1] = p_item->buildSubTrackIdOption();
}
input_item_t* p_input_item = input_item_NewExt( p_item->getResource(),
p_item->getTitle(),
0,
NULL,
0,
p_item->getDuration() );
p_item->getTitle(),
psz_input_slave ? 2 : 0,
psz_input_slave ? ppsz_opts : NULL,
VLC_INPUT_OPTION_TRUSTED, /* XXX */
p_item->getDuration() );
assert( p_input_item );
if( ppsz_opts )
{
free( ppsz_opts[0] );
free( ppsz_opts[1] );
free( ppsz_opts );
psz_input_slave = NULL;
}
input_item_node_AppendItem( p_input_node, p_input_item );
p_item->setInputItem( p_input_item );
}
......@@ -1107,14 +1134,17 @@ void MediaServerList::removeServer( const char* psz_udn )
/*
* Item class
*/
Item::Item( Container* p_parent, const char* psz_object_id, const char* psz_title,
const char* psz_resource, mtime_t i_duration )
Item::Item( Container* p_parent,
const char* psz_object_id, const char* psz_title,
const char* psz_resource, const char* psz_subtitles,
mtime_t i_duration )
{
_parent = p_parent;
_objectID = psz_object_id;
_title = psz_title;
_resource = psz_resource;
_subtitles = psz_subtitles ? psz_subtitles : "";
_duration = i_duration;
_p_input_item = NULL;
......@@ -1141,11 +1171,75 @@ const char* Item::getResource() const
return _resource.c_str();
}
const char* Item::getSubtitles() const
{
if( !_subtitles.size() )
return NULL;
return _subtitles.c_str();
}
mtime_t Item::getDuration() const
{
return _duration;
}
char* Item::buildInputSlaveOption() const
{
const char *psz_subtitles = getSubtitles();
const char *psz_scheme_delim = "://";
const char *psz_sub_opt_fmt = ":input-slave=%s/%s://%s";
const char *psz_demux = "subtitle";
char *psz_uri_scheme = NULL;
const char *psz_scheme_end = NULL;
const char *psz_uri_location = NULL;
char *psz_input_slave = NULL;
size_t i_scheme_len;
if( !psz_subtitles )
return NULL;
psz_scheme_end = strstr( psz_subtitles, psz_scheme_delim );
/* subtitles not being an URI would make no sense */
if( !psz_scheme_end )
return NULL;
i_scheme_len = psz_scheme_end - psz_subtitles;
psz_uri_scheme = (char*)malloc( i_scheme_len + 1 );
if( !psz_uri_scheme )
return NULL;
memcpy( psz_uri_scheme, psz_subtitles, i_scheme_len );
psz_uri_scheme[i_scheme_len] = '\0';
/* If the subtitles try to force a vlc demux,
* then something is very wrong */
if( strchr( psz_uri_scheme, '/' ) )
{
free( psz_uri_scheme );
return NULL;
}
psz_uri_location = psz_scheme_end + strlen( psz_scheme_delim );
if( -1 == asprintf( &psz_input_slave, psz_sub_opt_fmt,
psz_uri_scheme, psz_demux, psz_uri_location ) )
psz_input_slave = NULL;
free( psz_uri_scheme );
return psz_input_slave;
}
char* Item::buildSubTrackIdOption() const
{
return strdup( ":sub-track-id=2" );
}
void Item::setInputItem( input_item_t* p_input_item )
{
if( _p_input_item == p_input_item )
......
......@@ -120,6 +120,7 @@ public:
Item( Container* parent,
const char* objectID,
const char* title,
const char* subtitles,
const char* resource,
mtime_t duration );
~Item();
......@@ -127,6 +128,9 @@ public:
const char* getObjectID() const;
const char* getTitle() const;
const char* getResource() const;
const char* getSubtitles() const;
char* buildInputSlaveOption() const;
char* buildSubTrackIdOption() const;
mtime_t getDuration() const;
void setInputItem( input_item_t* p_input_item );
......@@ -139,6 +143,7 @@ private:
std::string _objectID;
std::string _title;
std::string _resource;
std::string _subtitles;
mtime_t _duration;
};
......
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