fegauthier-paragonandClaude Opus 4.6 6bb1b650b3 Enable HEVC/H.265 software video decoding on Linux (#34796)
* Enable HEVC/H.265 software video decoding on Linux

Adds FFmpeg-based HEVC/H.265 software decoding support for Linux,
providing a fallback when hardware decode is unavailable (e.g., NVIDIA
GPUs where VA-API is not functional in Chromium).

- chromium_src override for supported_types.cc (HEVC as built-in codec)
- brave/third_party/ffmpeg/sources.gni with HEVC source lists,
  imported via ffmpeg_generated.gni patch
- Minimal patches for ffmpeg_common.cc and ffmpeg_video_decoder.cc
  (anonymous namespace / file-local functions, not overridable)
- All HEVC code paths gated on BUILDFLAG(ENABLE_PLATFORM_HEVC) to
  allow disabling via build args
- FFmpeg config patches for Linux x64 (config.h, config_components.h,
  codec_list.c, parser_list.c, autorename wrappers)
- Enable enable_platform_hevc and enable_hevc_parser_and_hw_decoder
- Add ffmpeg to patch apply/update infrastructure with s.path guard

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Address review: advertise HEVC support to web content on Linux

On Linux, upstream's IsDecoderHevcProfileSupported takes the
PLATFORM_HAS_OPTIONAL_HEVC_DECODE_SUPPORT path and consults the
supplemental profile cache, which is populated only by hardware
decoders registering via the GPU mojo interface. Since we ship a
bundled FFmpeg software decoder that never touches that cache,
MediaSource.isTypeSupported('video/mp4;codecs="hev1.1.6.L93.B0"')
returned false even though the decoder could handle the stream.

Override IsDefaultDecoderSupportedVideoType so that when upstream
rejects HEVC for that reason alone (cache empty), we fall back to
returning true. HDR, color space, and proprietary-codec gating from
upstream are preserved.

* Address review: round-trip new-file patches through apply/update_patches

Two related issues with how brave's patch tooling handles patches that
create new files (new file mode diffs):

apply_patches would fail on a fresh checkout with "Target file does
not exist" because isPatchStale treats a missing target as SRC_REMOVED
and bails out before apply. Teach it to recognize "new file mode"
patches and re-route through SRC_CHANGED so apply proceeds. Also
unlink any leftover target before apply so re-runs on an existing
checkout don't hit "already exists in working directory".

update_patches would silently delete new-file patches because
getModifiedPaths only inspected tracked/modified files. git apply
creates new files without staging them, so they show up as untracked
(??) and never reach the diff. Extend it to pick up untracked paths
that correspond to an existing patch, and generate their diff via
git diff --no-index /dev/null <path> to match the new-file-mode
format produced by git apply.

The four autorename_*.c.patch files in third_party/ffmpeg now round-
trip cleanly across apply/update cycles, which addresses the
"update_patches currently removes some patches you added here" review
comment.

* Address review: rebase HEVC patches onto Chromium 147 ffmpeg

Refresh patch index hashes to the current third_party/ffmpeg tree,
tighten the ffmpeg_generated.gni patch to avoid an empty line at the
hunk boundary (presubmit warning), and pick up libavcodec/x86/hevc/
dequant.asm, which upstream added since the original patch set and
whose absence caused an ff_hevc_dequant_8_ssse3 link error.

All four autorename_*.c patches, the config/config_components toggles,
the generated-list import, and the BUILD.gn include_dirs tweak now
apply cleanly on Chromium 147 and the resulting build links and plays
HEVC streams end-to-end.

* Address review: host autorename stubs in brave/third_party/ffmpeg

Moves the four HEVC autorename .c stubs from patches/third_party/ffmpeg/
into brave/third_party/ffmpeg/libavcodec/ (and libavcodec/hevc/) so
they're regular brave-owned sources rather than new-file patches against
upstream ffmpeg. This is what goodov suggested in review.

The stubs use fully-qualified includes like "libavcodec/hevc/cabac.c",
which resolve through the existing -I "." on ffmpeg_internal — so the
upstream source is what actually gets compiled, just under a different
object name to keep the linker happy. sources.gni references the new
files with absolute //brave/... paths.

One thing I missed on the first build: libavcodec/cabac.c and
libavcodec/hevc/cabac.c are two different files, and the hevc stub
needs to point at the latter or the linker complains about duplicate
ff_init_cabac_decoder. Fixed before pushing.

Since no new-file patches are left in the PR, the apply/update_patches
tooling changes from c1b2b937cf9 don't have a reason to be here anymore.
Reverted them — gitPatcher.js and updatePatches.js are back to where
they were before this PR.

Tested locally on Linux x64 component build: apply_patches and
update_patches round-trip cleanly, gn_check passes, ffmpeg and media
targets both build, and HEVC playback still works end to end.

* Address review: centralize HEVC enabled check via FFmpegSupportsHEVC helper

Introduces FFmpegSupportsHEVC() and HEVCAsH264IfFFmpegSupportsHEVC() in
chromium_src/media/base/supported_types.{h,cc}. The helpers wrap the
BUILDFLAG(IS_LINUX) && BUILDFLAG(ENABLE_PLATFORM_HEVC) check in one
place so callers don't have to repeat it.

Most of this is shrinking the existing patches:

- patches/media-filters-ffmpeg_video_decoder.cc.patch: drops the nested
  #if BUILDFLAG blocks around the kHEVC switch case and IsCodecSupported.
  The switch now reads `HEVCAsH264IfFFmpegSupportsHEVC(config.codec())`
  so kHEVC reuses the kH264 threading branch, and IsCodecSupported maps
  the incoming codec the same way before its kH264 comparison.
- patches/media-ffmpeg-ffmpeg_common.cc.patch: one-line
  `if (FFmpegSupportsHEVC()) return "h264,hevc";` instead of a
  C-preprocessor branch.
- chromium_src/media/base/supported_types.cc: IsDecoderBuiltInVideoCodec,
  IsDefaultDecoderSupportedVideoType and IsDecoderSupportedVideoType all
  go through FFmpegSupportsHEVC() now. The third one matters: blink
  (webcodecs, media_capabilities) calls the public
  IsDecoderSupportedVideoType, and the upstream definition calls
  IsDefaultDecoderSupportedVideoType internally — which under our
  #define rebrand routes to _ChromiumImpl and bypasses our override.
  Overriding the public entry point too keeps the helper authoritative
  whichever path the caller takes.

The override file now includes media/base/supported_types.h *before*
the rebrand #defines and forward-declares the *_ChromiumImpl variants.
That way the MEDIA_EXPORT declarations of the three Is* functions are
visible with their original names when our override definitions are
compiled, so the symbols get the right visibility without having to
repeat MEDIA_EXPORT on every override body. Verified by checking
`nm -D libmedia.so` — IsDecoderBuiltInVideoCodec,
IsDefaultDecoderSupportedVideoType and IsDecoderSupportedVideoType are
all exported, and media:media_unittests links cleanly.

sources.gni: collapses the two duplicated `is_linux && ffmpeg_branding`
conditions into a single `enable_ffmpeg_hevc_support` flag derived from
the upstream `enable_hevc_parser_and_hw_decoder` build arg. Drops
chromeos / fuchsia from the condition (not relevant for this PR).

Test adjustments for the new HEVC-supported reality on Linux:

- media_unittests: SupportedTypesTest.IsDecoderBuiltInVideoCodec and
  IsDecoderSupportedVideoTypeBasics asserted HEVC=false unconditionally;
  switched to `EXPECT_EQ(..., FFmpegSupportsHEVC())` so they pass on
  Linux with the FFmpeg HEVC decoder built in and stay correct
  everywhere else.
- browser_tests: EncryptedMediaSupportedTypesTest::CheckPlatformHevcSupport
  asserted UNSUPPORTED for HEVC on Linux. With the software decoder
  built in HEVC is supported via Clear Key too, so the assertion now
  flips to EXPECT_ECK_PROPRIETARY when FFmpegSupportsHEVC() is true.
  This fixes EncryptedMediaSupportedTypesClearKeyTest.Video_MP4 and the
  two ExternalClearKey variants (Basic, Video_MP4).

Also renames the four autorename stubs to drop the "autorename_" prefix
and removes the "Auto-generated" wording from their comments — they
aren't produced by a script, they're hand-placed brave sources. The
sources.gni references are updated to match.

Verified on Linux x64 component build with chromium 149: gn_check,
format, presubmit, full brave build, SupportedTypesTest.* (32 tests)
and the four EME browser_tests above all green. HEVC playback + MSE
isTypeSupported confirmed end to end on a Main / Main10 / Level 5 test
clip.

* Address review: enable HEVC software decoder on linux-arm64

Mirrors the linux-x64 enablement on linux-arm64 so HEVC isn't a
brave-on-x64-only feature.

ffmpeg config patches: four new patches under chromium/config/Chrome/
linux/arm64/, symmetric to the existing x64 ones — flip CONFIG_BSWAPDSP,
CONFIG_HEVC_DECODER and CONFIG_HEVC_PARSER to 1, and add ff_hevc_decoder
/ ff_hevc_parser to codec_list.c / parser_list.c.

sources.gni: new `if (enable_ffmpeg_hevc_support && current_cpu ==
"arm64")` block pulling in the libavcodec/aarch64 HEVC NEON files that
upstream's Makefile lists for CONFIG_HEVC_DECODER (hevcdsp_init,
hevcdsp_{deblock,dequant,idct}_neon and h26x/{epel,qpel,sao}_neon).
Also introduce a `brave_third_party_ffmpeg_gas_sources` list — arm64
hand-written assembly goes through ffmpeg_gas_sources upstream rather
than ffmpeg_asm_sources (which is nasm-only). The ffmpeg_generated.gni
patch is extended to append it.

