Add Congestion Control

This commit is contained in:
Florian Märkl 2020-11-18 20:15:24 +01:00
commit ffb8851835
No known key found for this signature in database
GPG key ID: 125BC8A5A6A1E857
16 changed files with 269 additions and 60 deletions

View file

@ -8,6 +8,7 @@
#include "audio.h"
#include "takion.h"
#include "thread.h"
#include "packetstats.h"
#ifdef __cplusplus
extern "C" {
@ -33,19 +34,20 @@ typedef struct chiaki_audio_receiver_t
ChiakiMutex mutex;
ChiakiSeqNum16 frame_index_prev;
bool frame_index_startup; // whether frame_index_prev has definitely not wrapped yet
ChiakiPacketStats *packet_stats;
} ChiakiAudioReceiver;
CHIAKI_EXPORT ChiakiErrorCode chiaki_audio_receiver_init(ChiakiAudioReceiver *audio_receiver, struct chiaki_session_t *session);
CHIAKI_EXPORT ChiakiErrorCode chiaki_audio_receiver_init(ChiakiAudioReceiver *audio_receiver, struct chiaki_session_t *session, ChiakiPacketStats *packet_stats);
CHIAKI_EXPORT void chiaki_audio_receiver_fini(ChiakiAudioReceiver *audio_receiver);
CHIAKI_EXPORT void chiaki_audio_receiver_stream_info(ChiakiAudioReceiver *audio_receiver, ChiakiAudioHeader *audio_header);
CHIAKI_EXPORT void chiaki_audio_receiver_av_packet(ChiakiAudioReceiver *audio_receiver, ChiakiTakionAVPacket *packet);
static inline ChiakiAudioReceiver *chiaki_audio_receiver_new(struct chiaki_session_t *session)
static inline ChiakiAudioReceiver *chiaki_audio_receiver_new(struct chiaki_session_t *session, ChiakiPacketStats *packet_stats)
{
ChiakiAudioReceiver *audio_receiver = CHIAKI_NEW(ChiakiAudioReceiver);
if(!audio_receiver)
return NULL;
ChiakiErrorCode err = chiaki_audio_receiver_init(audio_receiver, session);
ChiakiErrorCode err = chiaki_audio_receiver_init(audio_receiver, session, packet_stats);
if(err != CHIAKI_ERR_SUCCESS)
{
free(audio_receiver);

View file

@ -5,6 +5,7 @@
#include "takion.h"
#include "thread.h"
#include "packetstats.h"
#ifdef __cplusplus
extern "C" {
@ -13,11 +14,12 @@ extern "C" {
typedef struct chiaki_congestion_control_t
{
ChiakiTakion *takion;
ChiakiPacketStats *stats;
ChiakiThread thread;
ChiakiBoolPredCond stop_cond;
} ChiakiCongestionControl;
CHIAKI_EXPORT ChiakiErrorCode chiaki_congestion_control_start(ChiakiCongestionControl *control, ChiakiTakion *takion);
CHIAKI_EXPORT ChiakiErrorCode chiaki_congestion_control_start(ChiakiCongestionControl *control, ChiakiTakion *takion, ChiakiPacketStats *stats);
/**
* Stop control and join the thread

View file

@ -5,6 +5,7 @@
#include "common.h"
#include "takion.h"
#include "packetstats.h"
#include <stdint.h>
#include <stdbool.h>
@ -13,6 +14,16 @@
extern "C" {
#endif
typedef struct chiaki_stream_stats_t
{
uint64_t frames;
uint64_t bytes;
} ChiakiStreamStats;
CHIAKI_EXPORT void chiaki_stream_stats_reset(ChiakiStreamStats *stats);
CHIAKI_EXPORT void chiaki_stream_stats_frame(ChiakiStreamStats *stats, uint64_t size);
CHIAKI_EXPORT uint64_t chiaki_stream_stats_bitrate(ChiakiStreamStats *stats, uint64_t framerate);
struct chiaki_frame_unit_t;
typedef struct chiaki_frame_unit_t ChiakiFrameUnit;
@ -29,6 +40,8 @@ typedef struct chiaki_frame_processor_t
unsigned int units_fec_received;
ChiakiFrameUnit *unit_slots;
size_t unit_slots_size;
bool flushed; // whether we have already flushed the current frame, i.e. are only interested in stats, not data.
ChiakiStreamStats stream_stats;
} ChiakiFrameProcessor;
typedef enum chiaki_frame_flush_result_t {
@ -41,6 +54,7 @@ typedef enum chiaki_frame_flush_result_t {
CHIAKI_EXPORT void chiaki_frame_processor_init(ChiakiFrameProcessor *frame_processor, ChiakiLog *log);
CHIAKI_EXPORT void chiaki_frame_processor_fini(ChiakiFrameProcessor *frame_processor);
CHIAKI_EXPORT void chiaki_frame_processor_report_packet_stats(ChiakiFrameProcessor *frame_processor, ChiakiPacketStats *packet_stats);
CHIAKI_EXPORT ChiakiErrorCode chiaki_frame_processor_alloc_frame(ChiakiFrameProcessor *frame_processor, ChiakiTakionAVPacket *packet);
CHIAKI_EXPORT ChiakiErrorCode chiaki_frame_processor_put_unit(ChiakiFrameProcessor *frame_processor, ChiakiTakionAVPacket *packet);

View file

@ -0,0 +1,38 @@
// SPDX-License-Identifier: LicenseRef-GPL-3.0-or-later-OpenSSL
#ifndef CHIAKI_PACKETSTATS_H
#define CHIAKI_PACKETSTATS_H
#include "thread.h"
#include "seqnum.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct chiaki_packet_stats_t
{
ChiakiMutex mutex;
// For generations of packets, i.e. where we know the number of expected packets per generation
uint64_t gen_received;
uint64_t gen_lost;
// For sequential packets, i.e. where packets are identified by a sequence number
ChiakiSeqNum16 seq_min; // sequence number that was max at the last reset
ChiakiSeqNum16 seq_max; // currently maximal sequence number
uint64_t seq_received; // total received packets since the last reset
} ChiakiPacketStats;
CHIAKI_EXPORT ChiakiErrorCode chiaki_packet_stats_init(ChiakiPacketStats *stats);
CHIAKI_EXPORT void chiaki_packet_stats_fini(ChiakiPacketStats *stats);
CHIAKI_EXPORT void chiaki_packet_stats_reset(ChiakiPacketStats *stats);
CHIAKI_EXPORT void chiaki_packet_stats_push_generation(ChiakiPacketStats *stats, uint64_t received, uint64_t lost);
CHIAKI_EXPORT void chiaki_packet_stats_push_seq(ChiakiPacketStats *stats, ChiakiSeqNum16 seq_num);
CHIAKI_EXPORT void chiaki_packet_stats_get(ChiakiPacketStats *stats, bool reset, uint64_t *received, uint64_t *lost);
#ifdef __cplusplus
}
#endif
#endif // CHIAKI_PACKETSTATS_H

View file

@ -12,8 +12,6 @@
#include "takion.h"
#include "ecdh.h"
#include "audio.h"
#include "audioreceiver.h"
#include "videoreceiver.h"
#include "controller.h"
#include "stoppipe.h"
@ -199,8 +197,6 @@ typedef struct chiaki_session_t
ChiakiLog *log;
ChiakiStreamConnection stream_connection;
ChiakiAudioReceiver *audio_receiver;
ChiakiVideoReceiver *video_receiver;
ChiakiControllerState controller_state;
} ChiakiSession;

View file

@ -8,6 +8,9 @@
#include "log.h"
#include "ecdh.h"
#include "gkcrypt.h"
#include "audioreceiver.h"
#include "videoreceiver.h"
#include "congestioncontrol.h"
#include <stdbool.h>
@ -26,6 +29,10 @@ typedef struct chiaki_stream_connection_t
ChiakiGKCrypt *gkcrypt_local;
ChiakiGKCrypt *gkcrypt_remote;
ChiakiPacketStats packet_stats;
ChiakiAudioReceiver *audio_receiver;
ChiakiVideoReceiver *video_receiver;
ChiakiFeedbackSender feedback_sender;
/**
* whether feedback_sender is initialized

View file

@ -27,9 +27,10 @@ typedef struct chiaki_video_receiver_t
int32_t frame_index_prev; // last frame that has been at least partially decoded
int32_t frame_index_prev_complete; // last frame that has been completely decoded
ChiakiFrameProcessor frame_processor;
ChiakiPacketStats *packet_stats;
} ChiakiVideoReceiver;
CHIAKI_EXPORT void chiaki_video_receiver_init(ChiakiVideoReceiver *video_receiver, struct chiaki_session_t *session);
CHIAKI_EXPORT void chiaki_video_receiver_init(ChiakiVideoReceiver *video_receiver, struct chiaki_session_t *session, ChiakiPacketStats *packet_stats);
CHIAKI_EXPORT void chiaki_video_receiver_fini(ChiakiVideoReceiver *video_receiver);
/**
@ -43,12 +44,12 @@ CHIAKI_EXPORT void chiaki_video_receiver_stream_info(ChiakiVideoReceiver *video_
CHIAKI_EXPORT void chiaki_video_receiver_av_packet(ChiakiVideoReceiver *video_receiver, ChiakiTakionAVPacket *packet);
static inline ChiakiVideoReceiver *chiaki_video_receiver_new(struct chiaki_session_t *session)
static inline ChiakiVideoReceiver *chiaki_video_receiver_new(struct chiaki_session_t *session, ChiakiPacketStats *packet_stats)
{
ChiakiVideoReceiver *video_receiver = CHIAKI_NEW(ChiakiVideoReceiver);
if(!video_receiver)
return NULL;
chiaki_video_receiver_init(video_receiver, session);
chiaki_video_receiver_init(video_receiver, session, packet_stats);
return video_receiver;
}