Skip to content

S and E combination error #14

@chivstyle

Description

@chivstyle

Please see the comment below for detail.

int SmolRTSP_NalTransport_send_packet(
    SmolRTSP_NalTransport *self, SmolRTSP_RtpTimestamp ts,
    SmolRTSP_NalUnit nalu) {
    assert(self);

    const size_t max_packet_size = MATCHES(nalu.header, SmolRTSP_NalHeader_H264)
                                       ? self->config.max_h264_nalu_size
                                       : self->config.max_h265_nalu_size,
                 nalu_size =
                     SmolRTSP_NalHeader_size(nalu.header) + nalu.payload.len;

    if (nalu_size < max_packet_size) {
        const bool marker =
            SmolRTSP_NalHeader_is_coded_slice_idr(nalu.header) ||
            SmolRTSP_NalHeader_is_coded_slice_non_idr(nalu.header);

        const size_t header_buf_size = SmolRTSP_NalHeader_size(nalu.header);
        uint8_t *header_buf = alloca(header_buf_size);
        SmolRTSP_NalHeader_serialize(nalu.header, header_buf);

        return SmolRTSP_RtpTransport_send_packet(
            self->transport, ts, marker,
            U8Slice99_new(header_buf, header_buf_size), nalu.payload);
    }
    // send fragmentized nal data ? Not absolutely.
    return send_fragmentized_nal_data(
        self->transport, ts, max_packet_size, nalu);
}

// See <https://tools.ietf.org/html/rfc6184#section-5.8> (H.264),
// <https://tools.ietf.org/html/rfc7798#section-4.4.3> (H.265).
static int send_fragmentized_nal_data(
    SmolRTSP_RtpTransport *t, SmolRTSP_RtpTimestamp ts, size_t max_packet_size,
    SmolRTSP_NalUnit nalu) {
    // define ENABLE_BUGFIX_S_AND_E  to apply bugfix.
#ifdef ENABLE_BUGFIX_S_AND_E
    if (nalu.payload.len <= max_packet_size) {
        max_packet_size >>= 1;
    }
#endif
    const size_t rem = nalu.payload.len % max_packet_size,
                 packets_count = (nalu.payload.len - rem) / max_packet_size;

    // max_packet_size == sizeof(header) + sizeof(nalu), but the loop below ingores the header size, it only split the nalu.
    // it means that nalu.play.len may be less than max_packet_size,  it tell us that it's the first fragment and it's also the last fragment,
    // the FU header contains S and E bit simultaneously. It's a bug, right ?

    for (size_t packet_idx = 0; packet_idx < packets_count; packet_idx++) {
        const bool is_first_fragment = 0 == packet_idx,
                   is_last_fragment =
                       0 == rem && (packets_count - 1 == packet_idx);

        const U8Slice99 fu_data = U8Slice99_sub(
            nalu.payload, packet_idx * max_packet_size,
            is_last_fragment ? nalu.payload.len
                             : (packet_idx + 1) * max_packet_size);
        const SmolRTSP_NalUnit fu = {nalu.header, fu_data};

        if (send_fu(t, ts, fu, is_first_fragment, is_last_fragment) == -1) {
            return -1;
        }
    }

    if (rem != 0) {
        const U8Slice99 fu_data =
            U8Slice99_advance(nalu.payload, packets_count * max_packet_size);
        const SmolRTSP_NalUnit fu = {nalu.header, fu_data};
        const bool is_first_fragment = 0 == packets_count,
                   is_last_fragment = true;

        if (send_fu(t, ts, fu, is_first_fragment, is_last_fragment) == -1) {
            return -1;
        }
    }

    return 0;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions