mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-25 20:27:34 +08:00
基本完成twcc rtcp fci的生成
This commit is contained in:
parent
e02bc9ce67
commit
0ae1d46892
@ -285,22 +285,16 @@ public:
|
|||||||
//获取symbollist
|
//获取symbollist
|
||||||
vector<SymbolStatus> getSymbolList() const;
|
vector<SymbolStatus> getSymbolList() const;
|
||||||
//构造函数
|
//构造函数
|
||||||
StatusVecChunk(const vector<SymbolStatus> &status);
|
StatusVecChunk(bool symbol_bit, const vector<SymbolStatus> &status);
|
||||||
//打印本对象
|
//打印本对象
|
||||||
string dumpString() const;
|
string dumpString() const;
|
||||||
} PACKED;
|
} 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;
|
uint16_t value = 0;
|
||||||
type = 1;
|
type = 1;
|
||||||
if (status.size() == 14) {
|
symbol = symbol_bit;
|
||||||
symbol = 0;
|
|
||||||
} else if (status.size() == 7) {
|
|
||||||
symbol = 1;
|
|
||||||
} else {
|
|
||||||
//非法
|
|
||||||
CHECK(0);
|
|
||||||
}
|
|
||||||
int i = 13;
|
int i = 13;
|
||||||
for (auto &item : status) {
|
for (auto &item : status) {
|
||||||
CHECK(item <= SymbolStatus::reserved);
|
CHECK(item <= SymbolStatus::reserved);
|
||||||
@ -428,8 +422,8 @@ static int16_t getRecvDelta(SymbolStatus status, uint8_t *&ptr, const uint8_t *e
|
|||||||
return delta;
|
return delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
map<uint16_t, std::pair<SymbolStatus, int16_t/*stamp*/> > FCI_TWCC::getPacketChunkList(size_t total_size) const {
|
FCI_TWCC::TwccPacketStatus FCI_TWCC::getPacketChunkList(size_t total_size) const {
|
||||||
map<uint16_t, std::pair<SymbolStatus, int16_t> > ret;
|
TwccPacketStatus ret;
|
||||||
auto ptr = (uint8_t *) this + kSize;
|
auto ptr = (uint8_t *) this + kSize;
|
||||||
auto end = (uint8_t *) this + total_size;
|
auto end = (uint8_t *) this + total_size;
|
||||||
CHECK(ptr < end);
|
CHECK(ptr < end);
|
||||||
@ -475,48 +469,83 @@ string FCI_TWCC::dumpString(size_t total_size) const {
|
|||||||
return std::move(printer);
|
return std::move(printer);
|
||||||
}
|
}
|
||||||
|
|
||||||
}//namespace mediakit
|
static void appendDeltaString(string &delta_str, FCI_TWCC::TwccPacketStatus &status, int count){
|
||||||
|
for (auto it = status.begin(); it != status.end() && count--;) {
|
||||||
#if 1
|
switch (it->second.first) {
|
||||||
using namespace mediakit;
|
//large delta模式先写高字节,再写低字节
|
||||||
void testFCI() {
|
case SymbolStatus::large_delta: delta_str.push_back((it->second.second >> 8) & 0xFF);
|
||||||
{
|
//small delta模式只写低字节
|
||||||
FCI_SLI fci(8191, 0, 63);
|
case SymbolStatus::small_delta: delta_str.push_back(it->second.second & 0xFF); break;
|
||||||
InfoL << hexdump(&fci, FCI_SLI::kSize) << fci.dumpString();
|
default: break;
|
||||||
}
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
return ret;
|
//移除已经处理过的数据
|
||||||
};
|
it = status.erase(it);
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#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{
|
class FCI_TWCC{
|
||||||
public:
|
public:
|
||||||
static size_t constexpr kSize = 8;
|
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);
|
void check(size_t size);
|
||||||
string dumpString(size_t total_size) const;
|
string dumpString(size_t total_size) const;
|
||||||
uint16_t getBaseSeq() const;
|
uint16_t getBaseSeq() const;
|
||||||
//单位64ms
|
//单位64ms
|
||||||
uint32_t getReferenceTime() const;
|
uint32_t getReferenceTime() const;
|
||||||
uint16_t getPacketCount() 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:
|
private:
|
||||||
//base sequence number,基础序号,本次反馈的第一个包的序号;也就是RTP扩展头的序列号
|
//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 "TwccContext.h"
|
||||||
|
#include "Rtcp/RtcpFCI.h"
|
||||||
|
|
||||||
|
using namespace mediakit;
|
||||||
|
|
||||||
enum class ExtSeqStatus : int {
|
enum class ExtSeqStatus : int {
|
||||||
normal = 0,
|
normal = 0,
|
||||||
@ -78,17 +81,27 @@ void TwccContext::onSendTwcc() {
|
|||||||
auto begin = _rtp_recv_status.begin();
|
auto begin = _rtp_recv_status.begin();
|
||||||
auto min = begin->first;
|
auto min = begin->first;
|
||||||
auto ref_time = begin->second;
|
auto ref_time = begin->second;
|
||||||
DebugL << "base_seq:" << min << ",pkt_status_count:" << max + 1 - min << ",ref time:" << ref_time / 64
|
FCI_TWCC::TwccPacketStatus status;
|
||||||
<< ", fb count:" << (int) (_twcc_pkt_count++);
|
for (auto seq = min; seq <= max; ++seq) {
|
||||||
for (auto i = min; i <= max; ++i) {
|
int16_t delta = 0;
|
||||||
auto it = _rtp_recv_status.find(i);
|
SymbolStatus symbol = SymbolStatus::not_received;
|
||||||
if (it == _rtp_recv_status.end()) {
|
auto it = _rtp_recv_status.find(seq);
|
||||||
DebugL << "rtp seq:" << i << ",packet status:" << 0 /*not recved*/ << ",delta_ms:" << 0;
|
if (it != _rtp_recv_status.end()) {
|
||||||
} else {
|
//recv delta,单位为250us,1ms等于4x250us
|
||||||
auto delta_ms = it->second - ref_time;
|
delta = (int16_t) (4 * ((int64_t) it->second - (int64_t) ref_time));
|
||||||
DebugL << "rtp seq:" << i << ",packet status:" << 1 /*recved*/ << ",delta_ms:" << delta_ms;
|
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();
|
clearStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user