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

Stefano Sabatini stefasab at gmail.com
Thu Jul 3 20:09:03 CEST 2014


On date Thursday 2014-07-03 13:19:04 +0200, Deti Fliegl encoded:
> 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

> diff --git a/libavformat/segment.c b/libavformat/segment.c

Please send a git-format patch complete with author info. Also please
update doc/muxers.texi segment documentation.

> 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 use_clocktime; ??

> +    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;

this could be double (in the not very likely but not impossible case
the user wants to cut at second fragments).

>  
>      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) {

nit: if_(

> +            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 },
-- 
FFmpeg = Fascinating and Frenzy Merciful Proud Elastic God


More information about the ffmpeg-devel mailing list