@item segment_list_size @var{size}
Overwrite the listfile once it reaches @var{size} entries. If 0
the listfile is never overwritten. Default value is 5.
+@item segment_list type @var{type}
+Specify the format for the segment list file.
+
+The following values are recognized:
+@table @option
+@item flat
+Generate a flat list for the created segments, one segment per line.
+
+@item ext
+Generate a list for the created segments, one segment per line,
+each line matching the format:
+@example
+@var{segment_filename},@var{segment_start_time},@var{segment_end_time}
+@end example
+
+@var{segment_filename} is the name of the output file generated by the
+muxer according to the provided pattern, and should not contain the
+"," character for simplifying parsing operations.
+
+@var{segment_start_time} and @var{segment_end_time} specify
+the segment start and end time expressed in seconds.
+@end table
+
+Default value is "flat".
@item segment_wrap @var{limit}
Wrap around segment index once it reaches @var{limit}.
@end table
#include "libavutil/parseutils.h"
#include "libavutil/mathematics.h"
+typedef enum {
+ LIST_TYPE_FLAT = 0,
+ LIST_TYPE_EXT,
+ LIST_TYPE_NB,
+} ListType;
+
typedef struct {
const AVClass *class; /**< Class for private options. */
int number;
char *format; ///< format to use for output segment files
char *list; ///< filename for the segment list file
int list_size; ///< number of entries for the segment list file
+ ListType list_type; ///< set the list type
AVIOContext *list_pb; ///< list file put-byte context
float time; ///< segment duration
int wrap; ///< number after which the index wraps
int64_t recording_time;
int has_video;
+ double start_time, end_time;
} SegmentContext;
static int segment_start(AVFormatContext *s)
&s->interrupt_callback, NULL)) < 0)
goto end;
}
- avio_printf(seg->list_pb, "%s\n", oc->filename);
+
+ if (seg->list_type == LIST_TYPE_FLAT) {
+ avio_printf(seg->list_pb, "%s\n", oc->filename);
+ } else if (seg->list_type == LIST_TYPE_EXT) {
+ avio_printf(seg->list_pb, "%s,%f,%f\n", oc->filename, seg->start_time, seg->end_time);
+ }
avio_flush(seg->list_pb);
}
if ((ret = segment_end(s)) < 0 || (ret = segment_start(s)) < 0)
goto fail;
+ seg->start_time = (double)pkt->pts * av_q2d(st->time_base);
+ } else if (pkt->pts != AV_NOPTS_VALUE) {
+ seg->end_time = FFMAX(seg->end_time,
+ (double)(pkt->pts + pkt->duration) * av_q2d(st->time_base));
}
ret = oc->oformat->write_packet(oc, pkt);
{ "segment_time", "set segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E },
{ "segment_list", "set the segment list filename", OFFSET(list), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
{ "segment_list_size", "set the maximum number of playlist entries", OFFSET(list_size), AV_OPT_TYPE_INT, {.dbl = 5}, 0, INT_MAX, E },
+ { "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" },
+ { "flat", "flat format", 0, AV_OPT_TYPE_CONST, {.dbl=LIST_TYPE_FLAT }, INT_MIN, INT_MAX, 0, "list_type" },
+ { "ext", "extended format", 0, AV_OPT_TYPE_CONST, {.dbl=LIST_TYPE_EXT }, INT_MIN, INT_MAX, 0, "list_type" },
{ "segment_wrap", "set number after which the index wraps", OFFSET(wrap), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, E },
{ NULL },
};