diff mbox

[FFmpeg-devel] avformat/hlsenc: support fmp4 single file mode

Message ID 20170731040315.9496-1-lq@chinaffmpeg.org
State Superseded
Headers show

Commit Message

Liu Steven July 31, 2017, 4:03 a.m. UTC
add byterange mode of the hls fmp4

Signed-off-by: Steven Liu <lq@onvideo.cn>
---
 libavformat/hlsenc.c | 72 ++++++++++++++++++++++++++++++++--------------------
 1 file changed, 44 insertions(+), 28 deletions(-)

Comments

Derek Buitenhuis Aug. 1, 2017, 12:41 p.m. UTC | #1
On 7/31/2017 5:03 AM, Steven Liu wrote:
> add byterange mode of the hls fmp4
> 
> Signed-off-by: Steven Liu <lq@onvideo.cn>
> ---
>  libavformat/hlsenc.c | 72 ++++++++++++++++++++++++++++++++--------------------
>  1 file changed, 44 insertions(+), 28 deletions(-)
> 
> diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
> index f98f041..cfc28d2 100644
> --- a/libavformat/hlsenc.c
> +++ b/libavformat/hlsenc.c
> @@ -531,6 +531,7 @@ static int hls_mux_init(AVFormatContext *s)
>      HLSContext *hls = s->priv_data;
>      AVFormatContext *oc;
>      AVFormatContext *vtt_oc = NULL;
> +    int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);

Not quite sure I understand the '|| (hls->max_seg_size > 0)' part. Is there ever a time
that byte range mode is used with more than one file, allowed by the spec?

