[FFmpeg-devel] [PATCH] avformat/dashenc: Add framerate to dash manifest

Bryan Huh bryan at box.com
Wed Nov 18 10:16:26 CET 2015


Second patchset addresses feedback after discussion with Martin. It is now
accounting for the fact that avg_frame_rate may not always be set.

On Wed, Nov 18, 2015 at 1:13 AM, Bryan Huh <bryan at box.com> wrote:

> 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.
> ---
>  libavformat/dashenc.c |   31 +++++++++++++++++++++++++++----
>  1 files changed, 27 insertions(+), 4 deletions(-)
>
> diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
> index 7a93214..9c2b4dd 100644
> --- a/libavformat/dashenc.c
> +++ b/libavformat/dashenc.c
> @@ -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;
> --
> 1.7.1
>
>


More information about the ffmpeg-devel mailing list