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, 14 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