[FFmpeg-devel] [PATCH 3/4] ffmpeg: make -bits_per_raw_sample a per-output-stream option

Anton Khirnov anton at khirnov.net
Tue Nov 23 12:30:00 EET 2021


Also, document it and make it apply to audio in addition to video.
---
 doc/ffmpeg.texi      |  7 +++++++
 fftools/ffmpeg.c     | 11 +++++++----
 fftools/ffmpeg.h     |  3 +++
 fftools/ffmpeg_opt.c | 11 +++++++----
 4 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index 8418573618..5279a05b10 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -1945,6 +1945,13 @@ filter (scale, aresample) in the graph.
 On by default, to explicitly disable it you need to specify
 @code{-noauto_conversion_filters}.
 
+ at item -bits_per_raw_sample[:@var{stream_specifier}] @var{value} (@emph{output,per-stream})
+Declare the number of bits per raw sample in the given output stream to be
+ at var{value}. Note that this option sets the information provided to the
+encoder/muxer, it does not change the stream to conform to this value. Setting
+values that do not match the stream properties may result in encoding failures
+or invalid output files.
+
 @end table
 
 @section Preset files
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index 7dfcfc13f5..55ad4e558e 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -3411,13 +3411,16 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
     switch (enc_ctx->codec_type) {
     case AVMEDIA_TYPE_AUDIO:
         enc_ctx->sample_fmt     = av_buffersink_get_format(ost->filter->filter);
-        if (dec_ctx)
-            enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample,
-                                                 av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3);
         enc_ctx->sample_rate    = av_buffersink_get_sample_rate(ost->filter->filter);
         enc_ctx->channel_layout = av_buffersink_get_channel_layout(ost->filter->filter);
         enc_ctx->channels       = av_buffersink_get_channels(ost->filter->filter);
 
+        if (ost->bits_per_raw_sample)
+            enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample;
+        else if (dec_ctx)
+            enc_ctx->bits_per_raw_sample = FFMIN(dec_ctx->bits_per_raw_sample,
+                                                 av_get_bytes_per_sample(enc_ctx->sample_fmt) << 3);
+
         init_encoder_time_base(ost, av_make_q(1, enc_ctx->sample_rate));
         break;
 
@@ -3460,7 +3463,7 @@ static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
             enc_ctx->width   != dec_ctx->width  ||
             enc_ctx->height  != dec_ctx->height ||
             enc_ctx->pix_fmt != dec_ctx->pix_fmt) {
-            enc_ctx->bits_per_raw_sample = frame_bits_per_raw_sample;
+            enc_ctx->bits_per_raw_sample = ost->bits_per_raw_sample;
         }
 
         // Field order: autodetection
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 545ff1c8e7..3d9bb30e72 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -236,6 +236,8 @@ typedef struct OptionsContext {
     int        nb_enc_time_bases;
     SpecifierOpt *autoscale;
     int        nb_autoscale;
+    SpecifierOpt *bits_per_raw_sample;
+    int        nb_bits_per_raw_sample;
 } OptionsContext;
 
 typedef struct InputFilter {
@@ -493,6 +495,7 @@ typedef struct OutputStream {
     int top_field_first;
     int rotate_overridden;
     int autoscale;
+    int bits_per_raw_sample;
     double rotate_override_value;
 
     AVRational frame_aspect_ratio;
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index b423d0e59c..e839a830a6 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -96,6 +96,7 @@ static const char *const opt_name_discard[]                   = {"discard", NULL
 static const char *const opt_name_disposition[]               = {"disposition", NULL};
 static const char *const opt_name_time_bases[]                = {"time_base", NULL};
 static const char *const opt_name_enc_time_bases[]            = {"enc_time_base", NULL};
+static const char *const opt_name_bits_per_raw_sample[]       = {"bits_per_raw_sample", NULL};
 
 #define WARN_MULTIPLE_OPT_USAGE(name, type, so, st)\
 {\
@@ -167,7 +168,6 @@ int abort_on_flags    = 0;
 int print_stats       = -1;
 int qp_hist           = 0;
 int stdin_interaction = 1;
-int frame_bits_per_raw_sample = 0;
 float max_error_rate  = 2.0/3;
 char *filter_nbthreads;
 int filter_complex_nbthreads = 0;
@@ -1636,6 +1636,9 @@ static OutputStream *new_output_stream(OptionsContext *o, AVFormatContext *oc, e
     ost->muxing_queue_data_threshold = 50*1024*1024;
     MATCH_PER_STREAM_OPT(muxing_queue_data_threshold, i, ost->muxing_queue_data_threshold, oc, st);
 
+    MATCH_PER_STREAM_OPT(bits_per_raw_sample, i, ost->bits_per_raw_sample,
+                         oc, st);
+
     if (oc->oformat->flags & AVFMT_GLOBALHEADER)
         ost->enc_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;
 
@@ -1801,7 +1804,6 @@ static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext *oc, in
             exit_program(1);
         }
 
-        video_enc->bits_per_raw_sample = frame_bits_per_raw_sample;
         MATCH_PER_STREAM_OPT(frame_pix_fmts, str, frame_pix_fmt, oc, st);
         if (frame_pix_fmt && *frame_pix_fmt == '+') {
             ost->keep_pix_fmt = 1;
@@ -3743,6 +3745,9 @@ const OptionDef options[] = {
         "set the maximum number of queued packets from the demuxer" },
     { "find_stream_info", OPT_BOOL | OPT_PERFILE | OPT_INPUT | OPT_EXPERT, { &find_stream_info },
         "read and decode the streams to fill missing information with heuristics" },
+    { "bits_per_raw_sample", OPT_INT | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_OUTPUT,
+        { .off = OFFSET(bits_per_raw_sample) },
+        "set the number of bits per raw sample", "number" },
 
     /* video options */
     { "vframes",      OPT_VIDEO | HAS_ARG  | OPT_PERFILE | OPT_OUTPUT,           { .func_arg = opt_video_frames },
@@ -3762,8 +3767,6 @@ const OptionDef options[] = {
     { "pix_fmt",      OPT_VIDEO | HAS_ARG | OPT_EXPERT  | OPT_STRING | OPT_SPEC |
                       OPT_INPUT | OPT_OUTPUT,                                    { .off = OFFSET(frame_pix_fmts) },
         "set pixel format", "format" },
-    { "bits_per_raw_sample", OPT_VIDEO | OPT_INT | HAS_ARG,                      { &frame_bits_per_raw_sample },
-        "set the number of bits per raw sample", "number" },
     { "intra",        OPT_VIDEO | OPT_BOOL | OPT_EXPERT,                         { &intra_only },
         "deprecated use -g 1" },
     { "vn",           OPT_VIDEO | OPT_BOOL  | OPT_OFFSET | OPT_INPUT | OPT_OUTPUT,{ .off = OFFSET(video_disable) },
-- 
2.33.0



More information about the ffmpeg-devel mailing list