>      if (hls->segment_type == SEGMENT_TYPE_FMP4) {
> -        hls->fmp4_init_mode = 1;
> +        if (byterange_mode) {
> +            hls->fmp4_init_mode = 0;
> +        } else {
> +            hls->fmp4_init_mode = 1;
> +        }

hls->fmp4_init_mode = !byterange_mode;

>      if(hls->has_subtitle) {
> -
>          if (hls->flags & HLS_SINGLE_FILE)

Accidental white space change.

> +    if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) {
> +        hls->fmp4_init_filename  = av_strdup(hls->basename);

Missing NULL check.

- Derek
Steven Liu Aug. 1, 2017, 2:51 p.m. UTC | #2
2017-08-01 20:41 GMT+08:00 Derek Buitenhuis <derek.buitenhuis@gmail.com>:
> On 7/31/2017 5:03 AM, Steven Liu wrote:
>> add byterange mode of the hls fmp4
>>
>> Signed-off-by: Steven Liu <lq@onvideo.cn>
>> ---
>>  libavformat/hlsenc.c | 72 ++++++++++++++++++++++++++++++++--------------------
>>  1 file changed, 44 insertions(+), 28 deletions(-)
>>
>> diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
>> index f98f041..cfc28d2 100644
>> --- a/libavformat/hlsenc.c
>> +++ b/libavformat/hlsenc.c
>> @@ -531,6 +531,7 @@ static int hls_mux_init(AVFormatContext *s)
>>      HLSContext *hls = s->priv_data;
>>      AVFormatContext *oc;
>>      AVFormatContext *vtt_oc = NULL;
>> +    int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
>
> Not quite sure I understand the '|| (hls->max_seg_size > 0)' part. Is there ever a time
> that byte range mode is used with more than one file, allowed by the spec?
more than one file is old version support and user require and be used
ok, so this is no problem, maybe this modify to
 int byterange_mode = ((hls->flags & HLS_SINGLE_FILE) ||
(hls->max_seg_size > 0)); will clearly

>
>>      if (hls->segment_type == SEGMENT_TYPE_FMP4) {
>> -        hls->fmp4_init_mode = 1;
>> +        if (byterange_mode) {
>> +            hls->fmp4_init_mode = 0;
>> +        } else {
>> +            hls->fmp4_init_mode = 1;
>> +        }
>
> hls->fmp4_init_mode = !byterange_mode;
looks good, will use this style code :)
>
>>      if(hls->has_subtitle) {
>> -
>>          if (hls->flags & HLS_SINGLE_FILE)
>
> Accidental white space change.
used
>
>> +    if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) {
>> +        hls->fmp4_init_filename  = av_strdup(hls->basename);
>
> Missing NULL check.
accept
>
> - Derek
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


patch will upadte later.
diff mbox

Patch

diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index f98f041..cfc28d2 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -531,6 +531,7 @@  static int hls_mux_init(AVFormatContext *s)
     HLSContext *hls = s->priv_data;
     AVFormatContext *oc;
     AVFormatContext *vtt_oc = NULL;
+    int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
     int i, ret;
 
     ret = avformat_alloc_output_context2(&hls->avf, hls->oformat, NULL, NULL);
@@ -584,7 +585,11 @@  static int hls_mux_init(AVFormatContext *s)
     hls->fmp4_init_mode = 0;
 
     if (hls->segment_type == SEGMENT_TYPE_FMP4) {
-        hls->fmp4_init_mode = 1;
+        if (byterange_mode) {
+            hls->fmp4_init_mode = 0;
+        } else {
+            hls->fmp4_init_mode = 1;
+        }
         if ((ret = s->io_open(s, &oc->pb, hls->base_output_dirname, AVIO_FLAG_WRITE, NULL)) < 0) {
             av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", hls->fmp4_init_filename);
             return ret;
@@ -980,9 +985,6 @@  static void write_m3u8_head_block(HLSContext *hls, AVIOContext *out, int version
     }
     avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
     avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
-    if (hls->segment_type == SEGMENT_TYPE_FMP4) {
-        avio_printf(out, "#EXT-X-MAP:URI=\"%s\"\n", hls->fmp4_init_filename);
-    }
     av_log(hls, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
 }
 
@@ -1066,13 +1068,21 @@  static int hls_window(AVFormatContext *s, int last)
             avio_printf(out, "#EXT-X-DISCONTINUITY\n");
         }
 
-        if (hls->flags & HLS_ROUND_DURATIONS)
-            avio_printf(out, "#EXTINF:%ld,\n",  lrint(en->duration));
-        else
-            avio_printf(out, "#EXTINF:%f,\n", en->duration);
-        if (byterange_mode)
-             avio_printf(out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
-                         en->size, en->pos);
+        if ((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == hls->segments)) {
+            avio_printf(out, "#EXT-X-MAP:URI=\"%s\"", hls->fmp4_init_filename);
+            if (hls->flags & HLS_SINGLE_FILE) {
+                avio_printf(out, ",BYTERANGE=\"%"PRId64"@%"PRId64"\"", en->size, en->pos);
+            }
+            avio_printf(out, "\n");
+        } else {
+            if (hls->flags & HLS_ROUND_DURATIONS)
+                avio_printf(out, "#EXTINF:%ld,\n",  lrint(en->duration));
+            else
+                avio_printf(out, "#EXTINF:%f,\n", en->duration);
+            if (byterange_mode)
+                avio_printf(out, "#EXT-X-BYTERANGE:%"PRId64"@%"PRId64"\n",
+                            en->size, en->pos);
+        }
         if (hls->flags & HLS_PROGRAM_DATE_TIME) {
             time_t tt, wrongsecs;
             int milli;
@@ -1097,9 +1107,11 @@  static int hls_window(AVFormatContext *s, int last)
             avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1);
             prog_date_time += en->duration;
         }
-        if (hls->baseurl)
-            avio_printf(out, "%s", hls->baseurl);
-        avio_printf(out, "%s\n", en->filename);
+        if (!((hls->segment_type == SEGMENT_TYPE_FMP4) && (en == hls->segments))) {
+            if (hls->baseurl)
+                avio_printf(out, "%s", hls->baseurl);
+            avio_printf(out, "%s\n", en->filename);
+        }
     }
 
     if (last && (hls->flags & HLS_OMIT_ENDLIST)==0)
@@ -1262,7 +1274,7 @@  static int hls_start(AVFormatContext *s)
     }
     av_dict_free(&options);
 
-    if (c->segment_type == SEGMENT_TYPE_FMP4) {
+    if (c->segment_type == SEGMENT_TYPE_FMP4 && !(c->flags & HLS_SINGLE_FILE)) {
             write_styp(oc->pb);
     } else {
         /* We only require one PAT/PMT per segment. */
@@ -1315,15 +1327,10 @@  static int hls_write_header(AVFormatContext *s)
     const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s);
     const char *vtt_pattern = "%d.vtt";
     AVDictionary *options = NULL;
-    int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0);
     int basename_size;
     int vtt_basename_size;
 
     if (hls->segment_type == SEGMENT_TYPE_FMP4) {
-        if (byterange_mode) {
-            av_log(s, AV_LOG_WARNING, "Have not support fmp4 byterange mode yet now\n");
-            return AVERROR_PATCHWELCOME;
-        }
         pattern = "%d.m4s";
     }
     if ((hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) ||
@@ -1400,8 +1407,13 @@  static int hls_write_header(AVFormatContext *s)
             goto fail;
         }
     } else {
-        if (hls->flags & HLS_SINGLE_FILE)
-            pattern = ".ts";
+        if (hls->flags & HLS_SINGLE_FILE) {
+            if (hls->segment_type == SEGMENT_TYPE_FMP4) {
+                pattern = ".m4s";
+            } else {
+                pattern = ".ts";
+            }
+        }
 
         if (hls->use_localtime) {
             basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1;
@@ -1462,7 +1474,6 @@  static int hls_write_header(AVFormatContext *s)
         }
     }
     if(hls->has_subtitle) {
-
         if (hls->flags & HLS_SINGLE_FILE)
             vtt_pattern = ".vtt";
         vtt_basename_size = strlen(s->filename) + strlen(vtt_pattern) + 1;
@@ -1490,6 +1501,10 @@  static int hls_write_header(AVFormatContext *s)
         av_strlcat(hls->vtt_basename, vtt_pattern, vtt_basename_size);
     }
 