Verified: gn_check, format, presubmit all green. autoninja
third_party/ffmpeg:ffmpeg in a cross-compiled Component_arm64 build dir
links cleanly. Couldn't get a full media:media_unittests build past
unrelated clang segfaults on V8 torque-generated sources locally, but
that's host-side flake — the brave CI arm64 builders should hit a clean
environment.

Don't have arm64 hardware to runtime-verify; relying on CI for that.

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-05 01:20:22 -07:00
2026-04-09 13:18:38 -07:00
2026-04-21 10:07:34 +01:00
2026-06-05 00:03:34 +00:00
2026-06-05 00:03:34 +00:00
2026-05-22 16:57:46 -04:00
2026-06-01 16:00:04 +01:00
2026-03-23 09:27:39 -07:00
2026-06-05 00:03:34 +00:00

Brave Browser

Brave Core

Brave Core is a set of changes, APIs, and scripts used for customizing Chromium to make the Brave browser. Please also check https://github.com/brave/brave-browser which only holds the issues, releases and the wiki.

Overview

This repository holds the build tools needed to build the Brave desktop browser for all platforms. In particular, it fetches and syncs code from the projects defined in package.json and src/brave/DEPS:

Resources

Downloads

You can visit our website to get the latest stable release.

Contributing

Please see the contributing guidelines.

