Ticket #1425: 0002-lavf-segment-add-reset_timestamps-option.patch

File 0002-lavf-segment-add-reset_timestamps-option.patch, 4.9 KB (added by saste, 4 years ago)
  • doc/muxers.texi

    From 7635ecc8759c71e103b06e21636676711a0ec9be Mon Sep 17 00:00:00 2001
    From: Stefano Sabatini <stefasab@gmail.com>
    Date: Thu, 29 Nov 2012 13:45:50 +0100
    Subject: [PATCH] lavf/segment: add reset_timestamps option
    
    The new options reset the timestamps at each new segment, so that the
    generated segments will have timestamps starting close to 0.
    
    It is meant to address trac ticket #1425.
    ---
     doc/muxers.texi       |    7 +++++++
     libavformat/segment.c |   25 +++++++++++++++++++++++++
     2 files changed, 32 insertions(+)
    
    diff --git a/doc/muxers.texi b/doc/muxers.texi
    index 1c8f93b..be22298 100644
    a b the specified time and the time set by @var{force_key_frames}. 
    588588@item segment_times @var{times} 
    589589Specify a list of split points. @var{times} contains a list of comma 
    590590separated duration specifications, in increasing order. 
     591 
    591592@item segment_wrap @var{limit} 
    592593Wrap around segment index once it reaches @var{limit}. 
     594 
     595@item reset_timestamps @var{1|0} 
     596Reset timestamps at the begin of each segment, so that each segment 
     597will start with near-zero timestamps. It is meant to ease the playback 
     598of the generated segments. May not work with some combinations of 
     599muxers/codecs. It is set to @code{0} by default. 
    593600@end table 
    594601 
    595602Some examples follow. 
  • libavformat/segment.c

    diff --git a/libavformat/segment.c b/libavformat/segment.c
    index 1ad410e..95ca2ab 100644
    a b  
    3535#include "libavutil/avstring.h" 
    3636#include "libavutil/parseutils.h" 
    3737#include "libavutil/mathematics.h" 
     38#include "libavutil/timestamp.h" 
    3839 
    3940typedef enum { 
    4041    LIST_TYPE_UNDEFINED = -1, 
    typedef struct { 
    7273    int64_t time_delta; 
    7374    int  individual_header_trailer; /**< Set by a private option. */ 
    7475    int  write_header_trailer; /**< Set by a private option. */ 
     76 
     77    int reset_timestamps;  ///< reset timestamps at the begin of each segment 
    7578    int has_video; 
    7679    double start_time, end_time; 
     80    int64_t start_pts, start_dts; 
    7781} SegmentContext; 
    7882 
    7983static void print_csv_escaped_str(AVIOContext *ctx, const char *str) 
    static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) 
    463467 
    464468    /* if the segment has video, start a new segment *only* with a key video frame */ 
    465469    if ((st->codec->codec_type == AVMEDIA_TYPE_VIDEO || !seg->has_video) && 
     470        pkt->pts != AV_NOPTS_VALUE && 
    466471        av_compare_ts(pkt->pts, st->time_base, 
    467472                      end_pts-seg->time_delta, AV_TIME_BASE_Q) >= 0 && 
    468473        pkt->flags & AV_PKT_FLAG_KEY) { 
    static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) 
    481486        oc = seg->avf; 
    482487 
    483488        seg->start_time = (double)pkt->pts * av_q2d(st->time_base); 
     489        seg->start_pts = av_rescale_q(pkt->pts, st->time_base, AV_TIME_BASE_Q); 
     490        seg->start_dts = pkt->dts != AV_NOPTS_VALUE ? 
     491            av_rescale_q(pkt->dts, st->time_base, AV_TIME_BASE_Q) : seg->start_pts; 
    484492    } else if (pkt->pts != AV_NOPTS_VALUE) { 
    485493        seg->end_time = FFMAX(seg->end_time, 
    486494                              (double)(pkt->pts + pkt->duration) * av_q2d(st->time_base)); 
    487495    } 
    488496 
     497    if (seg->reset_timestamps) { 
     498        av_log(s, AV_LOG_DEBUG, "start_pts:%s pts:%s start_dts:%s dts:%s", 
     499               av_ts2timestr(seg->start_pts, &AV_TIME_BASE_Q), av_ts2timestr(pkt->pts, &st->time_base), 
     500               av_ts2timestr(seg->start_dts, &AV_TIME_BASE_Q), av_ts2timestr(pkt->dts, &st->time_base)); 
     501 
     502        /* compute new timestamps */ 
     503        if (pkt->pts != AV_NOPTS_VALUE) 
     504            pkt->pts -= av_rescale_q(seg->start_pts, AV_TIME_BASE_Q, st->time_base); 
     505        if (pkt->dts != AV_NOPTS_VALUE) 
     506            pkt->dts -= av_rescale_q(seg->start_dts, AV_TIME_BASE_Q, st->time_base); 
     507 
     508        av_log(s, AV_LOG_DEBUG, " -> pts:%s dts:%s\n", 
     509               av_ts2timestr(pkt->pts, &st->time_base), av_ts2timestr(pkt->dts, &st->time_base)); 
     510    } 
     511 
    489512    ret = ff_write_chained(oc, pkt->stream_index, pkt, s); 
    490513 
    491514fail: 
    static const AVOption options[] = { 
    544567    { "segment_time_delta","set approximation value used for the segment times", OFFSET(time_delta_str), AV_OPT_TYPE_STRING, {.str = "0"}, 0, 0, E }, 
    545568    { "segment_times",     "set segment split time points",              OFFSET(times_str),AV_OPT_TYPE_STRING,{.str = NULL},  0, 0,       E }, 
    546569    { "segment_wrap",      "set number after which the index wraps",     OFFSET(segment_idx_wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, 
     570 
    547571    { "individual_header_trailer", "write header/trailer to each segment", OFFSET(individual_header_trailer), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E }, 
    548572    { "write_header_trailer", "write a header to the first segment and a trailer to the last one", OFFSET(write_header_trailer), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E }, 
     573    { "reset_timestamps", "reset timestamps at the begin of each segment", OFFSET(reset_timestamps), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E }, 
    549574    { NULL }, 
    550575}; 
    551576