[06/12] dashenc: support for hinting stream bandwidth using metadata option

Message ID 20170127200816.787.32793@localhost
State New
Headers show

Commit Message

Anton Khirnov Jan. 27, 2017, 8:08 p.m.
Quoting Peter Große (2017-01-27 20:16:31)
> On Fri, 27 Jan 2017 19:34:42 +0100
> Anton Khirnov <anton@khirnov.net> wrote:
> 
> > If we did, I don't remember the conclusion :)
> > 
> > Anyway, I agree that this is a misuse of metadata. There are at least
> > two methods for passing the stream bitrate to the muxer -- the
> > AVCodecParameters.bit_rate field and the AV_PKT_DATA_CPB_PROPERTIES side
> > data.
> > 
> > IIUC, the problem you're trying to solve is that avconv does not set the
> > bit_rate field in certain situations. If that's the case, that should be
> > fixed in avconv. We should not design our muxer behaviour around
> > limitations of one specific caller.
> > 
> > If you describe more fully what's the situation where bit_rate is not
> > set properly, I might have some more specific ideas for handling this.
> 
> Hm I see.
> 
> I tried to remux an already encoded MKV stream pulled from an icecast server.
> So I used -codec copy and the upstream container didn't contain bitrate
> metadata.
> Avprobe output from a stream dump see below [1].
> 
> For DASH I needed to hint the average bandwith of a stream in the manifest.
> Calculating this from the first segment created might be an option, but I felt
> more comfortable explicitly hinting the bandwidth via a metadata option.
> 
> Other than for the manifest, this value isn't used anywhere, as far as I
> remember.
> 
> I thought the parser for the adaptation_set option is complex enough. I tried
> to avoid writing another one for adding metadata to individual streams.
> 
> Yes, the obvious solution would be to fix the upstream encoder. But I'm not
> sure, whether I get all possible codecs to write an average bitrate to their
> stream metadata.

Actually I'd say the issue is just that matroska does not have a field
for storing the bitrate. And the right workaround for that issue would
be allowing avconv to override the muxer bitrate for streamcopy.

The following code should make -b work for streamcopy, then you can just
pull the information from AVCodecParameters.bit_rate:

Comments

Peter Große Jan. 28, 2017, 12:39 a.m. | #1
On Fri, 27 Jan 2017 21:08:16 +0100
Anton Khirnov <anton@khirnov.net> wrote:

> Actually I'd say the issue is just that matroska does not have a field
> for storing the bitrate. And the right workaround for that issue would
> be allowing avconv to override the muxer bitrate for streamcopy.
> 
> The following code should make -b work for streamcopy, then you can just
> pull the information from AVCodecParameters.bit_rate:

That works like a charm ;)

So I drop my patch.

Thanks ;)

Regards
Peter

Patch

diff --git a/avconv.c b/avconv.c
index fe60625..94b6da2 100644
--- a/avconv.c
+++ b/avconv.c
@@ -1852,6 +1852,9 @@  static int init_output_stream_streamcopy(OutputStream *ost)
 
     ost->st->time_base = ist->st->time_base;
 
+    if (ost->bitrate_override)
+        par_dst->bit_rate = ost->bitrate_override;
+
     if (ist->st->nb_side_data) {
         ost->st->side_data = av_realloc_array(NULL, ist->st->nb_side_data,
                                               sizeof(*ist->st->side_data));
diff --git a/avconv.h b/avconv.h
index 6360f76..3c3f0ef 100644
--- a/avconv.h
+++ b/avconv.h
@@ -162,6 +162,8 @@  typedef struct OptionsContext {
     int        nb_sample_fmts;
     SpecifierOpt *qscale;
     int        nb_qscale;
+    SpecifierOpt *bitrates;
+    int        nb_bitrates;
     SpecifierOpt *forced_key_frames;
     int        nb_forced_key_frames;
     SpecifierOpt *force_fps;
@@ -382,6 +384,9 @@  typedef struct OutputStream {
     int forced_kf_index;
     char *forced_keyframes;
 
+    // the bitrate to send to the muxer for streamcopy
+    int bitrate_override;
+
     char *logfile_prefix;
     FILE *logfile;
 
diff --git a/avconv_opt.c b/avconv_opt.c
index 8b43f0f..e078a0b 100644
--- a/avconv_opt.c
+++ b/avconv_opt.c
@@ -952,6 +952,7 @@  static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
     const char *bsfs = NULL;
     char *next, *codec_tag = NULL;
     double qscale = -1;
+    int bitrate = 0;
 
     if (!st) {
         av_log(NULL, AV_LOG_FATAL, "Could not alloc stream.\n");
@@ -1091,6 +1092,14 @@  static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
         ost->enc_ctx->global_quality = FF_QP2LAMBDA * qscale;
     }
 
+    MATCH_PER_STREAM_OPT(bitrates, i, bitrate, oc, st);
+    if (bitrate > 0) {
+        if (ost->stream_copy)
+            ost->bitrate_override = bitrate;
+        else
+            ost->enc_ctx->bit_rate = bitrate;
+    }
+
     ost->max_muxing_queue_size = 128;
     MATCH_PER_STREAM_OPT(max_muxing_queue_size, i, ost->max_muxing_queue_size, oc, st);
     ost->max_muxing_queue_size *= sizeof(AVPacket);
@@ -2570,6 +2579,8 @@  const OptionDef options[] = {
     { "qscale",         HAS_ARG | OPT_EXPERT | OPT_DOUBLE |
                         OPT_SPEC | OPT_OUTPUT,                       { .off = OFFSET(qscale) },
         "use fixed quality scale (VBR)", "q" },
+    { "b",              HAS_ARG | OPT_INT | OPT_SPEC | OPT_OUTPUT,    { .off = OFFSET(bitrates) },
+        "set stream bitrate in bits/second", "bitrate" },
     { "filter",         HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filters) },
         "set stream filterchain", "filter_list" },
     { "filter_script",  HAS_ARG | OPT_STRING | OPT_SPEC | OPT_OUTPUT, { .off = OFFSET(filter_scripts) },