aboutsummaryrefslogtreecommitdiff
path: root/logging
diff options
context:
space:
mode:
Diffstat (limited to 'logging')
-rw-r--r--logging/BUILD.gn263
-rw-r--r--logging/g3doc/rtc_event_log.md85
-rw-r--r--logging/rtc_event_log/DEPS1
-rw-r--r--logging/rtc_event_log/encoder/bit_writer.cc49
-rw-r--r--logging/rtc_event_log/encoder/bit_writer.h61
-rw-r--r--logging/rtc_event_log/encoder/blob_encoding.cc33
-rw-r--r--logging/rtc_event_log/encoder/blob_encoding.h8
-rw-r--r--logging/rtc_event_log/encoder/delta_encoding.cc261
-rw-r--r--logging/rtc_event_log/encoder/delta_encoding.h11
-rw-r--r--logging/rtc_event_log/encoder/delta_encoding_unittest.cc12
-rw-r--r--logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h4
-rw-r--r--logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc95
-rw-r--r--logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h7
-rw-r--r--logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc276
-rw-r--r--logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h4
-rw-r--r--logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc439
-rw-r--r--logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.cc164
-rw-r--r--logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.h46
-rw-r--r--logging/rtc_event_log/encoder/var_int.cc21
-rw-r--r--logging/rtc_event_log/encoder/var_int.h24
-rw-r--r--logging/rtc_event_log/events/fixed_length_encoding_parameters_v3.cc137
-rw-r--r--logging/rtc_event_log/events/fixed_length_encoding_parameters_v3.h96
-rw-r--r--logging/rtc_event_log/events/logged_rtp_rtcp.h260
-rw-r--r--logging/rtc_event_log/events/rtc_event_alr_state.cc18
-rw-r--r--logging/rtc_event_log/events/rtc_event_alr_state.h44
-rw-r--r--logging/rtc_event_log/events/rtc_event_audio_network_adaptation.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h40
-rw-r--r--logging/rtc_event_log/events/rtc_event_audio_playout.cc13
-rw-r--r--logging/rtc_event_log/events/rtc_event_audio_playout.h51
-rw-r--r--logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h41
-rw-r--r--logging/rtc_event_log/events/rtc_event_audio_send_stream_config.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h40
-rw-r--r--logging/rtc_event_log/events/rtc_event_begin_log.cc73
-rw-r--r--logging/rtc_event_log/events/rtc_event_begin_log.h74
-rw-r--r--logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.cc16
-rw-r--r--logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h96
-rw-r--r--logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h46
-rw-r--r--logging/rtc_event_log/events/rtc_event_definition.h152
-rw-r--r--logging/rtc_event_log/events/rtc_event_dtls_transport_state.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_dtls_transport_state.h33
-rw-r--r--logging/rtc_event_log/events/rtc_event_dtls_writable_state.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_dtls_writable_state.h36
-rw-r--r--logging/rtc_event_log/events/rtc_event_end_log.cc58
-rw-r--r--logging/rtc_event_log/events/rtc_event_end_log.h64
-rw-r--r--logging/rtc_event_log/events/rtc_event_field_encoding.cc299
-rw-r--r--logging/rtc_event_log/events/rtc_event_field_encoding.h179
-rw-r--r--logging/rtc_event_log/events/rtc_event_field_encoding_parser.cc398
-rw-r--r--logging/rtc_event_log/events/rtc_event_field_encoding_parser.h291
-rw-r--r--logging/rtc_event_log/events/rtc_event_field_encoding_unittest.cc886
-rw-r--r--logging/rtc_event_log/events/rtc_event_field_extraction.cc60
-rw-r--r--logging/rtc_event_log/events/rtc_event_field_extraction.h84
-rw-r--r--logging/rtc_event_log/events/rtc_event_field_extraction_unittest.cc97
-rw-r--r--logging/rtc_event_log/events/rtc_event_frame_decoded.cc44
-rw-r--r--logging/rtc_event_log/events/rtc_event_frame_decoded.h93
-rw-r--r--logging/rtc_event_log/events/rtc_event_generic_ack_received.cc9
-rw-r--r--logging/rtc_event_log/events/rtc_event_generic_ack_received.h55
-rw-r--r--logging/rtc_event_log/events/rtc_event_generic_packet_received.cc7
-rw-r--r--logging/rtc_event_log/events/rtc_event_generic_packet_received.h43
-rw-r--r--logging/rtc_event_log/events/rtc_event_generic_packet_sent.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_generic_packet_sent.h52
-rw-r--r--logging/rtc_event_log/events/rtc_event_ice_candidate_pair.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h46
-rw-r--r--logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc10
-rw-r--r--logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h43
-rw-r--r--logging/rtc_event_log/events/rtc_event_probe_cluster_created.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_probe_cluster_created.h49
-rw-r--r--logging/rtc_event_log/events/rtc_event_probe_result_failure.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_probe_result_failure.h41
-rw-r--r--logging/rtc_event_log/events/rtc_event_probe_result_success.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_probe_result_success.h41
-rw-r--r--logging/rtc_event_log/events/rtc_event_remote_estimate.h36
-rw-r--r--logging/rtc_event_log/events/rtc_event_route_change.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_route_change.h39
-rw-r--r--logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h25
-rw-r--r--logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h25
-rw-r--r--logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.cc23
-rw-r--r--logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h61
-rw-r--r--logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.cc25
-rw-r--r--logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h63
-rw-r--r--logging/rtc_event_log/events/rtc_event_video_receive_stream_config.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h38
-rw-r--r--logging/rtc_event_log/events/rtc_event_video_send_stream_config.cc8
-rw-r--r--logging/rtc_event_log/events/rtc_event_video_send_stream_config.h38
-rw-r--r--logging/rtc_event_log/fake_rtc_event_log.cc29
-rw-r--r--logging/rtc_event_log/fake_rtc_event_log.h17
-rw-r--r--logging/rtc_event_log/fake_rtc_event_log_factory.cc14
-rw-r--r--logging/rtc_event_log/fake_rtc_event_log_factory.h14
-rw-r--r--logging/rtc_event_log/logged_events.cc55
-rw-r--r--logging/rtc_event_log/logged_events.h649
-rw-r--r--logging/rtc_event_log/rtc_event_log.proto12
-rw-r--r--logging/rtc_event_log/rtc_event_log2.proto55
-rw-r--r--logging/rtc_event_log/rtc_event_log2rtp_dump.cc9
-rw-r--r--logging/rtc_event_log/rtc_event_log_impl.cc50
-rw-r--r--logging/rtc_event_log/rtc_event_log_impl.h16
-rw-r--r--logging/rtc_event_log/rtc_event_log_parser.cc1032
-rw-r--r--logging/rtc_event_log/rtc_event_log_parser.h459
-rw-r--r--logging/rtc_event_log/rtc_event_log_unittest.cc242
-rw-r--r--logging/rtc_event_log/rtc_event_log_unittest_helper.cc174
-rw-r--r--logging/rtc_event_log/rtc_event_log_unittest_helper.h36
-rw-r--r--logging/rtc_event_log/rtc_event_processor.cc2
-rw-r--r--logging/rtc_event_log/rtc_event_processor.h4
-rw-r--r--logging/rtc_event_log/rtc_event_processor_unittest.cc8
-rw-r--r--logging/rtc_event_log/rtc_stream_config.cc4
-rw-r--r--logging/rtc_event_log/rtc_stream_config.h3
108 files changed, 7081 insertions, 2383 deletions
diff --git a/logging/BUILD.gn b/logging/BUILD.gn
index c1edd69680..fea5569a7d 100644
--- a/logging/BUILD.gn
+++ b/logging/BUILD.gn
@@ -18,6 +18,7 @@ if (is_android) {
group("logging") {
deps = [
":rtc_event_audio",
+ ":rtc_event_begin_end",
":rtc_event_bwe",
":rtc_event_log_impl_encoder",
":rtc_event_pacing",
@@ -32,6 +33,34 @@ rtc_source_set("rtc_event_log_api") {
deps = [ "../api/rtc_event_log" ]
}
+rtc_library("rtc_event_field") {
+ sources = [
+ "rtc_event_log/events/fixed_length_encoding_parameters_v3.cc",
+ "rtc_event_log/events/fixed_length_encoding_parameters_v3.h",
+ "rtc_event_log/events/rtc_event_definition.h",
+ "rtc_event_log/events/rtc_event_field_encoding.cc",
+ "rtc_event_log/events/rtc_event_field_encoding.h",
+ "rtc_event_log/events/rtc_event_field_encoding_parser.cc",
+ "rtc_event_log/events/rtc_event_field_encoding_parser.h",
+ "rtc_event_log/events/rtc_event_field_extraction.cc",
+ "rtc_event_log/events/rtc_event_field_extraction.h",
+ ]
+
+ deps = [
+ ":rtc_event_number_encodings",
+ "../api:array_view",
+ "../api/rtc_event_log",
+ "../api/units:timestamp",
+ "../rtc_base:bitstream_reader",
+ "../rtc_base:checks",
+ "../rtc_base:logging",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
rtc_library("rtc_stream_config") {
sources = [
"rtc_event_log/rtc_stream_config.cc",
@@ -42,6 +71,7 @@ rtc_library("rtc_stream_config") {
"../api:rtp_headers",
"../api:rtp_parameters",
]
+ absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
}
rtc_library("rtc_event_pacing") {
@@ -51,10 +81,14 @@ rtc_library("rtc_event_pacing") {
]
deps = [
- "../api:scoped_refptr",
+ ":rtc_event_field",
"../api/rtc_event_log",
+ "../api/units:timestamp",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
]
- absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
}
rtc_library("rtc_event_audio") {
@@ -70,13 +104,33 @@ rtc_library("rtc_event_audio") {
]
deps = [
+ ":rtc_event_field",
":rtc_stream_config",
- "../api:scoped_refptr",
"../api/rtc_event_log",
+ "../api/units:timestamp",
"../modules/audio_coding:audio_network_adaptor_config",
"../rtc_base:checks",
]
- absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
+ ]
+}
+
+rtc_library("rtc_event_begin_end") {
+ sources = [
+ "rtc_event_log/events/rtc_event_begin_log.cc",
+ "rtc_event_log/events/rtc_event_begin_log.h",
+ "rtc_event_log/events/rtc_event_end_log.cc",
+ "rtc_event_log/events/rtc_event_end_log.h",
+ ]
+ deps = [
+ ":rtc_event_field",
+ "../api:array_view",
+ "../api/rtc_event_log",
+ "../api/units:timestamp",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/strings" ]
}
rtc_library("rtc_event_bwe") {
@@ -97,13 +151,34 @@ rtc_library("rtc_event_bwe") {
]
deps = [
- "../api:scoped_refptr",
+ ":rtc_event_field",
+ "../api:network_state_predictor_api",
"../api/rtc_event_log",
"../api/units:data_rate",
- "../modules/remote_bitrate_estimator",
+ "../api/units:timestamp",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+}
+
+rtc_library("rtc_event_frame_events") {
+ sources = [
+ "rtc_event_log/events/rtc_event_frame_decoded.cc",
+ "rtc_event_log/events/rtc_event_frame_decoded.h",
+ ]
+ deps = [
+ ":rtc_event_field",
+ "../api/rtc_event_log",
+ "../api/units:timestamp",
+ "../api/video:video_frame",
+ "../rtc_base:timeutils",
]
absl_deps = [
"//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
]
}
@@ -119,17 +194,21 @@ rtc_library("rtc_event_generic_packet_events") {
"rtc_event_log/events/rtc_event_generic_packet_sent.h",
]
deps = [
+ ":rtc_event_field",
"../api/rtc_event_log",
+ "../api/units:timestamp",
"../rtc_base:timeutils",
]
absl_deps = [
"//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
]
}
rtc_library("rtc_event_rtp_rtcp") {
sources = [
+ "rtc_event_log/events/logged_rtp_rtcp.h",
"rtc_event_log/events/rtc_event_rtcp_packet_incoming.cc",
"rtc_event_log/events/rtc_event_rtcp_packet_incoming.h",
"rtc_event_log/events/rtc_event_rtcp_packet_outgoing.cc",
@@ -141,14 +220,19 @@ rtc_library("rtc_event_rtp_rtcp") {
]
deps = [
+ ":rtc_event_field",
"../api:array_view",
- "../api:scoped_refptr",
+ "../api:rtp_headers",
"../api/rtc_event_log",
+ "../api/units:timestamp",
"../modules/rtp_rtcp:rtp_rtcp_format",
+ "../rtc_base:buffer",
"../rtc_base:checks",
- "../rtc_base:rtc_base_approved",
]
- absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
+ ]
}
rtc_library("rtc_event_video") {
@@ -160,12 +244,42 @@ rtc_library("rtc_event_video") {
]
deps = [
+ ":rtc_event_field",
":rtc_stream_config",
- "../api:scoped_refptr",
"../api/rtc_event_log",
+ "../api/units:timestamp",
"../rtc_base:checks",
]
- absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
+ ]
+}
+
+rtc_library("rtc_event_number_encodings") {
+ sources = [
+ "rtc_event_log/encoder/bit_writer.cc",
+ "rtc_event_log/encoder/bit_writer.h",
+ "rtc_event_log/encoder/rtc_event_log_encoder_common.cc",
+ "rtc_event_log/encoder/rtc_event_log_encoder_common.h",
+ "rtc_event_log/encoder/var_int.cc",
+ "rtc_event_log/encoder/var_int.h",
+ ]
+
+ defines = []
+
+ deps = [
+ "../rtc_base:bit_buffer",
+ "../rtc_base:bitstream_reader",
+ "../rtc_base:checks",
+ "../rtc_base:ignore_wundef",
+ "../rtc_base:macromagic",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
}
# TODO(eladalon): Break down into (1) encoder and (2) decoder; we don't need
@@ -176,21 +290,22 @@ rtc_library("rtc_event_log_impl_encoder") {
"rtc_event_log/encoder/blob_encoding.h",
"rtc_event_log/encoder/delta_encoding.cc",
"rtc_event_log/encoder/delta_encoding.h",
- "rtc_event_log/encoder/rtc_event_log_encoder_common.cc",
- "rtc_event_log/encoder/rtc_event_log_encoder_common.h",
- "rtc_event_log/encoder/var_int.cc",
- "rtc_event_log/encoder/var_int.h",
]
defines = []
deps = [
+ ":rtc_event_number_encodings",
"../api:rtp_headers",
"../api:rtp_parameters",
"../api/transport:network_control",
+ "../rtc_base:bit_buffer",
+ "../rtc_base:bitstream_reader",
+ "../rtc_base:buffer",
"../rtc_base:checks",
"../rtc_base:ignore_wundef",
- "../rtc_base:rtc_base_approved",
+ "../rtc_base:logging",
+ "../rtc_base:safe_conversions",
]
absl_deps = [
"//third_party/abseil-cpp/absl/memory",
@@ -202,7 +317,10 @@ rtc_library("rtc_event_log_impl_encoder") {
deps += [
":ice_log",
":rtc_event_audio",
+ ":rtc_event_begin_end",
":rtc_event_bwe",
+ ":rtc_event_field",
+ ":rtc_event_frame_events",
":rtc_event_generic_packet_events",
":rtc_event_log2_proto",
":rtc_event_log_api",
@@ -212,8 +330,8 @@ rtc_library("rtc_event_log_impl_encoder") {
":rtc_event_video",
":rtc_stream_config",
"../api:array_view",
+ "../api:network_state_predictor_api",
"../modules/audio_coding:audio_network_adaptor",
- "../modules/remote_bitrate_estimator",
"../modules/rtp_rtcp:rtp_rtcp_format",
]
sources += [
@@ -221,6 +339,8 @@ rtc_library("rtc_event_log_impl_encoder") {
"rtc_event_log/encoder/rtc_event_log_encoder_legacy.h",
"rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc",
"rtc_event_log/encoder/rtc_event_log_encoder_new_format.h",
+ "rtc_event_log/encoder/rtc_event_log_encoder_v3.cc",
+ "rtc_event_log/encoder/rtc_event_log_encoder_v3.h",
]
}
}
@@ -244,15 +364,24 @@ if (rtc_enable_protobuf) {
":rtc_event_log_api",
":rtc_event_log_impl_encoder",
"../api:libjingle_logging_api",
+ "../api:sequence_checker",
"../api/rtc_event_log",
"../api/task_queue",
+ "../api/units:time_delta",
"../rtc_base:checks",
- "../rtc_base:rtc_base_approved",
+ "../rtc_base:logging",
+ "../rtc_base:macromagic",
+ "../rtc_base:rtc_event",
"../rtc_base:rtc_task_queue",
+ "../rtc_base:safe_conversions",
"../rtc_base:safe_minmax",
- "../rtc_base/synchronization:sequence_checker",
+ "../rtc_base:timeutils",
+ "../rtc_base/system:no_unique_address",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/types:optional",
]
- absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
}
}
@@ -266,10 +395,10 @@ rtc_library("fake_rtc_event_log") {
]
deps = [
- ":ice_log",
"../api/rtc_event_log",
"../rtc_base",
- "../rtc_base:checks",
+ "../rtc_base:macromagic",
+ "../rtc_base/synchronization:mutex",
]
}
@@ -289,7 +418,6 @@ if (rtc_enable_protobuf) {
rtc_library("rtc_event_log_parser") {
visibility = [ "*" ]
sources = [
- "rtc_event_log/logged_events.cc",
"rtc_event_log/logged_events.h",
"rtc_event_log/rtc_event_log_parser.cc",
"rtc_event_log/rtc_event_log_parser.h",
@@ -299,34 +427,45 @@ if (rtc_enable_protobuf) {
deps = [
":ice_log",
+ ":rtc_event_audio",
+ ":rtc_event_begin_end",
":rtc_event_bwe",
+ ":rtc_event_frame_events",
+ ":rtc_event_generic_packet_events",
":rtc_event_log2_proto",
":rtc_event_log_impl_encoder",
":rtc_event_log_proto",
+ ":rtc_event_number_encodings",
+ ":rtc_event_pacing",
+ ":rtc_event_rtp_rtcp",
+ ":rtc_event_video",
":rtc_stream_config",
"../api:function_view",
+ "../api:network_state_predictor_api",
"../api:rtp_headers",
"../api:rtp_parameters",
"../api/rtc_event_log",
"../api/units:data_rate",
"../api/units:time_delta",
"../api/units:timestamp",
+ "../api/video:video_frame",
"../call:video_stream_api",
- "../modules:module_api",
"../modules:module_api_public",
"../modules/audio_coding:audio_network_adaptor",
- "../modules/remote_bitrate_estimator",
- "../modules/rtp_rtcp",
"../modules/rtp_rtcp:rtp_rtcp_format",
"../rtc_base:checks",
- "../rtc_base:deprecation",
+ "../rtc_base:copy_on_write_buffer",
"../rtc_base:ignore_wundef",
+ "../rtc_base:logging",
"../rtc_base:protobuf_utils",
- "../rtc_base:rtc_base_approved",
"../rtc_base:rtc_numerics",
+ "../rtc_base:safe_conversions",
+ "../rtc_base/system:file_wrapper",
]
absl_deps = [
+ "//third_party/abseil-cpp/absl/base:core_headers",
"//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
]
}
@@ -340,6 +479,8 @@ if (rtc_enable_protobuf) {
"rtc_event_log/encoder/delta_encoding_unittest.cc",
"rtc_event_log/encoder/rtc_event_log_encoder_common_unittest.cc",
"rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc",
+ "rtc_event_log/events/rtc_event_field_encoding_unittest.cc",
+ "rtc_event_log/events/rtc_event_field_extraction_unittest.cc",
"rtc_event_log/rtc_event_log_unittest.cc",
"rtc_event_log/rtc_event_log_unittest_helper.cc",
"rtc_event_log/rtc_event_log_unittest_helper.h",
@@ -349,61 +490,73 @@ if (rtc_enable_protobuf) {
":ice_log",
":rtc_event_audio",
":rtc_event_bwe",
+ ":rtc_event_field",
+ ":rtc_event_frame_events",
":rtc_event_generic_packet_events",
":rtc_event_log2_proto",
":rtc_event_log_impl_encoder",
":rtc_event_log_parser",
":rtc_event_log_proto",
+ ":rtc_event_number_encodings",
":rtc_event_pacing",
":rtc_event_rtp_rtcp",
":rtc_event_video",
":rtc_stream_config",
"../api:array_view",
+ "../api:network_state_predictor_api",
"../api:rtc_event_log_output_file",
"../api:rtp_headers",
"../api:rtp_parameters",
"../api/rtc_event_log",
"../api/rtc_event_log:rtc_event_log_factory",
"../api/task_queue:default_task_queue_factory",
+ "../api/units:time_delta",
+ "../api/units:timestamp",
"../call",
"../call:call_interfaces",
"../modules/audio_coding:audio_network_adaptor",
- "../modules/remote_bitrate_estimator",
"../modules/rtp_rtcp:rtp_rtcp_format",
+ "../rtc_base:buffer",
"../rtc_base:checks",
- "../rtc_base:rtc_base_approved",
+ "../rtc_base:macromagic",
+ "../rtc_base:random",
"../rtc_base:rtc_base_tests_utils",
+ "../rtc_base:timeutils",
"../system_wrappers",
"../test:fileutils",
"../test:test_support",
+ "../test/logging:log_writer",
"//testing/gtest",
]
absl_deps = [
"//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
]
}
- rtc_executable("rtc_event_log_rtp_dump") {
- testonly = true
- sources = [ "rtc_event_log/rtc_event_log2rtp_dump.cc" ]
- deps = [
- ":rtc_event_log_parser",
- "../api:array_view",
- "../api:rtp_headers",
- "../api/rtc_event_log",
- "../modules/rtp_rtcp",
- "../modules/rtp_rtcp:rtp_rtcp_format",
- "../rtc_base:checks",
- "../rtc_base:protobuf_utils",
- "../rtc_base:rtc_base_approved",
- "../test:rtp_test_utils",
- "//third_party/abseil-cpp/absl/flags:flag",
- "//third_party/abseil-cpp/absl/flags:parse",
- "//third_party/abseil-cpp/absl/flags:usage",
- "//third_party/abseil-cpp/absl/memory",
- "//third_party/abseil-cpp/absl/types:optional",
- ]
+ if (!build_with_chromium) {
+ rtc_executable("rtc_event_log_rtp_dump") {
+ testonly = true
+ sources = [ "rtc_event_log/rtc_event_log2rtp_dump.cc" ]
+ deps = [
+ ":rtc_event_log_parser",
+ "../api:array_view",
+ "../api:rtp_headers",
+ "../api/rtc_event_log",
+ "../modules/rtp_rtcp",
+ "../modules/rtp_rtcp:rtp_rtcp_format",
+ "../rtc_base:checks",
+ "../rtc_base:protobuf_utils",
+ "../test:rtp_test_utils",
+ "//third_party/abseil-cpp/absl/flags:flag",
+ "//third_party/abseil-cpp/absl/flags:parse",
+ "//third_party/abseil-cpp/absl/flags:usage",
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
+ "//third_party/abseil-cpp/absl/types:optional",
+ ]
+ }
}
}
}
@@ -423,12 +576,16 @@ rtc_library("ice_log") {
]
deps = [
+ ":rtc_event_field",
+ "../api:dtls_transport_interface",
"../api:libjingle_logging_api",
- "../api:libjingle_peerconnection_api", # For api/dtls_transport_interface.h
"../api/rtc_event_log",
- "../rtc_base:rtc_base_approved",
+ "../api/units:timestamp",
+ ]
+ absl_deps = [
+ "//third_party/abseil-cpp/absl/memory",
+ "//third_party/abseil-cpp/absl/strings",
]
- absl_deps = [ "//third_party/abseil-cpp/absl/memory" ]
}
if (rtc_include_tests) {
diff --git a/logging/g3doc/rtc_event_log.md b/logging/g3doc/rtc_event_log.md
new file mode 100644
index 0000000000..6b81de1066
--- /dev/null
+++ b/logging/g3doc/rtc_event_log.md
@@ -0,0 +1,85 @@
+# RTC event log
+
+<?% config.freshness.owner = 'terelius' %?>
+<?% config.freshness.reviewed = '2021-06-02' %?>
+
+## Overview
+
+RTC event logs can be enabled to capture in-depth inpformation about sent and
+received packets and the internal state of some WebRTC components. The logs are
+useful to understand network behavior and to debug issues around connectivity,
+bandwidth estimation and audio jitter buffers.
+
+The contents include:
+
+* Sent and received RTP headers
+* Full RTCP feedback
+* ICE candidates, pings and responses
+* Bandwidth estimator events, including loss-based estimate, delay-based
+ estimate, probe results and ALR state
+* Audio network adaptation settings
+* Audio playout events
+
+## Binary wire format
+
+No guarantees are made on the wire format, and the format may change without
+prior notice. To maintain compatibility with past and future formats, analysis
+tools should be built on top of the provided
+[rtc_event_log_parser.h](https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/logging/rtc_event_log/rtc_event_log_parser.h)
+
+In particular, an analysis tool should *not* read the log as a protobuf.
+
+## Visualization
+
+Since the logs contain a substantial amount of data, it is usually convenient to
+get an overview by visualizing them as a set of plots. Use the command:
+
+```
+out/Default/event_log_visualizer /path/to/log_file | python
+```
+
+This visualization requires matplotlib to be installed. The tool is capable of
+producing a substantial number of plots, of which only a handful are generated
+by default. You can select which plots are generated though the `--plot=`
+command line argument. For example, the command
+
+```
+out/Default/event_log_visualizer \
+ --plot=incoming_packet_sizes,incoming_stream_bitrate \
+ /path/to/log_file | python
+```
+
+plots the sizes of incoming packets and the bitrate per incoming stream.
+
+You can get a full list of options for the `--plot` argument through
+
+```
+out/Default/event_log_visualizer --list_plots /path/to/log_file
+```
+
+You can also synchronize the x-axis between all plots (so zooming or
+panning in one plot affects all of them), by adding the command line
+argument `--shared_xaxis`.
+
+
+## Viewing the raw log contents as text
+
+If you know which format version the log file uses, you can view the raw
+contents as text. For version 1, you can use the command
+
+```
+out/Default/protoc --decode webrtc.rtclog.EventStream \
+ ./logging/rtc_event_log/rtc_event_log.proto < /path/to/log_file
+```
+
+Similarly, you can use
+
+```
+out/Default/protoc --decode webrtc.rtclog2.EventStream \
+ ./logging/rtc_event_log/rtc_event_log2.proto < /path/to/log_file
+```
+
+for logs that use version 2. However, note that not all of the contents will be
+human readable. Some fields are based on the raw RTP format or may be encoded as
+deltas relative to previous fields. Such fields will be printed as a list of
+bytes.
diff --git a/logging/rtc_event_log/DEPS b/logging/rtc_event_log/DEPS
index 325114c199..fe8a9114ed 100644
--- a/logging/rtc_event_log/DEPS
+++ b/logging/rtc_event_log/DEPS
@@ -2,7 +2,6 @@ include_rules = [
"+call",
"+modules/audio_coding/audio_network_adaptor",
"+modules/congestion_controller",
- "+modules/remote_bitrate_estimator/include",
"+modules/rtp_rtcp",
"+system_wrappers",
]
diff --git a/logging/rtc_event_log/encoder/bit_writer.cc b/logging/rtc_event_log/encoder/bit_writer.cc
new file mode 100644
index 0000000000..e8748d3db3
--- /dev/null
+++ b/logging/rtc_event_log/encoder/bit_writer.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/encoder/bit_writer.h"
+
+namespace webrtc {
+
+namespace {
+size_t BitsToBytes(size_t bits) {
+ return (bits / 8) + (bits % 8 > 0 ? 1 : 0);
+}
+} // namespace
+
+void BitWriter::WriteBits(uint64_t val, size_t bit_count) {
+ RTC_DCHECK(valid_);
+ const bool success = bit_writer_.WriteBits(val, bit_count);
+ RTC_DCHECK(success);
+ written_bits_ += bit_count;
+}
+
+void BitWriter::WriteBits(absl::string_view input) {
+ RTC_DCHECK(valid_);
+ for (char c : input) {
+ WriteBits(static_cast<unsigned char>(c), CHAR_BIT);
+ }
+}
+
+// Returns everything that was written so far.
+// Nothing more may be written after this is called.
+std::string BitWriter::GetString() {
+ RTC_DCHECK(valid_);
+ valid_ = false;
+
+ buffer_.resize(BitsToBytes(written_bits_));
+ written_bits_ = 0;
+
+ std::string result;
+ std::swap(buffer_, result);
+ return result;
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/encoder/bit_writer.h b/logging/rtc_event_log/encoder/bit_writer.h
new file mode 100644
index 0000000000..421e7c4370
--- /dev/null
+++ b/logging/rtc_event_log/encoder/bit_writer.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_ENCODER_BIT_WRITER_H_
+#define LOGGING_RTC_EVENT_LOG_ENCODER_BIT_WRITER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+#include <utility>
+
+#include "absl/strings/string_view.h"
+#include "rtc_base/bit_buffer.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+// Wrap BitBufferWriter and extend its functionality by (1) keeping track of
+// the number of bits written and (2) owning its buffer.
+class BitWriter final {
+ public:
+ explicit BitWriter(size_t byte_count)
+ : buffer_(byte_count, '\0'),
+ bit_writer_(reinterpret_cast<uint8_t*>(&buffer_[0]), buffer_.size()),
+ written_bits_(0),
+ valid_(true) {
+ RTC_DCHECK_GT(byte_count, 0);
+ }
+
+ BitWriter(const BitWriter&) = delete;
+ BitWriter& operator=(const BitWriter&) = delete;
+
+ void WriteBits(uint64_t val, size_t bit_count);
+
+ void WriteBits(absl::string_view input);
+
+ // Returns everything that was written so far.
+ // Nothing more may be written after this is called.
+ std::string GetString();
+
+ private:
+ std::string buffer_;
+ rtc::BitBufferWriter bit_writer_;
+ // Note: Counting bits instead of bytes wraps around earlier than it has to,
+ // which means the maximum length is lower than it could be. We don't expect
+ // to go anywhere near the limit, though, so this is good enough.
+ size_t written_bits_;
+ bool valid_;
+};
+
+} // namespace webrtc
+
+#endif // LOGGING_RTC_EVENT_LOG_ENCODER_BIT_WRITER_H_
diff --git a/logging/rtc_event_log/encoder/blob_encoding.cc b/logging/rtc_event_log/encoder/blob_encoding.cc
index 48316b052b..96699dc96a 100644
--- a/logging/rtc_event_log/encoder/blob_encoding.cc
+++ b/logging/rtc_event_log/encoder/blob_encoding.cc
@@ -58,49 +58,30 @@ std::vector<absl::string_view> DecodeBlobs(absl::string_view encoded_blobs,
return std::vector<absl::string_view>();
}
- size_t read_idx = 0;
-
// Read the lengths of all blobs.
std::vector<uint64_t> lengths(num_of_blobs);
for (size_t i = 0; i < num_of_blobs; ++i) {
- if (read_idx >= encoded_blobs.length()) {
- RTC_DCHECK_EQ(read_idx, encoded_blobs.length());
- RTC_LOG(LS_WARNING) << "Corrupt input; excessive number of blobs.";
- return std::vector<absl::string_view>();
- }
-
- const size_t read_bytes =
- DecodeVarInt(encoded_blobs.substr(read_idx), &lengths[i]);
- if (read_bytes == 0) {
+ bool success = false;
+ std::tie(success, encoded_blobs) = DecodeVarInt(encoded_blobs, &lengths[i]);
+ if (!success) {
RTC_LOG(LS_WARNING) << "Corrupt input; varint decoding failed.";
return std::vector<absl::string_view>();
}
-
- read_idx += read_bytes;
-
- // Note: It might be that read_idx == encoded_blobs.length(), if this
- // is the last iteration, and all of the blobs are the empty string.
- RTC_DCHECK_LE(read_idx, encoded_blobs.length());
}
// Read the blobs themselves.
std::vector<absl::string_view> blobs(num_of_blobs);
for (size_t i = 0; i < num_of_blobs; ++i) {
- if (read_idx + lengths[i] < read_idx) { // Wrap-around detection.
- RTC_LOG(LS_WARNING) << "Corrupt input; unreasonably large blob sequence.";
- return std::vector<absl::string_view>();
- }
-
- if (read_idx + lengths[i] > encoded_blobs.length()) {
+ if (lengths[i] > encoded_blobs.length()) {
RTC_LOG(LS_WARNING) << "Corrupt input; blob sizes exceed input size.";
return std::vector<absl::string_view>();
}
- blobs[i] = encoded_blobs.substr(read_idx, lengths[i]);
- read_idx += lengths[i];
+ blobs[i] = encoded_blobs.substr(0, lengths[i]);
+ encoded_blobs = encoded_blobs.substr(lengths[i]);
}
- if (read_idx != encoded_blobs.length()) {
+ if (!encoded_blobs.empty()) {
RTC_LOG(LS_WARNING) << "Corrupt input; unrecognized trailer.";
return std::vector<absl::string_view>();
}
diff --git a/logging/rtc_event_log/encoder/blob_encoding.h b/logging/rtc_event_log/encoder/blob_encoding.h
index b5b589aaf6..123fffe8e8 100644
--- a/logging/rtc_event_log/encoder/blob_encoding.h
+++ b/logging/rtc_event_log/encoder/blob_encoding.h
@@ -32,13 +32,13 @@ namespace webrtc {
// EncodeBlobs() may not fail.
// EncodeBlobs() never returns the empty string.
//
-// Calling DecodeBlobs() on an empty string, or with |num_of_blobs| set to 0,
+// Calling DecodeBlobs() on an empty string, or with `num_of_blobs` set to 0,
// is an error.
// DecodeBlobs() returns an empty vector if it fails, e.g. due to a mismatch
-// between |num_of_blobs| and |encoded_blobs|, which can happen if
-// |encoded_blobs| is corrupted.
+// between `num_of_blobs` and `encoded_blobs`, which can happen if
+// `encoded_blobs` is corrupted.
// When successful, DecodeBlobs() returns a vector of string_view objects,
-// which refer to the original input (|encoded_blobs|), and therefore may
+// which refer to the original input (`encoded_blobs`), and therefore may
// not outlive it.
//
// Note that the returned std::string might have been reserved for significantly
diff --git a/logging/rtc_event_log/encoder/delta_encoding.cc b/logging/rtc_event_log/encoder/delta_encoding.cc
index 022fb9c163..c80424574c 100644
--- a/logging/rtc_event_log/encoder/delta_encoding.cc
+++ b/logging/rtc_event_log/encoder/delta_encoding.cc
@@ -16,10 +16,12 @@
#include <utility>
#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
+#include "logging/rtc_event_log/encoder/bit_writer.h"
#include "logging/rtc_event_log/encoder/var_int.h"
#include "rtc_base/bit_buffer.h"
+#include "rtc_base/bitstream_reader.h"
#include "rtc_base/checks.h"
-#include "rtc_base/constructor_magic.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
@@ -71,8 +73,8 @@ uint64_t MaxUnsignedValueOfBitWidth(uint64_t bit_width) {
: ((static_cast<uint64_t>(1) << bit_width) - 1);
}
-// Computes the delta between |previous| and |current|, under the assumption
-// that wrap-around occurs after |width| is exceeded.
+// Computes the delta between `previous` and `current`, under the assumption
+// that wrap-around occurs after `width` is exceeded.
uint64_t UnsignedDelta(uint64_t previous, uint64_t current, uint64_t bit_mask) {
return (current - previous) & bit_mask;
}
@@ -106,58 +108,6 @@ constexpr bool kDefaultSignedDeltas = false;
constexpr bool kDefaultValuesOptional = false;
constexpr uint64_t kDefaultValueWidthBits = 64;
-// Wrap BitBufferWriter and extend its functionality by (1) keeping track of
-// the number of bits written and (2) owning its buffer.
-class BitWriter final {
- public:
- explicit BitWriter(size_t byte_count)
- : buffer_(byte_count, '\0'),
- bit_writer_(reinterpret_cast<uint8_t*>(&buffer_[0]), buffer_.size()),
- written_bits_(0),
- valid_(true) {
- RTC_DCHECK_GT(byte_count, 0);
- }
-
- void WriteBits(uint64_t val, size_t bit_count) {
- RTC_DCHECK(valid_);
- const bool success = bit_writer_.WriteBits(val, bit_count);
- RTC_DCHECK(success);
- written_bits_ += bit_count;
- }
-
- void WriteBits(const std::string& input) {
- RTC_DCHECK(valid_);
- for (std::string::value_type c : input) {
- WriteBits(c, 8 * sizeof(std::string::value_type));
- }
- }
-
- // Returns everything that was written so far.
- // Nothing more may be written after this is called.
- std::string GetString() {
- RTC_DCHECK(valid_);
- valid_ = false;
-
- buffer_.resize(BitsToBytes(written_bits_));
- written_bits_ = 0;
-
- std::string result;
- std::swap(buffer_, result);
- return result;
- }
-
- private:
- std::string buffer_;
- rtc::BitBufferWriter bit_writer_;
- // Note: Counting bits instead of bytes wraps around earlier than it has to,
- // which means the maximum length is lower than it could be. We don't expect
- // to go anywhere near the limit, though, so this is good enough.
- size_t written_bits_;
- bool valid_;
-
- RTC_DISALLOW_COPY_AND_ASSIGN(BitWriter);
-};
-
// Parameters for fixed-size delta-encoding/decoding.
// These are tailored for the sequence which will be encoded (e.g. widths).
class FixedLengthEncodingParameters final {
@@ -237,6 +187,9 @@ class FixedLengthDeltaEncoder final {
absl::optional<uint64_t> base,
const std::vector<absl::optional<uint64_t>>& values);
+ FixedLengthDeltaEncoder(const FixedLengthDeltaEncoder&) = delete;
+ FixedLengthDeltaEncoder& operator=(const FixedLengthDeltaEncoder&) = delete;
+
private:
// Calculate min/max values of unsigned/signed deltas, given the bit width
// of all the values in the series.
@@ -258,7 +211,7 @@ class FixedLengthDeltaEncoder final {
// released by it before it returns. They're mostly a convenient way to
// avoid having to pass a lot of state between different functions.
// Therefore, it was deemed acceptable to let them have a reference to
- // |values|, whose lifetime must exceed the lifetime of |this|.
+ // `values`, whose lifetime must exceed the lifetime of `this`.
FixedLengthDeltaEncoder(const FixedLengthEncodingParameters& params,
absl::optional<uint64_t> base,
const std::vector<absl::optional<uint64_t>>& values,
@@ -287,7 +240,7 @@ class FixedLengthDeltaEncoder final {
// The encoding scheme assumes that at least one value is transmitted OOB,
// so that the first value can be encoded as a delta from that OOB value,
- // which is |base_|.
+ // which is `base_`.
const absl::optional<uint64_t> base_;
// The values to be encoded.
@@ -299,8 +252,6 @@ class FixedLengthDeltaEncoder final {
// ctor has finished running when this is constructed, so that the lower
// bound on the buffer size would be guaranteed correct.
std::unique_ptr<BitWriter> writer_;
-
- RTC_DISALLOW_COPY_AND_ASSIGN(FixedLengthDeltaEncoder);
};
// TODO(eladalon): Reduce the number of passes.
@@ -604,39 +555,42 @@ class FixedLengthDeltaDecoder final {
// bitstream. Note that this does NOT imply that stream is valid, and will
// be decoded successfully. It DOES imply that all other decoder classes
// will fail to decode this input, though.
- static bool IsSuitableDecoderFor(const std::string& input);
+ static bool IsSuitableDecoderFor(absl::string_view input);
- // Assuming that |input| is the result of fixed-size delta-encoding
- // that took place with the same value to |base| and over |num_of_deltas|
+ // Assuming that `input` is the result of fixed-size delta-encoding
+ // that took place with the same value to `base` and over `num_of_deltas`
// original values, this will return the sequence of original values.
- // If an error occurs (can happen if |input| is corrupt), an empty
+ // If an error occurs (can happen if `input` is corrupt), an empty
// vector will be returned.
static std::vector<absl::optional<uint64_t>> DecodeDeltas(
- const std::string& input,
+ absl::string_view input,
absl::optional<uint64_t> base,
size_t num_of_deltas);
+ FixedLengthDeltaDecoder(const FixedLengthDeltaDecoder&) = delete;
+ FixedLengthDeltaDecoder& operator=(const FixedLengthDeltaDecoder&) = delete;
+
private:
- // Reads the encoding header in |input| and returns a FixedLengthDeltaDecoder
+ // Reads the encoding header in `input` and returns a FixedLengthDeltaDecoder
// with the corresponding configuration, that can be used to decode the
- // values in |input|.
+ // values in `input`.
// If the encoding header is corrupt (contains an illegal configuration),
// nullptr will be returned.
// When a valid FixedLengthDeltaDecoder is returned, this does not mean that
// the entire stream is free of error. Rather, only the encoding header is
// examined and guaranteed.
static std::unique_ptr<FixedLengthDeltaDecoder> Create(
- const std::string& input,
+ absl::string_view input,
absl::optional<uint64_t> base,
size_t num_of_deltas);
// FixedLengthDeltaDecoder objects are to be created by DecodeDeltas() and
// released by it before it returns. They're mostly a convenient way to
// avoid having to pass a lot of state between different functions.
- // Therefore, it was deemed acceptable that |reader| does not own the buffer
- // it reads, meaning the lifetime of |this| must not exceed the lifetime
- // of |reader|'s underlying buffer.
- FixedLengthDeltaDecoder(std::unique_ptr<rtc::BitBuffer> reader,
+ // Therefore, it was deemed acceptable that `reader` does not own the buffer
+ // it reads, meaning the lifetime of `this` must not exceed the lifetime
+ // of `reader`'s underlying buffer.
+ FixedLengthDeltaDecoder(BitstreamReader reader,
const FixedLengthEncodingParameters& params,
absl::optional<uint64_t> base,
size_t num_of_deltas);
@@ -644,17 +598,7 @@ class FixedLengthDeltaDecoder final {
// Perform the decoding using the parameters given to the ctor.
std::vector<absl::optional<uint64_t>> Decode();
- // Decode a varint and write it to |output|. Return value indicates success
- // or failure. In case of failure, no guarantees are made about the contents
- // of |output| or the results of additional reads.
- bool ParseVarInt(uint64_t* output);
-
- // Attempt to parse a delta from the input reader.
- // Returns true/false for success/failure.
- // Writes the delta into |delta| if successful.
- bool ParseDelta(uint64_t* delta);
-
- // Add |delta| to |base| to produce the next value in a sequence.
+ // Add `delta` to `base` to produce the next value in a sequence.
// The delta is applied as signed/unsigned depending on the parameters
// given to the ctor. Wrap-around is taken into account according to the
// values' width, as specified by the aforementioned encoding parameters.
@@ -666,7 +610,7 @@ class FixedLengthDeltaDecoder final {
// Reader of the input stream to be decoded. Does not own that buffer.
// See comment above ctor for details.
- const std::unique_ptr<rtc::BitBuffer> reader_;
+ BitstreamReader reader_;
// The parameters according to which encoding will be done (width of
// fields, whether signed deltas should be used, etc.)
@@ -674,28 +618,20 @@ class FixedLengthDeltaDecoder final {
// The encoding scheme assumes that at least one value is transmitted OOB,
// so that the first value can be encoded as a delta from that OOB value,
- // which is |base_|.
+ // which is `base_`.
const absl::optional<uint64_t> base_;
// The number of values to be known to be decoded.
const size_t num_of_deltas_;
-
- RTC_DISALLOW_COPY_AND_ASSIGN(FixedLengthDeltaDecoder);
};
-bool FixedLengthDeltaDecoder::IsSuitableDecoderFor(const std::string& input) {
- if (input.length() < kBitsInHeaderForEncodingType) {
+bool FixedLengthDeltaDecoder::IsSuitableDecoderFor(absl::string_view input) {
+ BitstreamReader reader(input);
+ uint64_t encoding_type_bits = reader.ReadBits(kBitsInHeaderForEncodingType);
+ if (!reader.Ok()) {
return false;
}
- rtc::BitBuffer reader(reinterpret_cast<const uint8_t*>(&input[0]),
- kBitsInHeaderForEncodingType);
-
- uint32_t encoding_type_bits;
- const bool result =
- reader.ReadBits(&encoding_type_bits, kBitsInHeaderForEncodingType);
- RTC_DCHECK(result);
-
const auto encoding_type = static_cast<EncodingType>(encoding_type_bits);
return encoding_type ==
EncodingType::kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt ||
@@ -704,7 +640,7 @@ bool FixedLengthDeltaDecoder::IsSuitableDecoderFor(const std::string& input) {
}
std::vector<absl::optional<uint64_t>> FixedLengthDeltaDecoder::DecodeDeltas(
- const std::string& input,
+ absl::string_view input,
absl::optional<uint64_t> base,
size_t num_of_deltas) {
auto decoder = FixedLengthDeltaDecoder::Create(input, base, num_of_deltas);
@@ -716,21 +652,16 @@ std::vector<absl::optional<uint64_t>> FixedLengthDeltaDecoder::DecodeDeltas(
}
std::unique_ptr<FixedLengthDeltaDecoder> FixedLengthDeltaDecoder::Create(
- const std::string& input,
+ absl::string_view input,
absl::optional<uint64_t> base,
size_t num_of_deltas) {
- if (input.length() < kBitsInHeaderForEncodingType) {
+ BitstreamReader reader(input);
+ // Encoding type
+ uint32_t encoding_type_bits = reader.ReadBits(kBitsInHeaderForEncodingType);
+ if (!reader.Ok()) {
return nullptr;
}
- auto reader = std::make_unique<rtc::BitBuffer>(
- reinterpret_cast<const uint8_t*>(&input[0]), input.length());
-
- // Encoding type
- uint32_t encoding_type_bits;
- const bool result =
- reader->ReadBits(&encoding_type_bits, kBitsInHeaderForEncodingType);
- RTC_DCHECK(result);
const EncodingType encoding = static_cast<EncodingType>(encoding_type_bits);
if (encoding != EncodingType::kFixedSizeUnsignedDeltasNoEarlyWrapNoOpt &&
encoding !=
@@ -739,15 +670,10 @@ std::unique_ptr<FixedLengthDeltaDecoder> FixedLengthDeltaDecoder::Create(
return nullptr;
}
- uint32_t read_buffer;
-
- // delta_width_bits
- if (!reader->ReadBits(&read_buffer, kBitsInHeaderForDeltaWidthBits)) {
- return nullptr;
- }
- RTC_DCHECK_LE(read_buffer, 64 - 1); // See encoding for -1's rationale.
+ // See encoding for +1's rationale.
const uint64_t delta_width_bits =
- read_buffer + 1; // See encoding for +1's rationale.
+ reader.ReadBits(kBitsInHeaderForDeltaWidthBits) + 1;
+ RTC_DCHECK_LE(delta_width_bits, 64);
// signed_deltas, values_optional, value_width_bits
bool signed_deltas;
@@ -758,25 +684,15 @@ std::unique_ptr<FixedLengthDeltaDecoder> FixedLengthDeltaDecoder::Create(
values_optional = kDefaultValuesOptional;
value_width_bits = kDefaultValueWidthBits;
} else {
- // signed_deltas
- if (!reader->ReadBits(&read_buffer, kBitsInHeaderForSignedDeltas)) {
- return nullptr;
- }
- signed_deltas = rtc::dchecked_cast<bool>(read_buffer);
-
- // values_optional
- if (!reader->ReadBits(&read_buffer, kBitsInHeaderForValuesOptional)) {
- return nullptr;
- }
- RTC_DCHECK_LE(read_buffer, 1);
- values_optional = rtc::dchecked_cast<bool>(read_buffer);
+ signed_deltas = reader.Read<bool>();
+ values_optional = reader.Read<bool>();
+ // See encoding for +1's rationale.
+ value_width_bits = reader.ReadBits(kBitsInHeaderForValueWidthBits) + 1;
+ RTC_DCHECK_LE(value_width_bits, 64);
+ }
- // value_width_bits
- if (!reader->ReadBits(&read_buffer, kBitsInHeaderForValueWidthBits)) {
- return nullptr;
- }
- RTC_DCHECK_LE(read_buffer, 64 - 1); // See encoding for -1's rationale.
- value_width_bits = read_buffer + 1; // See encoding for +1's rationale.
+ if (!reader.Ok()) {
+ return nullptr;
}
// Note: Because of the way the parameters are read, it is not possible
@@ -790,35 +706,28 @@ std::unique_ptr<FixedLengthDeltaDecoder> FixedLengthDeltaDecoder::Create(
FixedLengthEncodingParameters params(delta_width_bits, signed_deltas,
values_optional, value_width_bits);
- return absl::WrapUnique(new FixedLengthDeltaDecoder(std::move(reader), params,
- base, num_of_deltas));
+ return absl::WrapUnique(
+ new FixedLengthDeltaDecoder(reader, params, base, num_of_deltas));
}
FixedLengthDeltaDecoder::FixedLengthDeltaDecoder(
- std::unique_ptr<rtc::BitBuffer> reader,
+ BitstreamReader reader,
const FixedLengthEncodingParameters& params,
absl::optional<uint64_t> base,
size_t num_of_deltas)
- : reader_(std::move(reader)),
+ : reader_(reader),
params_(params),
base_(base),
num_of_deltas_(num_of_deltas) {
- RTC_DCHECK(reader_);
+ RTC_DCHECK(reader_.Ok());
}
std::vector<absl::optional<uint64_t>> FixedLengthDeltaDecoder::Decode() {
- RTC_DCHECK(reader_);
-
+ RTC_DCHECK(reader_.Ok());
std::vector<bool> existing_values(num_of_deltas_);
if (params_.values_optional()) {
for (size_t i = 0; i < num_of_deltas_; ++i) {
- uint32_t exists;
- if (!reader_->ReadBits(&exists, 1u)) {
- RTC_LOG(LS_WARNING) << "Failed to read existence-indicating bit.";
- return std::vector<absl::optional<uint64_t>>();
- }
- RTC_DCHECK_LE(exists, 1u);
- existing_values[i] = (exists == 1);
+ existing_values[i] = reader_.Read<bool>();
}
} else {
std::fill(existing_values.begin(), existing_values.end(), true);
@@ -837,64 +746,20 @@ std::vector<absl::optional<uint64_t>> FixedLengthDeltaDecoder::Decode() {
// If the base is non-existent, the first existent value is encoded as
// a varint, rather than as a delta.
RTC_DCHECK(!base_.has_value());
- uint64_t first_value;
- if (!ParseVarInt(&first_value)) {
- RTC_LOG(LS_WARNING) << "Failed to read first value.";
- return std::vector<absl::optional<uint64_t>>();
- }
- values[i] = first_value;
+ values[i] = DecodeVarInt(reader_);
} else {
- uint64_t delta;
- if (!ParseDelta(&delta)) {
- return std::vector<absl::optional<uint64_t>>();
- }
- values[i] = ApplyDelta(previous.value(), delta);
+ uint64_t delta = reader_.ReadBits(params_.delta_width_bits());
+ values[i] = ApplyDelta(*previous, delta);
}
previous = values[i];
}
- return values;
-}
-
-bool FixedLengthDeltaDecoder::ParseVarInt(uint64_t* output) {
- RTC_DCHECK(reader_);
- return DecodeVarInt(reader_.get(), output) != 0;
-}
-
-bool FixedLengthDeltaDecoder::ParseDelta(uint64_t* delta) {
- RTC_DCHECK(reader_);
-
- // BitBuffer and BitBufferWriter read/write higher bits before lower bits.
-
- const size_t lower_bit_count =
- std::min<uint64_t>(params_.delta_width_bits(), 32u);
- const size_t higher_bit_count = (params_.delta_width_bits() <= 32u)
- ? 0
- : params_.delta_width_bits() - 32u;
-
- uint32_t lower_bits;
- uint32_t higher_bits;
-
- if (higher_bit_count > 0) {
- if (!reader_->ReadBits(&higher_bits, higher_bit_count)) {
- RTC_LOG(LS_WARNING) << "Failed to read higher half of delta.";
- return false;
- }
- } else {
- higher_bits = 0;
- }
-
- if (!reader_->ReadBits(&lower_bits, lower_bit_count)) {
- RTC_LOG(LS_WARNING) << "Failed to read lower half of delta.";
- return false;
+ if (!reader_.Ok()) {
+ values = {};
}
- const uint64_t lower_bits_64 = static_cast<uint64_t>(lower_bits);
- const uint64_t higher_bits_64 = static_cast<uint64_t>(higher_bits);
-
- *delta = (higher_bits_64 << 32) | lower_bits_64;
- return true;
+ return values;
}
uint64_t FixedLengthDeltaDecoder::ApplyDelta(uint64_t base,
@@ -940,7 +805,7 @@ std::string EncodeDeltas(absl::optional<uint64_t> base,
}
std::vector<absl::optional<uint64_t>> DecodeDeltas(
- const std::string& input,
+ absl::string_view input,
absl::optional<uint64_t> base,
size_t num_of_deltas) {
RTC_DCHECK_GT(num_of_deltas, 0); // Allows empty vector to indicate error.
diff --git a/logging/rtc_event_log/encoder/delta_encoding.h b/logging/rtc_event_log/encoder/delta_encoding.h
index 5e86a986f6..779cdc6b2f 100644
--- a/logging/rtc_event_log/encoder/delta_encoding.h
+++ b/logging/rtc_event_log/encoder/delta_encoding.h
@@ -17,14 +17,15 @@
#include <string>
#include <vector>
+#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
namespace webrtc {
-// Encode |values| as a sequence of deltas following on |base| and return it.
+// Encode `values` as a sequence of deltas following on `base` and return it.
// If all of the values were equal to the base, an empty string will be
// returned; this is a valid encoding of that edge case.
-// |base| is not guaranteed to be written into |output|, and must therefore
+// `base` is not guaranteed to be written into `output`, and must therefore
// be provided separately to the decoder.
// This function never fails.
// TODO(eladalon): Split into optional and non-optional variants (efficiency).
@@ -34,12 +35,12 @@ std::string EncodeDeltas(absl::optional<uint64_t> base,
// EncodeDeltas() and DecodeDeltas() are inverse operations;
// invoking DecodeDeltas() over the output of EncodeDeltas(), will return
// the input originally given to EncodeDeltas().
-// |num_of_deltas| must be greater than zero. If input is not a valid encoding
-// of |num_of_deltas| elements based on |base|, the function returns an empty
+// `num_of_deltas` must be greater than zero. If input is not a valid encoding
+// of `num_of_deltas` elements based on `base`, the function returns an empty
// vector, which signals an error.
// TODO(eladalon): Split into optional and non-optional variants (efficiency).
std::vector<absl::optional<uint64_t>> DecodeDeltas(
- const std::string& input,
+ absl::string_view input,
absl::optional<uint64_t> base,
size_t num_of_deltas);
diff --git a/logging/rtc_event_log/encoder/delta_encoding_unittest.cc b/logging/rtc_event_log/encoder/delta_encoding_unittest.cc
index b385b8998a..d0f7fb93db 100644
--- a/logging/rtc_event_log/encoder/delta_encoding_unittest.cc
+++ b/logging/rtc_event_log/encoder/delta_encoding_unittest.cc
@@ -44,7 +44,7 @@ void MaybeSetSignedness(DeltaSignedness signedness) {
SetFixedLengthEncoderDeltaSignednessForTesting(true);
return;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
uint64_t RandomWithMaxBitWidth(Random* prng, uint64_t max_width) {
@@ -64,9 +64,9 @@ uint64_t RandomWithMaxBitWidth(Random* prng, uint64_t max_width) {
}
}
-// Encodes |values| based on |base|, then decodes the result and makes sure
+// Encodes `values` based on `base`, then decodes the result and makes sure
// that it is equal to the original input.
-// If |encoded_string| is non-null, the encoded result will also be written
+// If `encoded_string` is non-null, the encoded result will also be written
// into it.
void TestEncodingAndDecoding(
absl::optional<uint64_t> base,
@@ -100,7 +100,7 @@ std::vector<absl::optional<uint64_t>> CreateSequenceByLastValue(
return result;
}
-// If |sequence_length| is greater than the number of deltas, the sequence of
+// If `sequence_length` is greater than the number of deltas, the sequence of
// deltas will wrap around.
std::vector<absl::optional<uint64_t>> CreateSequenceByOptionalDeltas(
uint64_t first,
@@ -141,7 +141,7 @@ size_t EncodingLengthUpperBound(size_t delta_max_bit_width,
return delta_max_bit_width * num_of_deltas + *smallest_header_size_bytes;
}
-// If |sequence_length| is greater than the number of deltas, the sequence of
+// If `sequence_length` is greater than the number of deltas, the sequence of
// deltas will wrap around.
std::vector<absl::optional<uint64_t>> CreateSequenceByDeltas(
uint64_t first,
@@ -502,7 +502,7 @@ TEST_P(DeltaEncodingCompressionQualityTest,
uint64_t last_element[arraysize(bases)];
memcpy(last_element, bases, sizeof(bases));
- // Avoid empty |deltas| due to first element causing wrap-around.
+ // Avoid empty `deltas` due to first element causing wrap-around.
deltas[0] = 1;
for (size_t i = 0; i < arraysize(last_element); ++i) {
last_element[i] += 1;
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h b/logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h
index 429f8ed2ad..c167a8eb8f 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h
@@ -55,7 +55,7 @@ uint64_t ToUnsigned(T y) {
}
}
-// Assuming x = ToUnsigned(y), return |y|.
+// Assuming x = ToUnsigned(y), return `y`.
// Note: static_cast<T>(x) would work on most platforms and compilers, but
// involves undefined behavior. This function is well-defined, and can be
// optimized to a noop for 64 bit types, or a few arithmetic
@@ -74,7 +74,7 @@ bool ToSigned(uint64_t x, T* y) {
using UNSIGNED_T = typename std::make_unsigned<T>::type;
constexpr auto MAX_UNSIGNED_T = std::numeric_limits<UNSIGNED_T>::max();
if (x > static_cast<uint64_t>(MAX_UNSIGNED_T)) {
- return false; // |x| cannot be represented using a T.
+ return false; // `x` cannot be represented using a T.
}
if (x <= static_cast<uint64_t>(MAX_T)) {
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
index 2f1c5a4533..9bc770849c 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.cc
@@ -15,6 +15,8 @@
#include <vector>
#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/network_state_predictor.h"
#include "api/rtp_headers.h"
#include "api/rtp_parameters.h"
#include "api/transport/network_types.h"
@@ -30,6 +32,7 @@
#include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
+#include "logging/rtc_event_log/events/rtc_event_remote_estimate.h"
#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h"
#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h"
#include "logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h"
@@ -38,12 +41,10 @@
#include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
#include "logging/rtc_event_log/rtc_stream_config.h"
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtcp_packet/app.h"
#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h"
#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
#include "modules/rtp_rtcp/source/rtcp_packet/psfb.h"
#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
@@ -77,9 +78,9 @@ rtclog::DelayBasedBweUpdate::DetectorState ConvertDetectorState(
case BandwidthUsage::kBwOverusing:
return rtclog::DelayBasedBweUpdate::BWE_OVERUSING;
case BandwidthUsage::kLast:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog::DelayBasedBweUpdate::BWE_NORMAL;
}
@@ -93,9 +94,9 @@ rtclog::BweProbeResult::ResultType ConvertProbeResultType(
case ProbeFailureReason::kTimeout:
return rtclog::BweProbeResult::TIMEOUT;
case ProbeFailureReason::kLast:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog::BweProbeResult::SUCCESS;
}
@@ -106,9 +107,9 @@ rtclog::VideoReceiveConfig_RtcpMode ConvertRtcpMode(RtcpMode rtcp_mode) {
case RtcpMode::kReducedSize:
return rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE;
case RtcpMode::kOff:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog::VideoReceiveConfig::RTCP_COMPOUND;
}
@@ -124,9 +125,9 @@ ConvertIceCandidatePairConfigType(IceCandidatePairConfigType type) {
case IceCandidatePairConfigType::kSelected:
return rtclog::IceCandidatePairConfig::SELECTED;
case IceCandidatePairConfigType::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog::IceCandidatePairConfig::ADDED;
}
@@ -144,9 +145,9 @@ rtclog::IceCandidatePairConfig::IceCandidateType ConvertIceCandidateType(
case IceCandidateType::kRelay:
return rtclog::IceCandidatePairConfig::RELAY;
case IceCandidateType::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE;
}
@@ -164,9 +165,9 @@ rtclog::IceCandidatePairConfig::Protocol ConvertIceCandidatePairProtocol(
case IceCandidatePairProtocol::kTls:
return rtclog::IceCandidatePairConfig::TLS;
case IceCandidatePairProtocol::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog::IceCandidatePairConfig::UNKNOWN_PROTOCOL;
}
@@ -181,9 +182,9 @@ ConvertIceCandidatePairAddressFamily(
case IceCandidatePairAddressFamily::kIpv6:
return rtclog::IceCandidatePairConfig::IPV6;
case IceCandidatePairAddressFamily::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY;
}
@@ -203,9 +204,9 @@ rtclog::IceCandidatePairConfig::NetworkType ConvertIceCandidateNetworkType(
case IceCandidateNetworkType::kCellular:
return rtclog::IceCandidatePairConfig::CELLULAR;
case IceCandidateNetworkType::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE;
}
@@ -221,9 +222,9 @@ ConvertIceCandidatePairEventType(IceCandidatePairEventType type) {
case IceCandidatePairEventType::kCheckResponseReceived:
return rtclog::IceCandidatePairEvent::CHECK_RESPONSE_RECEIVED;
case IceCandidatePairEventType::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog::IceCandidatePairEvent::CHECK_SENT;
}
@@ -331,6 +332,11 @@ std::string RtcEventLogEncoderLegacy::Encode(const RtcEvent& event) {
return EncodeProbeResultSuccess(rtc_event);
}
+ case RtcEvent::Type::RemoteEstimateEvent: {
+ auto& rtc_event = static_cast<const RtcEventRemoteEstimate&>(event);
+ return EncodeRemoteEstimate(rtc_event);
+ }
+
case RtcEvent::Type::RtcpPacketIncoming: {
auto& rtc_event = static_cast<const RtcEventRtcpPacketIncoming&>(event);
return EncodeRtcpPacketIncoming(rtc_event);
@@ -362,17 +368,23 @@ std::string RtcEventLogEncoderLegacy::Encode(const RtcEvent& event) {
static_cast<const RtcEventVideoSendStreamConfig&>(event);
return EncodeVideoSendStreamConfig(rtc_event);
}
+ case RtcEvent::Type::BeginV3Log:
+ case RtcEvent::Type::EndV3Log:
+ // These special events are written as part of starting
+ // and stopping the log, and only as part of version 3 of the format.
+ RTC_DCHECK_NOTREACHED();
+ break;
case RtcEvent::Type::RouteChangeEvent:
- case RtcEvent::Type::RemoteEstimateEvent:
case RtcEvent::Type::GenericPacketReceived:
case RtcEvent::Type::GenericPacketSent:
case RtcEvent::Type::GenericAckReceived:
+ case RtcEvent::Type::FrameDecoded:
// These are unsupported in the old format, but shouldn't crash.
return "";
}
int event_type = static_cast<int>(event.GetType());
- RTC_NOTREACHED() << "Unknown event type (" << event_type << ")";
+ RTC_DCHECK_NOTREACHED() << "Unknown event type (" << event_type << ")";
return "";
}
@@ -580,6 +592,23 @@ std::string RtcEventLogEncoderLegacy::EncodeProbeResultSuccess(
return Serialize(&rtclog_event);
}
+std::string RtcEventLogEncoderLegacy::EncodeRemoteEstimate(
+ const RtcEventRemoteEstimate& event) {
+ rtclog::Event rtclog_event;
+ rtclog_event.set_timestamp_us(event.timestamp_us());
+ rtclog_event.set_type(rtclog::Event::REMOTE_ESTIMATE);
+
+ auto* remote_estimate = rtclog_event.mutable_remote_estimate();
+ if (event.link_capacity_lower_.IsFinite())
+ remote_estimate->set_link_capacity_lower_kbps(
+ event.link_capacity_lower_.kbps<uint32_t>());
+ if (event.link_capacity_upper_.IsFinite())
+ remote_estimate->set_link_capacity_upper_kbps(
+ event.link_capacity_upper_.kbps<uint32_t>());
+
+ return Serialize(&rtclog_event);
+}
+
std::string RtcEventLogEncoderLegacy::EncodeRtcpPacketIncoming(
const RtcEventRtcpPacketIncoming& event) {
return EncodeRtcpPacket(event.timestamp_us(), event.packet(), true);
@@ -592,14 +621,14 @@ std::string RtcEventLogEncoderLegacy::EncodeRtcpPacketOutgoing(
std::string RtcEventLogEncoderLegacy::EncodeRtpPacketIncoming(
const RtcEventRtpPacketIncoming& event) {
- return EncodeRtpPacket(event.timestamp_us(), event.header(),
+ return EncodeRtpPacket(event.timestamp_us(), event.RawHeader(),
event.packet_length(), PacedPacketInfo::kNotAProbe,
true);
}
std::string RtcEventLogEncoderLegacy::EncodeRtpPacketOutgoing(
const RtcEventRtpPacketOutgoing& event) {
- return EncodeRtpPacket(event.timestamp_us(), event.header(),
+ return EncodeRtpPacket(event.timestamp_us(), event.RawHeader(),
event.packet_length(), event.probe_cluster_id(),
false);
}
@@ -672,7 +701,7 @@ std::string RtcEventLogEncoderLegacy::EncodeVideoSendStreamConfig(
encoder->set_payload_type(codec.payload_type);
if (event.config().codecs.size() > 1) {
- RTC_LOG(WARNING)
+ RTC_LOG(LS_WARNING)
<< "LogVideoSendStreamConfig currently only supports one "
"codec. Logging codec :"
<< codec.payload_name;
@@ -695,8 +724,7 @@ std::string RtcEventLogEncoderLegacy::EncodeRtcpPacket(
rtcp::CommonHeader header;
const uint8_t* block_begin = packet.data();
const uint8_t* packet_end = packet.data() + packet.size();
- RTC_DCHECK(packet.size() <= IP_PACKET_SIZE);
- uint8_t buffer[IP_PACKET_SIZE];
+ std::vector<uint8_t> buffer(packet.size());
uint32_t buffer_length = 0;
while (block_begin < packet_end) {
if (!header.Parse(block_begin, packet_end - block_begin)) {
@@ -706,16 +734,14 @@ std::string RtcEventLogEncoderLegacy::EncodeRtcpPacket(
uint32_t block_size = next_block - block_begin;
switch (header.type()) {
case rtcp::Bye::kPacketType:
- case rtcp::ExtendedJitterReport::kPacketType:
case rtcp::ExtendedReports::kPacketType:
case rtcp::Psfb::kPacketType:
case rtcp::ReceiverReport::kPacketType:
case rtcp::Rtpfb::kPacketType:
case rtcp::SenderReport::kPacketType:
- // We log sender reports, receiver reports, bye messages
- // inter-arrival jitter, third-party loss reports, payload-specific
- // feedback and extended reports.
- memcpy(buffer + buffer_length, block_begin, block_size);
+ // We log sender reports, receiver reports, bye messages, third-party
+ // loss reports, payload-specific feedback and extended reports.
+ memcpy(buffer.data() + buffer_length, block_begin, block_size);
buffer_length += block_size;
break;
case rtcp::App::kPacketType:
@@ -728,14 +754,15 @@ std::string RtcEventLogEncoderLegacy::EncodeRtcpPacket(
block_begin += block_size;
}
- rtclog_event.mutable_rtcp_packet()->set_packet_data(buffer, buffer_length);
+ rtclog_event.mutable_rtcp_packet()->set_packet_data(buffer.data(),
+ buffer_length);
return Serialize(&rtclog_event);
}
std::string RtcEventLogEncoderLegacy::EncodeRtpPacket(
int64_t timestamp_us,
- const webrtc::RtpPacket& header,
+ rtc::ArrayView<const uint8_t> header,
size_t packet_length,
int probe_cluster_id,
bool is_incoming) {
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
index 3105dc1e68..33c530789b 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h
@@ -15,6 +15,7 @@
#include <memory>
#include <string>
+#include "api/array_view.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder.h"
#include "rtc_base/buffer.h"
@@ -24,6 +25,7 @@ namespace rtclog {
class Event; // Auto-generated from protobuf.
} // namespace rtclog
+class RtcEventAlrState;
class RtcEventAudioNetworkAdaptation;
class RtcEventAudioPlayout;
class RtcEventAudioReceiveStreamConfig;
@@ -37,13 +39,13 @@ class RtcEventLoggingStopped;
class RtcEventProbeClusterCreated;
class RtcEventProbeResultFailure;
class RtcEventProbeResultSuccess;
+class RtcEventRemoteEstimate;
class RtcEventRtcpPacketIncoming;
class RtcEventRtcpPacketOutgoing;
class RtcEventRtpPacketIncoming;
class RtcEventRtpPacketOutgoing;
class RtcEventVideoReceiveStreamConfig;
class RtcEventVideoSendStreamConfig;
-class RtcEventAlrState;
class RtpPacket;
class RtcEventLogEncoderLegacy final : public RtcEventLogEncoder {
@@ -80,6 +82,7 @@ class RtcEventLogEncoderLegacy final : public RtcEventLogEncoder {
const RtcEventProbeClusterCreated& event);
std::string EncodeProbeResultFailure(const RtcEventProbeResultFailure& event);
std::string EncodeProbeResultSuccess(const RtcEventProbeResultSuccess&);
+ std::string EncodeRemoteEstimate(const RtcEventRemoteEstimate& event);
std::string EncodeRtcpPacketIncoming(const RtcEventRtcpPacketIncoming& event);
std::string EncodeRtcpPacketOutgoing(const RtcEventRtcpPacketOutgoing& event);
std::string EncodeRtpPacketIncoming(const RtcEventRtpPacketIncoming& event);
@@ -94,7 +97,7 @@ class RtcEventLogEncoderLegacy final : public RtcEventLogEncoder {
const rtc::Buffer& packet,
bool is_incoming);
std::string EncodeRtpPacket(int64_t timestamp_us,
- const RtpPacket& header,
+ rtc::ArrayView<const uint8_t> header,
size_t packet_length,
int probe_cluster_id,
bool is_incoming);
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
index 70c7f37356..9d791d1aca 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.cc
@@ -12,6 +12,7 @@
#include "absl/types/optional.h"
#include "api/array_view.h"
+#include "api/network_state_predictor.h"
#include "logging/rtc_event_log/encoder/blob_encoding.h"
#include "logging/rtc_event_log/encoder/delta_encoding.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h"
@@ -24,6 +25,7 @@
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
+#include "logging/rtc_event_log/events/rtc_event_frame_decoded.h"
#include "logging/rtc_event_log/events/rtc_event_generic_ack_received.h"
#include "logging/rtc_event_log/events/rtc_event_generic_packet_received.h"
#include "logging/rtc_event_log/events/rtc_event_generic_packet_sent.h"
@@ -42,13 +44,11 @@
#include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
#include "logging/rtc_event_log/rtc_stream_config.h"
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/rtp_rtcp/include/rtp_cvo.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtcp_packet/app.h"
#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h"
#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
#include "modules/rtp_rtcp/source/rtcp_packet/psfb.h"
#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
@@ -85,12 +85,32 @@ rtclog2::DelayBasedBweUpdates::DetectorState ConvertToProtoFormat(
case BandwidthUsage::kBwOverusing:
return rtclog2::DelayBasedBweUpdates::BWE_OVERUSING;
case BandwidthUsage::kLast:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog2::DelayBasedBweUpdates::BWE_UNKNOWN_STATE;
}
+rtclog2::FrameDecodedEvents::Codec ConvertToProtoFormat(VideoCodecType codec) {
+ switch (codec) {
+ case VideoCodecType::kVideoCodecGeneric:
+ return rtclog2::FrameDecodedEvents::CODEC_GENERIC;
+ case VideoCodecType::kVideoCodecVP8:
+ return rtclog2::FrameDecodedEvents::CODEC_VP8;
+ case VideoCodecType::kVideoCodecVP9:
+ return rtclog2::FrameDecodedEvents::CODEC_VP9;
+ case VideoCodecType::kVideoCodecAV1:
+ return rtclog2::FrameDecodedEvents::CODEC_AV1;
+ case VideoCodecType::kVideoCodecH264:
+ return rtclog2::FrameDecodedEvents::CODEC_H264;
+ case VideoCodecType::kVideoCodecMultiplex:
+ // This codec type is afaik not used.
+ return rtclog2::FrameDecodedEvents::CODEC_UNKNOWN;
+ }
+ RTC_DCHECK_NOTREACHED();
+ return rtclog2::FrameDecodedEvents::CODEC_UNKNOWN;
+}
+
rtclog2::BweProbeResultFailure::FailureReason ConvertToProtoFormat(
ProbeFailureReason failure_reason) {
switch (failure_reason) {
@@ -101,16 +121,16 @@ rtclog2::BweProbeResultFailure::FailureReason ConvertToProtoFormat(
case ProbeFailureReason::kTimeout:
return rtclog2::BweProbeResultFailure::TIMEOUT;
case ProbeFailureReason::kLast:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog2::BweProbeResultFailure::UNKNOWN;
}
// Returns true if there are recognized extensions that we should log
// and false if there are no extensions or all extensions are types we don't
// log. The protobuf representation of the header configs is written to
-// |proto_config|.
+// `proto_config`.
bool ConvertToProtoFormat(const std::vector<RtpExtension>& extensions,
rtclog2::RtpHeaderExtensionConfig* proto_config) {
size_t unknown_extensions = 0;
@@ -146,9 +166,9 @@ rtclog2::DtlsTransportStateEvent::DtlsTransportState ConvertToProtoFormat(
case webrtc::DtlsTransportState::kFailed:
return rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_FAILED;
case webrtc::DtlsTransportState::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog2::DtlsTransportStateEvent::UNKNOWN_DTLS_TRANSPORT_STATE;
}
@@ -164,9 +184,9 @@ ConvertToProtoFormat(IceCandidatePairConfigType type) {
case IceCandidatePairConfigType::kSelected:
return rtclog2::IceCandidatePairConfig::SELECTED;
case IceCandidatePairConfigType::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog2::IceCandidatePairConfig::UNKNOWN_CONFIG_TYPE;
}
@@ -184,9 +204,9 @@ rtclog2::IceCandidatePairConfig::IceCandidateType ConvertToProtoFormat(
case IceCandidateType::kRelay:
return rtclog2::IceCandidatePairConfig::RELAY;
case IceCandidateType::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog2::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE;
}
@@ -204,9 +224,9 @@ rtclog2::IceCandidatePairConfig::Protocol ConvertToProtoFormat(
case IceCandidatePairProtocol::kTls:
return rtclog2::IceCandidatePairConfig::TLS;
case IceCandidatePairProtocol::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog2::IceCandidatePairConfig::UNKNOWN_PROTOCOL;
}
@@ -220,9 +240,9 @@ rtclog2::IceCandidatePairConfig::AddressFamily ConvertToProtoFormat(
case IceCandidatePairAddressFamily::kIpv6:
return rtclog2::IceCandidatePairConfig::IPV6;
case IceCandidatePairAddressFamily::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog2::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY;
}
@@ -242,9 +262,9 @@ rtclog2::IceCandidatePairConfig::NetworkType ConvertToProtoFormat(
case IceCandidateNetworkType::kCellular:
return rtclog2::IceCandidatePairConfig::CELLULAR;
case IceCandidateNetworkType::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog2::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE;
}
@@ -260,18 +280,16 @@ rtclog2::IceCandidatePairEvent::IceCandidatePairEventType ConvertToProtoFormat(
case IceCandidatePairEventType::kCheckResponseReceived:
return rtclog2::IceCandidatePairEvent::CHECK_RESPONSE_RECEIVED;
case IceCandidatePairEventType::kNumValues:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return rtclog2::IceCandidatePairEvent::UNKNOWN_CHECK_TYPE;
}
-// Copies all RTCP blocks except APP, SDES and unknown from |packet| to
-// |buffer|. |buffer| must have space for |IP_PACKET_SIZE| bytes. |packet| must
-// be at most |IP_PACKET_SIZE| bytes long.
-size_t RemoveNonWhitelistedRtcpBlocks(const rtc::Buffer& packet,
+// Copies all RTCP blocks except APP, SDES and unknown from `packet` to
+// `buffer`. `buffer` must have space for at least `packet.size()` bytes.
+size_t RemoveNonAllowlistedRtcpBlocks(const rtc::Buffer& packet,
uint8_t* buffer) {
- RTC_DCHECK(packet.size() <= IP_PACKET_SIZE);
RTC_DCHECK(buffer != nullptr);
rtcp::CommonHeader header;
const uint8_t* block_begin = packet.data();
@@ -287,17 +305,15 @@ size_t RemoveNonWhitelistedRtcpBlocks(const rtc::Buffer& packet,
size_t block_size = next_block - block_begin;
switch (header.type()) {
case rtcp::Bye::kPacketType:
- case rtcp::ExtendedJitterReport::kPacketType:
case rtcp::ExtendedReports::kPacketType:
case rtcp::Psfb::kPacketType:
case rtcp::ReceiverReport::kPacketType:
case rtcp::Rtpfb::kPacketType:
case rtcp::SenderReport::kPacketType:
- // We log sender reports, receiver reports, bye messages
- // inter-arrival jitter, third-party loss reports, payload-specific
- // feedback and extended reports.
+ // We log sender reports, receiver reports, bye messages, third-party
+ // loss reports, payload-specific feedback and extended reports.
// TODO(terelius): As an optimization, don't copy anything if all blocks
- // in the packet are whitelisted types.
+ // in the packet are allowlisted types.
memcpy(buffer + buffer_length, block_begin, block_size);
buffer_length += block_size;
break;
@@ -325,10 +341,10 @@ void EncodeRtcpPacket(rtc::ArrayView<const EventType*> batch,
const EventType* const base_event = batch[0];
proto_batch->set_timestamp_ms(base_event->timestamp_ms());
{
- uint8_t buffer[IP_PACKET_SIZE];
+ std::vector<uint8_t> buffer(base_event->packet().size());
size_t buffer_length =
- RemoveNonWhitelistedRtcpBlocks(base_event->packet(), buffer);
- proto_batch->set_raw_packet(buffer, buffer_length);
+ RemoveNonAllowlistedRtcpBlocks(base_event->packet(), buffer.data());
+ proto_batch->set_raw_packet(buffer.data(), buffer_length);
}
if (batch.size() == 1) {
@@ -356,7 +372,7 @@ void EncodeRtcpPacket(rtc::ArrayView<const EventType*> batch,
const EventType* event = batch[i + 1];
scrubed_packets[i].resize(event->packet().size());
static_assert(sizeof(std::string::value_type) == sizeof(uint8_t), "");
- const size_t buffer_length = RemoveNonWhitelistedRtcpBlocks(
+ const size_t buffer_length = RemoveNonAllowlistedRtcpBlocks(
event->packet(), reinterpret_cast<uint8_t*>(&scrubed_packets[i][0]));
if (buffer_length < event->packet().size()) {
scrubed_packets[i].resize(buffer_length);
@@ -375,12 +391,12 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
// Base event
const EventType* const base_event = batch[0];
proto_batch->set_timestamp_ms(base_event->timestamp_ms());
- proto_batch->set_marker(base_event->header().Marker());
+ proto_batch->set_marker(base_event->Marker());
// TODO(terelius): Is payload type needed?
- proto_batch->set_payload_type(base_event->header().PayloadType());
- proto_batch->set_sequence_number(base_event->header().SequenceNumber());
- proto_batch->set_rtp_timestamp(base_event->header().Timestamp());
- proto_batch->set_ssrc(base_event->header().Ssrc());
+ proto_batch->set_payload_type(base_event->PayloadType());
+ proto_batch->set_sequence_number(base_event->SequenceNumber());
+ proto_batch->set_rtp_timestamp(base_event->Timestamp());
+ proto_batch->set_ssrc(base_event->Ssrc());
proto_batch->set_payload_size(base_event->payload_length());
proto_batch->set_header_size(base_event->header_length());
proto_batch->set_padding_size(base_event->padding_length());
@@ -389,8 +405,7 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
absl::optional<uint64_t> base_transport_sequence_number;
{
uint16_t seqnum;
- if (base_event->header().template GetExtension<TransportSequenceNumber>(
- &seqnum)) {
+ if (base_event->template GetExtension<TransportSequenceNumber>(&seqnum)) {
proto_batch->set_transport_sequence_number(seqnum);
base_transport_sequence_number = seqnum;
}
@@ -399,8 +414,7 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
absl::optional<uint64_t> unsigned_base_transmission_time_offset;
{
int32_t offset;
- if (base_event->header().template GetExtension<TransmissionOffset>(
- &offset)) {
+ if (base_event->template GetExtension<TransmissionOffset>(&offset)) {
proto_batch->set_transmission_time_offset(offset);
unsigned_base_transmission_time_offset = ToUnsigned(offset);
}
@@ -409,8 +423,7 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
absl::optional<uint64_t> base_absolute_send_time;
{
uint32_t sendtime;
- if (base_event->header().template GetExtension<AbsoluteSendTime>(
- &sendtime)) {
+ if (base_event->template GetExtension<AbsoluteSendTime>(&sendtime)) {
proto_batch->set_absolute_send_time(sendtime);
base_absolute_send_time = sendtime;
}
@@ -419,8 +432,7 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
absl::optional<uint64_t> base_video_rotation;
{
VideoRotation video_rotation;
- if (base_event->header().template GetExtension<VideoOrientation>(
- &video_rotation)) {
+ if (base_event->template GetExtension<VideoOrientation>(&video_rotation)) {
proto_batch->set_video_rotation(
ConvertVideoRotationToCVOByte(video_rotation));
base_video_rotation = ConvertVideoRotationToCVOByte(video_rotation);
@@ -432,8 +444,8 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
{
bool voice_activity;
uint8_t audio_level;
- if (base_event->header().template GetExtension<AudioLevel>(&voice_activity,
- &audio_level)) {
+ if (base_event->template GetExtension<AudioLevel>(&voice_activity,
+ &audio_level)) {
RTC_DCHECK_LE(audio_level, 0x7Fu);
base_audio_level = audio_level;
proto_batch->set_audio_level(audio_level);
@@ -465,9 +477,9 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
// marker (RTP base)
for (size_t i = 0; i < values.size(); ++i) {
const EventType* event = batch[i + 1];
- values[i] = event->header().Marker();
+ values[i] = event->Marker();
}
- encoded_deltas = EncodeDeltas(base_event->header().Marker(), values);
+ encoded_deltas = EncodeDeltas(base_event->Marker(), values);
if (!encoded_deltas.empty()) {
proto_batch->set_marker_deltas(encoded_deltas);
}
@@ -475,9 +487,9 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
// payload_type (RTP base)
for (size_t i = 0; i < values.size(); ++i) {
const EventType* event = batch[i + 1];
- values[i] = event->header().PayloadType();
+ values[i] = event->PayloadType();
}
- encoded_deltas = EncodeDeltas(base_event->header().PayloadType(), values);
+ encoded_deltas = EncodeDeltas(base_event->PayloadType(), values);
if (!encoded_deltas.empty()) {
proto_batch->set_payload_type_deltas(encoded_deltas);
}
@@ -485,9 +497,9 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
// sequence_number (RTP base)
for (size_t i = 0; i < values.size(); ++i) {
const EventType* event = batch[i + 1];
- values[i] = event->header().SequenceNumber();
+ values[i] = event->SequenceNumber();
}
- encoded_deltas = EncodeDeltas(base_event->header().SequenceNumber(), values);
+ encoded_deltas = EncodeDeltas(base_event->SequenceNumber(), values);
if (!encoded_deltas.empty()) {
proto_batch->set_sequence_number_deltas(encoded_deltas);
}
@@ -495,9 +507,9 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
// rtp_timestamp (RTP base)
for (size_t i = 0; i < values.size(); ++i) {
const EventType* event = batch[i + 1];
- values[i] = event->header().Timestamp();
+ values[i] = event->Timestamp();
}
- encoded_deltas = EncodeDeltas(base_event->header().Timestamp(), values);
+ encoded_deltas = EncodeDeltas(base_event->Timestamp(), values);
if (!encoded_deltas.empty()) {
proto_batch->set_rtp_timestamp_deltas(encoded_deltas);
}
@@ -505,9 +517,9 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
// ssrc (RTP base)
for (size_t i = 0; i < values.size(); ++i) {
const EventType* event = batch[i + 1];
- values[i] = event->header().Ssrc();
+ values[i] = event->Ssrc();
}
- encoded_deltas = EncodeDeltas(base_event->header().Ssrc(), values);
+ encoded_deltas = EncodeDeltas(base_event->Ssrc(), values);
if (!encoded_deltas.empty()) {
proto_batch->set_ssrc_deltas(encoded_deltas);
}
@@ -546,8 +558,7 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
for (size_t i = 0; i < values.size(); ++i) {
const EventType* event = batch[i + 1];
uint16_t seqnum;
- if (event->header().template GetExtension<TransportSequenceNumber>(
- &seqnum)) {
+ if (event->template GetExtension<TransportSequenceNumber>(&seqnum)) {
values[i] = seqnum;
} else {
values[i].reset();
@@ -562,7 +573,7 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
for (size_t i = 0; i < values.size(); ++i) {
const EventType* event = batch[i + 1];
int32_t offset;
- if (event->header().template GetExtension<TransmissionOffset>(&offset)) {
+ if (event->template GetExtension<TransmissionOffset>(&offset)) {
values[i] = ToUnsigned(offset);
} else {
values[i].reset();
@@ -577,7 +588,7 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
for (size_t i = 0; i < values.size(); ++i) {
const EventType* event = batch[i + 1];
uint32_t sendtime;
- if (event->header().template GetExtension<AbsoluteSendTime>(&sendtime)) {
+ if (event->template GetExtension<AbsoluteSendTime>(&sendtime)) {
values[i] = sendtime;
} else {
values[i].reset();
@@ -592,8 +603,7 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
for (size_t i = 0; i < values.size(); ++i) {
const EventType* event = batch[i + 1];
VideoRotation video_rotation;
- if (event->header().template GetExtension<VideoOrientation>(
- &video_rotation)) {
+ if (event->template GetExtension<VideoOrientation>(&video_rotation)) {
values[i] = ConvertVideoRotationToCVOByte(video_rotation);
} else {
values[i].reset();
@@ -609,8 +619,8 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
const EventType* event = batch[i + 1];
bool voice_activity;
uint8_t audio_level;
- if (event->header().template GetExtension<AudioLevel>(&voice_activity,
- &audio_level)) {
+ if (event->template GetExtension<AudioLevel>(&voice_activity,
+ &audio_level)) {
RTC_DCHECK_LE(audio_level, 0x7Fu);
values[i] = audio_level;
} else {
@@ -627,8 +637,8 @@ void EncodeRtpPacket(const std::vector<const EventType*>& batch,
const EventType* event = batch[i + 1];
bool voice_activity;
uint8_t audio_level;
- if (event->header().template GetExtension<AudioLevel>(&voice_activity,
- &audio_level)) {
+ if (event->template GetExtension<AudioLevel>(&voice_activity,
+ &audio_level)) {
RTC_DCHECK_LE(audio_level, 0x7Fu);
values[i] = voice_activity;
} else {
@@ -677,6 +687,8 @@ std::string RtcEventLogEncoderNewFormat::EncodeBatch(
std::vector<const RtcEventBweUpdateLossBased*> bwe_loss_based_updates;
std::vector<const RtcEventDtlsTransportState*> dtls_transport_states;
std::vector<const RtcEventDtlsWritableState*> dtls_writable_states;
+ std::map<uint32_t /* SSRC */, std::vector<const RtcEventFrameDecoded*>>
+ frames_decoded;
std::vector<const RtcEventGenericAckReceived*> generic_acks_received;
std::vector<const RtcEventGenericPacketReceived*> generic_packets_received;
std::vector<const RtcEventGenericPacketSent*> generic_packets_sent;
@@ -802,14 +814,14 @@ std::string RtcEventLogEncoderNewFormat::EncodeBatch(
case RtcEvent::Type::RtpPacketIncoming: {
auto* rtc_event =
static_cast<const RtcEventRtpPacketIncoming* const>(it->get());
- auto& v = incoming_rtp_packets[rtc_event->header().Ssrc()];
+ auto& v = incoming_rtp_packets[rtc_event->Ssrc()];
v.emplace_back(rtc_event);
break;
}
case RtcEvent::Type::RtpPacketOutgoing: {
auto* rtc_event =
static_cast<const RtcEventRtpPacketOutgoing* const>(it->get());
- auto& v = outgoing_rtp_packets[rtc_event->header().Ssrc()];
+ auto& v = outgoing_rtp_packets[rtc_event->Ssrc()];
v.emplace_back(rtc_event);
break;
}
@@ -859,6 +871,18 @@ std::string RtcEventLogEncoderNewFormat::EncodeBatch(
generic_acks_received.push_back(rtc_event);
break;
}
+ case RtcEvent::Type::FrameDecoded: {
+ auto* rtc_event =
+ static_cast<const RtcEventFrameDecoded* const>(it->get());
+ frames_decoded[rtc_event->ssrc()].emplace_back(rtc_event);
+ break;
+ }
+ case RtcEvent::Type::BeginV3Log:
+ case RtcEvent::Type::EndV3Log:
+ // These special events are written as part of starting
+ // and stopping the log, and only as part of version 3 of the format.
+ RTC_DCHECK_NOTREACHED();
+ break;
}
}
@@ -872,6 +896,9 @@ std::string RtcEventLogEncoderNewFormat::EncodeBatch(
EncodeBweUpdateLossBased(bwe_loss_based_updates, &event_stream);
EncodeDtlsTransportState(dtls_transport_states, &event_stream);
EncodeDtlsWritableState(dtls_writable_states, &event_stream);
+ for (const auto& kv : frames_decoded) {
+ EncodeFramesDecoded(kv.second, &event_stream);
+ }
EncodeGenericAcksReceived(generic_acks_received, &event_stream);
EncodeGenericPacketsReceived(generic_packets_received, &event_stream);
EncodeGenericPacketsSent(generic_packets_sent, &event_stream);
@@ -932,7 +959,7 @@ void RtcEventLogEncoderNewFormat::EncodeAudioNetworkAdaptation(
proto_batch->set_enable_fec(base_event->config().enable_fec.value());
if (base_event->config().enable_dtx.has_value())
proto_batch->set_enable_dtx(base_event->config().enable_dtx.value());
- // Note that |num_channels_deltas| encodes N as N-1, to keep deltas smaller,
+ // Note that `num_channels_deltas` encodes N as N-1, to keep deltas smaller,
// but there's no reason to do the same for the base event's value, since
// no bits will be spared.
if (base_event->config().num_channels.has_value())
@@ -1377,7 +1404,7 @@ void RtcEventLogEncoderNewFormat::EncodeRemoteEstimate(
// link_capacity_lower_kbps
for (size_t i = 0; i < values.size(); ++i) {
const auto* event = batch[i + 1];
- if (base_event->link_capacity_lower_.IsFinite()) {
+ if (event->link_capacity_lower_.IsFinite()) {
values[i] = event->link_capacity_lower_.kbps<uint32_t>();
} else {
values[i].reset();
@@ -1391,7 +1418,7 @@ void RtcEventLogEncoderNewFormat::EncodeRemoteEstimate(
// link_capacity_upper_kbps
for (size_t i = 0; i < values.size(); ++i) {
const auto* event = batch[i + 1];
- if (base_event->link_capacity_upper_.IsFinite()) {
+ if (event->link_capacity_upper_.IsFinite()) {
values[i] = event->link_capacity_upper_.kbps<uint32_t>();
} else {
values[i].reset();
@@ -1431,6 +1458,105 @@ void RtcEventLogEncoderNewFormat::EncodeRtpPacketIncoming(
}
}
+void RtcEventLogEncoderNewFormat::EncodeFramesDecoded(
+ rtc::ArrayView<const RtcEventFrameDecoded* const> batch,
+ rtclog2::EventStream* event_stream) {
+ if (batch.empty()) {
+ return;
+ }
+ const RtcEventFrameDecoded* const base_event = batch[0];
+ rtclog2::FrameDecodedEvents* proto_batch =
+ event_stream->add_frame_decoded_events();
+ proto_batch->set_timestamp_ms(base_event->timestamp_ms());
+ proto_batch->set_ssrc(base_event->ssrc());
+ proto_batch->set_render_time_ms(base_event->render_time_ms());
+ proto_batch->set_width(base_event->width());
+ proto_batch->set_height(base_event->height());
+ proto_batch->set_codec(ConvertToProtoFormat(base_event->codec()));
+ proto_batch->set_qp(base_event->qp());
+
+ if (batch.size() == 1) {
+ return;
+ }
+
+ // Delta encoding
+ proto_batch->set_number_of_deltas(batch.size() - 1);
+ std::vector<absl::optional<uint64_t>> values(batch.size() - 1);
+ std::string encoded_deltas;
+
+ // timestamp_ms
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventFrameDecoded* event = batch[i + 1];
+ values[i] = ToUnsigned(event->timestamp_ms());
+ }
+ encoded_deltas = EncodeDeltas(ToUnsigned(base_event->timestamp_ms()), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_timestamp_ms_deltas(encoded_deltas);
+ }
+
+ // SSRC
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventFrameDecoded* event = batch[i + 1];
+ values[i] = event->ssrc();
+ }
+ encoded_deltas = EncodeDeltas(base_event->ssrc(), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_ssrc_deltas(encoded_deltas);
+ }
+
+ // render_time_ms
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventFrameDecoded* event = batch[i + 1];
+ values[i] = ToUnsigned(event->render_time_ms());
+ }
+ encoded_deltas =
+ EncodeDeltas(ToUnsigned(base_event->render_time_ms()), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_render_time_ms_deltas(encoded_deltas);
+ }
+
+ // width
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventFrameDecoded* event = batch[i + 1];
+ values[i] = ToUnsigned(event->width());
+ }
+ encoded_deltas = EncodeDeltas(ToUnsigned(base_event->width()), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_width_deltas(encoded_deltas);
+ }
+
+ // height
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventFrameDecoded* event = batch[i + 1];
+ values[i] = ToUnsigned(event->height());
+ }
+ encoded_deltas = EncodeDeltas(ToUnsigned(base_event->height()), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_height_deltas(encoded_deltas);
+ }
+
+ // codec
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventFrameDecoded* event = batch[i + 1];
+ values[i] = static_cast<uint64_t>(ConvertToProtoFormat(event->codec()));
+ }
+ encoded_deltas = EncodeDeltas(
+ static_cast<uint64_t>(ConvertToProtoFormat(base_event->codec())), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_codec_deltas(encoded_deltas);
+ }
+
+ // qp
+ for (size_t i = 0; i < values.size(); ++i) {
+ const RtcEventFrameDecoded* event = batch[i + 1];
+ values[i] = event->qp();
+ }
+ encoded_deltas = EncodeDeltas(base_event->qp(), values);
+ if (!encoded_deltas.empty()) {
+ proto_batch->set_qp_deltas(encoded_deltas);
+ }
+}
+
void RtcEventLogEncoderNewFormat::EncodeGenericPacketsSent(
rtc::ArrayView<const RtcEventGenericPacketSent*> batch,
rtclog2::EventStream* event_stream) {
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h
index d25184ec4a..6af34bc6cd 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h
@@ -51,6 +51,7 @@ class RtcEventVideoSendStreamConfig;
class RtcEventIceCandidatePairConfig;
class RtcEventIceCandidatePair;
class RtpPacket;
+class RtcEventFrameDecoded;
class RtcEventGenericAckReceived;
class RtcEventGenericPacketReceived;
class RtcEventGenericPacketSent;
@@ -94,6 +95,9 @@ class RtcEventLogEncoderNewFormat final : public RtcEventLogEncoder {
void EncodeDtlsWritableState(
rtc::ArrayView<const RtcEventDtlsWritableState*> batch,
rtclog2::EventStream* event_stream);
+ void EncodeFramesDecoded(
+ rtc::ArrayView<const RtcEventFrameDecoded* const> batch,
+ rtclog2::EventStream* event_stream);
void EncodeGenericAcksReceived(
rtc::ArrayView<const RtcEventGenericAckReceived*> batch,
rtclog2::EventStream* event_stream);
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
index cf85775f52..c910003e29 100644
--- a/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_unittest.cc
@@ -16,6 +16,7 @@
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h"
+#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.h"
#include "logging/rtc_event_log/events/rtc_event_alr_state.h"
#include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
#include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
@@ -35,7 +36,7 @@
#include "logging/rtc_event_log/rtc_event_log_parser.h"
#include "logging/rtc_event_log/rtc_event_log_unittest_helper.h"
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "rtc_base/fake_clock.h"
#include "rtc_base/random.h"
@@ -43,21 +44,30 @@
namespace webrtc {
class RtcEventLogEncoderTest
- : public ::testing::TestWithParam<std::tuple<int, bool, size_t, bool>> {
+ : public ::testing::TestWithParam<
+ std::tuple<int, RtcEventLog::EncodingType, size_t, bool>> {
protected:
RtcEventLogEncoderTest()
: seed_(std::get<0>(GetParam())),
prng_(seed_),
- new_encoding_(std::get<1>(GetParam())),
+ encoding_type_(std::get<1>(GetParam())),
event_count_(std::get<2>(GetParam())),
force_repeated_fields_(std::get<3>(GetParam())),
gen_(seed_ * 880001UL),
- verifier_(new_encoding_ ? RtcEventLog::EncodingType::NewFormat
- : RtcEventLog::EncodingType::Legacy) {
- if (new_encoding_)
- encoder_ = std::make_unique<RtcEventLogEncoderNewFormat>();
- else
- encoder_ = std::make_unique<RtcEventLogEncoderLegacy>();
+ verifier_(encoding_type_) {
+ switch (encoding_type_) {
+ case RtcEventLog::EncodingType::Legacy:
+ encoder_ = std::make_unique<RtcEventLogEncoderLegacy>();
+ break;
+ case RtcEventLog::EncodingType::NewFormat:
+ encoder_ = std::make_unique<RtcEventLogEncoderNewFormat>();
+ break;
+ case RtcEventLog::EncodingType::ProtoFree:
+ encoder_ = std::make_unique<RtcEventLogEncoderV3>();
+ break;
+ }
+ encoded_ =
+ encoder_->EncodeLogStart(rtc::TimeMillis(), rtc::TimeUTCMillis());
}
~RtcEventLogEncoderTest() override = default;
@@ -85,11 +95,12 @@ class RtcEventLogEncoderTest
ParsedRtcEventLog parsed_log_;
const uint64_t seed_;
Random prng_;
- const bool new_encoding_;
+ const RtcEventLog::EncodingType encoding_type_;
const size_t event_count_;
const bool force_repeated_fields_;
test::EventGenerator gen_;
test::EventVerifier verifier_;
+ std::string encoded_;
};
void RtcEventLogEncoderTest::TestRtcEventAudioNetworkAdaptation(
@@ -101,8 +112,8 @@ void RtcEventLogEncoderTest::TestRtcEventAudioNetworkAdaptation(
history_.push_back(event->Copy());
}
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& ana_configs = parsed_log_.audio_network_adaptation_events();
ASSERT_EQ(ana_configs.size(), events.size());
@@ -163,11 +174,11 @@ void RtcEventLogEncoderTest::TestRtpPackets() {
// TODO(terelius): Test extensions for legacy encoding, too.
RtpHeaderExtensionMap extension_map;
- if (new_encoding_) {
+ if (encoding_type_ != RtcEventLog::EncodingType::Legacy) {
extension_map = gen_.NewRtpHeaderExtensionMap(true);
}
- // Simulate |event_count_| RTP packets, with SSRCs assigned randomly
+ // Simulate `event_count_` RTP packets, with SSRCs assigned randomly
// out of the small pool above.
std::map<uint32_t, std::vector<std::unique_ptr<EventType>>> events_by_ssrc;
for (size_t i = 0; i < event_count_; ++i) {
@@ -181,8 +192,8 @@ void RtcEventLogEncoderTest::TestRtpPackets() {
}
// Encode and parse.
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
// For each SSRC, make sure the RTP packets associated with it to have been
// correctly encoded and parsed.
@@ -208,8 +219,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventAlrState) {
history_.push_back(events[i]->Copy());
}
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& alr_state_events = parsed_log_.alr_state_events();
ASSERT_EQ(alr_state_events.size(), event_count_);
@@ -219,7 +230,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventAlrState) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventRouteChange) {
- if (!new_encoding_) {
+ if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
return;
}
std::vector<std::unique_ptr<RtcEventRouteChange>> events(event_count_);
@@ -229,8 +240,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRouteChange) {
history_.push_back(events[i]->Copy());
}
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& route_change_events = parsed_log_.route_change_events();
ASSERT_EQ(route_change_events.size(), event_count_);
@@ -240,9 +251,6 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRouteChange) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventRemoteEstimate) {
- if (!new_encoding_) {
- return;
- }
std::vector<std::unique_ptr<RtcEventRemoteEstimate>> events(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
events[i] = (i == 0 || !force_repeated_fields_)
@@ -251,8 +259,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRemoteEstimate) {
history_.push_back(std::make_unique<RtcEventRemoteEstimate>(*events[i]));
}
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& parsed_events = parsed_log_.remote_estimate_events();
ASSERT_EQ(parsed_events.size(), event_count_);
@@ -405,8 +413,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventAudioPlayout) {
original_events_by_ssrc[ssrc].push_back(std::move(event));
}
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& parsed_playout_events_by_ssrc =
parsed_log_.audio_playout_events();
@@ -441,8 +449,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventAudioReceiveStreamConfig) {
gen_.NewAudioReceiveStreamConfig(ssrc, extensions);
history_.push_back(event->Copy());
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& audio_recv_configs = parsed_log_.audio_recv_configs();
ASSERT_EQ(audio_recv_configs.size(), 1u);
@@ -457,8 +465,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventAudioSendStreamConfig) {
gen_.NewAudioSendStreamConfig(ssrc, extensions);
history_.push_back(event->Copy());
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& audio_send_configs = parsed_log_.audio_send_configs();
ASSERT_EQ(audio_send_configs.size(), 1u);
@@ -475,8 +483,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateDelayBased) {
history_.push_back(events[i]->Copy());
}
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& bwe_delay_updates = parsed_log_.bwe_delay_updates();
ASSERT_EQ(bwe_delay_updates.size(), event_count_);
@@ -495,8 +503,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateLossBased) {
history_.push_back(events[i]->Copy());
}
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& bwe_loss_updates = parsed_log_.bwe_loss_updates();
ASSERT_EQ(bwe_loss_updates.size(), event_count_);
@@ -507,7 +515,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateLossBased) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventGenericPacketReceived) {
- if (!new_encoding_) {
+ if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
return;
}
std::vector<std::unique_ptr<RtcEventGenericPacketReceived>> events(
@@ -519,8 +527,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventGenericPacketReceived) {
history_.push_back(events[i]->Copy());
}
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& packets_received = parsed_log_.generic_packets_received();
ASSERT_EQ(packets_received.size(), event_count_);
@@ -532,7 +540,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventGenericPacketReceived) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventGenericPacketSent) {
- if (!new_encoding_) {
+ if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
return;
}
std::vector<std::unique_ptr<RtcEventGenericPacketSent>> events(event_count_);
@@ -543,8 +551,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventGenericPacketSent) {
history_.push_back(events[i]->Copy());
}
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& packets_sent = parsed_log_.generic_packets_sent();
ASSERT_EQ(packets_sent.size(), event_count_);
@@ -555,7 +563,7 @@ TEST_P(RtcEventLogEncoderTest, RtcEventGenericPacketSent) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventGenericAcksReceived) {
- if (!new_encoding_) {
+ if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
return;
}
std::vector<std::unique_ptr<RtcEventGenericAckReceived>> events(event_count_);
@@ -566,8 +574,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventGenericAcksReceived) {
history_.push_back(events[i]->Copy());
}
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& decoded_events = parsed_log_.generic_acks_received();
ASSERT_EQ(decoded_events.size(), event_count_);
@@ -586,12 +594,11 @@ TEST_P(RtcEventLogEncoderTest, RtcEventDtlsTransportState) {
history_.push_back(events[i]->Copy());
}
- const std::string encoded =
- encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& dtls_transport_states = parsed_log_.dtls_transport_states();
- if (!new_encoding_) {
+ if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
ASSERT_EQ(dtls_transport_states.size(), 0u);
return;
}
@@ -612,12 +619,11 @@ TEST_P(RtcEventLogEncoderTest, RtcEventDtlsWritableState) {
history_.push_back(events[i]->Copy());
}
- const std::string encoded =
- encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& dtls_writable_states = parsed_log_.dtls_writable_states();
- if (!new_encoding_) {
+ if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
ASSERT_EQ(dtls_writable_states.size(), 0u);
return;
}
@@ -630,14 +636,68 @@ TEST_P(RtcEventLogEncoderTest, RtcEventDtlsWritableState) {
}
}
+TEST_P(RtcEventLogEncoderTest, RtcEventFrameDecoded) {
+ // SSRCs will be randomly assigned out of this small pool, significant only
+ // in that it also covers such edge cases as SSRC = 0 and SSRC = 0xffffffff.
+ // The pool is intentionally small, so as to produce collisions.
+ const std::vector<uint32_t> kSsrcPool = {0x00000000, 0x12345678, 0xabcdef01,
+ 0xffffffff, 0x20171024, 0x19840730,
+ 0x19831230};
+
+ std::map<uint32_t, std::vector<std::unique_ptr<RtcEventFrameDecoded>>>
+ original_events_by_ssrc;
+ for (size_t i = 0; i < event_count_; ++i) {
+ const uint32_t ssrc = kSsrcPool[prng_.Rand(kSsrcPool.size() - 1)];
+ std::unique_ptr<RtcEventFrameDecoded> event =
+ (original_events_by_ssrc[ssrc].empty() || !force_repeated_fields_)
+ ? gen_.NewFrameDecodedEvent(ssrc)
+ : original_events_by_ssrc[ssrc][0]->Copy();
+ history_.push_back(event->Copy());
+ original_events_by_ssrc[ssrc].push_back(std::move(event));
+ }
+
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ auto status = parsed_log_.ParseString(encoded_);
+ if (!status.ok())
+ RTC_LOG(LS_ERROR) << status.message();
+ ASSERT_TRUE(status.ok());
+
+ const auto& decoded_frames_by_ssrc = parsed_log_.decoded_frames();
+ if (encoding_type_ == RtcEventLog::EncodingType::Legacy) {
+ ASSERT_EQ(decoded_frames_by_ssrc.size(), 0u);
+ return;
+ }
+
+ // Same number of distinct SSRCs.
+ ASSERT_EQ(decoded_frames_by_ssrc.size(), original_events_by_ssrc.size());
+
+ for (const auto& original_event_it : original_events_by_ssrc) {
+ const uint32_t ssrc = original_event_it.first;
+ const std::vector<std::unique_ptr<RtcEventFrameDecoded>>& original_frames =
+ original_event_it.second;
+
+ const auto& parsed_event_it = decoded_frames_by_ssrc.find(ssrc);
+ ASSERT_TRUE(parsed_event_it != decoded_frames_by_ssrc.end());
+ const std::vector<LoggedFrameDecoded>& parsed_frames =
+ parsed_event_it->second;
+
+ // Same number events for the SSRC under examination.
+ ASSERT_EQ(original_frames.size(), parsed_frames.size());
+
+ for (size_t i = 0; i < original_frames.size(); ++i) {
+ verifier_.VerifyLoggedFrameDecoded(*original_frames[i], parsed_frames[i]);
+ }
+ }
+}
+
// TODO(eladalon/terelius): Test with multiple events in the batch.
TEST_P(RtcEventLogEncoderTest, RtcEventIceCandidatePairConfig) {
std::unique_ptr<RtcEventIceCandidatePairConfig> event =
gen_.NewIceCandidatePairConfig();
history_.push_back(event->Copy());
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& ice_candidate_pair_configs =
parsed_log_.ice_candidate_pair_configs();
@@ -651,8 +711,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventIceCandidatePair) {
std::unique_ptr<RtcEventIceCandidatePair> event = gen_.NewIceCandidatePair();
history_.push_back(event->Copy());
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& ice_candidate_pair_events =
parsed_log_.ice_candidate_pair_events();
@@ -662,31 +722,35 @@ TEST_P(RtcEventLogEncoderTest, RtcEventIceCandidatePair) {
}
TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStarted) {
- const int64_t timestamp_us = rtc::TimeMicros();
- const int64_t utc_time_us = rtc::TimeUTCMicros();
+ const int64_t timestamp_ms = prng_.Rand(1'000'000'000);
+ const int64_t utc_time_ms = prng_.Rand(1'000'000'000);
- std::string encoded = encoder_->EncodeLogStart(timestamp_us, utc_time_us);
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ // Overwrite the previously encoded LogStart event.
+ encoded_ = encoder_->EncodeLogStart(timestamp_ms * 1000, utc_time_ms * 1000);
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& start_log_events = parsed_log_.start_log_events();
ASSERT_EQ(start_log_events.size(), 1u);
- verifier_.VerifyLoggedStartEvent(timestamp_us, utc_time_us,
+ verifier_.VerifyLoggedStartEvent(timestamp_ms * 1000, utc_time_ms * 1000,
start_log_events[0]);
}
TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStopped) {
- const int64_t start_timestamp_us = rtc::TimeMicros();
- const int64_t start_utc_time_us = rtc::TimeUTCMicros();
- std::string encoded =
- encoder_->EncodeLogStart(start_timestamp_us, start_utc_time_us);
-
- const int64_t stop_timestamp_us = rtc::TimeMicros();
- encoded += encoder_->EncodeLogEnd(stop_timestamp_us);
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ const int64_t start_timestamp_ms = prng_.Rand(1'000'000'000);
+ const int64_t start_utc_time_ms = prng_.Rand(1'000'000'000);
+
+ // Overwrite the previously encoded LogStart event.
+ encoded_ = encoder_->EncodeLogStart(start_timestamp_ms * 1000,
+ start_utc_time_ms * 1000);
+
+ const int64_t stop_timestamp_ms =
+ prng_.Rand(start_timestamp_ms, 2'000'000'000);
+ encoded_ += encoder_->EncodeLogEnd(stop_timestamp_ms * 1000);
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& stop_log_events = parsed_log_.stop_log_events();
ASSERT_EQ(stop_log_events.size(), 1u);
- verifier_.VerifyLoggedStopEvent(stop_timestamp_us, stop_log_events[0]);
+ verifier_.VerifyLoggedStopEvent(stop_timestamp_ms * 1000, stop_log_events[0]);
}
// TODO(eladalon/terelius): Test with multiple events in the batch.
@@ -695,8 +759,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventProbeClusterCreated) {
gen_.NewProbeClusterCreated();
history_.push_back(event->Copy());
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& bwe_probe_cluster_created_events =
parsed_log_.bwe_probe_cluster_created_events();
@@ -711,8 +775,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultFailure) {
gen_.NewProbeResultFailure();
history_.push_back(event->Copy());
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& bwe_probe_failure_events = parsed_log_.bwe_probe_failure_events();
ASSERT_EQ(bwe_probe_failure_events.size(), 1u);
@@ -726,8 +790,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultSuccess) {
gen_.NewProbeResultSuccess();
history_.push_back(event->Copy());
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& bwe_probe_success_events = parsed_log_.bwe_probe_success_events();
ASSERT_EQ(bwe_probe_success_events.size(), 1u);
@@ -750,8 +814,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketIncoming) {
history_.push_back(events[i]->Copy());
}
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& incoming_rtcp_packets = parsed_log_.incoming_rtcp_packets();
ASSERT_EQ(incoming_rtcp_packets.size(), event_count_);
@@ -771,8 +835,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketOutgoing) {
history_.push_back(events[i]->Copy());
}
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& outgoing_rtcp_packets = parsed_log_.outgoing_rtcp_packets();
ASSERT_EQ(outgoing_rtcp_packets.size(), event_count_);
@@ -793,9 +857,9 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpReceiverReport) {
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::ReceiverReport> events(event_count_);
- std::vector<int64_t> timestamps_us(event_count_);
+ std::vector<int64_t> timestamps_ms(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- timestamps_us[i] = rtc::TimeMicros();
+ timestamps_ms[i] = rtc::TimeMillis();
events[i] = gen_.NewReceiverReport();
rtc::Buffer buffer = events[i].Build();
if (direction == kIncomingPacket) {
@@ -808,15 +872,14 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpReceiverReport) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- std::string encoded =
- encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& receiver_reports = parsed_log_.receiver_reports(direction);
ASSERT_EQ(receiver_reports.size(), event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- verifier_.VerifyLoggedReceiverReport(timestamps_us[i], events[i],
+ verifier_.VerifyLoggedReceiverReport(timestamps_ms[i], events[i],
receiver_reports[i]);
}
}
@@ -832,9 +895,9 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpSenderReport) {
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::SenderReport> events(event_count_);
- std::vector<int64_t> timestamps_us(event_count_);
+ std::vector<int64_t> timestamps_ms(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- timestamps_us[i] = rtc::TimeMicros();
+ timestamps_ms[i] = rtc::TimeMillis();
events[i] = gen_.NewSenderReport();
rtc::Buffer buffer = events[i].Build();
if (direction == kIncomingPacket) {
@@ -847,15 +910,14 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpSenderReport) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- std::string encoded =
- encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& sender_reports = parsed_log_.sender_reports(direction);
ASSERT_EQ(sender_reports.size(), event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- verifier_.VerifyLoggedSenderReport(timestamps_us[i], events[i],
+ verifier_.VerifyLoggedSenderReport(timestamps_ms[i], events[i],
sender_reports[i]);
}
}
@@ -871,9 +933,9 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpExtendedReports) {
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::ExtendedReports> events(event_count_);
- std::vector<int64_t> timestamps_us(event_count_);
+ std::vector<int64_t> timestamps_ms(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- timestamps_us[i] = rtc::TimeMicros();
+ timestamps_ms[i] = rtc::TimeMillis();
events[i] = gen_.NewExtendedReports();
rtc::Buffer buffer = events[i].Build();
if (direction == kIncomingPacket) {
@@ -886,15 +948,14 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpExtendedReports) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- std::string encoded =
- encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& extended_reports = parsed_log_.extended_reports(direction);
ASSERT_EQ(extended_reports.size(), event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- verifier_.VerifyLoggedExtendedReports(timestamps_us[i], events[i],
+ verifier_.VerifyLoggedExtendedReports(timestamps_ms[i], events[i],
extended_reports[i]);
}
}
@@ -910,9 +971,9 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpFir) {
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::Fir> events(event_count_);
- std::vector<int64_t> timestamps_us(event_count_);
+ std::vector<int64_t> timestamps_ms(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- timestamps_us[i] = rtc::TimeMicros();
+ timestamps_ms[i] = rtc::TimeMillis();
events[i] = gen_.NewFir();
rtc::Buffer buffer = events[i].Build();
if (direction == kIncomingPacket) {
@@ -925,15 +986,14 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpFir) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- std::string encoded =
- encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& firs = parsed_log_.firs(direction);
ASSERT_EQ(firs.size(), event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- verifier_.VerifyLoggedFir(timestamps_us[i], events[i], firs[i]);
+ verifier_.VerifyLoggedFir(timestamps_ms[i], events[i], firs[i]);
}
}
}
@@ -948,9 +1008,9 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPli) {
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::Pli> events(event_count_);
- std::vector<int64_t> timestamps_us(event_count_);
+ std::vector<int64_t> timestamps_ms(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- timestamps_us[i] = rtc::TimeMicros();
+ timestamps_ms[i] = rtc::TimeMillis();
events[i] = gen_.NewPli();
rtc::Buffer buffer = events[i].Build();
if (direction == kIncomingPacket) {
@@ -963,15 +1023,51 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPli) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- std::string encoded =
- encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& plis = parsed_log_.plis(direction);
ASSERT_EQ(plis.size(), event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- verifier_.VerifyLoggedPli(timestamps_us[i], events[i], plis[i]);
+ verifier_.VerifyLoggedPli(timestamps_ms[i], events[i], plis[i]);
+ }
+ }
+}
+
+TEST_P(RtcEventLogEncoderTest, RtcEventRtcpBye) {
+ if (force_repeated_fields_) {
+ return;
+ }
+
+ rtc::ScopedFakeClock fake_clock;
+ fake_clock.SetTime(Timestamp::Millis(prng_.Rand<uint32_t>()));
+
+ for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
+ std::vector<rtcp::Bye> events(event_count_);
+ std::vector<int64_t> timestamps_ms(event_count_);
+ for (size_t i = 0; i < event_count_; ++i) {
+ timestamps_ms[i] = rtc::TimeMillis();
+ events[i] = gen_.NewBye();
+ rtc::Buffer buffer = events[i].Build();
+ if (direction == kIncomingPacket) {
+ history_.push_back(
+ std::make_unique<RtcEventRtcpPacketIncoming>(buffer));
+ } else {
+ history_.push_back(
+ std::make_unique<RtcEventRtcpPacketOutgoing>(buffer));
+ }
+ fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
+ }
+
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
+
+ const auto& byes = parsed_log_.byes(direction);
+ ASSERT_EQ(byes.size(), event_count_);
+
+ for (size_t i = 0; i < event_count_; ++i) {
+ verifier_.VerifyLoggedBye(timestamps_ms[i], events[i], byes[i]);
}
}
}
@@ -986,9 +1082,9 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpNack) {
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::Nack> events(event_count_);
- std::vector<int64_t> timestamps_us(event_count_);
+ std::vector<int64_t> timestamps_ms(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- timestamps_us[i] = rtc::TimeMicros();
+ timestamps_ms[i] = rtc::TimeMillis();
events[i] = gen_.NewNack();
rtc::Buffer buffer = events[i].Build();
if (direction == kIncomingPacket) {
@@ -1001,15 +1097,14 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpNack) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- std::string encoded =
- encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& nacks = parsed_log_.nacks(direction);
ASSERT_EQ(nacks.size(), event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- verifier_.VerifyLoggedNack(timestamps_us[i], events[i], nacks[i]);
+ verifier_.VerifyLoggedNack(timestamps_ms[i], events[i], nacks[i]);
}
}
}
@@ -1024,9 +1119,9 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpRemb) {
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::Remb> events(event_count_);
- std::vector<int64_t> timestamps_us(event_count_);
+ std::vector<int64_t> timestamps_ms(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- timestamps_us[i] = rtc::TimeMicros();
+ timestamps_ms[i] = rtc::TimeMillis();
events[i] = gen_.NewRemb();
rtc::Buffer buffer = events[i].Build();
if (direction == kIncomingPacket) {
@@ -1039,15 +1134,14 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpRemb) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- std::string encoded =
- encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& rembs = parsed_log_.rembs(direction);
ASSERT_EQ(rembs.size(), event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- verifier_.VerifyLoggedRemb(timestamps_us[i], events[i], rembs[i]);
+ verifier_.VerifyLoggedRemb(timestamps_ms[i], events[i], rembs[i]);
}
}
}
@@ -1063,9 +1157,9 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpTransportFeedback) {
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::TransportFeedback> events;
events.reserve(event_count_);
- std::vector<int64_t> timestamps_us(event_count_);
+ std::vector<int64_t> timestamps_ms(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- timestamps_us[i] = rtc::TimeMicros();
+ timestamps_ms[i] = rtc::TimeMillis();
events.emplace_back(gen_.NewTransportFeedback());
rtc::Buffer buffer = events[i].Build();
if (direction == kIncomingPacket) {
@@ -1078,16 +1172,15 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpTransportFeedback) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- std::string encoded =
- encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& transport_feedbacks =
parsed_log_.transport_feedbacks(direction);
ASSERT_EQ(transport_feedbacks.size(), event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- verifier_.VerifyLoggedTransportFeedback(timestamps_us[i], events[i],
+ verifier_.VerifyLoggedTransportFeedback(timestamps_ms[i], events[i],
transport_feedbacks[i]);
}
}
@@ -1104,9 +1197,9 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpLossNotification) {
for (auto direction : {kIncomingPacket, kOutgoingPacket}) {
std::vector<rtcp::LossNotification> events;
events.reserve(event_count_);
- std::vector<int64_t> timestamps_us(event_count_);
+ std::vector<int64_t> timestamps_ms(event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- timestamps_us[i] = rtc::TimeMicros();
+ timestamps_ms[i] = rtc::TimeMillis();
events.emplace_back(gen_.NewLossNotification());
rtc::Buffer buffer = events[i].Build();
if (direction == kIncomingPacket) {
@@ -1119,15 +1212,14 @@ TEST_P(RtcEventLogEncoderTest, RtcEventRtcpLossNotification) {
fake_clock.AdvanceTime(TimeDelta::Millis(prng_.Rand(0, 1000)));
}
- std::string encoded =
- encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& loss_notifications = parsed_log_.loss_notifications(direction);
ASSERT_EQ(loss_notifications.size(), event_count_);
for (size_t i = 0; i < event_count_; ++i) {
- verifier_.VerifyLoggedLossNotification(timestamps_us[i], events[i],
+ verifier_.VerifyLoggedLossNotification(timestamps_ms[i], events[i],
loss_notifications[i]);
}
}
@@ -1149,8 +1241,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventVideoReceiveStreamConfig) {
gen_.NewVideoReceiveStreamConfig(ssrc, extensions);
history_.push_back(event->Copy());
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& video_recv_configs = parsed_log_.video_recv_configs();
ASSERT_EQ(video_recv_configs.size(), 1u);
@@ -1165,8 +1257,8 @@ TEST_P(RtcEventLogEncoderTest, RtcEventVideoSendStreamConfig) {
gen_.NewVideoSendStreamConfig(ssrc, extensions);
history_.push_back(event->Copy());
- std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
- ASSERT_TRUE(parsed_log_.ParseString(encoded).ok());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+ ASSERT_TRUE(parsed_log_.ParseString(encoded_).ok());
const auto& video_send_configs = parsed_log_.video_send_configs();
ASSERT_EQ(video_send_configs.size(), 1u);
@@ -1177,8 +1269,75 @@ INSTANTIATE_TEST_SUITE_P(
RandomSeeds,
RtcEventLogEncoderTest,
::testing::Combine(/* Random seed*: */ ::testing::Values(1, 2, 3, 4, 5),
- /* Encoding: */ ::testing::Bool(),
+ /* Encoding: */
+ ::testing::Values(RtcEventLog::EncodingType::Legacy,
+ RtcEventLog::EncodingType::NewFormat),
/* Event count: */ ::testing::Values(1, 2, 10, 100),
/* Repeated fields: */ ::testing::Bool()));
+class RtcEventLogEncoderSimpleTest
+ : public ::testing::TestWithParam<RtcEventLog::EncodingType> {
+ protected:
+ RtcEventLogEncoderSimpleTest() : encoding_type_(GetParam()) {
+ switch (encoding_type_) {
+ case RtcEventLog::EncodingType::Legacy:
+ encoder_ = std::make_unique<RtcEventLogEncoderLegacy>();
+ break;
+ case RtcEventLog::EncodingType::NewFormat:
+ encoder_ = std::make_unique<RtcEventLogEncoderNewFormat>();
+ break;
+ case RtcEventLog::EncodingType::ProtoFree:
+ encoder_ = std::make_unique<RtcEventLogEncoderV3>();
+ break;
+ }
+ encoded_ =
+ encoder_->EncodeLogStart(rtc::TimeMillis(), rtc::TimeUTCMillis());
+ }
+ ~RtcEventLogEncoderSimpleTest() override = default;
+
+ std::deque<std::unique_ptr<RtcEvent>> history_;
+ std::unique_ptr<RtcEventLogEncoder> encoder_;
+ ParsedRtcEventLog parsed_log_;
+ const RtcEventLog::EncodingType encoding_type_;
+ std::string encoded_;
+};
+
+TEST_P(RtcEventLogEncoderSimpleTest, RtcEventLargeCompoundRtcpPacketIncoming) {
+ // Create a compound packet containing multiple Bye messages.
+ rtc::Buffer packet;
+ size_t index = 0;
+ for (int i = 0; i < 8; i++) {
+ rtcp::Bye bye;
+ std::string reason(255, 'a'); // Add some arbitrary data.
+ bye.SetReason(reason);
+ bye.SetSenderSsrc(0x12345678);
+ packet.SetSize(packet.size() + bye.BlockLength());
+ bool created =
+ bye.Create(packet.data(), &index, packet.capacity(), nullptr);
+ ASSERT_TRUE(created);
+ ASSERT_EQ(index, packet.size());
+ }
+
+ EXPECT_GT(packet.size(), static_cast<size_t>(IP_PACKET_SIZE));
+ auto event = std::make_unique<RtcEventRtcpPacketIncoming>(packet);
+ history_.push_back(event->Copy());
+ encoded_ += encoder_->EncodeBatch(history_.begin(), history_.end());
+
+ ParsedRtcEventLog::ParseStatus status = parsed_log_.ParseString(encoded_);
+ ASSERT_TRUE(status.ok()) << status.message();
+
+ const auto& incoming_rtcp_packets = parsed_log_.incoming_rtcp_packets();
+ ASSERT_EQ(incoming_rtcp_packets.size(), 1u);
+ ASSERT_EQ(incoming_rtcp_packets[0].rtcp.raw_data.size(), packet.size());
+ EXPECT_EQ(memcmp(incoming_rtcp_packets[0].rtcp.raw_data.data(), packet.data(),
+ packet.size()),
+ 0);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ LargeCompoundRtcp,
+ RtcEventLogEncoderSimpleTest,
+ ::testing::Values(RtcEventLog::EncodingType::Legacy,
+ RtcEventLog::EncodingType::NewFormat));
+
} // namespace webrtc
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.cc b/logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.cc
new file mode 100644
index 0000000000..131aae1de8
--- /dev/null
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.cc
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.h"
+
+#include <string>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h"
+#include "logging/rtc_event_log/encoder/var_int.h"
+#include "logging/rtc_event_log/events/rtc_event_alr_state.h"
+#include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
+#include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
+#include "logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h"
+#include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
+#include "logging/rtc_event_log/events/rtc_event_begin_log.h"
+#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
+#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
+#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
+#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
+#include "logging/rtc_event_log/events/rtc_event_end_log.h"
+#include "logging/rtc_event_log/events/rtc_event_frame_decoded.h"
+#include "logging/rtc_event_log/events/rtc_event_generic_ack_received.h"
+#include "logging/rtc_event_log/events/rtc_event_generic_packet_received.h"
+#include "logging/rtc_event_log/events/rtc_event_generic_packet_sent.h"
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
+#include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
+#include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
+#include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
+#include "logging/rtc_event_log/events/rtc_event_remote_estimate.h"
+#include "logging/rtc_event_log/events/rtc_event_route_change.h"
+#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h"
+#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h"
+#include "logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h"
+#include "logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h"
+#include "logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h"
+#include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+
+std::string RtcEventLogEncoderV3::EncodeLogStart(int64_t timestamp_us,
+ int64_t utc_time_us) {
+ std::unique_ptr<RtcEventBeginLog> begin_log =
+ std::make_unique<RtcEventBeginLog>(Timestamp::Micros(timestamp_us),
+ Timestamp::Micros(utc_time_us));
+ std::vector<const RtcEvent*> batch;
+ batch.push_back(begin_log.get());
+
+ std::string encoded_event = RtcEventBeginLog::Encode(batch);
+
+ return encoded_event;
+}
+
+std::string RtcEventLogEncoderV3::EncodeLogEnd(int64_t timestamp_us) {
+ std::unique_ptr<RtcEventEndLog> end_log =
+ std::make_unique<RtcEventEndLog>(Timestamp::Micros(timestamp_us));
+ std::vector<const RtcEvent*> batch;
+ batch.push_back(end_log.get());
+
+ std::string encoded_event = RtcEventEndLog::Encode(batch);
+
+ return encoded_event;
+}
+
+RtcEventLogEncoderV3::RtcEventLogEncoderV3() {
+ encoders_[RtcEvent::Type::AlrStateEvent] = RtcEventAlrState::Encode;
+ encoders_[RtcEvent::Type::AudioNetworkAdaptation] =
+ RtcEventAudioNetworkAdaptation::Encode;
+ encoders_[RtcEvent::Type::AudioPlayout] = RtcEventAudioPlayout::Encode;
+ encoders_[RtcEvent::Type::AudioReceiveStreamConfig] =
+ RtcEventAudioReceiveStreamConfig::Encode;
+ encoders_[RtcEvent::Type::AudioSendStreamConfig] =
+ RtcEventAudioSendStreamConfig::Encode;
+ encoders_[RtcEvent::Type::BweUpdateDelayBased] =
+ RtcEventBweUpdateDelayBased::Encode;
+ encoders_[RtcEvent::Type::BweUpdateLossBased] =
+ RtcEventBweUpdateLossBased::Encode;
+ encoders_[RtcEvent::Type::DtlsTransportState] =
+ RtcEventDtlsTransportState::Encode;
+ encoders_[RtcEvent::Type::DtlsWritableState] =
+ RtcEventDtlsWritableState::Encode;
+ encoders_[RtcEvent::Type::FrameDecoded] = RtcEventFrameDecoded::Encode;
+ encoders_[RtcEvent::Type::GenericAckReceived] =
+ RtcEventGenericAckReceived::Encode;
+ encoders_[RtcEvent::Type::GenericPacketReceived] =
+ RtcEventGenericPacketReceived::Encode;
+ encoders_[RtcEvent::Type::GenericPacketSent] =
+ RtcEventGenericPacketSent::Encode;
+ encoders_[RtcEvent::Type::IceCandidatePairConfig] =
+ RtcEventIceCandidatePairConfig::Encode;
+ encoders_[RtcEvent::Type::IceCandidatePairEvent] =
+ RtcEventIceCandidatePair::Encode;
+ encoders_[RtcEvent::Type::ProbeClusterCreated] =
+ RtcEventProbeClusterCreated::Encode;
+ encoders_[RtcEvent::Type::ProbeResultFailure] =
+ RtcEventProbeResultFailure::Encode;
+ encoders_[RtcEvent::Type::ProbeResultSuccess] =
+ RtcEventProbeResultSuccess::Encode;
+ encoders_[RtcEvent::Type::RemoteEstimateEvent] =
+ RtcEventRemoteEstimate::Encode;
+ encoders_[RtcEvent::Type::RouteChangeEvent] = RtcEventRouteChange::Encode;
+ encoders_[RtcEvent::Type::RtcpPacketIncoming] =
+ RtcEventRtcpPacketIncoming::Encode;
+ encoders_[RtcEvent::Type::RtcpPacketOutgoing] =
+ RtcEventRtcpPacketOutgoing::Encode;
+ encoders_[RtcEvent::Type::RtpPacketIncoming] =
+ RtcEventRtpPacketIncoming::Encode;
+ encoders_[RtcEvent::Type::RtpPacketOutgoing] =
+ RtcEventRtpPacketOutgoing::Encode;
+ encoders_[RtcEvent::Type::VideoReceiveStreamConfig] =
+ RtcEventVideoReceiveStreamConfig::Encode;
+ encoders_[RtcEvent::Type::VideoSendStreamConfig] =
+ RtcEventVideoSendStreamConfig::Encode;
+}
+
+std::string RtcEventLogEncoderV3::EncodeBatch(
+ std::deque<std::unique_ptr<RtcEvent>>::const_iterator begin,
+ std::deque<std::unique_ptr<RtcEvent>>::const_iterator end) {
+ struct EventGroupKey {
+ // Events are grouped by event type. For compression efficiency,
+ // events can optionally have a secondary key, in most cases the
+ // SSRC.
+ RtcEvent::Type type;
+ uint32_t secondary_group_key;
+
+ bool operator<(EventGroupKey other) const {
+ return type < other.type ||
+ (type == other.type &&
+ secondary_group_key < other.secondary_group_key);
+ }
+ };
+
+ std::map<EventGroupKey, std::vector<const RtcEvent*>> event_groups;
+
+ for (auto it = begin; it != end; ++it) {
+ event_groups[{(*it)->GetType(), (*it)->GetGroupKey()}].push_back(it->get());
+ }
+
+ std::string encoded_output;
+ for (auto& kv : event_groups) {
+ auto it = encoders_.find(kv.first.type);
+ RTC_DCHECK(it != encoders_.end());
+ if (it != encoders_.end()) {
+ auto& encoder = it->second;
+ // TODO(terelius): Use some "string builder" or preallocate?
+ encoded_output += encoder(kv.second);
+ }
+ }
+
+ return encoded_output;
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.h b/logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.h
new file mode 100644
index 0000000000..cb796ec562
--- /dev/null
+++ b/logging/rtc_event_log/encoder/rtc_event_log_encoder_v3.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_V3_H_
+#define LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_V3_H_
+
+#include <deque>
+#include <map>
+#include <memory>
+#include <string>
+
+#include "api/array_view.h"
+#include "logging/rtc_event_log/encoder/rtc_event_log_encoder.h"
+#include "logging/rtc_event_log/events/rtc_event_definition.h"
+
+namespace webrtc {
+
+class RtcEventLogEncoderV3 final : public RtcEventLogEncoder {
+ public:
+ RtcEventLogEncoderV3();
+ ~RtcEventLogEncoderV3() override = default;
+
+ std::string EncodeBatch(
+ std::deque<std::unique_ptr<RtcEvent>>::const_iterator begin,
+ std::deque<std::unique_ptr<RtcEvent>>::const_iterator end) override;
+
+ std::string EncodeLogStart(int64_t timestamp_us,
+ int64_t utc_time_us) override;
+ std::string EncodeLogEnd(int64_t timestamp_us) override;
+
+ private:
+ std::map<RtcEvent::Type,
+ std::function<std::string(rtc::ArrayView<const RtcEvent*>)>>
+ encoders_;
+};
+
+} // namespace webrtc
+
+#endif // LOGGING_RTC_EVENT_LOG_ENCODER_RTC_EVENT_LOG_ENCODER_V3_H_
diff --git a/logging/rtc_event_log/encoder/var_int.cc b/logging/rtc_event_log/encoder/var_int.cc
index b2c695ee78..a84a233d6b 100644
--- a/logging/rtc_event_log/encoder/var_int.cc
+++ b/logging/rtc_event_log/encoder/var_int.cc
@@ -10,6 +10,7 @@
#include "logging/rtc_event_log/encoder/var_int.h"
+#include "rtc_base/bitstream_reader.h"
#include "rtc_base/checks.h"
// TODO(eladalon): Add unit tests.
@@ -39,7 +40,8 @@ std::string EncodeVarInt(uint64_t input) {
// There is some code duplication between the flavors of this function.
// For performance's sake, it's best to just keep it.
-size_t DecodeVarInt(absl::string_view input, uint64_t* output) {
+std::pair<bool, absl::string_view> DecodeVarInt(absl::string_view input,
+ uint64_t* output) {
RTC_DCHECK(output);
uint64_t decoded = 0;
@@ -48,32 +50,27 @@ size_t DecodeVarInt(absl::string_view input, uint64_t* output) {
<< static_cast<uint64_t>(7 * i));
if (!(input[i] & 0x80)) {
*output = decoded;
- return i + 1;
+ return {true, input.substr(i + 1)};
}
}
- return 0;
+ return {false, input};
}
// There is some code duplication between the flavors of this function.
// For performance's sake, it's best to just keep it.
-size_t DecodeVarInt(rtc::BitBuffer* input, uint64_t* output) {
- RTC_DCHECK(output);
-
+uint64_t DecodeVarInt(BitstreamReader& input) {
uint64_t decoded = 0;
for (size_t i = 0; i < kMaxVarIntLengthBytes; ++i) {
- uint8_t byte;
- if (!input->ReadUInt8(&byte)) {
- return 0;
- }
+ uint8_t byte = input.Read<uint8_t>();
decoded +=
(static_cast<uint64_t>(byte & 0x7f) << static_cast<uint64_t>(7 * i));
if (!(byte & 0x80)) {
- *output = decoded;
- return i + 1;
+ return decoded;
}
}
+ input.Invalidate();
return 0;
}
diff --git a/logging/rtc_event_log/encoder/var_int.h b/logging/rtc_event_log/encoder/var_int.h
index 178c9cec18..4624e046ba 100644
--- a/logging/rtc_event_log/encoder/var_int.h
+++ b/logging/rtc_event_log/encoder/var_int.h
@@ -15,9 +15,10 @@
#include <stdint.h>
#include <string>
+#include <utility>
#include "absl/strings/string_view.h"
-#include "rtc_base/bit_buffer.h"
+#include "rtc_base/bitstream_reader.h"
namespace webrtc {
@@ -26,22 +27,23 @@ extern const size_t kMaxVarIntLengthBytes;
// Encode a given uint64_t as a varint. From least to most significant,
// each batch of seven bits are put into the lower bits of a byte, and the last
// remaining bit in that byte (the highest one) marks whether additional bytes
-// follow (which happens if and only if there are other bits in |input| which
+// follow (which happens if and only if there are other bits in `input` which
// are non-zero).
// Notes: If input == 0, one byte is used. If input is uint64_t::max, exactly
// kMaxVarIntLengthBytes are used.
std::string EncodeVarInt(uint64_t input);
// Inverse of EncodeVarInt().
-// If decoding is successful, a non-zero number is returned, indicating the
-// number of bytes read from |input|, and the decoded varint is written
-// into |output|.
-// If not successful, 0 is returned, and |output| is not modified.
-size_t DecodeVarInt(absl::string_view input, uint64_t* output);
-
-// Same as other version, but uses a rtc::BitBuffer for input.
-// Some bits may be consumed even if a varint fails to be read.
-size_t DecodeVarInt(rtc::BitBuffer* input, uint64_t* output);
+// Returns true and the remaining (unread) slice of the input if decoding
+// succeeds. Returns false otherwise and `output` is not modified.
+std::pair<bool, absl::string_view> DecodeVarInt(absl::string_view input,
+ uint64_t* output);
+
+// Same as other version, but uses a BitstreamReader for input.
+// If decoding is successful returns the decoded varint.
+// If not successful, `input` reader is set into the failure state, return value
+// is unspecified.
+uint64_t DecodeVarInt(BitstreamReader& input);
} // namespace webrtc
diff --git a/logging/rtc_event_log/events/fixed_length_encoding_parameters_v3.cc b/logging/rtc_event_log/events/fixed_length_encoding_parameters_v3.cc
new file mode 100644
index 0000000000..0c93e6226d
--- /dev/null
+++ b/logging/rtc_event_log/events/fixed_length_encoding_parameters_v3.cc
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/events/fixed_length_encoding_parameters_v3.h"
+
+#include <algorithm>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
+#include "rtc_base/logging.h"
+
+using webrtc_event_logging::MaxUnsignedValueOfBitWidth;
+using webrtc_event_logging::SignedBitWidth;
+using webrtc_event_logging::UnsignedBitWidth;
+using webrtc_event_logging::UnsignedDelta;
+
+namespace webrtc {
+
+FixedLengthEncodingParametersV3
+FixedLengthEncodingParametersV3::CalculateParameters(
+ uint64_t base,
+ const rtc::ArrayView<const uint64_t> values,
+ uint64_t value_bit_width,
+ bool values_optional) {
+ // As a special case, if all of the elements are identical to the base
+ // we just encode the base value with a special delta header.
+ if (std::all_of(values.cbegin(), values.cend(),
+ [base](uint64_t val) { return val == base; })) {
+ // Delta header with signed=true and delta_bitwidth=64
+ return FixedLengthEncodingParametersV3(/*delta_bit_width=*/64,
+ /*signed_deltas=*/true,
+ values_optional, value_bit_width);
+ }
+
+ const uint64_t bit_mask = MaxUnsignedValueOfBitWidth(value_bit_width);
+
+ // Calculate the bitwidth required to encode all deltas when using a
+ // unsigned or signed represenation, respectively. For the unsigned
+ // representation, we just track the largest delta. For the signed
+ // representation, we have two possibilities for each delta; either
+ // going "forward" (i.e. current - previous) or "backwards"
+ // (i.e. previous - current) where both values are calculated with
+ // wrap around. We then track the largest positive and negative
+ // magnitude across the batch, assuming that we choose the smaller
+ // delta for each element.
+ uint64_t max_unsigned_delta = 0;
+ uint64_t max_positive_signed_delta = 0;
+ uint64_t min_negative_signed_delta = 0;
+ uint64_t prev = base;
+ for (uint64_t current : values) {
+ uint64_t positive_delta = UnsignedDelta(prev, current, bit_mask);
+ uint64_t negative_delta = UnsignedDelta(current, prev, bit_mask);
+
+ max_unsigned_delta = std::max(max_unsigned_delta, positive_delta);
+
+ if (positive_delta < negative_delta) {
+ max_positive_signed_delta =
+ std::max(max_positive_signed_delta, positive_delta);
+ } else {
+ min_negative_signed_delta =
+ std::max(min_negative_signed_delta, negative_delta);
+ }
+
+ prev = current;
+ }
+
+ // We now know the largest unsigned delta and the largest magnitudes of
+ // positive and negative signed deltas. Get the bitwidths required for
+ // each of the two encodings.
+ const uint64_t unsigned_delta_bit_width =
+ UnsignedBitWidth(max_unsigned_delta);
+ const uint64_t signed_delta_bit_width =
+ SignedBitWidth(max_positive_signed_delta, min_negative_signed_delta);
+
+ // Note: Preference for unsigned if the two have the same width (efficiency).
+ bool use_signed_deltas = signed_delta_bit_width < unsigned_delta_bit_width;
+ uint64_t delta_bit_width =
+ use_signed_deltas ? signed_delta_bit_width : unsigned_delta_bit_width;
+
+ // use_signed_deltas && delta_bit_width==64 is reserved for "all values
+ // equal".
+ RTC_DCHECK(!use_signed_deltas || delta_bit_width < 64);
+
+ RTC_DCHECK(ValidParameters(delta_bit_width, use_signed_deltas,
+ values_optional, value_bit_width));
+ return FixedLengthEncodingParametersV3(delta_bit_width, use_signed_deltas,
+ values_optional, value_bit_width);
+}
+
+uint64_t FixedLengthEncodingParametersV3::DeltaHeaderAsInt() const {
+ uint64_t header = delta_bit_width_ - 1;
+ RTC_CHECK_LT(header, 1u << 6);
+ if (signed_deltas_) {
+ header += 1u << 6;
+ }
+ RTC_CHECK_LT(header, 1u << 7);
+ if (values_optional_) {
+ header += 1u << 7;
+ }
+ return header;
+}
+
+absl::optional<FixedLengthEncodingParametersV3>
+FixedLengthEncodingParametersV3::ParseDeltaHeader(uint64_t header,
+ uint64_t value_bit_width) {
+ uint64_t delta_bit_width = (header & ((1u << 6) - 1)) + 1;
+ bool signed_deltas = header & (1u << 6);
+ bool values_optional = header & (1u << 7);
+
+ if (header >= (1u << 8)) {
+ RTC_LOG(LS_ERROR) << "Failed to parse delta header; unread bits remaining.";
+ return absl::nullopt;
+ }
+
+ if (!ValidParameters(delta_bit_width, signed_deltas, values_optional,
+ value_bit_width)) {
+ RTC_LOG(LS_ERROR) << "Failed to parse delta header. Invalid combination of "
+ "values: delta_bit_width="
+ << delta_bit_width << " signed_deltas=" << signed_deltas
+ << " values_optional=" << values_optional
+ << " value_bit_width=" << value_bit_width;
+ return absl::nullopt;
+ }
+
+ return FixedLengthEncodingParametersV3(delta_bit_width, signed_deltas,
+ values_optional, value_bit_width);
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/events/fixed_length_encoding_parameters_v3.h b/logging/rtc_event_log/events/fixed_length_encoding_parameters_v3.h
new file mode 100644
index 0000000000..666fae1c63
--- /dev/null
+++ b/logging/rtc_event_log/events/fixed_length_encoding_parameters_v3.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_FIXED_LENGTH_ENCODING_PARAMETERS_V3_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_FIXED_LENGTH_ENCODING_PARAMETERS_V3_H_
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
+
+namespace webrtc {
+
+// Parameters for fixed-size delta-encoding/decoding.
+// These are tailored for the sequence which will be encoded (e.g. widths).
+class FixedLengthEncodingParametersV3 final {
+ public:
+ static bool ValidParameters(uint64_t delta_bit_width,
+ bool signed_deltas,
+ bool values_optional,
+ uint64_t value_bit_width) {
+ return (1 <= delta_bit_width && delta_bit_width <= 64 &&
+ 1 <= value_bit_width && value_bit_width <= 64 &&
+ (delta_bit_width <= value_bit_width ||
+ (signed_deltas && delta_bit_width == 64)));
+ }
+
+ static FixedLengthEncodingParametersV3 CalculateParameters(
+ uint64_t base,
+ rtc::ArrayView<const uint64_t> values,
+ uint64_t value_bit_width,
+ bool values_optional);
+ static absl::optional<FixedLengthEncodingParametersV3> ParseDeltaHeader(
+ uint64_t header,
+ uint64_t value_bit_width);
+
+ uint64_t DeltaHeaderAsInt() const;
+
+ // Number of bits necessary to hold the widest(*) of the deltas between the
+ // values in the sequence.
+ // (*) - Widest might not be the largest, if signed deltas are used.
+ uint64_t delta_bit_width() const { return delta_bit_width_; }
+
+ // Whether deltas are signed.
+ bool signed_deltas() const { return signed_deltas_; }
+
+ // Whether the values of the sequence are optional. That is, it may be
+ // that some of them do not have a value (not even a sentinel value indicating
+ // invalidity).
+ bool values_optional() const { return values_optional_; }
+
+ // Whether all values are equal. 64-bit signed deltas are assumed to not
+ // occur, since those could equally well be represented using 64 bit unsigned
+ // deltas.
+ bool values_equal() const {
+ return delta_bit_width() == 64 && signed_deltas();
+ }
+
+ // Number of bits necessary to hold the largest value in the sequence.
+ uint64_t value_bit_width() const { return value_bit_width_; }
+
+ // Masks where only the bits relevant to the deltas/values are turned on.
+ uint64_t delta_mask() const { return delta_mask_; }
+ uint64_t value_mask() const { return value_mask_; }
+
+ private:
+ FixedLengthEncodingParametersV3(uint64_t delta_bit_width,
+ bool signed_deltas,
+ bool values_optional,
+ uint64_t value_bit_width)
+ : delta_bit_width_(delta_bit_width),
+ signed_deltas_(signed_deltas),
+ values_optional_(values_optional),
+ value_bit_width_(value_bit_width),
+ delta_mask_(
+ webrtc_event_logging::MaxUnsignedValueOfBitWidth(delta_bit_width_)),
+ value_mask_(webrtc_event_logging::MaxUnsignedValueOfBitWidth(
+ value_bit_width_)) {}
+
+ uint64_t delta_bit_width_;
+ bool signed_deltas_;
+ bool values_optional_;
+ uint64_t value_bit_width_;
+
+ uint64_t delta_mask_;
+ uint64_t value_mask_;
+};
+
+} // namespace webrtc
+#endif // LOGGING_RTC_EVENT_LOG_EVENTS_FIXED_LENGTH_ENCODING_PARAMETERS_V3_H_
diff --git a/logging/rtc_event_log/events/logged_rtp_rtcp.h b/logging/rtc_event_log/events/logged_rtp_rtcp.h
new file mode 100644
index 0000000000..00689a0a16
--- /dev/null
+++ b/logging/rtc_event_log/events/logged_rtp_rtcp.h
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2022 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_LOGGED_RTP_RTCP_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_LOGGED_RTP_RTCP_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/rtp_headers.h"
+#include "api/units/timestamp.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/fir.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/loss_notification.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/pli.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/remb.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
+
+namespace webrtc {
+
+struct LoggedRtpPacket {
+ LoggedRtpPacket(Timestamp timestamp,
+ RTPHeader header,
+ size_t header_length,
+ size_t total_length)
+ : timestamp(timestamp),
+ header(header),
+ header_length(header_length),
+ total_length(total_length) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp;
+ // TODO(terelius): This allocates space for 15 CSRCs even if none are used.
+ RTPHeader header;
+ size_t header_length;
+ size_t total_length;
+};
+
+struct LoggedRtpPacketIncoming {
+ LoggedRtpPacketIncoming(Timestamp timestamp,
+ RTPHeader header,
+ size_t header_length,
+ size_t total_length)
+ : rtp(timestamp, header, header_length, total_length) {}
+ int64_t log_time_us() const { return rtp.timestamp.us(); }
+ int64_t log_time_ms() const { return rtp.timestamp.ms(); }
+ Timestamp log_time() const { return rtp.timestamp; }
+
+ LoggedRtpPacket rtp;
+};
+
+struct LoggedRtpPacketOutgoing {
+ LoggedRtpPacketOutgoing(Timestamp timestamp,
+ RTPHeader header,
+ size_t header_length,
+ size_t total_length)
+ : rtp(timestamp, header, header_length, total_length) {}
+ int64_t log_time_us() const { return rtp.timestamp.us(); }
+ int64_t log_time_ms() const { return rtp.timestamp.ms(); }
+ Timestamp log_time() const { return rtp.timestamp; }
+
+ LoggedRtpPacket rtp;
+};
+
+struct LoggedRtcpPacket {
+ LoggedRtcpPacket(Timestamp timestamp, const std::vector<uint8_t>& packet)
+ : timestamp(timestamp), raw_data(packet) {}
+ LoggedRtcpPacket(Timestamp timestamp, absl::string_view packet)
+ : timestamp(timestamp), raw_data(packet.size()) {
+ memcpy(raw_data.data(), packet.data(), packet.size());
+ }
+
+ LoggedRtcpPacket(const LoggedRtcpPacket& rhs) = default;
+
+ ~LoggedRtcpPacket() = default;
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp;
+ std::vector<uint8_t> raw_data;
+};
+
+struct LoggedRtcpPacketIncoming {
+ LoggedRtcpPacketIncoming(Timestamp timestamp,
+ const std::vector<uint8_t>& packet)
+ : rtcp(timestamp, packet) {}
+ LoggedRtcpPacketIncoming(Timestamp timestamp, absl::string_view packet)
+ : rtcp(timestamp, packet) {}
+
+ int64_t log_time_us() const { return rtcp.timestamp.us(); }
+ int64_t log_time_ms() const { return rtcp.timestamp.ms(); }
+ Timestamp log_time() const { return rtcp.timestamp; }
+
+ LoggedRtcpPacket rtcp;
+};
+
+struct LoggedRtcpPacketOutgoing {
+ LoggedRtcpPacketOutgoing(Timestamp timestamp,
+ const std::vector<uint8_t>& packet)
+ : rtcp(timestamp, packet) {}
+ LoggedRtcpPacketOutgoing(Timestamp timestamp, absl::string_view packet)
+ : rtcp(timestamp, packet) {}
+
+ int64_t log_time_us() const { return rtcp.timestamp.us(); }
+ int64_t log_time_ms() const { return rtcp.timestamp.ms(); }
+ Timestamp log_time() const { return rtcp.timestamp; }
+
+ LoggedRtcpPacket rtcp;
+};
+
+struct LoggedRtcpPacketReceiverReport {
+ LoggedRtcpPacketReceiverReport() = default;
+ LoggedRtcpPacketReceiverReport(Timestamp timestamp,
+ const rtcp::ReceiverReport& rr)
+ : timestamp(timestamp), rr(rr) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtcp::ReceiverReport rr;
+};
+
+struct LoggedRtcpPacketSenderReport {
+ LoggedRtcpPacketSenderReport() = default;
+ LoggedRtcpPacketSenderReport(Timestamp timestamp,
+ const rtcp::SenderReport& sr)
+ : timestamp(timestamp), sr(sr) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtcp::SenderReport sr;
+};
+
+struct LoggedRtcpPacketExtendedReports {
+ LoggedRtcpPacketExtendedReports() = default;
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtcp::ExtendedReports xr;
+};
+
+struct LoggedRtcpPacketRemb {
+ LoggedRtcpPacketRemb() = default;
+ LoggedRtcpPacketRemb(Timestamp timestamp, const rtcp::Remb& remb)
+ : timestamp(timestamp), remb(remb) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtcp::Remb remb;
+};
+
+struct LoggedRtcpPacketNack {
+ LoggedRtcpPacketNack() = default;
+ LoggedRtcpPacketNack(Timestamp timestamp, const rtcp::Nack& nack)
+ : timestamp(timestamp), nack(nack) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtcp::Nack nack;
+};
+
+struct LoggedRtcpPacketFir {
+ LoggedRtcpPacketFir() = default;
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtcp::Fir fir;
+};
+
+struct LoggedRtcpPacketPli {
+ LoggedRtcpPacketPli() = default;
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtcp::Pli pli;
+};
+
+struct LoggedRtcpPacketTransportFeedback {
+ LoggedRtcpPacketTransportFeedback()
+ : transport_feedback(/*include_timestamps=*/true, /*include_lost*/ true) {
+ }
+ LoggedRtcpPacketTransportFeedback(
+ Timestamp timestamp,
+ const rtcp::TransportFeedback& transport_feedback)
+ : timestamp(timestamp), transport_feedback(transport_feedback) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtcp::TransportFeedback transport_feedback;
+};
+
+struct LoggedRtcpPacketLossNotification {
+ LoggedRtcpPacketLossNotification() = default;
+ LoggedRtcpPacketLossNotification(
+ Timestamp timestamp,
+ const rtcp::LossNotification& loss_notification)
+ : timestamp(timestamp), loss_notification(loss_notification) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtcp::LossNotification loss_notification;
+};
+
+struct LoggedRtcpPacketBye {
+ LoggedRtcpPacketBye() = default;
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtcp::Bye bye;
+};
+
+} // namespace webrtc
+
+#endif // LOGGING_RTC_EVENT_LOG_EVENTS_LOGGED_RTP_RTCP_H_
diff --git a/logging/rtc_event_log/events/rtc_event_alr_state.cc b/logging/rtc_event_log/events/rtc_event_alr_state.cc
index 8ab7f798c0..25941eb16b 100644
--- a/logging/rtc_event_log/events/rtc_event_alr_state.cc
+++ b/logging/rtc_event_log/events/rtc_event_alr_state.cc
@@ -13,6 +13,9 @@
#include "absl/memory/memory.h"
namespace webrtc {
+constexpr RtcEvent::Type RtcEventAlrState::kType;
+constexpr RtcEventDefinition<RtcEventAlrState, LoggedAlrStateEvent, bool>
+ RtcEventAlrState::definition_;
RtcEventAlrState::RtcEventAlrState(bool in_alr) : in_alr_(in_alr) {}
@@ -21,16 +24,15 @@ RtcEventAlrState::RtcEventAlrState(const RtcEventAlrState& other)
RtcEventAlrState::~RtcEventAlrState() = default;
-RtcEvent::Type RtcEventAlrState::GetType() const {
- return RtcEvent::Type::AlrStateEvent;
-}
-
-bool RtcEventAlrState::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventAlrState> RtcEventAlrState::Copy() const {
return absl::WrapUnique<RtcEventAlrState>(new RtcEventAlrState(*this));
}
+RtcEventLogParseStatus RtcEventAlrState::Parse(
+ absl::string_view s,
+ bool batched,
+ std::vector<LoggedAlrStateEvent>& output) {
+ return RtcEventAlrState::definition_.ParseBatch(s, batched, output);
+}
+
} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_alr_state.h b/logging/rtc_event_log/events/rtc_event_alr_state.h
index 0869aa4d98..9f595ecd90 100644
--- a/logging/rtc_event_log/events/rtc_event_alr_state.h
+++ b/logging/rtc_event_log/events/rtc_event_alr_state.h
@@ -12,28 +12,66 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_ALR_STATE_H_
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_definition.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
+#include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
namespace webrtc {
+struct LoggedAlrStateEvent {
+ LoggedAlrStateEvent() = default;
+ LoggedAlrStateEvent(Timestamp timestamp, bool in_alr)
+ : timestamp(timestamp), in_alr(in_alr) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ bool in_alr;
+};
+
class RtcEventAlrState final : public RtcEvent {
public:
+ static constexpr Type kType = Type::AlrStateEvent;
+
explicit RtcEventAlrState(bool in_alr);
~RtcEventAlrState() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventAlrState> Copy() const;
bool in_alr() const { return in_alr_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ return RtcEventAlrState::definition_.EncodeBatch(batch);
+ }
+
+ static RtcEventLogParseStatus Parse(absl::string_view s,
+ bool batched,
+ std::vector<LoggedAlrStateEvent>& output);
+
private:
RtcEventAlrState(const RtcEventAlrState& other);
const bool in_alr_;
+
+ static constexpr RtcEventDefinition<RtcEventAlrState,
+ LoggedAlrStateEvent,
+ bool>
+ definition_{{"AlrState", RtcEventAlrState::kType},
+ {&RtcEventAlrState::in_alr_,
+ &LoggedAlrStateEvent::in_alr,
+ {"in_alr", /*id=*/1, FieldType::kFixed8, /*width=*/1}}};
};
} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_audio_network_adaptation.cc b/logging/rtc_event_log/events/rtc_event_audio_network_adaptation.cc
index 73783167a9..5f2d55c357 100644
--- a/logging/rtc_event_log/events/rtc_event_audio_network_adaptation.cc
+++ b/logging/rtc_event_log/events/rtc_event_audio_network_adaptation.cc
@@ -31,14 +31,6 @@ RtcEventAudioNetworkAdaptation::RtcEventAudioNetworkAdaptation(
RtcEventAudioNetworkAdaptation::~RtcEventAudioNetworkAdaptation() = default;
-RtcEvent::Type RtcEventAudioNetworkAdaptation::GetType() const {
- return RtcEvent::Type::AudioNetworkAdaptation;
-}
-
-bool RtcEventAudioNetworkAdaptation::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventAudioNetworkAdaptation>
RtcEventAudioNetworkAdaptation::Copy() const {
return absl::WrapUnique(new RtcEventAudioNetworkAdaptation(*this));
diff --git a/logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h b/logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h
index 7c50054561..d4cae3abfa 100644
--- a/logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h
+++ b/logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h
@@ -12,27 +12,61 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_AUDIO_NETWORK_ADAPTATION_H_
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
+#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
namespace webrtc {
+struct LoggedAudioNetworkAdaptationEvent {
+ LoggedAudioNetworkAdaptationEvent() = default;
+ LoggedAudioNetworkAdaptationEvent(Timestamp timestamp,
+ const AudioEncoderRuntimeConfig& config)
+ : timestamp(timestamp), config(config) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ AudioEncoderRuntimeConfig config;
+};
+
struct AudioEncoderRuntimeConfig;
class RtcEventAudioNetworkAdaptation final : public RtcEvent {
public:
+ static constexpr Type kType = Type::AudioNetworkAdaptation;
+
explicit RtcEventAudioNetworkAdaptation(
std::unique_ptr<AudioEncoderRuntimeConfig> config);
~RtcEventAudioNetworkAdaptation() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventAudioNetworkAdaptation> Copy() const;
const AudioEncoderRuntimeConfig& config() const { return *config_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedAudioNetworkAdaptationEvent>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventAudioNetworkAdaptation(const RtcEventAudioNetworkAdaptation& other);
diff --git a/logging/rtc_event_log/events/rtc_event_audio_playout.cc b/logging/rtc_event_log/events/rtc_event_audio_playout.cc
index 6c4aa98d3e..21a3f9266c 100644
--- a/logging/rtc_event_log/events/rtc_event_audio_playout.cc
+++ b/logging/rtc_event_log/events/rtc_event_audio_playout.cc
@@ -14,19 +14,16 @@
namespace webrtc {
+constexpr RtcEventDefinition<RtcEventAudioPlayout,
+ LoggedAudioPlayoutEvent,
+ uint32_t>
+ RtcEventAudioPlayout::definition_;
+
RtcEventAudioPlayout::RtcEventAudioPlayout(uint32_t ssrc) : ssrc_(ssrc) {}
RtcEventAudioPlayout::RtcEventAudioPlayout(const RtcEventAudioPlayout& other)
: RtcEvent(other.timestamp_us_), ssrc_(other.ssrc_) {}
-RtcEvent::Type RtcEventAudioPlayout::GetType() const {
- return RtcEvent::Type::AudioPlayout;
-}
-
-bool RtcEventAudioPlayout::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventAudioPlayout> RtcEventAudioPlayout::Copy() const {
return absl::WrapUnique<RtcEventAudioPlayout>(
new RtcEventAudioPlayout(*this));
diff --git a/logging/rtc_event_log/events/rtc_event_audio_playout.h b/logging/rtc_event_log/events/rtc_event_audio_playout.h
index 45836b79e3..196c3ca247 100644
--- a/logging/rtc_event_log/events/rtc_event_audio_playout.h
+++ b/logging/rtc_event_log/events/rtc_event_audio_playout.h
@@ -13,29 +13,74 @@
#include <stdint.h>
+#include <map>
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_definition.h"
namespace webrtc {
+struct LoggedAudioPlayoutEvent {
+ LoggedAudioPlayoutEvent() = default;
+ LoggedAudioPlayoutEvent(Timestamp timestamp, uint32_t ssrc)
+ : timestamp(timestamp), ssrc(ssrc) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ uint32_t ssrc;
+};
+
class RtcEventAudioPlayout final : public RtcEvent {
public:
+ static constexpr Type kType = Type::AudioPlayout;
+
explicit RtcEventAudioPlayout(uint32_t ssrc);
~RtcEventAudioPlayout() override = default;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventAudioPlayout> Copy() const;
uint32_t ssrc() const { return ssrc_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ return RtcEventAudioPlayout::definition_.EncodeBatch(batch);
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::map<uint32_t, std::vector<LoggedAudioPlayoutEvent>>& output) {
+ std::vector<LoggedAudioPlayoutEvent> temp_output;
+ auto status = RtcEventAudioPlayout::definition_.ParseBatch(
+ encoded_bytes, batched, temp_output);
+ for (const LoggedAudioPlayoutEvent& event : temp_output) {
+ output[event.ssrc].push_back(event);
+ }
+ return status;
+ }
+
private:
RtcEventAudioPlayout(const RtcEventAudioPlayout& other);
const uint32_t ssrc_;
+
+ static constexpr RtcEventDefinition<RtcEventAudioPlayout,
+ LoggedAudioPlayoutEvent,
+ uint32_t>
+ definition_{{"AudioPlayout", RtcEventAudioPlayout::kType},
+ {&RtcEventAudioPlayout::ssrc_,
+ &LoggedAudioPlayoutEvent::ssrc,
+ {"ssrc", /*id=*/1, FieldType::kFixed32, /*width=*/32}}};
};
} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.cc b/logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.cc
index 5cdfb473bb..87caaff098 100644
--- a/logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.cc
+++ b/logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.cc
@@ -31,14 +31,6 @@ RtcEventAudioReceiveStreamConfig::RtcEventAudioReceiveStreamConfig(
RtcEventAudioReceiveStreamConfig::~RtcEventAudioReceiveStreamConfig() = default;
-RtcEvent::Type RtcEventAudioReceiveStreamConfig::GetType() const {
- return RtcEvent::Type::AudioReceiveStreamConfig;
-}
-
-bool RtcEventAudioReceiveStreamConfig::IsConfigEvent() const {
- return true;
-}
-
std::unique_ptr<RtcEventAudioReceiveStreamConfig>
RtcEventAudioReceiveStreamConfig::Copy() const {
return absl::WrapUnique<RtcEventAudioReceiveStreamConfig>(
diff --git a/logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h b/logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h
index 67f28602f3..9863e235af 100644
--- a/logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h
+++ b/logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h
@@ -12,29 +12,58 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_AUDIO_RECEIVE_STREAM_CONFIG_H_
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
+#include "logging/rtc_event_log/rtc_stream_config.h"
namespace webrtc {
-namespace rtclog {
-struct StreamConfig;
-} // namespace rtclog
+struct LoggedAudioRecvConfig {
+ LoggedAudioRecvConfig() = default;
+ LoggedAudioRecvConfig(Timestamp timestamp, const rtclog::StreamConfig config)
+ : timestamp(timestamp), config(config) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtclog::StreamConfig config;
+};
class RtcEventAudioReceiveStreamConfig final : public RtcEvent {
public:
+ static constexpr Type kType = Type::AudioReceiveStreamConfig;
+
explicit RtcEventAudioReceiveStreamConfig(
std::unique_ptr<rtclog::StreamConfig> config);
~RtcEventAudioReceiveStreamConfig() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return true; }
std::unique_ptr<RtcEventAudioReceiveStreamConfig> Copy() const;
const rtclog::StreamConfig& config() const { return *config_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedAudioRecvConfig>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventAudioReceiveStreamConfig(
const RtcEventAudioReceiveStreamConfig& other);
diff --git a/logging/rtc_event_log/events/rtc_event_audio_send_stream_config.cc b/logging/rtc_event_log/events/rtc_event_audio_send_stream_config.cc
index f4403afddf..681ae11e63 100644
--- a/logging/rtc_event_log/events/rtc_event_audio_send_stream_config.cc
+++ b/logging/rtc_event_log/events/rtc_event_audio_send_stream_config.cc
@@ -31,14 +31,6 @@ RtcEventAudioSendStreamConfig::RtcEventAudioSendStreamConfig(
RtcEventAudioSendStreamConfig::~RtcEventAudioSendStreamConfig() = default;
-RtcEvent::Type RtcEventAudioSendStreamConfig::GetType() const {
- return RtcEvent::Type::AudioSendStreamConfig;
-}
-
-bool RtcEventAudioSendStreamConfig::IsConfigEvent() const {
- return true;
-}
-
std::unique_ptr<RtcEventAudioSendStreamConfig>
RtcEventAudioSendStreamConfig::Copy() const {
return absl::WrapUnique<RtcEventAudioSendStreamConfig>(
diff --git a/logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h b/logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h
index 8617b950e7..550723bcf0 100644
--- a/logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h
+++ b/logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h
@@ -12,29 +12,57 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_AUDIO_SEND_STREAM_CONFIG_H_
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
+#include "logging/rtc_event_log/rtc_stream_config.h"
namespace webrtc {
-namespace rtclog {
-struct StreamConfig;
-} // namespace rtclog
+struct LoggedAudioSendConfig {
+ LoggedAudioSendConfig() = default;
+ LoggedAudioSendConfig(Timestamp timestamp, const rtclog::StreamConfig config)
+ : timestamp(timestamp), config(config) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtclog::StreamConfig config;
+};
class RtcEventAudioSendStreamConfig final : public RtcEvent {
public:
+ static constexpr Type kType = Type::AudioSendStreamConfig;
+
explicit RtcEventAudioSendStreamConfig(
std::unique_ptr<rtclog::StreamConfig> config);
~RtcEventAudioSendStreamConfig() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return true; }
std::unique_ptr<RtcEventAudioSendStreamConfig> Copy() const;
const rtclog::StreamConfig& config() const { return *config_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedAudioSendConfig>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventAudioSendStreamConfig(const RtcEventAudioSendStreamConfig& other);
diff --git a/logging/rtc_event_log/events/rtc_event_begin_log.cc b/logging/rtc_event_log/events/rtc_event_begin_log.cc
new file mode 100644
index 0000000000..49b9effa9e
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_begin_log.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/events/rtc_event_begin_log.h"
+
+#include "absl/strings/string_view.h"
+
+namespace webrtc {
+constexpr RtcEvent::Type RtcEventBeginLog::kType;
+constexpr EventParameters RtcEventBeginLog::event_params_;
+constexpr FieldParameters RtcEventBeginLog::utc_start_time_params_;
+
+RtcEventBeginLog::RtcEventBeginLog(Timestamp timestamp,
+ Timestamp utc_start_time)
+ : RtcEvent(timestamp.us()), utc_start_time_ms_(utc_start_time.ms()) {}
+
+RtcEventBeginLog::RtcEventBeginLog(const RtcEventBeginLog& other)
+ : RtcEvent(other.timestamp_us_) {}
+
+RtcEventBeginLog::~RtcEventBeginLog() = default;
+
+std::string RtcEventBeginLog::Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ EventEncoder encoder(event_params_, batch);
+
+ encoder.EncodeField(
+ utc_start_time_params_,
+ ExtractRtcEventMember(batch, &RtcEventBeginLog::utc_start_time_ms_));
+
+ return encoder.AsString();
+}
+
+RtcEventLogParseStatus RtcEventBeginLog::Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedStartEvent>& output) {
+ EventParser parser;
+ auto status = parser.Initialize(encoded_bytes, batched);
+ if (!status.ok())
+ return status;
+
+ rtc::ArrayView<LoggedStartEvent> output_batch =
+ ExtendLoggedBatch(output, parser.NumEventsInBatch());
+
+ constexpr FieldParameters timestamp_params{
+ "timestamp_ms", FieldParameters::kTimestampField, FieldType::kVarInt, 64};
+ RtcEventLogParseStatusOr<rtc::ArrayView<uint64_t>> result =
+ parser.ParseNumericField(timestamp_params);
+ if (!result.ok())
+ return result.status();
+ status = PopulateRtcEventTimestamp(
+ result.value(), &LoggedStartEvent::timestamp, output_batch);
+ if (!status.ok())
+ return status;
+
+ result = parser.ParseNumericField(utc_start_time_params_);
+ if (!result.ok())
+ return result.status();
+ status = PopulateRtcEventTimestamp(
+ result.value(), &LoggedStartEvent::utc_start_time, output_batch);
+ if (!status.ok())
+ return status;
+
+ return RtcEventLogParseStatus::Success();
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_begin_log.h b/logging/rtc_event_log/events/rtc_event_begin_log.h
new file mode 100644
index 0000000000..f3b74c117e
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_begin_log.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_BEGIN_LOG_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_BEGIN_LOG_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
+#include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
+
+namespace webrtc {
+
+struct LoggedStartEvent {
+ LoggedStartEvent() = default;
+
+ explicit LoggedStartEvent(Timestamp timestamp)
+ : LoggedStartEvent(timestamp, timestamp) {}
+
+ LoggedStartEvent(Timestamp timestamp, Timestamp utc_start_time)
+ : timestamp(timestamp), utc_start_time(utc_start_time) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp utc_time() const { return utc_start_time; }
+
+ Timestamp timestamp = Timestamp::PlusInfinity();
+ Timestamp utc_start_time = Timestamp::PlusInfinity();
+};
+
+class RtcEventBeginLog final : public RtcEvent {
+ public:
+ static constexpr Type kType = Type::BeginV3Log;
+
+ RtcEventBeginLog(Timestamp timestamp, Timestamp utc_start_time);
+ ~RtcEventBeginLog() override;
+
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
+
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch);
+
+ static RtcEventLogParseStatus Parse(absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedStartEvent>& output);
+
+ private:
+ RtcEventBeginLog(const RtcEventBeginLog& other);
+
+ int64_t utc_start_time_ms_;
+
+ static constexpr EventParameters event_params_{"BeginLog",
+ RtcEventBeginLog::kType};
+ static constexpr FieldParameters utc_start_time_params_{
+ "utc_start_time_ms", /*id=*/1, FieldType::kVarInt, /*width=*/64};
+};
+
+} // namespace webrtc
+#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_BEGIN_LOG_H_
diff --git a/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.cc b/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.cc
index dcc87421f8..0e98b2ff11 100644
--- a/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.cc
+++ b/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.cc
@@ -11,10 +11,16 @@
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "absl/memory/memory.h"
-#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
+#include "api/network_state_predictor.h"
namespace webrtc {
+constexpr RtcEventDefinition<RtcEventBweUpdateDelayBased,
+ LoggedBweDelayBasedUpdate,
+ int32_t,
+ BandwidthUsage>
+ RtcEventBweUpdateDelayBased::definition_;
+
RtcEventBweUpdateDelayBased::RtcEventBweUpdateDelayBased(
int32_t bitrate_bps,
BandwidthUsage detector_state)
@@ -28,14 +34,6 @@ RtcEventBweUpdateDelayBased::RtcEventBweUpdateDelayBased(
RtcEventBweUpdateDelayBased::~RtcEventBweUpdateDelayBased() = default;
-RtcEvent::Type RtcEventBweUpdateDelayBased::GetType() const {
- return RtcEvent::Type::BweUpdateDelayBased;
-}
-
-bool RtcEventBweUpdateDelayBased::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventBweUpdateDelayBased> RtcEventBweUpdateDelayBased::Copy()
const {
return absl::WrapUnique<RtcEventBweUpdateDelayBased>(
diff --git a/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h b/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h
index 8908ce2be1..796f119388 100644
--- a/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h
+++ b/logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h
@@ -13,34 +13,122 @@
#include <stdint.h>
+#include <limits>
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
+#include "api/network_state_predictor.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_definition.h"
namespace webrtc {
-enum class BandwidthUsage;
+// Separate the event log encoding from the enum values.
+// As long as the enum values are the same as the encodings,
+// the two conversion functions can be compiled to (roughly)
+// a range check each.
+template <>
+class RtcEventLogEnum<BandwidthUsage> {
+ static constexpr uint64_t kBwNormal = 0;
+ static constexpr uint64_t kBwUnderusing = 1;
+ static constexpr uint64_t kBwOverusing = 2;
+
+ public:
+ static uint64_t Encode(BandwidthUsage x) {
+ switch (x) {
+ case BandwidthUsage::kBwNormal:
+ return kBwNormal;
+ case BandwidthUsage::kBwUnderusing:
+ return kBwUnderusing;
+ case BandwidthUsage::kBwOverusing:
+ return kBwOverusing;
+ case BandwidthUsage::kLast:
+ RTC_DCHECK_NOTREACHED();
+ }
+ RTC_DCHECK_NOTREACHED();
+ return std::numeric_limits<uint64_t>::max();
+ }
+ static RtcEventLogParseStatusOr<BandwidthUsage> Decode(uint64_t x) {
+ switch (x) {
+ case kBwNormal:
+ return BandwidthUsage::kBwNormal;
+ case kBwUnderusing:
+ return BandwidthUsage::kBwUnderusing;
+ case kBwOverusing:
+ return BandwidthUsage::kBwOverusing;
+ }
+ return RtcEventLogParseStatus::Error("Failed to decode BandwidthUsage enum",
+ __FILE__, __LINE__);
+ }
+};
+
+struct LoggedBweDelayBasedUpdate {
+ LoggedBweDelayBasedUpdate() = default;
+ LoggedBweDelayBasedUpdate(Timestamp timestamp,
+ int32_t bitrate_bps,
+ BandwidthUsage detector_state)
+ : timestamp(timestamp),
+ bitrate_bps(bitrate_bps),
+ detector_state(detector_state) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ int32_t bitrate_bps;
+ BandwidthUsage detector_state;
+};
class RtcEventBweUpdateDelayBased final : public RtcEvent {
public:
+ static constexpr Type kType = Type::BweUpdateDelayBased;
+
RtcEventBweUpdateDelayBased(int32_t bitrate_bps,
BandwidthUsage detector_state);
~RtcEventBweUpdateDelayBased() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventBweUpdateDelayBased> Copy() const;
int32_t bitrate_bps() const { return bitrate_bps_; }
BandwidthUsage detector_state() const { return detector_state_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ return RtcEventBweUpdateDelayBased::definition_.EncodeBatch(batch);
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedBweDelayBasedUpdate>& output) {
+ return RtcEventBweUpdateDelayBased::definition_.ParseBatch(encoded_bytes,
+ batched, output);
+ }
+
private:
RtcEventBweUpdateDelayBased(const RtcEventBweUpdateDelayBased& other);
const int32_t bitrate_bps_;
const BandwidthUsage detector_state_;
+
+ static constexpr RtcEventDefinition<RtcEventBweUpdateDelayBased,
+ LoggedBweDelayBasedUpdate,
+ int32_t,
+ BandwidthUsage>
+ definition_{
+ {"BweDelayBased", RtcEventBweUpdateDelayBased::kType},
+ {&RtcEventBweUpdateDelayBased::bitrate_bps_,
+ &LoggedBweDelayBasedUpdate::bitrate_bps,
+ {"bitrate_bps", /*id=*/1, FieldType::kVarInt, /*width=*/32}},
+ {&RtcEventBweUpdateDelayBased::detector_state_,
+ &LoggedBweDelayBasedUpdate::detector_state,
+ {"detector_state", /*id=*/2, FieldType::kVarInt, /*width=*/64}}};
};
} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.cc b/logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.cc
index 8453238cf9..44524ab033 100644
--- a/logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.cc
+++ b/logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.cc
@@ -30,14 +30,6 @@ RtcEventBweUpdateLossBased::RtcEventBweUpdateLossBased(
RtcEventBweUpdateLossBased::~RtcEventBweUpdateLossBased() = default;
-RtcEvent::Type RtcEventBweUpdateLossBased::GetType() const {
- return RtcEvent::Type::BweUpdateLossBased;
-}
-
-bool RtcEventBweUpdateLossBased::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventBweUpdateLossBased> RtcEventBweUpdateLossBased::Copy()
const {
return absl::WrapUnique<RtcEventBweUpdateLossBased>(
diff --git a/logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h b/logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h
index 78829a9586..fd41b316e0 100644
--- a/logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h
+++ b/logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h
@@ -14,21 +14,48 @@
#include <stdint.h>
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
+struct LoggedBweLossBasedUpdate {
+ LoggedBweLossBasedUpdate() = default;
+ LoggedBweLossBasedUpdate(Timestamp timestamp,
+ int32_t bitrate_bps,
+ uint8_t fraction_lost,
+ int32_t expected_packets)
+ : timestamp(timestamp),
+ bitrate_bps(bitrate_bps),
+ fraction_lost(fraction_lost),
+ expected_packets(expected_packets) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ int32_t bitrate_bps;
+ uint8_t fraction_lost;
+ int32_t expected_packets;
+};
+
class RtcEventBweUpdateLossBased final : public RtcEvent {
public:
+ static constexpr Type kType = Type::BweUpdateLossBased;
+
RtcEventBweUpdateLossBased(int32_t bitrate_bps_,
uint8_t fraction_loss_,
int32_t total_packets_);
~RtcEventBweUpdateLossBased() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventBweUpdateLossBased> Copy() const;
@@ -36,6 +63,19 @@ class RtcEventBweUpdateLossBased final : public RtcEvent {
uint8_t fraction_loss() const { return fraction_loss_; }
int32_t total_packets() const { return total_packets_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedBweLossBasedUpdate>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventBweUpdateLossBased(const RtcEventBweUpdateLossBased& other);
diff --git a/logging/rtc_event_log/events/rtc_event_definition.h b/logging/rtc_event_log/events/rtc_event_definition.h
new file mode 100644
index 0000000000..8688c5fc7b
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_definition.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_DEFINITION_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_DEFINITION_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
+#include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+
+template <typename EventType, typename LoggedType, typename T>
+struct RtcEventFieldDefinition {
+ const T EventType::*event_member;
+ T LoggedType::*logged_member;
+ FieldParameters params;
+};
+
+// Base case
+template <typename EventType, typename LoggedType, typename... Ts>
+class RtcEventDefinitionImpl {
+ public:
+ void EncodeImpl(EventEncoder&, rtc::ArrayView<const RtcEvent*>) const {}
+ RtcEventLogParseStatus ParseImpl(EventParser&,
+ rtc::ArrayView<LoggedType>) const {
+ return RtcEventLogParseStatus::Success();
+ }
+};
+
+// Recursive case
+template <typename EventType, typename LoggedType, typename T, typename... Ts>
+class RtcEventDefinitionImpl<EventType, LoggedType, T, Ts...> {
+ public:
+ constexpr RtcEventDefinitionImpl(
+ RtcEventFieldDefinition<EventType, LoggedType, T> field,
+ RtcEventFieldDefinition<EventType, LoggedType, Ts>... rest)
+ : field_(field), rest_(rest...) {}
+
+ void EncodeImpl(EventEncoder& encoder,
+ rtc::ArrayView<const RtcEvent*> batch) const {
+ auto values = ExtractRtcEventMember(batch, field_.event_member);
+ encoder.EncodeField(field_.params, values);
+ rest_.EncodeImpl(encoder, batch);
+ }
+
+ RtcEventLogParseStatus ParseImpl(
+ EventParser& parser,
+ rtc::ArrayView<LoggedType> output_batch) const {
+ RtcEventLogParseStatusOr<rtc::ArrayView<uint64_t>> result =
+ parser.ParseNumericField(field_.params);
+ if (!result.ok())
+ return result.status();
+ auto status = PopulateRtcEventMember(result.value(), field_.logged_member,
+ output_batch);
+ if (!status.ok())
+ return status;
+
+ return rest_.ParseImpl(parser, output_batch);
+ }
+
+ private:
+ RtcEventFieldDefinition<EventType, LoggedType, T> field_;
+ RtcEventDefinitionImpl<EventType, LoggedType, Ts...> rest_;
+};
+
+// The RtcEventDefinition sets up a mapping between the fields
+// in an RtcEvent and the corresponding fields in the parsed struct.
+// For example, an RtcFoo class containing two fields; `uint32_t bar`
+// and `bool baz` (a log timestamp is always implicitly added)
+// might have a definition
+// RtcEventDefinition<RtcFoo, LoggedFoo, uint32_t, bool>(
+// {"foo", RtcFoo::Type},
+// {&RtcFoo::bar_, &LoggedFoo::bar, {"bar", 1, FieldType::kVarInt, 32}},
+// {&RtcFoo::baz_, &LoggedFoo::baz, {"baz", 2, FieldType::kFixed8, 1}},
+// );
+// In addition to defining string names to aid debugging,
+// this specifies that
+// * RtcFoo::Type uniquely identifies an RtcFoo in the encoded stream
+// * The `bar` field has ID 1, is encoded as a VarInt
+// (when not delta compressed), and wraps around after 32 bits.
+// * The `baz` field has ID 2, is encoded as an 8-bit field
+// (when not delta compressed), and wraps around after 1 bit.
+// Note that the numerical field and event IDs can't be changed since
+// that would break compatibility with old logs.
+// In most cases (including all cases where wrap around isn't
+// expected), the wrap around should be equal to the bitwidth of
+// the field.
+template <typename EventType, typename LoggedType, typename... Ts>
+class RtcEventDefinition {
+ public:
+ constexpr RtcEventDefinition(
+ EventParameters params,
+ RtcEventFieldDefinition<EventType, LoggedType, Ts>... fields)
+ : params_(params), fields_(fields...) {}
+
+ std::string EncodeBatch(rtc::ArrayView<const RtcEvent*> batch) const {
+ EventEncoder encoder(params_, batch);
+ fields_.EncodeImpl(encoder, batch);
+ return encoder.AsString();
+ }
+
+ RtcEventLogParseStatus ParseBatch(absl::string_view s,
+ bool batched,
+ std::vector<LoggedType>& output) const {
+ EventParser parser;
+ auto status = parser.Initialize(s, batched);
+ if (!status.ok())
+ return status;
+
+ rtc::ArrayView<LoggedType> output_batch =
+ ExtendLoggedBatch(output, parser.NumEventsInBatch());
+
+ constexpr FieldParameters timestamp_params{"timestamp_ms",
+ FieldParameters::kTimestampField,
+ FieldType::kVarInt, 64};
+ RtcEventLogParseStatusOr<rtc::ArrayView<uint64_t>> result =
+ parser.ParseNumericField(timestamp_params);
+ if (!result.ok())
+ return result.status();
+ status = PopulateRtcEventTimestamp(result.value(), &LoggedType::timestamp,
+ output_batch);
+ if (!status.ok())
+ return status;
+
+ return fields_.ParseImpl(parser, output_batch);
+ }
+
+ private:
+ EventParameters params_;
+ RtcEventDefinitionImpl<EventType, LoggedType, Ts...> fields_;
+};
+
+} // namespace webrtc
+
+#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_DEFINITION_H_
diff --git a/logging/rtc_event_log/events/rtc_event_dtls_transport_state.cc b/logging/rtc_event_log/events/rtc_event_dtls_transport_state.cc
index ac8e642daa..f00342df72 100644
--- a/logging/rtc_event_log/events/rtc_event_dtls_transport_state.cc
+++ b/logging/rtc_event_log/events/rtc_event_dtls_transport_state.cc
@@ -24,14 +24,6 @@ RtcEventDtlsTransportState::RtcEventDtlsTransportState(
RtcEventDtlsTransportState::~RtcEventDtlsTransportState() = default;
-RtcEvent::Type RtcEventDtlsTransportState::GetType() const {
- return RtcEvent::Type::DtlsTransportState;
-}
-
-bool RtcEventDtlsTransportState::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventDtlsTransportState> RtcEventDtlsTransportState::Copy()
const {
return absl::WrapUnique<RtcEventDtlsTransportState>(
diff --git a/logging/rtc_event_log/events/rtc_event_dtls_transport_state.h b/logging/rtc_event_log/events/rtc_event_dtls_transport_state.h
index 4fbe5a7932..b9af213256 100644
--- a/logging/rtc_event_log/events/rtc_event_dtls_transport_state.h
+++ b/logging/rtc_event_log/events/rtc_event_dtls_transport_state.h
@@ -12,19 +12,35 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_DTLS_TRANSPORT_STATE_H_
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/dtls_transport_interface.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
+struct LoggedDtlsTransportState {
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ DtlsTransportState dtls_transport_state;
+};
+
class RtcEventDtlsTransportState : public RtcEvent {
public:
+ static constexpr Type kType = Type::DtlsTransportState;
+
explicit RtcEventDtlsTransportState(DtlsTransportState state);
~RtcEventDtlsTransportState() override;
- Type GetType() const override;
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventDtlsTransportState> Copy() const;
@@ -32,6 +48,19 @@ class RtcEventDtlsTransportState : public RtcEvent {
return dtls_transport_state_;
}
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedDtlsTransportState>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventDtlsTransportState(const RtcEventDtlsTransportState& other);
diff --git a/logging/rtc_event_log/events/rtc_event_dtls_writable_state.cc b/logging/rtc_event_log/events/rtc_event_dtls_writable_state.cc
index 16c1e7b8e8..d4cb093ce6 100644
--- a/logging/rtc_event_log/events/rtc_event_dtls_writable_state.cc
+++ b/logging/rtc_event_log/events/rtc_event_dtls_writable_state.cc
@@ -23,14 +23,6 @@ RtcEventDtlsWritableState::RtcEventDtlsWritableState(
RtcEventDtlsWritableState::~RtcEventDtlsWritableState() = default;
-RtcEvent::Type RtcEventDtlsWritableState::GetType() const {
- return RtcEvent::Type::DtlsWritableState;
-}
-
-bool RtcEventDtlsWritableState::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventDtlsWritableState> RtcEventDtlsWritableState::Copy()
const {
return absl::WrapUnique<RtcEventDtlsWritableState>(
diff --git a/logging/rtc_event_log/events/rtc_event_dtls_writable_state.h b/logging/rtc_event_log/events/rtc_event_dtls_writable_state.h
index 06a7f9db7e..c820f184d7 100644
--- a/logging/rtc_event_log/events/rtc_event_dtls_writable_state.h
+++ b/logging/rtc_event_log/events/rtc_event_dtls_writable_state.h
@@ -12,23 +12,55 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_DTLS_WRITABLE_STATE_H_
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
+struct LoggedDtlsWritableState {
+ LoggedDtlsWritableState() = default;
+ explicit LoggedDtlsWritableState(bool writable) : writable(writable) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ bool writable;
+};
+
class RtcEventDtlsWritableState : public RtcEvent {
public:
+ static constexpr Type kType = Type::DtlsWritableState;
+
explicit RtcEventDtlsWritableState(bool writable);
~RtcEventDtlsWritableState() override;
- Type GetType() const override;
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventDtlsWritableState> Copy() const;
bool writable() const { return writable_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedDtlsWritableState>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventDtlsWritableState(const RtcEventDtlsWritableState& other);
diff --git a/logging/rtc_event_log/events/rtc_event_end_log.cc b/logging/rtc_event_log/events/rtc_event_end_log.cc
new file mode 100644
index 0000000000..52abf9e842
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_end_log.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/events/rtc_event_end_log.h"
+
+#include "absl/strings/string_view.h"
+
+namespace webrtc {
+constexpr RtcEvent::Type RtcEventEndLog::kType;
+constexpr EventParameters RtcEventEndLog::event_params_;
+
+RtcEventEndLog::RtcEventEndLog(Timestamp timestamp)
+ : RtcEvent(timestamp.us()) {}
+
+RtcEventEndLog::RtcEventEndLog(const RtcEventEndLog& other)
+ : RtcEvent(other.timestamp_us_) {}
+
+RtcEventEndLog::~RtcEventEndLog() = default;
+
+std::string RtcEventEndLog::Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ EventEncoder encoder(event_params_, batch);
+ return encoder.AsString();
+}
+
+RtcEventLogParseStatus RtcEventEndLog::Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedStopEvent>& output) {
+ EventParser parser;
+ auto status = parser.Initialize(encoded_bytes, batched);
+ if (!status.ok())
+ return status;
+
+ rtc::ArrayView<LoggedStopEvent> output_batch =
+ ExtendLoggedBatch(output, parser.NumEventsInBatch());
+
+ constexpr FieldParameters timestamp_params{
+ "timestamp_ms", FieldParameters::kTimestampField, FieldType::kVarInt, 64};
+ RtcEventLogParseStatusOr<rtc::ArrayView<uint64_t>> result =
+ parser.ParseNumericField(timestamp_params);
+ if (!result.ok())
+ return result.status();
+ status = PopulateRtcEventTimestamp(result.value(),
+ &LoggedStopEvent::timestamp, output_batch);
+ if (!status.ok())
+ return status;
+
+ return RtcEventLogParseStatus::Success();
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_end_log.h b/logging/rtc_event_log/events/rtc_event_end_log.h
new file mode 100644
index 0000000000..79648bdb8d
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_end_log.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_END_LOG_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_END_LOG_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
+#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
+#include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
+
+namespace webrtc {
+
+struct LoggedStopEvent {
+ LoggedStopEvent() = default;
+
+ explicit LoggedStopEvent(Timestamp timestamp) : timestamp(timestamp) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::PlusInfinity();
+};
+
+class RtcEventEndLog final : public RtcEvent {
+ public:
+ static constexpr Type kType = Type::EndV3Log;
+
+ explicit RtcEventEndLog(Timestamp timestamp);
+ ~RtcEventEndLog() override;
+
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
+
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch);
+
+ static RtcEventLogParseStatus Parse(absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedStopEvent>& output);
+
+ private:
+ RtcEventEndLog(const RtcEventEndLog& other);
+
+ static constexpr EventParameters event_params_{"EndLog",
+ RtcEventEndLog::kType};
+};
+
+} // namespace webrtc
+#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_END_LOG_H_
diff --git a/logging/rtc_event_log/events/rtc_event_field_encoding.cc b/logging/rtc_event_log/events/rtc_event_field_encoding.cc
new file mode 100644
index 0000000000..68188ce856
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_field_encoding.cc
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
+
+#include <algorithm>
+#include <limits>
+#include <memory>
+#include <utility>
+
+#include "logging/rtc_event_log/encoder/bit_writer.h"
+#include "logging/rtc_event_log/encoder/var_int.h"
+#include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+using webrtc_event_logging::UnsignedDelta;
+
+namespace {
+
+std::string SerializeLittleEndian(uint64_t value, uint8_t bytes) {
+ RTC_DCHECK_LE(bytes, sizeof(uint64_t));
+ RTC_DCHECK_GE(bytes, 1);
+ if (bytes < sizeof(uint64_t)) {
+ // Note that shifting a 64-bit value by 64 (or more) bits is undefined.
+ RTC_DCHECK_EQ(value >> (8 * bytes), 0);
+ }
+ std::string output(bytes, 0);
+ // Getting a non-const pointer to the representation. See e.g.
+ // https://en.cppreference.com/w/cpp/string/basic_string:
+ // "The elements of a basic_string are stored contiguously,
+ // that is, [...] a pointer to s[0] can be passed to functions
+ // that expect a pointer to the first element of a null-terminated
+ // CharT[] array."
+ uint8_t* p = reinterpret_cast<uint8_t*>(&output[0]);
+#ifdef WEBRTC_ARCH_LITTLE_ENDIAN
+ memcpy(p, &value, bytes);
+#else
+ while (bytes > 0) {
+ *p = static_cast<uint8_t>(value & 0xFF);
+ value >>= 8;
+ ++p;
+ --bytes;
+ }
+#endif // WEBRTC_ARCH_LITTLE_ENDIAN
+ return output;
+}
+
+} // namespace
+
+namespace webrtc {
+
+std::string EncodeOptionalValuePositions(std::vector<bool> positions) {
+ BitWriter writer((positions.size() + 7) / 8);
+ for (bool position : positions) {
+ writer.WriteBits(position ? 1u : 0u, 1);
+ }
+ return writer.GetString();
+}
+
+std::string EncodeSingleValue(uint64_t value, FieldType field_type) {
+ switch (field_type) {
+ case FieldType::kFixed8:
+ return SerializeLittleEndian(value, /*bytes=*/1);
+ case FieldType::kFixed32:
+ return SerializeLittleEndian(value, /*bytes=*/4);
+ case FieldType::kFixed64:
+ return SerializeLittleEndian(value, /*bytes=*/8);
+ case FieldType::kVarInt:
+ return EncodeVarInt(value);
+ case FieldType::kString:
+ RTC_DCHECK_NOTREACHED();
+ return std::string();
+ }
+ RTC_DCHECK_NOTREACHED();
+ return std::string();
+}
+
+absl::optional<FieldType> ConvertFieldType(uint64_t value) {
+ switch (value) {
+ case static_cast<uint64_t>(FieldType::kFixed8):
+ return FieldType::kFixed8;
+ case static_cast<uint64_t>(FieldType::kFixed32):
+ return FieldType::kFixed32;
+ case static_cast<uint64_t>(FieldType::kFixed64):
+ return FieldType::kFixed64;
+ case static_cast<uint64_t>(FieldType::kVarInt):
+ return FieldType::kVarInt;
+ case static_cast<uint64_t>(FieldType::kString):
+ return FieldType::kString;
+ default:
+ return absl::nullopt;
+ }
+}
+
+std::string EncodeDeltasV3(FixedLengthEncodingParametersV3 params,
+ uint64_t base,
+ rtc::ArrayView<const uint64_t> values) {
+ size_t outputbound = (values.size() * params.delta_bit_width() + 7) / 8;
+ BitWriter writer(outputbound);
+
+ uint64_t previous = base;
+ for (uint64_t value : values) {
+ if (params.signed_deltas()) {
+ uint64_t positive_delta =
+ UnsignedDelta(previous, value, params.value_mask());
+ uint64_t negative_delta =
+ UnsignedDelta(value, previous, params.value_mask());
+ uint64_t delta;
+ if (positive_delta <= negative_delta) {
+ delta = positive_delta;
+ } else {
+ // Compute the two's complement representation of a negative
+ // delta, in a field width params_.delta_mask().
+ RTC_DCHECK_GE(params.delta_mask(), negative_delta);
+ RTC_DCHECK_LT(params.delta_mask() - negative_delta,
+ params.delta_mask());
+ delta = params.delta_mask() - negative_delta + 1;
+ RTC_DCHECK_LE(delta, params.delta_mask());
+ }
+ writer.WriteBits(delta, params.delta_bit_width());
+ } else {
+ uint64_t delta = UnsignedDelta(previous, value, params.value_mask());
+ writer.WriteBits(delta, params.delta_bit_width());
+ }
+ previous = value;
+ }
+
+ return writer.GetString();
+}
+
+EventEncoder::EventEncoder(EventParameters params,
+ rtc::ArrayView<const RtcEvent*> batch) {
+ batch_size_ = batch.size();
+ if (!batch.empty()) {
+ // Encode event type.
+ uint32_t batched = batch.size() > 1 ? 1 : 0;
+ event_tag_ = (static_cast<uint32_t>(params.id) << 1) + batched;
+
+ // Event tag and number of encoded bytes will be filled in when the
+ // encoding is finalized in AsString().
+
+ // Encode number of events in batch
+ if (batched) {
+ encoded_fields_.push_back(EncodeVarInt(batch.size()));
+ }
+
+ // Encode timestamp
+ std::vector<uint64_t> timestamps;
+ timestamps.reserve(batch.size());
+ for (const RtcEvent* event : batch) {
+ timestamps.push_back(EncodeAsUnsigned(event->timestamp_ms()));
+ }
+ constexpr FieldParameters timestamp_params{"timestamp_ms",
+ FieldParameters::kTimestampField,
+ FieldType::kVarInt, 64};
+ EncodeField(timestamp_params, timestamps);
+ }
+}
+
+void EventEncoder::EncodeField(const FieldParameters& params,
+ const ValuesWithPositions& values) {
+ return EncodeField(params, values.values, &values.position_mask);
+}
+
+void EventEncoder::EncodeField(const FieldParameters& params,
+ const std::vector<uint64_t>& values,
+ const std::vector<bool>* positions) {
+ if (positions) {
+ RTC_DCHECK_EQ(positions->size(), batch_size_);
+ RTC_DCHECK_LE(values.size(), batch_size_);
+ } else {
+ RTC_DCHECK_EQ(values.size(), batch_size_);
+ }
+
+ if (values.size() == 0) {
+ // If all values for a particular field is empty/nullopt,
+ // then we completely skip the field even if the the batch is non-empty.
+ return;
+ }
+
+ // We know that each event starts with the varint encoded timestamp,
+ // so we omit that field tag (field id + field type). In all other
+ // cases, we write the field tag.
+ if (params.field_id != FieldParameters::kTimestampField) {
+ RTC_DCHECK_LE(params.field_id, std::numeric_limits<uint64_t>::max() >> 3);
+ uint64_t field_tag = params.field_id << 3;
+ field_tag += static_cast<uint64_t>(params.field_type);
+ encoded_fields_.push_back(EncodeVarInt(field_tag));
+ }
+
+ RTC_CHECK_GE(values.size(), 1);
+ if (batch_size_ == 1) {
+ encoded_fields_.push_back(EncodeSingleValue(values[0], params.field_type));
+ return;
+ }
+
+ const bool values_optional = values.size() != batch_size_;
+
+ // Compute delta parameters
+ rtc::ArrayView<const uint64_t> all_values(values);
+ uint64_t base = values[0];
+ rtc::ArrayView<const uint64_t> remaining_values(all_values.subview(1));
+
+ FixedLengthEncodingParametersV3 delta_params =
+ FixedLengthEncodingParametersV3::CalculateParameters(
+ base, remaining_values, params.value_width, values_optional);
+
+ encoded_fields_.push_back(EncodeVarInt(delta_params.DeltaHeaderAsInt()));
+
+ if (values_optional) {
+ RTC_CHECK(positions);
+ encoded_fields_.push_back(EncodeOptionalValuePositions(*positions));
+ }
+ // Base element, encoded as uint8, uint32, uint64 or varint
+ encoded_fields_.push_back(EncodeSingleValue(base, params.field_type));
+
+ // If all (existing) values are equal to the base, then we can skip
+ // writing the all-zero deltas, and instead infer those from the delta
+ // header.
+ if (!delta_params.values_equal()) {
+ encoded_fields_.push_back(
+ EncodeDeltasV3(delta_params, base, remaining_values));
+ }
+}
+
+void EventEncoder::EncodeField(const FieldParameters& params,
+ const std::vector<absl::string_view>& values) {
+ RTC_DCHECK_EQ(values.size(), batch_size_);
+
+ if (values.size() == 0) {
+ // If all values for a particular field is empty/nullopt,
+ // then we completely skip the field even if the the batch is non-empty.
+ return;
+ }
+
+ // Write the field tag.
+ RTC_CHECK_NE(params.field_id, FieldParameters::kTimestampField);
+ RTC_DCHECK_LE(params.field_id, std::numeric_limits<uint64_t>::max() >> 3);
+ RTC_DCHECK_EQ(params.field_type, FieldType::kString);
+ uint64_t field_tag = params.field_id << 3;
+ field_tag += static_cast<uint64_t>(params.field_type);
+ encoded_fields_.push_back(EncodeVarInt(field_tag));
+
+ if (values.size() > 1) {
+ // If multiple values in the batch, write the encoding
+ // parameters. (Values >0 reserved for future use.)
+ uint64_t encoding_params = 0;
+ encoded_fields_.push_back(EncodeVarInt(encoding_params));
+ }
+
+ // Write the strings as (length, data) pairs.
+ for (absl::string_view s : values) {
+ encoded_fields_.push_back(EncodeVarInt(s.size()));
+ encoded_fields_.push_back(std::string(s));
+ }
+}
+
+std::string EventEncoder::AsString() {
+ std::string encoded_event;
+
+ if (batch_size_ == 0) {
+ RTC_DCHECK_EQ(encoded_fields_.size(), 0);
+ return encoded_event;
+ }
+
+ // Compute size of encoded fields.
+ size_t total_fields_size = 0;
+ for (const std::string& s : encoded_fields_) {
+ total_fields_size += s.size();
+ }
+
+ constexpr size_t kExpectedMaxEventTagBytes = 4;
+ constexpr size_t kExpectedMaxSizeEncodingBytes = 4;
+ encoded_event.reserve(kExpectedMaxEventTagBytes +
+ kExpectedMaxSizeEncodingBytes + total_fields_size);
+
+ // Encode event tag (event id and whether batch or single event).
+ encoded_event.append(EncodeVarInt(event_tag_));
+
+ // Encode size of the remaining fields.
+ encoded_event.append(EncodeVarInt(total_fields_size));
+
+ // Append encoded fields.
+ for (const std::string& s : encoded_fields_) {
+ encoded_event.append(s);
+ }
+
+ return encoded_event;
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_field_encoding.h b/logging/rtc_event_log/events/rtc_event_field_encoding.h
new file mode 100644
index 0000000000..33b77b80f5
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_field_encoding.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/rtc_event_log/rtc_event.h"
+#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h"
+#include "logging/rtc_event_log/events/fixed_length_encoding_parameters_v3.h"
+#include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+
+// To maintain backwards compatibility with past (or future) logs,
+// the constants in this enum must not be changed.
+// New field types with numerical IDs 5-7 can be added, but old
+// parsers will fail to parse events containing the new fields.
+enum class FieldType : uint8_t {
+ kFixed8 = 0,
+ kFixed32 = 1,
+ kFixed64 = 2,
+ kVarInt = 3,
+ kString = 4,
+};
+
+// EventParameters map an event name to a numerical ID.
+struct EventParameters {
+ // The name is primarily used for debugging purposes.
+ const char* const name;
+ //
+ const RtcEvent::Type id;
+};
+
+// FieldParameters define the encoding for a field.
+struct FieldParameters {
+ // The name is primarily used for debugging purposes.
+ const char* const name;
+ // Numerical ID for the field. Must be strictly greater than 0,
+ // and unique within each event type.
+ const uint64_t field_id;
+ // Encoding type for the base (i.e. non-delta) field in a batch.
+ const FieldType field_type;
+ // Number of bits after which wrap-around occurs. In most cases,
+ // this should be the number of bits in the field data type, i.e.
+ // 8 for an uint8_t, 32 for a int32_t and so on. However, `value_width`
+ // can be used to achieve a more efficient encoding if it is known
+ // that the field uses a smaller number of bits. For example, a
+ // 15-bit counter could set `value_width` to 15 even if the data is
+ // actually stored in a uint32_t.
+ const uint64_t value_width;
+ // Field ID 0 is reserved for timestamps.
+ static constexpr uint64_t kTimestampField = 0;
+};
+
+// The EventEncoder is used to encode a batch of events.
+class EventEncoder {
+ public:
+ EventEncoder(EventParameters params, rtc::ArrayView<const RtcEvent*> batch);
+
+ void EncodeField(const FieldParameters& params,
+ const std::vector<uint64_t>& values,
+ const std::vector<bool>* positions = nullptr);
+
+ void EncodeField(const FieldParameters& params,
+ const ValuesWithPositions& values);
+
+ void EncodeField(const FieldParameters& params,
+ const std::vector<absl::string_view>& values);
+
+ std::string AsString();
+
+ private:
+ size_t batch_size_;
+ uint32_t event_tag_;
+ std::vector<std::string> encoded_fields_;
+};
+
+std::string EncodeSingleValue(uint64_t value, FieldType field_type);
+std::string EncodeDeltasV3(FixedLengthEncodingParametersV3 params,
+ uint64_t base,
+ rtc::ArrayView<const uint64_t> values);
+
+// Given a batch of RtcEvents and a member pointer, extract that
+// member from each event in the batch. Signed integer members are
+// encoded as unsigned, and the bitsize increased so the result can
+// represented as a std::vector<uint64_t>.
+// This is intended to be used in conjuction with
+// EventEncoder::EncodeField to encode a batch of events as follows:
+// auto values = ExtractRtcEventMember(batch, RtcEventFoo::timestamp_ms);
+// encoder.EncodeField(timestamp_params, values)
+template <typename T,
+ typename E,
+ std::enable_if_t<std::is_integral<T>::value, bool> = true>
+std::vector<uint64_t> ExtractRtcEventMember(
+ rtc::ArrayView<const RtcEvent*> batch,
+ const T E::*member) {
+ std::vector<uint64_t> values;
+ values.reserve(batch.size());
+ for (const RtcEvent* event : batch) {
+ RTC_CHECK_EQ(event->GetType(), E::kType);
+ T value = static_cast<const E*>(event)->*member;
+ values.push_back(EncodeAsUnsigned(value));
+ }
+ return values;
+}
+
+// Extract an optional field from a batch of RtcEvents.
+// The function returns a vector of positions in addition to the vector of
+// values. The vector `positions` has the same length as the batch where
+// `positions[i] == true` iff the batch[i]->member has a value.
+// The values vector only contains the values that exists, so it
+// may be shorter than the batch.
+template <typename T,
+ typename E,
+ std::enable_if_t<std::is_integral<T>::value, bool> = true>
+ValuesWithPositions ExtractRtcEventMember(rtc::ArrayView<const RtcEvent*> batch,
+ const absl::optional<T> E::*member) {
+ ValuesWithPositions result;
+ result.position_mask.reserve(batch.size());
+ result.values.reserve(batch.size());
+ for (const RtcEvent* event : batch) {
+ RTC_CHECK_EQ(event->GetType(), E::kType);
+ absl::optional<T> field = static_cast<const E*>(event)->*member;
+ result.position_mask.push_back(field.has_value());
+ if (field.has_value()) {
+ result.values.push_back(EncodeAsUnsigned(field.value()));
+ }
+ }
+ return result;
+}
+
+// Extract an enum field from a batch of RtcEvents.
+// Requires specializing RtcEventLogEnum<T> for the enum type T.
+template <typename T,
+ typename E,
+ std::enable_if_t<std::is_enum<T>::value, bool> = true>
+std::vector<uint64_t> ExtractRtcEventMember(
+ rtc::ArrayView<const RtcEvent*> batch,
+ const T E::*member) {
+ std::vector<uint64_t> values;
+ values.reserve(batch.size());
+ for (const RtcEvent* event : batch) {
+ RTC_CHECK_EQ(event->GetType(), E::kType);
+ T value = static_cast<const E*>(event)->*member;
+ values.push_back(RtcEventLogEnum<T>::Encode(value));
+ }
+ return values;
+}
+
+// Extract a string field from a batch of RtcEvents.
+template <typename E>
+std::vector<absl::string_view> ExtractRtcEventMember(
+ rtc::ArrayView<const RtcEvent*> batch,
+ const std::string E::*member) {
+ std::vector<absl::string_view> values;
+ values.reserve(batch.size());
+ for (const RtcEvent* event : batch) {
+ RTC_CHECK_EQ(event->GetType(), E::kType);
+ absl::string_view str = static_cast<const E*>(event)->*member;
+ values.push_back(str);
+ }
+ return values;
+}
+
+} // namespace webrtc
+#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_H_
diff --git a/logging/rtc_event_log/events/rtc_event_field_encoding_parser.cc b/logging/rtc_event_log/events/rtc_event_field_encoding_parser.cc
new file mode 100644
index 0000000000..a9b0c08307
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_field_encoding_parser.cc
@@ -0,0 +1,398 @@
+
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "logging/rtc_event_log/encoder/var_int.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
+#include "rtc_base/bitstream_reader.h"
+#include "rtc_base/checks.h"
+
+namespace {
+absl::optional<webrtc::FieldType> ConvertFieldType(uint64_t value) {
+ switch (value) {
+ case static_cast<uint64_t>(webrtc::FieldType::kFixed8):
+ return webrtc::FieldType::kFixed8;
+ case static_cast<uint64_t>(webrtc::FieldType::kFixed32):
+ return webrtc::FieldType::kFixed32;
+ case static_cast<uint64_t>(webrtc::FieldType::kFixed64):
+ return webrtc::FieldType::kFixed64;
+ case static_cast<uint64_t>(webrtc::FieldType::kVarInt):
+ return webrtc::FieldType::kVarInt;
+ case static_cast<uint64_t>(webrtc::FieldType::kString):
+ return webrtc::FieldType::kString;
+ default:
+ return absl::nullopt;
+ }
+}
+} // namespace
+
+namespace webrtc {
+
+uint64_t EventParser::ReadLittleEndian(uint8_t bytes) {
+ RTC_DCHECK_LE(bytes, sizeof(uint64_t));
+ RTC_DCHECK_GE(bytes, 1);
+
+ uint64_t value = 0;
+
+ if (bytes > pending_data_.length()) {
+ SetError();
+ return value;
+ }
+
+ const uint8_t* p = reinterpret_cast<const uint8_t*>(pending_data_.data());
+ unsigned int shift = 0;
+ uint8_t remaining = bytes;
+ while (remaining > 0) {
+ value += (static_cast<uint64_t>(*p) << shift);
+ shift += 8;
+ ++p;
+ --remaining;
+ }
+
+ pending_data_ = pending_data_.substr(bytes);
+ return value;
+}
+
+uint64_t EventParser::ReadVarInt() {
+ uint64_t output = 0;
+ bool success;
+ std::tie(success, pending_data_) = DecodeVarInt(pending_data_, &output);
+ if (!success) {
+ SetError();
+ }
+ return output;
+}
+
+uint64_t EventParser::ReadOptionalValuePositions() {
+ RTC_DCHECK(positions_.empty());
+ size_t bits_to_read = NumEventsInBatch();
+ positions_.reserve(bits_to_read);
+ if (pending_data_.size() * 8 < bits_to_read) {
+ SetError();
+ return 0;
+ }
+
+ BitstreamReader reader(pending_data_);
+ for (size_t i = 0; i < bits_to_read; i++) {
+ positions_.push_back(reader.ReadBit());
+ }
+ if (!reader.Ok()) {
+ SetError();
+ return 0;
+ }
+
+ size_t num_existing_values =
+ std::count(positions_.begin(), positions_.end(), 1);
+ pending_data_ = pending_data_.substr((bits_to_read + 7) / 8);
+ return num_existing_values;
+}
+
+uint64_t EventParser::ReadSingleValue(FieldType field_type) {
+ switch (field_type) {
+ case FieldType::kFixed8:
+ return ReadLittleEndian(/*bytes=*/1);
+ case FieldType::kFixed32:
+ return ReadLittleEndian(/*bytes=*/4);
+ case FieldType::kFixed64:
+ return ReadLittleEndian(/*bytes=*/8);
+ case FieldType::kVarInt:
+ return ReadVarInt();
+ case FieldType::kString:
+ RTC_DCHECK_NOTREACHED();
+ SetError();
+ return 0;
+ }
+ RTC_DCHECK_NOTREACHED();
+ SetError();
+ return 0;
+}
+
+void EventParser::ReadDeltasAndPopulateValues(
+ FixedLengthEncodingParametersV3 params,
+ uint64_t num_deltas,
+ uint64_t base) {
+ RTC_DCHECK(values_.empty());
+ values_.reserve(num_deltas + 1);
+ values_.push_back(base);
+
+ if (pending_data_.size() * 8 < num_deltas * params.delta_bit_width()) {
+ SetError();
+ return;
+ }
+
+ BitstreamReader reader(pending_data_);
+ const uint64_t top_bit = static_cast<uint64_t>(1)
+ << (params.delta_bit_width() - 1);
+
+ uint64_t value = base;
+ for (uint64_t i = 0; i < num_deltas; ++i) {
+ uint64_t delta = reader.ReadBits(params.delta_bit_width());
+ RTC_DCHECK_LE(value, webrtc_event_logging::MaxUnsignedValueOfBitWidth(
+ params.value_bit_width()));
+ RTC_DCHECK_LE(delta, webrtc_event_logging::MaxUnsignedValueOfBitWidth(
+ params.delta_bit_width()));
+ bool negative_delta = params.signed_deltas() && ((delta & top_bit) != 0);
+ if (negative_delta) {
+ uint64_t delta_abs = (~delta & params.delta_mask()) + 1;
+ value = (value - delta_abs) & params.value_mask();
+ } else {
+ value = (value + delta) & params.value_mask();
+ }
+ values_.push_back(value);
+ }
+
+ if (!reader.Ok()) {
+ SetError();
+ return;
+ }
+
+ pending_data_ =
+ pending_data_.substr((num_deltas * params.delta_bit_width() + 7) / 8);
+}
+
+RtcEventLogParseStatus EventParser::Initialize(absl::string_view s,
+ bool batched) {
+ pending_data_ = s;
+ num_events_ = 1;
+
+ if (batched) {
+ num_events_ = ReadVarInt();
+ if (!Ok()) {
+ return RtcEventLogParseStatus::Error(
+ "Failed to read number of events in batch.", __FILE__, __LINE__);
+ }
+ }
+ return RtcEventLogParseStatus::Success();
+}
+
+RtcEventLogParseStatus EventParser::ParseNumericFieldInternal(
+ uint64_t value_bit_width,
+ FieldType field_type) {
+ RTC_DCHECK(values_.empty());
+ RTC_DCHECK(positions_.empty());
+
+ if (num_events_ == 1) {
+ // Just a single value in the batch.
+ uint64_t base = ReadSingleValue(field_type);
+ if (!Ok()) {
+ return RtcEventLogParseStatus::Error("Failed to read value", __FILE__,
+ __LINE__);
+ }
+ positions_.push_back(true);
+ values_.push_back(base);
+ } else {
+ // Delta compressed batch.
+ // Read delta header.
+ uint64_t header_value = ReadVarInt();
+ if (!Ok())
+ return RtcEventLogParseStatus::Error("Failed to read delta header",
+ __FILE__, __LINE__);
+ // NB: value_bit_width may be incorrect for the field, if this isn't the
+ // field we are looking for.
+ absl::optional<FixedLengthEncodingParametersV3> delta_header =
+ FixedLengthEncodingParametersV3::ParseDeltaHeader(header_value,
+ value_bit_width);
+ if (!delta_header.has_value()) {
+ return RtcEventLogParseStatus::Error("Failed to parse delta header",
+ __FILE__, __LINE__);
+ }
+
+ uint64_t num_existing_deltas = NumEventsInBatch() - 1;
+ if (delta_header->values_optional()) {
+ size_t num_nonempty_values = ReadOptionalValuePositions();
+ if (!Ok()) {
+ return RtcEventLogParseStatus::Error(
+ "Failed to read positions of optional values", __FILE__, __LINE__);
+ }
+ if (num_nonempty_values < 1 || NumEventsInBatch() < num_nonempty_values) {
+ return RtcEventLogParseStatus::Error(
+ "Expected at least one non_empty value", __FILE__, __LINE__);
+ }
+ num_existing_deltas = num_nonempty_values - 1;
+ } else {
+ // All elements in the batch have values.
+ positions_.assign(NumEventsInBatch(), 1u);
+ }
+
+ // Read base.
+ uint64_t base = ReadSingleValue(field_type);
+ if (!Ok()) {
+ return RtcEventLogParseStatus::Error("Failed to read value", __FILE__,
+ __LINE__);
+ }
+
+ if (delta_header->values_equal()) {
+ // Duplicate the base value num_existing_deltas times.
+ values_.assign(num_existing_deltas + 1, base);
+ } else {
+ // Read deltas; ceil(num_existing_deltas*delta_width/8) bits
+ ReadDeltasAndPopulateValues(delta_header.value(), num_existing_deltas,
+ base);
+ if (!Ok()) {
+ return RtcEventLogParseStatus::Error("Failed to decode deltas",
+ __FILE__, __LINE__);
+ }
+ }
+ }
+ return RtcEventLogParseStatus::Success();
+}
+
+RtcEventLogParseStatus EventParser::ParseStringFieldInternal() {
+ RTC_DCHECK(strings_.empty());
+ if (num_events_ > 1) {
+ // String encoding params reserved for future use.
+ uint64_t encoding_params = ReadVarInt();
+ if (!Ok()) {
+ return RtcEventLogParseStatus::Error("Failed to read string encoding",
+ __FILE__, __LINE__);
+ }
+ if (encoding_params != 0) {
+ return RtcEventLogParseStatus::Error(
+ "Unrecognized string encoding parameters", __FILE__, __LINE__);
+ }
+ }
+ strings_.reserve(num_events_);
+ for (uint64_t i = 0; i < num_events_; ++i) {
+ // Just a single value in the batch.
+ uint64_t size = ReadVarInt();
+ if (!Ok()) {
+ return RtcEventLogParseStatus::Error("Failed to read string size",
+ __FILE__, __LINE__);
+ }
+ if (size > pending_data_.size()) {
+ return RtcEventLogParseStatus::Error("String size exceeds remaining data",
+ __FILE__, __LINE__);
+ }
+ strings_.push_back(pending_data_.substr(0, size));
+ pending_data_ = pending_data_.substr(size);
+ }
+ return RtcEventLogParseStatus::Success();
+}
+
+RtcEventLogParseStatus EventParser::ParseField(const FieldParameters& params) {
+ // Verify that the event parses fields in increasing order.
+ if (params.field_id == FieldParameters::kTimestampField) {
+ RTC_DCHECK_EQ(last_field_id_, FieldParameters::kTimestampField);
+ } else {
+ RTC_DCHECK_GT(params.field_id, last_field_id_);
+ }
+ last_field_id_ = params.field_id;
+
+ // Initialization for positional fields that don't encode field ID and type.
+ uint64_t field_id = params.field_id;
+ FieldType field_type = params.field_type;
+
+ // Fields are encoded in increasing field_id order.
+ // Skip unknown fields with field_id < params.field_id until we either
+ // find params.field_id or a field with higher id, in which case we know that
+ // params.field_id doesn't exist.
+ while (!pending_data_.empty()) {
+ absl::string_view field_start = pending_data_;
+ ClearTemporaries();
+
+ // Read tag for non-positional fields.
+ if (params.field_id != FieldParameters::kTimestampField) {
+ uint64_t field_tag = ReadVarInt();
+ if (!Ok())
+ return RtcEventLogParseStatus::Error("Failed to read field tag",
+ __FILE__, __LINE__);
+ // Split tag into field ID and field type.
+ field_id = field_tag >> 3;
+ absl::optional<FieldType> conversion = ConvertFieldType(field_tag & 7u);
+ if (!conversion.has_value())
+ return RtcEventLogParseStatus::Error("Failed to parse field type",
+ __FILE__, __LINE__);
+ field_type = conversion.value();
+ }
+
+ if (field_id > params.field_id) {
+ // We've passed all fields with ids less than or equal to what we are
+ // looking for. Reset pending_data_ to first field with id higher than
+ // params.field_id, since we didn't find the field we were looking for.
+ pending_data_ = field_start;
+ return RtcEventLogParseStatus::Success();
+ }
+
+ if (field_type == FieldType::kString) {
+ auto status = ParseStringFieldInternal();
+ if (!status.ok()) {
+ return status;
+ }
+ } else {
+ auto status = ParseNumericFieldInternal(params.value_width, field_type);
+ if (!status.ok()) {
+ return status;
+ }
+ }
+
+ if (field_id == params.field_id) {
+ // The field we're looking for has been found and values populated.
+ return RtcEventLogParseStatus::Success();
+ }
+ }
+
+ // Field not found because the event ended.
+ ClearTemporaries();
+ return RtcEventLogParseStatus::Success();
+}
+
+RtcEventLogParseStatusOr<rtc::ArrayView<absl::string_view>>
+EventParser::ParseStringField(const FieldParameters& params,
+ bool required_field) {
+ using StatusOr = RtcEventLogParseStatusOr<rtc::ArrayView<absl::string_view>>;
+ RTC_DCHECK_EQ(params.field_type, FieldType::kString);
+ auto status = ParseField(params);
+ if (!status.ok())
+ return StatusOr(status);
+ rtc::ArrayView<absl::string_view> strings = GetStrings();
+ if (required_field && strings.size() != NumEventsInBatch()) {
+ return StatusOr::Error("Required string field not found", __FILE__,
+ __LINE__);
+ }
+ return StatusOr(strings);
+}
+
+RtcEventLogParseStatusOr<rtc::ArrayView<uint64_t>>
+EventParser::ParseNumericField(const FieldParameters& params,
+ bool required_field) {
+ using StatusOr = RtcEventLogParseStatusOr<rtc::ArrayView<uint64_t>>;
+ RTC_DCHECK_NE(params.field_type, FieldType::kString);
+ auto status = ParseField(params);
+ if (!status.ok())
+ return StatusOr(status);
+ rtc::ArrayView<uint64_t> values = GetValues();
+ if (required_field && values.size() != NumEventsInBatch()) {
+ return StatusOr::Error("Required numerical field not found", __FILE__,
+ __LINE__);
+ }
+ return StatusOr(values);
+}
+
+RtcEventLogParseStatusOr<EventParser::ValueAndPostionView>
+EventParser::ParseOptionalNumericField(const FieldParameters& params,
+ bool required_field) {
+ using StatusOr = RtcEventLogParseStatusOr<ValueAndPostionView>;
+ RTC_DCHECK_NE(params.field_type, FieldType::kString);
+ auto status = ParseField(params);
+ if (!status.ok())
+ return StatusOr(status);
+ ValueAndPostionView view{GetValues(), GetPositions()};
+ if (required_field && view.positions.size() != NumEventsInBatch()) {
+ return StatusOr::Error("Required numerical field not found", __FILE__,
+ __LINE__);
+ }
+ return StatusOr(view);
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_field_encoding_parser.h b/logging/rtc_event_log/events/rtc_event_field_encoding_parser.h
new file mode 100644
index 0000000000..fc87faf611
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_field_encoding_parser.h
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_PARSER_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_PARSER_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
+
+// TODO(terelius): Compared to a generic 'Status' class, this
+// class allows us additional information about the context
+// in which the error occurred. This is currently limited to
+// the source location (file and line), but we plan on adding
+// information about the event and field name being parsed.
+// If/when we start using absl::Status in WebRTC, consider
+// whether payloads would be an appropriate alternative.
+class RtcEventLogParseStatus {
+ template <typename T>
+ friend class RtcEventLogParseStatusOr;
+
+ public:
+ static RtcEventLogParseStatus Success() { return RtcEventLogParseStatus(); }
+ static RtcEventLogParseStatus Error(absl::string_view error,
+ absl::string_view file,
+ int line) {
+ return RtcEventLogParseStatus(error, file, line);
+ }
+
+ bool ok() const { return error_.empty(); }
+ ABSL_DEPRECATED("Use ok() instead") explicit operator bool() const {
+ return ok();
+ }
+
+ std::string message() const { return error_; }
+
+ private:
+ RtcEventLogParseStatus() : error_() {}
+ RtcEventLogParseStatus(absl::string_view error,
+ absl::string_view file,
+ int line)
+ : error_(std::string(error) + " (" + std::string(file) + ": " +
+ std::to_string(line) + ")") {}
+
+ std::string error_;
+};
+
+template <typename T>
+class RtcEventLogParseStatusOr {
+ public:
+ RtcEventLogParseStatusOr(RtcEventLogParseStatus status) // NOLINT
+ : status_(status), value_() {}
+ RtcEventLogParseStatusOr(const T& value) // NOLINT
+ : status_(), value_(value) {}
+
+ bool ok() const { return status_.ok(); }
+
+ std::string message() const { return status_.message(); }
+
+ RtcEventLogParseStatus status() const { return status_; }
+
+ const T& value() const {
+ RTC_DCHECK(ok());
+ return value_;
+ }
+
+ T& value() {
+ RTC_DCHECK(ok());
+ return value_;
+ }
+
+ static RtcEventLogParseStatusOr Error(absl::string_view error,
+ absl::string_view file,
+ int line) {
+ return RtcEventLogParseStatusOr(error, file, line);
+ }
+
+ private:
+ RtcEventLogParseStatusOr() : status_() {}
+ RtcEventLogParseStatusOr(absl::string_view error,
+ absl::string_view file,
+ int line)
+ : status_(error, file, line), value_() {}
+
+ RtcEventLogParseStatus status_;
+ T value_;
+};
+
+namespace webrtc {
+
+class EventParser {
+ public:
+ struct ValueAndPostionView {
+ rtc::ArrayView<uint64_t> values;
+ rtc::ArrayView<uint8_t> positions;
+ };
+
+ EventParser() = default;
+
+ // N.B: This method stores a abls::string_view into the string to be
+ // parsed. The caller is responsible for ensuring that the actual string
+ // remains unmodified and outlives the EventParser.
+ RtcEventLogParseStatus Initialize(absl::string_view s, bool batched);
+
+ // Attempts to parse the field specified by `params`, skipping past
+ // other fields that may occur before it. If 'required_field == true',
+ // then failing to find the field is an error, otherwise the functions
+ // return success, but with an empty view of values.
+ RtcEventLogParseStatusOr<rtc::ArrayView<absl::string_view>> ParseStringField(
+ const FieldParameters& params,
+ bool required_field = true);
+ RtcEventLogParseStatusOr<rtc::ArrayView<uint64_t>> ParseNumericField(
+ const FieldParameters& params,
+ bool required_field = true);
+ RtcEventLogParseStatusOr<ValueAndPostionView> ParseOptionalNumericField(
+ const FieldParameters& params,
+ bool required_field = true);
+
+ // Number of events in a batch.
+ uint64_t NumEventsInBatch() const { return num_events_; }
+
+ // Bytes remaining in `pending_data_`. Assuming there are no unknown
+ // fields, BytesRemaining() should return 0 when all known fields
+ // in the event have been parsed.
+ size_t RemainingBytes() const { return pending_data_.size(); }
+
+ private:
+ uint64_t ReadLittleEndian(uint8_t bytes);
+ uint64_t ReadVarInt();
+ uint64_t ReadSingleValue(FieldType field_type);
+ uint64_t ReadOptionalValuePositions();
+ void ReadDeltasAndPopulateValues(FixedLengthEncodingParametersV3 params,
+ uint64_t num_deltas,
+ uint64_t base);
+ RtcEventLogParseStatus ParseNumericFieldInternal(uint64_t value_bit_width,
+ FieldType field_type);
+ RtcEventLogParseStatus ParseStringFieldInternal();
+
+ // Attempts to parse the field specified by `params`, skipping past
+ // other fields that may occur before it. Returns
+ // RtcEventLogParseStatus::Success() and populates `values_` (and
+ // `positions_`) if the field is found. Returns
+ // RtcEventLogParseStatus::Success() and clears `values_` (and `positions_`)
+ // if the field doesn't exist. Returns a RtcEventLogParseStatus::Error() if
+ // the log is incomplete, malformed or otherwise can't be parsed.
+ RtcEventLogParseStatus ParseField(const FieldParameters& params);
+
+ void SetError() { error_ = true; }
+ bool Ok() const { return !error_; }
+
+ rtc::ArrayView<uint64_t> GetValues() { return values_; }
+ rtc::ArrayView<uint8_t> GetPositions() { return positions_; }
+ rtc::ArrayView<absl::string_view> GetStrings() { return strings_; }
+
+ void ClearTemporaries() {
+ positions_.clear();
+ values_.clear();
+ strings_.clear();
+ }
+
+ // Tracks whether an error has occurred in one of the helper
+ // functions above.
+ bool error_ = false;
+
+ // Temporary storage for result.
+ std::vector<uint8_t> positions_;
+ std::vector<uint64_t> values_;
+ std::vector<absl::string_view> strings_;
+
+ // String to be consumed.
+ absl::string_view pending_data_;
+ uint64_t num_events_ = 1;
+ uint64_t last_field_id_ = FieldParameters::kTimestampField;
+};
+
+// Inverse of the ExtractRtcEventMember function used when parsing
+// a log. Uses a vector of values to populate a specific field in a
+// vector of structs.
+template <typename T,
+ typename E,
+ std::enable_if_t<std::is_integral<T>::value, bool> = true>
+ABSL_MUST_USE_RESULT RtcEventLogParseStatus
+PopulateRtcEventMember(const rtc::ArrayView<uint64_t> values,
+ T E::*member,
+ rtc::ArrayView<E> output) {
+ size_t batch_size = values.size();
+ RTC_CHECK_EQ(output.size(), batch_size);
+ for (size_t i = 0; i < batch_size; ++i) {
+ output[i].*member = DecodeFromUnsignedToType<T>(values[i]);
+ }
+ return RtcEventLogParseStatus::Success();
+}
+
+// Same as above, but for optional fields.
+template <typename T,
+ typename E,
+ std::enable_if_t<std::is_integral<T>::value, bool> = true>
+ABSL_MUST_USE_RESULT RtcEventLogParseStatus
+PopulateRtcEventMember(const rtc::ArrayView<uint8_t> positions,
+ const rtc::ArrayView<uint64_t> values,
+ absl::optional<T> E::*member,
+ rtc::ArrayView<E> output) {
+ size_t batch_size = positions.size();
+ RTC_CHECK_EQ(output.size(), batch_size);
+ RTC_CHECK_LE(values.size(), batch_size);
+ auto value_it = values.begin();
+ for (size_t i = 0; i < batch_size; ++i) {
+ if (positions[i]) {
+ RTC_CHECK(value_it != values.end());
+ output[i].*member = DecodeFromUnsignedToType<T>(value_it);
+ ++value_it;
+ } else {
+ output[i].*member = absl::nullopt;
+ }
+ }
+ RTC_CHECK(value_it == values.end());
+ return RtcEventLogParseStatus::Success();
+}
+
+// Same as above, but for enum fields.
+template <typename T,
+ typename E,
+ std::enable_if_t<std::is_enum<T>::value, bool> = true>
+ABSL_MUST_USE_RESULT RtcEventLogParseStatus
+PopulateRtcEventMember(const rtc::ArrayView<uint64_t> values,
+ T E::*member,
+ rtc::ArrayView<E> output) {
+ size_t batch_size = values.size();
+ RTC_CHECK_EQ(output.size(), batch_size);
+ for (size_t i = 0; i < batch_size; ++i) {
+ auto result = RtcEventLogEnum<T>::Decode(values[i]);
+ if (!result.ok()) {
+ return result.status();
+ }
+ output[i].*member = result.value();
+ }
+ return RtcEventLogParseStatus::Success();
+}
+
+// Same as above, but for string fields.
+template <typename E>
+ABSL_MUST_USE_RESULT RtcEventLogParseStatus
+PopulateRtcEventMember(const rtc::ArrayView<absl::string_view> values,
+ std::string E::*member,
+ rtc::ArrayView<E> output) {
+ size_t batch_size = values.size();
+ RTC_CHECK_EQ(output.size(), batch_size);
+ for (size_t i = 0; i < batch_size; ++i) {
+ output[i].*member = values[i];
+ }
+ return RtcEventLogParseStatus::Success();
+}
+
+// Same as above, but for Timestamp fields.
+// N.B. Assumes that the encoded value uses millisecond precision.
+template <typename E>
+ABSL_MUST_USE_RESULT RtcEventLogParseStatus
+PopulateRtcEventTimestamp(const rtc::ArrayView<uint64_t>& values,
+ Timestamp E::*timestamp,
+ rtc::ArrayView<E> output) {
+ size_t batch_size = values.size();
+ RTC_CHECK_EQ(batch_size, output.size());
+ for (size_t i = 0; i < batch_size; ++i) {
+ output[i].*timestamp =
+ Timestamp::Millis(DecodeFromUnsignedToType<int64_t>(values[i]));
+ }
+ return RtcEventLogParseStatus::Success();
+}
+
+template <typename E>
+rtc::ArrayView<E> ExtendLoggedBatch(std::vector<E>& output,
+ size_t new_elements) {
+ size_t old_size = output.size();
+ output.insert(output.end(), old_size + new_elements, E());
+ rtc::ArrayView<E> output_batch = output;
+ output_batch.subview(old_size);
+ RTC_DCHECK_EQ(output_batch.size(), new_elements);
+ return output_batch;
+}
+
+} // namespace webrtc
+#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_ENCODING_PARSER_H_
diff --git a/logging/rtc_event_log/events/rtc_event_field_encoding_unittest.cc b/logging/rtc_event_log/events/rtc_event_field_encoding_unittest.cc
new file mode 100644
index 0000000000..18beda1417
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_field_encoding_unittest.cc
@@ -0,0 +1,886 @@
+/* Copyright (c) 2021 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "logging/rtc_event_log/events/rtc_event_field_encoding.h"
+
+#include <limits>
+#include <memory>
+#include <string>
+
+#include "absl/strings/string_view.h"
+#include "api/rtc_event_log/rtc_event.h"
+#include "logging/rtc_event_log/encoder/var_int.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+namespace {
+constexpr int32_t kInt32Max = std::numeric_limits<int32_t>::max();
+constexpr int32_t kInt32Min = std::numeric_limits<int32_t>::min();
+constexpr uint32_t kUint32Max = std::numeric_limits<uint32_t>::max();
+constexpr int64_t kInt64Max = std::numeric_limits<int64_t>::max();
+constexpr int64_t kInt64Min = std::numeric_limits<int64_t>::min();
+constexpr uint64_t kUint64Max = std::numeric_limits<uint64_t>::max();
+
+template <typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
+size_t ExpectedVarIntSize(T value) {
+ size_t bytes = 0;
+ uint64_t x = EncodeAsUnsigned(value);
+ do {
+ ++bytes;
+ x = x >> 7;
+ } while (x > 0);
+ return bytes;
+}
+
+template <typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
+size_t ExpectedBaseValueSize(const FieldParameters& params, T value) {
+ switch (params.field_type) {
+ case FieldType::kFixed8:
+ return 1;
+ case FieldType::kFixed32:
+ return 4;
+ case FieldType::kFixed64:
+ return 8;
+ case FieldType::kVarInt:
+ return ExpectedVarIntSize(value);
+ default:
+ break;
+ }
+ RTC_DCHECK_NOTREACHED();
+ return 0;
+}
+
+template <typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
+size_t ExpectedEncodingSize(const FieldParameters& params,
+ const std::vector<T>& v,
+ size_t expected_bits_per_delta) {
+ if (v.size() == 0)
+ return 0;
+
+ uint64_t numeric_field_type = static_cast<uint64_t>(params.field_type);
+ RTC_DCHECK_LT(numeric_field_type, 1u << 3);
+ size_t tag_size =
+ ExpectedVarIntSize((params.field_id << 3) + numeric_field_type);
+ T base = v[0];
+ size_t base_size = ExpectedBaseValueSize(params, base);
+ if (v.size() == 1)
+ return tag_size + base_size;
+
+ size_t delta_header_size = 1;
+ // Check if there is an element *not* equal to base.
+ if (std::all_of(v.begin(), v.end(), [base](T x) { return x == base; })) {
+ return tag_size + base_size + delta_header_size;
+ }
+
+ size_t delta_size = ((v.size() - 1) * expected_bits_per_delta + 7) / 8;
+ return tag_size + base_size + delta_header_size + delta_size;
+}
+
+template <typename T, std::enable_if_t<std::is_integral<T>::value, bool> = true>
+size_t ExpectedEncodingSize(const FieldParameters& params,
+ const std::vector<absl::optional<T>>& v,
+ size_t expected_bits_per_delta) {
+ size_t num_existing_values =
+ v.size() - std::count(v.begin(), v.end(), absl::nullopt);
+ auto first_existing_value = std::find_if(
+ v.begin(), v.end(), [](absl::optional<T> x) { return x.has_value(); });
+ if (num_existing_values == 0)
+ return 0;
+
+ uint64_t numeric_field_type = static_cast<uint64_t>(params.field_type);
+ RTC_DCHECK_LT(numeric_field_type, 1u << 3);
+ size_t tag_size =
+ ExpectedVarIntSize((params.field_id << 3) + numeric_field_type);
+ T base = first_existing_value->value();
+ size_t base_size = ExpectedBaseValueSize(params, base);
+ if (num_existing_values == 1 && v.size() == 1)
+ return tag_size + base_size;
+
+ size_t delta_header_size = (num_existing_values == v.size() ? 1 : 2);
+ size_t positions_size =
+ (num_existing_values == v.size() ? 0 : (v.size() + 7) / 8);
+ // Check if there is an element *not* equal to base.
+ if (std::all_of(v.begin(), v.end(),
+ [base](absl::optional<T> x) { return x == base; })) {
+ return tag_size + base_size + delta_header_size + positions_size;
+ }
+
+ size_t delta_size =
+ ((num_existing_values - 1) * expected_bits_per_delta + 7) / 8;
+ return tag_size + base_size + delta_header_size + positions_size + delta_size;
+}
+
+size_t ExpectedStringEncodingSize(const FieldParameters& params,
+ const std::vector<std::string>& values) {
+ EXPECT_EQ(params.field_type, FieldType::kString);
+ uint64_t numeric_field_type = static_cast<uint64_t>(params.field_type);
+ RTC_DCHECK_LT(numeric_field_type, 1u << 3);
+ size_t tag_size =
+ ExpectedVarIntSize((params.field_id << 3) + numeric_field_type);
+
+ size_t expected_size = tag_size;
+ if (values.size() > 1) {
+ // VarInt encoding header reserved for future use. Currently always 0.
+ expected_size += 1;
+ }
+ for (const auto& s : values) {
+ expected_size += ExpectedVarIntSize(s.size());
+ expected_size += s.size();
+ }
+ return expected_size;
+}
+
+} // namespace
+
+class RtcTestEvent final : public RtcEvent {
+ public:
+ RtcTestEvent(bool b,
+ int32_t signed32,
+ uint32_t unsigned32,
+ int64_t signed64,
+ uint64_t unsigned64)
+ : b_(b),
+ signed32_(signed32),
+ unsigned32_(unsigned32),
+ signed64_(signed64),
+ unsigned64_(unsigned64) {}
+ RtcTestEvent(bool b,
+ int32_t signed32,
+ uint32_t unsigned32,
+ int64_t signed64,
+ uint64_t unsigned64,
+ absl::optional<int32_t> optional_signed32,
+ absl::optional<int64_t> optional_signed64,
+ uint32_t wrapping21,
+ absl::string_view string)
+ : b_(b),
+ signed32_(signed32),
+ unsigned32_(unsigned32),
+ signed64_(signed64),
+ unsigned64_(unsigned64),
+ optional_signed32_(optional_signed32),
+ optional_signed64_(optional_signed64),
+ wrapping21_(wrapping21),
+ string_(string) {}
+ ~RtcTestEvent() override = default;
+
+ Type GetType() const override { return static_cast<Type>(4711); }
+ bool IsConfigEvent() const override { return false; }
+
+ static constexpr EventParameters event_params{
+ "TestEvent", static_cast<RtcEvent::Type>(4711)};
+ static constexpr FieldParameters timestamp_params{
+ "timestamp_ms", FieldParameters::kTimestampField, FieldType::kVarInt, 64};
+ static constexpr FieldParameters bool_params{"b", 2, FieldType::kFixed8, 1};
+ static constexpr FieldParameters signed32_params{"signed32", 3,
+ FieldType::kVarInt, 32};
+ static constexpr FieldParameters unsigned32_params{"unsigned32", 4,
+ FieldType::kFixed32, 32};
+ static constexpr FieldParameters signed64_params{"signed64", 5,
+ FieldType::kFixed64, 64};
+ static constexpr FieldParameters unsigned64_params{"unsigned64", 6,
+ FieldType::kVarInt, 64};
+ static constexpr FieldParameters optional32_params{"optional_signed32", 7,
+ FieldType::kFixed32, 32};
+ static constexpr FieldParameters optional64_params{"optional_signed64", 8,
+ FieldType::kVarInt, 64};
+ static constexpr FieldParameters wrapping21_params{"wrapping21", 9,
+ FieldType::kFixed32, 21};
+ static constexpr FieldParameters string_params{
+ "string", 10, FieldType::kString, /*value_width = */ 0};
+
+ static constexpr Type kType = static_cast<RtcEvent::Type>(4711);
+
+ const bool b_;
+ const int32_t signed32_;
+ const uint32_t unsigned32_;
+ const int64_t signed64_;
+ const uint64_t unsigned64_;
+ const absl::optional<int32_t> optional_signed32_ = absl::nullopt;
+ const absl::optional<int64_t> optional_signed64_ = absl::nullopt;
+ const uint32_t wrapping21_ = 0;
+ const std::string string_;
+};
+
+constexpr EventParameters RtcTestEvent::event_params;
+constexpr FieldParameters RtcTestEvent::timestamp_params;
+constexpr FieldParameters RtcTestEvent::bool_params;
+constexpr FieldParameters RtcTestEvent::signed32_params;
+constexpr FieldParameters RtcTestEvent::unsigned32_params;
+constexpr FieldParameters RtcTestEvent::signed64_params;
+constexpr FieldParameters RtcTestEvent::unsigned64_params;
+
+constexpr FieldParameters RtcTestEvent::optional32_params;
+constexpr FieldParameters RtcTestEvent::optional64_params;
+constexpr FieldParameters RtcTestEvent::wrapping21_params;
+constexpr FieldParameters RtcTestEvent::string_params;
+
+constexpr RtcEvent::Type RtcTestEvent::kType;
+
+class RtcEventFieldTest : public ::testing::Test {
+ protected:
+ void SetUp() override {}
+
+ void CreateFullEvents(
+ const std::vector<bool>& bool_values,
+ const std::vector<int32_t>& signed32_values,
+ const std::vector<uint32_t>& unsigned32_values,
+ const std::vector<int64_t>& signed64_values,
+ const std::vector<uint64_t>& unsigned64_values,
+ const std::vector<absl::optional<int32_t>>& optional32_values,
+ const std::vector<absl::optional<int64_t>>& optional64_values,
+ const std::vector<uint32_t>& wrapping21_values,
+ const std::vector<std::string>& string_values) {
+ size_t size = bool_values.size();
+ RTC_CHECK_EQ(signed32_values.size(), size);
+ RTC_CHECK_EQ(unsigned32_values.size(), size);
+ RTC_CHECK_EQ(signed64_values.size(), size);
+ RTC_CHECK_EQ(unsigned64_values.size(), size);
+ RTC_CHECK_EQ(optional32_values.size(), size);
+ RTC_CHECK_EQ(optional64_values.size(), size);
+ RTC_CHECK_EQ(wrapping21_values.size(), size);
+ RTC_CHECK_EQ(string_values.size(), size);
+
+ for (size_t i = 0; i < size; i++) {
+ batch_.push_back(new RtcTestEvent(
+ bool_values[i], signed32_values[i], unsigned32_values[i],
+ signed64_values[i], unsigned64_values[i], optional32_values[i],
+ optional64_values[i], wrapping21_values[i], string_values[i]));
+ }
+ }
+
+ void PrintBytes(absl::string_view s) {
+ for (auto c : s) {
+ fprintf(stderr, "%d ", static_cast<uint8_t>(c));
+ }
+ fprintf(stderr, "\n");
+ }
+
+ void ParseEventHeader(absl::string_view encoded_event) {
+ uint64_t event_tag;
+ bool success;
+ std::tie(success, encoded_event) = DecodeVarInt(encoded_event, &event_tag);
+ ASSERT_TRUE(success);
+ uint64_t event_id = event_tag >> 1;
+ ASSERT_EQ(event_id, static_cast<uint64_t>(RtcTestEvent::event_params.id));
+ bool batched = event_tag & 1u;
+ ASSERT_EQ(batched, batch_.size() > 1u);
+
+ uint64_t size;
+ std::tie(success, encoded_event) = DecodeVarInt(encoded_event, &size);
+ ASSERT_EQ(encoded_event.size(), size);
+
+ ASSERT_TRUE(parser_.Initialize(encoded_event, batched).ok());
+ }
+
+ void ParseAndVerifyTimestamps() {
+ auto result = parser_.ParseNumericField(RtcTestEvent::timestamp_params);
+ ASSERT_TRUE(result.ok()) << result.message().c_str();
+ ASSERT_EQ(result.value().size(), batch_.size());
+ for (size_t i = 0; i < batch_.size(); i++) {
+ EXPECT_EQ(result.value()[i],
+ static_cast<uint64_t>(batch_[i]->timestamp_ms()));
+ }
+ }
+
+ void ParseAndVerifyStringField(
+ const FieldParameters& params,
+ const std::vector<std::string>& expected_values,
+ size_t expected_skipped_bytes = 0) {
+ size_t expected_size = ExpectedStringEncodingSize(params, expected_values) +
+ expected_skipped_bytes;
+ size_t size_before = parser_.RemainingBytes();
+ auto result = parser_.ParseStringField(params);
+ ASSERT_TRUE(result.ok()) << result.message().c_str();
+ ASSERT_EQ(result.value().size(), expected_values.size());
+ for (size_t i = 0; i < expected_values.size(); i++) {
+ EXPECT_EQ(result.value()[i], expected_values[i]);
+ }
+ size_t size_after = parser_.RemainingBytes();
+ EXPECT_EQ(size_before - size_after, expected_size)
+ << " for field " << params.name;
+ }
+
+ template <typename T>
+ void ParseAndVerifyField(const FieldParameters& params,
+ const std::vector<T>& expected_values,
+ size_t expected_bits_per_delta,
+ size_t expected_skipped_bytes = 0) {
+ size_t expected_size =
+ ExpectedEncodingSize(params, expected_values, expected_bits_per_delta) +
+ expected_skipped_bytes;
+ size_t size_before = parser_.RemainingBytes();
+ auto result = parser_.ParseNumericField(params);
+ ASSERT_TRUE(result.ok()) << result.message().c_str();
+ ASSERT_EQ(result.value().size(), expected_values.size());
+ for (size_t i = 0; i < expected_values.size(); i++) {
+ EXPECT_EQ(DecodeFromUnsignedToType<T>(result.value()[i]),
+ expected_values[i]);
+ }
+ size_t size_after = parser_.RemainingBytes();
+ EXPECT_EQ(size_before - size_after, expected_size)
+ << " for field " << params.name;
+ }
+
+ template <typename T>
+ void ParseAndVerifyOptionalField(
+ const FieldParameters& params,
+ const std::vector<absl::optional<T>>& expected_values,
+ size_t expected_bits_per_delta,
+ size_t expected_skipped_bytes = 0) {
+ size_t expected_size =
+ ExpectedEncodingSize(params, expected_values, expected_bits_per_delta) +
+ expected_skipped_bytes;
+ size_t size_before = parser_.RemainingBytes();
+ auto result = parser_.ParseOptionalNumericField(params);
+ ASSERT_TRUE(result.ok()) << result.message().c_str();
+ rtc::ArrayView<uint64_t> values = result.value().values;
+ rtc::ArrayView<uint8_t> positions = result.value().positions;
+ ASSERT_EQ(positions.size(), expected_values.size());
+ auto value_it = values.begin();
+ for (size_t i = 0; i < expected_values.size(); i++) {
+ if (positions[i]) {
+ ASSERT_NE(value_it, values.end());
+ ASSERT_TRUE(expected_values[i].has_value());
+ EXPECT_EQ(DecodeFromUnsignedToType<T>(*value_it),
+ expected_values[i].value());
+ ++value_it;
+ } else {
+ EXPECT_EQ(absl::nullopt, expected_values[i]);
+ }
+ }
+ EXPECT_EQ(value_it, values.end());
+ size_t size_after = parser_.RemainingBytes();
+ EXPECT_EQ(size_before - size_after, expected_size);
+ }
+
+ void ParseAndVerifyMissingField(const FieldParameters& params) {
+ auto result = parser_.ParseNumericField(params, /*required_field=*/false);
+ ASSERT_TRUE(result.ok()) << result.message().c_str();
+ EXPECT_EQ(result.value().size(), 0u);
+ }
+
+ void ParseAndVerifyMissingOptionalField(const FieldParameters& params) {
+ auto result =
+ parser_.ParseOptionalNumericField(params, /*required_field=*/false);
+ ASSERT_TRUE(result.ok()) << result.message().c_str();
+ rtc::ArrayView<uint64_t> values = result.value().values;
+ rtc::ArrayView<uint8_t> positions = result.value().positions;
+ EXPECT_EQ(positions.size(), 0u);
+ EXPECT_EQ(values.size(), 0u);
+ }
+
+ void TearDown() override {
+ for (const RtcEvent* event : batch_) {
+ delete event;
+ }
+ }
+
+ std::vector<const RtcEvent*> batch_;
+ EventParser parser_;
+};
+
+TEST_F(RtcEventFieldTest, EmptyList) {
+ EventEncoder encoder(RtcTestEvent::event_params, batch_);
+ encoder.EncodeField(RtcTestEvent::bool_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::b_));
+ std::string s = encoder.AsString();
+ EXPECT_TRUE(s.empty());
+}
+
+TEST_F(RtcEventFieldTest, Singleton) {
+ std::vector<bool> bool_values = {true};
+ std::vector<int32_t> signed32_values = {-2};
+ std::vector<uint32_t> unsigned32_values = {123456789};
+ std::vector<int64_t> signed64_values = {-9876543210};
+ std::vector<uint64_t> unsigned64_values = {9876543210};
+ std::vector<absl::optional<int32_t>> optional32_values = {kInt32Min};
+ std::vector<absl::optional<int64_t>> optional64_values = {kInt64Max};
+ std::vector<uint32_t> wrapping21_values = {(1 << 21) - 1};
+ std::vector<std::string> string_values = {"foo"};
+
+ CreateFullEvents(bool_values, signed32_values, unsigned32_values,
+ signed64_values, unsigned64_values, optional32_values,
+ optional64_values, wrapping21_values, string_values);
+
+ EventEncoder encoder(RtcTestEvent::event_params, batch_);
+ encoder.EncodeField(RtcTestEvent::bool_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::b_));
+ encoder.EncodeField(RtcTestEvent::signed32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::signed32_));
+ encoder.EncodeField(
+ RtcTestEvent::unsigned32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::unsigned32_));
+ encoder.EncodeField(RtcTestEvent::signed64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::signed64_));
+ encoder.EncodeField(
+ RtcTestEvent::unsigned64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::unsigned64_));
+ encoder.EncodeField(
+ RtcTestEvent::optional32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed32_));
+ encoder.EncodeField(
+ RtcTestEvent::optional64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed64_));
+ encoder.EncodeField(
+ RtcTestEvent::wrapping21_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::wrapping21_));
+ encoder.EncodeField(RtcTestEvent::string_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::string_));
+ std::string s = encoder.AsString();
+
+ // Optional debug printing
+ // PrintBytes(s);
+
+ ParseEventHeader(s);
+ ParseAndVerifyTimestamps();
+ ParseAndVerifyField(RtcTestEvent::bool_params, bool_values,
+ /*no deltas*/ 0);
+ ParseAndVerifyField(RtcTestEvent::signed32_params, signed32_values,
+ /*no deltas*/ 0);
+ ParseAndVerifyField(RtcTestEvent::unsigned32_params, unsigned32_values,
+ /*no deltas*/ 0);
+ ParseAndVerifyField(RtcTestEvent::signed64_params, signed64_values,
+ /*no deltas*/ 0);
+ ParseAndVerifyField(RtcTestEvent::unsigned64_params, unsigned64_values,
+ /*no deltas*/ 0);
+ ParseAndVerifyOptionalField(RtcTestEvent::optional32_params,
+ optional32_values, /*no deltas*/ 0);
+ ParseAndVerifyOptionalField(RtcTestEvent::optional64_params,
+ optional64_values, /*no deltas*/ 0);
+ ParseAndVerifyField(RtcTestEvent::wrapping21_params, wrapping21_values,
+ /*no deltas*/ 0);
+ ParseAndVerifyStringField(RtcTestEvent::string_params, string_values);
+ EXPECT_EQ(parser_.RemainingBytes(), 0u);
+}
+
+TEST_F(RtcEventFieldTest, EqualElements) {
+ std::vector<bool> bool_values = {true, true, true, true};
+ std::vector<int32_t> signed32_values = {-2, -2, -2, -2};
+ std::vector<uint32_t> unsigned32_values = {123456789, 123456789, 123456789,
+ 123456789};
+ std::vector<int64_t> signed64_values = {-9876543210, -9876543210, -9876543210,
+ -9876543210};
+ std::vector<uint64_t> unsigned64_values = {9876543210, 9876543210, 9876543210,
+ 9876543210};
+ std::vector<absl::optional<int32_t>> optional32_values = {
+ kInt32Min, kInt32Min, kInt32Min, kInt32Min};
+ std::vector<absl::optional<int64_t>> optional64_values = {
+ kInt64Max, kInt64Max, kInt64Max, kInt64Max};
+ std::vector<uint32_t> wrapping21_values = {(1 << 21) - 1, (1 << 21) - 1,
+ (1 << 21) - 1, (1 << 21) - 1};
+ std::vector<std::string> string_values = {"foo", "foo", "foo", "foo"};
+
+ CreateFullEvents(bool_values, signed32_values, unsigned32_values,
+ signed64_values, unsigned64_values, optional32_values,
+ optional64_values, wrapping21_values, string_values);
+ EventEncoder encoder(RtcTestEvent::event_params, batch_);
+ encoder.EncodeField(RtcTestEvent::bool_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::b_));
+ encoder.EncodeField(RtcTestEvent::signed32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::signed32_));
+ encoder.EncodeField(
+ RtcTestEvent::unsigned32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::unsigned32_));
+ encoder.EncodeField(RtcTestEvent::signed64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::signed64_));
+ encoder.EncodeField(
+ RtcTestEvent::unsigned64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::unsigned64_));
+ encoder.EncodeField(
+ RtcTestEvent::optional32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed32_));
+ encoder.EncodeField(
+ RtcTestEvent::optional64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed64_));
+ encoder.EncodeField(
+ RtcTestEvent::wrapping21_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::wrapping21_));
+ encoder.EncodeField(RtcTestEvent::string_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::string_));
+ std::string s = encoder.AsString();
+
+ // Optional debug printing
+ // PrintBytes(s);
+
+ ParseEventHeader(s);
+ ParseAndVerifyTimestamps();
+ ParseAndVerifyField(RtcTestEvent::bool_params, bool_values,
+ /*no deltas*/ 0);
+ ParseAndVerifyField(RtcTestEvent::signed32_params, signed32_values,
+ /*no deltas*/ 0);
+ ParseAndVerifyField(RtcTestEvent::unsigned32_params, unsigned32_values,
+ /*no deltas*/ 0);
+ ParseAndVerifyField(RtcTestEvent::signed64_params, signed64_values,
+ /*no deltas*/ 0);
+ ParseAndVerifyField(RtcTestEvent::unsigned64_params, unsigned64_values,
+ /*no deltas*/ 0);
+ ParseAndVerifyOptionalField(RtcTestEvent::optional32_params,
+ optional32_values, /*no deltas*/ 0);
+ ParseAndVerifyOptionalField(RtcTestEvent::optional64_params,
+ optional64_values, /*no deltas*/ 0);
+ ParseAndVerifyField(RtcTestEvent::wrapping21_params, wrapping21_values,
+ /*no deltas*/ 0);
+ ParseAndVerifyStringField(RtcTestEvent::string_params, string_values);
+ EXPECT_EQ(parser_.RemainingBytes(), 0u);
+}
+
+TEST_F(RtcEventFieldTest, Increasing) {
+ std::vector<bool> bool_values = {false, true, false, true};
+ std::vector<int32_t> signed32_values = {-2, -1, 0, 1};
+ std::vector<uint32_t> unsigned32_values = {kUint32Max - 1, kUint32Max, 0, 1};
+ std::vector<int64_t> signed64_values = {kInt64Max - 1, kInt64Max, kInt64Min,
+ kInt64Min + 1};
+ std::vector<uint64_t> unsigned64_values = {kUint64Max - 1, kUint64Max, 0, 1};
+ std::vector<absl::optional<int32_t>> optional32_values = {
+ kInt32Max - 1, kInt32Max, kInt32Min, kInt32Min + 1};
+ std::vector<absl::optional<int64_t>> optional64_values = {
+ kInt64Max - 1, kInt64Max, kInt64Min, kInt64Min + 1};
+ std::vector<uint32_t> wrapping21_values = {(1 << 21) - 2, (1 << 21) - 1, 0,
+ 1};
+ std::vector<std::string> string_values = {
+ "", "a", "bc", "def"}; // No special compression of strings.
+
+ CreateFullEvents(bool_values, signed32_values, unsigned32_values,
+ signed64_values, unsigned64_values, optional32_values,
+ optional64_values, wrapping21_values, string_values);
+
+ EventEncoder encoder(RtcTestEvent::event_params, batch_);
+ encoder.EncodeField(RtcTestEvent::bool_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::b_));
+ encoder.EncodeField(RtcTestEvent::signed32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::signed32_));
+ encoder.EncodeField(
+ RtcTestEvent::unsigned32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::unsigned32_));
+ encoder.EncodeField(RtcTestEvent::signed64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::signed64_));
+ encoder.EncodeField(
+ RtcTestEvent::unsigned64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::unsigned64_));
+ encoder.EncodeField(
+ RtcTestEvent::optional32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed32_));
+ encoder.EncodeField(
+ RtcTestEvent::optional64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed64_));
+ encoder.EncodeField(
+ RtcTestEvent::wrapping21_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::wrapping21_));
+ encoder.EncodeField(RtcTestEvent::string_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::string_));
+ std::string s = encoder.AsString();
+
+ // Optional debug printing
+ // PrintBytes(s);
+
+ ParseEventHeader(s);
+ ParseAndVerifyTimestamps();
+ ParseAndVerifyField(RtcTestEvent::bool_params, bool_values,
+ /*delta bits*/ 1);
+ ParseAndVerifyField(RtcTestEvent::signed32_params, signed32_values,
+ /*delta bits*/ 1);
+ ParseAndVerifyField(RtcTestEvent::unsigned32_params, unsigned32_values,
+ /*delta bits*/ 1);
+ ParseAndVerifyField(RtcTestEvent::signed64_params, signed64_values,
+ /*delta bits*/ 1);
+ ParseAndVerifyField(RtcTestEvent::unsigned64_params, unsigned64_values,
+ /*delta bits*/ 1);
+ ParseAndVerifyOptionalField(RtcTestEvent::optional32_params,
+ optional32_values, /*delta bits*/ 1);
+ ParseAndVerifyOptionalField(RtcTestEvent::optional64_params,
+ optional64_values, /*delta bits*/ 1);
+ ParseAndVerifyField(RtcTestEvent::wrapping21_params, wrapping21_values,
+ /*delta bits*/ 1);
+ ParseAndVerifyStringField(RtcTestEvent::string_params, string_values);
+ EXPECT_EQ(parser_.RemainingBytes(), 0u);
+}
+
+TEST_F(RtcEventFieldTest, Decreasing) {
+ std::vector<bool> bool_values = {true, false, true, false};
+ std::vector<int32_t> signed32_values = {2, 1, 0, -1};
+ std::vector<uint32_t> unsigned32_values = {1, 0, kUint32Max, kUint32Max - 1};
+ std::vector<int64_t> signed64_values = {kInt64Min + 1, kInt64Min, kInt64Max,
+ kInt64Max - 1};
+ std::vector<uint64_t> unsigned64_values = {1, 0, kUint64Max, kUint64Max - 1};
+ std::vector<absl::optional<int32_t>> optional32_values = {
+ kInt32Min + 1, kInt32Min, kInt32Max, kInt32Max - 1};
+ std::vector<absl::optional<int64_t>> optional64_values = {
+ kInt64Min + 1, kInt64Min, kInt64Max, kInt64Max - 1};
+ std::vector<uint32_t> wrapping21_values = {1, 0, (1 << 21) - 1,
+ (1 << 21) - 2};
+ std::vector<std::string> string_values = {
+ "def", "bc", "a", ""}; // No special compression of strings.
+
+ CreateFullEvents(bool_values, signed32_values, unsigned32_values,
+ signed64_values, unsigned64_values, optional32_values,
+ optional64_values, wrapping21_values, string_values);
+
+ EventEncoder encoder(RtcTestEvent::event_params, batch_);
+ encoder.EncodeField(RtcTestEvent::bool_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::b_));
+ encoder.EncodeField(RtcTestEvent::signed32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::signed32_));
+ encoder.EncodeField(
+ RtcTestEvent::unsigned32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::unsigned32_));
+ encoder.EncodeField(RtcTestEvent::signed64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::signed64_));
+ encoder.EncodeField(
+ RtcTestEvent::unsigned64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::unsigned64_));
+ encoder.EncodeField(
+ RtcTestEvent::optional32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed32_));
+ encoder.EncodeField(
+ RtcTestEvent::optional64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed64_));
+ encoder.EncodeField(
+ RtcTestEvent::wrapping21_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::wrapping21_));
+ encoder.EncodeField(RtcTestEvent::string_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::string_));
+ std::string s = encoder.AsString();
+
+ // Optional debug printing
+ // PrintBytes(s);
+
+ ParseEventHeader(s);
+ ParseAndVerifyTimestamps();
+ ParseAndVerifyField(RtcTestEvent::bool_params, bool_values,
+ /*delta bits*/ 1);
+ ParseAndVerifyField(RtcTestEvent::signed32_params, signed32_values,
+ /*delta bits*/ 1);
+ ParseAndVerifyField(RtcTestEvent::unsigned32_params, unsigned32_values,
+ /*delta bits*/ 1);
+ ParseAndVerifyField(RtcTestEvent::signed64_params, signed64_values,
+ /*delta bits*/ 1);
+ ParseAndVerifyField(RtcTestEvent::unsigned64_params, unsigned64_values,
+ /*delta bits*/ 1);
+ ParseAndVerifyOptionalField(RtcTestEvent::optional32_params,
+ optional32_values, /*delta bits*/ 1);
+ ParseAndVerifyOptionalField(RtcTestEvent::optional64_params,
+ optional64_values, /*delta bits*/ 1);
+ ParseAndVerifyField(RtcTestEvent::wrapping21_params, wrapping21_values,
+ /*delta bits*/ 1);
+ ParseAndVerifyStringField(RtcTestEvent::string_params, string_values);
+ EXPECT_EQ(parser_.RemainingBytes(), 0u);
+}
+
+TEST_F(RtcEventFieldTest, SkipsDeprecatedFields) {
+ // Expect parser to skip fields it doesn't recognize, but find subsequent
+ // fields.
+ std::vector<bool> bool_values = {true, false};
+ std::vector<int32_t> signed32_values = {kInt32Min / 2, kInt32Max / 2};
+ std::vector<uint32_t> unsigned32_values = {0, kUint32Max / 2};
+ std::vector<int64_t> signed64_values = {kInt64Min / 2, kInt64Max / 2};
+ std::vector<uint64_t> unsigned64_values = {0, kUint64Max / 2};
+ std::vector<absl::optional<int32_t>> optional32_values = {kInt32Max / 2,
+ kInt32Min / 2};
+ std::vector<absl::optional<int64_t>> optional64_values = {kInt64Min / 2,
+ kInt64Max / 2};
+ std::vector<uint32_t> wrapping21_values = {0, 1 << 20};
+ std::vector<std::string> string_values = {"foo", "bar"};
+
+ size_t signed32_encoding_size =
+ /*tag*/ 1 + /* varint base*/ 5 + /* delta_header*/ 1 + /*deltas*/ 4;
+ size_t signed64_encoding_size =
+ /*tag*/ 1 + /* fixed64 base*/ 8 + /* delta_header*/ 1 + /*deltas*/ 8;
+ size_t optional32_encoding_size =
+ /*tag*/ 1 + /* fixed32 base*/ 4 + /* delta_header*/ 1 + /*deltas*/ 4;
+
+ CreateFullEvents(bool_values, signed32_values, unsigned32_values,
+ signed64_values, unsigned64_values, optional32_values,
+ optional64_values, wrapping21_values, string_values);
+
+ EventEncoder encoder(RtcTestEvent::event_params, batch_);
+ encoder.EncodeField(RtcTestEvent::bool_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::b_));
+ encoder.EncodeField(RtcTestEvent::signed32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::signed32_));
+ encoder.EncodeField(
+ RtcTestEvent::unsigned32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::unsigned32_));
+ encoder.EncodeField(RtcTestEvent::signed64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::signed64_));
+ encoder.EncodeField(
+ RtcTestEvent::unsigned64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::unsigned64_));
+ encoder.EncodeField(
+ RtcTestEvent::optional32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed32_));
+ encoder.EncodeField(
+ RtcTestEvent::optional64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed64_));
+ encoder.EncodeField(
+ RtcTestEvent::wrapping21_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::wrapping21_));
+ encoder.EncodeField(RtcTestEvent::string_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::string_));
+ std::string s = encoder.AsString();
+
+ // Optional debug printing
+ // PrintBytes(s);
+
+ ParseEventHeader(s);
+ ParseAndVerifyTimestamps();
+ ParseAndVerifyField(RtcTestEvent::bool_params, bool_values,
+ /*delta_bits=*/1);
+ // Skips parsing the `signed32_values`. The following unsigned fields should
+ // still be found.
+ ParseAndVerifyField(RtcTestEvent::unsigned32_params, unsigned32_values,
+ /*delta_bits=*/31,
+ /*expected_skipped_bytes=*/signed32_encoding_size);
+ // Skips parsing the `signed64_values`. The following unsigned fields should
+ // still be found.
+ ParseAndVerifyField(RtcTestEvent::unsigned64_params, unsigned64_values,
+ /*delta_bits=*/63, signed64_encoding_size);
+ // Skips parsing the `optional32_values`. The following unsigned fields should
+ // still be found.
+ ParseAndVerifyOptionalField(RtcTestEvent::optional64_params,
+ optional64_values,
+ /*delta_bits=*/63, optional32_encoding_size);
+ ParseAndVerifyField(RtcTestEvent::wrapping21_params, wrapping21_values,
+ /*delta_bits=*/20);
+ ParseAndVerifyStringField(RtcTestEvent::string_params, string_values);
+ EXPECT_EQ(parser_.RemainingBytes(), 0u);
+}
+
+TEST_F(RtcEventFieldTest, SkipsMissingFields) {
+ // Expect parsing of missing field to succeed but return an empty list.
+
+ std::vector<bool> bool_values = {true, false};
+ std::vector<int32_t> signed32_values = {kInt32Min / 2, kInt32Max / 2};
+ std::vector<uint32_t> unsigned32_values = {0, kUint32Max / 2};
+ std::vector<int64_t> signed64_values = {kInt64Min / 2, kInt64Max / 2};
+ std::vector<uint64_t> unsigned64_values = {0, kUint64Max / 2};
+ std::vector<absl::optional<int32_t>> optional32_values = {kInt32Max / 2,
+ kInt32Min / 2};
+ std::vector<absl::optional<int64_t>> optional64_values = {kInt64Min / 2,
+ kInt64Max / 2};
+ std::vector<uint32_t> wrapping21_values = {0, 1 << 20};
+ std::vector<std::string> string_values = {"foo", "foo"};
+
+ CreateFullEvents(bool_values, signed32_values, unsigned32_values,
+ signed64_values, unsigned64_values, optional32_values,
+ optional64_values, wrapping21_values, string_values);
+
+ EventEncoder encoder(RtcTestEvent::event_params, batch_);
+ // Skip encoding the `bool_values`.
+ encoder.EncodeField(RtcTestEvent::signed32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::signed32_));
+ // Skip encoding the `unsigned32_values`.
+ encoder.EncodeField(RtcTestEvent::signed64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::signed64_));
+ // Skip encoding the `unsigned64_values`.
+ encoder.EncodeField(
+ RtcTestEvent::optional32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed32_));
+ // Skip encoding the `optional64_values`.
+ encoder.EncodeField(
+ RtcTestEvent::wrapping21_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::wrapping21_));
+ encoder.EncodeField(RtcTestEvent::string_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::string_));
+ std::string s = encoder.AsString();
+
+ // Optional debug printing
+ // PrintBytes(s);
+
+ ParseEventHeader(s);
+ ParseAndVerifyTimestamps();
+ ParseAndVerifyMissingField(RtcTestEvent::bool_params);
+ ParseAndVerifyField(RtcTestEvent::signed32_params, signed32_values,
+ /*delta_bits=*/31);
+ ParseAndVerifyMissingField(RtcTestEvent::unsigned32_params);
+ ParseAndVerifyField(RtcTestEvent::signed64_params, signed64_values,
+ /*delta_bits=*/63);
+ ParseAndVerifyMissingField(RtcTestEvent::unsigned64_params);
+ ParseAndVerifyOptionalField(RtcTestEvent::optional32_params,
+ optional32_values, /*delta_bits=*/31);
+ ParseAndVerifyMissingOptionalField(RtcTestEvent::optional64_params);
+ ParseAndVerifyField(RtcTestEvent::wrapping21_params, wrapping21_values,
+ /*delta_bits=*/20);
+ ParseAndVerifyStringField(RtcTestEvent::string_params, string_values);
+ EXPECT_EQ(parser_.RemainingBytes(), 0u);
+}
+
+TEST_F(RtcEventFieldTest, OptionalFields) {
+ std::vector<absl::optional<int32_t>> optional32_values = {
+ 2, absl::nullopt, 4, absl::nullopt, 6, absl::nullopt};
+ std::vector<absl::optional<int64_t>> optional64_values = {
+ absl::nullopt, 1024, absl::nullopt, 1025, absl::nullopt, 1026};
+ std::vector<uint32_t> wrapping21_values = {(1 << 21) - 3, 0, 2, 5, 5, 6};
+
+ for (size_t i = 0; i < optional32_values.size(); i++) {
+ batch_.push_back(new RtcTestEvent(0, 0, 0, 0, 0, optional32_values[i],
+ optional64_values[i],
+ wrapping21_values[i], ""));
+ }
+
+ EventEncoder encoder(RtcTestEvent::event_params, batch_);
+ encoder.EncodeField(
+ RtcTestEvent::optional32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed32_));
+ encoder.EncodeField(
+ RtcTestEvent::optional64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed64_));
+ encoder.EncodeField(
+ RtcTestEvent::wrapping21_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::wrapping21_));
+ std::string s = encoder.AsString();
+
+ // Optional debug output
+ // PrintBytes(s);
+
+ ParseEventHeader(s);
+ ParseAndVerifyTimestamps();
+ ParseAndVerifyOptionalField(RtcTestEvent::optional32_params,
+ optional32_values, /*delta bits*/ 2);
+ ParseAndVerifyOptionalField(RtcTestEvent::optional64_params,
+ optional64_values, /*delta bits*/ 1);
+ ParseAndVerifyField(RtcTestEvent::wrapping21_params, wrapping21_values,
+ /*delta bits*/ 2);
+ EXPECT_EQ(parser_.RemainingBytes(), 0u);
+}
+
+TEST_F(RtcEventFieldTest, AllNulloptTreatedAsMissing) {
+ std::vector<absl::optional<int32_t>> optional32_values = {
+ absl::nullopt, absl::nullopt, absl::nullopt,
+ absl::nullopt, absl::nullopt, absl::nullopt};
+ std::vector<absl::optional<int64_t>> optional64_values = {
+ absl::nullopt, 1024, absl::nullopt, 1025, absl::nullopt, 1026};
+
+ for (size_t i = 0; i < optional32_values.size(); i++) {
+ batch_.push_back(new RtcTestEvent(0, 0, 0, 0, 0, optional32_values[i],
+ optional64_values[i], 0, ""));
+ }
+
+ EventEncoder encoder(RtcTestEvent::event_params, batch_);
+ encoder.EncodeField(
+ RtcTestEvent::optional32_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed32_));
+ encoder.EncodeField(
+ RtcTestEvent::optional64_params,
+ ExtractRtcEventMember(batch_, &RtcTestEvent::optional_signed64_));
+ std::string s = encoder.AsString();
+
+ // Optional debug output
+ // PrintBytes(s);
+
+ ParseEventHeader(s);
+ ParseAndVerifyTimestamps();
+ ParseAndVerifyMissingOptionalField(RtcTestEvent::optional32_params);
+ ParseAndVerifyOptionalField(RtcTestEvent::optional64_params,
+ optional64_values, /*delta_bits=*/1);
+ EXPECT_EQ(parser_.RemainingBytes(), 0u);
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_field_extraction.cc b/logging/rtc_event_log/events/rtc_event_field_extraction.cc
new file mode 100644
index 0000000000..99f0b3697c
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_field_extraction.cc
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
+
+#include <algorithm>
+#include <limits>
+
+#include "rtc_base/checks.h"
+
+namespace webrtc_event_logging {
+
+// The bitwidth required to encode values in the range
+// [0, `max_pos_magnitude`] using an unsigned representation.
+uint8_t UnsignedBitWidth(uint64_t max_magnitude) {
+ uint8_t required_bits = 1;
+ while (max_magnitude >>= 1) {
+ ++required_bits;
+ }
+ return required_bits;
+}
+
+// The bitwidth required to encode signed values in the range
+// [-`max_neg_magnitude`, `max_pos_magnitude`] using a signed
+// 2-complement representation.
+uint8_t SignedBitWidth(uint64_t max_pos_magnitude, uint64_t max_neg_magnitude) {
+ const uint8_t bitwidth_positive =
+ max_pos_magnitude > 0 ? UnsignedBitWidth(max_pos_magnitude) : 0;
+ const uint8_t bitwidth_negative =
+ (max_neg_magnitude > 1) ? UnsignedBitWidth(max_neg_magnitude - 1) : 0;
+ return 1 + std::max(bitwidth_positive, bitwidth_negative);
+}
+
+// Return the maximum integer of a given bit width.
+uint64_t MaxUnsignedValueOfBitWidth(uint64_t bit_width) {
+ RTC_DCHECK_GE(bit_width, 1);
+ RTC_DCHECK_LE(bit_width, 64);
+ return (bit_width == 64) ? std::numeric_limits<uint64_t>::max()
+ : ((static_cast<uint64_t>(1) << bit_width) - 1);
+}
+
+// Computes the delta between `previous` and `current`, under the assumption
+// that `bit_mask` is the largest value before wrap-around occurs. The bitmask
+// must be of the form 2^x-1. (We use the wrap-around to more efficiently
+// compress counters that wrap around at different bit widths than the
+// backing C++ data type.)
+uint64_t UnsignedDelta(uint64_t previous, uint64_t current, uint64_t bit_mask) {
+ RTC_DCHECK_LE(previous, bit_mask);
+ RTC_DCHECK_LE(current, bit_mask);
+ return (current - previous) & bit_mask;
+}
+
+} // namespace webrtc_event_logging
diff --git a/logging/rtc_event_log/events/rtc_event_field_extraction.h b/logging/rtc_event_log/events/rtc_event_field_extraction.h
new file mode 100644
index 0000000000..eb9d67f1c2
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_field_extraction.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_EXTRACTION_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_EXTRACTION_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "api/array_view.h"
+#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc_event_logging {
+uint8_t UnsignedBitWidth(uint64_t max_magnitude);
+uint8_t SignedBitWidth(uint64_t max_pos_magnitude, uint64_t max_neg_magnitude);
+uint64_t MaxUnsignedValueOfBitWidth(uint64_t bit_width);
+uint64_t UnsignedDelta(uint64_t previous, uint64_t current, uint64_t bit_mask);
+} // namespace webrtc_event_logging
+
+namespace webrtc {
+template <typename T, std::enable_if_t<std::is_signed<T>::value, bool> = true>
+uint64_t EncodeAsUnsigned(T value) {
+ return webrtc_event_logging::ToUnsigned(value);
+}
+
+template <typename T, std::enable_if_t<std::is_unsigned<T>::value, bool> = true>
+uint64_t EncodeAsUnsigned(T value) {
+ return static_cast<uint64_t>(value);
+}
+
+template <typename T, std::enable_if_t<std::is_signed<T>::value, bool> = true>
+T DecodeFromUnsignedToType(uint64_t value) {
+ T signed_value = 0;
+ bool success = webrtc_event_logging::ToSigned<T>(value, &signed_value);
+ if (!success) {
+ RTC_LOG(LS_ERROR) << "Failed to convert " << value << "to signed type.";
+ // TODO(terelius): Propagate error?
+ }
+ return signed_value;
+}
+
+template <typename T, std::enable_if_t<std::is_unsigned<T>::value, bool> = true>
+T DecodeFromUnsignedToType(uint64_t value) {
+ // TODO(terelius): Check range?
+ return static_cast<T>(value);
+}
+
+// RtcEventLogEnum<T> defines a mapping between an enum T
+// and the event log encodings. To log a new enum type T,
+// specialize RtcEventLogEnum<T> and add static methods
+// static uint64_t Encode(T x) {}
+// static RtcEventLogParseStatusOr<T> Decode(uint64_t x) {}
+template <typename T>
+class RtcEventLogEnum {
+ static_assert(sizeof(T) != sizeof(T),
+ "Missing specialisation of RtcEventLogEnum for type");
+};
+
+// Represents a vector<optional<uint64_t>> optional_values
+// as a bit-vector `position_mask` which identifies the positions
+// of existing values, and a (potentially shorter)
+// `vector<uint64_t> values` containing the actual values.
+// The bit vector is constructed such that position_mask[i]
+// is true iff optional_values[i] has a value, and `values.size()`
+// is equal to the number of set bits in `position_mask`.
+struct ValuesWithPositions {
+ std::vector<bool> position_mask;
+ std::vector<uint64_t> values;
+};
+
+} // namespace webrtc
+
+#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FIELD_EXTRACTION_H_
diff --git a/logging/rtc_event_log/events/rtc_event_field_extraction_unittest.cc b/logging/rtc_event_log/events/rtc_event_field_extraction_unittest.cc
new file mode 100644
index 0000000000..f9fb993af0
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_field_extraction_unittest.cc
@@ -0,0 +1,97 @@
+/* Copyright (c) 2021 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/events/rtc_event_field_extraction.h"
+
+#include "rtc_base/random.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+
+TEST(UnsignedBitWidthTest, SmallValues) {
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(0), 1u);
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(1), 1u);
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(2), 2u);
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(3), 2u);
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(4), 3u);
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(5), 3u);
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(6), 3u);
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(7), 3u);
+}
+
+TEST(UnsignedBitWidthTest, PowersOfTwo) {
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(0), 1u);
+
+ for (unsigned i = 0; i < 64; i++) {
+ uint64_t x = 1;
+ x = x << i;
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(x), i + 1);
+ }
+}
+
+TEST(UnsignedBitWidthTest, PowersOfTwoMinusOne) {
+ for (unsigned i = 1; i < 64; i++) {
+ uint64_t x = 1;
+ x = (x << i) - 1;
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(x), i);
+ }
+
+ uint64_t x = ~static_cast<uint64_t>(0);
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(x), 64u);
+}
+
+TEST(UnsignedBitWidthTest, RandomInputs) {
+ Random rand(12345);
+
+ for (unsigned i = 0; i < 64; i++) {
+ uint64_t x = 1;
+ x = x << i;
+ uint64_t high = rand.Rand<uint32_t>();
+ uint64_t low = rand.Rand<uint32_t>();
+ x += ((high << 32) + low) % x;
+ EXPECT_EQ(webrtc_event_logging::UnsignedBitWidth(x), i + 1);
+ }
+}
+
+TEST(SignedBitWidthTest, SignedBitWidth) {
+ EXPECT_EQ(webrtc_event_logging::SignedBitWidth(0, 1), 1u);
+ EXPECT_EQ(webrtc_event_logging::SignedBitWidth(1, 0), 2u);
+ EXPECT_EQ(webrtc_event_logging::SignedBitWidth(1, 2), 2u);
+ EXPECT_EQ(webrtc_event_logging::SignedBitWidth(1, 128), 8u);
+ EXPECT_EQ(webrtc_event_logging::SignedBitWidth(127, 1), 8u);
+ EXPECT_EQ(webrtc_event_logging::SignedBitWidth(127, 128), 8u);
+ EXPECT_EQ(webrtc_event_logging::SignedBitWidth(1, 129), 9u);
+ EXPECT_EQ(webrtc_event_logging::SignedBitWidth(128, 1), 9u);
+}
+
+TEST(MaxUnsignedValueOfBitWidthTest, MaxUnsignedValueOfBitWidth) {
+ EXPECT_EQ(webrtc_event_logging::MaxUnsignedValueOfBitWidth(1), 0x01u);
+ EXPECT_EQ(webrtc_event_logging::MaxUnsignedValueOfBitWidth(6), 0x3Fu);
+ EXPECT_EQ(webrtc_event_logging::MaxUnsignedValueOfBitWidth(8), 0xFFu);
+ EXPECT_EQ(webrtc_event_logging::MaxUnsignedValueOfBitWidth(32), 0xFFFFFFFFu);
+}
+
+TEST(EncodeAsUnsignedTest, NegativeValues) {
+ // Negative values are converted as if cast to unsigned type of
+ // the same bitsize using 2-complement representation.
+ int16_t x = -1;
+ EXPECT_EQ(EncodeAsUnsigned(x), static_cast<uint64_t>(0xFFFF));
+ int64_t y = -1;
+ EXPECT_EQ(EncodeAsUnsigned(y), static_cast<uint64_t>(0xFFFFFFFFFFFFFFFFull));
+}
+
+TEST(EncodeAsUnsignedTest, PositiveValues) {
+ // Postive values are unchanged.
+ int16_t x = 42;
+ EXPECT_EQ(EncodeAsUnsigned(x), static_cast<uint64_t>(42));
+ int64_t y = 42;
+ EXPECT_EQ(EncodeAsUnsigned(y), static_cast<uint64_t>(42));
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_frame_decoded.cc b/logging/rtc_event_log/events/rtc_event_frame_decoded.cc
new file mode 100644
index 0000000000..cde412e6c4
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_frame_decoded.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "logging/rtc_event_log/events/rtc_event_frame_decoded.h"
+
+#include "absl/memory/memory.h"
+
+namespace webrtc {
+
+RtcEventFrameDecoded::RtcEventFrameDecoded(int64_t render_time_ms,
+ uint32_t ssrc,
+ int width,
+ int height,
+ VideoCodecType codec,
+ uint8_t qp)
+ : render_time_ms_(render_time_ms),
+ ssrc_(ssrc),
+ width_(width),
+ height_(height),
+ codec_(codec),
+ qp_(qp) {}
+
+RtcEventFrameDecoded::RtcEventFrameDecoded(const RtcEventFrameDecoded& other)
+ : RtcEvent(other.timestamp_us_),
+ render_time_ms_(other.render_time_ms_),
+ ssrc_(other.ssrc_),
+ width_(other.width_),
+ height_(other.height_),
+ codec_(other.codec_),
+ qp_(other.qp_) {}
+
+std::unique_ptr<RtcEventFrameDecoded> RtcEventFrameDecoded::Copy() const {
+ return absl::WrapUnique<RtcEventFrameDecoded>(
+ new RtcEventFrameDecoded(*this));
+}
+
+} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_frame_decoded.h b/logging/rtc_event_log/events/rtc_event_frame_decoded.h
new file mode 100644
index 0000000000..91190faea9
--- /dev/null
+++ b/logging/rtc_event_log/events/rtc_event_frame_decoded.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FRAME_DECODED_H_
+#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FRAME_DECODED_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "api/video/video_codec_type.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
+
+namespace webrtc {
+
+struct LoggedFrameDecoded {
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ int64_t render_time_ms;
+ uint32_t ssrc;
+ int width;
+ int height;
+ VideoCodecType codec;
+ uint8_t qp;
+};
+
+class RtcEventFrameDecoded final : public RtcEvent {
+ public:
+ static constexpr Type kType = Type::FrameDecoded;
+
+ RtcEventFrameDecoded(int64_t render_time_ms,
+ uint32_t ssrc,
+ int width,
+ int height,
+ VideoCodecType codec,
+ uint8_t qp);
+ ~RtcEventFrameDecoded() override = default;
+
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
+
+ std::unique_ptr<RtcEventFrameDecoded> Copy() const;
+
+ int64_t render_time_ms() const { return render_time_ms_; }
+ uint32_t ssrc() const { return ssrc_; }
+ int width() const { return width_; }
+ int height() const { return height_; }
+ VideoCodecType codec() const { return codec_; }
+ uint8_t qp() const { return qp_; }
+
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::map<uint32_t, std::vector<LoggedFrameDecoded>>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
+ private:
+ RtcEventFrameDecoded(const RtcEventFrameDecoded& other);
+
+ const int64_t render_time_ms_;
+ const uint32_t ssrc_;
+ const int width_;
+ const int height_;
+ const VideoCodecType codec_;
+ const uint8_t qp_;
+};
+
+} // namespace webrtc
+
+#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_FRAME_DECODED_H_
diff --git a/logging/rtc_event_log/events/rtc_event_generic_ack_received.cc b/logging/rtc_event_log/events/rtc_event_generic_ack_received.cc
index 0ffe62259f..ba18d50ab6 100644
--- a/logging/rtc_event_log/events/rtc_event_generic_ack_received.cc
+++ b/logging/rtc_event_log/events/rtc_event_generic_ack_received.cc
@@ -23,6 +23,7 @@ RtcEventGenericAckReceived::CreateLogs(
const std::vector<AckedPacket>& acked_packets) {
std::vector<std::unique_ptr<RtcEventGenericAckReceived>> result;
int64_t time_us = rtc::TimeMicros();
+ result.reserve(acked_packets.size());
for (const AckedPacket& packet : acked_packets) {
result.emplace_back(new RtcEventGenericAckReceived(
time_us, packet_number, packet.packet_number,
@@ -51,12 +52,4 @@ RtcEventGenericAckReceived::RtcEventGenericAckReceived(
RtcEventGenericAckReceived::~RtcEventGenericAckReceived() = default;
-RtcEvent::Type RtcEventGenericAckReceived::GetType() const {
- return RtcEvent::Type::GenericAckReceived;
-}
-
-bool RtcEventGenericAckReceived::IsConfigEvent() const {
- return false;
-}
-
} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_generic_ack_received.h b/logging/rtc_event_log/events/rtc_event_generic_ack_received.h
index 689c124619..57fd7cd9a6 100644
--- a/logging/rtc_event_log/events/rtc_event_generic_ack_received.h
+++ b/logging/rtc_event_log/events/rtc_event_generic_ack_received.h
@@ -12,13 +12,38 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_GENERIC_ACK_RECEIVED_H_
#include <memory>
+#include <string>
#include <vector>
+#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
+struct LoggedGenericAckReceived {
+ LoggedGenericAckReceived() = default;
+ LoggedGenericAckReceived(Timestamp timestamp,
+ int64_t packet_number,
+ int64_t acked_packet_number,
+ absl::optional<int64_t> receive_acked_packet_time_ms)
+ : timestamp(timestamp),
+ packet_number(packet_number),
+ acked_packet_number(acked_packet_number),
+ receive_acked_packet_time_ms(receive_acked_packet_time_ms) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ int64_t packet_number;
+ int64_t acked_packet_number;
+ absl::optional<int64_t> receive_acked_packet_time_ms;
+};
+
struct AckedPacket {
// The packet number that was acked.
int64_t packet_number;
@@ -30,6 +55,8 @@ struct AckedPacket {
class RtcEventGenericAckReceived final : public RtcEvent {
public:
+ static constexpr Type kType = Type::GenericAckReceived;
+
// For a collection of acked packets, it creates a vector of logs to log with
// the same timestamp.
static std::vector<std::unique_ptr<RtcEventGenericAckReceived>> CreateLogs(
@@ -40,9 +67,8 @@ class RtcEventGenericAckReceived final : public RtcEvent {
std::unique_ptr<RtcEventGenericAckReceived> Copy() const;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
// An identifier of the packet which contained an ack.
int64_t packet_number() const { return packet_number_; }
@@ -50,18 +76,31 @@ class RtcEventGenericAckReceived final : public RtcEvent {
// An identifier of the acked packet.
int64_t acked_packet_number() const { return acked_packet_number_; }
- // Timestamp when the |acked_packet_number| was received by the remote side.
+ // Timestamp when the `acked_packet_number` was received by the remote side.
absl::optional<int64_t> receive_acked_packet_time_ms() const {
return receive_acked_packet_time_ms_;
}
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedGenericAckReceived>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventGenericAckReceived(const RtcEventGenericAckReceived& packet);
- // When the ack is received, |packet_number| identifies the packet which
- // contained an ack for |acked_packet_number|, and contains the
- // |receive_acked_packet_time_ms| on which the |acked_packet_number| was
- // received on the remote side. The |receive_acked_packet_time_ms| may be
+ // When the ack is received, `packet_number` identifies the packet which
+ // contained an ack for `acked_packet_number`, and contains the
+ // `receive_acked_packet_time_ms` on which the `acked_packet_number` was
+ // received on the remote side. The `receive_acked_packet_time_ms` may be
// null.
RtcEventGenericAckReceived(
int64_t timestamp_us,
diff --git a/logging/rtc_event_log/events/rtc_event_generic_packet_received.cc b/logging/rtc_event_log/events/rtc_event_generic_packet_received.cc
index 92558b29dd..0bdc4dd505 100644
--- a/logging/rtc_event_log/events/rtc_event_generic_packet_received.cc
+++ b/logging/rtc_event_log/events/rtc_event_generic_packet_received.cc
@@ -28,12 +28,5 @@ std::unique_ptr<RtcEventGenericPacketReceived>
RtcEventGenericPacketReceived::Copy() const {
return absl::WrapUnique(new RtcEventGenericPacketReceived(*this));
}
-RtcEvent::Type RtcEventGenericPacketReceived::GetType() const {
- return RtcEvent::Type::GenericPacketReceived;
-}
-
-bool RtcEventGenericPacketReceived::IsConfigEvent() const {
- return false;
-}
} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_generic_packet_received.h b/logging/rtc_event_log/events/rtc_event_generic_packet_received.h
index 1034826a47..a6006ca4d4 100644
--- a/logging/rtc_event_log/events/rtc_event_generic_packet_received.h
+++ b/logging/rtc_event_log/events/rtc_event_generic_packet_received.h
@@ -12,21 +12,45 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_GENERIC_PACKET_RECEIVED_H_
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
+struct LoggedGenericPacketReceived {
+ LoggedGenericPacketReceived() = default;
+ LoggedGenericPacketReceived(Timestamp timestamp,
+ int64_t packet_number,
+ int packet_length)
+ : timestamp(timestamp),
+ packet_number(packet_number),
+ packet_length(packet_length) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ int64_t packet_number;
+ int packet_length;
+};
+
class RtcEventGenericPacketReceived final : public RtcEvent {
public:
+ static constexpr Type kType = Type::GenericPacketReceived;
+
RtcEventGenericPacketReceived(int64_t packet_number, size_t packet_length);
~RtcEventGenericPacketReceived() override;
std::unique_ptr<RtcEventGenericPacketReceived> Copy() const;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
// An identifier of the packet.
int64_t packet_number() const { return packet_number_; }
@@ -35,6 +59,19 @@ class RtcEventGenericPacketReceived final : public RtcEvent {
// including ICE/TURN/IP overheads.
size_t packet_length() const { return packet_length_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedGenericPacketReceived>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventGenericPacketReceived(const RtcEventGenericPacketReceived& packet);
diff --git a/logging/rtc_event_log/events/rtc_event_generic_packet_sent.cc b/logging/rtc_event_log/events/rtc_event_generic_packet_sent.cc
index ef761d5e9d..e8335624b1 100644
--- a/logging/rtc_event_log/events/rtc_event_generic_packet_sent.cc
+++ b/logging/rtc_event_log/events/rtc_event_generic_packet_sent.cc
@@ -33,12 +33,4 @@ std::unique_ptr<RtcEventGenericPacketSent> RtcEventGenericPacketSent::Copy()
return absl::WrapUnique(new RtcEventGenericPacketSent(*this));
}
-RtcEvent::Type RtcEventGenericPacketSent::GetType() const {
- return RtcEvent::Type::GenericPacketSent;
-}
-
-bool RtcEventGenericPacketSent::IsConfigEvent() const {
- return false;
-}
-
} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_generic_packet_sent.h b/logging/rtc_event_log/events/rtc_event_generic_packet_sent.h
index d87a54cbe2..903950a398 100644
--- a/logging/rtc_event_log/events/rtc_event_generic_packet_sent.h
+++ b/logging/rtc_event_log/events/rtc_event_generic_packet_sent.h
@@ -12,13 +12,47 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_GENERIC_PACKET_SENT_H_
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
+struct LoggedGenericPacketSent {
+ LoggedGenericPacketSent() = default;
+ LoggedGenericPacketSent(Timestamp timestamp,
+ int64_t packet_number,
+ size_t overhead_length,
+ size_t payload_length,
+ size_t padding_length)
+ : timestamp(timestamp),
+ packet_number(packet_number),
+ overhead_length(overhead_length),
+ payload_length(payload_length),
+ padding_length(padding_length) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ size_t packet_length() const {
+ return payload_length + padding_length + overhead_length;
+ }
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ int64_t packet_number;
+ size_t overhead_length;
+ size_t payload_length;
+ size_t padding_length;
+};
+
class RtcEventGenericPacketSent final : public RtcEvent {
public:
+ static constexpr Type kType = Type::GenericPacketSent;
+
RtcEventGenericPacketSent(int64_t packet_number,
size_t overhead_length,
size_t payload_length,
@@ -27,9 +61,8 @@ class RtcEventGenericPacketSent final : public RtcEvent {
std::unique_ptr<RtcEventGenericPacketSent> Copy() const;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
// An identifier of the packet.
int64_t packet_number() const { return packet_number_; }
@@ -50,6 +83,19 @@ class RtcEventGenericPacketSent final : public RtcEvent {
size_t padding_length() const { return padding_length_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedGenericPacketSent>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventGenericPacketSent(const RtcEventGenericPacketSent& packet);
diff --git a/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.cc b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.cc
index 225362d9e6..2b4b5ba762 100644
--- a/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.cc
+++ b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.cc
@@ -31,14 +31,6 @@ RtcEventIceCandidatePair::RtcEventIceCandidatePair(
RtcEventIceCandidatePair::~RtcEventIceCandidatePair() = default;
-RtcEvent::Type RtcEventIceCandidatePair::GetType() const {
- return RtcEvent::Type::IceCandidatePairEvent;
-}
-
-bool RtcEventIceCandidatePair::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventIceCandidatePair> RtcEventIceCandidatePair::Copy()
const {
return absl::WrapUnique<RtcEventIceCandidatePair>(
diff --git a/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h
index 88b8c8268f..bdacf15a59 100644
--- a/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h
+++ b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h
@@ -14,8 +14,13 @@
#include <stdint.h>
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
@@ -27,17 +32,39 @@ enum class IceCandidatePairEventType {
kNumValues,
};
+struct LoggedIceCandidatePairEvent {
+ LoggedIceCandidatePairEvent() = default;
+ LoggedIceCandidatePairEvent(Timestamp timestamp,
+ IceCandidatePairEventType type,
+ uint32_t candidate_pair_id,
+ uint32_t transaction_id)
+ : timestamp(timestamp),
+ type(type),
+ candidate_pair_id(candidate_pair_id),
+ transaction_id(transaction_id) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ IceCandidatePairEventType type;
+ uint32_t candidate_pair_id;
+ uint32_t transaction_id;
+};
+
class RtcEventIceCandidatePair final : public RtcEvent {
public:
+ static constexpr Type kType = Type::IceCandidatePairEvent;
+
RtcEventIceCandidatePair(IceCandidatePairEventType type,
uint32_t candidate_pair_id,
uint32_t transaction_id);
~RtcEventIceCandidatePair() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventIceCandidatePair> Copy() const;
@@ -45,6 +72,19 @@ class RtcEventIceCandidatePair final : public RtcEvent {
uint32_t candidate_pair_id() const { return candidate_pair_id_; }
uint32_t transaction_id() const { return transaction_id_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedIceCandidatePairEvent>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventIceCandidatePair(const RtcEventIceCandidatePair& other);
diff --git a/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc
index fbb8a73dfb..eb458c4640 100644
--- a/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc
+++ b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.cc
@@ -54,16 +54,6 @@ RtcEventIceCandidatePairConfig::RtcEventIceCandidatePairConfig(
RtcEventIceCandidatePairConfig::~RtcEventIceCandidatePairConfig() = default;
-RtcEvent::Type RtcEventIceCandidatePairConfig::GetType() const {
- return RtcEvent::Type::IceCandidatePairConfig;
-}
-
-// The ICE candidate pair config event is not equivalent to a RtcEventLog config
-// event.
-bool RtcEventIceCandidatePairConfig::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventIceCandidatePairConfig>
RtcEventIceCandidatePairConfig::Copy() const {
return absl::WrapUnique<RtcEventIceCandidatePairConfig>(
diff --git a/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h
index 338942acb3..e72d999cff 100644
--- a/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h
+++ b/logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h
@@ -14,8 +14,13 @@
#include <stdint.h>
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
@@ -64,6 +69,23 @@ enum class IceCandidateNetworkType {
kNumValues,
};
+struct LoggedIceCandidatePairConfig {
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ IceCandidatePairConfigType type;
+ uint32_t candidate_pair_id;
+ IceCandidateType local_candidate_type;
+ IceCandidatePairProtocol local_relay_protocol;
+ IceCandidateNetworkType local_network_type;
+ IceCandidatePairAddressFamily local_address_family;
+ IceCandidateType remote_candidate_type;
+ IceCandidatePairAddressFamily remote_address_family;
+ IceCandidatePairProtocol candidate_pair_protocol;
+};
+
class IceCandidatePairDescription {
public:
IceCandidatePairDescription();
@@ -83,6 +105,8 @@ class IceCandidatePairDescription {
class RtcEventIceCandidatePairConfig final : public RtcEvent {
public:
+ static constexpr Type kType = Type::IceCandidatePairConfig;
+
RtcEventIceCandidatePairConfig(
IceCandidatePairConfigType type,
uint32_t candidate_pair_id,
@@ -90,9 +114,9 @@ class RtcEventIceCandidatePairConfig final : public RtcEvent {
~RtcEventIceCandidatePairConfig() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ // N.B. An ICE config event is not considered an RtcEventLog config event.
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventIceCandidatePairConfig> Copy() const;
@@ -102,6 +126,19 @@ class RtcEventIceCandidatePairConfig final : public RtcEvent {
return candidate_pair_desc_;
}
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedIceCandidatePairConfig>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventIceCandidatePairConfig(const RtcEventIceCandidatePairConfig& other);
diff --git a/logging/rtc_event_log/events/rtc_event_probe_cluster_created.cc b/logging/rtc_event_log/events/rtc_event_probe_cluster_created.cc
index c11a6ce78e..c3d9e59b47 100644
--- a/logging/rtc_event_log/events/rtc_event_probe_cluster_created.cc
+++ b/logging/rtc_event_log/events/rtc_event_probe_cluster_created.cc
@@ -31,14 +31,6 @@ RtcEventProbeClusterCreated::RtcEventProbeClusterCreated(
min_probes_(other.min_probes_),
min_bytes_(other.min_bytes_) {}
-RtcEvent::Type RtcEventProbeClusterCreated::GetType() const {
- return RtcEvent::Type::ProbeClusterCreated;
-}
-
-bool RtcEventProbeClusterCreated::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventProbeClusterCreated> RtcEventProbeClusterCreated::Copy()
const {
return absl::WrapUnique<RtcEventProbeClusterCreated>(
diff --git a/logging/rtc_event_log/events/rtc_event_probe_cluster_created.h b/logging/rtc_event_log/events/rtc_event_probe_cluster_created.h
index 7bfe6a252e..ae6810c39d 100644
--- a/logging/rtc_event_log/events/rtc_event_probe_cluster_created.h
+++ b/logging/rtc_event_log/events/rtc_event_probe_cluster_created.h
@@ -14,22 +14,52 @@
#include <stdint.h>
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
+struct LoggedBweProbeClusterCreatedEvent {
+ LoggedBweProbeClusterCreatedEvent() = default;
+ LoggedBweProbeClusterCreatedEvent(Timestamp timestamp,
+ int32_t id,
+ int32_t bitrate_bps,
+ uint32_t min_packets,
+ uint32_t min_bytes)
+ : timestamp(timestamp),
+ id(id),
+ bitrate_bps(bitrate_bps),
+ min_packets(min_packets),
+ min_bytes(min_bytes) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ int32_t id;
+ int32_t bitrate_bps;
+ uint32_t min_packets;
+ uint32_t min_bytes;
+};
+
class RtcEventProbeClusterCreated final : public RtcEvent {
public:
+ static constexpr Type kType = Type::ProbeClusterCreated;
+
RtcEventProbeClusterCreated(int32_t id,
int32_t bitrate_bps,
uint32_t min_probes,
uint32_t min_bytes);
~RtcEventProbeClusterCreated() override = default;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventProbeClusterCreated> Copy() const;
@@ -38,6 +68,19 @@ class RtcEventProbeClusterCreated final : public RtcEvent {
uint32_t min_probes() const { return min_probes_; }
uint32_t min_bytes() const { return min_bytes_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedBweProbeClusterCreatedEvent>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventProbeClusterCreated(const RtcEventProbeClusterCreated& other);
diff --git a/logging/rtc_event_log/events/rtc_event_probe_result_failure.cc b/logging/rtc_event_log/events/rtc_event_probe_result_failure.cc
index 295003ae8d..a79b0c173d 100644
--- a/logging/rtc_event_log/events/rtc_event_probe_result_failure.cc
+++ b/logging/rtc_event_log/events/rtc_event_probe_result_failure.cc
@@ -25,14 +25,6 @@ RtcEventProbeResultFailure::RtcEventProbeResultFailure(
id_(other.id_),
failure_reason_(other.failure_reason_) {}
-RtcEvent::Type RtcEventProbeResultFailure::GetType() const {
- return RtcEvent::Type::ProbeResultFailure;
-}
-
-bool RtcEventProbeResultFailure::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventProbeResultFailure> RtcEventProbeResultFailure::Copy()
const {
return absl::WrapUnique<RtcEventProbeResultFailure>(
diff --git a/logging/rtc_event_log/events/rtc_event_probe_result_failure.h b/logging/rtc_event_log/events/rtc_event_probe_result_failure.h
index a493de8ec3..1aa6e75cb7 100644
--- a/logging/rtc_event_log/events/rtc_event_probe_result_failure.h
+++ b/logging/rtc_event_log/events/rtc_event_probe_result_failure.h
@@ -14,8 +14,13 @@
#include <stdint.h>
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
@@ -26,20 +31,50 @@ enum class ProbeFailureReason {
kLast
};
+struct LoggedBweProbeFailureEvent {
+ LoggedBweProbeFailureEvent() = default;
+ LoggedBweProbeFailureEvent(Timestamp timestamp,
+ int32_t id,
+ ProbeFailureReason failure_reason)
+ : timestamp(timestamp), id(id), failure_reason(failure_reason) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ int32_t id;
+ ProbeFailureReason failure_reason;
+};
+
class RtcEventProbeResultFailure final : public RtcEvent {
public:
+ static constexpr Type kType = Type::ProbeResultFailure;
+
RtcEventProbeResultFailure(int32_t id, ProbeFailureReason failure_reason);
~RtcEventProbeResultFailure() override = default;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventProbeResultFailure> Copy() const;
int32_t id() const { return id_; }
ProbeFailureReason failure_reason() const { return failure_reason_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedBweProbeFailureEvent>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventProbeResultFailure(const RtcEventProbeResultFailure& other);
diff --git a/logging/rtc_event_log/events/rtc_event_probe_result_success.cc b/logging/rtc_event_log/events/rtc_event_probe_result_success.cc
index d5f9e2f780..e7bc7c25da 100644
--- a/logging/rtc_event_log/events/rtc_event_probe_result_success.cc
+++ b/logging/rtc_event_log/events/rtc_event_probe_result_success.cc
@@ -24,14 +24,6 @@ RtcEventProbeResultSuccess::RtcEventProbeResultSuccess(
id_(other.id_),
bitrate_bps_(other.bitrate_bps_) {}
-RtcEvent::Type RtcEventProbeResultSuccess::GetType() const {
- return RtcEvent::Type::ProbeResultSuccess;
-}
-
-bool RtcEventProbeResultSuccess::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventProbeResultSuccess> RtcEventProbeResultSuccess::Copy()
const {
return absl::WrapUnique<RtcEventProbeResultSuccess>(
diff --git a/logging/rtc_event_log/events/rtc_event_probe_result_success.h b/logging/rtc_event_log/events/rtc_event_probe_result_success.h
index e0aba982a1..49d1abec5a 100644
--- a/logging/rtc_event_log/events/rtc_event_probe_result_success.h
+++ b/logging/rtc_event_log/events/rtc_event_probe_result_success.h
@@ -14,25 +14,60 @@
#include <stdint.h>
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
+struct LoggedBweProbeSuccessEvent {
+ LoggedBweProbeSuccessEvent() = default;
+ LoggedBweProbeSuccessEvent(Timestamp timestamp,
+ int32_t id,
+ int32_t bitrate_bps)
+ : timestamp(timestamp), id(id), bitrate_bps(bitrate_bps) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ int32_t id;
+ int32_t bitrate_bps;
+};
+
class RtcEventProbeResultSuccess final : public RtcEvent {
public:
+ static constexpr Type kType = Type::ProbeResultSuccess;
+
RtcEventProbeResultSuccess(int32_t id, int32_t bitrate_bps);
~RtcEventProbeResultSuccess() override = default;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventProbeResultSuccess> Copy() const;
int32_t id() const { return id_; }
int32_t bitrate_bps() const { return bitrate_bps_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedBweProbeSuccessEvent>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventProbeResultSuccess(const RtcEventProbeResultSuccess& other);
diff --git a/logging/rtc_event_log/events/rtc_event_remote_estimate.h b/logging/rtc_event_log/events/rtc_event_remote_estimate.h
index b7919483cc..4a39ecc597 100644
--- a/logging/rtc_event_log/events/rtc_event_remote_estimate.h
+++ b/logging/rtc_event_log/events/rtc_event_remote_estimate.h
@@ -11,24 +11,58 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_REMOTE_ESTIMATE_H_
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/rtc_event_log/rtc_event.h"
#include "api/units/data_rate.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
+struct LoggedRemoteEstimateEvent {
+ LoggedRemoteEstimateEvent() = default;
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ absl::optional<DataRate> link_capacity_lower;
+ absl::optional<DataRate> link_capacity_upper;
+};
+
class RtcEventRemoteEstimate final : public RtcEvent {
public:
+ static constexpr Type kType = Type::RemoteEstimateEvent;
+
RtcEventRemoteEstimate(DataRate link_capacity_lower,
DataRate link_capacity_upper)
: link_capacity_lower_(link_capacity_lower),
link_capacity_upper_(link_capacity_upper) {}
- Type GetType() const override { return RtcEvent::Type::RemoteEstimateEvent; }
+
+ Type GetType() const override { return kType; }
bool IsConfigEvent() const override { return false; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedRemoteEstimateEvent>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
const DataRate link_capacity_lower_;
const DataRate link_capacity_upper_;
};
+
} // namespace webrtc
#endif // LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_REMOTE_ESTIMATE_H_
diff --git a/logging/rtc_event_log/events/rtc_event_route_change.cc b/logging/rtc_event_log/events/rtc_event_route_change.cc
index 1ea63e2dcc..71bd78b346 100644
--- a/logging/rtc_event_log/events/rtc_event_route_change.cc
+++ b/logging/rtc_event_log/events/rtc_event_route_change.cc
@@ -24,14 +24,6 @@ RtcEventRouteChange::RtcEventRouteChange(const RtcEventRouteChange& other)
RtcEventRouteChange::~RtcEventRouteChange() = default;
-RtcEvent::Type RtcEventRouteChange::GetType() const {
- return RtcEvent::Type::RouteChangeEvent;
-}
-
-bool RtcEventRouteChange::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventRouteChange> RtcEventRouteChange::Copy() const {
return absl::WrapUnique<RtcEventRouteChange>(new RtcEventRouteChange(*this));
}
diff --git a/logging/rtc_event_log/events/rtc_event_route_change.h b/logging/rtc_event_log/events/rtc_event_route_change.h
index 09fb31c570..bc1461d7bb 100644
--- a/logging/rtc_event_log/events/rtc_event_route_change.h
+++ b/logging/rtc_event_log/events/rtc_event_route_change.h
@@ -12,25 +12,58 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_ROUTE_CHANGE_H_
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
namespace webrtc {
+struct LoggedRouteChangeEvent {
+ LoggedRouteChangeEvent() = default;
+ LoggedRouteChangeEvent(Timestamp timestamp, bool connected, uint32_t overhead)
+ : timestamp(timestamp), connected(connected), overhead(overhead) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ bool connected;
+ uint32_t overhead;
+};
+
class RtcEventRouteChange final : public RtcEvent {
public:
+ static constexpr Type kType = Type::RouteChangeEvent;
+
RtcEventRouteChange(bool connected, uint32_t overhead);
~RtcEventRouteChange() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventRouteChange> Copy() const;
bool connected() const { return connected_; }
uint32_t overhead() const { return overhead_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedRouteChangeEvent>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventRouteChange(const RtcEventRouteChange& other);
diff --git a/logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.cc b/logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.cc
index 45a418f1f6..0ea700a024 100644
--- a/logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.cc
+++ b/logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.cc
@@ -25,14 +25,6 @@ RtcEventRtcpPacketIncoming::RtcEventRtcpPacketIncoming(
RtcEventRtcpPacketIncoming::~RtcEventRtcpPacketIncoming() = default;
-RtcEvent::Type RtcEventRtcpPacketIncoming::GetType() const {
- return RtcEvent::Type::RtcpPacketIncoming;
-}
-
-bool RtcEventRtcpPacketIncoming::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventRtcpPacketIncoming> RtcEventRtcpPacketIncoming::Copy()
const {
return absl::WrapUnique<RtcEventRtcpPacketIncoming>(
diff --git a/logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h b/logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h
index 8237afea90..84fe398e08 100644
--- a/logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h
+++ b/logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h
@@ -14,26 +14,45 @@
#include <stdint.h>
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "logging/rtc_event_log/events/logged_rtp_rtcp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
#include "rtc_base/buffer.h"
namespace webrtc {
class RtcEventRtcpPacketIncoming final : public RtcEvent {
public:
+ static constexpr Type kType = Type::RtcpPacketIncoming;
+
explicit RtcEventRtcpPacketIncoming(rtc::ArrayView<const uint8_t> packet);
~RtcEventRtcpPacketIncoming() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventRtcpPacketIncoming> Copy() const;
const rtc::Buffer& packet() const { return packet_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedRtcpPacketIncoming>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventRtcpPacketIncoming(const RtcEventRtcpPacketIncoming& other);
diff --git a/logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.cc b/logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.cc
index b583e5614a..b6a41ac034 100644
--- a/logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.cc
+++ b/logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.cc
@@ -25,14 +25,6 @@ RtcEventRtcpPacketOutgoing::RtcEventRtcpPacketOutgoing(
RtcEventRtcpPacketOutgoing::~RtcEventRtcpPacketOutgoing() = default;
-RtcEvent::Type RtcEventRtcpPacketOutgoing::GetType() const {
- return RtcEvent::Type::RtcpPacketOutgoing;
-}
-
-bool RtcEventRtcpPacketOutgoing::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventRtcpPacketOutgoing> RtcEventRtcpPacketOutgoing::Copy()
const {
return absl::WrapUnique<RtcEventRtcpPacketOutgoing>(
diff --git a/logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h b/logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h
index f451c7301e..687bd319b4 100644
--- a/logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h
+++ b/logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h
@@ -14,26 +14,45 @@
#include <stdint.h>
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "logging/rtc_event_log/events/logged_rtp_rtcp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
#include "rtc_base/buffer.h"
namespace webrtc {
class RtcEventRtcpPacketOutgoing final : public RtcEvent {
public:
+ static constexpr Type kType = Type::RtcpPacketOutgoing;
+
explicit RtcEventRtcpPacketOutgoing(rtc::ArrayView<const uint8_t> packet);
~RtcEventRtcpPacketOutgoing() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventRtcpPacketOutgoing> Copy() const;
const rtc::Buffer& packet() const { return packet_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedRtcpPacketOutgoing>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventRtcpPacketOutgoing(const RtcEventRtcpPacketOutgoing& other);
diff --git a/logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.cc b/logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.cc
index 898c0aaf8e..4cf33a238f 100644
--- a/logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.cc
+++ b/logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.cc
@@ -18,33 +18,14 @@ namespace webrtc {
RtcEventRtpPacketIncoming::RtcEventRtpPacketIncoming(
const RtpPacketReceived& packet)
- : payload_length_(packet.payload_size()),
- header_length_(packet.headers_size()),
- padding_length_(packet.padding_size()) {
- header_.CopyHeaderFrom(packet);
- RTC_DCHECK_EQ(packet.size(),
- payload_length_ + header_length_ + padding_length_);
-}
+ : packet_(packet) {}
RtcEventRtpPacketIncoming::RtcEventRtpPacketIncoming(
const RtcEventRtpPacketIncoming& other)
- : RtcEvent(other.timestamp_us_),
- payload_length_(other.payload_length_),
- header_length_(other.header_length_),
- padding_length_(other.padding_length_) {
- header_.CopyHeaderFrom(other.header_);
-}
+ : RtcEvent(other.timestamp_us_), packet_(other.packet_) {}
RtcEventRtpPacketIncoming::~RtcEventRtpPacketIncoming() = default;
-RtcEvent::Type RtcEventRtpPacketIncoming::GetType() const {
- return RtcEvent::Type::RtpPacketIncoming;
-}
-
-bool RtcEventRtpPacketIncoming::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventRtpPacketIncoming> RtcEventRtpPacketIncoming::Copy()
const {
return absl::WrapUnique<RtcEventRtpPacketIncoming>(
diff --git a/logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h b/logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h
index 7e30d6d7c8..926ddddff5 100644
--- a/logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h
+++ b/logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h
@@ -11,9 +11,19 @@
#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_RTP_PACKET_INCOMING_H_
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_RTP_PACKET_INCOMING_H_
+#include <cstddef>
+#include <cstdint>
+#include <map>
#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "logging/rtc_event_log/events/logged_rtp_rtcp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
#include "modules/rtp_rtcp/source/rtp_packet.h"
namespace webrtc {
@@ -22,31 +32,56 @@ class RtpPacketReceived;
class RtcEventRtpPacketIncoming final : public RtcEvent {
public:
+ static constexpr Type kType = Type::RtpPacketIncoming;
+
explicit RtcEventRtpPacketIncoming(const RtpPacketReceived& packet);
~RtcEventRtpPacketIncoming() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventRtpPacketIncoming> Copy() const;
- size_t packet_length() const {
- return payload_length_ + header_length_ + padding_length_;
+ size_t packet_length() const { return packet_.size(); }
+
+ rtc::ArrayView<const uint8_t> RawHeader() const {
+ return rtc::MakeArrayView(packet_.data(), header_length());
+ }
+ uint32_t Ssrc() const { return packet_.Ssrc(); }
+ uint32_t Timestamp() const { return packet_.Timestamp(); }
+ uint16_t SequenceNumber() const { return packet_.SequenceNumber(); }
+ uint8_t PayloadType() const { return packet_.PayloadType(); }
+ bool Marker() const { return packet_.Marker(); }
+ template <typename ExtensionTrait, typename... Args>
+ bool GetExtension(Args&&... args) const {
+ return packet_.GetExtension<ExtensionTrait>(std::forward<Args>(args)...);
+ }
+ template <typename ExtensionTrait>
+ bool HasExtension() const {
+ return packet_.HasExtension<ExtensionTrait>();
}
- const RtpPacket& header() const { return header_; }
- size_t payload_length() const { return payload_length_; }
- size_t header_length() const { return header_length_; }
- size_t padding_length() const { return padding_length_; }
+ size_t payload_length() const { return packet_.payload_size(); }
+ size_t header_length() const { return packet_.headers_size(); }
+ size_t padding_length() const { return packet_.padding_size(); }
+
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::map<uint32_t, std::vector<LoggedRtpPacketIncoming>>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
private:
RtcEventRtpPacketIncoming(const RtcEventRtpPacketIncoming& other);
- RtpPacket header_; // Only the packet's header will be stored here.
- const size_t payload_length_; // Media payload, excluding header and padding.
- const size_t header_length_; // RTP header.
- const size_t padding_length_; // RTP padding.
+ const RtpPacket packet_;
};
} // namespace webrtc
diff --git a/logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.cc b/logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.cc
index 050474edda..a6a4d99702 100644
--- a/logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.cc
+++ b/logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.cc
@@ -19,35 +19,16 @@ namespace webrtc {
RtcEventRtpPacketOutgoing::RtcEventRtpPacketOutgoing(
const RtpPacketToSend& packet,
int probe_cluster_id)
- : payload_length_(packet.payload_size()),
- header_length_(packet.headers_size()),
- padding_length_(packet.padding_size()),
- probe_cluster_id_(probe_cluster_id) {
- header_.CopyHeaderFrom(packet);
- RTC_DCHECK_EQ(packet.size(),
- payload_length_ + header_length_ + padding_length_);
-}
+ : packet_(packet), probe_cluster_id_(probe_cluster_id) {}
RtcEventRtpPacketOutgoing::RtcEventRtpPacketOutgoing(
const RtcEventRtpPacketOutgoing& other)
: RtcEvent(other.timestamp_us_),
- payload_length_(other.payload_length_),
- header_length_(other.header_length_),
- padding_length_(other.padding_length_),
- probe_cluster_id_(other.probe_cluster_id_) {
- header_.CopyHeaderFrom(other.header_);
-}
+ packet_(other.packet_),
+ probe_cluster_id_(other.probe_cluster_id_) {}
RtcEventRtpPacketOutgoing::~RtcEventRtpPacketOutgoing() = default;
-RtcEvent::Type RtcEventRtpPacketOutgoing::GetType() const {
- return RtcEvent::Type::RtpPacketOutgoing;
-}
-
-bool RtcEventRtpPacketOutgoing::IsConfigEvent() const {
- return false;
-}
-
std::unique_ptr<RtcEventRtpPacketOutgoing> RtcEventRtpPacketOutgoing::Copy()
const {
return absl::WrapUnique<RtcEventRtpPacketOutgoing>(
diff --git a/logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h b/logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h
index 9211367bf4..c7b7a09718 100644
--- a/logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h
+++ b/logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h
@@ -11,9 +11,19 @@
#ifndef LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_RTP_PACKET_OUTGOING_H_
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_RTP_PACKET_OUTGOING_H_
+#include <cstddef>
+#include <cstdint>
+#include <map>
#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "logging/rtc_event_log/events/logged_rtp_rtcp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
#include "modules/rtp_rtcp/source/rtp_packet.h"
namespace webrtc {
@@ -22,34 +32,59 @@ class RtpPacketToSend;
class RtcEventRtpPacketOutgoing final : public RtcEvent {
public:
+ static constexpr Type kType = Type::RtpPacketOutgoing;
+
RtcEventRtpPacketOutgoing(const RtpPacketToSend& packet,
int probe_cluster_id);
~RtcEventRtpPacketOutgoing() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return false; }
std::unique_ptr<RtcEventRtpPacketOutgoing> Copy() const;
- size_t packet_length() const {
- return payload_length_ + header_length_ + padding_length_;
+ size_t packet_length() const { return packet_.size(); }
+
+ rtc::ArrayView<const uint8_t> RawHeader() const {
+ return rtc::MakeArrayView(packet_.data(), header_length());
+ }
+ uint32_t Ssrc() const { return packet_.Ssrc(); }
+ uint32_t Timestamp() const { return packet_.Timestamp(); }
+ uint16_t SequenceNumber() const { return packet_.SequenceNumber(); }
+ uint8_t PayloadType() const { return packet_.PayloadType(); }
+ bool Marker() const { return packet_.Marker(); }
+ template <typename ExtensionTrait, typename... Args>
+ bool GetExtension(Args&&... args) const {
+ return packet_.GetExtension<ExtensionTrait>(std::forward<Args>(args)...);
+ }
+ template <typename ExtensionTrait>
+ bool HasExtension() const {
+ return packet_.HasExtension<ExtensionTrait>();
}
- const RtpPacket& header() const { return header_; }
- size_t payload_length() const { return payload_length_; }
- size_t header_length() const { return header_length_; }
- size_t padding_length() const { return padding_length_; }
+ size_t payload_length() const { return packet_.payload_size(); }
+ size_t header_length() const { return packet_.headers_size(); }
+ size_t padding_length() const { return packet_.padding_size(); }
int probe_cluster_id() const { return probe_cluster_id_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::map<uint32_t, std::vector<LoggedRtpPacketOutgoing>>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventRtpPacketOutgoing(const RtcEventRtpPacketOutgoing& other);
- RtpPacket header_; // Only the packet's header will be stored here.
- const size_t payload_length_; // Media payload, excluding header and padding.
- const size_t header_length_; // RTP header.
- const size_t padding_length_; // RTP padding.
- // TODO(eladalon): Delete |probe_cluster_id_| along with legacy encoding.
+ const RtpPacket packet_;
+ // TODO(eladalon): Delete `probe_cluster_id_` along with legacy encoding.
const int probe_cluster_id_;
};
diff --git a/logging/rtc_event_log/events/rtc_event_video_receive_stream_config.cc b/logging/rtc_event_log/events/rtc_event_video_receive_stream_config.cc
index 8942f8a642..90ab8185a3 100644
--- a/logging/rtc_event_log/events/rtc_event_video_receive_stream_config.cc
+++ b/logging/rtc_event_log/events/rtc_event_video_receive_stream_config.cc
@@ -30,14 +30,6 @@ RtcEventVideoReceiveStreamConfig::RtcEventVideoReceiveStreamConfig(
RtcEventVideoReceiveStreamConfig::~RtcEventVideoReceiveStreamConfig() = default;
-RtcEvent::Type RtcEventVideoReceiveStreamConfig::GetType() const {
- return Type::VideoReceiveStreamConfig;
-}
-
-bool RtcEventVideoReceiveStreamConfig::IsConfigEvent() const {
- return true;
-}
-
std::unique_ptr<RtcEventVideoReceiveStreamConfig>
RtcEventVideoReceiveStreamConfig::Copy() const {
return absl::WrapUnique<RtcEventVideoReceiveStreamConfig>(
diff --git a/logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h b/logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h
index fe5099d11b..0be56c2065 100644
--- a/logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h
+++ b/logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h
@@ -12,26 +12,58 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_VIDEO_RECEIVE_STREAM_CONFIG_H_
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
#include "logging/rtc_event_log/rtc_stream_config.h"
namespace webrtc {
+struct LoggedVideoRecvConfig {
+ LoggedVideoRecvConfig() = default;
+ LoggedVideoRecvConfig(Timestamp timestamp, const rtclog::StreamConfig config)
+ : timestamp(timestamp), config(config) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtclog::StreamConfig config;
+};
+
class RtcEventVideoReceiveStreamConfig final : public RtcEvent {
public:
+ static constexpr Type kType = Type::VideoReceiveStreamConfig;
+
explicit RtcEventVideoReceiveStreamConfig(
std::unique_ptr<rtclog::StreamConfig> config);
~RtcEventVideoReceiveStreamConfig() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return true; }
std::unique_ptr<RtcEventVideoReceiveStreamConfig> Copy() const;
const rtclog::StreamConfig& config() const { return *config_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedVideoRecvConfig>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventVideoReceiveStreamConfig(
const RtcEventVideoReceiveStreamConfig& other);
diff --git a/logging/rtc_event_log/events/rtc_event_video_send_stream_config.cc b/logging/rtc_event_log/events/rtc_event_video_send_stream_config.cc
index 2c33466ab2..c28a476d01 100644
--- a/logging/rtc_event_log/events/rtc_event_video_send_stream_config.cc
+++ b/logging/rtc_event_log/events/rtc_event_video_send_stream_config.cc
@@ -27,14 +27,6 @@ RtcEventVideoSendStreamConfig::RtcEventVideoSendStreamConfig(
RtcEventVideoSendStreamConfig::~RtcEventVideoSendStreamConfig() = default;
-RtcEvent::Type RtcEventVideoSendStreamConfig::GetType() const {
- return RtcEvent::Type::VideoSendStreamConfig;
-}
-
-bool RtcEventVideoSendStreamConfig::IsConfigEvent() const {
- return true;
-}
-
std::unique_ptr<RtcEventVideoSendStreamConfig>
RtcEventVideoSendStreamConfig::Copy() const {
return absl::WrapUnique<RtcEventVideoSendStreamConfig>(
diff --git a/logging/rtc_event_log/events/rtc_event_video_send_stream_config.h b/logging/rtc_event_log/events/rtc_event_video_send_stream_config.h
index 11dd148b95..f1717b19ea 100644
--- a/logging/rtc_event_log/events/rtc_event_video_send_stream_config.h
+++ b/logging/rtc_event_log/events/rtc_event_video_send_stream_config.h
@@ -12,26 +12,58 @@
#define LOGGING_RTC_EVENT_LOG_EVENTS_RTC_EVENT_VIDEO_SEND_STREAM_CONFIG_H_
#include <memory>
+#include <string>
+#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event.h"
+#include "api/units/timestamp.h"
+#include "logging/rtc_event_log/events/rtc_event_field_encoding_parser.h"
#include "logging/rtc_event_log/rtc_stream_config.h"
namespace webrtc {
+struct LoggedVideoSendConfig {
+ LoggedVideoSendConfig() = default;
+ LoggedVideoSendConfig(Timestamp timestamp, const rtclog::StreamConfig config)
+ : timestamp(timestamp), config(config) {}
+
+ int64_t log_time_us() const { return timestamp.us(); }
+ int64_t log_time_ms() const { return timestamp.ms(); }
+ Timestamp log_time() const { return timestamp; }
+
+ Timestamp timestamp = Timestamp::MinusInfinity();
+ rtclog::StreamConfig config;
+};
+
class RtcEventVideoSendStreamConfig final : public RtcEvent {
public:
+ static constexpr Type kType = Type::VideoSendStreamConfig;
+
explicit RtcEventVideoSendStreamConfig(
std::unique_ptr<rtclog::StreamConfig> config);
~RtcEventVideoSendStreamConfig() override;
- Type GetType() const override;
-
- bool IsConfigEvent() const override;
+ Type GetType() const override { return kType; }
+ bool IsConfigEvent() const override { return true; }
std::unique_ptr<RtcEventVideoSendStreamConfig> Copy() const;
const rtclog::StreamConfig& config() const { return *config_; }
+ static std::string Encode(rtc::ArrayView<const RtcEvent*> batch) {
+ // TODO(terelius): Implement
+ return "";
+ }
+
+ static RtcEventLogParseStatus Parse(
+ absl::string_view encoded_bytes,
+ bool batched,
+ std::vector<LoggedVideoSendConfig>& output) {
+ // TODO(terelius): Implement
+ return RtcEventLogParseStatus::Error("Not Implemented", __FILE__, __LINE__);
+ }
+
private:
RtcEventVideoSendStreamConfig(const RtcEventVideoSendStreamConfig& other);
diff --git a/logging/rtc_event_log/fake_rtc_event_log.cc b/logging/rtc_event_log/fake_rtc_event_log.cc
index 55f4b582c7..5a44b00694 100644
--- a/logging/rtc_event_log/fake_rtc_event_log.cc
+++ b/logging/rtc_event_log/fake_rtc_event_log.cc
@@ -10,32 +10,29 @@
#include "logging/rtc_event_log/fake_rtc_event_log.h"
-#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
-#include "rtc_base/bind.h"
-#include "rtc_base/checks.h"
-#include "rtc_base/logging.h"
+#include <map>
+#include <memory>
-namespace webrtc {
+#include "api/rtc_event_log/rtc_event_log.h"
+#include "rtc_base/synchronization/mutex.h"
-FakeRtcEventLog::FakeRtcEventLog(rtc::Thread* thread) : thread_(thread) {
- RTC_DCHECK(thread_);
-}
-FakeRtcEventLog::~FakeRtcEventLog() = default;
+namespace webrtc {
bool FakeRtcEventLog::StartLogging(std::unique_ptr<RtcEventLogOutput> output,
int64_t output_period_ms) {
return true;
}
-void FakeRtcEventLog::StopLogging() {
- invoker_.Flush(thread_);
-}
+void FakeRtcEventLog::StopLogging() {}
void FakeRtcEventLog::Log(std::unique_ptr<RtcEvent> event) {
- RtcEvent::Type rtc_event_type = event->GetType();
- invoker_.AsyncInvoke<void>(
- RTC_FROM_HERE, thread_,
- rtc::Bind(&FakeRtcEventLog::IncrementEventCount, this, rtc_event_type));
+ MutexLock lock(&mu_);
+ ++count_[event->GetType()];
+}
+
+int FakeRtcEventLog::GetEventCount(RtcEvent::Type event_type) {
+ MutexLock lock(&mu_);
+ return count_[event_type];
}
} // namespace webrtc
diff --git a/logging/rtc_event_log/fake_rtc_event_log.h b/logging/rtc_event_log/fake_rtc_event_log.h
index fb0e6ff4dc..effa7507f1 100644
--- a/logging/rtc_event_log/fake_rtc_event_log.h
+++ b/logging/rtc_event_log/fake_rtc_event_log.h
@@ -16,26 +16,25 @@
#include "api/rtc_event_log/rtc_event.h"
#include "api/rtc_event_log/rtc_event_log.h"
-#include "rtc_base/async_invoker.h"
-#include "rtc_base/thread.h"
+#include "rtc_base/synchronization/mutex.h"
+#include "rtc_base/thread_annotations.h"
namespace webrtc {
class FakeRtcEventLog : public RtcEventLog {
public:
- explicit FakeRtcEventLog(rtc::Thread* thread);
- ~FakeRtcEventLog() override;
+ FakeRtcEventLog() = default;
+ ~FakeRtcEventLog() override = default;
+
bool StartLogging(std::unique_ptr<RtcEventLogOutput> output,
int64_t output_period_ms) override;
void StopLogging() override;
void Log(std::unique_ptr<RtcEvent> event) override;
- int GetEventCount(RtcEvent::Type event_type) { return count_[event_type]; }
+ int GetEventCount(RtcEvent::Type event_type);
private:
- void IncrementEventCount(RtcEvent::Type event_type) { ++count_[event_type]; }
- std::map<RtcEvent::Type, int> count_;
- rtc::Thread* thread_;
- rtc::AsyncInvoker invoker_;
+ Mutex mu_;
+ std::map<RtcEvent::Type, int> count_ RTC_GUARDED_BY(mu_);
};
} // namespace webrtc
diff --git a/logging/rtc_event_log/fake_rtc_event_log_factory.cc b/logging/rtc_event_log/fake_rtc_event_log_factory.cc
index f84f74fdb6..47db40c9f4 100644
--- a/logging/rtc_event_log/fake_rtc_event_log_factory.cc
+++ b/logging/rtc_event_log/fake_rtc_event_log_factory.cc
@@ -10,16 +10,24 @@
#include "logging/rtc_event_log/fake_rtc_event_log_factory.h"
+#include <memory>
+
#include "api/rtc_event_log/rtc_event_log.h"
#include "logging/rtc_event_log/fake_rtc_event_log.h"
namespace webrtc {
+std::unique_ptr<RtcEventLog> FakeRtcEventLogFactory::Create(
+ RtcEventLog::EncodingType /*encoding_type*/) const {
+ auto fake_event_log = std::make_unique<FakeRtcEventLog>();
+ const_cast<FakeRtcEventLogFactory*>(this)->last_log_created_ =
+ fake_event_log.get();
+ return fake_event_log;
+}
+
std::unique_ptr<RtcEventLog> FakeRtcEventLogFactory::CreateRtcEventLog(
RtcEventLog::EncodingType encoding_type) {
- std::unique_ptr<RtcEventLog> fake_event_log(new FakeRtcEventLog(thread()));
- last_log_created_ = fake_event_log.get();
- return fake_event_log;
+ return Create(encoding_type);
}
} // namespace webrtc
diff --git a/logging/rtc_event_log/fake_rtc_event_log_factory.h b/logging/rtc_event_log/fake_rtc_event_log_factory.h
index 873e50efdc..c7ff33dee4 100644
--- a/logging/rtc_event_log/fake_rtc_event_log_factory.h
+++ b/logging/rtc_event_log/fake_rtc_event_log_factory.h
@@ -15,24 +15,24 @@
#include "api/rtc_event_log/rtc_event_log_factory_interface.h"
#include "logging/rtc_event_log/fake_rtc_event_log.h"
-#include "rtc_base/thread.h"
namespace webrtc {
class FakeRtcEventLogFactory : public RtcEventLogFactoryInterface {
public:
- explicit FakeRtcEventLogFactory(rtc::Thread* thread) : thread_(thread) {}
- ~FakeRtcEventLogFactory() override {}
+ FakeRtcEventLogFactory() = default;
+ ~FakeRtcEventLogFactory() override = default;
+
+ std::unique_ptr<RtcEventLog> Create(
+ RtcEventLog::EncodingType encoding_type) const override;
std::unique_ptr<RtcEventLog> CreateRtcEventLog(
RtcEventLog::EncodingType encoding_type) override;
- webrtc::RtcEventLog* last_log_created() { return last_log_created_; }
- rtc::Thread* thread() { return thread_; }
+ webrtc::FakeRtcEventLog* last_log_created() { return last_log_created_; }
private:
- webrtc::RtcEventLog* last_log_created_;
- rtc::Thread* thread_;
+ webrtc::FakeRtcEventLog* last_log_created_;
};
} // namespace webrtc
diff --git a/logging/rtc_event_log/logged_events.cc b/logging/rtc_event_log/logged_events.cc
deleted file mode 100644
index 3cba8bab21..0000000000
--- a/logging/rtc_event_log/logged_events.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright 2019 The WebRTC project authors. All Rights Reserved.
- *
- * Use of this source code is governed by a BSD-style license
- * that can be found in the LICENSE file in the root of the source
- * tree. An additional intellectual property rights grant can be found
- * in the file PATENTS. All contributing project authors may
- * be found in the AUTHORS file in the root of the source tree.
- */
-#include "logging/rtc_event_log/logged_events.h"
-
-namespace webrtc {
-
-LoggedPacketInfo::LoggedPacketInfo(const LoggedRtpPacket& rtp,
- LoggedMediaType media_type,
- bool rtx,
- Timestamp capture_time)
- : ssrc(rtp.header.ssrc),
- stream_seq_no(rtp.header.sequenceNumber),
- size(static_cast<uint16_t>(rtp.total_length)),
- payload_size(static_cast<uint16_t>(rtp.total_length -
- rtp.header.paddingLength -
- rtp.header.headerLength)),
- padding_size(static_cast<uint16_t>(rtp.header.paddingLength)),
- payload_type(rtp.header.payloadType),
- media_type(media_type),
- rtx(rtx),
- marker_bit(rtp.header.markerBit),
- has_transport_seq_no(rtp.header.extension.hasTransportSequenceNumber),
- transport_seq_no(static_cast<uint16_t>(
- has_transport_seq_no ? rtp.header.extension.transportSequenceNumber
- : 0)),
- capture_time(capture_time),
- log_packet_time(Timestamp::Micros(rtp.log_time_us())),
- reported_send_time(rtp.header.extension.hasAbsoluteSendTime
- ? rtp.header.extension.GetAbsoluteSendTimestamp()
- : Timestamp::MinusInfinity()) {}
-
-LoggedPacketInfo::LoggedPacketInfo(const LoggedPacketInfo&) = default;
-
-LoggedPacketInfo::~LoggedPacketInfo() {}
-
-LoggedRtcpPacket::LoggedRtcpPacket(int64_t timestamp_us,
- const uint8_t* packet,
- size_t total_length)
- : timestamp_us(timestamp_us), raw_data(packet, packet + total_length) {}
-LoggedRtcpPacket::LoggedRtcpPacket(int64_t timestamp_us,
- const std::string& packet)
- : timestamp_us(timestamp_us), raw_data(packet.size()) {
- memcpy(raw_data.data(), packet.data(), packet.size());
-}
-LoggedRtcpPacket::LoggedRtcpPacket(const LoggedRtcpPacket& rhs) = default;
-LoggedRtcpPacket::~LoggedRtcpPacket() = default;
-
-} // namespace webrtc
diff --git a/logging/rtc_event_log/logged_events.h b/logging/rtc_event_log/logged_events.h
index e13bba0c43..d6b3cc607e 100644
--- a/logging/rtc_event_log/logged_events.h
+++ b/logging/rtc_event_log/logged_events.h
@@ -7,653 +7,12 @@
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
+
#ifndef LOGGING_RTC_EVENT_LOG_LOGGED_EVENTS_H_
#define LOGGING_RTC_EVENT_LOG_LOGGED_EVENTS_H_
-#include <string>
-#include <vector>
-
-#include "absl/types/optional.h"
-#include "api/rtp_headers.h"
-#include "api/units/data_rate.h"
-#include "api/units/time_delta.h"
-#include "api/units/timestamp.h"
-#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
-#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
-#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
-#include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
-#include "logging/rtc_event_log/rtc_stream_config.h"
-#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/fir.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/loss_notification.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/pli.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/remb.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
-#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
-
-namespace webrtc {
-
-// The different event types are deliberately POD. Analysis of large logs is
-// already resource intensive. The code simplifications that would be possible
-// possible by having a base class (containing e.g. the log time) are not
-// considered to outweigh the added memory and runtime overhead incurred by
-// adding a vptr.
-struct LoggedAlrStateEvent {
- LoggedAlrStateEvent() = default;
- LoggedAlrStateEvent(int64_t timestamp_us, bool in_alr)
- : timestamp_us(timestamp_us), in_alr(in_alr) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- bool in_alr;
-};
-
-struct LoggedAudioPlayoutEvent {
- LoggedAudioPlayoutEvent() = default;
- LoggedAudioPlayoutEvent(int64_t timestamp_us, uint32_t ssrc)
- : timestamp_us(timestamp_us), ssrc(ssrc) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- uint32_t ssrc;
-};
-
-struct LoggedAudioNetworkAdaptationEvent {
- LoggedAudioNetworkAdaptationEvent() = default;
- LoggedAudioNetworkAdaptationEvent(int64_t timestamp_us,
- const AudioEncoderRuntimeConfig& config)
- : timestamp_us(timestamp_us), config(config) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- AudioEncoderRuntimeConfig config;
-};
-
-struct LoggedBweDelayBasedUpdate {
- LoggedBweDelayBasedUpdate() = default;
- LoggedBweDelayBasedUpdate(int64_t timestamp_us,
- int32_t bitrate_bps,
- BandwidthUsage detector_state)
- : timestamp_us(timestamp_us),
- bitrate_bps(bitrate_bps),
- detector_state(detector_state) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- int32_t bitrate_bps;
- BandwidthUsage detector_state;
-};
-
-struct LoggedBweLossBasedUpdate {
- LoggedBweLossBasedUpdate() = default;
- LoggedBweLossBasedUpdate(int64_t timestamp_us,
- int32_t bitrate_bps,
- uint8_t fraction_lost,
- int32_t expected_packets)
- : timestamp_us(timestamp_us),
- bitrate_bps(bitrate_bps),
- fraction_lost(fraction_lost),
- expected_packets(expected_packets) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- int32_t bitrate_bps;
- uint8_t fraction_lost;
- int32_t expected_packets;
-};
-
-struct LoggedDtlsTransportState {
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- DtlsTransportState dtls_transport_state;
-};
-
-struct LoggedDtlsWritableState {
- LoggedDtlsWritableState() = default;
- explicit LoggedDtlsWritableState(bool writable) : writable(writable) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- bool writable;
-};
-
-struct LoggedBweProbeClusterCreatedEvent {
- LoggedBweProbeClusterCreatedEvent() = default;
- LoggedBweProbeClusterCreatedEvent(int64_t timestamp_us,
- int32_t id,
- int32_t bitrate_bps,
- uint32_t min_packets,
- uint32_t min_bytes)
- : timestamp_us(timestamp_us),
- id(id),
- bitrate_bps(bitrate_bps),
- min_packets(min_packets),
- min_bytes(min_bytes) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- int32_t id;
- int32_t bitrate_bps;
- uint32_t min_packets;
- uint32_t min_bytes;
-};
-
-struct LoggedBweProbeSuccessEvent {
- LoggedBweProbeSuccessEvent() = default;
- LoggedBweProbeSuccessEvent(int64_t timestamp_us,
- int32_t id,
- int32_t bitrate_bps)
- : timestamp_us(timestamp_us), id(id), bitrate_bps(bitrate_bps) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- int32_t id;
- int32_t bitrate_bps;
-};
-
-struct LoggedBweProbeFailureEvent {
- LoggedBweProbeFailureEvent() = default;
- LoggedBweProbeFailureEvent(int64_t timestamp_us,
- int32_t id,
- ProbeFailureReason failure_reason)
- : timestamp_us(timestamp_us), id(id), failure_reason(failure_reason) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- int32_t id;
- ProbeFailureReason failure_reason;
-};
-
-struct LoggedIceCandidatePairConfig {
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- IceCandidatePairConfigType type;
- uint32_t candidate_pair_id;
- IceCandidateType local_candidate_type;
- IceCandidatePairProtocol local_relay_protocol;
- IceCandidateNetworkType local_network_type;
- IceCandidatePairAddressFamily local_address_family;
- IceCandidateType remote_candidate_type;
- IceCandidatePairAddressFamily remote_address_family;
- IceCandidatePairProtocol candidate_pair_protocol;
-};
-
-struct LoggedIceCandidatePairEvent {
- LoggedIceCandidatePairEvent() = default;
- LoggedIceCandidatePairEvent(int64_t timestamp_us,
- IceCandidatePairEventType type,
- uint32_t candidate_pair_id,
- uint32_t transaction_id)
- : timestamp_us(timestamp_us),
- type(type),
- candidate_pair_id(candidate_pair_id),
- transaction_id(transaction_id) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- IceCandidatePairEventType type;
- uint32_t candidate_pair_id;
- uint32_t transaction_id;
-};
-
-struct LoggedRouteChangeEvent {
- LoggedRouteChangeEvent() = default;
- LoggedRouteChangeEvent(int64_t timestamp_ms,
- bool connected,
- uint32_t overhead)
- : timestamp_ms(timestamp_ms), connected(connected), overhead(overhead) {}
-
- int64_t log_time_us() const { return timestamp_ms * 1000; }
- int64_t log_time_ms() const { return timestamp_ms; }
-
- int64_t timestamp_ms;
- bool connected;
- uint32_t overhead;
-};
-
-struct LoggedRemoteEstimateEvent {
- LoggedRemoteEstimateEvent() = default;
-
- int64_t log_time_us() const { return timestamp_ms * 1000; }
- int64_t log_time_ms() const { return timestamp_ms; }
-
- int64_t timestamp_ms;
- absl::optional<DataRate> link_capacity_lower;
- absl::optional<DataRate> link_capacity_upper;
-};
-
-struct LoggedRtpPacket {
- LoggedRtpPacket(int64_t timestamp_us,
- RTPHeader header,
- size_t header_length,
- size_t total_length)
- : timestamp_us(timestamp_us),
- header(header),
- header_length(header_length),
- total_length(total_length) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- // TODO(terelius): This allocates space for 15 CSRCs even if none are used.
- RTPHeader header;
- size_t header_length;
- size_t total_length;
-};
-
-struct LoggedRtpPacketIncoming {
- LoggedRtpPacketIncoming(int64_t timestamp_us,
- RTPHeader header,
- size_t header_length,
- size_t total_length)
- : rtp(timestamp_us, header, header_length, total_length) {}
- int64_t log_time_us() const { return rtp.timestamp_us; }
- int64_t log_time_ms() const { return rtp.timestamp_us / 1000; }
-
- LoggedRtpPacket rtp;
-};
-
-struct LoggedRtpPacketOutgoing {
- LoggedRtpPacketOutgoing(int64_t timestamp_us,
- RTPHeader header,
- size_t header_length,
- size_t total_length)
- : rtp(timestamp_us, header, header_length, total_length) {}
- int64_t log_time_us() const { return rtp.timestamp_us; }
- int64_t log_time_ms() const { return rtp.timestamp_us / 1000; }
-
- LoggedRtpPacket rtp;
-};
-
-struct LoggedRtcpPacket {
- LoggedRtcpPacket(int64_t timestamp_us,
- const uint8_t* packet,
- size_t total_length);
- LoggedRtcpPacket(int64_t timestamp_us, const std::string& packet);
- LoggedRtcpPacket(const LoggedRtcpPacket&);
- ~LoggedRtcpPacket();
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- std::vector<uint8_t> raw_data;
-};
-
-struct LoggedRtcpPacketIncoming {
- LoggedRtcpPacketIncoming(int64_t timestamp_us,
- const uint8_t* packet,
- size_t total_length)
- : rtcp(timestamp_us, packet, total_length) {}
- LoggedRtcpPacketIncoming(uint64_t timestamp_us, const std::string& packet)
- : rtcp(timestamp_us, packet) {}
-
- int64_t log_time_us() const { return rtcp.timestamp_us; }
- int64_t log_time_ms() const { return rtcp.timestamp_us / 1000; }
-
- LoggedRtcpPacket rtcp;
-};
-
-struct LoggedRtcpPacketOutgoing {
- LoggedRtcpPacketOutgoing(int64_t timestamp_us,
- const uint8_t* packet,
- size_t total_length)
- : rtcp(timestamp_us, packet, total_length) {}
- LoggedRtcpPacketOutgoing(uint64_t timestamp_us, const std::string& packet)
- : rtcp(timestamp_us, packet) {}
-
- int64_t log_time_us() const { return rtcp.timestamp_us; }
- int64_t log_time_ms() const { return rtcp.timestamp_us / 1000; }
-
- LoggedRtcpPacket rtcp;
-};
-
-struct LoggedRtcpPacketReceiverReport {
- LoggedRtcpPacketReceiverReport() = default;
- LoggedRtcpPacketReceiverReport(int64_t timestamp_us,
- const rtcp::ReceiverReport& rr)
- : timestamp_us(timestamp_us), rr(rr) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtcp::ReceiverReport rr;
-};
-
-struct LoggedRtcpPacketSenderReport {
- LoggedRtcpPacketSenderReport() = default;
- LoggedRtcpPacketSenderReport(int64_t timestamp_us,
- const rtcp::SenderReport& sr)
- : timestamp_us(timestamp_us), sr(sr) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtcp::SenderReport sr;
-};
-
-struct LoggedRtcpPacketExtendedReports {
- LoggedRtcpPacketExtendedReports() = default;
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtcp::ExtendedReports xr;
-};
-
-struct LoggedRtcpPacketRemb {
- LoggedRtcpPacketRemb() = default;
- LoggedRtcpPacketRemb(int64_t timestamp_us, const rtcp::Remb& remb)
- : timestamp_us(timestamp_us), remb(remb) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtcp::Remb remb;
-};
-
-struct LoggedRtcpPacketNack {
- LoggedRtcpPacketNack() = default;
- LoggedRtcpPacketNack(int64_t timestamp_us, const rtcp::Nack& nack)
- : timestamp_us(timestamp_us), nack(nack) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtcp::Nack nack;
-};
-
-struct LoggedRtcpPacketFir {
- LoggedRtcpPacketFir() = default;
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtcp::Fir fir;
-};
-
-struct LoggedRtcpPacketPli {
- LoggedRtcpPacketPli() = default;
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtcp::Pli pli;
-};
-
-struct LoggedRtcpPacketTransportFeedback {
- LoggedRtcpPacketTransportFeedback()
- : transport_feedback(/*include_timestamps=*/true, /*include_lost*/ true) {
- }
- LoggedRtcpPacketTransportFeedback(
- int64_t timestamp_us,
- const rtcp::TransportFeedback& transport_feedback)
- : timestamp_us(timestamp_us), transport_feedback(transport_feedback) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtcp::TransportFeedback transport_feedback;
-};
-
-struct LoggedRtcpPacketLossNotification {
- LoggedRtcpPacketLossNotification() = default;
- LoggedRtcpPacketLossNotification(
- int64_t timestamp_us,
- const rtcp::LossNotification& loss_notification)
- : timestamp_us(timestamp_us), loss_notification(loss_notification) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtcp::LossNotification loss_notification;
-};
-
-struct LoggedStartEvent {
- explicit LoggedStartEvent(int64_t timestamp_us)
- : LoggedStartEvent(timestamp_us, timestamp_us / 1000) {}
-
- LoggedStartEvent(int64_t timestamp_us, int64_t utc_start_time_ms)
- : timestamp_us(timestamp_us), utc_start_time_ms(utc_start_time_ms) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- int64_t utc_start_time_ms;
-};
-
-struct LoggedStopEvent {
- explicit LoggedStopEvent(int64_t timestamp_us) : timestamp_us(timestamp_us) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
-};
-
-struct LoggedAudioRecvConfig {
- LoggedAudioRecvConfig() = default;
- LoggedAudioRecvConfig(int64_t timestamp_us, const rtclog::StreamConfig config)
- : timestamp_us(timestamp_us), config(config) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtclog::StreamConfig config;
-};
-
-struct LoggedAudioSendConfig {
- LoggedAudioSendConfig() = default;
- LoggedAudioSendConfig(int64_t timestamp_us, const rtclog::StreamConfig config)
- : timestamp_us(timestamp_us), config(config) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtclog::StreamConfig config;
-};
-
-struct LoggedVideoRecvConfig {
- LoggedVideoRecvConfig() = default;
- LoggedVideoRecvConfig(int64_t timestamp_us, const rtclog::StreamConfig config)
- : timestamp_us(timestamp_us), config(config) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtclog::StreamConfig config;
-};
-
-struct LoggedVideoSendConfig {
- LoggedVideoSendConfig() = default;
- LoggedVideoSendConfig(int64_t timestamp_us, const rtclog::StreamConfig config)
- : timestamp_us(timestamp_us), config(config) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- rtclog::StreamConfig config;
-};
-
-struct InferredRouteChangeEvent {
- int64_t log_time_ms() const { return log_time.ms(); }
- int64_t log_time_us() const { return log_time.us(); }
- uint32_t route_id;
- Timestamp log_time = Timestamp::MinusInfinity();
- uint16_t send_overhead;
- uint16_t return_overhead;
-};
-
-enum class LoggedMediaType : uint8_t { kUnknown, kAudio, kVideo };
-
-struct LoggedPacketInfo {
- LoggedPacketInfo(const LoggedRtpPacket& rtp,
- LoggedMediaType media_type,
- bool rtx,
- Timestamp capture_time);
- LoggedPacketInfo(const LoggedPacketInfo&);
- ~LoggedPacketInfo();
- int64_t log_time_ms() const { return log_packet_time.ms(); }
- int64_t log_time_us() const { return log_packet_time.us(); }
- uint32_t ssrc;
- uint16_t stream_seq_no;
- uint16_t size;
- uint16_t payload_size;
- uint16_t padding_size;
- uint16_t overhead = 0;
- uint8_t payload_type;
- LoggedMediaType media_type = LoggedMediaType::kUnknown;
- bool rtx = false;
- bool marker_bit = false;
- bool has_transport_seq_no = false;
- bool last_in_feedback = false;
- uint16_t transport_seq_no = 0;
- // The RTP header timestamp unwrapped and converted from tick count to seconds
- // based timestamp.
- Timestamp capture_time;
- // The time the packet was logged. This is the receive time for incoming
- // packets and send time for outgoing.
- Timestamp log_packet_time;
- // Send time as reported by abs-send-time extension, For outgoing packets this
- // corresponds to log_packet_time, but might be measured using another clock.
- Timestamp reported_send_time;
- // The receive time that was reported in feedback. For incoming packets this
- // corresponds to log_packet_time, but might be measured using another clock.
- // PlusInfinity indicates that the packet was lost.
- Timestamp reported_recv_time = Timestamp::MinusInfinity();
- // The time feedback message was logged. This is the feedback send time for
- // incoming packets and feedback receive time for outgoing.
- // PlusInfinity indicates that feedback was expected but not received.
- Timestamp log_feedback_time = Timestamp::MinusInfinity();
- // The delay betweeen receiving an RTP packet and sending feedback for
- // incoming packets. For outgoing packets we don't know the feedback send
- // time, and this is instead calculated as the difference in reported receive
- // time between this packet and the last packet in the same feedback message.
- TimeDelta feedback_hold_duration = TimeDelta::MinusInfinity();
-};
-
-enum class LoggedIceEventType {
- kAdded,
- kUpdated,
- kDestroyed,
- kSelected,
- kCheckSent,
- kCheckReceived,
- kCheckResponseSent,
- kCheckResponseReceived,
-};
-
-struct LoggedIceEvent {
- uint32_t candidate_pair_id;
- Timestamp log_time;
- LoggedIceEventType event_type;
-};
-
-struct LoggedGenericPacketSent {
- LoggedGenericPacketSent() = default;
- LoggedGenericPacketSent(int64_t timestamp_us,
- int64_t packet_number,
- size_t overhead_length,
- size_t payload_length,
- size_t padding_length)
- : timestamp_us(timestamp_us),
- packet_number(packet_number),
- overhead_length(overhead_length),
- payload_length(payload_length),
- padding_length(padding_length) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- size_t packet_length() const {
- return payload_length + padding_length + overhead_length;
- }
- int64_t timestamp_us;
- int64_t packet_number;
- size_t overhead_length;
- size_t payload_length;
- size_t padding_length;
-};
-
-struct LoggedGenericPacketReceived {
- LoggedGenericPacketReceived() = default;
- LoggedGenericPacketReceived(int64_t timestamp_us,
- int64_t packet_number,
- int packet_length)
- : timestamp_us(timestamp_us),
- packet_number(packet_number),
- packet_length(packet_length) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- int64_t packet_number;
- int packet_length;
-};
-
-struct LoggedGenericAckReceived {
- LoggedGenericAckReceived() = default;
- LoggedGenericAckReceived(int64_t timestamp_us,
- int64_t packet_number,
- int64_t acked_packet_number,
- absl::optional<int64_t> receive_acked_packet_time_ms)
- : timestamp_us(timestamp_us),
- packet_number(packet_number),
- acked_packet_number(acked_packet_number),
- receive_acked_packet_time_ms(receive_acked_packet_time_ms) {}
-
- int64_t log_time_us() const { return timestamp_us; }
- int64_t log_time_ms() const { return timestamp_us / 1000; }
-
- int64_t timestamp_us;
- int64_t packet_number;
- int64_t acked_packet_number;
- absl::optional<int64_t> receive_acked_packet_time_ms;
-};
+// TODO(terelius): Delete this forwarding header when downstream
+// projects have been updated.
+#include "logging/rtc_event_log/events/logged_rtp_rtcp.h"
-} // namespace webrtc
#endif // LOGGING_RTC_EVENT_LOG_LOGGED_EVENTS_H_
diff --git a/logging/rtc_event_log/rtc_event_log.proto b/logging/rtc_event_log/rtc_event_log.proto
index 94e288e024..12baa493bd 100644
--- a/logging/rtc_event_log/rtc_event_log.proto
+++ b/logging/rtc_event_log/rtc_event_log.proto
@@ -43,6 +43,7 @@ message Event {
ALR_STATE_EVENT = 19;
ICE_CANDIDATE_PAIR_CONFIG = 20;
ICE_CANDIDATE_PAIR_EVENT = 21;
+ REMOTE_ESTIMATE = 22;
}
// required - Indicates the type of this event
@@ -93,6 +94,9 @@ message Event {
// required if type == ICE_CANDIDATE_PAIR_EVENT
IceCandidatePairEvent ice_candidate_pair_event = 21;
+
+ // required if type == REMOTE_ESTIMATE
+ RemoteEstimate remote_estimate = 22;
}
}
@@ -327,6 +331,14 @@ message BweProbeResult {
optional int32 bitrate_bps = 3;
}
+message RemoteEstimate {
+ // optional - Lower estimate of link capacity.
+ optional uint32 link_capacity_lower_kbps = 1;
+
+ // optional - Upper estimate of link capacity.
+ optional uint32 link_capacity_upper_kbps = 2;
+}
+
message AlrState {
// required - If we are in ALR or not.
optional bool in_alr = 1;
diff --git a/logging/rtc_event_log/rtc_event_log2.proto b/logging/rtc_event_log/rtc_event_log2.proto
index 0cdb2a43c7..a541533dcc 100644
--- a/logging/rtc_event_log/rtc_event_log2.proto
+++ b/logging/rtc_event_log/rtc_event_log2.proto
@@ -20,7 +20,8 @@ message EventStream {
repeated IncomingRtcpPackets incoming_rtcp_packets = 4;
repeated OutgoingRtcpPackets outgoing_rtcp_packets = 5;
repeated AudioPlayoutEvents audio_playout_events = 6;
- // The field tags 7-15 are reserved for the most common events.
+ repeated FrameDecodedEvents frame_decoded_events = 7;
+ // The field tags 8-15 are reserved for the most common events.
repeated BeginLogEvent begin_log_events = 16;
repeated EndLogEvent end_log_events = 17;
repeated LossBasedBweUpdates loss_based_bwe_updates = 18;
@@ -143,7 +144,7 @@ message IncomingRtpPackets {
optional int32 transmission_time_offset = 16;
optional uint32 absolute_send_time = 17;
optional uint32 video_rotation = 18;
- // |audio_level| and |voice_activity| are always used in conjunction.
+ // `audio_level` and `voice_activity` are always used in conjunction.
optional uint32 audio_level = 19;
optional bool voice_activity = 20;
// TODO(terelius): Add other header extensions like playout delay?
@@ -164,7 +165,7 @@ message IncomingRtpPackets {
optional bytes transmission_time_offset_deltas = 116;
optional bytes absolute_send_time_deltas = 117;
optional bytes video_rotation_deltas = 118;
- // |audio_level| and |voice_activity| are always used in conjunction.
+ // `audio_level` and `voice_activity` are always used in conjunction.
optional bytes audio_level_deltas = 119;
optional bytes voice_activity_deltas = 120;
}
@@ -211,7 +212,7 @@ message OutgoingRtpPackets {
optional int32 transmission_time_offset = 16;
optional uint32 absolute_send_time = 17;
optional uint32 video_rotation = 18;
- // |audio_level| and |voice_activity| are always used in conjunction.
+ // `audio_level` and `voice_activity` are always used in conjunction.
optional uint32 audio_level = 19;
optional bool voice_activity = 20;
// TODO(terelius): Add other header extensions like playout delay?
@@ -232,7 +233,7 @@ message OutgoingRtpPackets {
optional bytes transmission_time_offset_deltas = 116;
optional bytes absolute_send_time_deltas = 117;
optional bytes video_rotation_deltas = 118;
- // |audio_level| and |voice_activity| are always used in conjunction.
+ // `audio_level` and `voice_activity` are always used in conjunction.
optional bytes audio_level_deltas = 119;
optional bytes voice_activity_deltas = 120;
}
@@ -284,6 +285,50 @@ message AudioPlayoutEvents {
optional bytes local_ssrc_deltas = 102;
}
+message FrameDecodedEvents {
+ enum Codec {
+ CODEC_UNKNOWN = 0;
+ CODEC_GENERIC = 1;
+ CODEC_VP8 = 2;
+ CODEC_VP9 = 3;
+ CODEC_AV1 = 4;
+ CODEC_H264 = 5;
+ }
+
+ // required
+ optional int64 timestamp_ms = 1;
+
+ // required - The SSRC of the video stream that the frame belongs to.
+ optional fixed32 ssrc = 2;
+
+ // required - The predicted render time of the frame.
+ optional int64 render_time_ms = 3;
+
+ // required - The width (in pixels) of the frame.
+ optional int32 width = 4;
+
+ // required - The height (in pixels) of the frame.
+ optional int32 height = 5;
+
+ // required - The codec type of the frame.
+ optional Codec codec = 6;
+
+ // required - The QP (quantization parameter) of the frame. Range [0,255].
+ optional uint32 qp = 7;
+
+ // optional - required if the batch contains delta encoded events.
+ optional uint32 number_of_deltas = 15;
+
+ // Delta encodings.
+ optional bytes timestamp_ms_deltas = 101;
+ optional bytes ssrc_deltas = 102;
+ optional bytes render_time_ms_deltas = 103;
+ optional bytes width_deltas = 104;
+ optional bytes height_deltas = 105;
+ optional bytes codec_deltas = 106;
+ optional bytes qp_deltas = 107;
+}
+
message BeginLogEvent {
// required
optional int64 timestamp_ms = 1;
diff --git a/logging/rtc_event_log/rtc_event_log2rtp_dump.cc b/logging/rtc_event_log/rtc_event_log2rtp_dump.cc
index c9d4a6ca88..a0514259aa 100644
--- a/logging/rtc_event_log/rtc_event_log2rtp_dump.cc
+++ b/logging/rtc_event_log/rtc_event_log2rtp_dump.cc
@@ -21,6 +21,7 @@
#include "absl/flags/parse.h"
#include "absl/flags/usage.h"
#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "api/rtc_event_log/rtc_event_log.h"
@@ -70,12 +71,12 @@ namespace {
using MediaType = webrtc::ParsedRtcEventLog::MediaType;
// Parses the input string for a valid SSRC. If a valid SSRC is found, it is
-// written to the output variable |ssrc|, and true is returned. Otherwise,
+// written to the output variable `ssrc`, and true is returned. Otherwise,
// false is returned.
// The empty string must be validated as true, because it is the default value
// of the command-line flag. In this case, no value is written to the output
// variable.
-absl::optional<uint32_t> ParseSsrc(std::string str) {
+absl::optional<uint32_t> ParseSsrc(absl::string_view str) {
// If the input string starts with 0x or 0X it indicates a hexadecimal number.
uint32_t ssrc;
auto read_mode = std::dec;
@@ -84,7 +85,7 @@ absl::optional<uint32_t> ParseSsrc(std::string str) {
read_mode = std::hex;
str = str.substr(2);
}
- std::stringstream ss(str);
+ std::stringstream ss(std::string{str});
ss >> read_mode >> ssrc;
if (str.empty() || (!ss.fail() && ss.eof()))
return ssrc;
@@ -240,7 +241,7 @@ int main(int argc, char* argv[]) {
continue;
event_processor.AddEvents(stream.incoming_packets, handle_rtp);
}
- // Note that |packet_ssrc| is the sender SSRC. An RTCP message may contain
+ // Note that `packet_ssrc` is the sender SSRC. An RTCP message may contain
// report blocks for many streams, thus several SSRCs and they don't
// necessarily have to be of the same media type. We therefore don't
// support filtering of RTCP based on SSRC and media type.
diff --git a/logging/rtc_event_log/rtc_event_log_impl.cc b/logging/rtc_event_log/rtc_event_log_impl.cc
index 4a272f08cf..a48bbdeb8e 100644
--- a/logging/rtc_event_log/rtc_event_log_impl.cc
+++ b/logging/rtc_event_log/rtc_event_log_impl.cc
@@ -16,13 +16,13 @@
#include <utility>
#include <vector>
+#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
-#include "api/task_queue/queued_task.h"
#include "api/task_queue/task_queue_base.h"
+#include "api/units/time_delta.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h"
#include "rtc_base/checks.h"
-#include "rtc_base/constructor_magic.h"
#include "rtc_base/event.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
@@ -40,15 +40,15 @@ std::unique_ptr<RtcEventLogEncoder> CreateEncoder(
RtcEventLog::EncodingType type) {
switch (type) {
case RtcEventLog::EncodingType::Legacy:
- RTC_LOG(LS_INFO) << "Creating legacy encoder for RTC event log.";
+ RTC_DLOG(LS_INFO) << "Creating legacy encoder for RTC event log.";
return std::make_unique<RtcEventLogEncoderLegacy>();
case RtcEventLog::EncodingType::NewFormat:
- RTC_LOG(LS_INFO) << "Creating new format encoder for RTC event log.";
+ RTC_DLOG(LS_INFO) << "Creating new format encoder for RTC event log.";
return std::make_unique<RtcEventLogEncoderNewFormat>();
default:
RTC_LOG(LS_ERROR) << "Unknown RtcEventLog encoder type (" << int(type)
<< ")";
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return std::unique_ptr<RtcEventLogEncoder>(nullptr);
}
}
@@ -90,15 +90,14 @@ bool RtcEventLogImpl::StartLogging(std::unique_ptr<RtcEventLogOutput> output,
return false;
}
- const int64_t timestamp_us = rtc::TimeMicros();
- const int64_t utc_time_us = rtc::TimeUTCMicros();
- RTC_LOG(LS_INFO) << "Starting WebRTC event log. (Timestamp, UTC) = "
- "("
+ const int64_t timestamp_us = rtc::TimeMillis() * 1000;
+ const int64_t utc_time_us = rtc::TimeUTCMillis() * 1000;
+ RTC_LOG(LS_INFO) << "Starting WebRTC event log. (Timestamp, UTC) = ("
<< timestamp_us << ", " << utc_time_us << ").";
RTC_DCHECK_RUN_ON(&logging_state_checker_);
logging_state_started_ = true;
- // Binding to |this| is safe because |this| outlives the |task_queue_|.
+ // Binding to `this` is safe because `this` outlives the `task_queue_`.
task_queue_->PostTask([this, output_period_ms, timestamp_us, utc_time_us,
output = std::move(output)]() mutable {
RTC_DCHECK_RUN_ON(task_queue_.get());
@@ -114,15 +113,15 @@ bool RtcEventLogImpl::StartLogging(std::unique_ptr<RtcEventLogOutput> output,
}
void RtcEventLogImpl::StopLogging() {
- RTC_LOG(LS_INFO) << "Stopping WebRTC event log.";
+ RTC_DLOG(LS_INFO) << "Stopping WebRTC event log.";
// TODO(danilchap): Do not block current thread waiting on the task queue.
// It might work for now, for current callers, but disallows caller to share
- // threads with the |task_queue_|.
+ // threads with the `task_queue_`.
rtc::Event output_stopped;
StopLogging([&output_stopped]() { output_stopped.Set(); });
output_stopped.Wait(rtc::Event::kForever);
- RTC_LOG(LS_INFO) << "WebRTC event log successfully stopped.";
+ RTC_DLOG(LS_INFO) << "WebRTC event log successfully stopped.";
}
void RtcEventLogImpl::StopLogging(std::function<void()> callback) {
@@ -142,7 +141,7 @@ void RtcEventLogImpl::StopLogging(std::function<void()> callback) {
void RtcEventLogImpl::Log(std::unique_ptr<RtcEvent> event) {
RTC_CHECK(event);
- // Binding to |this| is safe because |this| outlives the |task_queue_|.
+ // Binding to `this` is safe because `this` outlives the `task_queue_`.
task_queue_->PostTask([this, event = std::move(event)]() mutable {
RTC_DCHECK_RUN_ON(task_queue_.get());
LogToMemory(std::move(event));
@@ -162,7 +161,7 @@ void RtcEventLogImpl::ScheduleOutput() {
RTC_DCHECK(output_period_ms_.has_value());
if (*output_period_ms_ == kImmediateOutput) {
- // We are already on the |task_queue_| so there is no reason to post a task
+ // We are already on the `task_queue_` so there is no reason to post a task
// if we want to output immediately.
LogEventsFromMemoryToOutput();
return;
@@ -170,7 +169,7 @@ void RtcEventLogImpl::ScheduleOutput() {
if (!output_scheduled_) {
output_scheduled_ = true;
- // Binding to |this| is safe because |this| outlives the |task_queue_|.
+ // Binding to `this` is safe because `this` outlives the `task_queue_`.
auto output_task = [this]() {
RTC_DCHECK_RUN_ON(task_queue_.get());
if (event_output_) {
@@ -183,7 +182,8 @@ void RtcEventLogImpl::ScheduleOutput() {
const int64_t time_since_output_ms = now_ms - last_output_ms_;
const uint32_t delay = rtc::SafeClamp(
*output_period_ms_ - time_since_output_ms, 0, *output_period_ms_);
- task_queue_->PostDelayedTask(output_task, delay);
+ task_queue_->PostDelayedTask(std::move(output_task),
+ TimeDelta::Millis(delay));
}
}
@@ -205,7 +205,7 @@ void RtcEventLogImpl::LogEventsFromMemoryToOutput() {
last_output_ms_ = rtc::TimeMillis();
// Serialize all stream configurations that haven't already been written to
- // this output. |num_config_events_written_| is used to track which configs we
+ // this output. `num_config_events_written_` is used to track which configs we
// have already written. (Note that the config may have been written to
// previous outputs; configs are not discarded.)
std::string encoded_configs;
@@ -232,8 +232,8 @@ void RtcEventLogImpl::LogEventsFromMemoryToOutput() {
}
void RtcEventLogImpl::WriteConfigsAndHistoryToOutput(
- const std::string& encoded_configs,
- const std::string& encoded_history) {
+ absl::string_view encoded_configs,
+ absl::string_view encoded_history) {
// This function is used to merge the strings instead of calling the output
// object twice with small strings. The function also avoids copying any
// strings in the typical case where there are no config events.
@@ -242,7 +242,11 @@ void RtcEventLogImpl::WriteConfigsAndHistoryToOutput(
} else if (encoded_history.empty()) {
WriteToOutput(encoded_configs); // Very unusual case.
} else {
- WriteToOutput(encoded_configs + encoded_history);
+ std::string s;
+ s.reserve(encoded_configs.size() + encoded_history.size());
+ s.append(encoded_configs.data(), encoded_configs.size());
+ s.append(encoded_history.data(), encoded_history.size());
+ WriteToOutput(s);
}
}
@@ -253,13 +257,13 @@ void RtcEventLogImpl::StopOutput() {
void RtcEventLogImpl::StopLoggingInternal() {
if (event_output_) {
RTC_DCHECK(event_output_->IsActive());
- const int64_t timestamp_us = rtc::TimeMicros();
+ const int64_t timestamp_us = rtc::TimeMillis() * 1000;
event_output_->Write(event_encoder_->EncodeLogEnd(timestamp_us));
}
StopOutput();
}
-void RtcEventLogImpl::WriteToOutput(const std::string& output_string) {
+void RtcEventLogImpl::WriteToOutput(absl::string_view output_string) {
RTC_DCHECK(event_output_ && event_output_->IsActive());
if (!event_output_->Write(output_string)) {
RTC_LOG(LS_ERROR) << "Failed to write RTC event to output.";
diff --git a/logging/rtc_event_log/rtc_event_log_impl.h b/logging/rtc_event_log/rtc_event_log_impl.h
index 9c7aae669d..6c6417254e 100644
--- a/logging/rtc_event_log/rtc_event_log_impl.h
+++ b/logging/rtc_event_log/rtc_event_log_impl.h
@@ -17,13 +17,15 @@
#include <memory>
#include <string>
+#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/rtc_event_log/rtc_event.h"
#include "api/rtc_event_log/rtc_event_log.h"
#include "api/rtc_event_log_output.h"
+#include "api/sequence_checker.h"
#include "api/task_queue/task_queue_factory.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder.h"
-#include "rtc_base/synchronization/sequence_checker.h"
+#include "rtc_base/system/no_unique_address.h"
#include "rtc_base/task_queue.h"
#include "rtc_base/thread_annotations.h"
@@ -53,10 +55,10 @@ class RtcEventLogImpl final : public RtcEventLog {
void StopOutput() RTC_RUN_ON(task_queue_);
- void WriteConfigsAndHistoryToOutput(const std::string& encoded_configs,
- const std::string& encoded_history)
+ void WriteConfigsAndHistoryToOutput(absl::string_view encoded_configs,
+ absl::string_view encoded_history)
RTC_RUN_ON(task_queue_);
- void WriteToOutput(const std::string& output_string) RTC_RUN_ON(task_queue_);
+ void WriteToOutput(absl::string_view output_string) RTC_RUN_ON(task_queue_);
void StopLoggingInternal() RTC_RUN_ON(task_queue_);
@@ -78,11 +80,11 @@ class RtcEventLogImpl final : public RtcEventLog {
int64_t last_output_ms_ RTC_GUARDED_BY(*task_queue_);
bool output_scheduled_ RTC_GUARDED_BY(*task_queue_);
- SequenceChecker logging_state_checker_;
+ RTC_NO_UNIQUE_ADDRESS SequenceChecker logging_state_checker_;
bool logging_state_started_ RTC_GUARDED_BY(logging_state_checker_);
- // Since we are posting tasks bound to |this|, it is critical that the event
- // log and its members outlive |task_queue_|. Keep the |task_queue_|
+ // Since we are posting tasks bound to `this`, it is critical that the event
+ // log and its members outlive `task_queue_`. Keep the `task_queue_`
// last to ensure it destructs first, or else tasks living on the queue might
// access other members after they've been torn down.
std::unique_ptr<rtc::TaskQueue> task_queue_;
diff --git a/logging/rtc_event_log/rtc_event_log_parser.cc b/logging/rtc_event_log/rtc_event_log_parser.cc
index c88207607c..7e471ddd0f 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.cc
+++ b/logging/rtc_event_log/rtc_event_log_parser.cc
@@ -14,35 +14,37 @@
#include <string.h>
#include <algorithm>
-#include <fstream>
-#include <istream> // no-presubmit-check TODO(webrtc:8982)
#include <limits>
#include <map>
#include <utility>
#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
+#include "api/network_state_predictor.h"
#include "api/rtc_event_log/rtc_event_log.h"
#include "api/rtp_headers.h"
#include "api/rtp_parameters.h"
#include "logging/rtc_event_log/encoder/blob_encoding.h"
#include "logging/rtc_event_log/encoder/delta_encoding.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_common.h"
+#include "logging/rtc_event_log/encoder/var_int.h"
+#include "logging/rtc_event_log/events/logged_rtp_rtcp.h"
#include "logging/rtc_event_log/rtc_event_processor.h"
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor.h"
-#include "modules/include/module_common_types.h"
#include "modules/include/module_common_types_public.h"
-#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/rtp_rtcp/include/rtp_cvo.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/byte_io.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
-#include "modules/rtp_rtcp/source/rtp_utility.h"
+#include "modules/rtp_rtcp/source/rtp_packet_received.h"
#include "rtc_base/checks.h"
+#include "rtc_base/copy_on_write_buffer.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/numerics/sequence_number_util.h"
#include "rtc_base/protobuf_utils.h"
+#include "rtc_base/system/file_wrapper.h"
// These macros were added to convert existing code using RTC_CHECKs
// to returning a Status object instead. Macros are necessary (over
@@ -54,6 +56,12 @@
return ParsedRtcEventLog::ParseStatus::Error(#X, __FILE__, __LINE__); \
} while (0)
+#define RTC_PARSE_CHECK_OR_RETURN_MESSAGE(X, M) \
+ do { \
+ if (!(X)) \
+ return ParsedRtcEventLog::ParseStatus::Error((M), __FILE__, __LINE__); \
+ } while (0)
+
#define RTC_PARSE_CHECK_OR_RETURN_OP(OP, X, Y) \
do { \
if (!((X)OP(Y))) \
@@ -99,6 +107,8 @@ using webrtc_event_logging::ToUnsigned;
namespace webrtc {
namespace {
+constexpr int64_t kMaxLogSize = 250000000;
+
constexpr size_t kIpv4Overhead = 20;
constexpr size_t kIpv6Overhead = 40;
constexpr size_t kUdpOverhead = 8;
@@ -173,7 +183,7 @@ RtcpMode GetRuntimeRtcpMode(rtclog::VideoReceiveConfig::RtcpMode rtcp_mode) {
case rtclog::VideoReceiveConfig::RTCP_REDUCEDSIZE:
return RtcpMode::kReducedSize;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return RtcpMode::kOff;
}
@@ -187,7 +197,7 @@ BandwidthUsage GetRuntimeDetectorState(
case rtclog::DelayBasedBweUpdate::BWE_OVERUSING:
return BandwidthUsage::kBwOverusing;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return BandwidthUsage::kBwNormal;
}
@@ -203,7 +213,7 @@ IceCandidatePairConfigType GetRuntimeIceCandidatePairConfigType(
case rtclog::IceCandidatePairConfig::SELECTED:
return IceCandidatePairConfigType::kSelected;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return IceCandidatePairConfigType::kAdded;
}
@@ -221,7 +231,7 @@ IceCandidateType GetRuntimeIceCandidateType(
case rtclog::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE:
return IceCandidateType::kUnknown;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return IceCandidateType::kUnknown;
}
@@ -239,7 +249,7 @@ IceCandidatePairProtocol GetRuntimeIceCandidatePairProtocol(
case rtclog::IceCandidatePairConfig::UNKNOWN_PROTOCOL:
return IceCandidatePairProtocol::kUnknown;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return IceCandidatePairProtocol::kUnknown;
}
@@ -253,7 +263,7 @@ IceCandidatePairAddressFamily GetRuntimeIceCandidatePairAddressFamily(
case rtclog::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY:
return IceCandidatePairAddressFamily::kUnknown;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return IceCandidatePairAddressFamily::kUnknown;
}
@@ -273,7 +283,7 @@ IceCandidateNetworkType GetRuntimeIceCandidateNetworkType(
case rtclog::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE:
return IceCandidateNetworkType::kUnknown;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return IceCandidateNetworkType::kUnknown;
}
@@ -289,35 +299,29 @@ IceCandidatePairEventType GetRuntimeIceCandidatePairEventType(
case rtclog::IceCandidatePairEvent::CHECK_RESPONSE_RECEIVED:
return IceCandidatePairEventType::kCheckResponseReceived;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return IceCandidatePairEventType::kCheckSent;
}
-// Reads a VarInt from |stream| and returns it. Also writes the read bytes to
-// |buffer| starting |bytes_written| bytes into the buffer. |bytes_written| is
-// incremented for each written byte.
-ParsedRtcEventLog::ParseStatusOr<uint64_t> ParseVarInt(
- std::istream& stream, // no-presubmit-check TODO(webrtc:8982)
- char* buffer,
- size_t* bytes_written) {
- uint64_t varint = 0;
- for (size_t bytes_read = 0; bytes_read < 10; ++bytes_read) {
- // The most significant bit of each byte is 0 if it is the last byte in
- // the varint and 1 otherwise. Thus, we take the 7 least significant bits
- // of each byte and shift them 7 bits for each byte read previously to get
- // the (unsigned) integer.
- int byte = stream.get();
- RTC_PARSE_CHECK_OR_RETURN(!stream.eof());
- RTC_DCHECK_GE(byte, 0);
- RTC_DCHECK_LE(byte, 255);
- varint |= static_cast<uint64_t>(byte & 0x7F) << (7 * bytes_read);
- buffer[*bytes_written] = byte;
- *bytes_written += 1;
- if ((byte & 0x80) == 0) {
- return varint;
- }
- }
- RTC_PARSE_CHECK_OR_RETURN(false);
+VideoCodecType GetRuntimeCodecType(rtclog2::FrameDecodedEvents::Codec codec) {
+ switch (codec) {
+ case rtclog2::FrameDecodedEvents::CODEC_GENERIC:
+ return VideoCodecType::kVideoCodecGeneric;
+ case rtclog2::FrameDecodedEvents::CODEC_VP8:
+ return VideoCodecType::kVideoCodecVP8;
+ case rtclog2::FrameDecodedEvents::CODEC_VP9:
+ return VideoCodecType::kVideoCodecVP9;
+ case rtclog2::FrameDecodedEvents::CODEC_AV1:
+ return VideoCodecType::kVideoCodecAV1;
+ case rtclog2::FrameDecodedEvents::CODEC_H264:
+ return VideoCodecType::kVideoCodecH264;
+ case rtclog2::FrameDecodedEvents::CODEC_UNKNOWN:
+ RTC_LOG(LS_ERROR) << "Unknown codec type. Assuming "
+ "VideoCodecType::kVideoCodecMultiplex";
+ return VideoCodecType::kVideoCodecMultiplex;
+ }
+ RTC_DCHECK_NOTREACHED();
+ return VideoCodecType::kVideoCodecMultiplex;
}
ParsedRtcEventLog::ParseStatus GetHeaderExtensions(
@@ -395,7 +399,7 @@ ParsedRtcEventLog::ParseStatus StoreRtpPackets(
RTC_PARSE_CHECK_OR_RETURN(!proto.has_voice_activity());
}
(*rtp_packets_map)[header.ssrc].emplace_back(
- proto.timestamp_ms() * 1000, header, proto.header_size(),
+ Timestamp::Millis(proto.timestamp_ms()), header, proto.header_size(),
proto.payload_size() + header.headerLength + header.paddingLength);
}
@@ -528,7 +532,7 @@ ParsedRtcEventLog::ParseStatus StoreRtpPackets(
number_of_deltas);
}
- // Delta decoding
+ // Populate events from decoded deltas
for (size_t i = 0; i < number_of_deltas; ++i) {
RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
RTC_PARSE_CHECK_OR_RETURN(marker_values[i].has_value());
@@ -597,7 +601,7 @@ ParsedRtcEventLog::ParseStatus StoreRtpPackets(
!voice_activity_values[i].has_value());
}
(*rtp_packets_map)[header.ssrc].emplace_back(
- 1000 * timestamp_ms, header, header.headerLength,
+ Timestamp::Millis(timestamp_ms), header, header.headerLength,
payload_size_values[i].value() + header.headerLength +
header.paddingLength);
}
@@ -620,7 +624,8 @@ ParsedRtcEventLog::ParseStatus StoreRtcpPackets(
!IdenticalRtcpContents(rtcp_packets->back().rtcp.raw_data,
proto.raw_packet())) {
// Base event
- rtcp_packets->emplace_back(proto.timestamp_ms() * 1000, proto.raw_packet());
+ rtcp_packets->emplace_back(Timestamp::Millis(proto.timestamp_ms()),
+ proto.raw_packet());
}
const size_t number_of_deltas =
@@ -641,7 +646,7 @@ ParsedRtcEventLog::ParseStatus StoreRtcpPackets(
DecodeBlobs(proto.raw_packet_blobs(), number_of_deltas);
RTC_PARSE_CHECK_OR_RETURN_EQ(raw_packet_values.size(), number_of_deltas);
- // Delta decoding
+ // Populate events from decoded deltas
for (size_t i = 0; i < number_of_deltas; ++i) {
RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
int64_t timestamp_ms;
@@ -657,10 +662,8 @@ ParsedRtcEventLog::ParseStatus StoreRtcpPackets(
raw_packet_values[i])) {
continue;
}
- const size_t data_size = raw_packet_values[i].size();
- const uint8_t* data =
- reinterpret_cast<const uint8_t*>(raw_packet_values[i].data());
- rtcp_packets->emplace_back(1000 * timestamp_ms, data, data_size);
+ std::string data(raw_packet_values[i]);
+ rtcp_packets->emplace_back(Timestamp::Millis(timestamp_ms), data);
}
return ParsedRtcEventLog::ParseStatus::Success();
}
@@ -676,8 +679,10 @@ ParsedRtcEventLog::ParseStatus StoreRtcpBlocks(
std::vector<LoggedRtcpPacketNack>* nack_list,
std::vector<LoggedRtcpPacketFir>* fir_list,
std::vector<LoggedRtcpPacketPli>* pli_list,
+ std::vector<LoggedRtcpPacketBye>* bye_list,
std::vector<LoggedRtcpPacketTransportFeedback>* transport_feedback_list,
std::vector<LoggedRtcpPacketLossNotification>* loss_notification_list) {
+ Timestamp timestamp = Timestamp::Micros(timestamp_us);
rtcp::CommonHeader header;
for (const uint8_t* block = packet_begin; block < packet_end;
block = header.NextPacket()) {
@@ -685,47 +690,47 @@ ParsedRtcEventLog::ParseStatus StoreRtcpBlocks(
if (header.type() == rtcp::TransportFeedback::kPacketType &&
header.fmt() == rtcp::TransportFeedback::kFeedbackMessageType) {
LoggedRtcpPacketTransportFeedback parsed_block;
- parsed_block.timestamp_us = timestamp_us;
- if (parsed_block.transport_feedback.Parse(header))
- transport_feedback_list->push_back(std::move(parsed_block));
+ parsed_block.timestamp = timestamp;
+ RTC_PARSE_CHECK_OR_RETURN(parsed_block.transport_feedback.Parse(header));
+ transport_feedback_list->push_back(std::move(parsed_block));
} else if (header.type() == rtcp::SenderReport::kPacketType) {
LoggedRtcpPacketSenderReport parsed_block;
- parsed_block.timestamp_us = timestamp_us;
- if (parsed_block.sr.Parse(header)) {
- sr_list->push_back(std::move(parsed_block));
- }
+ parsed_block.timestamp = timestamp;
+ RTC_PARSE_CHECK_OR_RETURN(parsed_block.sr.Parse(header));
+ sr_list->push_back(std::move(parsed_block));
} else if (header.type() == rtcp::ReceiverReport::kPacketType) {
LoggedRtcpPacketReceiverReport parsed_block;
- parsed_block.timestamp_us = timestamp_us;
- if (parsed_block.rr.Parse(header)) {
- rr_list->push_back(std::move(parsed_block));
- }
+ parsed_block.timestamp = timestamp;
+ RTC_PARSE_CHECK_OR_RETURN(parsed_block.rr.Parse(header));
+ rr_list->push_back(std::move(parsed_block));
} else if (header.type() == rtcp::ExtendedReports::kPacketType) {
LoggedRtcpPacketExtendedReports parsed_block;
- parsed_block.timestamp_us = timestamp_us;
- if (parsed_block.xr.Parse(header)) {
- xr_list->push_back(std::move(parsed_block));
- }
+ parsed_block.timestamp = timestamp;
+ RTC_PARSE_CHECK_OR_RETURN(parsed_block.xr.Parse(header));
+ xr_list->push_back(std::move(parsed_block));
} else if (header.type() == rtcp::Fir::kPacketType &&
header.fmt() == rtcp::Fir::kFeedbackMessageType) {
LoggedRtcpPacketFir parsed_block;
- parsed_block.timestamp_us = timestamp_us;
- if (parsed_block.fir.Parse(header)) {
- fir_list->push_back(std::move(parsed_block));
- }
+ parsed_block.timestamp = timestamp;
+ RTC_PARSE_CHECK_OR_RETURN(parsed_block.fir.Parse(header));
+ fir_list->push_back(std::move(parsed_block));
} else if (header.type() == rtcp::Pli::kPacketType &&
header.fmt() == rtcp::Pli::kFeedbackMessageType) {
LoggedRtcpPacketPli parsed_block;
- parsed_block.timestamp_us = timestamp_us;
- if (parsed_block.pli.Parse(header)) {
- pli_list->push_back(std::move(parsed_block));
- }
- } else if (header.type() == rtcp::Remb::kPacketType &&
+ parsed_block.timestamp = timestamp;
+ RTC_PARSE_CHECK_OR_RETURN(parsed_block.pli.Parse(header));
+ pli_list->push_back(std::move(parsed_block));
+ } else if (header.type() == rtcp::Bye::kPacketType) {
+ LoggedRtcpPacketBye parsed_block;
+ parsed_block.timestamp = timestamp;
+ RTC_PARSE_CHECK_OR_RETURN(parsed_block.bye.Parse(header));
+ bye_list->push_back(std::move(parsed_block));
+ } else if (header.type() == rtcp::Psfb::kPacketType &&
header.fmt() == rtcp::Psfb::kAfbMessageType) {
bool type_found = false;
if (!type_found) {
LoggedRtcpPacketRemb parsed_block;
- parsed_block.timestamp_us = timestamp_us;
+ parsed_block.timestamp = timestamp;
if (parsed_block.remb.Parse(header)) {
remb_list->push_back(std::move(parsed_block));
type_found = true;
@@ -733,19 +738,19 @@ ParsedRtcEventLog::ParseStatus StoreRtcpBlocks(
}
if (!type_found) {
LoggedRtcpPacketLossNotification parsed_block;
- parsed_block.timestamp_us = timestamp_us;
+ parsed_block.timestamp = timestamp;
if (parsed_block.loss_notification.Parse(header)) {
loss_notification_list->push_back(std::move(parsed_block));
type_found = true;
}
}
+ // We ignore other application-layer feedback types.
} else if (header.type() == rtcp::Nack::kPacketType &&
header.fmt() == rtcp::Nack::kFeedbackMessageType) {
LoggedRtcpPacketNack parsed_block;
- parsed_block.timestamp_us = timestamp_us;
- if (parsed_block.nack.Parse(header)) {
- nack_list->push_back(std::move(parsed_block));
- }
+ parsed_block.timestamp = timestamp;
+ RTC_PARSE_CHECK_OR_RETURN(parsed_block.nack.Parse(header));
+ nack_list->push_back(std::move(parsed_block));
}
}
return ParsedRtcEventLog::ParseStatus::Success();
@@ -766,7 +771,7 @@ BandwidthUsage GetRuntimeDetectorState(
case rtclog2::DelayBasedBweUpdates::BWE_UNKNOWN_STATE:
break;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return BandwidthUsage::kBwNormal;
}
@@ -782,7 +787,7 @@ ProbeFailureReason GetRuntimeProbeFailureReason(
case rtclog2::BweProbeResultFailure::UNKNOWN:
break;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return ProbeFailureReason::kTimeout;
}
@@ -800,10 +805,10 @@ DtlsTransportState GetRuntimeDtlsTransportState(
case rtclog2::DtlsTransportStateEvent::DTLS_TRANSPORT_FAILED:
return DtlsTransportState::kFailed;
case rtclog2::DtlsTransportStateEvent::UNKNOWN_DTLS_TRANSPORT_STATE:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return DtlsTransportState::kNumValues;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return DtlsTransportState::kNumValues;
}
@@ -821,7 +826,7 @@ IceCandidatePairConfigType GetRuntimeIceCandidatePairConfigType(
case rtclog2::IceCandidatePairConfig::UNKNOWN_CONFIG_TYPE:
break;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return IceCandidatePairConfigType::kAdded;
}
@@ -839,7 +844,7 @@ IceCandidateType GetRuntimeIceCandidateType(
case rtclog2::IceCandidatePairConfig::UNKNOWN_CANDIDATE_TYPE:
return IceCandidateType::kUnknown;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return IceCandidateType::kUnknown;
}
@@ -857,7 +862,7 @@ IceCandidatePairProtocol GetRuntimeIceCandidatePairProtocol(
case rtclog2::IceCandidatePairConfig::UNKNOWN_PROTOCOL:
return IceCandidatePairProtocol::kUnknown;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return IceCandidatePairProtocol::kUnknown;
}
@@ -871,7 +876,7 @@ IceCandidatePairAddressFamily GetRuntimeIceCandidatePairAddressFamily(
case rtclog2::IceCandidatePairConfig::UNKNOWN_ADDRESS_FAMILY:
return IceCandidatePairAddressFamily::kUnknown;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return IceCandidatePairAddressFamily::kUnknown;
}
@@ -891,7 +896,7 @@ IceCandidateNetworkType GetRuntimeIceCandidateNetworkType(
case rtclog2::IceCandidatePairConfig::UNKNOWN_NETWORK_TYPE:
return IceCandidateNetworkType::kUnknown;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return IceCandidateNetworkType::kUnknown;
}
@@ -909,7 +914,7 @@ IceCandidatePairEventType GetRuntimeIceCandidatePairEventType(
case rtclog2::IceCandidatePairEvent::UNKNOWN_CHECK_TYPE:
break;
}
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return IceCandidatePairEventType::kCheckSent;
}
@@ -943,6 +948,35 @@ std::vector<RtpExtension> GetRuntimeRtpHeaderExtensionConfig(
}
// End of conversion functions.
+LoggedPacketInfo::LoggedPacketInfo(const LoggedRtpPacket& rtp,
+ LoggedMediaType media_type,
+ bool rtx,
+ Timestamp capture_time)
+ : ssrc(rtp.header.ssrc),
+ stream_seq_no(rtp.header.sequenceNumber),
+ size(static_cast<uint16_t>(rtp.total_length)),
+ payload_size(static_cast<uint16_t>(rtp.total_length -
+ rtp.header.paddingLength -
+ rtp.header.headerLength)),
+ padding_size(static_cast<uint16_t>(rtp.header.paddingLength)),
+ payload_type(rtp.header.payloadType),
+ media_type(media_type),
+ rtx(rtx),
+ marker_bit(rtp.header.markerBit),
+ has_transport_seq_no(rtp.header.extension.hasTransportSequenceNumber),
+ transport_seq_no(static_cast<uint16_t>(
+ has_transport_seq_no ? rtp.header.extension.transportSequenceNumber
+ : 0)),
+ capture_time(capture_time),
+ log_packet_time(Timestamp::Micros(rtp.log_time_us())),
+ reported_send_time(rtp.header.extension.hasAbsoluteSendTime
+ ? rtp.header.extension.GetAbsoluteSendTimestamp()
+ : Timestamp::MinusInfinity()) {}
+
+LoggedPacketInfo::LoggedPacketInfo(const LoggedPacketInfo&) = default;
+
+LoggedPacketInfo::~LoggedPacketInfo() {}
+
ParsedRtcEventLog::~ParsedRtcEventLog() = default;
ParsedRtcEventLog::LoggedRtpStreamIncoming::LoggedRtpStreamIncoming() = default;
@@ -959,23 +993,21 @@ ParsedRtcEventLog::LoggedRtpStreamOutgoing::~LoggedRtpStreamOutgoing() =
ParsedRtcEventLog::LoggedRtpStreamView::LoggedRtpStreamView(
uint32_t ssrc,
- const LoggedRtpPacketIncoming* ptr,
- size_t num_elements)
- : ssrc(ssrc),
- packet_view(PacketView<const LoggedRtpPacket>::Create(
- ptr,
- num_elements,
- offsetof(LoggedRtpPacketIncoming, rtp))) {}
+ const std::vector<LoggedRtpPacketIncoming>& packets)
+ : ssrc(ssrc), packet_view() {
+ for (const LoggedRtpPacketIncoming& packet : packets) {
+ packet_view.push_back(&(packet.rtp));
+ }
+}
ParsedRtcEventLog::LoggedRtpStreamView::LoggedRtpStreamView(
uint32_t ssrc,
- const LoggedRtpPacketOutgoing* ptr,
- size_t num_elements)
- : ssrc(ssrc),
- packet_view(PacketView<const LoggedRtpPacket>::Create(
- ptr,
- num_elements,
- offsetof(LoggedRtpPacketOutgoing, rtp))) {}
+ const std::vector<LoggedRtpPacketOutgoing>& packets)
+ : ssrc(ssrc), packet_view() {
+ for (const LoggedRtpPacketOutgoing& packet : packets) {
+ packet_view.push_back(&(packet.rtp));
+ }
+}
ParsedRtcEventLog::LoggedRtpStreamView::LoggedRtpStreamView(
const LoggedRtpStreamView&) = default;
@@ -1063,6 +1095,7 @@ void ParsedRtcEventLog::Clear() {
bwe_loss_updates_.clear();
dtls_transport_states_.clear();
dtls_writable_states_.clear();
+ decoded_frames_.clear();
alr_state_events_.clear();
ice_candidate_pair_configs_.clear();
ice_candidate_pair_events_.clear();
@@ -1071,11 +1104,10 @@ void ParsedRtcEventLog::Clear() {
video_recv_configs_.clear();
video_send_configs_.clear();
- memset(last_incoming_rtcp_packet_, 0, IP_PACKET_SIZE);
- last_incoming_rtcp_packet_length_ = 0;
+ last_incoming_rtcp_packet_.clear();
- first_timestamp_ = std::numeric_limits<int64_t>::max();
- last_timestamp_ = std::numeric_limits<int64_t>::min();
+ first_timestamp_ = Timestamp::PlusInfinity();
+ last_timestamp_ = Timestamp::MinusInfinity();
first_log_segment_ = LogSegment(0, std::numeric_limits<int64_t>::max());
incoming_rtp_extensions_maps_.clear();
@@ -1083,28 +1115,40 @@ void ParsedRtcEventLog::Clear() {
}
ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseFile(
- const std::string& filename) {
- std::ifstream file( // no-presubmit-check TODO(webrtc:8982)
- filename, std::ios_base::in | std::ios_base::binary);
- if (!file.good() || !file.is_open()) {
- RTC_LOG(LS_WARNING) << "Could not open file for reading.";
- RTC_PARSE_CHECK_OR_RETURN(file.good() && file.is_open());
+ absl::string_view filename) {
+ FileWrapper file = FileWrapper::OpenReadOnly(filename);
+ if (!file.is_open()) {
+ RTC_LOG(LS_WARNING) << "Could not open file " << filename
+ << " for reading.";
+ RTC_PARSE_CHECK_OR_RETURN(file.is_open());
+ }
+
+ // Compute file size.
+ long signed_filesize = file.FileSize(); // NOLINT(runtime/int)
+ RTC_PARSE_CHECK_OR_RETURN_GE(signed_filesize, 0);
+ RTC_PARSE_CHECK_OR_RETURN_LE(signed_filesize, kMaxLogSize);
+ size_t filesize = rtc::checked_cast<size_t>(signed_filesize);
+
+ // Read file into memory.
+ std::string buffer(filesize, '\0');
+ size_t bytes_read = file.Read(&buffer[0], buffer.size());
+ if (bytes_read != filesize) {
+ RTC_LOG(LS_WARNING) << "Failed to read file " << filename;
+ RTC_PARSE_CHECK_OR_RETURN_EQ(bytes_read, filesize);
}
- return ParseStream(file);
+ return ParseStream(buffer);
}
ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseString(
- const std::string& s) {
- std::istringstream stream( // no-presubmit-check TODO(webrtc:8982)
- s, std::ios_base::in | std::ios_base::binary);
- return ParseStream(stream);
+ absl::string_view s) {
+ return ParseStream(s);
}
ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStream(
- std::istream& stream) { // no-presubmit-check TODO(webrtc:8982)
+ absl::string_view s) {
Clear();
- ParseStatus status = ParseStreamInternal(stream);
+ ParseStatus status = ParseStreamInternal(s);
// Cache the configured SSRCs.
for (const auto& video_recv_config : video_recv_configs()) {
@@ -1147,38 +1191,36 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStream(
// Build PacketViews for easier iteration over RTP packets.
for (const auto& stream : incoming_rtp_packets_by_ssrc_) {
incoming_rtp_packet_views_by_ssrc_.emplace_back(
- LoggedRtpStreamView(stream.ssrc, stream.incoming_packets.data(),
- stream.incoming_packets.size()));
+ LoggedRtpStreamView(stream.ssrc, stream.incoming_packets));
}
for (const auto& stream : outgoing_rtp_packets_by_ssrc_) {
outgoing_rtp_packet_views_by_ssrc_.emplace_back(
- LoggedRtpStreamView(stream.ssrc, stream.outgoing_packets.data(),
- stream.outgoing_packets.size()));
+ LoggedRtpStreamView(stream.ssrc, stream.outgoing_packets));
}
// Set up convenience wrappers around the most commonly used RTCP types.
for (const auto& incoming : incoming_rtcp_packets_) {
- const int64_t timestamp_us = incoming.rtcp.timestamp_us;
+ const int64_t timestamp_us = incoming.rtcp.timestamp.us();
const uint8_t* packet_begin = incoming.rtcp.raw_data.data();
const uint8_t* packet_end = packet_begin + incoming.rtcp.raw_data.size();
- auto status = StoreRtcpBlocks(
+ auto store_rtcp_status = StoreRtcpBlocks(
timestamp_us, packet_begin, packet_end, &incoming_sr_, &incoming_rr_,
&incoming_xr_, &incoming_remb_, &incoming_nack_, &incoming_fir_,
- &incoming_pli_, &incoming_transport_feedback_,
+ &incoming_pli_, &incoming_bye_, &incoming_transport_feedback_,
&incoming_loss_notification_);
- RTC_RETURN_IF_ERROR(status);
+ RTC_RETURN_IF_ERROR(store_rtcp_status);
}
for (const auto& outgoing : outgoing_rtcp_packets_) {
- const int64_t timestamp_us = outgoing.rtcp.timestamp_us;
+ const int64_t timestamp_us = outgoing.rtcp.timestamp.us();
const uint8_t* packet_begin = outgoing.rtcp.raw_data.data();
const uint8_t* packet_end = packet_begin + outgoing.rtcp.raw_data.size();
- auto status = StoreRtcpBlocks(
+ auto store_rtcp_status = StoreRtcpBlocks(
timestamp_us, packet_begin, packet_end, &outgoing_sr_, &outgoing_rr_,
&outgoing_xr_, &outgoing_remb_, &outgoing_nack_, &outgoing_fir_,
- &outgoing_pli_, &outgoing_transport_feedback_,
+ &outgoing_pli_, &outgoing_bye_, &outgoing_transport_feedback_,
&outgoing_loss_notification_);
- RTC_RETURN_IF_ERROR(status);
+ RTC_RETURN_IF_ERROR(store_rtcp_status);
}
// Store first and last timestamp events that might happen before the call is
@@ -1186,8 +1228,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStream(
// stream configurations and starting/stopping the log.
// TODO(terelius): Figure out if we actually need to find the first and last
// timestamp in the parser. It seems like this could be done by the caller.
- first_timestamp_ = std::numeric_limits<int64_t>::max();
- last_timestamp_ = std::numeric_limits<int64_t>::min();
+ first_timestamp_ = Timestamp::PlusInfinity();
+ last_timestamp_ = Timestamp::MinusInfinity();
StoreFirstAndLastTimestamp(alr_state_events());
StoreFirstAndLastTimestamp(route_change_events());
for (const auto& audio_stream : audio_playout_events()) {
@@ -1200,6 +1242,9 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStream(
StoreFirstAndLastTimestamp(bwe_probe_success_events());
StoreFirstAndLastTimestamp(bwe_delay_updates());
StoreFirstAndLastTimestamp(bwe_loss_updates());
+ for (const auto& frame_stream : decoded_frames()) {
+ StoreFirstAndLastTimestamp(frame_stream.second);
+ }
StoreFirstAndLastTimestamp(dtls_transport_states());
StoreFirstAndLastTimestamp(dtls_writable_states());
StoreFirstAndLastTimestamp(ice_candidate_pair_configs());
@@ -1223,7 +1268,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStream(
// event, we could use the timestamp of the the last previous regular event.
auto start_iter = start_log_events().begin();
auto stop_iter = stop_log_events().begin();
- int64_t start_us = first_timestamp();
+ int64_t start_us =
+ first_timestamp().us_or(std::numeric_limits<int64_t>::max());
int64_t next_start_us = std::numeric_limits<int64_t>::max();
int64_t stop_us = std::numeric_limits<int64_t>::max();
if (start_iter != start_log_events().end()) {
@@ -1237,51 +1283,62 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStream(
}
stop_us = std::min(stop_us, next_start_us);
if (stop_us == std::numeric_limits<int64_t>::max() &&
- last_timestamp() != std::numeric_limits<int64_t>::min()) {
- stop_us = last_timestamp();
+ !last_timestamp().IsMinusInfinity()) {
+ stop_us = last_timestamp().us();
}
RTC_PARSE_CHECK_OR_RETURN_LE(start_us, stop_us);
first_log_segment_ = LogSegment(start_us, stop_us);
- if (first_timestamp_ == std::numeric_limits<int64_t>::max() &&
- last_timestamp_ == std::numeric_limits<int64_t>::min()) {
- first_timestamp_ = last_timestamp_ = 0;
+ if (first_timestamp_ > last_timestamp_) {
+ first_timestamp_ = last_timestamp_ = Timestamp::Zero();
}
return status;
}
ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStreamInternal(
- std::istream& stream) { // no-presubmit-check TODO(webrtc:8982)
+ absl::string_view s) {
constexpr uint64_t kMaxEventSize = 10000000; // Sanity check.
- std::vector<char> buffer(0xFFFF);
-
- RTC_DCHECK(stream.good());
- while (1) {
- // Check whether we have reached end of file.
- stream.peek();
- if (stream.eof()) {
- break;
- }
-
- // Read the next message tag. Protobuf defines the message tag as
- // (field_number << 3) | wire_type. In the legacy encoding, the field number
- // is supposed to be 1 and the wire type for a length-delimited field is 2.
- // In the new encoding we still expect the wire type to be 2, but the field
- // number will be greater than 1.
- constexpr uint64_t kExpectedV1Tag = (1 << 3) | 2;
- size_t bytes_written = 0;
- ParsedRtcEventLog::ParseStatusOr<uint64_t> tag =
- ParseVarInt(stream, buffer.data(), &bytes_written);
- if (!tag.ok()) {
+ // Protobuf defines the message tag as
+ // (field_number << 3) | wire_type. In the legacy encoding, the field number
+ // is supposed to be 1 and the wire type for a length-delimited field is 2.
+ // In the new encoding we still expect the wire type to be 2, but the field
+ // number will be greater than 1.
+ constexpr uint64_t kExpectedV1Tag = (1 << 3) | 2;
+ bool success = false;
+
+ // "Peek" at the first varint.
+ absl::string_view event_start = s;
+ uint64_t tag = 0;
+ std::tie(success, std::ignore) = DecodeVarInt(s, &tag);
+ if (!success) {
+ RTC_LOG(LS_WARNING) << "Failed to read varint from beginning of event log.";
+ RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
+ kIncompleteLogError);
+ return ParseStatus::Error("Failed to read field tag varint", __FILE__,
+ __LINE__);
+ }
+ s = event_start;
+
+ if (tag >> 1 == static_cast<uint64_t>(RtcEvent::Type::BeginV3Log)) {
+ return ParseStreamInternalV3(s);
+ }
+
+ while (!s.empty()) {
+ // If not, "reset" event_start and read the field tag for the next event.
+ event_start = s;
+ std::tie(success, s) = DecodeVarInt(s, &tag);
+ if (!success) {
RTC_LOG(LS_WARNING)
- << "Missing field tag from beginning of protobuf event.";
+ << "Failed to read field tag from beginning of protobuf event.";
RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
kIncompleteLogError);
- return tag.status();
+ return ParseStatus::Error("Failed to read field tag varint", __FILE__,
+ __LINE__);
}
+
constexpr uint64_t kWireTypeMask = 0x07;
- const uint64_t wire_type = tag.value() & kWireTypeMask;
+ const uint64_t wire_type = tag & kWireTypeMask;
if (wire_type != 2) {
RTC_LOG(LS_WARNING) << "Expected field tag with wire type 2 (length "
"delimited message). Found wire type "
@@ -1292,36 +1349,37 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStreamInternal(
}
// Read the length field.
- ParsedRtcEventLog::ParseStatusOr<uint64_t> message_length =
- ParseVarInt(stream, buffer.data(), &bytes_written);
- if (!message_length.ok()) {
+ uint64_t message_length = 0;
+ std::tie(success, s) = DecodeVarInt(s, &message_length);
+ if (!success) {
RTC_LOG(LS_WARNING) << "Missing message length after protobuf field tag.";
RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
kIncompleteLogError);
- return message_length.status();
- } else if (message_length.value() > kMaxEventSize) {
- RTC_LOG(LS_WARNING) << "Protobuf message length is too large.";
- RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
- kIncompleteLogError);
- RTC_PARSE_CHECK_OR_RETURN_LE(message_length.value(), kMaxEventSize);
+ return ParseStatus::Error("Failed to read message length varint",
+ __FILE__, __LINE__);
}
- // Read the next protobuf event to a temporary char buffer.
- if (buffer.size() < bytes_written + message_length.value())
- buffer.resize(bytes_written + message_length.value());
- stream.read(buffer.data() + bytes_written, message_length.value());
- if (stream.gcount() != static_cast<int>(message_length.value())) {
- RTC_LOG(LS_WARNING) << "Failed to read protobuf message.";
+ if (message_length > s.size()) {
+ RTC_LOG(LS_WARNING) << "Protobuf message length is larger than the "
+ "remaining bytes in the proto.";
RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
kIncompleteLogError);
- RTC_PARSE_CHECK_OR_RETURN(false);
+ return ParseStatus::Error(
+ "Incomplete message: the length of the next message is larger than "
+ "the remaining bytes in the proto",
+ __FILE__, __LINE__);
}
- size_t buffer_size = bytes_written + message_length.value();
- if (tag.value() == kExpectedV1Tag) {
+ RTC_PARSE_CHECK_OR_RETURN_LE(message_length, kMaxEventSize);
+ // Skip forward to the start of the next event.
+ s = s.substr(message_length);
+ size_t total_event_size = event_start.size() - s.size();
+ RTC_CHECK_LE(total_event_size, event_start.size());
+
+ if (tag == kExpectedV1Tag) {
// Parse the protobuf event from the buffer.
rtclog::EventStream event_stream;
- if (!event_stream.ParseFromArray(buffer.data(), buffer_size)) {
+ if (!event_stream.ParseFromArray(event_start.data(), total_event_size)) {
RTC_LOG(LS_WARNING)
<< "Failed to parse legacy-format protobuf message.";
RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
@@ -1335,7 +1393,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStreamInternal(
} else {
// Parse the protobuf event from the buffer.
rtclog2::EventStream event_stream;
- if (!event_stream.ParseFromArray(buffer.data(), buffer_size)) {
+ if (!event_stream.ParseFromArray(event_start.data(), total_event_size)) {
RTC_LOG(LS_WARNING) << "Failed to parse new-format protobuf message.";
RTC_PARSE_WARN_AND_RETURN_SUCCESS_IF(allow_incomplete_logs_,
kIncompleteLogError);
@@ -1348,18 +1406,166 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStreamInternal(
return ParseStatus::Success();
}
+ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::ParseStreamInternalV3(
+ absl::string_view s) {
+ constexpr uint64_t kMaxEventSize = 10000000; // Sanity check.
+ bool expect_begin_log_event = true;
+ bool success = false;
+
+ while (!s.empty()) {
+ // Read event type.
+ uint64_t event_tag = 0;
+ std::tie(success, s) = DecodeVarInt(s, &event_tag);
+ RTC_PARSE_CHECK_OR_RETURN_MESSAGE(success, "Failed to read event type.");
+ bool batched = event_tag & 1;
+ uint64_t event_type = event_tag >> 1;
+
+ // Read event size
+ uint64_t event_size_bytes = 0;
+ std::tie(success, s) = DecodeVarInt(s, &event_size_bytes);
+ RTC_PARSE_CHECK_OR_RETURN_MESSAGE(success, "Failed to read event size.");
+ if (event_size_bytes > kMaxEventSize || event_size_bytes > s.size()) {
+ RTC_LOG(LS_WARNING) << "Event size is too large.";
+ RTC_PARSE_CHECK_OR_RETURN_LE(event_size_bytes, kMaxEventSize);
+ RTC_PARSE_CHECK_OR_RETURN_LE(event_size_bytes, s.size());
+ }
+
+ // Read remaining event fields into a buffer.
+ absl::string_view event_fields = s.substr(0, event_size_bytes);
+ s = s.substr(event_size_bytes);
+
+ if (expect_begin_log_event) {
+ RTC_PARSE_CHECK_OR_RETURN_EQ(
+ event_type, static_cast<uint32_t>(RtcEvent::Type::BeginV3Log));
+ expect_begin_log_event = false;
+ }
+
+ switch (event_type) {
+ case static_cast<uint32_t>(RtcEvent::Type::BeginV3Log):
+ RtcEventBeginLog::Parse(event_fields, batched, start_log_events_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::EndV3Log):
+ RtcEventEndLog::Parse(event_fields, batched, stop_log_events_);
+ expect_begin_log_event = true;
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::AlrStateEvent):
+ RtcEventAlrState::Parse(event_fields, batched, alr_state_events_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::AudioPlayout):
+ RtcEventAudioPlayout::Parse(event_fields, batched,
+ audio_playout_events_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::BweUpdateDelayBased):
+ RtcEventBweUpdateDelayBased::Parse(event_fields, batched,
+ bwe_delay_updates_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::AudioNetworkAdaptation):
+ RtcEventAudioNetworkAdaptation::Parse(event_fields, batched,
+ audio_network_adaptation_events_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::AudioReceiveStreamConfig):
+ RtcEventAudioReceiveStreamConfig::Parse(event_fields, batched,
+ audio_recv_configs_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::AudioSendStreamConfig):
+ RtcEventAudioSendStreamConfig::Parse(event_fields, batched,
+ audio_send_configs_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::BweUpdateLossBased):
+ RtcEventBweUpdateLossBased::Parse(event_fields, batched,
+ bwe_loss_updates_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::DtlsTransportState):
+ RtcEventDtlsTransportState::Parse(event_fields, batched,
+ dtls_transport_states_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::DtlsWritableState):
+ RtcEventDtlsWritableState::Parse(event_fields, batched,
+ dtls_writable_states_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::FrameDecoded):
+ RtcEventFrameDecoded::Parse(event_fields, batched, decoded_frames_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::GenericAckReceived):
+ RtcEventGenericAckReceived::Parse(event_fields, batched,
+ generic_acks_received_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::GenericPacketReceived):
+ RtcEventGenericPacketReceived::Parse(event_fields, batched,
+ generic_packets_received_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::GenericPacketSent):
+ RtcEventGenericPacketSent::Parse(event_fields, batched,
+ generic_packets_sent_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::IceCandidatePairConfig):
+ RtcEventIceCandidatePairConfig::Parse(event_fields, batched,
+ ice_candidate_pair_configs_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::IceCandidatePairEvent):
+ RtcEventIceCandidatePair::Parse(event_fields, batched,
+ ice_candidate_pair_events_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::ProbeClusterCreated):
+ RtcEventProbeClusterCreated::Parse(event_fields, batched,
+ bwe_probe_cluster_created_events_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::ProbeResultFailure):
+ RtcEventProbeResultFailure::Parse(event_fields, batched,
+ bwe_probe_failure_events_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::ProbeResultSuccess):
+ RtcEventProbeResultSuccess::Parse(event_fields, batched,
+ bwe_probe_success_events_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::RemoteEstimateEvent):
+ RtcEventRemoteEstimate::Parse(event_fields, batched,
+ remote_estimate_events_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::RouteChangeEvent):
+ RtcEventRouteChange::Parse(event_fields, batched, route_change_events_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::RtcpPacketIncoming):
+ RtcEventRtcpPacketIncoming::Parse(event_fields, batched,
+ incoming_rtcp_packets_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::RtcpPacketOutgoing):
+ RtcEventRtcpPacketOutgoing::Parse(event_fields, batched,
+ outgoing_rtcp_packets_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::RtpPacketIncoming):
+ RtcEventRtpPacketIncoming::Parse(event_fields, batched,
+ incoming_rtp_packets_map_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::RtpPacketOutgoing):
+ RtcEventRtpPacketOutgoing::Parse(event_fields, batched,
+ outgoing_rtp_packets_map_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::VideoReceiveStreamConfig):
+ RtcEventVideoReceiveStreamConfig::Parse(event_fields, batched,
+ video_recv_configs_);
+ break;
+ case static_cast<uint32_t>(RtcEvent::Type::VideoSendStreamConfig):
+ RtcEventVideoSendStreamConfig::Parse(event_fields, batched,
+ video_send_configs_);
+ break;
+ }
+ }
+
+ return ParseStatus::Success();
+}
+
template <typename T>
void ParsedRtcEventLog::StoreFirstAndLastTimestamp(const std::vector<T>& v) {
if (v.empty())
return;
- first_timestamp_ = std::min(first_timestamp_, v.front().log_time_us());
- last_timestamp_ = std::max(last_timestamp_, v.back().log_time_us());
+ first_timestamp_ = std::min(first_timestamp_, v.front().log_time());
+ last_timestamp_ = std::max(last_timestamp_, v.back().log_time());
}
ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreParsedLegacyEvent(
const rtclog::Event& event) {
RTC_PARSE_CHECK_OR_RETURN(event.has_type());
- RTC_PARSE_CHECK_OR_RETURN(event.has_type());
switch (event.type()) {
case rtclog::Event::VIDEO_RECEIVER_CONFIG_EVENT: {
auto config = GetVideoReceiveConfig(event);
@@ -1368,7 +1574,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreParsedLegacyEvent(
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
int64_t timestamp_us = event.timestamp_us();
- video_recv_configs_.emplace_back(timestamp_us, config.value());
+ video_recv_configs_.emplace_back(Timestamp::Micros(timestamp_us),
+ config.value());
incoming_rtp_extensions_maps_[config.value().remote_ssrc] =
RtpHeaderExtensionMap(config.value().rtp_extensions);
incoming_rtp_extensions_maps_[config.value().rtx_ssrc] =
@@ -1382,7 +1589,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreParsedLegacyEvent(
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
int64_t timestamp_us = event.timestamp_us();
- video_send_configs_.emplace_back(timestamp_us, config.value());
+ video_send_configs_.emplace_back(Timestamp::Micros(timestamp_us),
+ config.value());
outgoing_rtp_extensions_maps_[config.value().local_ssrc] =
RtpHeaderExtensionMap(config.value().rtp_extensions);
outgoing_rtp_extensions_maps_[config.value().rtx_ssrc] =
@@ -1396,7 +1604,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreParsedLegacyEvent(
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
int64_t timestamp_us = event.timestamp_us();
- audio_recv_configs_.emplace_back(timestamp_us, config.value());
+ audio_recv_configs_.emplace_back(Timestamp::Micros(timestamp_us),
+ config.value());
incoming_rtp_extensions_maps_[config.value().remote_ssrc] =
RtpHeaderExtensionMap(config.value().rtp_extensions);
break;
@@ -1407,84 +1616,91 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreParsedLegacyEvent(
return config.status();
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
int64_t timestamp_us = event.timestamp_us();
- audio_send_configs_.emplace_back(timestamp_us, config.value());
+ audio_send_configs_.emplace_back(Timestamp::Micros(timestamp_us),
+ config.value());
outgoing_rtp_extensions_maps_[config.value().local_ssrc] =
RtpHeaderExtensionMap(config.value().rtp_extensions);
break;
}
case rtclog::Event::RTP_EVENT: {
- PacketDirection direction;
- uint8_t header[IP_PACKET_SIZE];
- size_t header_length;
- size_t total_length;
- ParseStatus status = GetRtpHeader(event, &direction, header,
- &header_length, &total_length, nullptr);
- RTC_RETURN_IF_ERROR(status);
+ RTC_PARSE_CHECK_OR_RETURN(event.has_rtp_packet());
+ const rtclog::RtpPacket& rtp_packet = event.rtp_packet();
+ RTC_PARSE_CHECK_OR_RETURN(rtp_packet.has_header());
+ RTC_PARSE_CHECK_OR_RETURN(rtp_packet.has_incoming());
+ RTC_PARSE_CHECK_OR_RETURN(rtp_packet.has_packet_length());
+ size_t total_length = rtp_packet.packet_length();
+
+ // Use RtpPacketReceived instead of more generic RtpPacket because former
+ // has a buildin convertion to RTPHeader.
+ RtpPacketReceived rtp_header;
+ RTC_PARSE_CHECK_OR_RETURN(
+ rtp_header.Parse(rtc::CopyOnWriteBuffer(rtp_packet.header())));
+
+ if (const RtpHeaderExtensionMap* extension_map = GetRtpHeaderExtensionMap(
+ rtp_packet.incoming(), rtp_header.Ssrc())) {
+ rtp_header.IdentifyExtensions(*extension_map);
+ }
- uint32_t ssrc = ByteReader<uint32_t>::ReadBigEndian(header + 8);
- const RtpHeaderExtensionMap* extension_map =
- GetRtpHeaderExtensionMap(direction, ssrc);
- RtpUtility::RtpHeaderParser rtp_parser(header, header_length);
RTPHeader parsed_header;
- rtp_parser.Parse(&parsed_header, extension_map, /*header_only*/ true);
+ rtp_header.GetHeader(&parsed_header);
// Since we give the parser only a header, there is no way for it to know
// the padding length. The best solution would be to log the padding
// length in RTC event log. In absence of it, we assume the RTP packet to
// contain only padding, if the padding bit is set.
// TODO(webrtc:9730): Use a generic way to obtain padding length.
- if ((header[0] & 0x20) != 0)
- parsed_header.paddingLength = total_length - header_length;
+ if (rtp_header.has_padding())
+ parsed_header.paddingLength = total_length - rtp_header.size();
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
int64_t timestamp_us = event.timestamp_us();
- if (direction == kIncomingPacket) {
+ if (rtp_packet.incoming()) {
incoming_rtp_packets_map_[parsed_header.ssrc].push_back(
- LoggedRtpPacketIncoming(timestamp_us, parsed_header, header_length,
+ LoggedRtpPacketIncoming(Timestamp::Micros(timestamp_us),
+ parsed_header, rtp_header.size(),
total_length));
} else {
outgoing_rtp_packets_map_[parsed_header.ssrc].push_back(
- LoggedRtpPacketOutgoing(timestamp_us, parsed_header, header_length,
+ LoggedRtpPacketOutgoing(Timestamp::Micros(timestamp_us),
+ parsed_header, rtp_header.size(),
total_length));
}
break;
}
case rtclog::Event::RTCP_EVENT: {
PacketDirection direction;
- uint8_t packet[IP_PACKET_SIZE];
- size_t total_length;
- auto status = GetRtcpPacket(event, &direction, packet, &total_length);
+ std::vector<uint8_t> packet;
+ auto status = GetRtcpPacket(event, &direction, &packet);
RTC_RETURN_IF_ERROR(status);
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
int64_t timestamp_us = event.timestamp_us();
- RTC_PARSE_CHECK_OR_RETURN_LE(total_length, IP_PACKET_SIZE);
if (direction == kIncomingPacket) {
// Currently incoming RTCP packets are logged twice, both for audio and
// video. Only act on one of them. Compare against the previous parsed
// incoming RTCP packet.
- if (total_length == last_incoming_rtcp_packet_length_ &&
- memcmp(last_incoming_rtcp_packet_, packet, total_length) == 0)
+ if (packet == last_incoming_rtcp_packet_)
break;
incoming_rtcp_packets_.push_back(
- LoggedRtcpPacketIncoming(timestamp_us, packet, total_length));
- last_incoming_rtcp_packet_length_ = total_length;
- memcpy(last_incoming_rtcp_packet_, packet, total_length);
+ LoggedRtcpPacketIncoming(Timestamp::Micros(timestamp_us), packet));
+ last_incoming_rtcp_packet_ = packet;
} else {
outgoing_rtcp_packets_.push_back(
- LoggedRtcpPacketOutgoing(timestamp_us, packet, total_length));
+ LoggedRtcpPacketOutgoing(Timestamp::Micros(timestamp_us), packet));
}
break;
}
case rtclog::Event::LOG_START: {
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
int64_t timestamp_us = event.timestamp_us();
- start_log_events_.push_back(LoggedStartEvent(timestamp_us));
+ start_log_events_.push_back(
+ LoggedStartEvent(Timestamp::Micros(timestamp_us)));
break;
}
case rtclog::Event::LOG_END: {
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
int64_t timestamp_us = event.timestamp_us();
- stop_log_events_.push_back(LoggedStopEvent(timestamp_us));
+ stop_log_events_.push_back(
+ LoggedStopEvent(Timestamp::Micros(timestamp_us)));
break;
}
case rtclog::Event::AUDIO_PLAYOUT_EVENT: {
@@ -1554,88 +1770,44 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreParsedLegacyEvent(
ice_candidate_pair_events_.push_back(status_or_value.value());
break;
}
- case rtclog::Event::UNKNOWN_EVENT: {
+ case rtclog::Event::REMOTE_ESTIMATE: {
+ auto status_or_value = GetRemoteEstimateEvent(event);
+ RTC_RETURN_IF_ERROR(status_or_value.status());
+ remote_estimate_events_.push_back(status_or_value.value());
break;
}
- }
- return ParseStatus::Success();
-}
-
-// The header must have space for at least IP_PACKET_SIZE bytes.
-ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::GetRtpHeader(
- const rtclog::Event& event,
- PacketDirection* incoming,
- uint8_t* header,
- size_t* header_length,
- size_t* total_length,
- int* probe_cluster_id) const {
- RTC_PARSE_CHECK_OR_RETURN(event.has_type());
- RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(), rtclog::Event::RTP_EVENT);
- RTC_PARSE_CHECK_OR_RETURN(event.has_rtp_packet());
- const rtclog::RtpPacket& rtp_packet = event.rtp_packet();
- // Get direction of packet.
- RTC_PARSE_CHECK_OR_RETURN(rtp_packet.has_incoming());
- if (incoming != nullptr) {
- *incoming = rtp_packet.incoming() ? kIncomingPacket : kOutgoingPacket;
- }
- // Get packet length.
- RTC_PARSE_CHECK_OR_RETURN(rtp_packet.has_packet_length());
- if (total_length != nullptr) {
- *total_length = rtp_packet.packet_length();
- }
- // Get header length.
- RTC_PARSE_CHECK_OR_RETURN(rtp_packet.has_header());
- if (header_length != nullptr) {
- *header_length = rtp_packet.header().size();
- }
- if (probe_cluster_id != nullptr) {
- if (rtp_packet.has_probe_cluster_id()) {
- *probe_cluster_id = rtp_packet.probe_cluster_id();
- RTC_PARSE_CHECK_OR_RETURN_NE(*probe_cluster_id,
- PacedPacketInfo::kNotAProbe);
- } else {
- *probe_cluster_id = PacedPacketInfo::kNotAProbe;
+ case rtclog::Event::UNKNOWN_EVENT: {
+ break;
}
}
- // Get header contents.
- if (header != nullptr) {
- const size_t kMinRtpHeaderSize = 12;
- RTC_PARSE_CHECK_OR_RETURN_GE(rtp_packet.header().size(), kMinRtpHeaderSize);
- RTC_PARSE_CHECK_OR_RETURN_LE(rtp_packet.header().size(),
- static_cast<size_t>(IP_PACKET_SIZE));
- memcpy(header, rtp_packet.header().data(), rtp_packet.header().size());
- }
return ParseStatus::Success();
}
const RtpHeaderExtensionMap* ParsedRtcEventLog::GetRtpHeaderExtensionMap(
- PacketDirection direction,
+ bool incoming,
uint32_t ssrc) {
- auto& extensions_maps = direction == PacketDirection::kIncomingPacket
- ? incoming_rtp_extensions_maps_
- : outgoing_rtp_extensions_maps_;
+ auto& extensions_maps =
+ incoming ? incoming_rtp_extensions_maps_ : outgoing_rtp_extensions_maps_;
auto it = extensions_maps.find(ssrc);
if (it != extensions_maps.end()) {
return &(it->second);
}
if (parse_unconfigured_header_extensions_ ==
UnconfiguredHeaderExtensions::kAttemptWebrtcDefaultConfig) {
- RTC_LOG(LS_WARNING) << "Using default header extension map for SSRC "
- << ssrc;
+ RTC_DLOG(LS_WARNING) << "Using default header extension map for SSRC "
+ << ssrc;
extensions_maps.insert(std::make_pair(ssrc, default_extension_map_));
return &default_extension_map_;
}
- RTC_LOG(LS_WARNING) << "Not parsing header extensions for SSRC " << ssrc
- << ". No header extension map found.";
+ RTC_DLOG(LS_WARNING) << "Not parsing header extensions for SSRC " << ssrc
+ << ". No header extension map found.";
return nullptr;
}
-// The packet must have space for at least IP_PACKET_SIZE bytes.
ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::GetRtcpPacket(
const rtclog::Event& event,
PacketDirection* incoming,
- uint8_t* packet,
- size_t* length) const {
+ std::vector<uint8_t>* packet) const {
RTC_PARSE_CHECK_OR_RETURN(event.has_type());
RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(), rtclog::Event::RTCP_EVENT);
RTC_PARSE_CHECK_OR_RETURN(event.has_rtcp_packet());
@@ -1645,16 +1817,11 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::GetRtcpPacket(
if (incoming != nullptr) {
*incoming = rtcp_packet.incoming() ? kIncomingPacket : kOutgoingPacket;
}
- // Get packet length.
- RTC_PARSE_CHECK_OR_RETURN(rtcp_packet.has_packet_data());
- if (length != nullptr) {
- *length = rtcp_packet.packet_data().size();
- }
// Get packet contents.
+ RTC_PARSE_CHECK_OR_RETURN(rtcp_packet.has_packet_data());
if (packet != nullptr) {
- RTC_PARSE_CHECK_OR_RETURN_LE(rtcp_packet.packet_data().size(),
- static_cast<unsigned>(IP_PACKET_SIZE));
- memcpy(packet, rtcp_packet.packet_data().data(),
+ packet->resize(rtcp_packet.packet_data().size());
+ memcpy(packet->data(), rtcp_packet.packet_data().data(),
rtcp_packet.packet_data().size());
}
return ParseStatus::Success();
@@ -1810,7 +1977,7 @@ ParsedRtcEventLog::GetAudioPlayout(const rtclog::Event& event) const {
const rtclog::AudioPlayoutEvent& playout_event = event.audio_playout_event();
LoggedAudioPlayoutEvent res;
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
- res.timestamp_us = event.timestamp_us();
+ res.timestamp = Timestamp::Micros(event.timestamp_us());
RTC_PARSE_CHECK_OR_RETURN(playout_event.has_local_ssrc());
res.ssrc = playout_event.local_ssrc();
return res;
@@ -1826,7 +1993,7 @@ ParsedRtcEventLog::GetLossBasedBweUpdate(const rtclog::Event& event) const {
LoggedBweLossBasedUpdate bwe_update;
RTC_CHECK(event.has_timestamp_us());
- bwe_update.timestamp_us = event.timestamp_us();
+ bwe_update.timestamp = Timestamp::Micros(event.timestamp_us());
RTC_PARSE_CHECK_OR_RETURN(loss_event.has_bitrate_bps());
bwe_update.bitrate_bps = loss_event.bitrate_bps();
RTC_PARSE_CHECK_OR_RETURN(loss_event.has_fraction_loss());
@@ -1847,7 +2014,7 @@ ParsedRtcEventLog::GetDelayBasedBweUpdate(const rtclog::Event& event) const {
LoggedBweDelayBasedUpdate res;
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
- res.timestamp_us = event.timestamp_us();
+ res.timestamp = Timestamp::Micros(event.timestamp_us());
RTC_PARSE_CHECK_OR_RETURN(delay_event.has_bitrate_bps());
res.bitrate_bps = delay_event.bitrate_bps();
RTC_PARSE_CHECK_OR_RETURN(delay_event.has_detector_state());
@@ -1866,7 +2033,7 @@ ParsedRtcEventLog::GetAudioNetworkAdaptation(const rtclog::Event& event) const {
LoggedAudioNetworkAdaptationEvent res;
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
- res.timestamp_us = event.timestamp_us();
+ res.timestamp = Timestamp::Micros(event.timestamp_us());
if (ana_event.has_bitrate_bps())
res.config.bitrate_bps = ana_event.bitrate_bps();
if (ana_event.has_enable_fec())
@@ -1892,7 +2059,7 @@ ParsedRtcEventLog::GetBweProbeClusterCreated(const rtclog::Event& event) const {
const rtclog::BweProbeCluster& pcc_event = event.probe_cluster();
LoggedBweProbeClusterCreatedEvent res;
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
- res.timestamp_us = event.timestamp_us();
+ res.timestamp = Timestamp::Micros(event.timestamp_us());
RTC_PARSE_CHECK_OR_RETURN(pcc_event.has_id());
res.id = pcc_event.id();
RTC_PARSE_CHECK_OR_RETURN(pcc_event.has_bitrate_bps());
@@ -1917,7 +2084,7 @@ ParsedRtcEventLog::GetBweProbeFailure(const rtclog::Event& event) const {
LoggedBweProbeFailureEvent res;
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
- res.timestamp_us = event.timestamp_us();
+ res.timestamp = Timestamp::Micros(event.timestamp_us());
RTC_PARSE_CHECK_OR_RETURN(pr_event.has_id());
res.id = pr_event.id();
RTC_PARSE_CHECK_OR_RETURN(pr_event.has_result());
@@ -1930,7 +2097,7 @@ ParsedRtcEventLog::GetBweProbeFailure(const rtclog::Event& event) const {
} else if (pr_event.result() == rtclog::BweProbeResult::TIMEOUT) {
res.failure_reason = ProbeFailureReason::kTimeout;
} else {
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
RTC_PARSE_CHECK_OR_RETURN(!pr_event.has_bitrate_bps());
@@ -1950,7 +2117,7 @@ ParsedRtcEventLog::GetBweProbeSuccess(const rtclog::Event& event) const {
LoggedBweProbeSuccessEvent res;
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
- res.timestamp_us = event.timestamp_us();
+ res.timestamp = Timestamp::Micros(event.timestamp_us());
RTC_PARSE_CHECK_OR_RETURN(pr_event.has_id());
res.id = pr_event.id();
RTC_PARSE_CHECK_OR_RETURN(pr_event.has_bitrate_bps());
@@ -1967,7 +2134,7 @@ ParsedRtcEventLog::GetAlrState(const rtclog::Event& event) const {
const rtclog::AlrState& alr_event = event.alr_state();
LoggedAlrStateEvent res;
RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
- res.timestamp_us = event.timestamp_us();
+ res.timestamp = Timestamp::Micros(event.timestamp_us());
RTC_PARSE_CHECK_OR_RETURN(alr_event.has_in_alr());
res.in_alr = alr_event.in_alr();
@@ -1983,8 +2150,8 @@ ParsedRtcEventLog::GetIceCandidatePairConfig(
LoggedIceCandidatePairConfig res;
const rtclog::IceCandidatePairConfig& config =
rtc_event.ice_candidate_pair_config();
- RTC_CHECK(rtc_event.has_timestamp_us());
- res.timestamp_us = rtc_event.timestamp_us();
+ RTC_PARSE_CHECK_OR_RETURN(rtc_event.has_timestamp_us());
+ res.timestamp = Timestamp::Micros(rtc_event.timestamp_us());
RTC_PARSE_CHECK_OR_RETURN(config.has_config_type());
res.type = GetRuntimeIceCandidatePairConfigType(config.config_type());
RTC_PARSE_CHECK_OR_RETURN(config.has_candidate_pair_id());
@@ -2022,8 +2189,8 @@ ParsedRtcEventLog::GetIceCandidatePairEvent(
LoggedIceCandidatePairEvent res;
const rtclog::IceCandidatePairEvent& event =
rtc_event.ice_candidate_pair_event();
- RTC_CHECK(rtc_event.has_timestamp_us());
- res.timestamp_us = rtc_event.timestamp_us();
+ RTC_PARSE_CHECK_OR_RETURN(rtc_event.has_timestamp_us());
+ res.timestamp = Timestamp::Micros(rtc_event.timestamp_us());
RTC_PARSE_CHECK_OR_RETURN(event.has_event_type());
res.type = GetRuntimeIceCandidatePairEventType(event.event_type());
RTC_PARSE_CHECK_OR_RETURN(event.has_candidate_pair_id());
@@ -2033,6 +2200,23 @@ ParsedRtcEventLog::GetIceCandidatePairEvent(
return res;
}
+ParsedRtcEventLog::ParseStatusOr<LoggedRemoteEstimateEvent>
+ParsedRtcEventLog::GetRemoteEstimateEvent(const rtclog::Event& event) const {
+ RTC_PARSE_CHECK_OR_RETURN(event.has_type());
+ RTC_PARSE_CHECK_OR_RETURN_EQ(event.type(), rtclog::Event::REMOTE_ESTIMATE);
+ LoggedRemoteEstimateEvent res;
+ const rtclog::RemoteEstimate& remote_estimate_event = event.remote_estimate();
+ RTC_PARSE_CHECK_OR_RETURN(event.has_timestamp_us());
+ res.timestamp = Timestamp::Micros(event.timestamp_us());
+ if (remote_estimate_event.has_link_capacity_lower_kbps())
+ res.link_capacity_lower = DataRate::KilobitsPerSec(
+ remote_estimate_event.link_capacity_lower_kbps());
+ if (remote_estimate_event.has_link_capacity_upper_kbps())
+ res.link_capacity_upper = DataRate::KilobitsPerSec(
+ remote_estimate_event.link_capacity_upper_kbps());
+ return res;
+}
+
// Returns the MediaType for registered SSRCs. Search from the end to use last
// registered types first.
ParsedRtcEventLog::MediaType ParsedRtcEventLog::GetMediaType(
@@ -2120,12 +2304,12 @@ std::vector<LoggedPacketInfo> ParsedRtcEventLog::GetPacketInfos(
seq_num_unwrapper = SequenceNumberUnwrapper();
indices.clear();
}
- RTC_DCHECK(new_log_time >= last_log_time);
+ RTC_DCHECK_GE(new_log_time, last_log_time);
last_log_time = new_log_time;
};
auto rtp_handler = [&](const LoggedRtpPacket& rtp) {
- advance_time(Timestamp::Millis(rtp.log_time_ms()));
+ advance_time(rtp.log_time());
MediaStreamInfo* stream = &streams[rtp.header.ssrc];
Timestamp capture_time = Timestamp::MinusInfinity();
if (!stream->rtx) {
@@ -2133,9 +2317,9 @@ std::vector<LoggedPacketInfo> ParsedRtcEventLog::GetPacketInfos(
// RTX streams don't have a unique clock offset and frequency, so
// the RTP timstamps can't be unwrapped.
- // Add an offset to avoid |capture_ticks| to become negative in the case
+ // Add an offset to avoid `capture_ticks` to become negative in the case
// of reordering.
- constexpr int64_t kStartingCaptureTimeTicks = 90 * 48 * 1000;
+ constexpr int64_t kStartingCaptureTimeTicks = 90 * 48 * 10000;
int64_t capture_ticks =
kStartingCaptureTimeTicks +
stream->unwrap_capture_ticks.Unwrap(rtp.header.timestamp);
@@ -2164,23 +2348,22 @@ std::vector<LoggedPacketInfo> ParsedRtcEventLog::GetPacketInfos(
};
Timestamp feedback_base_time = Timestamp::MinusInfinity();
- absl::optional<int64_t> last_feedback_base_time_us;
+ Timestamp last_feedback_base_time = Timestamp::MinusInfinity();
auto feedback_handler =
[&](const LoggedRtcpPacketTransportFeedback& logged_rtcp) {
- auto log_feedback_time = Timestamp::Millis(logged_rtcp.log_time_ms());
+ auto log_feedback_time = logged_rtcp.log_time();
advance_time(log_feedback_time);
const auto& feedback = logged_rtcp.transport_feedback;
// Add timestamp deltas to a local time base selected on first packet
// arrival. This won't be the true time base, but makes it easier to
// manually inspect time stamps.
- if (!last_feedback_base_time_us) {
+ if (!last_feedback_base_time.IsFinite()) {
feedback_base_time = log_feedback_time;
} else {
- feedback_base_time += TimeDelta::Micros(
- feedback.GetBaseDeltaUs(*last_feedback_base_time_us));
+ feedback_base_time += feedback.GetBaseDelta(last_feedback_base_time);
}
- last_feedback_base_time_us = feedback.GetBaseTimeUs();
+ last_feedback_base_time = feedback.BaseTime();
std::vector<LoggedPacketInfo*> packet_feedbacks;
packet_feedbacks.reserve(feedback.GetAllPackets().size());
@@ -2202,10 +2385,9 @@ std::vector<LoggedPacketInfo> ParsedRtcEventLog::GetPacketInfos(
continue;
}
if (packet.received()) {
- receive_timestamp += TimeDelta::Micros(packet.delta_us());
+ receive_timestamp += packet.delta();
if (sent->reported_recv_time.IsInfinite()) {
- sent->reported_recv_time =
- Timestamp::Millis(receive_timestamp.ms());
+ sent->reported_recv_time = receive_timestamp;
sent->log_feedback_time = log_feedback_time;
}
} else {
@@ -2228,8 +2410,11 @@ std::vector<LoggedPacketInfo> ParsedRtcEventLog::GetPacketInfos(
last->last_in_feedback = true;
for (LoggedPacketInfo* fb : packet_feedbacks) {
if (direction == PacketDirection::kOutgoingPacket) {
- fb->feedback_hold_duration =
- last->reported_recv_time - fb->reported_recv_time;
+ if (last->reported_recv_time.IsFinite() &&
+ fb->reported_recv_time.IsFinite()) {
+ fb->feedback_hold_duration =
+ last->reported_recv_time - fb->reported_recv_time;
+ }
} else {
fb->feedback_hold_duration =
log_feedback_time - fb->log_packet_time;
@@ -2337,7 +2522,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreParsedNewFormatEvent(
stream.video_send_stream_configs_size() +
stream.generic_packets_sent_size() +
stream.generic_packets_received_size() +
- stream.generic_acks_received_size(),
+ stream.generic_acks_received_size() +
+ stream.frame_decoded_events_size(),
1u);
if (stream.incoming_rtp_packets_size() == 1) {
@@ -2395,8 +2581,10 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreParsedNewFormatEvent(
return StoreGenericPacketSentEvent(stream.generic_packets_sent(0));
} else if (stream.generic_acks_received_size() == 1) {
return StoreGenericAckReceivedEvent(stream.generic_acks_received(0));
+ } else if (stream.frame_decoded_events_size() == 1) {
+ return StoreFrameDecodedEvents(stream.frame_decoded_events(0));
} else {
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
return ParseStatus::Success();
}
}
@@ -2406,7 +2594,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreAlrStateEvent(
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
RTC_PARSE_CHECK_OR_RETURN(proto.has_in_alr());
LoggedAlrStateEvent alr_event;
- alr_event.timestamp_us = proto.timestamp_ms() * 1000;
+ alr_event.timestamp = Timestamp::Millis(proto.timestamp_ms());
alr_event.in_alr = proto.in_alr();
alr_state_events_.push_back(alr_event);
@@ -2420,7 +2608,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreRouteChangeEvent(
RTC_PARSE_CHECK_OR_RETURN(proto.has_connected());
RTC_PARSE_CHECK_OR_RETURN(proto.has_overhead());
LoggedRouteChangeEvent route_event;
- route_event.timestamp_ms = proto.timestamp_ms();
+ route_event.timestamp = Timestamp::Millis(proto.timestamp_ms());
route_event.connected = proto.connected();
route_event.overhead = proto.overhead();
@@ -2434,7 +2622,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreRemoteEstimateEvent(
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
// Base event
LoggedRemoteEstimateEvent base_event;
- base_event.timestamp_ms = proto.timestamp_ms();
+ base_event.timestamp = Timestamp::Millis(proto.timestamp_ms());
absl::optional<uint64_t> base_link_capacity_lower_kbps;
if (proto.has_link_capacity_lower_kbps()) {
@@ -2478,11 +2666,11 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreRemoteEstimateEvent(
RTC_PARSE_CHECK_OR_RETURN_EQ(link_capacity_upper_kbps_values.size(),
number_of_deltas);
- // Delta decoding
+ // Populate events from decoded deltas
for (size_t i = 0; i < number_of_deltas; ++i) {
LoggedRemoteEstimateEvent event;
RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
- event.timestamp_ms = *timestamp_ms_values[i];
+ event.timestamp = Timestamp::Millis(*timestamp_ms_values[i]);
if (link_capacity_lower_kbps_values[i])
event.link_capacity_lower =
DataRate::KilobitsPerSec(*link_capacity_lower_kbps_values[i]);
@@ -2500,9 +2688,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreAudioPlayoutEvent(
RTC_PARSE_CHECK_OR_RETURN(proto.has_local_ssrc());
// Base event
- auto map_it = audio_playout_events_[proto.local_ssrc()];
audio_playout_events_[proto.local_ssrc()].emplace_back(
- 1000 * proto.timestamp_ms(), proto.local_ssrc());
+ Timestamp::Millis(proto.timestamp_ms()), proto.local_ssrc());
const size_t number_of_deltas =
proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
@@ -2521,7 +2708,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreAudioPlayoutEvent(
proto.local_ssrc_deltas(), proto.local_ssrc(), number_of_deltas);
RTC_PARSE_CHECK_OR_RETURN_EQ(local_ssrc_values.size(), number_of_deltas);
- // Delta decoding
+ // Populate events from decoded deltas
for (size_t i = 0; i < number_of_deltas; ++i) {
RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
RTC_PARSE_CHECK_OR_RETURN(local_ssrc_values[i].has_value());
@@ -2534,8 +2721,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreAudioPlayoutEvent(
const uint32_t local_ssrc =
static_cast<uint32_t>(local_ssrc_values[i].value());
- audio_playout_events_[local_ssrc].emplace_back(1000 * timestamp_ms,
- local_ssrc);
+ audio_playout_events_[local_ssrc].emplace_back(
+ Timestamp::Millis(timestamp_ms), local_ssrc);
}
return ParseStatus::Success();
}
@@ -2568,8 +2755,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreStartEvent(
RTC_PARSE_CHECK_OR_RETURN(proto.has_version());
RTC_PARSE_CHECK_OR_RETURN(proto.has_utc_time_ms());
RTC_PARSE_CHECK_OR_RETURN_EQ(proto.version(), 2);
- LoggedStartEvent start_event(proto.timestamp_ms() * 1000,
- proto.utc_time_ms());
+ LoggedStartEvent start_event(Timestamp::Millis(proto.timestamp_ms()),
+ Timestamp::Millis(proto.utc_time_ms()));
start_log_events_.push_back(start_event);
return ParseStatus::Success();
@@ -2578,7 +2765,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreStartEvent(
ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreStopEvent(
const rtclog2::EndLogEvent& proto) {
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
- LoggedStopEvent stop_event(proto.timestamp_ms() * 1000);
+ LoggedStopEvent stop_event(Timestamp::Millis(proto.timestamp_ms()));
stop_log_events_.push_back(stop_event);
return ParseStatus::Success();
@@ -2592,7 +2779,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweLossBasedUpdate(
RTC_PARSE_CHECK_OR_RETURN(proto.has_total_packets());
// Base event
- bwe_loss_updates_.emplace_back(1000 * proto.timestamp_ms(),
+ bwe_loss_updates_.emplace_back(Timestamp::Millis(proto.timestamp_ms()),
proto.bitrate_bps(), proto.fraction_loss(),
proto.total_packets());
@@ -2623,7 +2810,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweLossBasedUpdate(
proto.total_packets_deltas(), proto.total_packets(), number_of_deltas);
RTC_PARSE_CHECK_OR_RETURN_EQ(total_packets_values.size(), number_of_deltas);
- // Delta decoding
+ // Populate events from decoded deltas
for (size_t i = 0; i < number_of_deltas; ++i) {
RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
int64_t timestamp_ms;
@@ -2648,7 +2835,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweLossBasedUpdate(
const uint32_t total_packets =
static_cast<uint32_t>(total_packets_values[i].value());
- bwe_loss_updates_.emplace_back(1000 * timestamp_ms, bitrate_bps,
+ bwe_loss_updates_.emplace_back(Timestamp::Millis(timestamp_ms), bitrate_bps,
fraction_loss, total_packets);
}
return ParseStatus::Success();
@@ -2663,7 +2850,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweDelayBasedUpdate(
// Base event
const BandwidthUsage base_detector_state =
GetRuntimeDetectorState(proto.detector_state());
- bwe_delay_updates_.emplace_back(1000 * proto.timestamp_ms(),
+ bwe_delay_updates_.emplace_back(Timestamp::Millis(proto.timestamp_ms()),
proto.bitrate_bps(), base_detector_state);
const size_t number_of_deltas =
@@ -2689,7 +2876,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweDelayBasedUpdate(
static_cast<uint64_t>(proto.detector_state()), number_of_deltas);
RTC_PARSE_CHECK_OR_RETURN_EQ(detector_state_values.size(), number_of_deltas);
- // Delta decoding
+ // Populate events from decoded deltas
for (size_t i = 0; i < number_of_deltas; ++i) {
RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
int64_t timestamp_ms;
@@ -2707,7 +2894,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweDelayBasedUpdate(
static_cast<rtclog2::DelayBasedBweUpdates::DetectorState>(
detector_state_values[i].value());
- bwe_delay_updates_.emplace_back(1000 * timestamp_ms, bitrate_bps,
+ bwe_delay_updates_.emplace_back(Timestamp::Millis(timestamp_ms),
+ bitrate_bps,
GetRuntimeDetectorState(detector_state));
}
return ParseStatus::Success();
@@ -2717,7 +2905,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweProbeClusterCreated(
const rtclog2::BweProbeCluster& proto) {
LoggedBweProbeClusterCreatedEvent probe_cluster;
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
- probe_cluster.timestamp_us = proto.timestamp_ms() * 1000;
+ probe_cluster.timestamp = Timestamp::Millis(proto.timestamp_ms());
RTC_PARSE_CHECK_OR_RETURN(proto.has_id());
probe_cluster.id = proto.id();
RTC_PARSE_CHECK_OR_RETURN(proto.has_bitrate_bps());
@@ -2737,7 +2925,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweProbeSuccessEvent(
const rtclog2::BweProbeResultSuccess& proto) {
LoggedBweProbeSuccessEvent probe_result;
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
- probe_result.timestamp_us = proto.timestamp_ms() * 1000;
+ probe_result.timestamp = Timestamp::Millis(proto.timestamp_ms());
RTC_PARSE_CHECK_OR_RETURN(proto.has_id());
probe_result.id = proto.id();
RTC_PARSE_CHECK_OR_RETURN(proto.has_bitrate_bps());
@@ -2753,7 +2941,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweProbeFailureEvent(
const rtclog2::BweProbeResultFailure& proto) {
LoggedBweProbeFailureEvent probe_result;
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
- probe_result.timestamp_us = proto.timestamp_ms() * 1000;
+ probe_result.timestamp = Timestamp::Millis(proto.timestamp_ms());
RTC_PARSE_CHECK_OR_RETURN(proto.has_id());
probe_result.id = proto.id();
RTC_PARSE_CHECK_OR_RETURN(proto.has_failure());
@@ -2765,6 +2953,113 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreBweProbeFailureEvent(
return ParseStatus::Success();
}
+ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreFrameDecodedEvents(
+ const rtclog2::FrameDecodedEvents& proto) {
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_ssrc());
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_render_time_ms());
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_width());
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_height());
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_codec());
+ RTC_PARSE_CHECK_OR_RETURN(proto.has_qp());
+
+ LoggedFrameDecoded base_frame;
+ base_frame.timestamp = Timestamp::Millis(proto.timestamp_ms());
+ base_frame.ssrc = proto.ssrc();
+ base_frame.render_time_ms = proto.render_time_ms();
+ base_frame.width = proto.width();
+ base_frame.height = proto.height();
+ base_frame.codec = GetRuntimeCodecType(proto.codec());
+ RTC_PARSE_CHECK_OR_RETURN_GE(proto.qp(), 0);
+ RTC_PARSE_CHECK_OR_RETURN_LE(proto.qp(), 255);
+ base_frame.qp = static_cast<uint8_t>(proto.qp());
+
+ decoded_frames_[base_frame.ssrc].push_back(base_frame);
+
+ const size_t number_of_deltas =
+ proto.has_number_of_deltas() ? proto.number_of_deltas() : 0u;
+ if (number_of_deltas == 0) {
+ return ParseStatus::Success();
+ }
+
+ // timestamp_ms
+ std::vector<absl::optional<uint64_t>> timestamp_ms_values =
+ DecodeDeltas(proto.timestamp_ms_deltas(),
+ ToUnsigned(proto.timestamp_ms()), number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(timestamp_ms_values.size(), number_of_deltas);
+
+ // SSRC
+ std::vector<absl::optional<uint64_t>> ssrc_values =
+ DecodeDeltas(proto.ssrc_deltas(), proto.ssrc(), number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(ssrc_values.size(), number_of_deltas);
+
+ // render_time_ms
+ std::vector<absl::optional<uint64_t>> render_time_ms_values =
+ DecodeDeltas(proto.render_time_ms_deltas(),
+ ToUnsigned(proto.render_time_ms()), number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(render_time_ms_values.size(), number_of_deltas);
+
+ // width
+ std::vector<absl::optional<uint64_t>> width_values = DecodeDeltas(
+ proto.width_deltas(), ToUnsigned(proto.width()), number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(width_values.size(), number_of_deltas);
+
+ // height
+ std::vector<absl::optional<uint64_t>> height_values = DecodeDeltas(
+ proto.height_deltas(), ToUnsigned(proto.height()), number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(height_values.size(), number_of_deltas);
+
+ // codec
+ std::vector<absl::optional<uint64_t>> codec_values =
+ DecodeDeltas(proto.codec_deltas(), static_cast<uint64_t>(proto.codec()),
+ number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(codec_values.size(), number_of_deltas);
+
+ // qp
+ std::vector<absl::optional<uint64_t>> qp_values =
+ DecodeDeltas(proto.qp_deltas(), proto.qp(), number_of_deltas);
+ RTC_PARSE_CHECK_OR_RETURN_EQ(qp_values.size(), number_of_deltas);
+
+ // Populate events from decoded deltas
+ for (size_t i = 0; i < number_of_deltas; ++i) {
+ LoggedFrameDecoded frame;
+ int64_t timestamp_ms;
+ RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
+ RTC_PARSE_CHECK_OR_RETURN(
+ ToSigned(timestamp_ms_values[i].value(), &timestamp_ms));
+ frame.timestamp = Timestamp::Millis(timestamp_ms);
+
+ RTC_PARSE_CHECK_OR_RETURN(ssrc_values[i].has_value());
+ RTC_PARSE_CHECK_OR_RETURN_LE(ssrc_values[i].value(),
+ std::numeric_limits<uint32_t>::max());
+ frame.ssrc = static_cast<uint32_t>(ssrc_values[i].value());
+
+ RTC_PARSE_CHECK_OR_RETURN(render_time_ms_values[i].has_value());
+ RTC_PARSE_CHECK_OR_RETURN(
+ ToSigned(render_time_ms_values[i].value(), &frame.render_time_ms));
+
+ RTC_PARSE_CHECK_OR_RETURN(width_values[i].has_value());
+ RTC_PARSE_CHECK_OR_RETURN(ToSigned(width_values[i].value(), &frame.width));
+
+ RTC_PARSE_CHECK_OR_RETURN(height_values[i].has_value());
+ RTC_PARSE_CHECK_OR_RETURN(
+ ToSigned(height_values[i].value(), &frame.height));
+
+ RTC_PARSE_CHECK_OR_RETURN(codec_values[i].has_value());
+ frame.codec =
+ GetRuntimeCodecType(static_cast<rtclog2::FrameDecodedEvents::Codec>(
+ codec_values[i].value()));
+
+ RTC_PARSE_CHECK_OR_RETURN(qp_values[i].has_value());
+ RTC_PARSE_CHECK_OR_RETURN_LE(qp_values[i].value(),
+ std::numeric_limits<uint8_t>::max());
+ frame.qp = static_cast<uint8_t>(qp_values[i].value());
+
+ decoded_frames_[frame.ssrc].push_back(frame);
+ }
+ return ParseStatus::Success();
+}
+
ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreGenericAckReceivedEvent(
const rtclog2::GenericAckReceived& proto) {
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
@@ -2777,7 +3072,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreGenericAckReceivedEvent(
base_receive_acked_packet_time_ms = proto.receive_acked_packet_time_ms();
}
generic_acks_received_.push_back(
- {proto.timestamp_ms() * 1000, proto.packet_number(),
+ {Timestamp::Millis(proto.timestamp_ms()), proto.packet_number(),
proto.acked_packet_number(), base_receive_acked_packet_time_ms});
const size_t number_of_deltas =
@@ -2836,8 +3131,8 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreGenericAckReceivedEvent(
ToSigned(receive_acked_packet_time_ms_values[i].value(), &value));
receive_acked_packet_time_ms = value;
}
- generic_acks_received_.push_back({timestamp_ms * 1000, packet_number,
- acked_packet_number,
+ generic_acks_received_.push_back({Timestamp::Millis(timestamp_ms),
+ packet_number, acked_packet_number,
receive_acked_packet_time_ms});
}
return ParseStatus::Success();
@@ -2854,7 +3149,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreGenericPacketSentEvent(
RTC_PARSE_CHECK_OR_RETURN(proto.has_padding_length());
generic_packets_sent_.push_back(
- {proto.timestamp_ms() * 1000, proto.packet_number(),
+ {Timestamp::Millis(proto.timestamp_ms()), proto.packet_number(),
static_cast<size_t>(proto.overhead_length()),
static_cast<size_t>(proto.payload_length()),
static_cast<size_t>(proto.padding_length())});
@@ -2882,14 +3177,12 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreGenericPacketSentEvent(
number_of_deltas);
RTC_PARSE_CHECK_OR_RETURN_EQ(overhead_length_values.size(), number_of_deltas);
- std::vector<absl::optional<uint64_t>> payload_length_values =
- DecodeDeltas(proto.payload_length_deltas(),
- ToUnsigned(proto.payload_length()), number_of_deltas);
+ std::vector<absl::optional<uint64_t>> payload_length_values = DecodeDeltas(
+ proto.payload_length_deltas(), proto.payload_length(), number_of_deltas);
RTC_PARSE_CHECK_OR_RETURN_EQ(payload_length_values.size(), number_of_deltas);
- std::vector<absl::optional<uint64_t>> padding_length_values =
- DecodeDeltas(proto.padding_length_deltas(),
- ToUnsigned(proto.padding_length()), number_of_deltas);
+ std::vector<absl::optional<uint64_t>> padding_length_values = DecodeDeltas(
+ proto.padding_length_deltas(), proto.padding_length(), number_of_deltas);
RTC_PARSE_CHECK_OR_RETURN_EQ(padding_length_values.size(), number_of_deltas);
for (size_t i = 0; i < number_of_deltas; i++) {
@@ -2903,7 +3196,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreGenericPacketSentEvent(
RTC_PARSE_CHECK_OR_RETURN(payload_length_values[i].has_value());
RTC_PARSE_CHECK_OR_RETURN(padding_length_values[i].has_value());
generic_packets_sent_.push_back(
- {timestamp_ms * 1000, packet_number,
+ {Timestamp::Millis(timestamp_ms), packet_number,
static_cast<size_t>(overhead_length_values[i].value()),
static_cast<size_t>(payload_length_values[i].value()),
static_cast<size_t>(padding_length_values[i].value())});
@@ -2920,7 +3213,7 @@ ParsedRtcEventLog::StoreGenericPacketReceivedEvent(
RTC_PARSE_CHECK_OR_RETURN(proto.has_packet_number());
RTC_PARSE_CHECK_OR_RETURN(proto.has_packet_length());
- generic_packets_received_.push_back({proto.timestamp_ms() * 1000,
+ generic_packets_received_.push_back({Timestamp::Millis(proto.timestamp_ms()),
proto.packet_number(),
proto.packet_length()});
@@ -2953,11 +3246,12 @@ ParsedRtcEventLog::StoreGenericPacketReceivedEvent(
int64_t packet_number;
RTC_PARSE_CHECK_OR_RETURN(
ToSigned(packet_number_values[i].value(), &packet_number));
- int32_t packet_length;
- RTC_PARSE_CHECK_OR_RETURN(
- ToSigned(packet_length_values[i].value(), &packet_length));
+ RTC_PARSE_CHECK_OR_RETURN_LE(packet_length_values[i].value(),
+ std::numeric_limits<int32_t>::max());
+ int32_t packet_length =
+ static_cast<int32_t>(packet_length_values[i].value());
generic_packets_received_.push_back(
- {timestamp_ms * 1000, packet_number, packet_length});
+ {Timestamp::Millis(timestamp_ms), packet_number, packet_length});
}
return ParseStatus::Success();
}
@@ -2989,11 +3283,11 @@ ParsedRtcEventLog::StoreAudioNetworkAdaptationEvent(
runtime_config.enable_dtx = proto.enable_dtx();
}
if (proto.has_num_channels()) {
- // Note: Encoding N as N-1 only done for |num_channels_deltas|.
+ // Note: Encoding N as N-1 only done for `num_channels_deltas`.
runtime_config.num_channels = proto.num_channels();
}
- audio_network_adaptation_events_.emplace_back(1000 * proto.timestamp_ms(),
- runtime_config);
+ audio_network_adaptation_events_.emplace_back(
+ Timestamp::Millis(proto.timestamp_ms()), runtime_config);
}
const size_t number_of_deltas =
@@ -3074,7 +3368,7 @@ ParsedRtcEventLog::StoreAudioNetworkAdaptationEvent(
}
RTC_PARSE_CHECK_OR_RETURN_EQ(num_channels_values.size(), number_of_deltas);
- // Delta decoding
+ // Populate events from decoded deltas
for (size_t i = 0; i < number_of_deltas; ++i) {
RTC_PARSE_CHECK_OR_RETURN(timestamp_ms_values[i].has_value());
int64_t timestamp_ms;
@@ -3095,12 +3389,12 @@ ParsedRtcEventLog::StoreAudioNetworkAdaptationEvent(
runtime_config.frame_length_ms = signed_frame_length_ms;
}
if (uplink_packet_loss_fraction_values[i].has_value()) {
- float uplink_packet_loss_fraction;
+ float uplink_packet_loss_fraction2;
RTC_PARSE_CHECK_OR_RETURN(ParsePacketLossFractionFromProtoFormat(
rtc::checked_cast<uint32_t>(
uplink_packet_loss_fraction_values[i].value()),
- &uplink_packet_loss_fraction));
- runtime_config.uplink_packet_loss_fraction = uplink_packet_loss_fraction;
+ &uplink_packet_loss_fraction2));
+ runtime_config.uplink_packet_loss_fraction = uplink_packet_loss_fraction2;
}
if (enable_fec_values[i].has_value()) {
runtime_config.enable_fec =
@@ -3114,8 +3408,8 @@ ParsedRtcEventLog::StoreAudioNetworkAdaptationEvent(
runtime_config.num_channels =
rtc::checked_cast<size_t>(num_channels_values[i].value());
}
- audio_network_adaptation_events_.emplace_back(1000 * timestamp_ms,
- runtime_config);
+ audio_network_adaptation_events_.emplace_back(
+ Timestamp::Millis(timestamp_ms), runtime_config);
}
return ParseStatus::Success();
}
@@ -3124,7 +3418,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreDtlsTransportState(
const rtclog2::DtlsTransportStateEvent& proto) {
LoggedDtlsTransportState dtls_state;
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
- dtls_state.timestamp_us = proto.timestamp_ms() * 1000;
+ dtls_state.timestamp = Timestamp::Millis(proto.timestamp_ms());
RTC_PARSE_CHECK_OR_RETURN(proto.has_dtls_transport_state());
dtls_state.dtls_transport_state =
@@ -3138,7 +3432,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreDtlsWritableState(
const rtclog2::DtlsWritableState& proto) {
LoggedDtlsWritableState dtls_writable_state;
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
- dtls_writable_state.timestamp_us = proto.timestamp_ms() * 1000;
+ dtls_writable_state.timestamp = Timestamp::Millis(proto.timestamp_ms());
RTC_PARSE_CHECK_OR_RETURN(proto.has_writable());
dtls_writable_state.writable = proto.writable();
@@ -3150,7 +3444,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreIceCandidatePairConfig(
const rtclog2::IceCandidatePairConfig& proto) {
LoggedIceCandidatePairConfig ice_config;
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
- ice_config.timestamp_us = proto.timestamp_ms() * 1000;
+ ice_config.timestamp = Timestamp::Millis(proto.timestamp_ms());
RTC_PARSE_CHECK_OR_RETURN(proto.has_config_type());
ice_config.type = GetRuntimeIceCandidatePairConfigType(proto.config_type());
@@ -3188,7 +3482,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreIceCandidateEvent(
const rtclog2::IceCandidatePairEvent& proto) {
LoggedIceCandidatePairEvent ice_event;
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
- ice_event.timestamp_us = proto.timestamp_ms() * 1000;
+ ice_event.timestamp = Timestamp::Millis(proto.timestamp_ms());
RTC_PARSE_CHECK_OR_RETURN(proto.has_event_type());
ice_event.type = GetRuntimeIceCandidatePairEventType(proto.event_type());
RTC_PARSE_CHECK_OR_RETURN(proto.has_candidate_pair_id());
@@ -3208,7 +3502,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreVideoRecvConfig(
const rtclog2::VideoRecvStreamConfig& proto) {
LoggedVideoRecvConfig stream;
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
- stream.timestamp_us = proto.timestamp_ms() * 1000;
+ stream.timestamp = Timestamp::Millis(proto.timestamp_ms());
RTC_PARSE_CHECK_OR_RETURN(proto.has_remote_ssrc());
stream.config.remote_ssrc = proto.remote_ssrc();
RTC_PARSE_CHECK_OR_RETURN(proto.has_local_ssrc());
@@ -3228,7 +3522,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreVideoSendConfig(
const rtclog2::VideoSendStreamConfig& proto) {
LoggedVideoSendConfig stream;
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
- stream.timestamp_us = proto.timestamp_ms() * 1000;
+ stream.timestamp = Timestamp::Millis(proto.timestamp_ms());
RTC_PARSE_CHECK_OR_RETURN(proto.has_ssrc());
stream.config.local_ssrc = proto.ssrc();
if (proto.has_rtx_ssrc()) {
@@ -3246,7 +3540,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreAudioRecvConfig(
const rtclog2::AudioRecvStreamConfig& proto) {
LoggedAudioRecvConfig stream;
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
- stream.timestamp_us = proto.timestamp_ms() * 1000;
+ stream.timestamp = Timestamp::Millis(proto.timestamp_ms());
RTC_PARSE_CHECK_OR_RETURN(proto.has_remote_ssrc());
stream.config.remote_ssrc = proto.remote_ssrc();
RTC_PARSE_CHECK_OR_RETURN(proto.has_local_ssrc());
@@ -3263,7 +3557,7 @@ ParsedRtcEventLog::ParseStatus ParsedRtcEventLog::StoreAudioSendConfig(
const rtclog2::AudioSendStreamConfig& proto) {
LoggedAudioSendConfig stream;
RTC_PARSE_CHECK_OR_RETURN(proto.has_timestamp_ms());
- stream.timestamp_us = proto.timestamp_ms() * 1000;
+ stream.timestamp = Timestamp::Millis(proto.timestamp_ms());
RTC_PARSE_CHECK_OR_RETURN(proto.has_ssrc());
stream.config.local_ssrc = proto.ssrc();
if (proto.has_header_extensions()) {
diff --git a/logging/rtc_event_log/rtc_event_log_parser.h b/logging/rtc_event_log/rtc_event_log_parser.h
index 8d3351e815..ae2d4fe586 100644
--- a/logging/rtc_event_log/rtc_event_log_parser.h
+++ b/logging/rtc_event_log/rtc_event_log_parser.h
@@ -14,15 +14,43 @@
#include <limits>
#include <map>
#include <set>
-#include <sstream> // no-presubmit-check TODO(webrtc:8982)
#include <string>
-#include <utility> // pair
#include <vector>
+#include "absl/base/attributes.h"
+#include "absl/strings/string_view.h"
#include "api/rtc_event_log/rtc_event_log.h"
#include "call/video_receive_stream.h"
#include "call/video_send_stream.h"
-#include "logging/rtc_event_log/logged_events.h"
+#include "logging/rtc_event_log/events/logged_rtp_rtcp.h"
+#include "logging/rtc_event_log/events/rtc_event_alr_state.h"
+#include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
+#include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
+#include "logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h"
+#include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
+#include "logging/rtc_event_log/events/rtc_event_begin_log.h"
+#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
+#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
+#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
+#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
+#include "logging/rtc_event_log/events/rtc_event_end_log.h"
+#include "logging/rtc_event_log/events/rtc_event_frame_decoded.h"
+#include "logging/rtc_event_log/events/rtc_event_generic_ack_received.h"
+#include "logging/rtc_event_log/events/rtc_event_generic_packet_received.h"
+#include "logging/rtc_event_log/events/rtc_event_generic_packet_sent.h"
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair.h"
+#include "logging/rtc_event_log/events/rtc_event_ice_candidate_pair_config.h"
+#include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
+#include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
+#include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
+#include "logging/rtc_event_log/events/rtc_event_remote_estimate.h"
+#include "logging/rtc_event_log/events/rtc_event_route_change.h"
+#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h"
+#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h"
+#include "logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h"
+#include "logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h"
+#include "logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h"
+#include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
#include "rtc_base/ignore_wundef.h"
@@ -42,144 +70,182 @@ namespace webrtc {
enum PacketDirection { kIncomingPacket = 0, kOutgoingPacket };
-template <typename T>
-class PacketView;
+enum class LoggedMediaType : uint8_t { kUnknown, kAudio, kVideo };
+
+struct LoggedPacketInfo {
+ LoggedPacketInfo(const LoggedRtpPacket& rtp,
+ LoggedMediaType media_type,
+ bool rtx,
+ Timestamp capture_time);
+ LoggedPacketInfo(const LoggedPacketInfo&);
+ ~LoggedPacketInfo();
+ int64_t log_time_ms() const { return log_packet_time.ms(); }
+ int64_t log_time_us() const { return log_packet_time.us(); }
+ uint32_t ssrc;
+ uint16_t stream_seq_no;
+ uint16_t size;
+ uint16_t payload_size;
+ uint16_t padding_size;
+ uint16_t overhead = 0;
+ uint8_t payload_type;
+ LoggedMediaType media_type = LoggedMediaType::kUnknown;
+ bool rtx = false;
+ bool marker_bit = false;
+ bool has_transport_seq_no = false;
+ bool last_in_feedback = false;
+ uint16_t transport_seq_no = 0;
+ // The RTP header timestamp unwrapped and converted from tick count to seconds
+ // based timestamp.
+ Timestamp capture_time;
+ // The time the packet was logged. This is the receive time for incoming
+ // packets and send time for outgoing.
+ Timestamp log_packet_time;
+ // Send time as reported by abs-send-time extension, For outgoing packets this
+ // corresponds to log_packet_time, but might be measured using another clock.
+ Timestamp reported_send_time;
+ // The receive time that was reported in feedback. For incoming packets this
+ // corresponds to log_packet_time, but might be measured using another clock.
+ // PlusInfinity indicates that the packet was lost.
+ Timestamp reported_recv_time = Timestamp::MinusInfinity();
+ // The time feedback message was logged. This is the feedback send time for
+ // incoming packets and feedback receive time for outgoing.
+ // PlusInfinity indicates that feedback was expected but not received.
+ Timestamp log_feedback_time = Timestamp::MinusInfinity();
+ // The delay betweeen receiving an RTP packet and sending feedback for
+ // incoming packets. For outgoing packets we don't know the feedback send
+ // time, and this is instead calculated as the difference in reported receive
+ // time between this packet and the last packet in the same feedback message.
+ TimeDelta feedback_hold_duration = TimeDelta::MinusInfinity();
+};
-template <typename T>
-class PacketIterator {
- friend class PacketView<T>;
+struct InferredRouteChangeEvent {
+ int64_t log_time_ms() const { return log_time.ms(); }
+ int64_t log_time_us() const { return log_time.us(); }
+ uint32_t route_id;
+ Timestamp log_time = Timestamp::MinusInfinity();
+ uint16_t send_overhead;
+ uint16_t return_overhead;
+};
- public:
- // Standard iterator traits.
- using difference_type = std::ptrdiff_t;
- using value_type = T;
- using pointer = T*;
- using reference = T&;
- using iterator_category = std::bidirectional_iterator_tag;
+enum class LoggedIceEventType {
+ kAdded,
+ kUpdated,
+ kDestroyed,
+ kSelected,
+ kCheckSent,
+ kCheckReceived,
+ kCheckResponseSent,
+ kCheckResponseReceived,
+};
- // The default-contructed iterator is meaningless, but is required by the
- // ForwardIterator concept.
- PacketIterator() : ptr_(nullptr), element_size_(0) {}
- PacketIterator(const PacketIterator& other)
- : ptr_(other.ptr_), element_size_(other.element_size_) {}
- PacketIterator(const PacketIterator&& other)
- : ptr_(other.ptr_), element_size_(other.element_size_) {}
- ~PacketIterator() = default;
+struct LoggedIceEvent {
+ uint32_t candidate_pair_id;
+ Timestamp log_time;
+ LoggedIceEventType event_type;
+};
- PacketIterator& operator=(const PacketIterator& other) {
- ptr_ = other.ptr_;
- element_size_ = other.element_size_;
- return *this;
- }
- PacketIterator& operator=(const PacketIterator&& other) {
- ptr_ = other.ptr_;
- element_size_ = other.element_size_;
- return *this;
- }
+// This class is used to process lists of LoggedRtpPacketIncoming
+// and LoggedRtpPacketOutgoing without duplicating the code.
+// TODO(terelius): Remove this class. Instead use e.g. a vector of pointers
+// to LoggedRtpPacket or templatize the surrounding code.
+template <typename T>
+class DereferencingVector {
+ public:
+ template <bool IsConst>
+ class DereferencingIterator {
+ public:
+ // Standard iterator traits.
+ using difference_type = std::ptrdiff_t;
+ using value_type = T;
+ using pointer = typename std::conditional_t<IsConst, const T*, T*>;
+ using reference = typename std::conditional_t<IsConst, const T&, T&>;
+ using iterator_category = std::bidirectional_iterator_tag;
+
+ using representation =
+ typename std::conditional_t<IsConst, const T* const*, T**>;
+
+ explicit DereferencingIterator(representation ptr) : ptr_(ptr) {}
+
+ DereferencingIterator(const DereferencingIterator& other)
+ : ptr_(other.ptr_) {}
+ DereferencingIterator(const DereferencingIterator&& other)
+ : ptr_(other.ptr_) {}
+ ~DereferencingIterator() = default;
+
+ DereferencingIterator& operator=(const DereferencingIterator& other) {
+ ptr_ = other.ptr_;
+ return *this;
+ }
+ DereferencingIterator& operator=(const DereferencingIterator&& other) {
+ ptr_ = other.ptr_;
+ return *this;
+ }
- bool operator==(const PacketIterator<T>& other) const {
- RTC_DCHECK_EQ(element_size_, other.element_size_);
- return ptr_ == other.ptr_;
- }
- bool operator!=(const PacketIterator<T>& other) const {
- RTC_DCHECK_EQ(element_size_, other.element_size_);
- return ptr_ != other.ptr_;
- }
+ bool operator==(const DereferencingIterator& other) const {
+ return ptr_ == other.ptr_;
+ }
+ bool operator!=(const DereferencingIterator& other) const {
+ return ptr_ != other.ptr_;
+ }
- PacketIterator& operator++() {
- ptr_ += element_size_;
- return *this;
- }
- PacketIterator& operator--() {
- ptr_ -= element_size_;
- return *this;
- }
- PacketIterator operator++(int) {
- PacketIterator iter_copy(ptr_, element_size_);
- ptr_ += element_size_;
- return iter_copy;
- }
- PacketIterator operator--(int) {
- PacketIterator iter_copy(ptr_, element_size_);
- ptr_ -= element_size_;
- return iter_copy;
- }
+ DereferencingIterator& operator++() {
+ ++ptr_;
+ return *this;
+ }
+ DereferencingIterator& operator--() {
+ --ptr_;
+ return *this;
+ }
+ DereferencingIterator operator++(int) {
+ DereferencingIterator iter_copy(ptr_);
+ ++ptr_;
+ return iter_copy;
+ }
+ DereferencingIterator operator--(int) {
+ DereferencingIterator iter_copy(ptr_);
+ --ptr_;
+ return iter_copy;
+ }
- T& operator*() { return *reinterpret_cast<T*>(ptr_); }
- const T& operator*() const { return *reinterpret_cast<const T*>(ptr_); }
+ template <bool _IsConst = IsConst>
+ std::enable_if_t<!_IsConst, reference> operator*() {
+ return **ptr_;
+ }
- T* operator->() { return reinterpret_cast<T*>(ptr_); }
- const T* operator->() const { return reinterpret_cast<const T*>(ptr_); }
+ template <bool _IsConst = IsConst>
+ std::enable_if_t<_IsConst, reference> operator*() const {
+ return **ptr_;
+ }
- private:
- PacketIterator(typename std::conditional<std::is_const<T>::value,
- const void*,
- void*>::type p,
- size_t s)
- : ptr_(reinterpret_cast<decltype(ptr_)>(p)), element_size_(s) {}
-
- typename std::conditional<std::is_const<T>::value, const char*, char*>::type
- ptr_;
- size_t element_size_;
-};
+ template <bool _IsConst = IsConst>
+ std::enable_if_t<!_IsConst, pointer> operator->() {
+ return *ptr_;
+ }
-// Suppose that we have a struct S where we are only interested in a specific
-// member M. Given an array of S, PacketView can be used to treat the array
-// as an array of M, without exposing the type S to surrounding code and without
-// accessing the member through a virtual function. In this case, we want to
-// have a common view for incoming and outgoing RtpPackets, hence the PacketView
-// name.
-// Note that constructing a PacketView bypasses the typesystem, so the caller
-// has to take extra care when constructing these objects. The implementation
-// also requires that the containing struct is standard-layout (e.g. POD).
-//
-// Usage example:
-// struct A {...};
-// struct B { A a; ...};
-// struct C { A a; ...};
-// size_t len = 10;
-// B* array1 = new B[len];
-// C* array2 = new C[len];
-//
-// PacketView<A> view1 = PacketView<A>::Create<B>(array1, len, offsetof(B, a));
-// PacketView<A> view2 = PacketView<A>::Create<C>(array2, len, offsetof(C, a));
-//
-// The following code works with either view1 or view2.
-// void f(PacketView<A> view)
-// for (A& a : view) {
-// DoSomething(a);
-// }
-template <typename T>
-class PacketView {
- public:
- template <typename U>
- static PacketView Create(U* ptr, size_t num_elements, size_t offset) {
- static_assert(std::is_standard_layout<U>::value,
- "PacketView can only be created for standard layout types.");
- static_assert(std::is_standard_layout<T>::value,
- "PacketView can only be created for standard layout types.");
- return PacketView(ptr, num_elements, offset, sizeof(U));
- }
+ template <bool _IsConst = IsConst>
+ std::enable_if_t<_IsConst, pointer> operator->() const {
+ return *ptr_;
+ }
+
+ private:
+ representation ptr_;
+ };
using value_type = T;
using reference = value_type&;
using const_reference = const value_type&;
- using iterator = PacketIterator<T>;
- using const_iterator = PacketIterator<const T>;
+ using iterator = DereferencingIterator<false>;
+ using const_iterator = DereferencingIterator<true>;
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
- iterator begin() { return iterator(data_, element_size_); }
- iterator end() {
- auto end_ptr = data_ + num_elements_ * element_size_;
- return iterator(end_ptr, element_size_);
- }
+ iterator begin() { return iterator(elems_.data()); }
+ iterator end() { return iterator(elems_.data() + elems_.size()); }
- const_iterator begin() const { return const_iterator(data_, element_size_); }
+ const_iterator begin() const { return const_iterator(elems_.data()); }
const_iterator end() const {
- auto end_ptr = data_ + num_elements_ * element_size_;
- return const_iterator(end_ptr, element_size_);
+ return const_iterator(elems_.data() + elems_.size());
}
reverse_iterator rbegin() { return reverse_iterator(end()); }
@@ -192,35 +258,27 @@ class PacketView {
return const_reverse_iterator(begin());
}
- size_t size() const { return num_elements_; }
+ size_t size() const { return elems_.size(); }
- bool empty() const { return num_elements_ == 0; }
+ bool empty() const { return elems_.empty(); }
T& operator[](size_t i) {
- auto elem_ptr = data_ + i * element_size_;
- return *reinterpret_cast<T*>(elem_ptr);
+ RTC_DCHECK_LT(i, elems_.size());
+ return *elems_[i];
}
const T& operator[](size_t i) const {
- auto elem_ptr = data_ + i * element_size_;
- return *reinterpret_cast<const T*>(elem_ptr);
+ RTC_DCHECK_LT(i, elems_.size());
+ return *elems_[i];
+ }
+
+ void push_back(T* elem) {
+ RTC_DCHECK(elem != nullptr);
+ elems_.push_back(elem);
}
private:
- PacketView(typename std::conditional<std::is_const<T>::value,
- const void*,
- void*>::type data,
- size_t num_elements,
- size_t offset,
- size_t element_size)
- : data_(reinterpret_cast<decltype(data_)>(data) + offset),
- num_elements_(num_elements),
- element_size_(element_size) {}
-
- typename std::conditional<std::is_const<T>::value, const char*, char*>::type
- data_;
- size_t num_elements_;
- size_t element_size_;
+ std::vector<T*> elems_;
};
// Conversion functions for version 2 of the wire format.
@@ -262,48 +320,11 @@ class ParsedRtcEventLog {
kDontParse,
kAttemptWebrtcDefaultConfig
};
- class ParseStatus {
- public:
- static ParseStatus Success() { return ParseStatus(); }
- static ParseStatus Error(std::string error, std::string file, int line) {
- return ParseStatus(error, file, line);
- }
-
- bool ok() const { return error_.empty() && file_.empty() && line_ == 0; }
- std::string message() const {
- return error_ + " failed at " + file_ + " line " + std::to_string(line_);
- }
- RTC_DEPRECATED operator bool() const { return ok(); }
-
- private:
- ParseStatus() : error_(), file_(), line_(0) {}
- ParseStatus(std::string error, std::string file, int line)
- : error_(error), file_(file), line_(line) {}
- std::string error_;
- std::string file_;
- int line_;
- };
+ using ParseStatus = RtcEventLogParseStatus;
template <typename T>
- class ParseStatusOr {
- public:
- ParseStatusOr(const ParseStatus& error) // NOLINT
- : status_(error), value_() {}
- ParseStatusOr(const T& value) // NOLINT
- : status_(ParseStatus::Success()), value_(value) {}
- bool ok() const { return status_.ok(); }
- const T& value() const& {
- RTC_DCHECK(status_.ok());
- return value_;
- }
- std::string message() const { return status_.message(); }
- const ParseStatus& status() const { return status_; }
-
- private:
- ParseStatus status_;
- T value_;
- };
+ using ParseStatusOr = RtcEventLogParseStatusOr<T>;
struct LoggedRtpStreamIncoming {
LoggedRtpStreamIncoming();
@@ -323,14 +344,12 @@ class ParsedRtcEventLog {
struct LoggedRtpStreamView {
LoggedRtpStreamView(uint32_t ssrc,
- const LoggedRtpPacketIncoming* ptr,
- size_t num_elements);
+ const std::vector<LoggedRtpPacketIncoming>& packets);
LoggedRtpStreamView(uint32_t ssrc,
- const LoggedRtpPacketOutgoing* ptr,
- size_t num_elements);
+ const std::vector<LoggedRtpPacketOutgoing>& packets);
LoggedRtpStreamView(const LoggedRtpStreamView&);
uint32_t ssrc;
- PacketView<const LoggedRtpPacket> packet_view;
+ DereferencingVector<const LoggedRtpPacket> packet_view;
};
class LogSegment {
@@ -361,14 +380,13 @@ class ParsedRtcEventLog {
void Clear();
// Reads an RtcEventLog file and returns success if parsing was successful.
- ParseStatus ParseFile(const std::string& file_name);
+ ParseStatus ParseFile(absl::string_view file_name);
// Reads an RtcEventLog from a string and returns success if successful.
- ParseStatus ParseString(const std::string& s);
+ ParseStatus ParseString(absl::string_view s);
- // Reads an RtcEventLog from an istream and returns success if successful.
- ParseStatus ParseStream(
- std::istream& stream); // no-presubmit-check TODO(webrtc:8982)
+ // Reads an RtcEventLog from an string and returns success if successful.
+ ParseStatus ParseStream(absl::string_view s);
MediaType GetMediaType(uint32_t ssrc, PacketDirection direction) const;
@@ -581,6 +599,15 @@ class ParsedRtcEventLog {
}
}
+ const std::vector<LoggedRtcpPacketBye>& byes(
+ PacketDirection direction) const {
+ if (direction == kIncomingPacket) {
+ return incoming_bye_;
+ } else {
+ return outgoing_bye_;
+ }
+ }
+
const std::vector<LoggedRtcpPacketTransportFeedback>& transport_feedbacks(
PacketDirection direction) const {
if (direction == kIncomingPacket) {
@@ -611,8 +638,14 @@ class ParsedRtcEventLog {
return generic_acks_received_;
}
- int64_t first_timestamp() const { return first_timestamp_; }
- int64_t last_timestamp() const { return last_timestamp_; }
+ // Media
+ const std::map<uint32_t, std::vector<LoggedFrameDecoded>>& decoded_frames()
+ const {
+ return decoded_frames_;
+ }
+
+ Timestamp first_timestamp() const { return first_timestamp_; }
+ Timestamp last_timestamp() const { return last_timestamp_; }
const LogSegment& first_log_segment() const { return first_log_segment_; }
@@ -629,8 +662,8 @@ class ParsedRtcEventLog {
std::vector<InferredRouteChangeEvent> GetRouteChanges() const;
private:
- ABSL_MUST_USE_RESULT ParseStatus ParseStreamInternal(
- std::istream& stream); // no-presubmit-check TODO(webrtc:8982)
+ ABSL_MUST_USE_RESULT ParseStatus ParseStreamInternal(absl::string_view s);
+ ABSL_MUST_USE_RESULT ParseStatus ParseStreamInternalV3(absl::string_view s);
ABSL_MUST_USE_RESULT ParseStatus
StoreParsedLegacyEvent(const rtclog::Event& event);
@@ -638,34 +671,20 @@ class ParsedRtcEventLog {
template <typename T>
void StoreFirstAndLastTimestamp(const std::vector<T>& v);
- // Reads the header, direction, header length and packet length from the RTP
- // event at |index|, and stores the values in the corresponding output
- // parameters. Each output parameter can be set to nullptr if that value
- // isn't needed.
- // NB: The header must have space for at least IP_PACKET_SIZE bytes.
- ParseStatus GetRtpHeader(const rtclog::Event& event,
- PacketDirection* incoming,
- uint8_t* header,
- size_t* header_length,
- size_t* total_length,
- int* probe_cluster_id) const;
-
// Returns: a pointer to a header extensions map acquired from parsing
// corresponding Audio/Video Sender/Receiver config events.
// Warning: if the same SSRC is reused by both video and audio streams during
// call, extensions maps may be incorrect (the last one would be returned).
- const RtpHeaderExtensionMap* GetRtpHeaderExtensionMap(
- PacketDirection direction,
- uint32_t ssrc);
+ const RtpHeaderExtensionMap* GetRtpHeaderExtensionMap(bool incoming,
+ uint32_t ssrc);
- // Reads packet, direction and packet length from the RTCP event at |index|,
+ // Reads packet, direction and packet length from the RTCP event at `index`,
// and stores the values in the corresponding output parameters.
// Each output parameter can be set to nullptr if that value isn't needed.
// NB: The packet must have space for at least IP_PACKET_SIZE bytes.
ParseStatus GetRtcpPacket(const rtclog::Event& event,
PacketDirection* incoming,
- uint8_t* packet,
- size_t* length) const;
+ std::vector<uint8_t>* packet) const;
ParseStatusOr<rtclog::StreamConfig> GetVideoReceiveConfig(
const rtclog::Event& event) const;
@@ -706,6 +725,9 @@ class ParsedRtcEventLog {
ParsedRtcEventLog::ParseStatusOr<LoggedIceCandidatePairEvent>
GetIceCandidatePairEvent(const rtclog::Event& event) const;
+ ParsedRtcEventLog::ParseStatusOr<LoggedRemoteEstimateEvent>
+ GetRemoteEstimateEvent(const rtclog::Event& event) const;
+
// Parsing functions for new format.
ParseStatus StoreAlrStateEvent(const rtclog2::AlrState& proto);
ParseStatus StoreAudioNetworkAdaptationEvent(
@@ -726,6 +748,8 @@ class ParsedRtcEventLog {
ParseStatus StoreDtlsTransportState(
const rtclog2::DtlsTransportStateEvent& proto);
ParseStatus StoreDtlsWritableState(const rtclog2::DtlsWritableState& proto);
+ ParsedRtcEventLog::ParseStatus StoreFrameDecodedEvents(
+ const rtclog2::FrameDecodedEvents& proto);
ParseStatus StoreGenericAckReceivedEvent(
const rtclog2::GenericAckReceived& proto);
ParseStatus StoreGenericPacketReceivedEvent(
@@ -820,6 +844,8 @@ class ParsedRtcEventLog {
std::vector<LoggedRtcpPacketFir> outgoing_fir_;
std::vector<LoggedRtcpPacketPli> incoming_pli_;
std::vector<LoggedRtcpPacketPli> outgoing_pli_;
+ std::vector<LoggedRtcpPacketBye> incoming_bye_;
+ std::vector<LoggedRtcpPacketBye> outgoing_bye_;
std::vector<LoggedRtcpPacketTransportFeedback> incoming_transport_feedback_;
std::vector<LoggedRtcpPacketTransportFeedback> outgoing_transport_feedback_;
std::vector<LoggedRtcpPacketLossNotification> incoming_loss_notification_;
@@ -848,6 +874,8 @@ class ParsedRtcEventLog {
std::vector<LoggedDtlsTransportState> dtls_transport_states_;
std::vector<LoggedDtlsWritableState> dtls_writable_states_;
+ std::map<uint32_t, std::vector<LoggedFrameDecoded>> decoded_frames_;
+
std::vector<LoggedIceCandidatePairConfig> ice_candidate_pair_configs_;
std::vector<LoggedIceCandidatePairEvent> ice_candidate_pair_events_;
@@ -863,11 +891,10 @@ class ParsedRtcEventLog {
std::vector<LoggedRouteChangeEvent> route_change_events_;
std::vector<LoggedRemoteEstimateEvent> remote_estimate_events_;
- uint8_t last_incoming_rtcp_packet_[IP_PACKET_SIZE];
- uint8_t last_incoming_rtcp_packet_length_;
+ std::vector<uint8_t> last_incoming_rtcp_packet_;
- int64_t first_timestamp_;
- int64_t last_timestamp_;
+ Timestamp first_timestamp_ = Timestamp::PlusInfinity();
+ Timestamp last_timestamp_ = Timestamp::MinusInfinity();
LogSegment first_log_segment_ =
LogSegment(0, std::numeric_limits<int64_t>::max());
diff --git a/logging/rtc_event_log/rtc_event_log_unittest.cc b/logging/rtc_event_log/rtc_event_log_unittest.cc
index e785d6160a..314bfd90e9 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest.cc
@@ -8,6 +8,8 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+#include "api/rtc_event_log/rtc_event_log.h"
+
#include <algorithm>
#include <limits>
#include <map>
@@ -17,9 +19,7 @@
#include <utility>
#include <vector>
-#include "api/rtc_event_log/rtc_event_log.h"
#include "api/rtc_event_log/rtc_event_log_factory.h"
-#include "api/rtc_event_log_output_file.h"
#include "api/task_queue/default_task_queue_factory.h"
#include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
#include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
@@ -50,6 +50,7 @@
#include "rtc_base/fake_clock.h"
#include "rtc_base/random.h"
#include "test/gtest.h"
+#include "test/logging/memory_log_writer.h"
#include "test/testsupport/file_utils.h"
namespace webrtc {
@@ -69,6 +70,7 @@ struct EventCounts {
size_t bwe_delay_events = 0;
size_t dtls_transport_states = 0;
size_t dtls_writable_states = 0;
+ size_t frame_decoded_events = 0;
size_t probe_creations = 0;
size_t probe_successes = 0;
size_t probe_failures = 0;
@@ -85,9 +87,9 @@ struct EventCounts {
size_t total_nonconfig_events() const {
return alr_states + route_changes + audio_playouts + ana_configs +
bwe_loss_events + bwe_delay_events + dtls_transport_states +
- dtls_writable_states + probe_creations + probe_successes +
- probe_failures + ice_configs + ice_events + incoming_rtp_packets +
- outgoing_rtp_packets + incoming_rtcp_packets +
+ dtls_writable_states + frame_decoded_events + probe_creations +
+ probe_successes + probe_failures + ice_configs + ice_events +
+ incoming_rtp_packets + outgoing_rtp_packets + incoming_rtcp_packets +
outgoing_rtcp_packets + generic_packets_sent +
generic_packets_received + generic_acks_received;
}
@@ -112,11 +114,12 @@ class RtcEventLogSession
output_period_ms_(std::get<1>(GetParam())),
encoding_type_(std::get<2>(GetParam())),
gen_(seed_ * 880001UL),
- verifier_(encoding_type_) {
+ verifier_(encoding_type_),
+ log_storage_(),
+ log_output_factory_(log_storage_.CreateFactory()) {
clock_.SetTime(Timestamp::Micros(prng_.Rand<uint32_t>()));
// Find the name of the current test, in order to use it as a temporary
// filename.
- // TODO(terelius): Use a general utility function to generate a temp file.
auto test_info = ::testing::UnitTest::GetInstance()->current_test_info();
std::string test_name =
std::string(test_info->test_case_name()) + "_" + test_info->name();
@@ -124,7 +127,7 @@ class RtcEventLogSession
temp_filename_ = test::OutputPath() + test_name;
}
- // Create and buffer the config events and |num_events_before_log_start|
+ // Create and buffer the config events and `num_events_before_log_start`
// randomized non-config events. Then call StartLogging and finally create and
// write the remaining non-config events.
void WriteLog(EventCounts count, size_t num_events_before_log_start);
@@ -165,6 +168,8 @@ class RtcEventLogSession
dtls_transport_state_list_;
std::vector<std::unique_ptr<RtcEventDtlsWritableState>>
dtls_writable_state_list_;
+ std::map<uint32_t, std::vector<std::unique_ptr<RtcEventFrameDecoded>>>
+ frame_decoded_event_map_;
std::vector<std::unique_ptr<RtcEventGenericAckReceived>>
generic_acks_received_;
std::vector<std::unique_ptr<RtcEventGenericPacketReceived>>
@@ -200,6 +205,8 @@ class RtcEventLogSession
test::EventVerifier verifier_;
rtc::ScopedFakeClock clock_;
std::string temp_filename_;
+ MemoryLogStorage log_storage_;
+ std::unique_ptr<LogWriterFactoryInterface> log_output_factory_;
};
bool SsrcUsed(
@@ -269,9 +276,9 @@ void RtcEventLogSession::WriteVideoRecvConfigs(size_t video_recv_streams,
} while (SsrcUsed(ssrc, incoming_extensions_));
RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
incoming_extensions_.emplace_back(ssrc, extensions);
- auto event = gen_.NewVideoReceiveStreamConfig(ssrc, extensions);
- event_log->Log(event->Copy());
- video_recv_config_list_.push_back(std::move(event));
+ auto new_event = gen_.NewVideoReceiveStreamConfig(ssrc, extensions);
+ event_log->Log(new_event->Copy());
+ video_recv_config_list_.push_back(std::move(new_event));
}
}
@@ -311,7 +318,7 @@ void RtcEventLogSession::WriteLog(EventCounts count,
auto task_queue_factory = CreateDefaultTaskQueueFactory();
RtcEventLogFactory rtc_event_log_factory(task_queue_factory.get());
- // The log file will be flushed to disk when the event_log goes out of scope.
+ // The log will be flushed to output when the event_log goes out of scope.
std::unique_ptr<RtcEventLog> event_log =
rtc_event_log_factory.CreateRtcEventLog(encoding_type_);
@@ -330,9 +337,8 @@ void RtcEventLogSession::WriteLog(EventCounts count,
for (; remaining_events > 0; remaining_events--) {
if (remaining_events == remaining_events_at_start) {
clock_.AdvanceTime(TimeDelta::Millis(prng_.Rand(20)));
- event_log->StartLogging(
- std::make_unique<RtcEventLogOutputFile>(temp_filename_, 10000000),
- output_period_ms_);
+ event_log->StartLogging(log_output_factory_->Create(temp_filename_),
+ output_period_ms_);
start_time_us_ = rtc::TimeMicros();
utc_start_time_us_ = rtc::TimeUTCMicros();
}
@@ -444,6 +450,18 @@ void RtcEventLogSession::WriteLog(EventCounts count,
}
selection -= count.dtls_writable_states;
+ if (selection < count.frame_decoded_events) {
+ size_t stream = prng_.Rand(incoming_extensions_.size() - 1);
+ // This might be an audio SSRC, but that won't affect the parser.
+ uint32_t ssrc = incoming_extensions_[stream].first;
+ auto event = gen_.NewFrameDecodedEvent(ssrc);
+ event_log->Log(event->Copy());
+ frame_decoded_event_map_[ssrc].push_back(std::move(event));
+ count.frame_decoded_events--;
+ continue;
+ }
+ selection -= count.frame_decoded_events;
+
if (selection < count.ice_configs) {
auto event = gen_.NewIceCandidatePairConfig();
event_log->Log(event->Copy());
@@ -531,7 +549,7 @@ void RtcEventLogSession::WriteLog(EventCounts count,
}
selection -= count.generic_acks_received;
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
}
event_log->StopLogging();
@@ -540,12 +558,14 @@ void RtcEventLogSession::WriteLog(EventCounts count,
ASSERT_EQ(count.total_nonconfig_events(), static_cast<size_t>(0));
}
-// Read the file and verify that what we read back from the event log is the
+// Read the log and verify that what we read back from the event log is the
// same as what we wrote down.
void RtcEventLogSession::ReadAndVerifyLog() {
- // Read the generated file from disk.
+ // Read the generated log from memory.
ParsedRtcEventLog parsed_log;
- ASSERT_TRUE(parsed_log.ParseFile(temp_filename_).ok());
+ auto it = log_storage_.logs().find(temp_filename_);
+ ASSERT_TRUE(it != log_storage_.logs().end());
+ ASSERT_TRUE(parsed_log.ParseString(it->second).ok());
// Start and stop events.
auto& parsed_start_log_events = parsed_log.start_log_events();
@@ -577,7 +597,7 @@ void RtcEventLogSession::ReadAndVerifyLog() {
const auto& parsed_audio_playout_stream = kv.second;
const auto& audio_playout_stream = audio_playout_map_[ssrc];
ASSERT_EQ(parsed_audio_playout_stream.size(), audio_playout_stream.size());
- for (size_t i = 0; i < parsed_audio_playout_map.size(); i++) {
+ for (size_t i = 0; i < audio_playout_stream.size(); i++) {
verifier_.VerifyLoggedAudioPlayoutEvent(*audio_playout_stream[i],
parsed_audio_playout_stream[i]);
}
@@ -629,6 +649,35 @@ void RtcEventLogSession::ReadAndVerifyLog() {
*probe_success_list_[i], parsed_bwe_probe_success_events[i]);
}
+ auto& parsed_dtls_transport_states = parsed_log.dtls_transport_states();
+ ASSERT_EQ(parsed_dtls_transport_states.size(),
+ dtls_transport_state_list_.size());
+ for (size_t i = 0; i < parsed_dtls_transport_states.size(); i++) {
+ verifier_.VerifyLoggedDtlsTransportState(*dtls_transport_state_list_[i],
+ parsed_dtls_transport_states[i]);
+ }
+
+ auto& parsed_dtls_writable_states = parsed_log.dtls_writable_states();
+ ASSERT_EQ(parsed_dtls_writable_states.size(),
+ dtls_writable_state_list_.size());
+ for (size_t i = 0; i < parsed_dtls_writable_states.size(); i++) {
+ verifier_.VerifyLoggedDtlsWritableState(*dtls_writable_state_list_[i],
+ parsed_dtls_writable_states[i]);
+ }
+
+ const auto& parsed_frame_decoded_map = parsed_log.decoded_frames();
+ ASSERT_EQ(parsed_frame_decoded_map.size(), frame_decoded_event_map_.size());
+ for (const auto& kv : parsed_frame_decoded_map) {
+ uint32_t ssrc = kv.first;
+ const auto& parsed_decoded_frames = kv.second;
+ const auto& decoded_frames = frame_decoded_event_map_[ssrc];
+ ASSERT_EQ(parsed_decoded_frames.size(), decoded_frames.size());
+ for (size_t i = 0; i < decoded_frames.size(); i++) {
+ verifier_.VerifyLoggedFrameDecoded(*decoded_frames[i],
+ parsed_decoded_frames[i]);
+ }
+ }
+
auto& parsed_ice_candidate_pair_configs =
parsed_log.ice_candidate_pair_configs();
ASSERT_EQ(parsed_ice_candidate_pair_configs.size(), ice_config_list_.size());
@@ -736,16 +785,13 @@ void RtcEventLogSession::ReadAndVerifyLog() {
parsed_generic_acks_received[i]);
}
- EXPECT_EQ(first_timestamp_ms_, parsed_log.first_timestamp() / 1000);
- EXPECT_EQ(last_timestamp_ms_, parsed_log.last_timestamp() / 1000);
+ EXPECT_EQ(first_timestamp_ms_, parsed_log.first_timestamp().ms());
+ EXPECT_EQ(last_timestamp_ms_, parsed_log.last_timestamp().ms());
EXPECT_EQ(parsed_log.first_log_segment().start_time_ms(),
std::min(start_time_us_ / 1000, first_timestamp_ms_));
EXPECT_EQ(parsed_log.first_log_segment().stop_time_ms(),
stop_time_us_ / 1000);
-
- // Clean up temporary file - can be pretty slow.
- remove(temp_filename_.c_str());
}
} // namespace
@@ -761,8 +807,6 @@ TEST_P(RtcEventLogSession, StartLoggingFromBeginning) {
count.ana_configs = 3;
count.bwe_loss_events = 20;
count.bwe_delay_events = 20;
- count.dtls_transport_states = 4;
- count.dtls_writable_states = 2;
count.probe_creations = 4;
count.probe_successes = 2;
count.probe_failures = 2;
@@ -773,10 +817,13 @@ TEST_P(RtcEventLogSession, StartLoggingFromBeginning) {
count.incoming_rtcp_packets = 20;
count.outgoing_rtcp_packets = 20;
if (IsNewFormat()) {
- count.route_changes = 4;
+ count.dtls_transport_states = 4;
+ count.dtls_writable_states = 2;
+ count.frame_decoded_events = 50;
count.generic_packets_sent = 100;
count.generic_packets_received = 100;
count.generic_acks_received = 20;
+ count.route_changes = 4;
}
WriteLog(count, 0);
@@ -794,8 +841,6 @@ TEST_P(RtcEventLogSession, StartLoggingInTheMiddle) {
count.ana_configs = 10;
count.bwe_loss_events = 50;
count.bwe_delay_events = 50;
- count.dtls_transport_states = 4;
- count.dtls_writable_states = 5;
count.probe_creations = 10;
count.probe_successes = 5;
count.probe_failures = 5;
@@ -806,10 +851,13 @@ TEST_P(RtcEventLogSession, StartLoggingInTheMiddle) {
count.incoming_rtcp_packets = 50;
count.outgoing_rtcp_packets = 50;
if (IsNewFormat()) {
- count.route_changes = 10;
+ count.dtls_transport_states = 4;
+ count.dtls_writable_states = 5;
+ count.frame_decoded_events = 250;
count.generic_packets_sent = 500;
count.generic_packets_received = 500;
count.generic_acks_received = 50;
+ count.route_changes = 10;
}
WriteLog(count, 500);
@@ -829,9 +877,14 @@ class RtcEventLogCircularBufferTest
: public ::testing::TestWithParam<RtcEventLog::EncodingType> {
public:
RtcEventLogCircularBufferTest()
- : encoding_type_(GetParam()), verifier_(encoding_type_) {}
+ : encoding_type_(GetParam()),
+ verifier_(encoding_type_),
+ log_storage_(),
+ log_output_factory_(log_storage_.CreateFactory()) {}
const RtcEventLog::EncodingType encoding_type_;
const test::EventVerifier verifier_;
+ MemoryLogStorage log_storage_;
+ std::unique_ptr<LogWriterFactoryInterface> log_output_factory_;
};
TEST_P(RtcEventLogCircularBufferTest, KeepsMostRecentEvents) {
@@ -851,36 +904,45 @@ TEST_P(RtcEventLogCircularBufferTest, KeepsMostRecentEvents) {
std::make_unique<rtc::ScopedFakeClock>();
fake_clock->SetTime(Timestamp::Seconds(kStartTimeSeconds));
- auto task_queue_factory = CreateDefaultTaskQueueFactory();
- RtcEventLogFactory rtc_event_log_factory(task_queue_factory.get());
- // When log_dumper goes out of scope, it causes the log file to be flushed
- // to disk.
- std::unique_ptr<RtcEventLog> log_dumper =
- rtc_event_log_factory.CreateRtcEventLog(encoding_type_);
-
- for (size_t i = 0; i < kNumEvents; i++) {
- // The purpose of the test is to verify that the log can handle
- // more events than what fits in the internal circular buffer. The exact
- // type of events does not matter so we chose ProbeSuccess events for
- // simplicity.
- // We base the various values on the index. We use this for some basic
- // consistency checks when we read back.
- log_dumper->Log(std::make_unique<RtcEventProbeResultSuccess>(
- i, kStartBitrate + i * 1000));
+ // Create a scope for the TQ and event log factories.
+ // This way, we make sure that task queue instances that may rely on a clock
+ // have been torn down before we run the verification steps at the end of
+ // the test.
+ int64_t start_time_us, utc_start_time_us, stop_time_us;
+
+ {
+ auto task_queue_factory = CreateDefaultTaskQueueFactory();
+ RtcEventLogFactory rtc_event_log_factory(task_queue_factory.get());
+ // When `log` goes out of scope, the contents are flushed
+ // to the output.
+ std::unique_ptr<RtcEventLog> log =
+ rtc_event_log_factory.CreateRtcEventLog(encoding_type_);
+
+ for (size_t i = 0; i < kNumEvents; i++) {
+ // The purpose of the test is to verify that the log can handle
+ // more events than what fits in the internal circular buffer. The exact
+ // type of events does not matter so we chose ProbeSuccess events for
+ // simplicity.
+ // We base the various values on the index. We use this for some basic
+ // consistency checks when we read back.
+ log->Log(std::make_unique<RtcEventProbeResultSuccess>(
+ i, kStartBitrate + i * 1000));
+ fake_clock->AdvanceTime(TimeDelta::Millis(10));
+ }
+ start_time_us = rtc::TimeMicros();
+ utc_start_time_us = rtc::TimeUTCMicros();
+ log->StartLogging(log_output_factory_->Create(temp_filename),
+ RtcEventLog::kImmediateOutput);
fake_clock->AdvanceTime(TimeDelta::Millis(10));
+ stop_time_us = rtc::TimeMicros();
+ log->StopLogging();
}
- int64_t start_time_us = rtc::TimeMicros();
- int64_t utc_start_time_us = rtc::TimeUTCMicros();
- log_dumper->StartLogging(
- std::make_unique<RtcEventLogOutputFile>(temp_filename, 10000000),
- RtcEventLog::kImmediateOutput);
- fake_clock->AdvanceTime(TimeDelta::Millis(10));
- int64_t stop_time_us = rtc::TimeMicros();
- log_dumper->StopLogging();
- // Read the generated file from disk.
+ // Read the generated log from memory.
ParsedRtcEventLog parsed_log;
- ASSERT_TRUE(parsed_log.ParseFile(temp_filename).ok());
+ auto it = log_storage_.logs().find(temp_filename);
+ ASSERT_TRUE(it != log_storage_.logs().end());
+ ASSERT_TRUE(parsed_log.ParseString(it->second).ok());
const auto& start_log_events = parsed_log.start_log_events();
ASSERT_EQ(start_log_events.size(), 1u);
@@ -898,7 +960,7 @@ TEST_P(RtcEventLogCircularBufferTest, KeepsMostRecentEvents) {
EXPECT_LT(probe_success_events.size(), kNumEvents);
ASSERT_GT(probe_success_events.size(), 1u);
- int64_t first_timestamp_us = probe_success_events[0].timestamp_us;
+ int64_t first_timestamp_ms = probe_success_events[0].timestamp.ms();
uint32_t first_id = probe_success_events[0].id;
int32_t first_bitrate_bps = probe_success_events[0].bitrate_bps;
// We want to reset the time to what we used when generating the events, but
@@ -907,7 +969,7 @@ TEST_P(RtcEventLogCircularBufferTest, KeepsMostRecentEvents) {
// destroyed before the new one is created, so we have to reset() first.
fake_clock.reset();
fake_clock = std::make_unique<rtc::ScopedFakeClock>();
- fake_clock->SetTime(Timestamp::Micros(first_timestamp_us));
+ fake_clock->SetTime(Timestamp::Millis(first_timestamp_ms));
for (size_t i = 1; i < probe_success_events.size(); i++) {
fake_clock->AdvanceTime(TimeDelta::Millis(10));
verifier_.VerifyLoggedBweProbeSuccessEvent(
@@ -925,4 +987,64 @@ INSTANTIATE_TEST_SUITE_P(
// TODO(terelius): Verify parser behavior if the timestamps are not
// monotonically increasing in the log.
+TEST(DereferencingVectorTest, NonConstVector) {
+ std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ DereferencingVector<int> even;
+ EXPECT_TRUE(even.empty());
+ EXPECT_EQ(even.size(), 0u);
+ EXPECT_EQ(even.begin(), even.end());
+ for (size_t i = 0; i < v.size(); i += 2) {
+ even.push_back(&v[i]);
+ }
+ EXPECT_FALSE(even.empty());
+ EXPECT_EQ(even.size(), 5u);
+ EXPECT_NE(even.begin(), even.end());
+
+ // Test direct access.
+ for (size_t i = 0; i < even.size(); i++) {
+ EXPECT_EQ(even[i], 2 * static_cast<int>(i));
+ }
+
+ // Test iterator.
+ for (int val : even) {
+ EXPECT_EQ(val % 2, 0);
+ }
+
+ // Test modification through iterator.
+ for (int& val : even) {
+ val = val * 2;
+ EXPECT_EQ(val % 2, 0);
+ }
+
+ // Backing vector should have been modified.
+ std::vector<int> expected{0, 1, 4, 3, 8, 5, 12, 7, 16, 9};
+ for (size_t i = 0; i < v.size(); i++) {
+ EXPECT_EQ(v[i], expected[i]);
+ }
+}
+
+TEST(DereferencingVectorTest, ConstVector) {
+ std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ DereferencingVector<const int> odd;
+ EXPECT_TRUE(odd.empty());
+ EXPECT_EQ(odd.size(), 0u);
+ EXPECT_EQ(odd.begin(), odd.end());
+ for (size_t i = 1; i < v.size(); i += 2) {
+ odd.push_back(&v[i]);
+ }
+ EXPECT_FALSE(odd.empty());
+ EXPECT_EQ(odd.size(), 5u);
+ EXPECT_NE(odd.begin(), odd.end());
+
+ // Test direct access.
+ for (size_t i = 0; i < odd.size(); i++) {
+ EXPECT_EQ(odd[i], 2 * static_cast<int>(i) + 1);
+ }
+
+ // Test iterator.
+ for (int val : odd) {
+ EXPECT_EQ(val % 2, 1);
+ }
+}
+
} // namespace webrtc
diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
index 2a41f6d25b..2607028f60 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
+++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.cc
@@ -21,12 +21,15 @@
#include <utility>
#include <vector>
+#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "api/array_view.h"
+#include "api/network_state_predictor.h"
#include "api/rtp_headers.h"
#include "api/rtp_parameters.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
-#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/rtp_rtcp/include/rtp_cvo.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtcp_packet/dlrr.h"
@@ -37,6 +40,7 @@
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
+#include "rtc_base/time_utils.h"
#include "system_wrappers/include/ntp_time.h"
#include "test/gtest.h"
@@ -78,7 +82,7 @@ void ShuffleInPlace(Random* prng, rtc::ArrayView<T> array) {
}
absl::optional<int> GetExtensionId(const std::vector<RtpExtension>& extensions,
- const std::string& uri) {
+ absl::string_view uri) {
for (const auto& extension : extensions) {
if (extension.uri == uri)
return extension.id;
@@ -147,6 +151,29 @@ EventGenerator::NewDtlsWritableState() {
return std::make_unique<RtcEventDtlsWritableState>(writable);
}
+std::unique_ptr<RtcEventFrameDecoded> EventGenerator::NewFrameDecodedEvent(
+ uint32_t ssrc) {
+ constexpr int kMinRenderDelayMs = 1;
+ constexpr int kMaxRenderDelayMs = 2000000;
+ constexpr int kMaxWidth = 15360;
+ constexpr int kMaxHeight = 8640;
+ constexpr int kMinWidth = 16;
+ constexpr int kMinHeight = 16;
+ constexpr int kNumCodecTypes = 5;
+
+ constexpr VideoCodecType kCodecList[kNumCodecTypes] = {
+ kVideoCodecGeneric, kVideoCodecVP8, kVideoCodecVP9, kVideoCodecAV1,
+ kVideoCodecH264};
+ const int64_t render_time_ms =
+ rtc::TimeMillis() + prng_.Rand(kMinRenderDelayMs, kMaxRenderDelayMs);
+ const int width = prng_.Rand(kMinWidth, kMaxWidth);
+ const int height = prng_.Rand(kMinHeight, kMaxHeight);
+ const VideoCodecType codec = kCodecList[prng_.Rand(0, kNumCodecTypes - 1)];
+ const uint8_t qp = prng_.Rand<uint8_t>();
+ return std::make_unique<RtcEventFrameDecoded>(render_time_ms, ssrc, width,
+ height, codec, qp);
+}
+
std::unique_ptr<RtcEventProbeClusterCreated>
EventGenerator::NewProbeClusterCreated() {
constexpr int kMaxBweBps = 20000000;
@@ -314,17 +341,30 @@ rtcp::Pli EventGenerator::NewPli() {
return pli;
}
+rtcp::Bye EventGenerator::NewBye() {
+ rtcp::Bye bye;
+ bye.SetSenderSsrc(prng_.Rand<uint32_t>());
+ std::vector<uint32_t> csrcs{prng_.Rand<uint32_t>(), prng_.Rand<uint32_t>()};
+ bye.SetCsrcs(csrcs);
+ if (prng_.Rand(0, 2)) {
+ bye.SetReason("foo");
+ } else {
+ bye.SetReason("bar");
+ }
+ return bye;
+}
+
rtcp::TransportFeedback EventGenerator::NewTransportFeedback() {
rtcp::TransportFeedback transport_feedback;
uint16_t base_seq_no = prng_.Rand<uint16_t>();
- int64_t base_time_us = prng_.Rand<uint32_t>();
- transport_feedback.SetBase(base_seq_no, base_time_us);
- transport_feedback.AddReceivedPacket(base_seq_no, base_time_us);
- int64_t time_us = base_time_us;
+ Timestamp base_time = Timestamp::Micros(prng_.Rand<uint32_t>());
+ transport_feedback.SetBase(base_seq_no, base_time);
+ transport_feedback.AddReceivedPacket(base_seq_no, base_time);
+ Timestamp time = base_time;
for (uint16_t i = 1u; i < 10u; i++) {
- time_us += prng_.Rand(0, 100000);
+ time += TimeDelta::Micros(prng_.Rand(0, 100'000));
if (prng_.Rand<bool>()) {
- transport_feedback.AddReceivedPacket(base_seq_no + i, time_us);
+ transport_feedback.AddReceivedPacket(base_seq_no + i, time);
}
}
return transport_feedback;
@@ -372,6 +412,7 @@ EventGenerator::NewRtcpPacketIncoming() {
kPli,
kNack,
kRemb,
+ kBye,
kTransportFeedback,
kNumValues
};
@@ -413,13 +454,18 @@ EventGenerator::NewRtcpPacketIncoming() {
rtc::Buffer buffer = remb.Build();
return std::make_unique<RtcEventRtcpPacketIncoming>(buffer);
}
+ case SupportedRtcpTypes::kBye: {
+ rtcp::Bye bye = NewBye();
+ rtc::Buffer buffer = bye.Build();
+ return std::make_unique<RtcEventRtcpPacketIncoming>(buffer);
+ }
case SupportedRtcpTypes::kTransportFeedback: {
rtcp::TransportFeedback transport_feedback = NewTransportFeedback();
rtc::Buffer buffer = transport_feedback.Build();
return std::make_unique<RtcEventRtcpPacketIncoming>(buffer);
}
default:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
rtc::Buffer buffer;
return std::make_unique<RtcEventRtcpPacketIncoming>(buffer);
}
@@ -435,6 +481,7 @@ EventGenerator::NewRtcpPacketOutgoing() {
kPli,
kNack,
kRemb,
+ kBye,
kTransportFeedback,
kNumValues
};
@@ -476,13 +523,18 @@ EventGenerator::NewRtcpPacketOutgoing() {
rtc::Buffer buffer = remb.Build();
return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer);
}
+ case SupportedRtcpTypes::kBye: {
+ rtcp::Bye bye = NewBye();
+ rtc::Buffer buffer = bye.Build();
+ return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer);
+ }
case SupportedRtcpTypes::kTransportFeedback: {
rtcp::TransportFeedback transport_feedback = NewTransportFeedback();
rtc::Buffer buffer = transport_feedback.Build();
return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer);
}
default:
- RTC_NOTREACHED();
+ RTC_DCHECK_NOTREACHED();
rtc::Buffer buffer;
return std::make_unique<RtcEventRtcpPacketOutgoing>(buffer);
}
@@ -835,6 +887,18 @@ void EventVerifier::VerifyLoggedDtlsWritableState(
EXPECT_EQ(original_event.writable(), logged_event.writable);
}
+void EventVerifier::VerifyLoggedFrameDecoded(
+ const RtcEventFrameDecoded& original_event,
+ const LoggedFrameDecoded& logged_event) const {
+ EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
+ EXPECT_EQ(original_event.ssrc(), logged_event.ssrc);
+ EXPECT_EQ(original_event.render_time_ms(), logged_event.render_time_ms);
+ EXPECT_EQ(original_event.width(), logged_event.width);
+ EXPECT_EQ(original_event.height(), logged_event.height);
+ EXPECT_EQ(original_event.codec(), logged_event.codec);
+ EXPECT_EQ(original_event.qp(), logged_event.qp);
+}
+
void EventVerifier::VerifyLoggedIceCandidatePairConfig(
const RtcEventIceCandidatePairConfig& original_event,
const LoggedIceCandidatePairConfig& logged_event) const {
@@ -870,7 +934,8 @@ void EventVerifier::VerifyLoggedIceCandidatePairEvent(
}
}
-void VerifyLoggedRtpHeader(const RtpPacket& original_header,
+template <typename Event>
+void VerifyLoggedRtpHeader(const Event& original_header,
const RTPHeader& logged_header) {
// Standard RTP header.
EXPECT_EQ(original_header.Marker(), logged_header.markerBit);
@@ -879,53 +944,57 @@ void VerifyLoggedRtpHeader(const RtpPacket& original_header,
EXPECT_EQ(original_header.Timestamp(), logged_header.timestamp);
EXPECT_EQ(original_header.Ssrc(), logged_header.ssrc);
- EXPECT_EQ(original_header.headers_size(), logged_header.headerLength);
+ EXPECT_EQ(original_header.header_length(), logged_header.headerLength);
// TransmissionOffset header extension.
- ASSERT_EQ(original_header.HasExtension<TransmissionOffset>(),
+ ASSERT_EQ(original_header.template HasExtension<TransmissionOffset>(),
logged_header.extension.hasTransmissionTimeOffset);
if (logged_header.extension.hasTransmissionTimeOffset) {
int32_t offset;
- ASSERT_TRUE(original_header.GetExtension<TransmissionOffset>(&offset));
+ ASSERT_TRUE(
+ original_header.template GetExtension<TransmissionOffset>(&offset));
EXPECT_EQ(offset, logged_header.extension.transmissionTimeOffset);
}
// AbsoluteSendTime header extension.
- ASSERT_EQ(original_header.HasExtension<AbsoluteSendTime>(),
+ ASSERT_EQ(original_header.template HasExtension<AbsoluteSendTime>(),
logged_header.extension.hasAbsoluteSendTime);
if (logged_header.extension.hasAbsoluteSendTime) {
uint32_t sendtime;
- ASSERT_TRUE(original_header.GetExtension<AbsoluteSendTime>(&sendtime));
+ ASSERT_TRUE(
+ original_header.template GetExtension<AbsoluteSendTime>(&sendtime));
EXPECT_EQ(sendtime, logged_header.extension.absoluteSendTime);
}
// TransportSequenceNumber header extension.
- ASSERT_EQ(original_header.HasExtension<TransportSequenceNumber>(),
+ ASSERT_EQ(original_header.template HasExtension<TransportSequenceNumber>(),
logged_header.extension.hasTransportSequenceNumber);
if (logged_header.extension.hasTransportSequenceNumber) {
uint16_t seqnum;
- ASSERT_TRUE(original_header.GetExtension<TransportSequenceNumber>(&seqnum));
+ ASSERT_TRUE(original_header.template GetExtension<TransportSequenceNumber>(
+ &seqnum));
EXPECT_EQ(seqnum, logged_header.extension.transportSequenceNumber);
}
// AudioLevel header extension.
- ASSERT_EQ(original_header.HasExtension<AudioLevel>(),
+ ASSERT_EQ(original_header.template HasExtension<AudioLevel>(),
logged_header.extension.hasAudioLevel);
if (logged_header.extension.hasAudioLevel) {
bool voice_activity;
uint8_t audio_level;
- ASSERT_TRUE(original_header.GetExtension<AudioLevel>(&voice_activity,
- &audio_level));
+ ASSERT_TRUE(original_header.template GetExtension<AudioLevel>(
+ &voice_activity, &audio_level));
EXPECT_EQ(voice_activity, logged_header.extension.voiceActivity);
EXPECT_EQ(audio_level, logged_header.extension.audioLevel);
}
// VideoOrientation header extension.
- ASSERT_EQ(original_header.HasExtension<VideoOrientation>(),
+ ASSERT_EQ(original_header.template HasExtension<VideoOrientation>(),
logged_header.extension.hasVideoRotation);
if (logged_header.extension.hasVideoRotation) {
uint8_t rotation;
- ASSERT_TRUE(original_header.GetExtension<VideoOrientation>(&rotation));
+ ASSERT_TRUE(
+ original_header.template GetExtension<VideoOrientation>(&rotation));
EXPECT_EQ(ConvertCVOByteToVideoRotation(rotation),
logged_header.extension.videoRotation);
}
@@ -954,8 +1023,7 @@ void EventVerifier::VerifyLoggedRtpPacketIncoming(
const LoggedRtpPacketIncoming& logged_event) const {
EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
- EXPECT_EQ(original_event.header().headers_size(),
- logged_event.rtp.header_length);
+ EXPECT_EQ(original_event.header_length(), logged_event.rtp.header_length);
EXPECT_EQ(original_event.packet_length(), logged_event.rtp.total_length);
@@ -964,7 +1032,7 @@ void EventVerifier::VerifyLoggedRtpPacketIncoming(
EXPECT_EQ(original_event.padding_length(),
logged_event.rtp.header.paddingLength);
- VerifyLoggedRtpHeader(original_event.header(), logged_event.rtp.header);
+ VerifyLoggedRtpHeader(original_event, logged_event.rtp.header);
}
void EventVerifier::VerifyLoggedRtpPacketOutgoing(
@@ -972,8 +1040,7 @@ void EventVerifier::VerifyLoggedRtpPacketOutgoing(
const LoggedRtpPacketOutgoing& logged_event) const {
EXPECT_EQ(original_event.timestamp_ms(), logged_event.log_time_ms());
- EXPECT_EQ(original_event.header().headers_size(),
- logged_event.rtp.header_length);
+ EXPECT_EQ(original_event.header_length(), logged_event.rtp.header_length);
EXPECT_EQ(original_event.packet_length(), logged_event.rtp.total_length);
@@ -985,7 +1052,7 @@ void EventVerifier::VerifyLoggedRtpPacketOutgoing(
// TODO(terelius): Probe cluster ID isn't parsed, used or tested. Unless
// someone has a strong reason to keep it, it'll be removed.
- VerifyLoggedRtpHeader(original_event.header(), logged_event.rtp.header);
+ VerifyLoggedRtpHeader(original_event, logged_event.rtp.header);
}
void EventVerifier::VerifyLoggedGenericPacketSent(
@@ -1060,10 +1127,10 @@ void EventVerifier::VerifyReportBlock(
}
void EventVerifier::VerifyLoggedSenderReport(
- int64_t log_time_us,
+ int64_t log_time_ms,
const rtcp::SenderReport& original_sr,
const LoggedRtcpPacketSenderReport& logged_sr) {
- EXPECT_EQ(log_time_us, logged_sr.log_time_us());
+ EXPECT_EQ(log_time_ms, logged_sr.log_time_ms());
EXPECT_EQ(original_sr.sender_ssrc(), logged_sr.sr.sender_ssrc());
EXPECT_EQ(original_sr.ntp(), logged_sr.sr.ntp());
EXPECT_EQ(original_sr.rtp_timestamp(), logged_sr.sr.rtp_timestamp());
@@ -1080,10 +1147,10 @@ void EventVerifier::VerifyLoggedSenderReport(
}
void EventVerifier::VerifyLoggedReceiverReport(
- int64_t log_time_us,
+ int64_t log_time_ms,
const rtcp::ReceiverReport& original_rr,
const LoggedRtcpPacketReceiverReport& logged_rr) {
- EXPECT_EQ(log_time_us, logged_rr.log_time_us());
+ EXPECT_EQ(log_time_ms, logged_rr.log_time_ms());
EXPECT_EQ(original_rr.sender_ssrc(), logged_rr.rr.sender_ssrc());
ASSERT_EQ(original_rr.report_blocks().size(),
logged_rr.rr.report_blocks().size());
@@ -1094,9 +1161,10 @@ void EventVerifier::VerifyLoggedReceiverReport(
}
void EventVerifier::VerifyLoggedExtendedReports(
- int64_t log_time_us,
+ int64_t log_time_ms,
const rtcp::ExtendedReports& original_xr,
const LoggedRtcpPacketExtendedReports& logged_xr) {
+ EXPECT_EQ(log_time_ms, logged_xr.log_time_ms());
EXPECT_EQ(original_xr.sender_ssrc(), logged_xr.xr.sender_ssrc());
EXPECT_EQ(original_xr.rrtr().has_value(), logged_xr.xr.rrtr().has_value());
@@ -1134,11 +1202,11 @@ void EventVerifier::VerifyLoggedExtendedReports(
}
}
-void EventVerifier::VerifyLoggedFir(int64_t log_time_us,
+void EventVerifier::VerifyLoggedFir(int64_t log_time_ms,
const rtcp::Fir& original_fir,
const LoggedRtcpPacketFir& logged_fir) {
+ EXPECT_EQ(log_time_ms, logged_fir.log_time_ms());
EXPECT_EQ(original_fir.sender_ssrc(), logged_fir.fir.sender_ssrc());
-
const auto& original_requests = original_fir.requests();
const auto& logged_requests = logged_fir.fir.requests();
ASSERT_EQ(original_requests.size(), logged_requests.size());
@@ -1148,25 +1216,35 @@ void EventVerifier::VerifyLoggedFir(int64_t log_time_us,
}
}
-void EventVerifier::VerifyLoggedPli(int64_t log_time_us,
+void EventVerifier::VerifyLoggedPli(int64_t log_time_ms,
const rtcp::Pli& original_pli,
const LoggedRtcpPacketPli& logged_pli) {
+ EXPECT_EQ(log_time_ms, logged_pli.log_time_ms());
EXPECT_EQ(original_pli.sender_ssrc(), logged_pli.pli.sender_ssrc());
EXPECT_EQ(original_pli.media_ssrc(), logged_pli.pli.media_ssrc());
}
-void EventVerifier::VerifyLoggedNack(int64_t log_time_us,
+void EventVerifier::VerifyLoggedBye(int64_t log_time_ms,
+ const rtcp::Bye& original_bye,
+ const LoggedRtcpPacketBye& logged_bye) {
+ EXPECT_EQ(log_time_ms, logged_bye.log_time_ms());
+ EXPECT_EQ(original_bye.sender_ssrc(), logged_bye.bye.sender_ssrc());
+ EXPECT_EQ(original_bye.csrcs(), logged_bye.bye.csrcs());
+ EXPECT_EQ(original_bye.reason(), logged_bye.bye.reason());
+}
+
+void EventVerifier::VerifyLoggedNack(int64_t log_time_ms,
const rtcp::Nack& original_nack,
const LoggedRtcpPacketNack& logged_nack) {
- EXPECT_EQ(log_time_us, logged_nack.log_time_us());
+ EXPECT_EQ(log_time_ms, logged_nack.log_time_ms());
EXPECT_EQ(original_nack.packet_ids(), logged_nack.nack.packet_ids());
}
void EventVerifier::VerifyLoggedTransportFeedback(
- int64_t log_time_us,
+ int64_t log_time_ms,
const rtcp::TransportFeedback& original_transport_feedback,
const LoggedRtcpPacketTransportFeedback& logged_transport_feedback) {
- EXPECT_EQ(log_time_us, logged_transport_feedback.log_time_us());
+ EXPECT_EQ(log_time_ms, logged_transport_feedback.log_time_ms());
ASSERT_EQ(
original_transport_feedback.GetReceivedPackets().size(),
logged_transport_feedback.transport_feedback.GetReceivedPackets().size());
@@ -1177,25 +1255,25 @@ void EventVerifier::VerifyLoggedTransportFeedback(
logged_transport_feedback.transport_feedback.GetReceivedPackets()[i]
.sequence_number());
EXPECT_EQ(
- original_transport_feedback.GetReceivedPackets()[i].delta_us(),
+ original_transport_feedback.GetReceivedPackets()[i].delta(),
logged_transport_feedback.transport_feedback.GetReceivedPackets()[i]
- .delta_us());
+ .delta());
}
}
-void EventVerifier::VerifyLoggedRemb(int64_t log_time_us,
+void EventVerifier::VerifyLoggedRemb(int64_t log_time_ms,
const rtcp::Remb& original_remb,
const LoggedRtcpPacketRemb& logged_remb) {
- EXPECT_EQ(log_time_us, logged_remb.log_time_us());
+ EXPECT_EQ(log_time_ms, logged_remb.log_time_ms());
EXPECT_EQ(original_remb.ssrcs(), logged_remb.remb.ssrcs());
EXPECT_EQ(original_remb.bitrate_bps(), logged_remb.remb.bitrate_bps());
}
void EventVerifier::VerifyLoggedLossNotification(
- int64_t log_time_us,
+ int64_t log_time_ms,
const rtcp::LossNotification& original_loss_notification,
const LoggedRtcpPacketLossNotification& logged_loss_notification) {
- EXPECT_EQ(log_time_us, logged_loss_notification.log_time_us());
+ EXPECT_EQ(log_time_ms, logged_loss_notification.log_time_ms());
EXPECT_EQ(original_loss_notification.last_decoded(),
logged_loss_notification.loss_notification.last_decoded());
EXPECT_EQ(original_loss_notification.last_received(),
@@ -1210,7 +1288,7 @@ void EventVerifier::VerifyLoggedStartEvent(
const LoggedStartEvent& logged_event) const {
EXPECT_EQ(start_time_us / 1000, logged_event.log_time_ms());
if (encoding_type_ == RtcEventLog::EncodingType::NewFormat) {
- EXPECT_EQ(utc_start_time_us / 1000, logged_event.utc_start_time_ms);
+ EXPECT_EQ(utc_start_time_us / 1000, logged_event.utc_start_time.ms());
}
}
diff --git a/logging/rtc_event_log/rtc_event_log_unittest_helper.h b/logging/rtc_event_log/rtc_event_log_unittest_helper.h
index 6f0a9c9afe..94a46c195c 100644
--- a/logging/rtc_event_log/rtc_event_log_unittest_helper.h
+++ b/logging/rtc_event_log/rtc_event_log_unittest_helper.h
@@ -25,6 +25,7 @@
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_transport_state.h"
#include "logging/rtc_event_log/events/rtc_event_dtls_writable_state.h"
+#include "logging/rtc_event_log/events/rtc_event_frame_decoded.h"
#include "logging/rtc_event_log/events/rtc_event_generic_ack_received.h"
#include "logging/rtc_event_log/events/rtc_event_generic_packet_received.h"
#include "logging/rtc_event_log/events/rtc_event_generic_packet_sent.h"
@@ -44,6 +45,7 @@
#include "logging/rtc_event_log/rtc_event_log_parser.h"
#include "logging/rtc_event_log/rtc_stream_config.h"
#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
#include "modules/rtp_rtcp/source/rtcp_packet/fir.h"
#include "modules/rtp_rtcp/source/rtcp_packet/loss_notification.h"
@@ -71,6 +73,7 @@ class EventGenerator {
std::unique_ptr<RtcEventBweUpdateLossBased> NewBweUpdateLossBased();
std::unique_ptr<RtcEventDtlsTransportState> NewDtlsTransportState();
std::unique_ptr<RtcEventDtlsWritableState> NewDtlsWritableState();
+ std::unique_ptr<RtcEventFrameDecoded> NewFrameDecodedEvent(uint32_t ssrc);
std::unique_ptr<RtcEventGenericAckReceived> NewGenericAckReceived();
std::unique_ptr<RtcEventGenericPacketReceived> NewGenericPacketReceived();
std::unique_ptr<RtcEventGenericPacketSent> NewGenericPacketSent();
@@ -91,10 +94,11 @@ class EventGenerator {
rtcp::Remb NewRemb();
rtcp::Fir NewFir();
rtcp::Pli NewPli();
+ rtcp::Bye NewBye();
rtcp::TransportFeedback NewTransportFeedback();
rtcp::LossNotification NewLossNotification();
- // |all_configured_exts| determines whether the RTP packet exhibits all
+ // `all_configured_exts` determines whether the RTP packet exhibits all
// configured extensions, or a random subset thereof.
void RandomizeRtpPacket(size_t payload_size,
size_t padding_size,
@@ -103,21 +107,21 @@ class EventGenerator {
RtpPacket* rtp_packet,
bool all_configured_exts);
- // |all_configured_exts| determines whether the RTP packet exhibits all
+ // `all_configured_exts` determines whether the RTP packet exhibits all
// configured extensions, or a random subset thereof.
std::unique_ptr<RtcEventRtpPacketIncoming> NewRtpPacketIncoming(
uint32_t ssrc,
const RtpHeaderExtensionMap& extension_map,
bool all_configured_exts = true);
- // |all_configured_exts| determines whether the RTP packet exhibits all
+ // `all_configured_exts` determines whether the RTP packet exhibits all
// configured extensions, or a random subset thereof.
std::unique_ptr<RtcEventRtpPacketOutgoing> NewRtpPacketOutgoing(
uint32_t ssrc,
const RtpHeaderExtensionMap& extension_map,
bool all_configured_exts = true);
- // |configure_all| determines whether all supported extensions are configured,
+ // `configure_all` determines whether all supported extensions are configured,
// or a random subset.
RtpHeaderExtensionMap NewRtpHeaderExtensionMap(bool configure_all = false);
@@ -189,6 +193,9 @@ class EventVerifier {
const RtcEventDtlsWritableState& original_event,
const LoggedDtlsWritableState& logged_event) const;
+ void VerifyLoggedFrameDecoded(const RtcEventFrameDecoded& original_event,
+ const LoggedFrameDecoded& logged_event) const;
+
void VerifyLoggedIceCandidatePairConfig(
const RtcEventIceCandidatePairConfig& original_event,
const LoggedIceCandidatePairConfig& logged_event) const;
@@ -253,35 +260,38 @@ class EventVerifier {
const RtcEventRtcpPacketOutgoing& original_event,
const LoggedRtcpPacketOutgoing& logged_event) const;
- void VerifyLoggedSenderReport(int64_t log_time_us,
+ void VerifyLoggedSenderReport(int64_t log_time_ms,
const rtcp::SenderReport& original_sr,
const LoggedRtcpPacketSenderReport& logged_sr);
void VerifyLoggedReceiverReport(
- int64_t log_time_us,
+ int64_t log_time_ms,
const rtcp::ReceiverReport& original_rr,
const LoggedRtcpPacketReceiverReport& logged_rr);
void VerifyLoggedExtendedReports(
- int64_t log_time_us,
+ int64_t log_time_ms,
const rtcp::ExtendedReports& original_xr,
const LoggedRtcpPacketExtendedReports& logged_xr);
- void VerifyLoggedFir(int64_t log_time_us,
+ void VerifyLoggedFir(int64_t log_time_ms,
const rtcp::Fir& original_fir,
const LoggedRtcpPacketFir& logged_fir);
- void VerifyLoggedPli(int64_t log_time_us,
+ void VerifyLoggedPli(int64_t log_time_ms,
const rtcp::Pli& original_pli,
const LoggedRtcpPacketPli& logged_pli);
- void VerifyLoggedNack(int64_t log_time_us,
+ void VerifyLoggedBye(int64_t log_time_ms,
+ const rtcp::Bye& original_bye,
+ const LoggedRtcpPacketBye& logged_bye);
+ void VerifyLoggedNack(int64_t log_time_ms,
const rtcp::Nack& original_nack,
const LoggedRtcpPacketNack& logged_nack);
void VerifyLoggedTransportFeedback(
- int64_t log_time_us,
+ int64_t log_time_ms,
const rtcp::TransportFeedback& original_transport_feedback,
const LoggedRtcpPacketTransportFeedback& logged_transport_feedback);
- void VerifyLoggedRemb(int64_t log_time_us,
+ void VerifyLoggedRemb(int64_t log_time_ms,
const rtcp::Remb& original_remb,
const LoggedRtcpPacketRemb& logged_remb);
void VerifyLoggedLossNotification(
- int64_t log_time_us,
+ int64_t log_time_ms,
const rtcp::LossNotification& original_loss_notification,
const LoggedRtcpPacketLossNotification& logged_loss_notification);
diff --git a/logging/rtc_event_log/rtc_event_processor.cc b/logging/rtc_event_log/rtc_event_processor.cc
index 804e283851..e6a9983b6f 100644
--- a/logging/rtc_event_log/rtc_event_processor.cc
+++ b/logging/rtc_event_log/rtc_event_processor.cc
@@ -15,7 +15,7 @@ RtcEventProcessor::RtcEventProcessor() = default;
RtcEventProcessor::~RtcEventProcessor() = default;
void RtcEventProcessor::ProcessEventsInOrder() {
- // |event_lists_| is a min-heap of lists ordered by the timestamp of the
+ // `event_lists_` is a min-heap of lists ordered by the timestamp of the
// first element in the list. We therefore process the first element of the
// first list, then reinsert the remainder of that list into the heap
// if the list still contains unprocessed elements.
diff --git a/logging/rtc_event_log/rtc_event_processor.h b/logging/rtc_event_log/rtc_event_processor.h
index abb73701db..9bf4c9c5db 100644
--- a/logging/rtc_event_log/rtc_event_processor.h
+++ b/logging/rtc_event_log/rtc_event_processor.h
@@ -98,7 +98,7 @@ class RtcEventProcessor {
// The elements of each list is processed in the index order. To process all
// elements in all lists in timestamp order, each list needs to be sorted in
// timestamp order prior to insertion.
- // N.B. |iterable| is not owned by RtcEventProcessor. The caller must ensure
+ // N.B. `iterable` is not owned by RtcEventProcessor. The caller must ensure
// that the iterable outlives RtcEventProcessor and it must not be modified
// until processing has finished.
template <typename Iterable>
@@ -122,7 +122,7 @@ class RtcEventProcessor {
std::unique_ptr<event_processor_impl::ProcessableEventListInterface>;
int insertion_order_index_ = 0;
std::vector<ListPtrType> event_lists_;
- // Comparison function to make |event_lists_| into a min heap.
+ // Comparison function to make `event_lists_` into a min heap.
static bool Cmp(const ListPtrType& a, const ListPtrType& b);
};
diff --git a/logging/rtc_event_log/rtc_event_processor_unittest.cc b/logging/rtc_event_log/rtc_event_processor_unittest.cc
index 4ec5abee5e..b0cec25f1f 100644
--- a/logging/rtc_event_log/rtc_event_processor_unittest.cc
+++ b/logging/rtc_event_log/rtc_event_processor_unittest.cc
@@ -29,7 +29,7 @@ std::vector<LoggedStartEvent> CreateEventList(
std::initializer_list<int64_t> timestamp_list) {
std::vector<LoggedStartEvent> v;
for (int64_t timestamp_ms : timestamp_list) {
- v.emplace_back(timestamp_ms * 1000); // Convert ms to us.
+ v.emplace_back(Timestamp::Millis(timestamp_ms));
}
return v;
}
@@ -41,7 +41,7 @@ CreateRandomEventLists(size_t num_lists, size_t num_elements, uint64_t seed) {
for (size_t elem = 0; elem < num_elements; elem++) {
uint32_t i = prng.Rand(0u, num_lists - 1);
int64_t timestamp_ms = elem;
- lists[i].emplace_back(timestamp_ms * 1000);
+ lists[i].emplace_back(Timestamp::Millis(timestamp_ms));
}
return lists;
}
@@ -146,8 +146,8 @@ TEST(RtcEventProcessor, DifferentTypes) {
result.push_back(elem.log_time_ms());
};
- std::vector<LoggedStartEvent> events1{LoggedStartEvent(2000)};
- std::vector<LoggedStopEvent> events2{LoggedStopEvent(1000)};
+ std::vector<LoggedStartEvent> events1{LoggedStartEvent(Timestamp::Millis(2))};
+ std::vector<LoggedStopEvent> events2{LoggedStopEvent(Timestamp::Millis(1))};
RtcEventProcessor processor;
processor.AddEvents(events1, f1);
processor.AddEvents(events2, f2);
diff --git a/logging/rtc_event_log/rtc_stream_config.cc b/logging/rtc_event_log/rtc_stream_config.cc
index d4d30d00bc..aa107c80bc 100644
--- a/logging/rtc_event_log/rtc_stream_config.cc
+++ b/logging/rtc_event_log/rtc_stream_config.cc
@@ -10,6 +10,8 @@
#include "logging/rtc_event_log/rtc_stream_config.h"
+#include "absl/strings/string_view.h"
+
namespace webrtc {
namespace rtclog {
@@ -30,7 +32,7 @@ bool StreamConfig::operator!=(const StreamConfig& other) const {
return !(*this == other);
}
-StreamConfig::Codec::Codec(const std::string& payload_name,
+StreamConfig::Codec::Codec(absl::string_view payload_name,
int payload_type,
int rtx_payload_type)
: payload_name(payload_name),
diff --git a/logging/rtc_event_log/rtc_stream_config.h b/logging/rtc_event_log/rtc_stream_config.h
index a81249aebf..d114332d34 100644
--- a/logging/rtc_event_log/rtc_stream_config.h
+++ b/logging/rtc_event_log/rtc_stream_config.h
@@ -16,6 +16,7 @@
#include <string>
#include <vector>
+#include "absl/strings/string_view.h"
#include "api/rtp_headers.h"
#include "api/rtp_parameters.h"
@@ -41,7 +42,7 @@ struct StreamConfig {
RtcpMode rtcp_mode = RtcpMode::kReducedSize;
struct Codec {
- Codec(const std::string& payload_name,
+ Codec(absl::string_view payload_name,
int payload_type,
int rtx_payload_type);