понедельник, 26 декабря 2011 г. пользователь Martin Storsjö <[email protected]>
писал:
>
> This might be ok, but this needs a check for v->n_segments > 0. To
simplify the expression, a separate duration variable perhaps can be
declared above, e.g.
>
> int duration = v->n-segments > 0 ?
>               v->segments[v->n_segments - 1]->duration :
>               v->target_duration;
>
> // Martin

Yes, such situation seems weird, but we don't have such check during
parse_playlist. And wowza is sufficiently weird software to end up in such
situation :)
Looking more at that code, i expanded a patch. Please review again.

---
 libavformat/applehttp.c |   28 +++++++++++++++++++++++-----
 1 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/libavformat/applehttp.c b/libavformat/applehttp.c
index 99febc6..27c446e 100644
--- a/libavformat/applehttp.c
+++ b/libavformat/applehttp.c
@@ -373,14 +373,33 @@ static int read_data(void *opaque, uint8_t *buf, int
buf_size)
     struct variant *v = opaque;
     AppleHTTPContext *c = v->parent->priv_data;
     int ret, i;
+    int64_t reload_interval;

 restart:
     if (!v->input) {
 reload:
-        /* If this is a live stream and target_duration has elapsed since
-         * the last playlist reload, reload the variant playlists now. */
+        /*
+         * According to draft-pantos-http-live-streaming-07, 6.3.4.,
+         * === quote ===
+         * The initial minimum reload delay is the duration of the last
media
+         * segment in the Playlist.  Media segment duration is specified
by the
+         * EXTINF tag.
+         * If the client reloads a Playlist file and finds that it has not
+         * changed then it MUST wait for a period of one-half the target
+         * duration before retrying.
+         * === quote end ===
+         * This code does not follow it strictly.
+         * It uses last segment's EXTINF as reload interval.
+         * If, at some reason, we have empty segments list after last
reload,
+         * TARGETDURATION is used as reload interval.
+         */
+        reload_interval = v->n_segments > 0 ?
+            v->segments[v->n_segments - 1]->duration :
+            v->target_duration; // not by spec, just fallback to what we
have
+        reload_interval *= 1000000; // microseconds, to be like
last_load_time
+
         if (!v->finished &&
-            av_gettime() - v->last_load_time >= v->target_duration*1000000
&&
+            av_gettime() - v->last_load_time >= reload_interval &&
             (ret = parse_playlist(c, v->url, v, NULL)) < 0)
                 return ret;
         if (v->cur_seq_no < v->start_seq_no) {
@@ -392,8 +411,7 @@ reload:
         if (v->cur_seq_no >= v->start_seq_no + v->n_segments) {
             if (v->finished)
                 return AVERROR_EOF;
-            while (av_gettime() - v->last_load_time <
-                   v->target_duration*1000000) {
+            while (av_gettime() - v->last_load_time < reload_interval) {
                 if (ff_check_interrupt(c->interrupt_callback))
                     return AVERROR_EXIT;
                 usleep(100*1000);
--
From 779dc8688441a6e7e2b9b2360c1872ca5a7c676d Mon Sep 17 00:00:00 2001
From: Andrey Utkin <[email protected]>
Date: Mon, 26 Dec 2011 21:25:52 +0200
Subject: [PATCH] applehttp: reload interval is duration of last segment

According to draft-pantos-http-live-streaming-07, 6.3.4.,
=== quote ===
The initial minimum reload delay is the duration of the last media
segment in the Playlist.  Media segment duration is specified by the
EXTINF tag.
If the client reloads a Playlist file and finds that it has not
changed then it MUST wait for a period of one-half the target
duration before retrying.
=== quote end ===
Did not implement the second part (if playlist has not changed).
Previously, playlist reloading interval was TARGETDURATION seconds,
and lags have happened at playback.
Now reloading interval is last known (listed in playlist) segment's
EXTINF value.
Tested old and new way with Wowza 3.0.2 patch3.
---
 libavformat/applehttp.c |   28 +++++++++++++++++++++++-----
 1 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/libavformat/applehttp.c b/libavformat/applehttp.c
index 99febc6..27c446e 100644
--- a/libavformat/applehttp.c
+++ b/libavformat/applehttp.c
@@ -373,14 +373,33 @@ static int read_data(void *opaque, uint8_t *buf, int buf_size)
     struct variant *v = opaque;
     AppleHTTPContext *c = v->parent->priv_data;
     int ret, i;
+    int64_t reload_interval;
 
 restart:
     if (!v->input) {
 reload:
-        /* If this is a live stream and target_duration has elapsed since
-         * the last playlist reload, reload the variant playlists now. */
+        /*
+         * According to draft-pantos-http-live-streaming-07, 6.3.4.,
+         * === quote ===
+         * The initial minimum reload delay is the duration of the last media
+         * segment in the Playlist.  Media segment duration is specified by the
+         * EXTINF tag.
+         * If the client reloads a Playlist file and finds that it has not
+         * changed then it MUST wait for a period of one-half the target
+         * duration before retrying.
+         * === quote end ===
+         * This code does not follow it strictly.
+         * It uses last segment's EXTINF as reload interval.
+         * If, at some reason, we have empty segments list after last reload,
+         * TARGETDURATION is used as reload interval.
+         */
+        reload_interval = v->n_segments > 0 ?
+            v->segments[v->n_segments - 1]->duration :
+            v->target_duration; // not by spec, just fallback to what we have
+        reload_interval *= 1000000; // microseconds, to be like last_load_time
+
         if (!v->finished &&
-            av_gettime() - v->last_load_time >= v->target_duration*1000000 &&
+            av_gettime() - v->last_load_time >= reload_interval &&
             (ret = parse_playlist(c, v->url, v, NULL)) < 0)
                 return ret;
         if (v->cur_seq_no < v->start_seq_no) {
@@ -392,8 +411,7 @@ reload:
         if (v->cur_seq_no >= v->start_seq_no + v->n_segments) {
             if (v->finished)
                 return AVERROR_EOF;
-            while (av_gettime() - v->last_load_time <
-                   v->target_duration*1000000) {
+            while (av_gettime() - v->last_load_time < reload_interval) {
                 if (ff_check_interrupt(c->interrupt_callback))
                     return AVERROR_EXIT;
                 usleep(100*1000);
-- 
1.7.7

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to