ZLMediaKit Rtp包处理Seq的方式(二)

文章详细描述了PacketSortor类中的几个关键函数,如needForceFlush用于判断是否需要强制清空缓冲区,distance计算包序列距离,forceFlush处理可能的包丢失和回环,flushPacket负责清空连续包,以及popIterator用于取出并更新缓冲区数据。这些函数共同维护数据排序和缓冲区的有效管理。
摘要由CSDN通过智能技术生成

PacketSortor::needForceFlush

bool needForceFlush(SEQ seq) {
    return 
    // 缓冲区不为空
    !_pkt_sort_cache_map.empty()
    &&
    // 缓冲区长度超过最大值 
    (_pkt_sort_cache_map.size() > _max_buffer_size
        // 包间隔超过指定值 
        || distance(seq) > _max_distance
        // 收包超过指定时间
        || _ticker.elapsedTime() > _max_buffer_ms);
}

此函数用于判断是否需要清空缓冲区

PacketSortor::distance

SEQ distance(SEQ seq) {
    SEQ ret;
    auto next_seq = static_cast<SEQ>(_last_seq_out + 1);
    if (seq > next_seq) {
        ret = seq - next_seq;
    } else {
        ret = next_seq - seq;
    }
    // 超过最大值1/2情况, 最大值1/2-ret
    if (ret > SEQ_MAX >> 1) {
        return SEQ_MAX - ret;
    }
    return ret;
}

此函数用于判断当前包的seq与预期seq的距离

PacketSorter::forceFlush

// 外部调用代码确保_pkt_sort_cache_map不为空
void forceFlush(SEQ next_seq) {
    // 寻找距离比next_seq大的最近的seq
    auto it = _pkt_sort_cache_map.lower_bound(next_seq);
    if (it == _pkt_sort_cache_map.end()) {
        // 没有比next_seq更大的seq,应该是回环时丢包导致
        it = _pkt_sort_cache_map.begin();
    }
    // 丢包无法恢复,把这个包当做next_seq
    popIterator(it);
    // 清空连续包列表
    flushPacket();
    // 删除距离next_seq太大的包
    for (auto it = _pkt_sort_cache_map.begin(); it != _pkt_sort_cache_map.end();) {
        if (distance(it->first) > _max_distance) {
            it = _pkt_sort_cache_map.erase(it);
        } else {
            ++it;
        }
    }
}
  • popIterator(it) 使用最新的包作为next_seq
  • 后续清空前面连续的包,和距离太远的包

PacketSorter::flushPacket

void flushPacket() {
    if (_pkt_sort_cache_map.empty()) {
        return;
    }
    auto next_seq = static_cast<SEQ>(_last_seq_out + 1);
    // 在forceflush函数中,会删除所有,next_seq已被更新为最大值
    auto it = _pkt_sort_cache_map.lower_bound(next_seq);
    if (!mayLooped(next_seq, next_seq)) {
        // 无回环风险, 清空 < next_seq的值
        it = _pkt_sort_cache_map.erase(_pkt_sort_cache_map.begin(), it);
    }

    // 在forceflush函数中,此段代码不会被调用
    // _pkt_sort_cache_map 已经被清空
    // 而且事先已经更新了_last_seq_out,即使存在非连续也不会满足要求
    while (it != _pkt_sort_cache_map.end()) {
        // 找到下一个包
        if (it->first == static_cast<SEQ>(_last_seq_out + 1)) {
            it = popIterator(it);
            continue;
        }
        break;
    }
}

此函数用于清空buffer中存在的连续包

PacketSorter::popIterator

iterator popIterator(iterator it) {
    output(it->first, std::move(it->second));
    return _pkt_sort_cache_map.erase(it);
}

此函数用于将缓冲区的数据取出,更新seq和定时器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值