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, 11 months ago) |
|---|
-
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 { 36 36 AVFormatContext *avf; 37 37 char *format; /**< Set by a private option. */ 38 38 char *list; /**< Set by a private option. */ 39 char *valid_frames; /**< Set by a private option. */ 40 const char *valid_frame_delimiter; 39 41 float time; /**< Set by a private option. */ 40 42 int size; /**< Set by a private option. */ 41 43 int wrap; /**< Set by a private option. */ … … typedef struct { 43 45 int64_t recording_time; 44 46 int has_video; 45 47 AVIOContext *pb; 48 int64_t next_valid_frame; 49 char *next_valid_frame_ptr; 50 int64_t frame_count; 51 int observe_valid_frames; 46 52 } SegmentContext; 47 53 48 54 static int segment_start(AVFormatContext *s) … … static int seg_write_header(AVFormatContext *s) 107 113 SegmentContext *seg = s->priv_data; 108 114 AVFormatContext *oc; 109 115 int ret, i; 116 char* token; 110 117 111 118 seg->number = 0; 112 119 seg->offset_time = 0; 113 120 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 114 136 115 137 oc = avformat_alloc_context(); 116 138 … … static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) 189 211 AVStream *st = oc->streams[pkt->stream_index]; 190 212 int64_t end_pts = seg->recording_time * seg->number; 191 213 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 } 192 230 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) { 197 232 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; 200 237 201 238 ret = segment_end(oc); 202 239 … … static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) 218 255 } 219 256 } 220 257 258 if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { 259 seg->frame_count++; 260 } 261 221 262 ret = oc->oformat->write_packet(oc, pkt); 222 263 223 264 fail: … … static int seg_write_trailer(struct AVFormatContext *s) 248 289 #define OFFSET(x) offsetof(SegmentContext, x) 249 290 #define E AV_OPT_FLAG_ENCODING_PARAM 250 291 static 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 }, 256 298 { NULL }, 257 299 }; 258 300
