Skip to content

Commit 2ccf08f

Browse files
authored
Merge pull request #1679 from private-octopus/media_test_check_reset
Improve the quality reporting API
2 parents 5c86dca + 5306df4 commit 2ccf08f

File tree

7 files changed

+73
-17
lines changed

7 files changed

+73
-17
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ else()
88
endif()
99

1010
project(picoquic
11-
VERSION 1.1.19.9
11+
VERSION 1.1.19.10
1212
DESCRIPTION "picoquic library"
1313
LANGUAGES C CXX)
1414

picoquic/frames.c

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2427,9 +2427,9 @@ picoquic_packet_t* picoquic_check_spurious_retransmission(picoquic_cnx_t* cnx,
24272427

24282428
if ( p->sequence_number <= end_of_range) {
24292429

2430-
uint64_t max_spurious_rtt = current_time - p->send_time;
2431-
uint64_t max_reorder_delay = pkt_ctx->latest_time_acknowledged - p->send_time;
2432-
uint64_t max_reorder_gap = pkt_ctx->highest_acknowledged - p->sequence_number;
2430+
uint64_t spurious_rtt = current_time - p->send_time;
2431+
uint64_t reorder_delay = pkt_ctx->latest_time_acknowledged - p->send_time;
2432+
uint64_t reorder_gap = pkt_ctx->highest_acknowledged - p->sequence_number;
24332433
picoquic_path_t * old_path = p->send_path;
24342434

24352435
/* If the packet contained an ACK frame, perform the ACK of ACK pruning logic.
@@ -2468,20 +2468,16 @@ picoquic_packet_t* picoquic_check_spurious_retransmission(picoquic_cnx_t* cnx,
24682468
old_path->mtu_probe_sent = 0;
24692469
}
24702470

2471-
if (max_spurious_rtt > old_path->max_spurious_rtt) {
2472-
old_path->max_spurious_rtt = max_spurious_rtt;
2471+
if (spurious_rtt > old_path->max_spurious_rtt) {
2472+
old_path->max_spurious_rtt = spurious_rtt;
24732473
}
24742474

2475-
if (max_reorder_delay > old_path->max_reorder_delay) {
2476-
old_path->max_reorder_delay = max_reorder_delay;
2475+
if (reorder_delay > old_path->max_reorder_delay) {
2476+
old_path->max_reorder_delay = reorder_delay;
24772477
}
24782478

2479-
if (max_reorder_gap > old_path->max_reorder_gap) {
2480-
old_path->max_reorder_gap = max_reorder_gap;
2481-
}
2482-
2483-
if (old_path->nb_losses_found > 0) {
2484-
old_path->nb_losses_found--;
2479+
if (reorder_gap > old_path->max_reorder_gap) {
2480+
old_path->max_reorder_gap = reorder_gap;
24852481
}
24862482

24872483
if (old_path->total_bytes_lost > p->length) {

picoquic/loss_recovery.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -944,6 +944,9 @@ static void picoquic_count_and_notify_loss(
944944

945945
if (old_p->send_path != NULL) {
946946
old_p->send_path->nb_losses_found++;
947+
if (timer_based_retransmit) {
948+
old_p->send_path->nb_timer_losses++;
949+
}
947950
if ((old_p->send_path->smoothed_rtt != PICOQUIC_INITIAL_RTT ||
948951
old_p->send_path->rtt_variant != 0) &&
949952
old_p->send_time > cnx->start_time + old_p->send_path->smoothed_rtt) {

picoquic/picoquic.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
extern "C" {
4141
#endif
4242

43-
#define PICOQUIC_VERSION "1.1.19.9"
43+
#define PICOQUIC_VERSION "1.1.19.10"
4444
#define PICOQUIC_ERROR_CLASS 0x400
4545
#define PICOQUIC_ERROR_DUPLICATE (PICOQUIC_ERROR_CLASS + 1)
4646
#define PICOQUIC_ERROR_AEAD_CHECK (PICOQUIC_ERROR_CLASS + 3)
@@ -900,7 +900,13 @@ typedef struct st_picoquic_path_quality_t {
900900
uint64_t rtt_max; /* maximum value of RTT, computed since path creation */
901901
uint64_t sent; /* number of packets sent on the path */
902902
uint64_t lost; /* number of packets considered lost among those sent */
903+
uint64_t timer_losses; /* packet losses detected due to timer expiring */
904+
uint64_t spurious_losses; /* number of packet lost that were later acked. */
905+
uint64_t max_spurious_rtt; /* maximum RTT for spurious losses */
906+
uint64_t max_reorder_delay; /* maximum time gap for out of order packets */
907+
uint64_t max_reorder_gap; /* maximum number gap for out of order packets */
903908
uint64_t bytes_in_transit; /* number of bytes currently in transit */
909+
904910
} picoquic_path_quality_t;
905911

906912
int picoquic_get_path_quality(picoquic_cnx_t* cnx, uint64_t unique_path_id, picoquic_path_quality_t * quality);

picoquic/picoquic_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1091,7 +1091,8 @@ typedef struct st_picoquic_path_t {
10911091
uint64_t nb_retransmit; /* Number of timeout retransmissions since last ACK */
10921092
uint64_t total_bytes_lost; /* Sum of length of packet lost on this path */
10931093
uint64_t nb_losses_found;
1094-
uint64_t nb_spurious; /* Number of spurious retransmissiosn for the path */
1094+
uint64_t nb_timer_losses;
1095+
uint64_t nb_spurious; /* Number of spurious retransmissions for the path */
10951096
uint64_t path_packet_acked_number; /* path packet number of highest ack */
10961097
uint64_t path_packet_acked_time_sent; /* path packet number of highest ack */
10971098
uint64_t path_packet_acked_received; /* time at which the highest ack was received */

picoquic/quicctx.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2257,6 +2257,11 @@ static void picoquic_get_path_quality_from_context(picoquic_path_t* path_x, pico
22572257
quality->receive_rate_estimate = path_x->receive_rate_estimate;
22582258
quality->sent = path_x->path_packet_number;
22592259
quality->lost = path_x->nb_losses_found;
2260+
quality->timer_losses = path_x->nb_timer_losses;
2261+
quality->spurious_losses = path_x->nb_spurious;
2262+
quality->max_spurious_rtt = path_x->max_spurious_rtt;
2263+
quality->max_reorder_delay = path_x->max_reorder_delay;
2264+
quality->max_reorder_gap = path_x->max_reorder_gap;
22602265
quality->bytes_in_transit = path_x->bytes_in_transit;
22612266
}
22622267

picoquictest/mediatest.c

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,16 @@ typedef struct st_mediatest_stream_ctx_t {
102102
unsigned int finished_sending : 1;
103103
unsigned int fin_received : 1;
104104
unsigned int is_fin_sent : 1;
105+
unsigned int is_reset : 1;
105106

106107
uint64_t frames_to_send;
107108
uint64_t frames_sent;
109+
uint64_t frames_skipped;
108110
uint64_t frames_received;
109111
size_t bytes_sent;
110112
size_t bytes_received;
111113
uint64_t next_frame_time;
114+
uint64_t next_iframe_time;
112115

113116
mediatest_message_buffer_t message_sent;
114117
mediatest_message_buffer_t message_received;
@@ -446,11 +449,40 @@ int mediatest_receive_stream_data(mediatest_stream_ctx_t* stream_ctx, uint8_t* b
446449
return ret;
447450
}
448451

452+
/* For the high speed video stream, check if the media is far behind. if
453+
* it is, mark the current state as "skipping". If the state is marked
454+
* "reset", abstain from sending any frame until the next I frame.
455+
*/
456+
void mediatest_simulate_reset(mediatest_stream_ctx_t* stream_ctx, uint64_t current_time, uint64_t frame_duration, uint64_t cycle_length, uint64_t queue_limit)
457+
{
458+
uint64_t frame_rank = stream_ctx->frames_sent % cycle_length;
459+
460+
if (frame_rank != 0){
461+
if ((stream_ctx->frames_sent + queue_limit * frame_duration) > current_time) {
462+
stream_ctx->is_reset = 1;
463+
}
464+
if (stream_ctx->is_reset) {
465+
for (uint64_t i = frame_rank; i < cycle_length; i++) {
466+
stream_ctx->next_frame_time += frame_duration;
467+
stream_ctx->frames_sent++;
468+
stream_ctx->frames_skipped++;
469+
}
470+
}
471+
}
472+
else {
473+
stream_ctx->is_reset = 0;
474+
}
475+
}
476+
449477
/* Prepare next frame. Do this as soon as we know that a new frame can be sent. */
450478
int mediatest_prepare_new_frame(mediatest_stream_ctx_t* stream_ctx, uint64_t current_time)
451479
{
452480
int ret = 0;
453-
/* Is this the right time? */
481+
/* Is the high bandwidth stream reset? */
482+
if (stream_ctx->stream_type == media_test_video2) {
483+
mediatest_simulate_reset(stream_ctx, current_time, MEDIATEST_VIDEO_PERIOD, 100, 10);
484+
}
485+
/* Is this the right time? */
454486
if (stream_ctx->next_frame_time <= current_time) {
455487
if (stream_ctx->frames_sent == 0) {
456488
stream_ctx->next_frame_time = current_time;
@@ -470,8 +502,12 @@ int mediatest_prepare_new_frame(mediatest_stream_ctx_t* stream_ctx, uint64_t cur
470502
case media_test_video:
471503
stream_ctx->message_sent.message_size = ((stream_ctx->frames_sent % 100) == 0) ? 0x8000 : 0x800;
472504
stream_ctx->next_frame_time += MEDIATEST_VIDEO_PERIOD;
505+
473506
break;
474507
case media_test_video2:
508+
if ((stream_ctx->frames_sent % 100) == 0) {
509+
stream_ctx->next_iframe_time = stream_ctx->next_frame_time + 100 * MEDIATEST_VIDEO_PERIOD;
510+
}
475511
stream_ctx->message_sent.message_size = ((stream_ctx->frames_sent % 100) == 0) ? 0x10000 : 0x1800;
476512
stream_ctx->next_frame_time += MEDIATEST_VIDEO_PERIOD;
477513
break;
@@ -1211,6 +1247,7 @@ int mediatest_one(mediatest_id_enum media_test_id, mediatest_spec_t * spec)
12111247
uint64_t sim_time = 0;
12121248
uint64_t blocked_sequence = 4;
12131249
uint64_t unblocked_sequence = 1;
1250+
12141251
for (int i=0; i<2; i++){
12151252
mt_ctx->link[i]->picosec_per_byte = 160000; /* 160 nanosec per byte, i.e., 50Mbps*/
12161253
mt_ctx->link[i]->microsec_latency = 2000; /* 2ms */
@@ -1270,6 +1307,14 @@ int mediatest_one(mediatest_id_enum media_test_id, mediatest_spec_t * spec)
12701307
ret = mediatest_check_stats(mt_ctx, spec, media_test_video2);
12711308
}
12721309
}
1310+
if (ret == 0 && media_test_id == mediatest_wifi) {
1311+
picoquic_path_quality_t quality = { 0 };
1312+
picoquic_get_default_path_quality(mt_ctx->client_cnx->cnx, &quality);
1313+
if (quality.lost == 0 || quality.spurious_losses == 0 || quality.timer_losses == 0) {
1314+
/* Unexpected. the wifi tst should have triggered at least on spurious timer loss. */
1315+
ret = -1;
1316+
}
1317+
}
12731318
if (mt_ctx != NULL) {
12741319
mediatest_delete_ctx(mt_ctx);
12751320
}

0 commit comments

Comments
 (0)