mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 10:40:05 +08:00
基本完成twcc rtcp fci的生成
This commit is contained in:
parent
e02bc9ce67
commit
0ae1d46892
@ -285,22 +285,16 @@ public:
|
||||
//获取symbollist
|
||||
vector<SymbolStatus> getSymbolList() const;
|
||||
//构造函数
|
||||
StatusVecChunk(const vector<SymbolStatus> &status);
|
||||
StatusVecChunk(bool symbol_bit, const vector<SymbolStatus> &status);
|
||||
//打印本对象
|
||||
string dumpString() const;
|
||||
} PACKED;
|
||||
|
||||
StatusVecChunk::StatusVecChunk(const vector<SymbolStatus> &status) {
|
||||
StatusVecChunk::StatusVecChunk(bool symbol_bit, const vector<SymbolStatus> &status) {
|
||||
CHECK((1 + symbol_bit) * status.size() <= 14);
|
||||
uint16_t value = 0;
|
||||
type = 1;
|
||||
if (status.size() == 14) {
|
||||
symbol = 0;
|
||||
} else if (status.size() == 7) {
|
||||
symbol = 1;
|
||||
} else {
|
||||
//非法
|
||||
CHECK(0);
|
||||
}
|
||||
symbol = symbol_bit;
|
||||
int i = 13;
|
||||
for (auto &item : status) {
|
||||
CHECK(item <= SymbolStatus::reserved);
|
||||
@ -428,8 +422,8 @@ static int16_t getRecvDelta(SymbolStatus status, uint8_t *&ptr, const uint8_t *e
|
||||
return delta;
|
||||
}
|
||||
|
||||
map<uint16_t, std::pair<SymbolStatus, int16_t/*stamp*/> > FCI_TWCC::getPacketChunkList(size_t total_size) const {
|
||||
map<uint16_t, std::pair<SymbolStatus, int16_t> > ret;
|
||||
FCI_TWCC::TwccPacketStatus FCI_TWCC::getPacketChunkList(size_t total_size) const {
|
||||
TwccPacketStatus ret;
|
||||
auto ptr = (uint8_t *) this + kSize;
|
||||
auto end = (uint8_t *) this + total_size;
|
||||
CHECK(ptr < end);
|
||||
@ -475,48 +469,83 @@ string FCI_TWCC::dumpString(size_t total_size) const {
|
||||
return std::move(printer);
|
||||
}
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
#if 1
|
||||
using namespace mediakit;
|
||||
void testFCI() {
|
||||
{
|
||||
FCI_SLI fci(8191, 0, 63);
|
||||
InfoL << hexdump(&fci, FCI_SLI::kSize) << fci.dumpString();
|
||||
}
|
||||
{
|
||||
FCI_FIR fci(123456, 139, 456789);
|
||||
InfoL << hexdump(&fci, FCI_FIR::kSize) << fci.dumpString();
|
||||
}
|
||||
{
|
||||
auto str = FCI_REMB::create({1234, 2345, 5678}, 4 * 1024 * 1024);
|
||||
FCI_REMB *ptr = (FCI_REMB *) str.data();
|
||||
InfoL << hexdump(str.data(), str.size()) << ptr->dumpString();
|
||||
}
|
||||
{
|
||||
FCI_NACK nack(1234, vector<bool>({1, 0, 0, 0, 1, 0, 1, 0, 1, 0}));
|
||||
InfoL << hexdump(&nack, FCI_NACK::kSize) << nack.dumpString();
|
||||
}
|
||||
|
||||
{
|
||||
RunLengthChunk chunk(SymbolStatus::large_delta, 8024);
|
||||
InfoL << hexdump(&chunk, RunLengthChunk::kSize) << chunk.dumpString();
|
||||
}
|
||||
|
||||
auto lam = [](const initializer_list<int> &lst) {
|
||||
vector<SymbolStatus> ret;
|
||||
for (auto &num : lst) {
|
||||
ret.emplace_back((SymbolStatus) num);
|
||||
static void appendDeltaString(string &delta_str, FCI_TWCC::TwccPacketStatus &status, int count){
|
||||
for (auto it = status.begin(); it != status.end() && count--;) {
|
||||
switch (it->second.first) {
|
||||
//large delta模式先写高字节,再写低字节
|
||||
case SymbolStatus::large_delta: delta_str.push_back((it->second.second >> 8) & 0xFF);
|
||||
//small delta模式只写低字节
|
||||
case SymbolStatus::small_delta: delta_str.push_back(it->second.second & 0xFF); break;
|
||||
default: break;
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
{
|
||||
StatusVecChunk chunk(lam({0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1}));
|
||||
InfoL << hexdump(&chunk, StatusVecChunk::kSize) << chunk.dumpString();
|
||||
}
|
||||
{
|
||||
StatusVecChunk chunk(lam({0, 1, 2, 2, 0, 1, 2}));
|
||||
InfoL << hexdump(&chunk, StatusVecChunk::kSize) << chunk.dumpString();
|
||||
//移除已经处理过的数据
|
||||
it = status.erase(it);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
string FCI_TWCC::create(uint32_t ref_time, uint8_t fb_pkt_count, TwccPacketStatus &status) {
|
||||
string fci;
|
||||
fci.resize(FCI_TWCC::kSize);
|
||||
FCI_TWCC *ptr = (FCI_TWCC *) (fci.data());
|
||||
ptr->base_seq = htons(status.begin()->first);
|
||||
ptr->pkt_status_count = htons(status.size());
|
||||
ptr->fb_pkt_count = fb_pkt_count;
|
||||
ptr->ref_time[0] = (ref_time >> 16) & 0xFF;
|
||||
ptr->ref_time[1] = (ref_time >> 8) & 0xFF;
|
||||
ptr->ref_time[2] = (ref_time >> 0) & 0xFF;
|
||||
|
||||
string delta_str;
|
||||
while (!status.empty()) {
|
||||
{
|
||||
//第一个rtp的状态
|
||||
auto symbol = status.begin()->second.first;
|
||||
int16_t count = 0;
|
||||
for (auto &pr : status) {
|
||||
if (++count == (0xFFFF >> 3)) {
|
||||
//RunLengthChunk 13个bit表明rtp个数,最多可以表述0xFFFF >> 3个rtp状态
|
||||
break;
|
||||
}
|
||||
if (pr.second.first != symbol) {
|
||||
//状态发送变更了,本chunk结束
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (count >= 7) {
|
||||
//连续状态相同个数大于6个时,使用RunLengthChunk模式比较节省带宽
|
||||
RunLengthChunk chunk(symbol, count);
|
||||
fci.append((char *)&chunk, RunLengthChunk::kSize);
|
||||
appendDeltaString(delta_str, status, count);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
//StatusVecChunk模式
|
||||
//symbol_list中元素是1个bit
|
||||
auto symbol = 0;
|
||||
int count = 0;
|
||||
vector<SymbolStatus> vec;
|
||||
for (auto &pr : status) {
|
||||
vec.push_back(pr.second.first);
|
||||
if (pr.second.first >= SymbolStatus::large_delta) {
|
||||
//symbol_list中元素是2个bit
|
||||
symbol = 1;
|
||||
}
|
||||
if ((1 + symbol) * (++count) == 14) {
|
||||
//symbol为0时,最多存放14个rtp的状态
|
||||
//symbol为1时,最多存放7个rtp的状态
|
||||
break;
|
||||
}
|
||||
}
|
||||
StatusVecChunk chunk(symbol, vec);
|
||||
fci.append((char *)&chunk, StatusVecChunk::kSize);
|
||||
appendDeltaString(delta_str, status, count);
|
||||
}
|
||||
}
|
||||
|
||||
//recv delta部分
|
||||
fci.append(delta_str);
|
||||
return fci;
|
||||
}
|
||||
|
||||
}//namespace mediakit
|
@ -346,14 +346,16 @@ enum class SymbolStatus : uint8_t{
|
||||
class FCI_TWCC{
|
||||
public:
|
||||
static size_t constexpr kSize = 8;
|
||||
|
||||
using TwccPacketStatus = map<uint16_t/*rtp ext seq*/, std::pair<SymbolStatus, int16_t/*recv delta,单位为250us*/> >;
|
||||
void check(size_t size);
|
||||
string dumpString(size_t total_size) const;
|
||||
uint16_t getBaseSeq() const;
|
||||
//单位64ms
|
||||
uint32_t getReferenceTime() const;
|
||||
uint16_t getPacketCount() const;
|
||||
map<uint16_t/*rtp ext seq*/, std::pair<SymbolStatus, int16_t/*recv delta,单位为250us*/> > getPacketChunkList(size_t total_size) const;
|
||||
TwccPacketStatus getPacketChunkList(size_t total_size) const;
|
||||
|
||||
static string create(uint32_t ref_time, uint8_t fb_pkt_count, TwccPacketStatus &status);
|
||||
|
||||
private:
|
||||
//base sequence number,基础序号,本次反馈的第一个包的序号;也就是RTP扩展头的序列号
|
||||
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
|
||||
*
|
||||
* This file is part of ZLToolKit(https://github.com/xia-chu/ZLToolKit).
|
||||
*
|
||||
* Use of this source code is governed by MIT license that can be found in the
|
||||
* LICENSE file in the root of the source tree. All contributing project authors
|
||||
* may be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "Util/logger.h"
|
||||
#include "Rtcp/RtcpFCI.h"
|
||||
using namespace std;
|
||||
using namespace toolkit;
|
||||
using namespace mediakit;
|
||||
|
||||
extern void testFCI();
|
||||
|
||||
int main() {
|
||||
Logger::Instance().add(std::make_shared<ConsoleChannel>());
|
||||
|
||||
testFCI();
|
||||
return 0;
|
||||
}
|
@ -9,6 +9,9 @@
|
||||
*/
|
||||
|
||||
#include "TwccContext.h"
|
||||
#include "Rtcp/RtcpFCI.h"
|
||||
|
||||
using namespace mediakit;
|
||||
|
||||
enum class ExtSeqStatus : int {
|
||||
normal = 0,
|
||||
@ -78,17 +81,27 @@ void TwccContext::onSendTwcc() {
|
||||
auto begin = _rtp_recv_status.begin();
|
||||
auto min = begin->first;
|
||||
auto ref_time = begin->second;
|
||||
DebugL << "base_seq:" << min << ",pkt_status_count:" << max + 1 - min << ",ref time:" << ref_time / 64
|
||||
<< ", fb count:" << (int) (_twcc_pkt_count++);
|
||||
for (auto i = min; i <= max; ++i) {
|
||||
auto it = _rtp_recv_status.find(i);
|
||||
if (it == _rtp_recv_status.end()) {
|
||||
DebugL << "rtp seq:" << i << ",packet status:" << 0 /*not recved*/ << ",delta_ms:" << 0;
|
||||
} else {
|
||||
auto delta_ms = it->second - ref_time;
|
||||
DebugL << "rtp seq:" << i << ",packet status:" << 1 /*recved*/ << ",delta_ms:" << delta_ms;
|
||||
FCI_TWCC::TwccPacketStatus status;
|
||||
for (auto seq = min; seq <= max; ++seq) {
|
||||
int16_t delta = 0;
|
||||
SymbolStatus symbol = SymbolStatus::not_received;
|
||||
auto it = _rtp_recv_status.find(seq);
|
||||
if (it != _rtp_recv_status.end()) {
|
||||
//recv delta,单位为250us,1ms等于4x250us
|
||||
delta = (int16_t) (4 * ((int64_t) it->second - (int64_t) ref_time));
|
||||
if (delta < 0 || delta > 0xFF) {
|
||||
symbol = SymbolStatus::large_delta;
|
||||
} else {
|
||||
symbol = SymbolStatus::small_delta;
|
||||
}
|
||||
ref_time = it->second;
|
||||
}
|
||||
status.emplace(seq, std::make_pair(symbol, delta));
|
||||
}
|
||||
auto fci = FCI_TWCC::create(ref_time / 64, _twcc_pkt_count, status);
|
||||
InfoL << ((FCI_TWCC *) (fci.data()))->dumpString(fci.size());
|
||||
|
||||
++_twcc_pkt_count;
|
||||
clearStatus();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user