[FFmpeg-devel] [PATCH 2/3] ffmpeg.c: refine picking default video stream
Anton Khirnov
anton at khirnov.net
Wed Oct 14 11:53:10 EEST 2020
Use a floating-point score value to take into account bitrate, when
multiple streams with the same resolution are present.
Stop accessing private AVStream.codec_info_nb_frames field, as the
sample in question
http://samples.ffmpeg.org/ffmpeg-bugs/trac/ticket2639/Thailand-Wave.wmv
is now handled by the above change.
---
fftools/ffmpeg_opt.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c
index a0d1b06f2d..afef23919c 100644
--- a/fftools/ffmpeg_opt.c
+++ b/fftools/ffmpeg_opt.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <float.h>
#include <stdint.h>
#include "ffmpeg.h"
@@ -2208,15 +2209,27 @@ static int open_output_file(OptionsContext *o, const char *filename)
char *subtitle_codec_name = NULL;
/* pick the "best" stream of each type */
- /* video: highest resolution */
+ /* video */
if (!o->video_disable && av_guess_codec(oc->oformat, NULL, filename, NULL, AVMEDIA_TYPE_VIDEO) != AV_CODEC_ID_NONE) {
- int best_score = 0, idx = -1;
+ double best_score = 0.0;
+ int idx = -1;
int qcr = avformat_query_codec(oc->oformat, oc->oformat->video_codec, 0);
for (i = 0; i < nb_input_streams; i++) {
- int score;
+ double score;
ist = input_streams[i];
- score = ist->st->codecpar->width * ist->st->codecpar->height + 100000000*!!ist->st->codec_info_nb_frames
- + 5000000*!!(ist->st->disposition & AV_DISPOSITION_DEFAULT);
+
+ /* base score is just the area in pixels */
+ score = (double)ist->st->codecpar->width * ist->st->codecpar->height;
+ /* add a fractional part favoring higher bitrate among same-area streams */
+ if (ist->st->codecpar->bit_rate) {
+ const double bitrate_max = 100e6; // cap at 100Mb/s
+ const double bitrate = FFMIN(ist->st->codecpar->bit_rate, bitrate_max - 1.0);
+ score += bitrate / bitrate_max;
+ }
+ /* default streams get max score */
+ if (ist->st->disposition & AV_DISPOSITION_DEFAULT)
+ score = DBL_MAX;
+
if (ist->user_set_discard == AVDISCARD_ALL)
continue;
if((qcr!=MKTAG('A', 'P', 'I', 'C')) && (ist->st->disposition & AV_DISPOSITION_ATTACHED_PIC))
--
2.28.0
More information about the ffmpeg-devel
mailing list