mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2024-12-24 00:02:52 +00:00
avformat/dashenc: Add framerate to dash manifest
DASH manifest should have framerate specified as an attribute in the AdaptationSet element and Representation elements. Though ISO/IEC 23009-1:2014 doesn't seem to define frameRate as a required attribute, it is at least optional, and DASH-IF IOP 3.0 seems to require it. See section 3.2.4 of http://dashif.org/w/2015/04/DASH-IF-IOP-v3.0.pdf In the event that avg_frame_rate is not set in the muxer, we ignore the frameRate tag altogther. Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
parent
35bbc1955a
commit
0be48dd9bb
@ -24,10 +24,12 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "libavutil/avassert.h"
|
||||
#include "libavutil/avstring.h"
|
||||
#include "libavutil/intreadwrite.h"
|
||||
#include "libavutil/mathematics.h"
|
||||
#include "libavutil/opt.h"
|
||||
#include "libavutil/rational.h"
|
||||
#include "libavutil/time_internal.h"
|
||||
|
||||
#include "avc.h"
|
||||
@ -94,6 +96,8 @@ typedef struct DASHContext {
|
||||
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;
|
||||
} DASHContext;
|
||||
|
||||
static int dash_write(void *opaque, uint8_t *buf, int buf_size)
|
||||
@ -503,7 +507,11 @@ static int write_manifest(AVFormatContext *s, int final)
|
||||
}
|
||||
|
||||
if (c->has_video) {
|
||||
avio_printf(out, "\t\t<AdaptationSet contentType=\"video\" segmentAlignment=\"true\" bitstreamSwitching=\"true\">\n");
|
||||
avio_printf(out, "\t\t<AdaptationSet contentType=\"video\" segmentAlignment=\"true\" bitstreamSwitching=\"true\"");
|
||||
if (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);
|
||||
avio_printf(out, ">\n");
|
||||
|
||||
for (i = 0; i < s->nb_streams; i++) {
|
||||
AVStream *st = s->streams[i];
|
||||
OutputStream *os = &c->streams[i];
|
||||
@ -511,7 +519,11 @@ static int write_manifest(AVFormatContext *s, int final)
|
||||
if (st->codec->codec_type != AVMEDIA_TYPE_VIDEO)
|
||||
continue;
|
||||
|
||||
avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/mp4\" codecs=\"%s\"%s width=\"%d\" height=\"%d\">\n", i, os->codec_str, os->bandwidth_str, st->codec->width, st->codec->height);
|
||||
avio_printf(out, "\t\t\t<Representation id=\"%d\" mimeType=\"video/mp4\" codecs=\"%s\"%s width=\"%d\" height=\"%d\"", i, os->codec_str, os->bandwidth_str, st->codec->width, st->codec->height);
|
||||
if (st->avg_frame_rate.num)
|
||||
avio_printf(out, " frameRate=\"%d/%d\"", st->avg_frame_rate.num, st->avg_frame_rate.den);
|
||||
avio_printf(out, ">\n");
|
||||
|
||||
output_segment_list(&c->streams[i], out, c);
|
||||
avio_printf(out, "\t\t\t</Representation>\n");
|
||||
}
|
||||
@ -552,6 +564,7 @@ static int dash_write_header(AVFormatContext *s)
|
||||
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, '/');
|
||||
@ -655,10 +668,20 @@ static int dash_write_header(AVFormatContext *s)
|
||||
// already before being handed to this muxer, so we don't have mismatches
|
||||
// between the MPD and the actual segments.
|
||||
s->avoid_negative_ts = ctx->avoid_negative_ts;
|
||||
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
if (st->codec->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;
|
||||
} else {
|
||||
c->ambiguous_frame_rate = 1;
|
||||
}
|
||||
c->has_video = 1;
|
||||
else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO)
|
||||
} else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
|
||||
c->has_audio = 1;
|
||||
}
|
||||
|
||||
set_codec_str(s, st->codec, os->codec_str, sizeof(os->codec_str));
|
||||
os->first_pts = AV_NOPTS_VALUE;
|
||||
|
Loading…
Reference in New Issue
Block a user