|  | @@ -32,6 +32,7 @@ | 
														
													
														
															
																|  |  | #include "libavutil/avstring.h" |  |  | #include "libavutil/avstring.h" | 
														
													
														
															
																|  |  | #include "libavutil/opt.h" |  |  | #include "libavutil/opt.h" | 
														
													
														
															
																|  |  | #include "libavutil/log.h" |  |  | #include "libavutil/log.h" | 
														
													
														
															
																|  |  |  |  |  | #include "libavutil/time_internal.h" | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | #include "avformat.h" |  |  | #include "avformat.h" | 
														
													
														
															
																|  |  | #include "internal.h" |  |  | #include "internal.h" | 
														
													
												
													
														
															
																|  | @@ -79,6 +80,7 @@ typedef struct HLSContext { | 
														
													
														
															
																|  |  | uint32_t flags;        // enum HLSFlags |  |  | uint32_t flags;        // enum HLSFlags | 
														
													
														
															
																|  |  | char *segment_filename; |  |  | char *segment_filename; | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  |  |  |  | int use_localtime;      ///< flag to expand filename with localtime | 
														
													
														
															
																|  |  | int allowcache; |  |  | int allowcache; | 
														
													
														
															
																|  |  | int64_t recording_time; |  |  | int64_t recording_time; | 
														
													
														
															
																|  |  | int has_video; |  |  | int has_video; | 
														
													
												
													
														
															
																|  | @@ -479,9 +481,18 @@ static int hls_start(AVFormatContext *s) | 
														
													
														
															
																|  |  | av_strlcpy(vtt_oc->filename, c->vtt_basename, |  |  | av_strlcpy(vtt_oc->filename, c->vtt_basename, | 
														
													
														
															
																|  |  | sizeof(vtt_oc->filename)); |  |  | sizeof(vtt_oc->filename)); | 
														
													
														
															
																|  |  | } else { |  |  | } else { | 
														
													
														
															
																|  |  | if (av_get_frame_filename(oc->filename, sizeof(oc->filename), |  |  |  | 
														
													
														
															
																|  |  |  |  |  | if (c->use_localtime) { | 
														
													
														
															
																|  |  |  |  |  | time_t now0; | 
														
													
														
															
																|  |  |  |  |  | struct tm *tm, tmpbuf; | 
														
													
														
															
																|  |  |  |  |  | time(&now0); | 
														
													
														
															
																|  |  |  |  |  | tm = localtime_r(&now0, &tmpbuf); | 
														
													
														
															
																|  |  |  |  |  | if (!strftime(oc->filename, sizeof(oc->filename), c->basename, tm)) { | 
														
													
														
															
																|  |  |  |  |  | av_log(oc, AV_LOG_ERROR, "Could not get segment filename with use_localtime\n"); | 
														
													
														
															
																|  |  |  |  |  | return AVERROR(EINVAL); | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  |  |  |  | } else if (av_get_frame_filename(oc->filename, sizeof(oc->filename), | 
														
													
														
															
																|  |  | c->basename, c->wrap ? c->sequence % c->wrap : c->sequence) < 0) { |  |  | c->basename, c->wrap ? c->sequence % c->wrap : c->sequence) < 0) { | 
														
													
														
															
																|  |  | av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->basename); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try use -use_localtime 1 with it\n", c->basename); | 
														
													
														
															
																|  |  | return AVERROR(EINVAL); |  |  | return AVERROR(EINVAL); | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | if( c->vtt_basename) { |  |  | if( c->vtt_basename) { | 
														
													
												
													
														
															
																|  | @@ -542,6 +553,7 @@ static int hls_write_header(AVFormatContext *s) | 
														
													
														
															
																|  |  | int ret, i; |  |  | int ret, i; | 
														
													
														
															
																|  |  | char *p; |  |  | char *p; | 
														
													
														
															
																|  |  | const char *pattern = "%d.ts"; |  |  | const char *pattern = "%d.ts"; | 
														
													
														
															
																|  |  |  |  |  | const char *pattern_localtime_fmt = "-%s.ts"; | 
														
													
														
															
																|  |  | const char *vtt_pattern = "%d.vtt"; |  |  | const char *vtt_pattern = "%d.vtt"; | 
														
													
														
															
																|  |  | AVDictionary *options = NULL; |  |  | AVDictionary *options = NULL; | 
														
													
														
															
																|  |  | int basename_size; |  |  | int basename_size; | 
														
													
												
													
														
															
																|  | @@ -596,7 +608,11 @@ static int hls_write_header(AVFormatContext *s) | 
														
													
														
															
																|  |  | if (hls->flags & HLS_SINGLE_FILE) |  |  | if (hls->flags & HLS_SINGLE_FILE) | 
														
													
														
															
																|  |  | pattern = ".ts"; |  |  | pattern = ".ts"; | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | basename_size = strlen(s->filename) + strlen(pattern) + 1; |  |  |  | 
														
													
														
															
																|  |  |  |  |  | if (hls->use_localtime) { | 
														
													
														
															
																|  |  |  |  |  | basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1; | 
														
													
														
															
																|  |  |  |  |  | } else { | 
														
													
														
															
																|  |  |  |  |  | basename_size = strlen(s->filename) + strlen(pattern) + 1; | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  | hls->basename = av_malloc(basename_size); |  |  | hls->basename = av_malloc(basename_size); | 
														
													
														
															
																|  |  | if (!hls->basename) { |  |  | if (!hls->basename) { | 
														
													
														
															
																|  |  | ret = AVERROR(ENOMEM); |  |  | ret = AVERROR(ENOMEM); | 
														
													
												
													
														
															
																|  | @@ -608,7 +624,11 @@ static int hls_write_header(AVFormatContext *s) | 
														
													
														
															
																|  |  | p = strrchr(hls->basename, '.'); |  |  | p = strrchr(hls->basename, '.'); | 
														
													
														
															
																|  |  | if (p) |  |  | if (p) | 
														
													
														
															
																|  |  | *p = '\0'; |  |  | *p = '\0'; | 
														
													
														
															
																|  |  | av_strlcat(hls->basename, pattern, basename_size); |  |  |  | 
														
													
														
															
																|  |  |  |  |  | if (hls->use_localtime) { | 
														
													
														
															
																|  |  |  |  |  | av_strlcat(hls->basename, pattern_localtime_fmt, basename_size); | 
														
													
														
															
																|  |  |  |  |  | } else { | 
														
													
														
															
																|  |  |  |  |  | av_strlcat(hls->basename, pattern, basename_size); | 
														
													
														
															
																|  |  |  |  |  | } | 
														
													
														
															
																|  |  | } |  |  | } | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | if(hls->has_subtitle) { |  |  | if(hls->has_subtitle) { | 
														
													
												
													
														
															
																|  | @@ -817,6 +837,7 @@ static const AVOption options[] = { | 
														
													
														
															
																|  |  | {"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX,   E, "flags"}, |  |  | {"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX,   E, "flags"}, | 
														
													
														
															
																|  |  | {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX,   E, "flags"}, |  |  | {"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX,   E, "flags"}, | 
														
													
														
															
																|  |  | {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX,   E, "flags"}, |  |  | {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX,   E, "flags"}, | 
														
													
														
															
																|  |  |  |  |  | { "use_localtime",          "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, E }, | 
														
													
														
															
																|  |  | 
 |  |  | 
 | 
														
													
														
															
																|  |  | { NULL }, |  |  | { NULL }, | 
														
													
														
															
																|  |  | }; |  |  | }; | 
														
													
												
													
														
															
																|  | 
 |