Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
GSoC
GSoC2018
macOS
vlc
Commits
9565350a
Commit
9565350a
authored
May 08, 2015
by
François Cartegnie
🤞
Browse files
demux: hls: add adaptative based hls demuxer
parent
621b86f9
Changes
18
Hide whitespace changes
Inline
Side-by-side
NEWS
View file @
9565350a
...
...
@@ -57,6 +57,7 @@ Demuxers:
* Support for Creative ADPCM/alaw/ulaw/S16L in VOC files
* Support for Creative ADPCM in AVI
* Directory Demux can now sort items, ignore extensions and hidden files
* Replaced httplive stream filter with new hls demuxer
Stream filter:
* Added ARIB STD-B25 TS streams decoder
...
...
modules/MODULES_LIST
View file @
9565350a
...
...
@@ -175,6 +175,7 @@ $Id$
* hevc: HEVC demuxer
* hotkeys: hotkeys control module
* hqdn3d: High Quality denoising filter
* hls: HTTP Live Streaming demuxer
* http: HTTP Network access module
* httplive: HTTP Live streaming for playback
* i420_rgb: planar YUV to packed RGB conversion functions
...
...
modules/demux/Makefile.am
View file @
9565350a
...
...
@@ -244,45 +244,7 @@ if HAVE_DVBPSI
demux_LTLIBRARIES
+=
libts_plugin.la
endif
libdash_plugin_la_SOURCES
=
\
demux/dash/mpd/AdaptationSet.cpp
\
demux/dash/mpd/AdaptationSet.h
\
demux/dash/mpd/DASHCommonAttributesElements.cpp
\
demux/dash/mpd/DASHCommonAttributesElements.h
\
demux/dash/mpd/DASHSegment.cpp
\
demux/dash/mpd/DASHSegment.h
\
demux/dash/mpd/ContentDescription.cpp
\
demux/dash/mpd/ContentDescription.h
\
demux/dash/mpd/IsoffMainParser.cpp
\
demux/dash/mpd/IsoffMainParser.h
\
demux/dash/mpd/MPD.cpp
\
demux/dash/mpd/MPD.h
\
demux/dash/mpd/MPDFactory.cpp
\
demux/dash/mpd/MPDFactory.h
\
demux/dash/mpd/Period.cpp
\
demux/dash/mpd/Period.h
\
demux/dash/mpd/Profile.cpp
\
demux/dash/mpd/Profile.hpp
\
demux/dash/mpd/ProgramInformation.cpp
\
demux/dash/mpd/ProgramInformation.h
\
demux/dash/mpd/Representation.cpp
\
demux/dash/mpd/Representation.h
\
demux/dash/mpd/TrickModeType.cpp
\
demux/dash/mpd/TrickModeType.h
\
demux/dash/mp4/AtomsReader.cpp
\
demux/dash/mp4/AtomsReader.hpp
\
demux/dash/xml/DOMHelper.cpp
\
demux/dash/xml/DOMHelper.h
\
demux/dash/xml/DOMParser.cpp
\
demux/dash/xml/DOMParser.h
\
demux/dash/xml/Node.cpp
\
demux/dash/xml/Node.h
\
demux/dash/dash.cpp
\
demux/dash/dash.hpp
\
demux/dash/DASHManager.cpp
\
demux/dash/DASHManager.h
libdash_plugin_la_SOURCES
+=
\
adaptative_SOURCES
=
\
demux/adaptative/playlist/AbstractPlaylist.cpp
\
demux/adaptative/playlist/AbstractPlaylist.hpp
\
demux/adaptative/playlist/BaseAdaptationSet.cpp
\
...
...
@@ -345,8 +307,46 @@ libdash_plugin_la_SOURCES += \
demux/adaptative/tools/Retrieve.cpp
\
demux/adaptative/tools/Retrieve.hpp
libdash_plugin_la_SOURCES
+=
demux/mp4/libmp4.c demux/mp4/libmp4.h
libdash_plugin_la_SOURCES
=
\
demux/dash/mpd/AdaptationSet.cpp
\
demux/dash/mpd/AdaptationSet.h
\
demux/dash/mpd/DASHCommonAttributesElements.cpp
\
demux/dash/mpd/DASHCommonAttributesElements.h
\
demux/dash/mpd/DASHSegment.cpp
\
demux/dash/mpd/DASHSegment.h
\
demux/dash/mpd/ContentDescription.cpp
\
demux/dash/mpd/ContentDescription.h
\
demux/dash/mpd/IsoffMainParser.cpp
\
demux/dash/mpd/IsoffMainParser.h
\
demux/dash/mpd/MPD.cpp
\
demux/dash/mpd/MPD.h
\
demux/dash/mpd/MPDFactory.cpp
\
demux/dash/mpd/MPDFactory.h
\
demux/dash/mpd/Period.cpp
\
demux/dash/mpd/Period.h
\
demux/dash/mpd/Profile.cpp
\
demux/dash/mpd/Profile.hpp
\
demux/dash/mpd/ProgramInformation.cpp
\
demux/dash/mpd/ProgramInformation.h
\
demux/dash/mpd/Representation.cpp
\
demux/dash/mpd/Representation.h
\
demux/dash/mpd/TrickModeType.cpp
\
demux/dash/mpd/TrickModeType.h
\
demux/dash/mp4/AtomsReader.cpp
\
demux/dash/mp4/AtomsReader.hpp
\
demux/dash/xml/DOMHelper.cpp
\
demux/dash/xml/DOMHelper.h
\
demux/dash/xml/DOMParser.cpp
\
demux/dash/xml/DOMParser.h
\
demux/dash/xml/Node.cpp
\
demux/dash/xml/Node.h
\
demux/dash/dash.cpp
\
demux/dash/dash.hpp
\
demux/dash/DASHManager.cpp
\
demux/dash/DASHManager.h
libdash_plugin_la_SOURCES
+=
$(adaptative_SOURCES)
libdash_plugin_la_SOURCES
+=
demux/mp4/libmp4.c demux/mp4/libmp4.h
libdash_plugin_la_CXXFLAGS
=
$(AM_CFLAGS)
-I
$(srcdir)
/demux/dash
libdash_plugin_la_LIBADD
=
$(SOCKET_LIBS)
$(LIBM)
if
HAVE_ZLIB
...
...
@@ -354,6 +354,36 @@ libdash_plugin_la_LIBADD += -lz
endif
demux_LTLIBRARIES
+=
libdash_plugin.la
libhls_plugin_la_SOURCES
=
\
demux/hls/playlist/M3U8.hpp
\
demux/hls/playlist/M3U8.cpp
\
demux/hls/playlist/Parser.hpp
\
demux/hls/playlist/Parser.cpp
\
demux/hls/playlist/Representation.hpp
\
demux/hls/playlist/Representation.cpp
\
demux/hls/playlist/HLSSegment.hpp
\
demux/hls/playlist/HLSSegment.cpp
\
demux/hls/playlist/Tags.hpp
\
demux/hls/playlist/Tags.cpp
\
demux/hls/HLSManager.hpp
\
demux/hls/HLSManager.cpp
\
demux/hls/hls.cpp
\
demux/hls/hls.hpp
libhls_plugin_la_SOURCES
+=
$(adaptative_SOURCES)
libhls_plugin_la_CXXFLAGS
=
$(AM_CFLAGS)
-I
$(srcdir)
/demux/hls
libhls_plugin_la_LIBADD
=
$(SOCKET_LIBS)
$(LIBM)
if
HAVE_ZLIB
libhls_plugin_la_LIBADD
+=
-lz
endif
if
HAVE_GCRYPT
libhls_plugin_la_CXXFLAGS
+=
$(GCRYPT_CFLAGS)
libhls_plugin_la_LIBADD
+=
$(GCRYPT_LIBS)
endif
demux_LTLIBRARIES
+=
libhls_plugin.la
libttml_plugin_la_SOURCES
=
demux/ttml.c
demux_LTLIBRARIES
+=
libttml_plugin.la
modules/demux/hls/HLSManager.cpp
0 → 100644
View file @
9565350a
/*****************************************************************************
* HLSManager.cpp
*****************************************************************************
* Copyright © 2015 VideoLAN authors
*
* 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 the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include
"HLSManager.hpp"
#include
"../adaptative/logic/RateBasedAdaptationLogic.h"
#include
"../adaptative/tools/Retrieve.hpp"
#include
"playlist/Parser.hpp"
#include
<vlc_stream.h>
using
namespace
adaptative
;
using
namespace
adaptative
::
logic
;
using
namespace
hls
;
using
namespace
hls
::
playlist
;
HLSManager
::
HLSManager
(
M3U8
*
playlist
,
AbstractAdaptationLogic
::
LogicType
type
,
stream_t
*
stream
)
:
PlaylistManager
(
playlist
,
type
,
stream
)
{
}
HLSManager
::~
HLSManager
()
{
}
AbstractAdaptationLogic
*
HLSManager
::
createLogic
(
AbstractAdaptationLogic
::
LogicType
type
)
{
size_t
bps
=
var_InheritInteger
(
stream
,
"hls-prefbw"
)
*
8192
;
switch
(
type
)
{
case
AbstractAdaptationLogic
::
FixedRate
:
{
size_t
bps
=
var_InheritInteger
(
stream
,
"hls-prefbw"
)
*
8192
;
return
new
(
std
::
nothrow
)
FixedRateAdaptationLogic
(
bps
);
}
case
AbstractAdaptationLogic
::
Default
:
case
AbstractAdaptationLogic
::
RateBased
:
{
int
width
=
var_InheritInteger
(
stream
,
"hls-prefwidth"
);
int
height
=
var_InheritInteger
(
stream
,
"hls-prefheight"
);
return
new
(
std
::
nothrow
)
RateBasedAdaptationLogic
(
width
,
height
);
}
default:
return
PlaylistManager
::
createLogic
(
type
);
}
}
bool
HLSManager
::
updatePlaylist
()
{
if
(
!
playlist
->
isLive
()
||
!
playlist
->
minUpdatePeriod
.
Get
())
return
true
;
mtime_t
now
=
time
(
NULL
);
if
(
nextPlaylistupdate
&&
now
<
nextPlaylistupdate
)
return
true
;
M3U8
*
updatedplaylist
=
NULL
;
/* do update */
if
(
nextPlaylistupdate
)
{
std
::
string
url
(
stream
->
psz_access
);
url
.
append
(
"://"
);
url
.
append
(
stream
->
psz_path
);
uint8_t
*
p_data
=
NULL
;
size_t
i_data
=
Retrieve
::
HTTP
(
VLC_OBJECT
(
stream
),
url
,
(
void
**
)
&
p_data
);
if
(
!
p_data
)
return
false
;
stream_t
*
updatestream
=
stream_MemoryNew
(
stream
,
p_data
,
i_data
,
false
);
if
(
!
updatestream
)
{
free
(
p_data
);
nextPlaylistupdate
=
now
+
playlist
->
minUpdatePeriod
.
Get
();
return
false
;
}
Parser
parser
(
updatestream
);
updatedplaylist
=
parser
.
parse
(
url
);
if
(
!
updatedplaylist
)
{
stream_Delete
(
updatestream
);
nextPlaylistupdate
=
now
+
playlist
->
minUpdatePeriod
.
Get
();
return
false
;
}
stream_Delete
(
updatestream
);
}
/* Compute new MPD update time */
mtime_t
mininterval
=
0
;
mtime_t
maxinterval
=
0
;
if
(
updatedplaylist
)
{
updatedplaylist
->
getPlaylistDurationsRange
(
&
mininterval
,
&
maxinterval
);
playlist
->
mergeWith
(
updatedplaylist
);
playlist
->
debug
();
delete
updatedplaylist
;
/* pruning */
for
(
int
type
=
0
;
type
<
StreamTypeCount
;
type
++
)
{
if
(
!
streams
[
type
])
continue
;
streams
[
type
]
->
prune
();
}
}
else
{
playlist
->
getPlaylistDurationsRange
(
&
mininterval
,
&
maxinterval
);
}
if
(
playlist
->
minUpdatePeriod
.
Get
()
*
CLOCK_FREQ
>
mininterval
)
mininterval
=
playlist
->
minUpdatePeriod
.
Get
()
*
CLOCK_FREQ
;
if
(
maxinterval
<
mininterval
)
maxinterval
=
mininterval
;
nextPlaylistupdate
=
now
+
(
mininterval
+
maxinterval
)
/
(
2
*
CLOCK_FREQ
);
msg_Dbg
(
stream
,
"Updated playlist, next update in %"
PRId64
"s %ld %ld"
,
nextPlaylistupdate
-
now
,
mininterval
,
maxinterval
);
return
true
;
}
modules/demux/hls/HLSManager.hpp
0 → 100644
View file @
9565350a
/*
* HLSManager.hpp
*****************************************************************************
* Copyright © 2015 - VideoLAN authors
*
* 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 the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef HLSMANAGER_HPP
#define HLSMANAGER_HPP
#include
"../adaptative/PlaylistManager.h"
#include
"../adaptative/logic/AbstractAdaptationLogic.h"
#include
"playlist/M3U8.hpp"
namespace
hls
{
using
namespace
adaptative
;
class
HLSManager
:
public
PlaylistManager
{
public:
HLSManager
(
playlist
::
M3U8
*
,
logic
::
AbstractAdaptationLogic
::
LogicType
type
,
stream_t
*
stream
);
virtual
~
HLSManager
();
virtual
AbstractAdaptationLogic
*
createLogic
(
AbstractAdaptationLogic
::
LogicType
);
virtual
bool
updatePlaylist
();
};
}
#endif // HLSMANAGER_HPP
modules/demux/hls/hls.cpp
0 → 100644
View file @
9565350a
/*****************************************************************************
* hls.cpp: HTTP Live Streaming module
*****************************************************************************
* Copyright © 2015 - VideoLAN Authors
*
* 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 the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#define __STDC_CONSTANT_MACROS 1
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include
<stdint.h>
#include
<vlc_common.h>
#include
<vlc_plugin.h>
#include
<vlc_demux.h>
#include
<vlc_meta.h>
#include
<errno.h>
#include
"../adaptative/logic/AbstractAdaptationLogic.h"
#include
"HLSManager.hpp"
#include
"playlist/Parser.hpp"
#include
"playlist/M3U8.hpp"
#include
"hls.hpp"
using
namespace
adaptative
;
using
namespace
adaptative
::
logic
;
using
namespace
adaptative
::
playlist
;
using
namespace
hls
;
using
namespace
hls
::
playlist
;
/*****************************************************************************
* Module descriptor
*****************************************************************************/
static
int
Open
(
vlc_object_t
*
);
static
void
Close
(
vlc_object_t
*
);
#define HLS_WIDTH_TEXT N_("Preferred Width")
#define HLS_WIDTH_LONGTEXT N_("Preferred Width")
#define HLS_HEIGHT_TEXT N_("Preferred Height")
#define HLS_HEIGHT_LONGTEXT N_("Preferred Height")
#define HLS_BW_TEXT N_("Fixed Bandwidth in KiB/s")
#define HLS_BW_LONGTEXT N_("Preferred bandwidth for non adaptative streams")
#define HLS_LOGIC_TEXT N_("Adaptation Logic")
static
const
int
pi_logics
[]
=
{
AbstractAdaptationLogic
::
RateBased
,
AbstractAdaptationLogic
::
FixedRate
,
AbstractAdaptationLogic
::
AlwaysLowest
,
AbstractAdaptationLogic
::
AlwaysBest
};
static
const
char
*
const
ppsz_logics
[]
=
{
N_
(
"Bandwidth Adaptive"
),
N_
(
"Fixed Bandwidth"
),
N_
(
"Lowest Bandwidth/Quality"
),
N_
(
"Highest Bandwith/Quality"
)};
vlc_module_begin
()
set_shortname
(
N_
(
"hls"
))
set_description
(
N_
(
"HTTP Live Streaming"
)
)
set_capability
(
"demux"
,
12
)
set_category
(
CAT_INPUT
)
set_subcategory
(
SUBCAT_INPUT_DEMUX
)
add_integer
(
"hls-logic"
,
AbstractAdaptationLogic
::
Default
,
HLS_LOGIC_TEXT
,
NULL
,
false
)
change_integer_list
(
pi_logics
,
ppsz_logics
)
add_integer
(
"hls-prefwidth"
,
480
,
HLS_WIDTH_TEXT
,
HLS_WIDTH_LONGTEXT
,
true
)
add_integer
(
"hls-prefheight"
,
360
,
HLS_HEIGHT_TEXT
,
HLS_HEIGHT_LONGTEXT
,
true
)
add_integer
(
"hls-prefbw"
,
250
,
HLS_BW_TEXT
,
HLS_BW_LONGTEXT
,
false
)
set_callbacks
(
Open
,
Close
)
vlc_module_end
()
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static
int
Demux
(
demux_t
*
);
static
int
Control
(
demux_t
*
p_demux
,
int
i_query
,
va_list
args
);
/*****************************************************************************
* Open:
*****************************************************************************/
static
bool
isHTTPLiveStreaming
(
stream_t
*
s
)
{
const
uint8_t
*
peek
;
int
size
=
stream_Peek
(
s
,
&
peek
,
46
);
if
(
size
<
7
)
return
false
;
if
(
memcmp
(
peek
,
"#EXTM3U"
,
7
)
!=
0
)
return
false
;
peek
+=
7
;
size
-=
7
;
/* Parse stream and search for
* EXT-X-TARGETDURATION or EXT-X-STREAM-INF tag, see
* http://tools.ietf.org/html/draft-pantos-http-live-streaming-04#page-8 */
while
(
size
--
)
{
static
const
char
*
const
ext
[]
=
{
"TARGETDURATION"
,
"MEDIA-SEQUENCE"
,
"KEY"
,
"ALLOW-CACHE"
,
"ENDLIST"
,
"STREAM-INF"
,
"DISCONTINUITY"
,
"VERSION"
};
if
(
*
peek
++
!=
'#'
)
continue
;
if
(
size
<
6
)
continue
;
if
(
memcmp
(
peek
,
"EXT-X-"
,
6
))
continue
;
peek
+=
6
;
size
-=
6
;
for
(
size_t
i
=
0
;
i
<
ARRAY_SIZE
(
ext
);
i
++
)
{
size_t
len
=
strlen
(
ext
[
i
]);
if
(
size
<
0
||
(
size_t
)
size
<
len
)
continue
;
if
(
!
memcmp
(
peek
,
ext
[
i
],
len
))
return
true
;
}
}
return
false
;
}
static
int
Open
(
vlc_object_t
*
p_obj
)
{
demux_t
*
p_demux
=
(
demux_t
*
)
p_obj
;
if
(
!
isHTTPLiveStreaming
(
p_demux
->
s
))
return
VLC_EGENERIC
;
demux_sys_t
*
p_sys
=
(
demux_sys_t
*
)
malloc
(
sizeof
(
demux_sys_t
));
if
(
unlikely
(
p_sys
==
NULL
))
return
VLC_ENOMEM
;
Parser
parser
(
p_demux
->
s
);
p_sys
->
p_playlist
=
parser
.
parse
(
std
::
string
());
if
(
!
p_sys
->
p_playlist
)
{
free
(
p_sys
);
return
VLC_EGENERIC
;
}
int
logic
=
var_InheritInteger
(
p_obj
,
"hls-logic"
);
HLSManager
*
p_manager
=
new
(
std
::
nothrow
)
HLSManager
(
p_sys
->
p_playlist
,
static_cast
<
AbstractAdaptationLogic
::
LogicType
>
(
logic
),
p_demux
->
s
);
BasePeriod
*
period
=
p_sys
->
p_playlist
->
getFirstPeriod
();
if
(
period
&&
!
p_manager
->
start
(
p_demux
))
{
delete
p_manager
;
free
(
p_sys
);
return
VLC_EGENERIC
;
}
p_sys
->
p_manager
=
p_manager
;
p_demux
->
p_sys
=
p_sys
;
p_demux
->
pf_demux
=
Demux
;
p_demux
->
pf_control
=
Control
;
p_sys
->
i_nzpcr
=
VLC_TS_INVALID
;
msg_Dbg
(
p_obj
,
"opening mpd file (%s)"
,
p_demux
->
s
->
psz_path
);
return
VLC_SUCCESS
;
}
/*****************************************************************************
* Close:
*****************************************************************************/
static
void
Close
(
vlc_object_t
*
p_obj
)
{
demux_t
*
p_demux
=
(
demux_t
*
)
p_obj
;
demux_sys_t
*
p_sys
=
(
demux_sys_t
*
)
p_demux
->
p_sys
;
delete
p_sys
->
p_manager
;
free
(
p_sys
);
}
/*****************************************************************************
* Callbacks:
*****************************************************************************/
#define DEMUX_INCREMENT (CLOCK_FREQ / 20)
static
int
Demux
(
demux_t
*
p_demux
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
Stream
::
status
status
=
p_sys
->
p_manager
->
demux
(
p_sys
->
i_nzpcr
+
DEMUX_INCREMENT
);
switch
(
status
)
{
case
Stream
::
status_eof
:
return
VLC_DEMUXER_EOF
;
case
Stream
::
status_buffering
:
break
;
case
Stream
::
status_demuxed
:
if
(
p_sys
->
i_nzpcr
==
VLC_TS_INVALID
)
p_sys
->
i_nzpcr
=
p_sys
->
p_manager
->
getPCR
();
else
p_sys
->
i_nzpcr
+=
DEMUX_INCREMENT
;
int
group
=
p_sys
->
p_manager
->
getGroup
();
es_out_Control
(
p_demux
->
out
,
ES_OUT_SET_GROUP_PCR
,
group
,
VLC_TS_0
+
p_sys
->
i_nzpcr
);
break
;
}
if
(
!
p_sys
->
p_manager
->
updatePlaylist
()
)
msg_Warn
(
p_demux
,
"Can't update playlist"
);
return
VLC_DEMUXER_SUCCESS
;
}
static
int
Control
(
demux_t
*
p_demux
,
int
i_query
,
va_list
args
)
{
demux_sys_t
*
p_sys
=
p_demux
->
p_sys
;
switch
(
i_query
)
{
case
DEMUX_CAN_SEEK
:
*
(
va_arg
(
args
,
bool
*
))
=
p_sys
->
p_manager
->
seekAble
();
break
;
case
DEMUX_CAN_CONTROL_PACE
:
*
(
va_arg
(
args
,
bool
*
))
=
true
;
break
;
case
DEMUX_CAN_PAUSE
:
*
(
va_arg
(
args
,
bool
*
))
=
p_sys
->
p_playlist
->
isLive
();
break
;
case
DEMUX_GET_TIME
:
*
(
va_arg
(
args
,
int64_t
*
))
=
p_sys
->
i_nzpcr
;
break
;
case
DEMUX_GET_LENGTH
:
*
(
va_arg
(
args
,
int64_t
*
))
=
p_sys
->
p_manager
->
getDuration
();
break
;
case
DEMUX_GET_POSITION
:
if
(
!
p_sys
->
p_manager
->
getDuration
())
return
VLC_EGENERIC
;
*
(
va_arg
(
args
,
double
*
))
=
(
double
)
p_sys
->
i_nzpcr
/
p_sys
->
p_manager
->
getDuration
();
break
;
case
DEMUX_SET_POSITION
:
{
int64_t
time
=
p_sys
->
p_manager
->
getDuration
()
*
va_arg
(
args
,
double
);
if
(
p_sys
->
p_playlist
->
isLive
()
||