[FFmpeg-devel] [PATCH] avformat/hlsenc: support fmp4 single file mode
Steven Liu
lq at chinaffmpeg.org
Mon Jul 31 07:03:15 EEST 2017
add byterange mode of the hls fmp4
Signed-off-by: Steven Liu <lq at 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);
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);
--
2.10.1.382.ga23ca1b.dirty
More information about the ffmpeg-devel
mailing list