Personal notes. Measured on one Blackwell-class NVENC GPU feeding HEVC into fragmented MP4 for browser playback. Not tried across every Blackwell SKU, driver, or ffmpeg version, and one part of the causal chain below was never isolated cleanly (marked where). Treat this as a well-supported observation plus a low-risk fix, not gospel. No warranty, your mileage may vary, corrections welcome.

At 10,000 feet

Setting: a video pipeline that encodes live HEVC (H.265) video on an NVIDIA Blackwell-generation GPU’s hardware encoder (NVENC) and serves it to web browsers as fragmented MP4. Browsers play this kind of stream through Media Source Extensions (MSE), which binds playback to a single codec configuration.

Problem: browser playback would intermittently freeze, and the trail led to the codec configuration bytes themselves.

What this note establishes: every time the encoder process restarts, it emits different HEVC decoder-configuration bytes (the hvcC record) even though nothing about the encoder settings changed. Measured across thousands of segments: 5-16 distinct configurations per stream. I could not find this behavior reported publicly anywhere.

Takeaway: mux browser-bound HEVC with -tag:v hvc1 (at the MP4 muxing stage), which pins the parameter sets out-of-band as Apple’s HLS spec already requires. It is low-risk and spec-correct even though the causal link between the byte drift and the freezes is not proven (details below).

The finding

A Blackwell-generation NVENC encoder emits non-deterministic hvcC / HEVC parameter-set bytes across encoder restarts. Same GPU, same encoder flags, but each time the encoder process comes back up the HEVC decoder configuration record in the MP4 sample description carries different bytes. I could not find this reported anywhere, so the byte-level evidence is the point of this note.

The drift, by the numbers

Scanning recorded HEVC segments and hashing the hvcC box body (the HEVC decoder configuration record in the MP4 sample description) yielded multiple distinct values per stream, even though the encoder flags never changed:

Stream Segments scanned Distinct hvcC values
A 4623 6
B 3167 5
C 1728 5
D 333 12
E 2865 16

A new hvcC value appeared after each encoder restart (process respawn, watchdog kick, pipeline re-init). Each distinct value rewrites VPS / SPS / HRD fields inside the config record.

The codec string flip

The codec string itself shifted generationally when moving from the previous (Turing) GPU to Blackwell, and the compatibility flags flipped with it:

  • Turing emitted hev1.1.2.L150.90
  • Blackwell emitted hev1.1.6.L150.90

The general_profile_compatibility_flags byte changed from 0x40 to 0x60 between generations. That particular change is a fixed generational difference, not the per-restart drift, but it is the same class of surprise: the bytes a browser decoder keys off of are not what you assumed they were, and they move both across GPU generations (the 0x40 -> 0x60 flip, hev1.1.2 -> hev1.1.6) and across restarts of a single Blackwell encoder (the table above).

Why this matters for browsers (standard background)

Short version of decade-old, canonical Apple-HLS knowledge, included only so the byte drift has context: HEVC parameter sets (VPS/SPS/PPS) can live either in-band (inside media samples, allowed to change over the stream: the hev1 sample-entry tag many muxers pick by default) or out-of-band only (in the hvcC sample description, must not change within the track: the hvc1 tag). Media Source Extensions binds a SourceBuffer to a single decoder configuration, and Apple’s HLS authoring spec requires hvc1 for exactly this reason. The well-known fix for HEVC-in-browser trouble is to mux with -tag:v hvc1 so parameter sets are pinned out of band. None of that is a discovery; it is why the parameter-set bytes above are worth caring about at all. One implementation nuance worth stating: -tag:v hvc1 only takes effect at the MP4 muxing stage (it is an MP4 sample-entry property and a no-op on TS/elementary streams), so in a pipeline that encodes to TS then remuxes to MP4 with -c copy, the tag belongs on the remux stage.

Honesty: what is established and what is not

  • “No public report” is the only novelty claim, and it is weaker than “first.” What I have established is the absence of a public report of Blackwell NVENC drifting hvcC across restarts, not that this is genuinely the first occurrence. Someone may have hit it and never written it up.
  • The drift itself is verified; its effect on playback is not. The hvcC drift is real and measurable (the table). Whether it causes browser MSE freezes is correlation with a plausible mechanism, not proven causation. After applying hvc1 the freezes I was chasing stopped, which is equally consistent with (a) hvc1 genuinely fixing it, (b) hvc1 merely making MSE more tolerant while the drift continues underneath, or (c) coincidence, since right after the change the encoder had not yet accumulated many restarts so recent segments happened to share one hvcC.
  • The mechanism is even debatable. A properly authored out-of-band hvc1 configuration arguably should not be sensitive to in-band SPS drift at all, so it is not obvious the parameter drift is what breaks MSE in the first place. That tension is unresolved here and is a reason to hold the causal story loosely.

hvc1 is spec-required and low-risk regardless, so it remains the correct first move even though the causal chain is unproven. Verification after applying it: codec_tag_string=hvc1 on fresh segments, and an MP4 container check (MP4Box-style, the same class of parser Chrome uses) passed. If freezes return after the encoder accumulates restarts over days, the drift itself is still there to address.

If hvc1 alone is not enough (fallback)

The deeper fix (not deployed here, therefore unverified) is to clamp the parameter-set fields at the bitstream level so the encoder cannot emit varying VPS/SPS/HRD values in the first place. The candidate is the hevc_metadata bitstream filter to normalize every VUI/HRD field to fixed values before muxing. That is the next step if an hvc1-tagged stream still drifts across restarts.

References

  • ISO/IEC 14496-15 (HEVC in ISO base media file format): hvc1 vs hev1 sample entries and where parameter sets may live
  • Apple HLS Authoring Specification (requires hvc1 for HEVC)
  • W3C Media Source Extensions (SourceBuffer codec configuration constraints)
  • ffmpeg -tag:v muxer option; hevc_metadata bitstream filter

Licensed under the site footer’s CC BY 4.0. If this saved you a debugging session, the optional thanks link in the footer is appreciated, no obligation.