This option allows segment filenames to be specified. Unless -hls_flags
single_file is set the filename is used as a string format with the
segment number.
Example:
ffmpeg -f lavfi -i testsrc -c:v h264 -map 0 -hls_segment_filename
bar%03d.ts foo.m3u8
Signed-off-by: Christian Suloway <csuloway@globaleagleent.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -254,6 +254,15 @@ and it is not to be confused with the segment filename sequence number |
254 | 254 |
which can be cyclic, for example if the @option{wrap} option is |
255 | 255 |
specified. |
256 | 256 |
|
257 |
+@item hls_segment_filename @var{filename} |
|
258 |
+Set the segment filename. Unless hls_flags single_file is set @var{filename} |
|
259 |
+is used as a string format with the segment number: |
|
260 |
+@example |
|
261 |
+ffmpeg in.nut -hls_segment_filename 'file%03d.ts' out.m3u8 |
|
262 |
+@end example |
|
263 |
+This example will produce the playlist, @file{out.m3u8}, and segment files: |
|
264 |
+@file{file000.ts}, @file{file001.ts}, @file{file002.ts}, etc. |
|
265 |
+ |
|
257 | 266 |
@item hls_flags single_file |
258 | 267 |
If this flag is set, the muxer will store all segments in a single MPEG-TS |
259 | 268 |
file, and will use byte ranges in the playlist. HLS playlists generated with |
... | ... |
@@ -59,6 +59,7 @@ typedef struct HLSContext { |
59 | 59 |
int max_nb_segments; // Set by a private option. |
60 | 60 |
int wrap; // Set by a private option. |
61 | 61 |
uint32_t flags; // enum HLSFlags |
62 |
+ char *segment_filename; |
|
62 | 63 |
|
63 | 64 |
int allowcache; |
64 | 65 |
int64_t recording_time; |
... | ... |
@@ -237,15 +238,12 @@ static int hls_write_header(AVFormatContext *s) |
237 | 237 |
char *p; |
238 | 238 |
const char *pattern = "%d.ts"; |
239 | 239 |
AVDictionary *options = NULL; |
240 |
- int basename_size = strlen(s->filename) + strlen(pattern) + 1; |
|
240 |
+ int basename_size; |
|
241 | 241 |
|
242 | 242 |
hls->sequence = hls->start_sequence; |
243 | 243 |
hls->recording_time = hls->time * AV_TIME_BASE; |
244 | 244 |
hls->start_pts = AV_NOPTS_VALUE; |
245 | 245 |
|
246 |
- if (hls->flags & HLS_SINGLE_FILE) |
|
247 |
- pattern = ".ts"; |
|
248 |
- |
|
249 | 246 |
if (hls->format_options_str) { |
250 | 247 |
ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0); |
251 | 248 |
if (ret < 0) { |
... | ... |
@@ -270,21 +268,30 @@ static int hls_write_header(AVFormatContext *s) |
270 | 270 |
goto fail; |
271 | 271 |
} |
272 | 272 |
|
273 |
- hls->basename = av_malloc(basename_size); |
|
274 |
- |
|
275 |
- if (!hls->basename) { |
|
276 |
- ret = AVERROR(ENOMEM); |
|
277 |
- goto fail; |
|
278 |
- } |
|
279 |
- |
|
280 |
- strcpy(hls->basename, s->filename); |
|
273 |
+ if (hls->segment_filename) { |
|
274 |
+ hls->basename = av_strdup(hls->segment_filename); |
|
275 |
+ if (!hls->basename) { |
|
276 |
+ ret = AVERROR(ENOMEM); |
|
277 |
+ goto fail; |
|
278 |
+ } |
|
279 |
+ } else { |
|
280 |
+ if (hls->flags & HLS_SINGLE_FILE) |
|
281 |
+ pattern = ".ts"; |
|
281 | 282 |
|
282 |
- p = strrchr(hls->basename, '.'); |
|
283 |
+ basename_size = strlen(s->filename) + strlen(pattern) + 1; |
|
284 |
+ hls->basename = av_malloc(basename_size); |
|
285 |
+ if (!hls->basename) { |
|
286 |
+ ret = AVERROR(ENOMEM); |
|
287 |
+ goto fail; |
|
288 |
+ } |
|
283 | 289 |
|
284 |
- if (p) |
|
285 |
- *p = '\0'; |
|
290 |
+ av_strlcpy(hls->basename, s->filename, basename_size); |
|
286 | 291 |
|
287 |
- av_strlcat(hls->basename, pattern, basename_size); |
|
292 |
+ p = strrchr(hls->basename, '.'); |
|
293 |
+ if (p) |
|
294 |
+ *p = '\0'; |
|
295 |
+ av_strlcat(hls->basename, pattern, basename_size); |
|
296 |
+ } |
|
288 | 297 |
|
289 | 298 |
if ((ret = hls_mux_init(s)) < 0) |
290 | 299 |
goto fail; |
... | ... |
@@ -410,6 +417,7 @@ static const AVOption options[] = { |
410 | 410 |
{"hls_wrap", "set number after which the index wraps", OFFSET(wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E}, |
411 | 411 |
{"hls_allow_cache", "explicitly set whether the client MAY (1) or MUST NOT (0) cache media segments", OFFSET(allowcache), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, E}, |
412 | 412 |
{"hls_base_url", "url to prepend to each playlist entry", OFFSET(baseurl), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, |
413 |
+ {"hls_segment_filename", "filename template for segment files", OFFSET(segment_filename), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E}, |
|
413 | 414 |
{"hls_flags", "set flags affecting HLS playlist and media file generation", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = 0 }, 0, UINT_MAX, E, "flags"}, |
414 | 415 |
{"single_file", "generate a single media file indexed with byte ranges", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_SINGLE_FILE }, 0, UINT_MAX, E, "flags"}, |
415 | 416 |
|