Our Wiki also has some useful technical information, especially about setting the development environment.

Security Policy

Please see the security policy.

Community

Join the Q&A community if you'd like to get more involved with Brave. You can ask for help, discuss features you'd like to see, and a lot more. We'd love to have your help so that we can continue improving Brave.

You can also ask questions and interact in the community-guest channel on Brave Software's Slack.

Help us translate Brave to your language by submitting translations at https://explore.transifex.com/brave/brave_en/.

Follow @brave on X for important news and announcements.

Install prerequisites

Follow the instructions for your platform:

Clone and initialize

Once you have the prerequisites installed, you can get the code and initialize the build environment.

git clone git@github.com:brave/brave-core.git path-to-your-project-folder/src/brave
cd path-to-your-project-folder/src/brave
npm install

# the Chromium source is downloaded, which has a large history (gigabytes of data)
# this might take really long to finish depending on internet speed

npm run init

brave-core based android builds should use npm run init -- --target_os=android --target_arch=arm (or whichever CPU type you want to build for) brave-core based iOS builds should use npm run init -- --target_os=ios

You can also set the target_os and target_arch for init and build using:

npm config set target_os android
npm config set target_arch arm

Additional config needed to build are documented at https://github.com/brave/brave-browser/wiki/Build-configuration

Internal developers can find more information at https://github.com/brave/internal/wiki/Build-configuration

