Browse code

avformat/hlsenc: fix hls fmp4 extention name bug

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>

Steven Liu authored on 2017/07/24 20:55:19
Showing 1 changed files
... ...
@@ -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