TODO: add documentation, add support to chapters. --- libavformat/segment.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+)
diff --git a/libavformat/segment.c b/libavformat/segment.c index b65a2eb..794504a 100644 --- a/libavformat/segment.c +++ b/libavformat/segment.c @@ -33,6 +33,7 @@ #include "internal.h" #include "libavutil/avassert.h" +#include "libavutil/eval.h" #include "libavutil/log.h" #include "libavutil/opt.h" #include "libavutil/avstring.h" @@ -62,6 +63,28 @@ typedef enum { LIST_TYPE_NB, } ListType; +static const char *const var_names[] = { + "segment_n", ///< segment count + "segment_packets_n", + "segment_size", + + "packet_pos", ///< position in the file + "packet_n", + "packet_t", + NULL +}; + +enum var_name { + VAR_SEGMENT_N, + VAR_SEGMENT_PACKETS_N, + VAR_SEGMENT_SIZE, + + VAR_PACKET_POS, + VAR_PACKET_N, + VAR_PACKET_T, + VAR_VARS_NB +}; + #define SEGMENT_LIST_FLAG_CACHE 1 #define SEGMENT_LIST_FLAG_LIVE 2 @@ -71,6 +94,11 @@ typedef struct SegmentContext { int segment_idx_wrap; ///< number after which the index wraps int segment_idx_wrap_nb; ///< number of time the index has wraped int segment_count; ///< number of segment files already written + + char *segment_expr; + AVExpr *segment_pexpr; + double var_values[VAR_VARS_NB]; + AVOutputFormat *oformat; AVFormatContext *avf; char *format; ///< format to use for output segment files @@ -225,6 +253,10 @@ static int segment_start(AVFormatContext *s, int write_header) } seg->segment_idx++; + + seg->var_values[VAR_SEGMENT_SIZE] = 0; + seg->var_values[VAR_SEGMENT_PACKETS_N] = 0; + if ((seg->segment_idx_wrap) && (seg->segment_idx%seg->segment_idx_wrap == 0)) seg->segment_idx_wrap_nb++; @@ -606,6 +638,15 @@ static int seg_write_header(AVFormatContext *s) } else if (seg->frames_str) { if ((ret = parse_frames(s, &seg->frames, &seg->nb_frames, seg->frames_str)) < 0) return ret; + } else if (seg->segment_expr) { + ret = av_expr_parse(&seg->segment_pexpr, seg->segment_expr, var_names, + NULL, NULL, NULL, NULL, 0, s); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, + "Error when evaluating the segment expression '%s'\n", + seg->segment_expr); + return ret; + } } else { /* set default value if not specified */ if (!seg->time_str) @@ -732,12 +773,26 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) if (!seg->avf) return AVERROR(EINVAL); +#define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts) * av_q2d(tb)) + seg->var_values[VAR_SEGMENT_N] = seg->segment_count; + + seg->var_values[VAR_SEGMENT_SIZE] += pkt->size; + seg->var_values[VAR_SEGMENT_PACKETS_N] += 1; + + seg->var_values[VAR_PACKET_POS] = pkt->pos; + seg->var_values[VAR_PACKET_T] = TS2T(pkt->pts, st->time_base); + seg->var_values[VAR_PACKET_N] += 1; + if (seg->times) { end_pts = seg->segment_count < seg->nb_times ? seg->times[seg->segment_count] : INT64_MAX; } else if (seg->frames) { start_frame = seg->segment_count < seg->nb_frames ? seg->frames[seg->segment_count] : INT_MAX; + } else if (seg->segment_expr) { + double res = av_expr_eval(seg->segment_pexpr, seg->var_values, NULL); + if (res != 0) + seg->cut_pending = 1; } else { if (seg->use_clocktime) { int64_t avgt = av_gettime(); @@ -855,6 +910,7 @@ fail: av_opt_free(seg); av_freep(&seg->times); av_freep(&seg->frames); + av_expr_free(seg->segment_pexpr); seg->segment_pexpr = NULL; cur = seg->segment_list_entries; while (cur) { @@ -891,6 +947,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_expr", "set segmentation expression", OFFSET(segment_expr), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, { "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 }, -- 1.8.3.2 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel