Browse code

lavf/segment: add segment_list_type option, extend format for the segment list file

Add list extended format which specifies in the list file the start and
ending time for each segment. This is required to make it available this
information to external tools, avoiding the need to perform file analysis
in the output segments.

Stefano Sabatini authored on 2012/01/14 07:29:09
Showing 3 changed files
... ...
@@ -450,6 +450,30 @@ listfile is generated.
450 450
 @item segment_list_size @var{size}
451 451
 Overwrite the listfile once it reaches @var{size} entries. If 0
452 452
 the listfile is never overwritten. Default value is 5.
453
+@item segment_list type @var{type}
454
+Specify the format for the segment list file.
455
+
456
+The following values are recognized:
457
+@table @option
458
+@item flat
459
+Generate a flat list for the created segments, one segment per line.
460
+
461
+@item ext
462
+Generate a list for the created segments, one segment per line,
463
+each line matching the format:
464
+@example
465
+@var{segment_filename},@var{segment_start_time},@var{segment_end_time}
466
+@end example
467
+
468
+@var{segment_filename} is the name of the output file generated by the
469
+muxer according to the provided pattern, and should not contain the
470
+"," character for simplifying parsing operations.
471
+
472
+@var{segment_start_time} and @var{segment_end_time} specify
473
+the segment start and end time expressed in seconds.
474
+@end table
475
+
476
+Default value is "flat".
453 477
 @item segment_wrap @var{limit}
454 478
 Wrap around segment index once it reaches @var{limit}.
455 479
 @end table
... ...
@@ -30,6 +30,12 @@
30 30
 #include "libavutil/parseutils.h"
31 31
 #include "libavutil/mathematics.h"
32 32
 
33
+typedef enum {
34
+    LIST_TYPE_FLAT = 0,
35
+    LIST_TYPE_EXT,
36
+    LIST_TYPE_NB,
37
+} ListType;
38
+
33 39
 typedef struct {
34 40
     const AVClass *class;  /**< Class for private options. */
35 41
     int number;
... ...
@@ -37,11 +43,13 @@ typedef struct {
37 37
     char *format;          ///< format to use for output segment files
38 38
     char *list;            ///< filename for the segment list file
39 39
     int   list_size;       ///< number of entries for the segment list file
40
+    ListType list_type;    ///< set the list type
40 41
     AVIOContext *list_pb;  ///< list file put-byte context
41 42
     float time;            ///< segment duration
42 43
     int  wrap;             ///< number after which the index wraps
43 44
     int64_t recording_time;
44 45
     int has_video;
46
+    double start_time, end_time;
45 47
 } SegmentContext;
46 48
 
47 49
 static int segment_start(AVFormatContext *s)
... ...
@@ -110,7 +118,12 @@ static int segment_end(AVFormatContext *s)
110 110
                                   &s->interrupt_callback, NULL)) < 0)
111 111
                 goto end;
112 112
         }
113
-        avio_printf(seg->list_pb, "%s\n", oc->filename);
113
+
114
+        if (seg->list_type == LIST_TYPE_FLAT) {
115
+            avio_printf(seg->list_pb, "%s\n", oc->filename);
116
+        } else if (seg->list_type == LIST_TYPE_EXT) {
117
+            avio_printf(seg->list_pb, "%s,%f,%f\n", oc->filename, seg->start_time, seg->end_time);
118
+        }
114 119
         avio_flush(seg->list_pb);
115 120
     }
116 121
 
... ...
@@ -216,6 +229,10 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
216 216
 
217 217
         if ((ret = segment_end(s)) < 0 || (ret = segment_start(s)) < 0)
218 218
             goto fail;
219
+        seg->start_time = (double)pkt->pts * av_q2d(st->time_base);
220
+    } else if (pkt->pts != AV_NOPTS_VALUE) {
221
+        seg->end_time = FFMAX(seg->end_time,
222
+                              (double)(pkt->pts + pkt->duration) * av_q2d(st->time_base));
219 223
     }
220 224
 
221 225
     ret = oc->oformat->write_packet(oc, pkt);
... ...
@@ -252,6 +269,9 @@ static const AVOption options[] = {
252 252
     { "segment_time",      "set segment length in seconds",              OFFSET(time),    AV_OPT_TYPE_FLOAT,  {.dbl = 2},     0, FLT_MAX, E },
253 253
     { "segment_list",      "set the segment list filename",              OFFSET(list),    AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       E },
254 254
     { "segment_list_size", "set the maximum number of playlist entries", OFFSET(list_size), AV_OPT_TYPE_INT,  {.dbl = 5},     0, INT_MAX, E },
255
+    { "segment_list_type", "set the segment list type",                  OFFSET(list_type), AV_OPT_TYPE_INT,  {.dbl = LIST_TYPE_FLAT}, 0, LIST_TYPE_NB-1, E, "list_type" },
256
+    { "flat", "flat format",     0, AV_OPT_TYPE_CONST, {.dbl=LIST_TYPE_FLAT }, INT_MIN, INT_MAX, 0, "list_type" },
257
+    { "ext",  "extended format", 0, AV_OPT_TYPE_CONST, {.dbl=LIST_TYPE_EXT  }, INT_MIN, INT_MAX, 0, "list_type" },
255 258
     { "segment_wrap",      "set number after which the index wraps",     OFFSET(wrap),    AV_OPT_TYPE_INT,    {.dbl = 0},     0, INT_MAX, E },
256 259
     { NULL },
257 260
 };
... ...
@@ -31,7 +31,7 @@
31 31
 
32 32
 #define LIBAVFORMAT_VERSION_MAJOR 54
33 33
 #define LIBAVFORMAT_VERSION_MINOR 15
34
-#define LIBAVFORMAT_VERSION_MICRO 100
34
+#define LIBAVFORMAT_VERSION_MICRO 101
35 35
 
36 36
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
37 37
                                                LIBAVFORMAT_VERSION_MINOR, \