Build Brave

The default build type is component.

# start the component build compile
npm run build

To do a release build:

# start the release compile
npm run build Release

brave-core based android builds should use npm run build -- --target_os=android --target_arch=arm or set the npm config variables as specified above for init

brave-core based iOS builds should use the Xcode project found in ios/brave-ios/App. You can open this project directly or run npm run ios_bootstrap -- --open_xcodeproj to have it opened in Xcode. See the iOS Developer Environment for more information on iOS builds.

Build Configurations

Running a release build with npm run build Release can be very slow and use a lot of RAM, especially on Linux with the Gold LLVM plugin.

To run a statically linked build (takes longer to build, but starts faster):

npm run build -- Static

To run a debug build (Component build with is_debug=true):

npm run build -- Debug

NOTE: the build will take a while to complete. Depending on your processor and memory, it could potentially take a few hours.

Run Brave

To start the build:

npm start [Release|Component|Static|Debug]

Update Brave

npm run sync -- [--force] [--init] [--create] [brave_core_ref]

This will attempt to stash your local changes in brave-core, but it's safer to commit local changes before running this

npm run sync will (depending on the below flags):

  1. 📥 Update sub-projects (chromium, brave-core) to latest commit of a git ref (e.g. tag or branch)
  2. 🤕 Apply patches
  3. 🔄 Update gclient DEPS dependencies
  4. Run hooks (e.g. to perform npm install on child projects)
flag Description
[no flags] updates chromium if needed and re-applies patches. If the chromium version did not change, it will only re-apply patches that have changed. Will update child dependencies only if any project needed updating during this script run.
**Use this if you want the script to manage keeping you up to date instead of pulling or switching branches manually. **
--force updates both Chromium and brave-core to the latest remote commit for the current brave-core branch and the Chromium ref specified in brave-core/package.json (e.g. master or 74.0.0.103). Will re-apply all patches. Will force update all child dependencies.
**Use this if you're having trouble and want to force the branches back to a known state. **
--init force update both Chromium and brave-core to the versions specified in brave-core/package.json and force updates all dependent repos - same as npm run init
--sync_chromium (true/false) Will force or skip the chromium version update when applicable. Useful if you want to avoid a minor update when not ready for the larger build time a chromium update may result in. A warning will be output about the current code state expecting a different chromium version. Your build may fail as a result.
-D, --delete_unused_deps Will delete from the working copy any dependencies that have been removed since the last sync. Mimics gclient sync -D.

Run npm run sync brave_core_ref to checkout the specified brave-core ref and update all dependent repos including chromium if needed.

Scenarios

Create a new branch:

> cd src/brave
src/brave> git checkout -b branch_name

Checkout an existing branch or tag:

src/brave> git fetch origin
src/brave> git checkout [-b] branch_name
src/brave> npm run sync
...Updating 2 patches...
...Updating child dependencies...
...Running hooks...

Update the current branch to the latest remote:

src/brave> git pull
src/brave> npm run sync
...Updating 2 patches...
...Updating child dependencies...
...Running hooks...

Reset to latest brave-core master (via init, will always result in a longer build and will remove any pending changes in your brave-core working directory):

src/brave> git checkout master
src/brave> git pull
src/brave> npm run sync -- --init

When you know that DEPS didn't change, but .patch files did (quickest attempt to perform a mini-sync before a build):

src/brave> git checkout featureB
src/brave> git pull
src/brave> npm run apply_patches
...Applying 2 patches...

Enabling third-party APIs

  1. Google Safe Browsing: Get an API key with SafeBrowsing API enabled from https://console.developers.google.com/. Update the GOOGLE_API_KEY environment variable with your key as per https://www.chromium.org/developers/how-tos/api-keys to enable Google SafeBrowsing.

Development

Troubleshooting

See Troubleshooting for solutions to common problems.

S
Description
No description provided
Readme MPL-2.0
3.8 GiB
Languages
C++ 36.9%
HTML 31.6%
Swift 9.4%
TypeScript 9%
Java 4.8%
Other 8.1%