Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

referenceTime calculation error in FeedbackRtpTransport.cpp #874

Closed
bianxg opened this issue Jul 22, 2022 · 14 comments
Closed

referenceTime calculation error in FeedbackRtpTransport.cpp #874

bianxg opened this issue Jul 22, 2022 · 14 comments
Labels

Comments

@bianxg
Copy link

bianxg commented Jul 22, 2022

this->referenceTime = static_cast<int32_t>((timestamp & 0x1FFFFFC0) / 64);
should be (referenceTime is 3 byte long)
this->referenceTime = static_cast<int32_t>((timestamp & 0x3FFFFFC0) / 64);

for example
timestamp = 763974970
BIN 00101101100010010101010100111010
0x1FFFFFC0 is 00011111111111111111111111000000

from webrtc source
constexpr int kBaseScaleFactor = 64;
constexpr int64_t kTimeWrapPeriod = (1ll << 24) * kBaseScaleFactor;
this->referenceTime = static_cast<int32_t>((timestamp % kTimeWrapPeriod)/64);

@bianxg bianxg added the bug label Jul 22, 2022
@ibc
Copy link
Member

ibc commented Jul 22, 2022

CC @jmillan

@jmillan
Copy link
Member

jmillan commented Jul 22, 2022

It's definitely odd.

I wonder why we set that mask. Being a 3 byte field it should be 0x00FFFFFF indeed.

What's the reason behind 0x3FFFFFC0, @bianxg ?

@jmillan
Copy link
Member

jmillan commented Jul 22, 2022

Indeed we need it to be a 23bit field, so the mask should be: 0x7FFFFF00

@jmillan
Copy link
Member

jmillan commented Jul 22, 2022

There is indeed discussion/explanation about this here meetecho/janus-gateway#1733 (comment) @ibc , but I don't see why we set that mask.

@jmillan
Copy link
Member

jmillan commented Jul 22, 2022

I'm checking it.

@ibc
Copy link
Member

ibc commented Jul 22, 2022

Honestly I don't think I can give better rationale than the one given in that comment when it was fresh in my mind, but AFAIS I provide there even with code to demonstrate things.

@jmillan
Copy link
Member

jmillan commented Jul 22, 2022

Got it:

0x1FFFFFC0 => 536870848 => 11111111111111111111111000000

Dividing such value by 64:

0x7FFFFF => 8388607 => 00000000011111111111111111111111

So by adding 0x1FFFFFC0 mask we make sure that after dividing the value by 64, the resulting number will fit in 23 bits.

@jmillan
Copy link
Member

jmillan commented Jul 22, 2022

Where do you then see the problem @bianxg ?

@bianxg
Copy link
Author

bianxg commented Jul 23, 2022

from webrtc source code, referenceTime is calculated as below:
constexpr int kBaseScaleFactor = 64;
constexpr int64_t kTimeWrapPeriod = (1ll << 24) * kBaseScaleFactor;
this->referenceTime = static_cast<int32_t>((timestamp % kTimeWrapPeriod)/64);

which is equals to
this->referenceTime = static_cast<int32_t>((timestamp & 0x3FFFFFC0) / 64);
by adding 0x3FFFFFC0 mask after dividing the value by 64, the resulting number will fit in 24 bits.

@kingpeter2015
Copy link

I wrote one test:

auto calc_mediasoup = [](uint64_t ts){
    return static_cast<int32_t>((ts & 0x1FFFFFC0) / 64);
};

auto calc_mediasoup_modified = [](uint64_t ts){
    return static_cast<int32_t>((ts & 0x3FFFFFC0) / 64);
};

auto calc_webrtc = [](uint64_t ts){
    constexpr int kBaseScaleFactor = 64;
		constexpr int64_t kTimeWrapPeriod = (1ll << 24) * kBaseScaleFactor;
    return static_cast<int32_t>((ts % kTimeWrapPeriod) / 64);
};

for(uint64_t t = 0; t < UINT64_MAX; t++) {
    int32_t ref_mediasoup = calc_mediasoup(t);
    int32_t ref_mediasoup_modified = calc_mediasoup_modified (t);
    int32_t ref_webrtc = calc_webrtc(t);
    if(ref_mediasoup != ref_webrtc ) {
      printf("mediasoup vs webrtc difference: timestamp=%d, mediasoup reference time=%d, webrtc reference time=%d\n", t, ref_mediasoup , ref_webrtc );
    }

    if(ref_mediasoup_modified != ref_webrtc ) {
      printf("mediasoup_modified vs webrtc difference: timestamp=%d, mediasoup reference time=%d, webrtc reference time=%d\n", t, ref_mediasoup_modified , ref_webrtc );
    }
  }  

I found definitely ref_mediasoup != ref_webrtc, whereas ref_mediasoup_modified == ref_webrtc

ref

@jmillan
Copy link
Member

jmillan commented Jul 28, 2022

The difference is that mediasoup does NOT generate negative timestamp values. That's why we use 23 bits to represent it, so the most significant bit (sign) is always 0 and thus represent a positive number.

@jmillan
Copy link
Member

jmillan commented Jul 28, 2022

Anyway, have you seen this is an issue for libwebrtc processing this RTCP packets?

@kingpeter2015
Copy link

@jmillan There are int, int16_t, int32_t, int64_t etc types in C/C++, however, there is no 24-bit signed integer. And using the lowest 24 bits of a uint32_t type to assign and store can ensure reference_time is not negative.

@jmillan
Copy link
Member

jmillan commented Sep 29, 2022

This was handled here #899

@jmillan jmillan closed this as completed Sep 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

4 participants