Skip to content

Commit

Permalink
H265NalUnitFragment: Mask nuhTempIdPlus1 correctly
Browse files Browse the repository at this point in the history
Previously, `H265NalUnitFragment::fragmentsFrom()` was masking the value
of nuhTempIdPlus1 against the value 0xE (0b1110) which was corrupting
the generated NALU fragments. This commit updates the `fragmentsFrom()`
method to mask against the value 0x7 (0b111) instead. However, it looks
like the masking in this method is redundant with the equivalent masking
that is done by `H265NalUnitHeader`'s setters.

According to [RFC 7798](https://datatracker.ietf.org/doc/html/rfc7798#section-1.1.4):

    1.1.4.  NAL Unit Header

       HEVC maintains the NAL unit concept of H.264 with modifications.
       HEVC uses a two-byte NAL unit header, as shown in Figure 1.  The
       payload of a NAL unit refers to the NAL unit excluding the NAL unit
       header.

                +---------------+---------------+
                |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
                +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
                |F|   Type    |  LayerId  | TID |
                +-------------+-----------------+

       Figure 1: The Structure of the HEVC NAL Unit Header

    [...]

       TID: 3 bits
          nuh_temporal_id_plus1.  This field specifies the temporal
          identifier of the NAL unit plus 1.  The value of TemporalId is
          equal to TID minus 1.  A TID value of 0 is illegal to ensure that
          there is at least one bit in the NAL unit header equal to 1, so to
          enable independent considerations of start code emulations in the
          NAL unit header and in the NAL unit payload data.

The minimum value of the "TID" field is 1, because it will have 1
subtracted from it to recover the original HEVC "TemporalId" value.

Without this commit, the RTP fragments being generated by
libdatachannel's `H265RtpPacketizer` were being rejected by this
consistency check in libavformat:

https://github.com/FFmpeg/FFmpeg/blob/release/6.1/libavformat/rtpdec_hevc.c#L219-L223

With this commit, I can successfully relay HEVC video from ffmpeg
through a libdatachannel program (based on the media-sender and
media-receiver examples) and play it with ffplay.
  • Loading branch information
edmonds committed Dec 18, 2023
1 parent a1078c5 commit 93a3fb9
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion src/h265nalunit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ H265NalUnitFragment::fragmentsFrom(shared_ptr<H265NalUnit> nalu, uint16_t maximu
maximumFragmentSize -= (H265_NAL_HEADER_SIZE + H265_FU_HEADER_SIZE);
auto f = nalu->forbiddenBit();
uint8_t nuhLayerId = nalu->nuhLayerId() & 0x3F; // 6 bits
uint8_t nuhTempIdPlus1 = nalu->nuhTempIdPlus1() & 0xE; // 3 bits
uint8_t nuhTempIdPlus1 = nalu->nuhTempIdPlus1() & 0x7; // 3 bits
uint8_t naluType = nalu->unitType() & 0x3F; // 6 bits
auto payload = nalu->payload();
vector<shared_ptr<H265NalUnitFragment>> result{};
Expand Down

0 comments on commit 93a3fb9

Please sign in to comment.