Skip to content

Commit 45675fa

Browse files
committed
[fixup][ffmpeg] Fix building with system ffmpeg
Refactor workaround for codec selection issues. Introduce FindDecoder which meant to replace avcodec_find_decoder. Imporove codec detection in format context. Fixes: QTBUG-132762 Task-number: QTBUG-130273 Change-Id: I6d520633ebebbb9bdb7aa71b8247066c2a662be3 Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/617873 Reviewed-by: Moss Heim <[email protected]> Reviewed-by: Allan Sandfeld Jensen <[email protected]> (cherry picked from commit 54a756b) Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/624053 Reviewed-by: Qt Cherry-pick Bot <[email protected]>
1 parent add08d5 commit 45675fa

File tree

8 files changed

+69
-24
lines changed

8 files changed

+69
-24
lines changed

chromium/media/cdm/library_cdm/clear_key_cdm/ffmpeg_cdm_audio_decoder.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,12 @@ bool FFmpegCdmAudioDecoder::Initialize(
177177
if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P)
178178
codec_context_->request_sample_fmt = AV_SAMPLE_FMT_S16;
179179

180+
#if BUILDFLAG(IS_QTWEBENGINE) && BUILDFLAG(USE_SYSTEM_FFMPEG)
181+
const AVCodec* codec =
182+
FindDecoder(codec_context_->codec_id, codec_context_->codec_whitelist);
183+
#else
180184
const AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
185+
#endif
181186
if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) {
182187
DLOG(ERROR) << "Could not initialize audio decoder: "
183188
<< codec_context_->codec_id;

chromium/media/ffmpeg/ffmpeg_common.cc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
2929
#endif
3030
#endif
3131

32+
#if BUILDFLAG(IS_QTWEBENGINE) && BUILDFLAG(USE_SYSTEM_FFMPEG)
33+
extern "C" {
34+
#include <libavutil/avstring.h>
35+
}
36+
#endif
3237
namespace media {
3338

3439
namespace {
@@ -67,6 +72,24 @@ static_assert(
6772
VideoFrame::kFrameAddressAlignment % kFFmpegBufferAddressAlignment == 0,
6873
"VideoFrame frame address alignment does not fit ffmpeg requirement");
6974

75+
#if BUILDFLAG(IS_QTWEBENGINE) && BUILDFLAG(USE_SYSTEM_FFMPEG)
76+
const AVCodec* FindDecoder(AVCodecID id, const char* whitelist) {
77+
if (!whitelist) {
78+
return avcodec_find_decoder(id);
79+
}
80+
81+
void* i = 0;
82+
const AVCodec* codec;
83+
while (codec = av_codec_iterate(&i)) {
84+
if (av_codec_is_decoder(codec) && codec->id == id &&
85+
av_match_list(codec->name, whitelist, ',')) {
86+
return codec;
87+
}
88+
}
89+
return nullptr;
90+
}
91+
#endif
92+
7093
static const AVRational kMicrosBase = { 1, base::Time::kMicrosecondsPerSecond };
7194

7295
base::TimeDelta ConvertFromTimeBase(const AVRational& time_base,

chromium/media/ffmpeg/ffmpeg_common.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ inline base::span<const uint8_t> AVPacketData(const AVPacket& packet) {
9393
base::span(packet.data, base::checked_cast<size_t>(packet.size)));
9494
}
9595

96+
#if BUILDFLAG(IS_QTWEBENGINE) && BUILDFLAG(USE_SYSTEM_FFMPEG)
97+
// Systemlib friendly version of avcodec_find_decoder that respects the
98+
// whitelisted codecs.
99+
MEDIA_EXPORT const AVCodec* FindDecoder(AVCodecID id, const char* whitelist);
100+
#endif
101+
96102
// Converts an int64_t timestamp in |time_base| units to a base::TimeDelta.
97103
// For example if |timestamp| equals 11025 and |time_base| equals {1, 44100}
98104
// then the return value will be a base::TimeDelta for 0.25 seconds since that

chromium/media/filters/audio_file_reader.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,12 @@ bool AudioFileReader::OpenDemuxer() {
9797
}
9898

9999
bool AudioFileReader::OpenDecoder() {
100+
#if BUILDFLAG(IS_QTWEBENGINE) && BUILDFLAG(USE_SYSTEM_FFMPEG)
101+
const AVCodec* codec =
102+
FindDecoder(codec_context_->codec_id, codec_context_->codec_whitelist);
103+
#else
100104
const AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
105+
#endif
101106
if (codec) {
102107
// MP3 decodes to S16P which we don't support, tell it to use S16 instead.
103108
if (codec_context_->sample_fmt == AV_SAMPLE_FMT_S16P)

chromium/media/filters/ffmpeg_audio_decoder.cc

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -360,19 +360,8 @@ bool FFmpegAudioDecoder::ConfigureDecoder(const AudioDecoderConfig& config) {
360360
}
361361

362362
#if BUILDFLAG(IS_QTWEBENGINE) && BUILDFLAG(USE_SYSTEM_FFMPEG)
363-
// Workaround http://crbug.com/41492567
364-
// Chromium only supports the 'libopus' decoder.
365-
// 'avcodec_find_decoder' finds the experimental 'opus' decoder first
366-
// because the lookup is based on codec_id and both have the same id.
367-
// Bundled ffmpeg only have libopus but the system usually have both.
368-
const AVCodec* codec = [&config, this]() {
369-
if (config.codec() == AudioCodec::kOpus)
370-
return avcodec_find_decoder_by_name("libopus");
371-
if (config.codec() == AudioCodec::kMP3) {
372-
return avcodec_find_decoder_by_name("mp3");
373-
}
374-
return avcodec_find_decoder(codec_context_->codec_id);
375-
}();
363+
AVCodecID id = AudioCodecToCodecID(config.codec(), config.sample_format());
364+
const AVCodec* codec = FindDecoder(id, codec_context_->codec_whitelist);
376365
#else
377366
const AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
378367
#endif

chromium/media/filters/ffmpeg_glue.cc

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -247,20 +247,27 @@ bool FFmpegGlue::OpenContext(bool is_local_file) {
247247
LogContainer(is_local_file, container_);
248248

249249
#if BUILDFLAG(IS_QTWEBENGINE) && BUILDFLAG(USE_SYSTEM_FFMPEG)
250-
// Sometimes FFmpeg is not aware of the whitelisted codecs and
251-
// configures streams and demuxers with unsupported codecs/params.
252-
// Force the correct codecs to avoid problems later.
250+
// 'avformat_find_stream_info' is not aware of the whitelisted codecs.
251+
// However it respects the codecs set in the format_context.
252+
// Try to force the correct codecs here at context creation.
253253
// https://ffmpeg.org/doxygen/7.0/structAVFormatContext.html#a52f39351b15890ef57cc6ff0ec9ab42d
254254
// https://ffmpeg.org/doxygen/7.0/structAVFormatContext.html#ae5e087f4623b907517c0f7dd8327387d
255255

256-
// Note: don't forget to update FFmpeg[Audio|Video]Decoder::ConfigureDecoder
257-
258-
if (strcmp(format_context_->iformat->name, "mp3") == 0) {
259-
const AVCodec* mp3_codec = avcodec_find_decoder_by_name("mp3");
260-
if (mp3_codec) {
261-
format_context_->audio_codec = mp3_codec;
262-
} else {
263-
LOG(ERROR) << "No supported codec for mp3";
256+
for (int i = 0; i < format_context_->nb_streams; i++) {
257+
AVCodecParameters *params = format_context_->streams[i]->codecpar;
258+
if (!params)
259+
continue;
260+
const AVCodec* audio_codec =
261+
FindDecoder(params->codec_id, GetAllowedAudioDecoders());
262+
if (audio_codec) {
263+
if (format_context_->audio_codec &&
264+
format_context_->audio_codec != audio_codec) {
265+
LOG(INFO) << "Conflicting codecs " << format_context_->audio_codec->name
266+
<< ", " << audio_codec->name;
267+
format_context_->audio_codec = nullptr;
268+
break;
269+
}
270+
format_context_->audio_codec = audio_codec;
264271
}
265272
}
266273
#endif

chromium/media/filters/ffmpeg_video_decoder.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,12 @@ bool FFmpegVideoDecoder::ConfigureDecoder(const VideoDecoderConfig& config,
519519
codec_context_->flags2 |= AV_CODEC_FLAG2_CHUNKS;
520520
}
521521

522+
#if BUILDFLAG(IS_QTWEBENGINE) && BUILDFLAG(USE_SYSTEM_FFMPEG)
523+
const AVCodec* codec =
524+
FindDecoder(codec_context_->codec_id, codec_context_->codec_whitelist);
525+
#else
522526
const AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id);
527+
#endif
523528
if (!codec || avcodec_open2(codec_context_.get(), codec, NULL) < 0) {
524529
ReleaseFFmpegResources();
525530
return false;

chromium/media/filters/media_file_checker.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,12 @@ bool MediaFileChecker::Start(base::TimeDelta check_time) {
6969
auto context = AVStreamToAVCodecContext(format_context->streams[i]);
7070
if (!context)
7171
continue;
72+
#if BUILDFLAG(IS_QTWEBENGINE) && BUILDFLAG(USE_SYSTEM_FFMPEG)
73+
const AVCodec* codec =
74+
FindDecoder(cp->codec_id, context->codec_whitelist);
75+
#else
7276
const AVCodec* codec = avcodec_find_decoder(cp->codec_id);
77+
#endif
7378
if (codec && avcodec_open2(context.get(), codec, nullptr) >= 0) {
7479
auto loop = std::make_unique<FFmpegDecodingLoop>(context.get());
7580
stream_contexts[i] = {std::move(context), std::move(loop)};

0 commit comments

Comments
 (0)