[FFmpeg-devel] avformat/hlsenc: strftime identifiers and segment index in segment filenames

Submitted by Steven Liu on Dec. 27, 2016, 2:42 a.m.

Details

Message ID CADxeRwmfKGdDxzTjCReF3M-8JdK4HVPF7De2wAre2uj7apmbtA@mail.gmail.com
State New
Headers show

Commit Message

Steven Liu Dec. 27, 2016, 2:42 a.m.
2016-12-27 9:30 GMT+08:00 Bodecs Bela <bodecsb@vivanet.hu>:

>
>
> Dear All,
>
>
> Putting date/time values into segment filenames is very usefull.
> But to produce non-conflicting segment filenames with -use_localtime
> option with date/time
> values in hls_segment_filename option, sometimes is not enough.
> Like in cases when multiple segments produced in the same second.
> But hlsenc currently does not make possible to use segment index (%d) at
> the
>
> same time whe use_localtime is in effect, due to identifier conflict.
> This patch makes possible to use strftime identifiers and still put
> segment index (%d) at same time in segment filenames by introducing
> second_level_segment_index flag. When -use_localtime is active,
> identifier %d is for month day index, so %%d is the segment index
> placeholder. This enhanced behaviour only exists when new
> second_level_segment_index flag is specified.
> For instance putting 'segment_%Y%m%d%H%M%S_%%05d.ts' value into
> -hls_segment_filename option and specifing -hls_flags
> second_level_segment_index and -use_localtime 1, may produce segment
> filename as 'segment_20161230235758_00002.ts'
>
>
> An example:
>
> ffmpeg -loglevel info -y -f lavfi -i color=c=red:size=640x480:r=25 -f
> lavfi -i anullsrc=r=44100:cl=stereo -c:v mpeg2video -g 25 -acodec aac
> -cutoff 20000 -ac 2 -ar 44100 -ab 192k -f hls -hls_time 3 -hls_list_size
> 5 -hls_flags delete_segments+second_level_segment_index -use_localtime 1
> -hls_segment_filename "segment_%Y%m%d%H%M%S_%%05d.ts" stream.m3u8
>
> will produce segments filenames:
>
> ....
> segment_20161227005902_00013.ts
> segment_20161227005902_00014.ts
> segment_20161227005902_00015.ts
> segment_20161227005903_00016.ts
> segment_20161227005903_00017.ts
> segment_20161227005903_00018.ts
> segment_20161227005903_00019.ts
> segment_20161227005903_00020.ts
> ....
>
>
> thank you,
>
> best regards,
>
> Bela Bodecs
>
>
>
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> Signed-off-by: Bela Bodecs <bodecsb@vivanet.hu>
---
 doc/muxers.texi      | 11 ++++++++++-
 libavformat/hlsenc.c | 22 ++++++++++++++++++++--
 2 files changed, 30 insertions(+), 3 deletions(-)

 typedef enum {
@@ -717,7 +718,19 @@ static int hls_start(AVFormatContext *s)
                 av_log(oc, AV_LOG_ERROR, "Could not get segment filename
with use_localtime\n");
                 return AVERROR(EINVAL);
             }
-
+            if (c->flags & HLS_SECOND_LEVEL_SEGMENT_INDEX) {
+                char * filename = av_strdup(oc->filename);  // %%d will be
%d after strftime
+                if (!filename)
+                    return AVERROR(ENOMEM);
+                if (av_get_frame_filename2(oc->filename,
sizeof(oc->filename),
+                    filename, c->wrap ? c->sequence % c->wrap :
c->sequence,
+                    AV_FRAME_FILENAME_FLAGS_MULTIPLE) < 0) {
+                    av_log(c, AV_LOG_ERROR, "Invalid second level segment
filename template '%s', you can try to remove second_level_segment_index
flag\n", filename);
+                    av_free(filename);
+                    return AVERROR(EINVAL);
+                }
+                av_free(filename);
+            }
             if (find_segment_by_filename(c->segments, oc->filename)
                 || find_segment_by_filename(c->old_segments,
oc->filename)) {
                 av_log(c, AV_LOG_WARNING, "Duplicated segment filename
detected: %s\n", oc->filename);
@@ -900,7 +913,11 @@ static int hls_write_header(AVFormatContext *s)
             av_strlcat(hls->basename, pattern, basename_size);
         }
     }
-
+    if (!hls->use_localtime && (hls->flags &
HLS_SECOND_LEVEL_SEGMENT_INDEX)) {
+        av_log(hls, AV_LOG_ERROR, "second_level_segment_index hls_flag
requires use_localtime to be true\n");
+        ret = AVERROR(EINVAL);
+        goto fail;
+    }
     if(hls->has_subtitle) {

         if (hls->flags & HLS_SINGLE_FILE)
@@ -1156,6 +1173,7 @@ static const AVOption options[] = {
     {"split_by_time", "split the hls segment by time which user set by
hls_time", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SPLIT_BY_TIME }, 0, UINT_MAX,
  E, "flags"},
     {"append_list", "append the new segments into old hls segment list",
0, AV_OPT_TYPE_CONST, {.i64 = HLS_APPEND_LIST }, 0, UINT_MAX,   E, "flags"},
     {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0,
AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 0, UINT_MAX,   E,
"flags"},
+    {"second_level_segment_index", "include segment index in segment
filenames when use_localtime", 0, AV_OPT_TYPE_CONST, {.i64 =
HLS_SECOND_LEVEL_SEGMENT_INDEX }, 0, UINT_MAX,   E, "flags"},
     {"use_localtime", "set filename expansion with strftime at segment
creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
     {"use_localtime_mkdir", "create last directory component in
strftime-generated filename", OFFSET(use_localtime_mkdir),
AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
     {"hls_playlist_type", "set the HLS playlist type", OFFSET(pl_type),
AV_OPT_TYPE_INT, {.i64 = PLAYLIST_TYPE_NONE }, 0, PLAYLIST_TYPE_NB-1, E,
"pl_type" },

Patch hide | download patch | download mbox

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 075b8d3..3520120 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -443,12 +443,18 @@  This example will produce the playlist,
@file{out.m3u8}, and segment files:

 @item use_localtime
 Use strftime on @var{filename} to expand the segment filename with
localtime.
-The segment number (%d) is not available in this mode.
+The segment number is also available in this mode, but to use it, you need
to specify second_level_segment_index
+hls_flag and %%d will be the specifier.
 @example
 ffmpeg -i in.nut -use_localtime 1 -hls_segment_filename
'file-%Y%m%d-%s.ts' out.m3u8
 @end example
 This example will produce the playlist, @file{out.m3u8}, and segment files:
 @file{file-20160215-1455569023.ts}, @file{file-20160215-1455569024.ts},
etc.
+@example
+ffmpeg -i in.nut -use_localtime 1 -hls_flags second_level_segment_index
-hls_segment_filename 'file-%Y%m%d-%%04d.ts' out.m3u8
+@end example
+This example will produce the playlist, @file{out.m3u8}, and segment files:
+@file{file-20160215-0001.ts}, @file{file-20160215-0002.ts}, etc.

 @item use_localtime_mkdir
 Used together with -use_localtime, it will create up to one subdirectory
which
@@ -556,6 +562,9 @@  seeking. This flag should be used with the
@code{hls_time} option.
 @item hls_flags program_date_time
 Generate @code{EXT-X-PROGRAM-DATE-TIME} tags.

+@item hls_flags second_level_segment_index
+Makes it possible to use segment indexes as %%d besides date/time values
when use_localtime is on.
+
 @item hls_playlist_type event
 Emit @code{#EXT-X-PLAYLIST-TYPE:EVENT} in the m3u8 header. Forces
 @option{hls_list_size} to 0; the playlist can only be appended to.
diff --git a/libavformat/hlsenc.c b/libavformat/hlsenc.c
index e46e9b4..a20666a 100644
--- a/libavformat/hlsenc.c
+++ b/libavformat/hlsenc.c
@@ -66,6 +66,7 @@  typedef enum HLSFlags {
     HLS_SPLIT_BY_TIME = (1 << 5),
     HLS_APPEND_LIST = (1 << 6),
     HLS_PROGRAM_DATE_TIME = (1 << 7),
+    HLS_SECOND_LEVEL_SEGMENT_INDEX = (1 << 8), // include segment index in
segment filenames when use_localtime  e.g.: %%03d
 } HLSFlags;