ticket-id: #6541
when use hls fmp4 muxer, the extention name is not .m4s, this
code can fix it.
Found-by: JohnPi
Signed-off-by: Steven Liu <lq@onvideo.cn>
... | ... |
@@ -147,6 +147,7 @@ typedef struct HLSContext { |
147 | 147 |
HLSSegment *old_segments; |
148 | 148 |
|
149 | 149 |
char *basename; |
150 |
+ char *base_output_dirname; |
|
150 | 151 |
char *vtt_basename; |
151 | 152 |
char *vtt_m3u8_name; |
152 | 153 |
char *baseurl; |
... | ... |
@@ -584,7 +585,7 @@ static int hls_mux_init(AVFormatContext *s) |
584 | 584 |
|
585 | 585 |
if (hls->segment_type == SEGMENT_TYPE_FMP4) { |
586 | 586 |
hls->fmp4_init_mode = 1; |
587 |
- if ((ret = s->io_open(s, &oc->pb, hls->fmp4_init_filename, AVIO_FLAG_WRITE, NULL)) < 0) { |
|
587 |
+ if ((ret = s->io_open(s, &oc->pb, hls->base_output_dirname, AVIO_FLAG_WRITE, NULL)) < 0) { |
|
588 | 588 |
av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", hls->fmp4_init_filename); |
589 | 589 |
return ret; |
590 | 590 |
} |
... | ... |
@@ -1286,14 +1287,19 @@ fail: |
1286 | 1286 |
return err; |
1287 | 1287 |
} |
1288 | 1288 |
|
1289 |
-static const char * get_default_pattern_localtime_fmt(void) |
|
1289 |
+static const char * get_default_pattern_localtime_fmt(AVFormatContext *s) |
|
1290 | 1290 |
{ |
1291 | 1291 |
char b[21]; |
1292 | 1292 |
time_t t = time(NULL); |
1293 | 1293 |
struct tm *p, tmbuf; |
1294 |
+ HLSContext *hls = s->priv_data; |
|
1295 |
+ |
|
1294 | 1296 |
p = localtime_r(&t, &tmbuf); |
1295 | 1297 |
// no %s support when strftime returned error or left format string unchanged |
1296 | 1298 |
// also no %s support on MSVC, which invokes the invalid parameter handler on unsupported format strings, instead of returning an error |
1299 |
+ if (hls->segment_type == SEGMENT_TYPE_FMP4) { |
|
1300 |
+ return (HAVE_LIBC_MSVCRT || !strftime(b, sizeof(b), "%s", p) || !strcmp(b, "%s")) ? "-%Y%m%d%H%M%S.m4s" : "-%s.m4s"; |
|
1301 |
+ } |
|
1297 | 1302 |
return (HAVE_LIBC_MSVCRT || !strftime(b, sizeof(b), "%s", p) || !strcmp(b, "%s")) ? "-%Y%m%d%H%M%S.ts" : "-%s.ts"; |
1298 | 1303 |
} |
1299 | 1304 |
|
... | ... |
@@ -1303,16 +1309,19 @@ static int hls_write_header(AVFormatContext *s) |
1303 | 1303 |
int ret, i; |
1304 | 1304 |
char *p; |
1305 | 1305 |
const char *pattern = "%d.ts"; |
1306 |
- const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(); |
|
1306 |
+ const char *pattern_localtime_fmt = get_default_pattern_localtime_fmt(s); |
|
1307 | 1307 |
const char *vtt_pattern = "%d.vtt"; |
1308 | 1308 |
AVDictionary *options = NULL; |
1309 | 1309 |
int byterange_mode = (hls->flags & HLS_SINGLE_FILE) || (hls->max_seg_size > 0); |
1310 | 1310 |
int basename_size; |
1311 | 1311 |
int vtt_basename_size; |
1312 | 1312 |
|
1313 |
- if (hls->segment_type == SEGMENT_TYPE_FMP4 && byterange_mode) { |
|
1314 |
- av_log(s, AV_LOG_WARNING, "Have not support fmp4 byterange mode yet now\n"); |
|
1315 |
- return AVERROR_PATCHWELCOME; |
|
1313 |
+ if (hls->segment_type == SEGMENT_TYPE_FMP4) { |
|
1314 |
+ if (byterange_mode) { |
|
1315 |
+ av_log(s, AV_LOG_WARNING, "Have not support fmp4 byterange mode yet now\n"); |
|
1316 |
+ return AVERROR_PATCHWELCOME; |
|
1317 |
+ } |
|
1318 |
+ pattern = "%d.m4s"; |
|
1316 | 1319 |
} |
1317 | 1320 |
if ((hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_SECONDS_SINCE_EPOCH) || |
1318 | 1321 |
(hls->start_sequence_source_type == HLS_START_SEQUENCE_AS_FORMATTED_DATETIME)) { |
... | ... |
@@ -1412,6 +1421,31 @@ static int hls_write_header(AVFormatContext *s) |
1412 | 1412 |
} else { |
1413 | 1413 |
av_strlcat(hls->basename, pattern, basename_size); |
1414 | 1414 |
} |
1415 |
+ |
|
1416 |
+ if (av_strcasecmp(hls->fmp4_init_filename, "init.mp4")) { |
|
1417 |
+ int fmp4_init_filename_len = strlen(hls->fmp4_init_filename) + 1; |
|
1418 |
+ hls->base_output_dirname = av_malloc(fmp4_init_filename_len); |
|
1419 |
+ if (!hls->base_output_dirname) { |
|
1420 |
+ ret = AVERROR(ENOMEM); |
|
1421 |
+ goto fail; |
|
1422 |
+ } |
|
1423 |
+ av_strlcpy(hls->base_output_dirname, hls->fmp4_init_filename, fmp4_init_filename_len); |
|
1424 |
+ } else { |
|
1425 |
+ hls->base_output_dirname = av_malloc(basename_size); |
|
1426 |
+ if (!hls->base_output_dirname) { |
|
1427 |
+ ret = AVERROR(ENOMEM); |
|
1428 |
+ goto fail; |
|
1429 |
+ } |
|
1430 |
+ |
|
1431 |
+ av_strlcpy(hls->base_output_dirname, s->filename, basename_size); |
|
1432 |
+ p = strrchr(hls->base_output_dirname, '/'); |
|
1433 |
+ if (p) { |
|
1434 |
+ *(p + 1) = '\0'; |
|
1435 |
+ av_strlcat(hls->base_output_dirname, hls->fmp4_init_filename, basename_size); |
|
1436 |
+ } else { |
|
1437 |
+ av_strlcpy(hls->base_output_dirname, hls->fmp4_init_filename, basename_size); |
|
1438 |
+ } |
|
1439 |
+ } |
|
1415 | 1440 |
} |
1416 | 1441 |
if (!hls->use_localtime) { |
1417 | 1442 |
ret = sls_flag_check_duration_size_index(hls); |
... | ... |
@@ -1686,6 +1720,7 @@ static int hls_write_trailer(struct AVFormatContext *s) |
1686 | 1686 |
ff_format_io_close(s, &vtt_oc->pb); |
1687 | 1687 |
} |
1688 | 1688 |
av_freep(&hls->basename); |
1689 |
+ av_freep(&hls->base_output_dirname); |
|
1689 | 1690 |
av_freep(&hls->key_basename); |
1690 | 1691 |
avformat_free_context(oc); |
1691 | 1692 |
|