Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

support a keyframe white list in the segment format. if present, segm…

…ents will only start with the provided frames.

Signed-off-by: Gordon <wgordonw1@gmail.com>
  • Loading branch information...
commit db7fbe2fa4160c0fb9e33ea8061f880fdcb58b97 1 parent 2fa5d8f
thenewguy authored June 27, 2012

Showing 1 changed file with 53 additions and 11 deletions. Show diff stats Hide diff stats

  1. 64  libavformat/segment.c
64  libavformat/segment.c
@@ -36,6 +36,8 @@ 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. */
@@ -43,6 +45,10 @@ 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)
@@ -107,10 +113,26 @@ 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
 
@@ -189,14 +211,29 @@ 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
 
@@ -218,6 +255,10 @@ 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:
@@ -248,11 +289,12 @@ 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
 

0 notes on commit db7fbe2

Please sign in to comment.
Something went wrong with that request. Please try again.