#include <time.h>
#include "avformat.h"
+#include "avio_internal.h"
#include "internal.h"
#include "libavutil/avassert.h"
int list_size; ///< number of entries for the segment list file
int use_clocktime; ///< flag to cut segments at regular clock time
+ int64_t clocktime_offset; //< clock offset for cutting the segments at regular clock time
+ int64_t clocktime_wrap_duration; //< wrapping duration considered for starting a new segment
int64_t last_val; ///< remember last time for wrap around detection
int64_t last_cut; ///< remember last cut
int cut_pending;
if ((err = set_segment_filename(s)) < 0)
return err;
- if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
- &s->interrupt_callback, NULL)) < 0) {
+ if ((err = ffio_open_whitelist(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
+ &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
return err;
}
int ret;
snprintf(seg->temp_list_filename, sizeof(seg->temp_list_filename), seg->use_rename ? "%s.tmp" : "%s", seg->list);
- ret = avio_open2(&seg->list_pb, seg->temp_list_filename, AVIO_FLAG_WRITE,
- &s->interrupt_callback, NULL);
+ ret = ffio_open_whitelist(&seg->list_pb, seg->temp_list_filename, AVIO_FLAG_WRITE,
+ &s->interrupt_callback, NULL, s->protocol_whitelist);
if (ret < 0) {
av_log(s, AV_LOG_ERROR, "Failed to open segment list '%s'\n", seg->list);
return ret;
seg->time_str);
return ret;
}
+ if (seg->use_clocktime) {
+ if (seg->time <= 0) {
+ av_log(s, AV_LOG_ERROR, "Invalid negative segment_time with segment_atclocktime option set\n");
+ return AVERROR(EINVAL);
+ }
+ seg->clocktime_offset = seg->time - (seg->clocktime_offset % seg->time);
+ }
}
if (seg->format_options_str) {
goto fail;
if (seg->write_header_trailer) {
- if ((ret = avio_open2(&oc->pb, seg->header_filename ? seg->header_filename : oc->filename, AVIO_FLAG_WRITE,
- &s->interrupt_callback, NULL)) < 0) {
+ if ((ret = ffio_open_whitelist(&oc->pb, seg->header_filename ? seg->header_filename : oc->filename, AVIO_FLAG_WRITE,
+ &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0) {
av_log(s, AV_LOG_ERROR, "Failed to open segment '%s'\n", oc->filename);
goto fail;
}
} else {
close_null_ctxp(&oc->pb);
}
- if ((ret = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
- &s->interrupt_callback, NULL)) < 0)
+ if ((ret = ffio_open_whitelist(&oc->pb, oc->filename, AVIO_FLAG_WRITE,
+ &s->interrupt_callback, NULL, s->protocol_whitelist)) < 0)
goto fail;
if (!seg->individual_header_trailer)
oc->pb->seekable = 0;
time_t sec = avgt / 1000000;
localtime_r(&sec, &ti);
usecs = (int64_t)(ti.tm_hour * 3600 + ti.tm_min * 60 + ti.tm_sec) * 1000000 + (avgt % 1000000);
- wrapped_val = usecs % seg->time;
- if (seg->last_cut != usecs && wrapped_val < seg->last_val) {
+ wrapped_val = (usecs + seg->clocktime_offset) % seg->time;
+ if (seg->last_cut != usecs && wrapped_val < seg->last_val && wrapped_val < seg->clocktime_wrap_duration) {
seg->cut_pending = 1;
seg->last_cut = usecs;
}
{ "hls", "Apple HTTP Live Streaming compatible", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_M3U8 }, INT_MIN, INT_MAX, E, "list_type" },
{ "segment_atclocktime", "set segment to be cut at clocktime", OFFSET(use_clocktime), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, E},
+ { "segment_clocktime_offset", "set segment clocktime offset", OFFSET(clocktime_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, 86400000000LL, E},
+ { "segment_clocktime_wrap_duration", "set segment clocktime wrapping duration", OFFSET(clocktime_wrap_duration), AV_OPT_TYPE_DURATION, {.i64 = INT64_MAX}, 0, INT64_MAX, E},
{ "segment_time", "set segment duration", OFFSET(time_str),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
{ "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 },