Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 35d05dcb authored by Chia-chi Yeh's avatar Chia-chi Yeh
Browse files

RTP: support payloads with larger packetization interval.

RFC 3551 section 4.2 said that a receiver should accept packets
representing between 0 and 200ms of audio data. Now we add the
ability to decode multiple frames in a payload as long as the
jitter buffer is not full. This change covers G711, GSM, and
GSM-EFR. AMR will be added later.

Bug: 3029736
Change-Id: Ifd194596766d14f02177925c58432cd620e44dd7
parent 1ed7a407
Loading
Loading
Loading
Loading
+12 −8
Original line number Diff line number Diff line
@@ -52,7 +52,7 @@ public:

    int set(int sampleRate, const char *fmtp);
    int encode(void *payload, int16_t *samples);
    int decode(int16_t *samples, void *payload, int length);
    int decode(int16_t *samples, int count, void *payload, int length);

private:
    void *mEncoder;
@@ -128,7 +128,7 @@ int AmrCodec::encode(void *payload, int16_t *samples)
    return length;
}

int AmrCodec::decode(int16_t *samples, void *payload, int length)
int AmrCodec::decode(int16_t *samples, int count, void *payload, int length)
{
    unsigned char *bytes = (unsigned char *)payload;
    Frame_Type_3GPP type;
@@ -213,7 +213,7 @@ public:
    }

    int encode(void *payload, int16_t *samples);
    int decode(int16_t *samples, void *payload, int length);
    int decode(int16_t *samples, int count, void *payload, int length);

private:
    void *mEncoder;
@@ -239,20 +239,24 @@ int GsmEfrCodec::encode(void *payload, int16_t *samples)
    return -1;
}

int GsmEfrCodec::decode(int16_t *samples, void *payload, int length)
int GsmEfrCodec::decode(int16_t *samples, int count, void *payload, int length)
{
    unsigned char *bytes = (unsigned char *)payload;
    if (length == 31 && (bytes[0] >> 4) == 0x0C) {
    int n = 0;
    while (n + 160 <= count && length >= 31 && (bytes[0] >> 4) == 0x0C) {
        for (int i = 0; i < 30; ++i) {
            bytes[i] = (bytes[i] << 4) | (bytes[i + 1] >> 4);
        }
        bytes[30] <<= 4;

        if (AMRDecode(mDecoder, AMR_122, bytes, samples, MIME_IETF) == 31) {
            return 160;
        if (AMRDecode(mDecoder, AMR_122, bytes, &samples[n], MIME_IETF) != 31) {
            break;
        }
        n += 160;
        length -= 31;
        bytes += 31;
    }
    return -1;
    return n;
}

} // namespace
+1 −1
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ public:
    // Returns the length of payload in bytes.
    virtual int encode(void *payload, int16_t *samples) = 0;
    // Returns the number of decoded samples.
    virtual int decode(int16_t *samples, void *payload, int length) = 0;
    virtual int decode(int16_t *samples, int count, void *payload, int length) = 0;
};

