[FFmpeg-devel] [PATCH] libavformat/segment.c cut at clocktime

Deti Fliegl deti at fliegl.de
Thu Jul 3 13:19:04 CEST 2014


Hello,

this patch allows the segmenter to cut a segment aligned to normal
clocktime. For example it is possible to get a new segment every 15
minutes at 12:00, 12:15, 12:30, 12:45, ... with this simple syntax:

ffmpeg -i http://stream.example.org -f segment -segment_time 900
-segment_atclocktime 1 -c copy -map 0 output%02d.mp3

The code is designed to start counting at midnight and it cuts at this
condition:

if(!(seconds_since_midnight % segment_time_in_seconds)) {
...
}

We use this feature for logging live signals.

Deti
-------------- next part --------------
diff --git a/libavformat/segment.c b/libavformat/segment.c
index fe84f27..c1c315e 100644
--- a/libavformat/segment.c
+++ b/libavformat/segment.c
@@ -38,6 +38,7 @@
 #include "libavutil/parseutils.h"
 #include "libavutil/mathematics.h"
 #include "libavutil/timestamp.h"
+#include "libavutil/time.h"
 
 typedef struct SegmentListEntry {
     int index;
@@ -73,6 +74,9 @@ typedef struct {
     char *list;            ///< filename for the segment list file
     int   list_flags;      ///< flags affecting list generation
     int   list_size;       ///< number of entries for the segment list file
+    int *use_clocktime;    ///< cut segments at regular clock time
+    int   cut_pending;     ///< cut at clocktime pending
+    int   last_cut;	   ///< remember last cut
     char *entry_prefix;    ///< prefix to add to list entry filenames
     ListType list_type;    ///< set the list type
     AVIOContext *list_pb;  ///< list file put-byte context
@@ -668,6 +672,9 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
     int64_t end_pts = INT64_MAX, offset;
     int start_frame = INT_MAX;
     int ret;
+    struct tm *ti;
+    time_t now;
+    int secs;
 
     if (seg->times) {
         end_pts = seg->segment_count < seg->nb_times ?
@@ -676,7 +683,17 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
         start_frame = seg->segment_count <= seg->nb_frames ?
             seg->frames[seg->segment_count] : INT_MAX;
     } else {
-        end_pts = seg->time * (seg->segment_count+1);
+        if(seg->use_clocktime) {
+            now = time(NULL);
+            ti = localtime(&now);
+            secs=ti->tm_hour*3600+ti->tm_min*60+ti->tm_sec;
+            if(seg->last_cut != secs && !(secs % (seg->time/1000000))) {
+                seg->cut_pending = 1;
+                seg->last_cut = secs;
+            }
+        } else {
+            end_pts = seg->time * (seg->segment_count+1);
+        }
     }
 
     av_dlog(s, "packet stream:%d pts:%s pts_time:%s is_key:%d frame:%d\n",
@@ -686,10 +703,11 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt)
 
     if (pkt->stream_index == seg->reference_stream_index &&
         pkt->flags & AV_PKT_FLAG_KEY &&
-        (seg->frame_count >= start_frame ||
+        (seg->cut_pending || seg->frame_count >= start_frame ||
          (pkt->pts != AV_NOPTS_VALUE &&
           av_compare_ts(pkt->pts, st->time_base,
                         end_pts-seg->time_delta, AV_TIME_BASE_Q) >= 0))) {
+        seg->cut_pending = 0;
         if ((ret = segment_end(s, seg->individual_header_trailer, 0)) < 0)
             goto fail;
 
@@ -795,6 +813,7 @@ static const AVOption options[] = {
     { "m3u8", "M3U8 format",     0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_M3U8 }, INT_MIN, INT_MAX, E, "list_type" },
     { "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_INT, {.i64 = 0}, 0, 1, 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 },


More information about the ffmpeg-devel mailing list