avformat/hlsenc: add a use_localtime option to expand the segment filename with localtime
test examples: ./ffmpeg -re -i ~/Movies/objectC/facebook.mp4 -v verbose -c copy -f hls -hls_segment_filename test-%s.ts -use_localtime 1 -bsf:v h264_mp4toannexb aaa.m3u8 [StevenLiu@localhost ffmpeg]$ cat aaa.m3u8;ll test-*.ts test-1441052221.ts test-1441052231.ts test-1441052235.ts test-1441052243.ts test-1441052249.ts -rw-r--r-- 1 StevenLiu staff 1310736 9 1 04:15 test-1441052131.ts -rw-r--r-- 1 StevenLiu staff 495192 9 1 04:15 test-1441052141.ts -rw-r--r-- 1 StevenLiu staff 1310736 9 1 04:17 test-1441052212.ts -rw-r--r-- 1 StevenLiu staff 1067840 9 1 04:17 test-1441052221.ts -rw-r--r-- 1 StevenLiu staff 235564 9 1 04:17 test-1441052231.ts -rw-r--r-- 1 StevenLiu staff 1187220 9 1 04:17 test-1441052235.ts -rw-r--r-- 1 StevenLiu staff 694848 9 1 04:17 test-1441052243.ts -rw-r--r-- 1 StevenLiu staff 526588 9 1 04:17 test-1441052249.ts [StevenLiu@localhost ffmpeg]$ ./ffmpeg -re -i ~/Movies/objectC/facebook.mp4 -v verbose -c copy -f hls -hls_segment_filename test-%s.ts -use_localtime 1 -bsf:v h264_mp4toannexb aaa.m3u8 [StevenLiu@localhost ffmpeg]$ cat aaa.m3u8;ll aaa-*.ts aaa-1441052417.ts aaa-1441052427.ts aaa-1441052437.ts aaa-1441052440.ts aaa-1441052449.ts -rw-r--r-- 1 StevenLiu staff 1310736 9 1 04:19 aaa-1441052382.ts -rw-r--r-- 1 StevenLiu staff 277300 9 1 04:19 aaa-1441052392.ts -rw-r--r-- 1 StevenLiu staff 1310736 9 1 04:20 aaa-1441052417.ts -rw-r--r-- 1 StevenLiu staff 1067840 9 1 04:20 aaa-1441052427.ts -rw-r--r-- 1 StevenLiu staff 235564 9 1 04:20 aaa-1441052437.ts -rw-r--r-- 1 StevenLiu staff 1187220 9 1 04:20 aaa-1441052440.ts -rw-r--r-- 1 StevenLiu staff 338776 9 1 04:20 aaa-1441052449.ts [StevenLiu@localhost ffmpeg]$ Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
parent
62bd8deef9
commit
a4055d3e5d
@ -32,6 +32,7 @@
|
|||||||
#include "libavutil/avstring.h"
|
#include "libavutil/avstring.h"
|
||||||
#include "libavutil/opt.h"
|
#include "libavutil/opt.h"
|
||||||
#include "libavutil/log.h"
|
#include "libavutil/log.h"
|
||||||
|
#include "libavutil/time_internal.h"
|
||||||
|
|
||||||
#include "avformat.h"
|
#include "avformat.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
@ -79,6 +80,7 @@ typedef struct HLSContext {
|
|||||||
uint32_t flags; // enum HLSFlags
|
uint32_t flags; // enum HLSFlags
|
||||||
char *segment_filename;
|
char *segment_filename;
|
||||||
|
|
||||||
|
int use_localtime; ///< flag to expand filename with localtime
|
||||||
int allowcache;
|
int allowcache;
|
||||||
int64_t recording_time;
|
int64_t recording_time;
|
||||||
int has_video;
|
int has_video;
|
||||||
@ -479,9 +481,18 @@ static int hls_start(AVFormatContext *s)
|
|||||||
av_strlcpy(vtt_oc->filename, c->vtt_basename,
|
av_strlcpy(vtt_oc->filename, c->vtt_basename,
|
||||||
sizeof(vtt_oc->filename));
|
sizeof(vtt_oc->filename));
|
||||||
} else {
|
} else {
|
||||||
if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
|
if (c->use_localtime) {
|
||||||
|
time_t now0;
|
||||||
|
struct tm *tm, tmpbuf;
|
||||||
|
time(&now0);
|
||||||
|
tm = localtime_r(&now0, &tmpbuf);
|
||||||
|
if (!strftime(oc->filename, sizeof(oc->filename), c->basename, tm)) {
|
||||||
|
av_log(oc, AV_LOG_ERROR, "Could not get segment filename with use_localtime\n");
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
}
|
||||||
|
} else if (av_get_frame_filename(oc->filename, sizeof(oc->filename),
|
||||||
c->basename, c->wrap ? c->sequence % c->wrap : c->sequence) < 0) {
|
c->basename, c->wrap ? c->sequence % c->wrap : c->sequence) < 0) {
|
||||||
av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->basename);
|
av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s' you can try use -use_localtime 1 with it\n", c->basename);
|
||||||
return AVERROR(EINVAL);
|
return AVERROR(EINVAL);
|
||||||
}
|
}
|
||||||
if( c->vtt_basename) {
|
if( c->vtt_basename) {
|
||||||
@ -542,6 +553,7 @@ static int hls_write_header(AVFormatContext *s)
|
|||||||
int ret, i;
|
int ret, i;
|
||||||
char *p;
|
char *p;
|
||||||
const char *pattern = "%d.ts";
|
const char *pattern = "%d.ts";
|
||||||
|
const char *pattern_localtime_fmt = "-%s.ts";
|
||||||
const char *vtt_pattern = "%d.vtt";
|
const char *vtt_pattern = "%d.vtt";
|
||||||
AVDictionary *options = NULL;
|
AVDictionary *options = NULL;
|
||||||
int basename_size;
|
int basename_size;
|
||||||
@ -596,7 +608,11 @@ static int hls_write_header(AVFormatContext *s)
|
|||||||
if (hls->flags & HLS_SINGLE_FILE)
|
if (hls->flags & HLS_SINGLE_FILE)
|
||||||
pattern = ".ts";
|
pattern = ".ts";
|
||||||
|
|
||||||
basename_size = strlen(s->filename) + strlen(pattern) + 1;
|
if (hls->use_localtime) {
|
||||||
|
basename_size = strlen(s->filename) + strlen(pattern_localtime_fmt) + 1;
|
||||||
|
} else {
|
||||||
|
basename_size = strlen(s->filename) + strlen(pattern) + 1;
|
||||||
|
}
|
||||||
hls->basename = av_malloc(basename_size);
|
hls->basename = av_malloc(basename_size);
|
||||||
if (!hls->basename) {
|
if (!hls->basename) {
|
||||||
ret = AVERROR(ENOMEM);
|
ret = AVERROR(ENOMEM);
|
||||||
@ -608,7 +624,11 @@ static int hls_write_header(AVFormatContext *s)
|
|||||||
p = strrchr(hls->basename, '.');
|
p = strrchr(hls->basename, '.');
|
||||||
if (p)
|
if (p)
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
av_strlcat(hls->basename, pattern, basename_size);
|
if (hls->use_localtime) {
|
||||||
|
av_strlcat(hls->basename, pattern_localtime_fmt, basename_size);
|
||||||
|
} else {
|
||||||
|
av_strlcat(hls->basename, pattern, basename_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(hls->has_subtitle) {
|
if(hls->has_subtitle) {
|
||||||
@ -817,6 +837,7 @@ static const AVOption options[] = {
|
|||||||
{"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX, E, "flags"},
|
{"round_durations", "round durations in m3u8 to whole numbers", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_ROUND_DURATIONS }, 0, UINT_MAX, E, "flags"},
|
||||||
{"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX, E, "flags"},
|
{"discont_start", "start the playlist with a discontinuity tag", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_DISCONT_START }, 0, UINT_MAX, E, "flags"},
|
||||||
{"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX, E, "flags"},
|
{"omit_endlist", "Do not append an endlist when ending stream", 0, AV_OPT_TYPE_CONST, {.i64 = HLS_OMIT_ENDLIST }, 0, UINT_MAX, E, "flags"},
|
||||||
|
{ "use_localtime", "set filename expansion with strftime at segment creation", OFFSET(use_localtime), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, E },
|
||||||
|
|
||||||
{ NULL },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user