char id[10];
enum AVMediaType media_type;
AVDictionary *metadata;
+ AVRational min_frame_rate, max_frame_rate;
+ int ambiguous_frame_rate;
} AdaptationSet;
typedef struct OutputStream {
const char *single_file_name;
const char *init_seg_name;
const char *media_seg_name;
- AVRational min_frame_rate, max_frame_rate;
- int ambiguous_frame_rate;
const char *utc_timing_url;
} DASHContext;
avio_printf(out, "\t\t<AdaptationSet id=\"%s\" contentType=\"%s\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"",
as->id, as->media_type == AVMEDIA_TYPE_VIDEO ? "video" : "audio");
- if (as->media_type == AVMEDIA_TYPE_VIDEO && c->max_frame_rate.num && !c->ambiguous_frame_rate)
- avio_printf(out, " %s=\"%d/%d\"", (av_cmp_q(c->min_frame_rate, c->max_frame_rate) < 0) ? "maxFrameRate" : "frameRate", c->max_frame_rate.num, c->max_frame_rate.den);
+ if (as->media_type == AVMEDIA_TYPE_VIDEO && as->max_frame_rate.num && !as->ambiguous_frame_rate && av_cmp_q(as->min_frame_rate, as->max_frame_rate) < 0)
+ avio_printf(out, " maxFrameRate=\"%d/%d\"", as->max_frame_rate.num, as->max_frame_rate.den);
lang = av_dict_get(as->metadata, "language", NULL, 0);
if (lang)
avio_printf(out, " lang=\"%s\"", lang->value);
av_free(escaped);
}
avio_printf(out, "\t</ProgramInformation>\n");
- if (c->utc_timing_url)
- avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
if (c->window_size && s->nb_streams > 0 && c->streams[0].nb_segments > 0 && !c->use_template) {
OutputStream *os = &c->streams[0];
return ret;
}
avio_printf(out, "\t</Period>\n");
+
+ if (c->utc_timing_url)
+ avio_printf(out, "\t<UTCTiming schemeIdUri=\"urn:mpeg:dash:utc:http-xsdate:2014\" value=\"%s\"/>\n", c->utc_timing_url);
+
avio_printf(out, "</MPD>\n");
avio_flush(out);
ff_format_io_close(s, &out);
return 0;
}
-static int dict_set_int(AVDictionary **pm, const char *key, int64_t value, int flags)
-{
- char valuestr[22];
- snprintf(valuestr, sizeof(valuestr), "%"PRId64, value);
- flags &= ~AV_DICT_DONT_STRDUP_VAL;
- return av_dict_set(pm, key, valuestr, flags);
-}
-
static int dash_init(AVFormatContext *s)
{
DASHContext *c = s->priv_data;
c->single_file = 1;
if (c->single_file)
c->use_template = 0;
- c->ambiguous_frame_rate = 0;
av_strlcpy(c->dirname, s->filename, sizeof(c->dirname));
ptr = strrchr(c->dirname, '/');
avcodec_parameters_copy(st->codecpar, s->streams[i]->codecpar);
st->sample_aspect_ratio = s->streams[i]->sample_aspect_ratio;
st->time_base = s->streams[i]->time_base;
+ st->avg_frame_rate = s->streams[i]->avg_frame_rate;
ctx->avoid_negative_ts = s->avoid_negative_ts;
ctx->flags = s->flags;
if (!strcmp(os->format_name, "mp4")) {
av_dict_set(&opts, "movflags", "frag_custom+dash+delay_moov", 0);
} else {
- dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0);
- dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit
+ av_dict_set_int(&opts, "cluster_time_limit", c->min_seg_duration / 1000, 0);
+ av_dict_set_int(&opts, "cluster_size_limit", 5 * 1024 * 1024, 0); // set a large cluster size limit
+ av_dict_set_int(&opts, "dash", 1, 0);
+ av_dict_set_int(&opts, "dash_track_number", i + 1, 0);
+ av_dict_set_int(&opts, "live", 1, 0);
}
- if ((ret = avformat_write_header(ctx, &opts)) < 0)
+ if ((ret = avformat_init_output(ctx, &opts)) < 0)
return ret;
os->ctx_inited = 1;
avio_flush(ctx->pb);
if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
AVRational avg_frame_rate = s->streams[i]->avg_frame_rate;
if (avg_frame_rate.num > 0) {
- if (av_cmp_q(avg_frame_rate, c->min_frame_rate) < 0)
- c->min_frame_rate = avg_frame_rate;
- if (av_cmp_q(c->max_frame_rate, avg_frame_rate) < 0)
- c->max_frame_rate = avg_frame_rate;
+ if (av_cmp_q(avg_frame_rate, as->min_frame_rate) < 0)
+ as->min_frame_rate = avg_frame_rate;
+ if (av_cmp_q(as->max_frame_rate, avg_frame_rate) < 0)
+ as->max_frame_rate = avg_frame_rate;
} else {
- c->ambiguous_frame_rate = 1;
+ as->ambiguous_frame_rate = 1;
}
c->has_video = 1;
}
for (i = 0; i < s->nb_streams; i++) {
OutputStream *os = &c->streams[i];
+ AVStream *st = s->streams[i];
char filename[1024] = "", full_path[1024], temp_path[1024];
int range_length, index_length = 0;
if (!os->bit_rate) {
// calculate average bitrate of first segment
- int64_t bitrate = (int64_t) range_length * 8 * AV_TIME_BASE / (os->max_pts - os->start_pts);
+ int64_t bitrate = (int64_t) range_length * 8 / ((os->max_pts - os->start_pts) * av_q2d(st->time_base));
if (bitrate >= 0) {
os->bit_rate = bitrate;
snprintf(os->bandwidth_str, sizeof(os->bandwidth_str),