AudioCodec *newAudioCodec(const char *codecName);
+11 −10
Original line number Diff line number Diff line
@@ -395,7 +395,8 @@ void AudioStream::decode(int tick)
        mLatencyTimer = tick;
    }

    if (mBufferTail - mBufferHead > BUFFER_SIZE - mInterval) {
    int count = (BUFFER_SIZE - (mBufferTail - mBufferHead)) * mSampleRate;
    if (count < mSampleCount) {
        // Buffer overflow. Drop the packet.
        LOGV("stream[%d] buffer overflow", mSocket);
        recv(mSocket, &c, 1, MSG_DONTWAIT);
@@ -403,19 +404,18 @@ void AudioStream::decode(int tick)
    }

    // Receive the packet and decode it.
    int16_t samples[mSampleCount];
    int length = 0;
    int16_t samples[count];
    if (!mCodec) {
        // Special case for device stream.
        length = recv(mSocket, samples, sizeof(samples),
        count = recv(mSocket, samples, sizeof(samples),
            MSG_TRUNC | MSG_DONTWAIT) >> 1;
    } else {
        __attribute__((aligned(4))) uint8_t buffer[2048];
        sockaddr_storage remote;
        socklen_t len = sizeof(remote);
        socklen_t addrlen = sizeof(remote);

        length = recvfrom(mSocket, buffer, sizeof(buffer),
            MSG_TRUNC | MSG_DONTWAIT, (sockaddr *)&remote, &len);
        int length = recvfrom(mSocket, buffer, sizeof(buffer),
            MSG_TRUNC | MSG_DONTWAIT, (sockaddr *)&remote, &addrlen);

        // Do we need to check SSRC, sequence, and timestamp? They are not
        // reliable but at least they can be used to identify duplicates?
@@ -433,14 +433,15 @@ void AudioStream::decode(int tick)
        }
        length -= offset;
        if (length >= 0) {
            length = mCodec->decode(samples, &buffer[offset], length);
            length = mCodec->decode(samples, count, &buffer[offset], length);
        }
        if (length > 0 && mFixRemote) {
            mRemote = remote;
            mFixRemote = false;
        }
        count = length;
    }
    if (length <= 0) {
    if (count <= 0) {
        LOGV("stream[%d] decoder error", mSocket);
        return;
    }
@@ -462,7 +463,7 @@ void AudioStream::decode(int tick)

    // Append to the jitter buffer.
    int tail = mBufferTail * mSampleRate;
    for (int i = 0; i < mSampleCount; ++i) {
    for (int i = 0; i < count; ++i) {
        mBuffer[tail & mBufferMask] = samples[i];
        ++tail;
    }
+10 −4
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ public:
        return mSampleCount;
    }
    int encode(void *payload, int16_t *samples);
    int decode(int16_t *samples, void *payload, int length);
    int decode(int16_t *samples, int count, void *payload, int length);
private:
    int mSampleCount;
};
@@ -64,9 +64,12 @@ int UlawCodec::encode(void *payload, int16_t *samples)
    return mSampleCount;
}

int UlawCodec::decode(int16_t *samples, void *payload, int length)
int UlawCodec::decode(int16_t *samples, int count, void *payload, int length)
{
    int8_t *ulaws = (int8_t *)payload;
    if (length > count) {
        length = count;
    }
    for (int i = 0; i < length; ++i) {
        int ulaw = ~ulaws[i];
        int exponent = (ulaw >> 4) & 0x07;
@@ -87,7 +90,7 @@ public:
        return mSampleCount;
    }
    int encode(void *payload, int16_t *samples);
    int decode(int16_t *samples, void *payload, int length);
    int decode(int16_t *samples, int count, void *payload, int length);
private:
    int mSampleCount;
};
@@ -111,9 +114,12 @@ int AlawCodec::encode(void *payload, int16_t *samples)
    return mSampleCount;
}

int AlawCodec::decode(int16_t *samples, void *payload, int length)
int AlawCodec::decode(int16_t *samples, int count, void *payload, int length)
{
    int8_t *alaws = (int8_t *)payload;
    if (length > count) {
        length = count;
    }
    for (int i = 0; i < length; ++i) {
        int alaw = alaws[i] ^ 0x55;
        int exponent = (alaw >> 4) & 0x07;
+10 −6
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ public:
    }

    int encode(void *payload, int16_t *samples);
    int decode(int16_t *samples, void *payload, int length);
    int decode(int16_t *samples, int count, void *payload, int length);

private:
    gsm mEncode;
@@ -57,13 +57,17 @@ int GsmCodec::encode(void *payload, int16_t *samples)
    return 33;
}

int GsmCodec::decode(int16_t *samples, void *payload, int length)
int GsmCodec::decode(int16_t *samples, int count, void *payload, int length)
{
    if (length == 33 &&
        gsm_decode(mDecode, (unsigned char *)payload, samples) == 0) {
        return 160;
    unsigned char *bytes = (unsigned char *)payload;
    int n = 0;
    while (n + 160 <= count && length >= 33 &&
        gsm_decode(mDecode, bytes, &samples[n]) == 0) {
        n += 160;
        length -= 33;
        bytes += 33;
    }
    return -1;
    return n;
}

} // namespace