Ticket #1483: 0001-support-a-keyframe-white-list-in-the-segment-format..patch

File 0001-support-a-keyframe-white-list-in-the-segment-format..patch, 5.8 KB (added by gordon, 4 years ago)

patch

  • libavformat/segment.c

    From db7fbe2fa4160c0fb9e33ea8061f880fdcb58b97 Mon Sep 17 00:00:00 2001
    From: gordon <wgordonw1@gmail.com>
    Date: Wed, 27 Jun 2012 20:39:36 -0400
    Subject: [PATCH] support a keyframe white list in the segment format.  if
     present, segments will only start with the provided frames.
     Signed-off-by: Gordon <wgordonw1@gmail.com>
    
    ---
     libavformat/segment.c |   64 ++++++++++++++++++++++++++++++++++++++++--------
     1 files changed, 53 insertions(+), 11 deletions(-)
    
    diff --git a/libavformat/segment.c b/libavformat/segment.c
    index 6025aad..7a32e4e 100644
    a b typedef struct { 
    3636    AVFormatContext *avf; 
    3737    char *format;          /**< Set by a private option. */ 
    3838    char *list;            /**< Set by a private option. */ 
     39    char *valid_frames;    /**< Set by a private option. */ 
     40    const char *valid_frame_delimiter; 
    3941    float time;            /**< Set by a private option. */ 
    4042    int  size;             /**< Set by a private option. */ 
    4143    int  wrap;             /**< Set by a private option. */ 
    typedef struct { 
    4345    int64_t recording_time; 
    4446    int has_video; 
    4547    AVIOContext *pb; 
     48    int64_t next_valid_frame; 
     49    char *next_valid_frame_ptr; 
     50    int64_t frame_count; 
     51    int observe_valid_frames; 
    4652} SegmentContext; 
    4753 
    4854static int segment_start(AVFormatContext *s) 
    static int seg_write_header(AVFormatContext *s) 
    107113    SegmentContext *seg = s->priv_data; 
    108114    AVFormatContext *oc; 
    109115    int ret, i; 
     116    char* token; 
    110117 
    111118    seg->number = 0; 
    112119    seg->offset_time = 0; 
    113120    seg->recording_time = seg->time * 1000000; 
     121    seg->frame_count = 0; 
     122    seg->valid_frame_delimiter = ","; 
     123    seg->next_valid_frame_ptr = NULL; 
     124 
     125    if (seg->valid_frames) { 
     126        token = av_strtok(seg->valid_frames, seg->valid_frame_delimiter, &seg->next_valid_frame_ptr); 
     127        if (token) { 
     128            seg->next_valid_frame = strtol(token, NULL, 10); 
     129        } 
     130        seg->observe_valid_frames = 1; 
     131    } else { 
     132        seg->next_valid_frame = 0; 
     133        seg->observe_valid_frames = 0; 
     134    } 
     135 
    114136 
    115137    oc = avformat_alloc_context(); 
    116138 
    static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) 
    189211    AVStream *st = oc->streams[pkt->stream_index]; 
    190212    int64_t end_pts = seg->recording_time * seg->number; 
    191213    int ret; 
     214    char* token; 
     215    int can_split; 
     216 
     217    can_split = seg->has_video && st->codec->codec_type == AVMEDIA_TYPE_VIDEO && (pkt->flags & AV_PKT_FLAG_KEY); 
     218 
     219    if (seg->observe_valid_frames) { 
     220        if (seg->next_valid_frame < seg->frame_count) { 
     221            token = av_strtok(NULL, seg->valid_frame_delimiter, &seg->next_valid_frame_ptr); 
     222            if (token) { 
     223                seg->next_valid_frame = strtol(token, NULL, 10); 
     224            } 
     225        } 
     226        if (seg->next_valid_frame != seg->frame_count) { 
     227            can_split = 0; 
     228        } 
     229    } 
    192230 
    193     if ((seg->has_video && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && 
    194         av_compare_ts(pkt->pts, st->time_base, 
    195                       end_pts, AV_TIME_BASE_Q) >= 0 && 
    196         pkt->flags & AV_PKT_FLAG_KEY) { 
     231    if (can_split && av_compare_ts(pkt->pts, st->time_base, end_pts, AV_TIME_BASE_Q) >= 0) { 
    197232 
    198         av_log(s, AV_LOG_DEBUG, "Next segment starts at %d %"PRId64"\n", 
    199                pkt->stream_index, pkt->pts); 
     233        av_log(s, AV_LOG_DEBUG, "Next segment starts at %d %"PRId64" with frame count of %"PRId64" \n", 
     234               pkt->stream_index, pkt->pts, seg->frame_count); 
     235 
     236        seg->next_valid_frame = -1; 
    200237 
    201238        ret = segment_end(oc); 
    202239 
    static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) 
    218255        } 
    219256    } 
    220257 
     258    if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { 
     259        seg->frame_count++; 
     260    } 
     261 
    221262    ret = oc->oformat->write_packet(oc, pkt); 
    222263 
    223264fail: 
    static int seg_write_trailer(struct AVFormatContext *s) 
    248289#define OFFSET(x) offsetof(SegmentContext, x) 
    249290#define E AV_OPT_FLAG_ENCODING_PARAM 
    250291static const AVOption options[] = { 
    251     { "segment_format",    "container format used for the segments",  OFFSET(format),  AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       E }, 
    252     { "segment_time",      "segment length in seconds",               OFFSET(time),    AV_OPT_TYPE_FLOAT,  {.dbl = 2},     0, FLT_MAX, E }, 
    253     { "segment_list",      "output the segment list",                 OFFSET(list),    AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       E }, 
    254     { "segment_list_size", "maximum number of playlist entries",      OFFSET(size),    AV_OPT_TYPE_INT,    {.dbl = 5},     0, INT_MAX, E }, 
    255     { "segment_wrap",      "number after which the index wraps",      OFFSET(wrap),    AV_OPT_TYPE_INT,    {.dbl = 0},     0, INT_MAX, E }, 
     292    { "segment_format",          "container format used for the segments",                              OFFSET(format),          AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       E }, 
     293    { "segment_time",            "segment length in seconds",                                           OFFSET(time),           AV_OPT_TYPE_FLOAT,   {.dbl = 2},     0, FLT_MAX, E }, 
     294    { "segment_valid_frames",    "comma separated list of frame numbers allowed to start segments",     OFFSET(valid_frames),   AV_OPT_TYPE_STRING,  {.str = NULL},  0, 0,       E }, 
     295    { "segment_list",            "output the segment list",                                             OFFSET(list),           AV_OPT_TYPE_STRING,  {.str = NULL},  0, 0,       E }, 
     296    { "segment_list_size",       "maximum number of playlist entries",                                  OFFSET(size),           AV_OPT_TYPE_INT,     {.dbl = 5},     0, INT_MAX, E }, 
     297    { "segment_wrap",            "number after which the index wraps",                                  OFFSET(wrap),           AV_OPT_TYPE_INT,     {.dbl = 0},     0, INT_MAX, E }, 
    256298    { NULL }, 
    257299}; 
    258300