The current implementation creates new segments comparing
pkt->pts - first_pts > total_duration
This works fine, but if the keyframe interval is smaller than "min_seg_duration"
segments shorter than the minimum segment duration are created.
Example: keyint=50, min_seg_duration=3000000
segment 1 contains keyframe 1 (duration=2s < total_duration=3s)
and keyframe 2 (duration=4s >= total_duration=3s)
segment 2 contains keyframe 3 (duration=6s >= total_duration=6s)
segment 3 contains keyframe 4 (duration=8s < total_duration=9s)
and keyframe 5 (duration=10s >= total_duration=9s)
...
Segment 2 is only 2s long, shorter than min_seg_duration = 3s.
To fix this, new segments are created based on the actual written duration.
Otherwise the option name "min_seg_duration" is misleading.
Signed-off-by: Peter Große <[email protected]>
---
libavformat/dashenc.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 198932c..93c292f 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -62,7 +62,7 @@ typedef struct OutputStream {
int ctx_inited;
uint8_t iobuf[32768];
AVIOContext *out;
- int packets_written;
+ int duration_written;
char initfile[1024];
int64_t init_start_pos;
int init_range_length;
@@ -785,7 +785,7 @@ static int dash_flush(AVFormatContext *s, int final, int
stream)
int64_t start_pos;
int range_length, index_length = 0;
- if (!os->packets_written)
+ if (!os->duration_written)
continue;
// Flush the single stream that got a keyframe right now.
@@ -823,7 +823,7 @@ static int dash_flush(AVFormatContext *s, int final, int
stream)
av_write_frame(os->ctx, NULL);
avio_flush(os->ctx->pb);
- os->packets_written = 0;
+ os->duration_written = 0;
range_length = avio_tell(os->ctx->pb) - start_pos;
if (c->single_file) {
@@ -868,7 +868,6 @@ static int dash_write_packet(AVFormatContext *s, AVPacket
*pkt)
DASHContext *c = s->priv_data;
AVStream *st = s->streams[pkt->stream_index];
OutputStream *os = &c->streams[pkt->stream_index];
- int64_t seg_end_duration = (os->segment_index) * (int64_t)
c->min_seg_duration;
int ret;
ret = update_stream_extradata(s, os, st->codecpar);
@@ -897,9 +896,9 @@ static int dash_write_packet(AVFormatContext *s, AVPacket
*pkt)
os->first_pts = pkt->pts;
if ((!c->has_video || st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) &&
- pkt->flags & AV_PKT_FLAG_KEY && os->packets_written &&
- av_compare_ts(pkt->pts - os->first_pts, st->time_base,
- seg_end_duration, AV_TIME_BASE_Q) >= 0) {
+ pkt->flags & AV_PKT_FLAG_KEY && os->duration_written &&
+ av_compare_ts(os->duration_written + pkt->duration, st->time_base,
+ c->min_seg_duration, AV_TIME_BASE_Q) >= 0) {
int64_t prev_duration = c->last_duration;
c->last_duration = av_rescale_q(pkt->pts - os->start_pts,
@@ -922,7 +921,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket
*pkt)
return ret;
}
- if (!os->packets_written) {
+ if (!os->duration_written) {
// If we wrote a previous segment, adjust the start time of the segment
// to the end of the previous one (which is the same as the mp4 muxer
// does). This avoids gaps in the timeline.
@@ -935,7 +934,7 @@ static int dash_write_packet(AVFormatContext *s, AVPacket
*pkt)
os->max_pts = pkt->pts + pkt->duration;
else
os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);
- os->packets_written++;
+ os->duration_written += pkt->duration;
return ff_write_chained(os->ctx, 0, pkt, s);
}
--
2.10.2
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel