To show how to handle random-access writing, allow skipping writing
earlier segments. No packets for the skipped segments are sent to
the actual mp4 muxer.
---
I don't think this really should be committed, but it does serve as
an example on how to use the frag_discont/stream_start_times options,
and for verifying that the later segment files produced in this setup
are identical to the ones created in a normal setup.
---
libavformat/dashenc.c | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 0b9570d..0cce6f5 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -94,6 +94,7 @@ typedef struct DASHContext {
const char *init_seg_name;
const char *media_seg_name;
int start_segment;
+ int skip_segments;
} DASHContext;
static int dash_write(void *opaque, uint8_t *buf, int buf_size)
@@ -546,7 +547,8 @@ static int dash_write_header(AVFormatContext *s)
* timestamps back to zero, just make them nonnegative. The fragment
* timestamp offset written in the tfdt atoms assume that the stream
* starts (in the fragments that haven't been written) at dts=0. */
- if (c->start_segment > 1 && s->avoid_negative_ts ==
AVFMT_AVOID_NEG_TS_AUTO)
+ if (c->start_segment > 1 &&
+ s->avoid_negative_ts == AVFMT_AVOID_NEG_TS_AUTO)
s->avoid_negative_ts = AVFMT_AVOID_NEG_TS_MAKE_NON_NEGATIVE;
av_strlcpy(c->dirname, s->filename, sizeof(c->dirname));
@@ -634,8 +636,10 @@ static int dash_write_header(AVFormatContext *s)
goto fail;
os->init_start_pos = 0;
- if (c->start_segment > 1) {
+ if (c->start_segment > 1 || c->skip_segments > 0) {
av_dict_set(&opts, "movflags",
"frag_custom+dash+delay_moov+frag_discont", 0);
+ if (c->start_segment == 1)
+ av_dict_set(&opts, "use_editlist", "1", 0);
} else {
av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
av_dict_set(&opts, "use_editlist", "1", 0);
@@ -665,6 +669,10 @@ static int dash_write_header(AVFormatContext *s)
os->segment_index = c->start_segment;
}
+ // Set os->segment_index to start as usual, but set start_segment
+ // to match the first number that actually is written.
+ c->start_segment = FFMAX(c->skip_segments + 1, c->start_segment);
+
if (!c->has_video && c->min_seg_duration <= 0) {
av_log(s, AV_LOG_WARNING, "no video stream and no min seg duration
set\n");
ret = AVERROR(EINVAL);
@@ -772,6 +780,11 @@ static int dash_flush(AVFormatContext *s, int final, int
stream)
if (c->has_video && os->segment_index > cur_flush_segment_index)
continue;
}
+ if (os->segment_index <= c->skip_segments) {
+ os->packets_written = 0;
+ os->segment_index++;
+ continue;
+ }
if (!os->init_range_length) {
av_write_frame(os->ctx, NULL);
@@ -856,8 +869,12 @@ static int dash_write_packet(AVFormatContext *s, AVPacket
*pkt)
pkt->dts = 0;
}
- if (os->first_pts == AV_NOPTS_VALUE)
+ if (os->first_pts == AV_NOPTS_VALUE) {
+ char buf[100];
os->first_pts = pkt->pts;
+ snprintf(buf, sizeof(buf), "%"PRId64",%"PRId64, pkt->dts, pkt->pts);
+ av_opt_set(os->ctx, "stream_start_times", buf, AV_OPT_SEARCH_CHILDREN);
+ }
if ((!c->has_video || st->codec->codec_type == AVMEDIA_TYPE_VIDEO) &&
pkt->flags & AV_PKT_FLAG_KEY && os->packets_written &&
@@ -899,6 +916,8 @@ static int dash_write_packet(AVFormatContext *s, AVPacket
*pkt)
else
os->max_pts = FFMAX(os->max_pts, pkt->pts + pkt->duration);
os->packets_written++;
+ if (os->segment_index <= c->skip_segments)
+ return 0;
return ff_write_chained(os->ctx, 0, pkt, s);
}
@@ -949,6 +968,7 @@ static const AVOption options[] = {
{ "init_seg_name", "DASH-templated name to used for the initialization
segment", OFFSET(init_seg_name), AV_OPT_TYPE_STRING, {.str =
"init-stream$RepresentationID$.m4s"}, 0, 0, E },
{ "media_seg_name", "DASH-templated name to used for the media segments",
OFFSET(media_seg_name), AV_OPT_TYPE_STRING, {.str =
"chunk-stream$RepresentationID$-$Number%05d$.m4s"}, 0, 0, E },
{ "start_segment", "Segment number of the first segment",
OFFSET(start_segment), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, E },
+ { "skip_segments", "Skip segments", OFFSET(skip_segments),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, E },
{ NULL },
};
--
1.9.3 (Apple Git-50)
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel