Skip to content

H.265: reassembled FU NAL units get the FU header as the second NAL header byte #43

Closed

Description

@compot-dev

Found by the new unit tests (#34).

NalAssembler.assemble() handles the start fragment of an H.265 FU (type 49) like this:

nalBuffer[nalSize++] = (byte)((rx[cp] & 0x81) | ((rx[cp + 2] & 0x7F) << 1));
int donlField = (rx[cp + 1] & 0x80) >> 7;
cp += donlField != 0 ? 3 : 2;

The code writes only the first byte of the 2-byte H.265 NAL header. After cp += 2, copying starts at the FU header, so the FU header becomes the second NAL header byte.

Example: IDR_W_RADL with payload header 62 01 and FU header 93. The result is 00 00 00 01 26 93 ... instead of 00 00 00 01 26 01 .... Decoded, 0x93 means nuh_layer_id = 18 and TemporalId = 2.

Effects:

  • H.265 says a single-layer decoder ignores NAL units with nuh_layer_id > 0. Fragmented NAL units, which in practice means every IDR and most P frames, can therefore be dropped by a conforming decoder, leaving a black picture. Decoders that do not check the layer id play the stream.
  • The "DONL" check reads a layer-id bit, not a DONL flag. DONL is only present when the SDP has sprop-max-don-diff > 0.
  • (fu & 0x7F) << 1 also shifts the E bit into the F bit; it should be & 0x3F.

The basic branch writes 0x01 as the second byte, which is close to correct.

Fix: copy the second byte of the payload header (rx[cp + 1]), mask the type with 0x3F, and skip 3 bytes (payload header + FU header).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions