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.
pull/59/head
Stefano Sabatini 13 years ago
parent b010d9b586
commit 7f08bfae6e
  1. 24
      doc/muxers.texi
  2. 20
      libavformat/segment.c
  3. 2
      libavformat/version.h

@ -450,6 +450,30 @@ listfile is generated.
@item segment_list_size @var{size} @item segment_list_size @var{size}
Overwrite the listfile once it reaches @var{size} entries. If 0 Overwrite the listfile once it reaches @var{size} entries. If 0
the listfile is never overwritten. Default value is 5. 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} @item segment_wrap @var{limit}
Wrap around segment index once it reaches @var{limit}. Wrap around segment index once it reaches @var{limit}.
@end table @end table

@ -30,6 +30,12 @@
#include "libavutil/parseutils.h" #include "libavutil/parseutils.h"
#include "libavutil/mathematics.h" #include "libavutil/mathematics.h"
typedef enum {
LIST_TYPE_FLAT = 0,
LIST_TYPE_EXT,
LIST_TYPE_NB,
} ListType;
typedef struct { typedef struct {
const AVClass *class; /**< Class for private options. */ const AVClass *class; /**< Class for private options. */
int number; int number;
@ -37,11 +43,13 @@ typedef struct {
char *format; ///< format to use for output segment files char *format; ///< format to use for output segment files
char *list; ///< filename for the segment list file char *list; ///< filename for the segment list file
int list_size; ///< number of entries 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 AVIOContext *list_pb; ///< list file put-byte context
float time; ///< segment duration float time; ///< segment duration
int wrap; ///< number after which the index wraps int wrap; ///< number after which the index wraps
int64_t recording_time; int64_t recording_time;
int has_video; int has_video;
double start_time, end_time;
} SegmentContext; } SegmentContext;
static int segment_start(AVFormatContext *s) static int segment_start(AVFormatContext *s)
@ -110,7 +118,12 @@ static int segment_end(AVFormatContext *s)
&s->interrupt_callback, NULL)) < 0) &s->interrupt_callback, NULL)) < 0)
goto end; goto end;
} }
if (seg->list_type == LIST_TYPE_FLAT) {
avio_printf(seg->list_pb, "%s\n", oc->filename); 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); avio_flush(seg->list_pb);
} }
@ -216,6 +229,10 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
if ((ret = segment_end(s)) < 0 || (ret = segment_start(s)) < 0) if ((ret = segment_end(s)) < 0 || (ret = segment_start(s)) < 0)
goto fail; 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); ret = oc->oformat->write_packet(oc, pkt);
@ -252,6 +269,9 @@ static const AVOption options[] = {
{ "segment_time", "set segment length in seconds", OFFSET(time), AV_OPT_TYPE_FLOAT, {.dbl = 2}, 0, FLT_MAX, E }, { "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", "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_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 }, { "segment_wrap", "set number after which the index wraps", OFFSET(wrap), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, E },
{ NULL }, { NULL },
}; };

@ -31,7 +31,7 @@
#define LIBAVFORMAT_VERSION_MAJOR 54 #define LIBAVFORMAT_VERSION_MAJOR 54
#define LIBAVFORMAT_VERSION_MINOR 15 #define LIBAVFORMAT_VERSION_MINOR 15
#define LIBAVFORMAT_VERSION_MICRO 100 #define LIBAVFORMAT_VERSION_MICRO 101
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
LIBAVFORMAT_VERSION_MINOR, \ LIBAVFORMAT_VERSION_MINOR, \

Loading…
Cancel
Save