Browse code

avformat/hlsenc: implement program_date_time

Reviewed-by: Steven Liu <lingjiujianke@gmail.com>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>

Michael Niedermayer authored on 2016/09/08 04:34:44
Showing 3 changed files
... ...
@@ -522,6 +522,9 @@ behavior on some players when the time between keyframes is inconsistent,
522 522
 but may make things worse on others, and can cause some oddities during
523 523
 seeking. This flag should be used with the @code{hls_time} option.
524 524
 
525
+@item hls_flags program_date_time
526
+Generate @code{EXT-X-PROGRAM-DATE-TIME} tags.
527
+
525 528
 @item hls_playlist_type event
526 529
 Emit @code{#EXT-X-PLAYLIST-TYPE:EVENT} in the m3u8 header. Forces
527 530
 @option{hls_list_size} to 0; the playlist can only be appended to.
... ...
@@ -64,6 +64,7 @@ typedef enum HLSFlags {
64 64
     HLS_OMIT_ENDLIST = (1 << 4),
65 65
     HLS_SPLIT_BY_TIME = (1 << 5),
66 66
     HLS_APPEND_LIST = (1 << 6),
67
+    HLS_PROGRAM_DATE_TIME = (1 << 7),
67 68
 } HLSFlags;
68 69
 
69 70
 typedef enum {
... ...
@@ -128,6 +129,7 @@ typedef struct HLSContext {
128 128
 
129 129
     char *method;
130 130
 
131
+    double initial_prog_date_time;
131 132
 } HLSContext;
132 133
 
133 134
 static int hls_delete_old_segments(HLSContext *hls) {
... ...
@@ -481,6 +483,7 @@ static int hls_window(AVFormatContext *s, int last)
481 481
     char *key_uri = NULL;
482 482
     char *iv_string = NULL;
483 483
     AVDictionary *options = NULL;
484
+    double prog_date_time = hls->initial_prog_date_time;
484 485
 
485 486
     if (!use_rename && !warned_non_file++)
486 487
         av_log(s, AV_LOG_ERROR, "Cannot use rename on non file protocol, this may lead to races and temporarly partial files\n");
... ...
@@ -533,6 +536,19 @@ static int hls_window(AVFormatContext *s, int last)
533 533
         if (hls->flags & HLS_SINGLE_FILE)
534 534
              avio_printf(out, "#EXT-X-BYTERANGE:%"PRIi64"@%"PRIi64"\n",
535 535
                          en->size, en->pos);
536
+        if (hls->flags & HLS_PROGRAM_DATE_TIME) {
537
+            time_t tt;
538
+            int milli;
539
+            struct tm *tm, tmpbuf;
540
+            char buf0[128], buf1[128];
541
+            tt = (int64_t)prog_date_time;
542
+            milli = av_clip(lrint(1000*(prog_date_time - tt)), 0, 999);
543
+            tm = localtime_r(&tt, &tmpbuf);
544
+            strftime(buf0, sizeof(buf0), "%FT%T", tm);
545
+            strftime(buf1, sizeof(buf1), "%z", tm);
546
+            avio_printf(out, "#EXT-X-PROGRAM-DATE-TIME:%s.%03d%s\n", buf0, milli, buf1);
547
+            prog_date_time += en->duration;
548
+        }
536 549
         if (hls->baseurl)
537 550
             avio_printf(out, "%s", hls->baseurl);
538 551
         avio_printf(out, "%s\n", en->filename);
... ...
@@ -710,6 +726,12 @@ static int hls_write_header(AVFormatContext *s)
710 710
     hls->recording_time = (hls->init_time ? hls->init_time : hls->time) * AV_TIME_BASE;
711 711
     hls->start_pts      = AV_NOPTS_VALUE;
712 712
 
713
+    if (hls->flags & HLS_PROGRAM_DATE_TIME) {
714
+        time_t now0;
715
+        time(&now0);
716
+        hls->initial_prog_date_time = now0;
717
+    }
718
+
713 719
     if (hls->format_options_str) {
714 720
         ret = av_dict_parse_string(&hls->format_options, hls->format_options_str, "=", ":", 0);
715 721
         if (ret < 0) {
... ...
@@ -1005,6 +1027,7 @@ static const AVOption options[] = {
1005 1005
     {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX,   E, "flags"},
1006 1006
     {"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"},
1007 1007
     {"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"},
1008
+    {"program_date_time", "add EXT-X-PROGRAM-DATE-TIME", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_PROGRAM_DATE_TIME }, 0, UINT_MAX,   E, "flags"},
1008 1009
     {"use_localtime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1009 1010
     {"use_localtime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
1010 1011
     {"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" },
... ...
@@ -33,7 +33,7 @@
33 33
 // Also please add any ticket numbers that you believe might be affected here
34 34
 #define LIBAVFORMAT_VERSION_MAJOR  57
35 35
 #define LIBAVFORMAT_VERSION_MINOR  48
36
-#define LIBAVFORMAT_VERSION_MICRO 102
36
+#define LIBAVFORMAT_VERSION_MICRO 103
37 37
 
38 38
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
39 39
                                                LIBAVFORMAT_VERSION_MINOR, \