Browse code

avformat/hlsenc: Add support for HLS PLAYLIST types EVENT and VOD

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>

Adam Kent authored on 2015/12/17 12:16:45
Showing 2 changed files
... ...
@@ -408,6 +408,14 @@ Will produce the playlist, @file{out.m3u8}, and a single segment file,
408 408
 @item hls_flags delete_segments
409 409
 Segment files removed from the playlist are deleted after a period of time
410 410
 equal to the duration of the segment plus the duration of the playlist.
411
+
412
+@item hls_playlist_type event
413
+Emit @code{#EXT-X-PLAYLIST-TYPE:EVENT} in the m3u8 header. Forces
414
+@option{hls_list_size} to 0; the playlist can only be appended to.
415
+
416
+@item hls_playlist_type vod
417
+Emit @code{#EXT-X-PLAYLIST-TYPE:VOD} in the m3u8 header. Forces
418
+@option{hls_list_size} to 0; the playlist must not change.
411 419
 @end table
412 420
 
413 421
 @anchor{ico}
... ...
@@ -64,6 +64,13 @@ typedef enum HLSFlags {
64 64
     HLS_OMIT_ENDLIST = (1 << 4),
65 65
 } HLSFlags;
66 66
 
67
+typedef enum {
68
+    PLAYLIST_TYPE_NONE,
69
+    PLAYLIST_TYPE_EVENT,
70
+    PLAYLIST_TYPE_VOD,
71
+    PLAYLIST_TYPE_NB,
72
+} PlaylistType;
73
+
67 74
 typedef struct HLSContext {
68 75
     const AVClass *class;  // Class for private options.
69 76
     unsigned number;
... ...
@@ -79,6 +86,7 @@ typedef struct HLSContext {
79 79
     int max_nb_segments;   // Set by a private option.
80 80
     int  wrap;             // Set by a private option.
81 81
     uint32_t flags;        // enum HLSFlags
82
+    uint32_t pl_type;      // enum PlaylistType
82 83
     char *segment_filename;
83 84
 
84 85
     int use_localtime;      ///< flag to expand filename with localtime
... ...
@@ -357,6 +365,10 @@ static int hls_append_segment(struct AVFormatContext *s, HLSContext *hls, double
357 357
 
358 358
     hls->last_segment = en;
359 359
 
360
+    // EVENT or VOD playlists imply sliding window cannot be used
361
+    if (hls->pl_type != PLAYLIST_TYPE_NONE)
362
+        hls->max_nb_segments = 0;
363
+
360 364
     if (hls->max_nb_segments && hls->nb_entries >= hls->max_nb_segments) {
361 365
         en = hls->segments;
362 366
         hls->segments = en->next;
... ...
@@ -432,6 +444,11 @@ static int hls_window(AVFormatContext *s, int last)
432 432
     }
433 433
     avio_printf(out, "#EXT-X-TARGETDURATION:%d\n", target_duration);
434 434
     avio_printf(out, "#EXT-X-MEDIA-SEQUENCE:%"PRId64"\n", sequence);
435
+    if (hls->pl_type == PLAYLIST_TYPE_EVENT) {
436
+        avio_printf(out, "#EXT-X-PLAYLIST-TYPE:EVENT\n");
437
+    } else if (hls->pl_type == PLAYLIST_TYPE_VOD) {
438
+        avio_printf(out, "#EXT-X-PLAYLIST-TYPE:VOD\n");
439
+    }
435 440
 
436 441
     av_log(s, AV_LOG_VERBOSE, "EXT-X-MEDIA-SEQUENCE:%"PRId64"\n",
437 442
            sequence);
... ...
@@ -908,6 +925,9 @@ static const AVOption options[] = {
908 908
     {"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX,   E, "flags"},
909 909
     {"use_localtime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
910 910
     {"use_localtime_mkdir", "create last directory component in strftime-generated filename", OFFSET(use_localtime_mkdir), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, E },
911
+    {"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" },
912
+    {"event", "EVENT playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_EVENT }, INT_MIN, INT_MAX, E, "pl_type" },
913
+    {"vod", "VOD playlist", 0, AV_OPT_TYPE_CONST, {.i64 = PLAYLIST_TYPE_VOD }, INT_MIN, INT_MAX, E, "pl_type" },
911 914
     {"method", "set the HTTP method", OFFSET(method), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,    E},
912 915
 
913 916
     { NULL },