lavf/segment: add new option segment_clocktime_wrap_duration
authorMarton Balint <cus@passwd.hu>
Mon, 18 Jan 2016 00:29:06 +0000 (01:29 +0100)
committerMarton Balint <cus@passwd.hu>
Thu, 28 Jan 2016 20:35:44 +0000 (21:35 +0100)
This option can force the segmenter to only start a new segment if a packet
reaches the muxer within the specified duration after the segmenting clock
time, which makes it more resilient to backward local time jumps, such as leap
seconds or transition to standard time from daylight savings time.

Reviewed-by: Stefano Sabatini <stefasab@gmail.com>
Signed-off-by: Marton Balint <cus@passwd.hu>
doc/muxers.texi
libavformat/segment.c

index ed806d37067aad6fb0bd34de2e7e5a836d62df8c..4ba88831c36c5534cdb44a5391388071eb47a2f9 100644 (file)
@@ -1110,6 +1110,18 @@ create files at 12:05, 12:20, 12:35, etc.
 
 Default value is "0".
 
+@item segment_clocktime_wrap_duration @var{duration}
+Force the segmenter to only start a new segment if a packet reaches the muxer
+within the specified duration after the segmenting clock time. This way you
+can make the segmenter more resilient to backward local time jumps, such as
+leap seconds or transition to standard time from daylight savings time.
+
+Assuming that the delay between the packets of your source is less than 0.5
+second you can detect a leap second by specifying 0.5 as the duration.
+
+Default is the maximum possible duration which means starting a new segment
+regardless of the elapsed time since the last clock time.
+
 @item segment_time_delta @var{delta}
 Specify the accuracy time when selecting the start time for a
 segment, expressed as a duration specification. Default value is "0".
index a91a6323ef685fd438ad42867cd2230ca47afd5c..9da51689ae35fa5ee395af515f6158eb8f72f71b 100644 (file)
@@ -83,6 +83,7 @@ typedef struct SegmentContext {
 
     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;
@@ -784,7 +785,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
             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->clocktime_offset) % seg->time;
-            if (seg->last_cut != usecs && wrapped_val < seg->last_val) {
+            if (seg->last_cut != usecs && wrapped_val < seg->last_val && wrapped_val < seg->clocktime_wrap_duration) {
                 seg->cut_pending = 1;
                 seg->last_cut = usecs;
             }
@@ -935,6 +936,7 @@ static const AVOption options[] = {
 
     { "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 },