diff --git a/arm/build/config/compiler/BUILD.gn b/arm/build/config/compiler/BUILD.gn index 46c23485c..c5fb826e5 100644 --- a/arm/build/config/compiler/BUILD.gn +++ b/arm/build/config/compiler/BUILD.gn @@ -499,6 +499,12 @@ config("compiler") { ldflags += [ "-fPIC" ] rustflags += [ "-Crelocation-model=pic" ] + if (is_clang && chrome_pgo_phase == 2) { + asmflags += [ "-fbasic-block-sections=labels" ] + cflags += [ "-fbasic-block-sections=labels" ] + rustflags += [ "-Cllvm-args=-basic-block-sections=labels" ] + } + if (!is_clang) { # Use pipes for communicating between sub-processes. Faster. # (This flag doesn't do anything with Clang.) diff --git a/arm/raspi/build/config/compiler/BUILD.gn b/arm/raspi/build/config/compiler/BUILD.gn index 9de6e0d9b..2632b00c7 100644 --- a/arm/raspi/build/config/compiler/BUILD.gn +++ b/arm/raspi/build/config/compiler/BUILD.gn @@ -499,6 +499,12 @@ config("compiler") { ldflags += [ "-fPIC" ] rustflags += [ "-Crelocation-model=pic" ] + if (is_clang && chrome_pgo_phase == 2) { + asmflags += [ "-fbasic-block-sections=labels" ] + cflags += [ "-fbasic-block-sections=labels" ] + rustflags += [ "-Cllvm-args=-basic-block-sections=labels" ] + } + if (!is_clang) { # Use pipes for communicating between sub-processes. Faster. # (This flag doesn't do anything with Clang.) diff --git a/infra/THORIUM_DEV_BOOKMARKS.html b/infra/THORIUM_DEV_BOOKMARKS.html index 3004c158d..51113a236 100644 --- a/infra/THORIUM_DEV_BOOKMARKS.html +++ b/infra/THORIUM_DEV_BOOKMARKS.html @@ -48,6 +48,7 @@

Bookmarks

BUILD.gn - Chromium Code Search
media_switches.cc - Chromium Code Search
ffmpeg_video_decoder.cc - Chromium Code Search +
ffmpeg_glue.cc - Chromium Code Search
gpu_video_decode_accelerator_factory.cc - Chromium Code Search
gpu_video_decode_accelerator.cc - Chromium Code Search
vaapi_video_decode_accelerator.cc - Chromium Code Search diff --git a/other/AVX2/build/config/compiler/BUILD.gn b/other/AVX2/build/config/compiler/BUILD.gn index bcd95ff84..062193185 100644 --- a/other/AVX2/build/config/compiler/BUILD.gn +++ b/other/AVX2/build/config/compiler/BUILD.gn @@ -499,6 +499,12 @@ config("compiler") { ldflags += [ "-fPIC" ] rustflags += [ "-Crelocation-model=pic" ] + if (is_clang && chrome_pgo_phase == 2) { + asmflags += [ "-fbasic-block-sections=labels" ] + cflags += [ "-fbasic-block-sections=labels" ] + rustflags += [ "-Cllvm-args=-basic-block-sections=labels" ] + } + if (!is_clang) { # Use pipes for communicating between sub-processes. Faster. # (This flag doesn't do anything with Clang.) diff --git a/other/CrOS/build/config/compiler/BUILD.gn b/other/CrOS/build/config/compiler/BUILD.gn index 8038e1edf..dd92a4f2c 100644 --- a/other/CrOS/build/config/compiler/BUILD.gn +++ b/other/CrOS/build/config/compiler/BUILD.gn @@ -499,6 +499,12 @@ config("compiler") { ldflags += [ "-fPIC" ] rustflags += [ "-Crelocation-model=pic" ] + if (is_clang && chrome_pgo_phase == 2) { + asmflags += [ "-fbasic-block-sections=labels" ] + cflags += [ "-fbasic-block-sections=labels" ] + rustflags += [ "-Cllvm-args=-basic-block-sections=labels" ] + } + if (!is_clang) { # Use pipes for communicating between sub-processes. Faster. # (This flag doesn't do anything with Clang.) diff --git a/other/SSE3/build/config/compiler/BUILD.gn b/other/SSE3/build/config/compiler/BUILD.gn index 845d66c77..847d1bc33 100644 --- a/other/SSE3/build/config/compiler/BUILD.gn +++ b/other/SSE3/build/config/compiler/BUILD.gn @@ -499,6 +499,12 @@ config("compiler") { ldflags += [ "-fPIC" ] rustflags += [ "-Crelocation-model=pic" ] + if (is_clang && chrome_pgo_phase == 2) { + asmflags += [ "-fbasic-block-sections=labels" ] + cflags += [ "-fbasic-block-sections=labels" ] + rustflags += [ "-Cllvm-args=-basic-block-sections=labels" ] + } + if (!is_clang) { # Use pipes for communicating between sub-processes. Faster. # (This flag doesn't do anything with Clang.) diff --git a/src/build/config/compiler/BUILD.gn b/src/build/config/compiler/BUILD.gn index e42d2006c..919054d9d 100644 --- a/src/build/config/compiler/BUILD.gn +++ b/src/build/config/compiler/BUILD.gn @@ -499,6 +499,12 @@ config("compiler") { ldflags += [ "-fPIC" ] rustflags += [ "-Crelocation-model=pic" ] + if (is_clang && chrome_pgo_phase == 2) { + asmflags += [ "-fbasic-block-sections=labels" ] + cflags += [ "-fbasic-block-sections=labels" ] + rustflags += [ "-Cllvm-args=-basic-block-sections=labels" ] + } + if (!is_clang) { # Use pipes for communicating between sub-processes. Faster. # (This flag doesn't do anything with Clang.) diff --git a/src/media/filters/ffmpeg_glue.cc b/src/media/filters/ffmpeg_glue.cc new file mode 100644 index 000000000..9a56b4e1c --- /dev/null +++ b/src/media/filters/ffmpeg_glue.cc @@ -0,0 +1,187 @@ +// Copyright 2023 The Chromium Authors, Alex313031, and RobRich999 +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/filters/ffmpeg_glue.h" + +#include "base/check_op.h" +#include "base/metrics/histogram_functions.h" +#include "base/notreached.h" +#include "base/types/cxx23_to_underlying.h" +#include "media/base/container_names.h" +#include "media/ffmpeg/ffmpeg_common.h" + +namespace media { + +// Internal buffer size used by AVIO for reading. +// TODO(dalecurtis): Experiment with this buffer size and measure impact on +// performance. Currently we want to use 32kb to preserve existing behavior +// with the previous URLProtocol based approach. +enum { kBufferSize = 32 * 1024 }; + +static int AVIOReadOperation(void* opaque, uint8_t* buf, int buf_size) { + return reinterpret_cast(opaque)->Read(buf_size, buf); +} + +static int64_t AVIOSeekOperation(void* opaque, int64_t offset, int whence) { + FFmpegURLProtocol* protocol = reinterpret_cast(opaque); + int64_t new_offset = AVERROR(EIO); + switch (whence) { + case SEEK_SET: + if (protocol->SetPosition(offset)) + protocol->GetPosition(&new_offset); + break; + + case SEEK_CUR: + int64_t pos; + if (!protocol->GetPosition(&pos)) + break; + if (protocol->SetPosition(pos + offset)) + protocol->GetPosition(&new_offset); + break; + + case SEEK_END: + int64_t size; + if (!protocol->GetSize(&size)) + break; + if (protocol->SetPosition(size + offset)) + protocol->GetPosition(&new_offset); + break; + + case AVSEEK_SIZE: + protocol->GetSize(&new_offset); + break; + + default: + NOTREACHED(); + } + return new_offset; +} + +static void LogContainer(bool is_local_file, + container_names::MediaContainerName container) { + base::UmaHistogramSparse("Media.DetectedContainer", + base::to_underlying(container)); + if (is_local_file) { + base::UmaHistogramSparse("Media.DetectedContainer.Local", + base::to_underlying(container)); + } +} + +FFmpegGlue::FFmpegGlue(FFmpegURLProtocol* protocol) { + // Initialize an AVIOContext using our custom read and seek operations. Don't + // keep pointers to the buffer since FFmpeg may reallocate it on the fly. It + // will be cleaned up + format_context_ = avformat_alloc_context(); + avio_context_.reset(avio_alloc_context( + static_cast(av_malloc(kBufferSize)), kBufferSize, 0, + protocol, &AVIOReadOperation, nullptr, &AVIOSeekOperation)); + + // Ensure FFmpeg only tries to seek on resources we know to be seekable. + avio_context_->seekable = + protocol->IsStreaming() ? 0 : AVIO_SEEKABLE_NORMAL; + + // Ensure writing is disabled. + avio_context_->write_flag = 0; + + // Tell the format context about our custom IO context. avformat_open_input() + // will set the AVFMT_FLAG_CUSTOM_IO flag for us, but do so here to ensure an + // early error state doesn't cause FFmpeg to free our resources in error. + format_context_->flags |= AVFMT_FLAG_CUSTOM_IO; + + // Enable fast, but inaccurate seeks for MP3. + format_context_->flags |= AVFMT_FLAG_FAST_SEEK; + + // Ensures format parsing errors will bail out. From an audit on 11/2017, all + // instances were real failures. Solves bugs like http://crbug.com/710791. + format_context_->error_recognition |= AV_EF_EXPLODE; + + format_context_->pb = avio_context_.get(); +} + +bool FFmpegGlue::OpenContext(bool is_local_file) { + DCHECK(!open_called_) << "OpenContext() shouldn't be called twice."; + + // If avformat_open_input() is called we have to take a slightly different + // destruction path to avoid double frees. + open_called_ = true; + + // By passing nullptr for the filename (second parameter) we are telling + // FFmpeg to use the AVIO context we setup from the AVFormatContext structure. + const int ret = + avformat_open_input(&format_context_, nullptr, nullptr, nullptr); + + // If FFmpeg can't identify the file, read the first 8k and attempt to guess + // at the container type ourselves. This way we can track emergent formats. + // Only try on AVERROR_INVALIDDATA to avoid running after I/O errors. + if (ret == AVERROR_INVALIDDATA) { + std::vector buffer(8192); + + const int64_t pos = AVIOSeekOperation(avio_context_->opaque, 0, SEEK_SET); + if (pos < 0) + return false; + + const int num_read = + AVIOReadOperation(avio_context_->opaque, buffer.data(), buffer.size()); + if (num_read < container_names::kMinimumContainerSize) + return false; + + container_ = container_names::DetermineContainer(buffer.data(), num_read); + LogContainer(is_local_file, container_); + + detected_hls_ = + container_ == container_names::MediaContainerName::kContainerHLS; + return false; + } else if (ret < 0) { + return false; + } + + // Rely on ffmpeg's parsing if we're able to succesfully open the file. + if (strcmp(format_context_->iformat->name, "mov,mp4,m4a,3gp,3g2,mj2") == 0) + container_ = container_names::MediaContainerName::kContainerMOV; + else if (strcmp(format_context_->iformat->name, "flac") == 0) + container_ = container_names::MediaContainerName::kContainerFLAC; + else if (strcmp(format_context_->iformat->name, "matroska,webm") == 0) + container_ = container_names::MediaContainerName::kContainerWEBM; + else if (strcmp(format_context_->iformat->name, "ogg") == 0) + container_ = container_names::MediaContainerName::kContainerOgg; + else if (strcmp(format_context_->iformat->name, "wav") == 0) + container_ = container_names::MediaContainerName::kContainerWAV; + else if (strcmp(format_context_->iformat->name, "aac") == 0) + container_ = container_names::MediaContainerName::kContainerAAC; + else if (strcmp(format_context_->iformat->name, "mp3") == 0) + container_ = container_names::MediaContainerName::kContainerMP3; + else if (strcmp(format_context_->iformat->name, "amr") == 0) + container_ = container_names::MediaContainerName::kContainerAMR; + else if (strcmp(format_context_->iformat->name, "avi") == 0) + container_ = container_names::MediaContainerName::kContainerAVI; + + // For a successfully opened file, we will get a container we've compiled in. + CHECK_NE(container_, container_names::MediaContainerName::kContainerUnknown); + LogContainer(is_local_file, container_); + + return true; +} + +FFmpegGlue::~FFmpegGlue() { + // In the event of avformat_open_input() failure, FFmpeg may sometimes free + // our AVFormatContext behind the scenes, but leave the buffer alive. It will + // helpfully set |format_context_| to nullptr in this case. + if (!format_context_) { + av_free(avio_context_->buffer); + return; + } + + // If avformat_open_input() hasn't been called, we should simply free the + // AVFormatContext and buffer instead of using avformat_close_input(). + if (!open_called_) { + avformat_free_context(format_context_); + av_free(avio_context_->buffer); + return; + } + + avformat_close_input(&format_context_); + av_free(avio_context_->buffer); +} + +} // namespace media diff --git a/src/media/filters/ffmpeg_video_decoder.cc b/src/media/filters/ffmpeg_video_decoder.cc index 89924776e..5a7c876ed 100644 --- a/src/media/filters/ffmpeg_video_decoder.cc +++ b/src/media/filters/ffmpeg_video_decoder.cc @@ -1,4 +1,4 @@ -// Copyright 2023 The Chromium Authors and Alex313031 +// Copyright 2023 The Chromium Authors, Alex313031, and RobRich999 // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.