[vlc-devel] [PATCH] HttpLive stream_filter: alternative version of ChooseSegment function
Hugo Beauzée-Luyssen
beauze.h at gmail.com
Tue Mar 6 23:58:17 CET 2012
2012/3/6 Łukasz Korbel <korbel85 at gmail.com>:
> HLS: Alternative way of choosing first segment to play
>
> The goal is to allow user to specify how playlist will be played.
> Default bahaviour is to choose first segment from playlist.
> Option --hls-play-all, --no-hls-play-all If enabled (default)
> always first segment in playlist will be choosed for starting point.
> If disabled segment is choosed from the ending of playlist according
> to value of --hls-delay.
> Option --hls-delay [seconds] Specify how far before list end must
> be first segment to play. If set to 0 (default) the latest possible
> segment is choosed, which according to HLS specification is last but
> two segment in playlist.
>
> diff --git a/modules/stream_filter/httplive.c b/modules/stream_filter/httplive.c
> index 71730f4..48bd061 100644
> --- a/modules/stream_filter/httplive.c
> +++ b/modules/stream_filter/httplive.c
> @@ -49,11 +49,24 @@
> static int Open (vlc_object_t *);
> static void Close(vlc_object_t *);
>
> +#define HLS_PLAYALL_TEXT N_("Play whole playlist (default enabled)")
> +#define HLS_PLAYALL_LONGTEXT N_("Start playback of live stream from first "\
> + "segment in the playlist. If disabled playback "\
> + "starting segment is choosed based on
> hls-delay "\
> + "value.")
> +#define HLS_DELAY_TEXT N_("Minimal playback delay (seconds, default: 0)")
> +#define HLS_DELAY_LONGTEXT N_("Define minimal delay of live stream playback. "\
> + "If this values is set to 0 vlc will
> use minimal"\
> + " delay, starting from last but two segment.")
> +
> vlc_module_begin()
> set_category(CAT_INPUT)
> set_subcategory(SUBCAT_INPUT_STREAM_FILTER)
> set_description(N_("Http Live Streaming stream filter"))
> set_capability("stream_filter", 20)
> + add_bool( "hls-play-all", true, HLS_PLAYALL_TEXT,HLS_PLAYALL_LONGTEXT,
> + true )
> + add_integer( "hls-delay", -1, HLS_DELAY_TEXT, HLS_DELAY_LONGTEXT, true )
> set_callbacks(Open, Close)
> vlc_module_end()
>
> @@ -83,6 +96,8 @@ typedef struct hls_stream_s
> int version; /* protocol version should be 1 */
> int sequence; /* media sequence number */
> int duration; /* maximum duration per segment (s) */
> + bool b_play_all; /* start always from first segment in playlist */
> + int delay; /* minimal delay of live stream playback
> (seconds)*/
> uint64_t bandwidth; /* bandwidth usage of segments (bits per second)*/
> uint64_t size; /* stream length is calculated by taking the sum
> foreach segment of (segment->duration
> * hls->bandwidth/8) */
> @@ -165,56 +180,44 @@ static void segment_Free(segment_t *segment);
> /****************************************************************************
> *
> ****************************************************************************/
> +static const char *const ext[] = {
> + "#EXT-X-TARGETDURATION",
> + "#EXT-X-MEDIA-SEQUENCE",
> + "#EXT-X-KEY",
> + "#EXT-X-ALLOW-CACHE",
> + "#EXT-X-ENDLIST",
> + "#EXT-X-STREAM-INF",
> + "#EXT-X-DISCONTINUITY",
> + "#EXT-X-VERSION"
> +};
> +
> static bool isHTTPLiveStreaming(stream_t *s)
> {
> - const uint8_t *peek;
> + const uint8_t *peek, *peek_end;
>
> - int size = stream_Peek(s->p_source, &peek, 46);
> - if (size < 7)
> + int64_t i_size = stream_Peek(s->p_source, &peek, 46);
> + if (i_size < 1)
> return false;
>
> - if (memcmp(peek, "#EXTM3U", 7) != 0)
> + if (strncasecmp((const char*)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++)
> + peek_end = peek + i_size;
> + while(peek <= peek_end)
> + {
> + if (*peek == '#')
> {
> - size_t len = strlen(ext[i]);
> - if (size < len)
> - continue;
> - if (!memcmp(peek, ext[i], len))
> - return true;
> + for (unsigned int i = 0; i < ARRAY_SIZE(ext); i++)
> + {
> + char *p = strstr((const char*)peek, ext[i]);
> + if (p != NULL)
> + return true;
> + }
> }
> + peek++;
> }
>
> return false;
> @@ -229,6 +232,8 @@ static hls_stream_t *hls_New(vlc_array_t
> *hls_stream, const int id, const uint64
> hls->id = id;
> hls->bandwidth = bw;
> hls->duration = -1;/* unknown */
> + hls->b_play_all = true;
> + hls->delay = 0;
> hls->size = 0;
> hls->sequence = 0; /* default is 0 */
> hls->version = 1; /* default protocol version */
> @@ -425,48 +430,51 @@ static segment_t *segment_Find(hls_stream_t
> *hls, const int sequence)
> return NULL;
> }
>
> +static int segment_Duration(hls_stream_t *hls, const int index)
> +{
> + segment_t *segment = segment_GetSegment(hls, index);
> + assert(segment);
> +
> + /*if (segment->duration > hls->duration)
> + {
> + msg_Err(hls, "EXTINF:%d duration is larger than
> EXT-X-TARGETDURATION:%d",
> + segment->duration, hls->duration);
> + }*/
> +
> + return segment->duration;
> +}
> +
> static int ChooseSegment(stream_t *s, const int current)
> {
> stream_sys_t *p_sys = (stream_sys_t *)s->p_sys;
> hls_stream_t *hls = hls_Get(p_sys->hls_stream, current);
> if (hls == NULL) return 0;
>
> - /* Choose a segment to start which is no closer than
> - * 3 times the target duration from the end of the playlist.
> - */
> int wanted = 0;
> - int duration = 0;
> - int sequence = 0;
> int count = vlc_array_count(hls->segments);
> - int i = p_sys->b_live ? count - 1 : 0;
>
> - while((i >= 0) && (i < count))
> + /* If playing live stream and hls-play-all is disabled start playback from
> + hls-delay number of seconds before end of playlist. Otherwise start from
> + first segment in playlist (wanted = 0) */
> + if (p_sys->b_live && !hls->b_play_all)
> {
> - segment_t *segment = segment_GetSegment(hls, i);
> - assert(segment);
> -
> - if (segment->duration > hls->duration)
> - {
> - msg_Err(s, "EXTINF:%d duration is larger than
> EXT-X-TARGETDURATION:%d",
> - segment->duration, hls->duration);
> - }
> -
> - duration += segment->duration;
> - if (duration >= 3 * hls->duration)
> - {
> - /* Start point found */
> - wanted = p_sys->b_live ? i : 0;
> - sequence = segment->sequence;
> - break;
> - }
> -
> - if (p_sys->b_live)
> - i-- ;
> - else
> - i++;
> + /* Must start at least before last two segments.
> + See: http://tools.ietf.org/html/draft-pantos-http-live-streaming-00#section-6.2.2
> */
> + int duration = 0;
> + duration += segment_Duration( hls, count -1); //last seg
> + duration += segment_Duration( hls, count -2); //last but one seg
> +
> + int i= count - 3; //first available
> + while (duration < hls->delay && i >= 0)
> + duration += segment_Duration( hls, i--);
> + wanted = i;
> }
>
> - msg_Info(s, "Choose segment %d/%d (sequence=%d)", wanted, count, sequence);
> + //query for starting segment sequence number
> + segment_t *segment = segment_GetSegment(hls, wanted);
> + int sequence = segment->sequence;
> +
> + msg_Info(s, "Choose segment %d/%d (sequence=%d)", wanted+1,
> count, sequence);
> return wanted;
> }
>
> @@ -671,6 +679,8 @@ static int parse_StreamInformation(stream_t *s,
> vlc_array_t **hls_stream,
> char *psz_uri = relative_URI(s->p_sys->m3u8, uri);
>
> *hls = hls_New(*hls_stream, id, bw, psz_uri ? psz_uri : uri);
> + (*hls)->b_play_all = var_InheritBool(s, "hls-play-all");
> + (*hls)->delay = var_InheritInteger(s, "hls-delay");
>
> free(psz_uri);
>
> @@ -1010,6 +1020,8 @@ static int parse_M3U8(stream_t *s, vlc_array_t
> *streams, uint8_t *buffer, const
> {
> /* No Meta playlist used */
> hls = hls_New(streams, 0, 0, p_sys->m3u8);
> + hls->b_play_all = var_InheritBool(s, "hls-play-all");
> + hls->delay = var_InheritInteger(s, "hls-delay");
> if (hls)
> {
> /* Get TARGET-DURATION first */
> @@ -1470,10 +1482,10 @@ static int hls_DownloadSegmentData(stream_t
> *s, hls_stream_t *hls, segment_t *se
> return VLC_EGENERIC;
> }
> mtime_t duration = mdate() - start;
> - if (hls->bandwidth == 0 && segment->duration > 0)
> + if (hls->bandwidth == 0)
> {
> /* Try to estimate the bandwidth for this stream */
> - hls->bandwidth = (uint64_t)(((double)segment->size * 8) /
> ((double)segment->duration));
> + hls->bandwidth = (uint64_t)((double)segment->size /
> ((double)duration / 1000000.0));
> }
>
> /* If the segment is encrypted, decode it */
> @@ -1856,16 +1868,6 @@ static int Open(vlc_object_t *p_this)
> }
> p_sys->m3u8 = psz_uri;
>
> - char *new_path;
> - if (asprintf(&new_path, "%s.ts", s->psz_path) < 0)
> - {
> - free(p_sys->m3u8);
> - free(p_sys);
> - return VLC_ENOMEM;
> - }
> - free(s->psz_path);
> - s->psz_path = new_path;
> -
> p_sys->bandwidth = 0;
> p_sys->b_live = true;
> p_sys->b_meta = false;
> @@ -2404,12 +2406,14 @@ static int segment_Seek(stream_t *s, const uint64_t pos)
> vlc_mutex_lock(&p_sys->download.lock_wait);
> p_sys->download.seek = p_sys->playback.segment;
> vlc_cond_signal(&p_sys->download.wait);
> + vlc_mutex_unlock(&p_sys->download.lock_wait);
>
> /* Wait for download to be finished */
> + vlc_mutex_lock(&p_sys->download.lock_wait);
> msg_Info(s, "seek to segment %d", p_sys->playback.segment);
> - while ((p_sys->download.seek != -1) ||
> - ((p_sys->download.segment - p_sys->playback.segment < 3) &&
> - (p_sys->download.segment < count)))
> + while (((p_sys->download.seek != -1) ||
> + (p_sys->download.segment - p_sys->playback.segment < 3)) &&
> + (p_sys->download.segment < (count - 6)))
> {
> vlc_cond_wait(&p_sys->download.wait, &p_sys->download.lock_wait);
> if (!vlc_object_alive(s) || s->b_error) break;
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> http://mailman.videolan.org/listinfo/vlc-devel
Hello,
This patch seems to revert 74f02326dc168aa632fe68c29951cf3824dfce06 "silently"
You probably failed to merge something at a point.
Regards,
--
Hugo Beauzée-Luyssen
More information about the vlc-devel
mailing list