+    if ((hls->flags & HLS_SINGLE_FILE) && (hls->segment_type == SEGMENT_TYPE_FMP4)) {
+        hls->fmp4_init_filename  = av_strdup(hls->basename);
+    }
+
     if ((ret = hls_mux_init(s)) < 0)
         goto fail;
 
@@ -1504,7 +1519,7 @@  static int hls_write_header(AVFormatContext *s)
         }
     }
 
-    if (hls->segment_type != SEGMENT_TYPE_FMP4) {
+    if (hls->segment_type != SEGMENT_TYPE_FMP4 || hls->flags & HLS_SINGLE_FILE) {
         if ((ret = hls_start(s)) < 0)
             goto fail;
     }
@@ -1643,7 +1658,7 @@  static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
             hls->number--;
         }
 
-        if (!hls->fmp4_init_mode)
+        if (!hls->fmp4_init_mode || byterange_mode)
             ret = hls_append_segment(s, hls, hls->duration, hls->start_pos, hls->size);
 
         hls->start_pos = new_start_pos;
@@ -1679,9 +1694,10 @@  static int hls_write_packet(AVFormatContext *s, AVPacket *pkt)
             return ret;
         }
 
-        if ((ret = hls_window(s, 0)) < 0) {
-            return ret;
-        }
+        if (!hls->fmp4_init_mode || byterange_mode)
+            if ((ret = hls_window(s, 0)) < 0) {
+                return ret;
+            }
     }
 
     ret = ff_write_chained(oc, stream_index, pkt, s, 0);