[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