... | ... |
@@ -474,6 +474,28 @@ the segment start and end time expressed in seconds. |
474 | 474 |
Default value is "flat". |
475 | 475 |
@item segment_time @var{time} |
476 | 476 |
Set segment duration to @var{time}. Default value is "2". |
477 |
+@item segment_time_delta @var{delta} |
|
478 |
+Specify the accuracy time when selecting the start time for a |
|
479 |
+segment. Default value is "0". |
|
480 |
+ |
|
481 |
+When delta is specified a key-frame will start a new segment if its |
|
482 |
+PTS satisfies the relation: |
|
483 |
+@example |
|
484 |
+PTS >= start_time - time_delta |
|
485 |
+@end example |
|
486 |
+ |
|
487 |
+This option is useful when splitting video content, which is always |
|
488 |
+split at GOP boundaries, in case a key frame is found just before the |
|
489 |
+specified split time. |
|
490 |
+ |
|
491 |
+In particular may be used in combination with the @file{ffmpeg} option |
|
492 |
+@var{force_key_frames}. The key frame times specified by |
|
493 |
+@var{force_key_frames} may not be set accurately because of rounding |
|
494 |
+issues, with the consequence that a key frame time may result set just |
|
495 |
+before the specified time. For constant frame rate videos a value of |
|
496 |
+1/2*@var{frame_rate} should address the worst case mismatch between |
|
497 |
+the specified time and the time set by @var{force_key_frames}. |
|
498 |
+ |
|
477 | 499 |
@item segment_times @var{times} |
478 | 500 |
Specify a list of split points. @var{times} contains a list of comma |
479 | 501 |
separated duration specifications, in increasing order. |
... | ... |
@@ -500,6 +522,18 @@ ffmpeg -i in.mkv -codec copy -map 0 -f segment -segment_list_type ext -segment_l |
500 | 500 |
@end example |
501 | 501 |
|
502 | 502 |
@item |
503 |
+As the example above, but use the @code{ffmpeg} @var{force_key_frames} |
|
504 |
+option to force key frames in the input at the specified location, together |
|
505 |
+with the segment option @var{segment_time_delta} to account for |
|
506 |
+possible roundings operated when setting key frame times. |
|
507 |
+@example |
|
508 |
+ffmpeg -i in.mkv -force_key_frames 1,2,3,5,8,13,21 -vcodec mpeg4 -acodec pcm_s16le -map 0 \ |
|
509 |
+-f segment -segment_list_type ext -segment_list out.list -segment_list_size 0 -segment_times 1,2,3,5,8,13,21 -segment_time_delta 0.05 out%03d.nut |
|
510 |
+@end example |
|
511 |
+In order to force key frames on the input file, transcoding is |
|
512 |
+required. |
|
513 |
+ |
|
514 |
+@item |
|
503 | 515 |
To convert the @file{in.mkv} to TS segments using the @code{libx264} |
504 | 516 |
and @code{libfaac} encoders: |
505 | 517 |
@example |
... | ... |
@@ -52,6 +52,8 @@ typedef struct { |
52 | 52 |
char *times_str; ///< segment times specification string |
53 | 53 |
int64_t *times; ///< list of segment interval specification |
54 | 54 |
int nb_times; ///< number of elments in the times array |
55 |
+ char *time_delta_str; ///< approximation value duration used for the segment times |
|
56 |
+ int64_t time_delta; |
|
55 | 57 |
int has_video; |
56 | 58 |
double start_time, end_time; |
57 | 59 |
} SegmentContext; |
... | ... |
@@ -222,6 +224,15 @@ static int seg_write_header(AVFormatContext *s) |
222 | 222 |
} |
223 | 223 |
} |
224 | 224 |
|
225 |
+ if (seg->time_delta_str) { |
|
226 |
+ if ((ret = av_parse_time(&seg->time_delta, seg->time_delta_str, 1)) < 0) { |
|
227 |
+ av_log(s, AV_LOG_ERROR, |
|
228 |
+ "Invalid time duration specification '%s' for delta option\n", |
|
229 |
+ seg->time_delta_str); |
|
230 |
+ return ret; |
|
231 |
+ } |
|
232 |
+ } |
|
233 |
+ |
|
225 | 234 |
oc = avformat_alloc_context(); |
226 | 235 |
|
227 | 236 |
if (!oc) |
... | ... |
@@ -304,7 +315,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) |
304 | 304 |
/* if the segment has video, start a new segment *only* with a key video frame */ |
305 | 305 |
if ((st->codec->codec_type == AVMEDIA_TYPE_VIDEO || !seg->has_video) && |
306 | 306 |
av_compare_ts(pkt->pts, st->time_base, |
307 |
- end_pts, AV_TIME_BASE_Q) >= 0 && |
|
307 |
+ end_pts-seg->time_delta, AV_TIME_BASE_Q) >= 0 && |
|
308 | 308 |
pkt->flags & AV_PKT_FLAG_KEY) { |
309 | 309 |
|
310 | 310 |
av_log(s, AV_LOG_DEBUG, "Next segment starts with packet stream:%d pts:%"PRId64" pts_time:%f\n", |
... | ... |
@@ -359,6 +370,7 @@ static const AVOption options[] = { |
359 | 359 |
{ "flat", "flat format", 0, AV_OPT_TYPE_CONST, {.dbl=LIST_TYPE_FLAT }, INT_MIN, INT_MAX, 0, "list_type" }, |
360 | 360 |
{ "ext", "extended format", 0, AV_OPT_TYPE_CONST, {.dbl=LIST_TYPE_EXT }, INT_MIN, INT_MAX, 0, "list_type" }, |
361 | 361 |
{ "segment_time", "set segment duration", OFFSET(time_str),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, |
362 |
+ { "segment_time_delta","set approximation value used for the segment times", OFFSET(time_delta_str), AV_OPT_TYPE_STRING, {.str = "0"}, 0, 0, E }, |
|
362 | 363 |
{ "segment_times", "set segment split time points", OFFSET(times_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E }, |
363 | 364 |
{ "segment_wrap", "set number after which the index wraps", OFFSET(wrap), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, E }, |
364 | 365 |
{ NULL }, |
... | ... |
@@ -31,7 +31,7 @@ |
31 | 31 |
|
32 | 32 |
#define LIBAVFORMAT_VERSION_MAJOR 54 |
33 | 33 |
#define LIBAVFORMAT_VERSION_MINOR 15 |
34 |
-#define LIBAVFORMAT_VERSION_MICRO 103 |
|
34 |
+#define LIBAVFORMAT_VERSION_MICRO 104 |
|
35 | 35 |
|
36 | 36 |
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ |
37 | 37 |
LIBAVFORMAT_VERSION_MINOR, \ |