[FFmpeg-devel] [PATCH] Add segment name id set by user defined
Steven Liu
lingjiujianke at gmail.com
Thu May 8 19:29:14 CEST 2014
Hi!
Some times, m3u8 can be used for timeshift used segment id,
for example:
xxx.m3u8?starttime=139xxxxxxx&endtime=139xxxxxxx,
or
xxx.m3u8?starttime=20140408121221&endtime=20140408131221
or
seek m3u8 file
xxx.m3u8?starttime=14&endtime=3600
so add the parameters for the segment id for index,
for example:
segment name id by mpegts starttime, use the parameters:
-segment_name_flag starttime
output-0.ts
output-14.ts
output-24.ts
output-34.ts
segment name id by time(), use the parameters:
-segment_name_flag time
output-1399568846.ts
output-1399568856.ts
output-1399568866.ts
segment name id by format time, use the parameters:
-segment_name_flag fmt_time
output-20140509010807.ts
output-20140509010817.ts
output-20140509010827.ts
this parameters can use default, if use the default, it will as before
this functions can be used for m3u8 time shift
Signed-off-by: Steven Liu <qi.liu at chinacache.com>
---
libavformat/avformat.h | 2 +-
libavformat/segment.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++----
libavformat/utils.c | 4 +--
3 files changed, 79 insertions(+), 8 deletions(-)
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 7d2db6a..a11a9eb 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -2465,7 +2465,7 @@ void av_dump_format(AVFormatContext *ic,
* @return 0 if OK, -1 on format error
*/
int av_get_frame_filename(char *buf, int buf_size,
- const char *path, int number);
+ const char *path, int64_t number);
/**
* Check whether filename actually is a numbered sequence generator.
diff --git a/libavformat/segment.c b/libavformat/segment.c
index fe84f27..0b02752 100644
--- a/libavformat/segment.c
+++ b/libavformat/segment.c
@@ -58,12 +58,19 @@ typedef enum {
LIST_TYPE_NB,
} ListType;
+typedef enum {
+ SEG_NAME_FORMAT_INDEX_DEFAULT = 0,
+ SEG_NAME_FORMAT_TIME_FROM_0 = 1,
+ SEG_NAME_FORMAT_TIME_139XXX = 2,
+ SEG_NAME_FORMAT_TIME_YMDHMS = 3,
+} SegNameFmt;
+
#define SEGMENT_LIST_FLAG_CACHE 1
#define SEGMENT_LIST_FLAG_LIVE 2
typedef struct {
const AVClass *class; /**< Class for private options. */
- int segment_idx; ///< index of the segment file to write, starting from 0
+ int64_t segment_idx; ///< index of the segment file to write, starting from 0
int segment_idx_wrap; ///< number after which the index wraps
int segment_idx_wrap_nb; ///< number of time the index has wraped
int segment_count; ///< number of segment files already written
@@ -87,6 +94,8 @@ typedef struct {
int *frames; ///< list of frame number specification
int nb_frames; ///< number of elments in the frames array
int frame_count;
+ int seg_name_format; ///< segment name format flag
+ time_t start_by_systime; ///< get system time for start of the m3u8
int64_t time_delta;
int individual_header_trailer; /**< Set by a private option. */
@@ -156,14 +165,44 @@ static int segment_mux_init(AVFormatContext *s)
return 0;
}
+static int64_t time_to_int64(struct tm *p)
+{
+ char time_str[16] = { 0, };
+
+ snprintf(time_str, sizeof(time_str), "%04d%02d%02d%02d%02d%02d",
+ 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday,
+ p->tm_hour, p->tm_min, p->tm_sec);
+
+ return strtoll((char *)time_str, NULL, 10);
+}
+
static int set_segment_filename(AVFormatContext *s)
{
SegmentContext *seg = s->priv_data;
AVFormatContext *oc = seg->avf;
size_t size;
+ double seg_cur_val = seg->cur_entry.end_time - seg->cur_entry.start_time;
+ struct tm *p;
+
+ switch (seg->seg_name_format) {
+ case SEG_NAME_FORMAT_TIME_YMDHMS:
+ seg->start_by_systime += (int)seg_cur_val;
+ p = localtime(&(seg->start_by_systime));
+ seg->segment_idx = time_to_int64(p);
+ break;
+
+ case SEG_NAME_FORMAT_TIME_139XXX:
+ case SEG_NAME_FORMAT_TIME_FROM_0:
+ seg->segment_idx += (int) seg_cur_val;
+ break;
+ case SEG_NAME_FORMAT_INDEX_DEFAULT:
+ default:
+ seg->segment_idx++;
+ if (seg->segment_idx_wrap)
+ seg->segment_idx %= seg->segment_idx_wrap;
+ break;
+ }
- if (seg->segment_idx_wrap)
- seg->segment_idx %= seg->segment_idx_wrap;
if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
s->filename, seg->segment_idx) < 0) {
av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", s->filename);
@@ -185,6 +224,32 @@ static int set_segment_filename(AVFormatContext *s)
return 0;
}
+static int64_t get_seg_idx(AVFormatContext *s, int fmt)
+{
+ SegmentContext *seg = s->priv_data;
+
+ switch (fmt) {
+ case SEG_NAME_FORMAT_TIME_FROM_0:
+ seg->segment_idx = 0;
+ break;
+
+ case SEG_NAME_FORMAT_TIME_139XXX:
+ seg->segment_idx = time(0);
+ break;
+
+ case SEG_NAME_FORMAT_TIME_YMDHMS:
+ seg->segment_idx = time(&(seg->start_by_systime));
+ break;
+
+ case SEG_NAME_FORMAT_INDEX_DEFAULT:
+ default:
+ seg->segment_idx++;
+ break;
+ }
+
+ return seg->segment_idx;
+}
+
static int segment_start(AVFormatContext *s, int write_header)
{
SegmentContext *seg = s->priv_data;
@@ -199,7 +264,6 @@ static int segment_start(AVFormatContext *s, int write_header)
oc = seg->avf;
}
- seg->segment_idx++;
if ((seg->segment_idx_wrap) && (seg->segment_idx%seg->segment_idx_wrap == 0))
seg->segment_idx_wrap_nb++;
@@ -621,6 +685,8 @@ static int seg_write_header(AVFormatContext *s)
goto fail;
oc = seg->avf;
+ seg->segment_idx = get_seg_idx(s, seg->seg_name_format);
+
if ((ret = set_segment_filename(s)) < 0)
goto fail;
@@ -796,12 +862,17 @@ static const AVOption options[] = {
{ "hls", "Apple HTTP Live Streaming compatible", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_M3U8 }, INT_MIN, INT_MAX, E, "list_type" },
{ "segment_time", "set segment duration", OFFSET(time_str),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
+ { "segment_name_flag", "set segment name format", OFFSET(seg_name_format),AV_OPT_TYPE_INT, {.i64 = 0}, 0, 3, E, "name_flag" },
+ { "seq", "name id by sequence", 0, AV_OPT_TYPE_CONST, {.i64=SEG_NAME_FORMAT_INDEX_DEFAULT }, INT_MIN, INT_MAX, E, "name_flag" },
+ { "starttime", "name id by starttime", 0, AV_OPT_TYPE_CONST, {.i64=SEG_NAME_FORMAT_TIME_FROM_0 }, INT_MIN, INT_MAX, E, "name_flag" },
+ { "time", "name id by 139XXXXXXX", 0, AV_OPT_TYPE_CONST, {.i64=SEG_NAME_FORMAT_TIME_139XXX }, INT_MIN, INT_MAX, E, "name_flag" },
+ { "fmt_time", "name id by YYYYMMDDhhmmss", 0, AV_OPT_TYPE_CONST, {.i64=SEG_NAME_FORMAT_TIME_YMDHMS }, INT_MIN, INT_MAX, E, "name_flag" },
{ "segment_time_delta","set approximation value used for the segment times", OFFSET(time_delta), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, 0, E },
{ "segment_times", "set segment split time points", OFFSET(times_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E },
{ "segment_frames", "set segment split frame numbers", OFFSET(frames_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E },
{ "segment_wrap", "set number after which the index wraps", OFFSET(segment_idx_wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
{ "segment_list_entry_prefix", "set base url prefix for segments", OFFSET(entry_prefix), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
- { "segment_start_number", "set the sequence number of the first segment", OFFSET(segment_idx), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
+ { "segment_start_number", "set the sequence number of the first segment", OFFSET(segment_idx), AV_OPT_TYPE_INT64, {.i64 = 0}, 0, INT64_MAX, E },
{ "segment_wrap_number", "set the number of wrap before the first segment", OFFSET(segment_idx_wrap_nb), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E },
{ "individual_header_trailer", "write header/trailer to each segment", OFFSET(individual_header_trailer), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E },
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 4f5b310..5a4e5e0 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -3985,7 +3985,7 @@ uint64_t ff_ntp_time(void)
return (av_gettime() / 1000) * 1000 + NTP_OFFSET_US;
}
-int av_get_frame_filename(char *buf, int buf_size, const char *path, int number)
+int av_get_frame_filename(char *buf, int buf_size, const char *path, int64_t number)
{
const char *p;
char *q, buf1[20], c;
@@ -4013,7 +4013,7 @@ int av_get_frame_filename(char *buf, int buf_size, const char *path, int number)
if (percentd_found)
goto fail;
percentd_found = 1;
- snprintf(buf1, sizeof(buf1), "%0*d", nd, number);
+ snprintf(buf1, sizeof(buf1), "%0*lld", nd, number);
len = strlen(buf1);
if ((q - buf + len) > buf_size - 1)
goto fail;
--
1.8.5.2 (Apple Git-48)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Add-segment-name-id-set-by-user-defined.patch
Type: application/octet-stream
Size: 9399 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20140509/7bda3494/attachment.obj>
More information about the ffmpeg-devel
mailing list