ultravideo / uvgRTP

An open-source library for RTP/SRTP media delivery
BSD 2-Clause "Simplified" License
318 stars 90 forks source link

H26x incorrectly detected start code if preceded by 0x1 #212

Closed festlv closed 8 months ago

festlv commented 8 months ago

While testing with real h264 data encoded by ffmpeg I noticed the following error:

[uvgRTP][ERROR][::enqueue_message] Tried to enqueue invalid message
[uvgRTP][ERROR][::single_nal_unit] Failed to enqueue single h26x NAL Unit packet!

I traced the issue to start code lookup returning incorrect offset for certain data (particularly, if the byte right before start code is 0x1, but it only happens with particular alignment).

The following test case can be used to reproduce the issue:

TEST(FormatTests, h264_scl_01_before_sc) {
    uvgrtp::context ctx;
    uvgrtp::session* local_session = ctx.create_session("127.0.0.1");
    std::shared_ptr<uvgrtp::rtp>    rtp_;
    auto socket_ = std::shared_ptr<uvgrtp::socket>(new uvgrtp::socket(0));
    auto format_26x = uvgrtp::formats::h264(socket_, rtp_, 0);

    for (int offset = 0; offset < 16; offset++) {
        uint8_t data[DATA_SIZE];
        memset(data, DATA_VALUE, DATA_SIZE);

        if (offset > 0)
            data[offset - 1] = 1;

        data[offset] = 0;
        data[offset + 1] = 0;
        data[offset + 2] = 1;

        std::cout << "Testing h264 SCL offset " << offset << std::endl;
        uint8_t start_len;
        size_t out = format_26x.find_h26x_start_code(data, 128 - offset, 0, start_len);

        EXPECT_EQ(3 + offset, (int)out);
        EXPECT_EQ(3, start_len);
    }
}

This test succeeds for offset 0 (obviously, since there is no preceding byte), 1, 8, 9 but fails for other offset values.

jrsnen commented 8 months ago

Fixed by 73018e2bdfed2b753c8dbeea48dba8c5962785b0