RtcEventLogSource no longer uses deprecated parsing functions.
Also remove header extension map from NetEqEventLogInput and RtcEventLogSource. Bug: webrtc:8111 Change-Id: Ic9be7b03e32ab8aa12284596e21e53b6763f483a Reviewed-on: https://webrtc-review.googlesource.com/c/102622 Commit-Queue: Björn Terelius <terelius@webrtc.org> Reviewed-by: Minyue Li <minyue@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25122}
This commit is contained in:
committed by
Commit Bot
parent
499bc6c5d0
commit
5350d1cafd
@ -19,11 +19,8 @@ namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
NetEqEventLogInput::NetEqEventLogInput(const std::string& file_name,
|
||||
const RtpHeaderExtensionMap& hdr_ext_map)
|
||||
: source_(RtcEventLogSource::Create(file_name)) {
|
||||
for (const auto& ext_pair : hdr_ext_map) {
|
||||
source_->RegisterRtpHeaderExtension(ext_pair.second, ext_pair.first);
|
||||
}
|
||||
absl::optional<uint32_t> ssrc_filter)
|
||||
: source_(RtcEventLogSource::Create(file_name, ssrc_filter)) {
|
||||
LoadNextPacket();
|
||||
AdvanceOutputEvent();
|
||||
}
|
||||
|
||||
@ -28,7 +28,7 @@ class RtcEventLogSource;
|
||||
class NetEqEventLogInput final : public NetEqPacketSourceInput {
|
||||
public:
|
||||
NetEqEventLogInput(const std::string& file_name,
|
||||
const RtpHeaderExtensionMap& hdr_ext_map);
|
||||
absl::optional<uint32_t> ssrc_filter);
|
||||
|
||||
absl::optional<int64_t> NextOutputEventTime() const override;
|
||||
void AdvanceOutputEvent() override;
|
||||
|
||||
@ -58,15 +58,10 @@ std::unique_ptr<NetEqInput::PacketData> NetEqPacketSourceInput::PopPacket() {
|
||||
return packet_data;
|
||||
}
|
||||
|
||||
void NetEqPacketSourceInput::SelectSsrc(uint32_t ssrc) {
|
||||
source()->SelectSsrc(ssrc);
|
||||
if (packet_ && packet_->header().ssrc != ssrc)
|
||||
LoadNextPacket();
|
||||
}
|
||||
|
||||
NetEqRtpDumpInput::NetEqRtpDumpInput(const std::string& file_name,
|
||||
const RtpHeaderExtensionMap& hdr_ext_map)
|
||||
: source_(RtpFileSource::Create(file_name)) {
|
||||
const RtpHeaderExtensionMap& hdr_ext_map,
|
||||
absl::optional<uint32_t> ssrc_filter)
|
||||
: source_(RtpFileSource::Create(file_name, ssrc_filter)) {
|
||||
for (const auto& ext_pair : hdr_ext_map) {
|
||||
source_->RegisterRtpHeaderExtension(ext_pair.second, ext_pair.first);
|
||||
}
|
||||
|
||||
@ -12,8 +12,10 @@
|
||||
#define MODULES_AUDIO_CODING_NETEQ_TOOLS_NETEQ_PACKET_SOURCE_INPUT_H_
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "modules/audio_coding/neteq/tools/neteq_input.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
|
||||
@ -32,7 +34,6 @@ class NetEqPacketSourceInput : public NetEqInput {
|
||||
std::unique_ptr<PacketData> PopPacket() override;
|
||||
absl::optional<RTPHeader> NextHeader() const override;
|
||||
bool ended() const override { return !next_output_event_ms_; }
|
||||
void SelectSsrc(uint32_t);
|
||||
|
||||
protected:
|
||||
virtual PacketSource* source() = 0;
|
||||
@ -48,7 +49,8 @@ class NetEqPacketSourceInput : public NetEqInput {
|
||||
class NetEqRtpDumpInput final : public NetEqPacketSourceInput {
|
||||
public:
|
||||
NetEqRtpDumpInput(const std::string& file_name,
|
||||
const RtpHeaderExtensionMap& hdr_ext_map);
|
||||
const RtpHeaderExtensionMap& hdr_ext_map,
|
||||
absl::optional<uint32_t> ssrc_filter);
|
||||
|
||||
absl::optional<int64_t> NextOutputEventTime() const override;
|
||||
void AdvanceOutputEvent() override;
|
||||
|
||||
@ -309,25 +309,27 @@ std::unique_ptr<NetEqTest> NetEqTestFactory::InitializeTest(
|
||||
{FLAG_video_content_type, kRtpExtensionVideoContentType},
|
||||
{FLAG_video_timing, kRtpExtensionVideoTiming}};
|
||||
|
||||
absl::optional<uint32_t> ssrc_filter;
|
||||
// Check if an SSRC value was provided.
|
||||
if (strlen(FLAG_ssrc) > 0) {
|
||||
uint32_t ssrc;
|
||||
RTC_CHECK(ParseSsrc(FLAG_ssrc, &ssrc)) << "Flag verification has failed.";
|
||||
ssrc_filter = ssrc;
|
||||
}
|
||||
|
||||
std::unique_ptr<NetEqInput> input;
|
||||
if (RtpFileSource::ValidRtpDump(input_file_name) ||
|
||||
RtpFileSource::ValidPcap(input_file_name)) {
|
||||
input.reset(new NetEqRtpDumpInput(input_file_name, rtp_ext_map));
|
||||
input.reset(
|
||||
new NetEqRtpDumpInput(input_file_name, rtp_ext_map, ssrc_filter));
|
||||
} else {
|
||||
input.reset(new NetEqEventLogInput(input_file_name, rtp_ext_map));
|
||||
input.reset(new NetEqEventLogInput(input_file_name, ssrc_filter));
|
||||
}
|
||||
|
||||
std::cout << "Input file: " << input_file_name << std::endl;
|
||||
RTC_CHECK(input) << "Cannot open input file";
|
||||
RTC_CHECK(!input->ended()) << "Input file is empty";
|
||||
|
||||
// Check if an SSRC value was provided.
|
||||
if (strlen(FLAG_ssrc) > 0) {
|
||||
uint32_t ssrc;
|
||||
RTC_CHECK(ParseSsrc(FLAG_ssrc, &ssrc)) << "Flag verification has failed.";
|
||||
static_cast<NetEqPacketSourceInput*>(input.get())->SelectSsrc(ssrc);
|
||||
}
|
||||
|
||||
// Check the sample rate.
|
||||
absl::optional<int> sample_rate_hz;
|
||||
std::set<std::pair<int, uint32_t>> discarded_pt_and_ssrc;
|
||||
|
||||
@ -49,6 +49,20 @@ Packet::Packet(uint8_t* packet_memory,
|
||||
valid_header_ = ParseHeader(parser);
|
||||
}
|
||||
|
||||
Packet::Packet(const RTPHeader& header,
|
||||
size_t virtual_packet_length_bytes,
|
||||
size_t virtual_payload_length_bytes,
|
||||
double time_ms)
|
||||
: header_(header),
|
||||
payload_memory_(),
|
||||
payload_(NULL),
|
||||
packet_length_bytes_(0),
|
||||
payload_length_bytes_(0),
|
||||
virtual_packet_length_bytes_(virtual_packet_length_bytes),
|
||||
virtual_payload_length_bytes_(virtual_payload_length_bytes),
|
||||
time_ms_(time_ms),
|
||||
valid_header_(true) {}
|
||||
|
||||
Packet::Packet(uint8_t* packet_memory, size_t allocated_bytes, double time_ms)
|
||||
: payload_memory_(packet_memory),
|
||||
payload_(NULL),
|
||||
|
||||
@ -50,7 +50,17 @@ class Packet {
|
||||
double time_ms,
|
||||
const RtpHeaderParser& parser);
|
||||
|
||||
// The following two constructors are the same as above, but without a
|
||||
// Same as above, but creates the packet from an already parsed RTPHeader.
|
||||
// This is typically used when reading RTP dump files that only contain the
|
||||
// RTP headers, and no payload. The |virtual_packet_length_bytes| tells what
|
||||
// size the packet had on wire, including the now discarded payload,
|
||||
// The |virtual_payload_length_bytes| tells the size of the payload.
|
||||
Packet(const RTPHeader& header,
|
||||
size_t virtual_packet_length_bytes,
|
||||
size_t virtual_payload_length_bytes,
|
||||
double time_ms);
|
||||
|
||||
// The following constructors are the same as the first two, but without a
|
||||
// parser. Note that when the object is constructed using any of these
|
||||
// methods, the header will be parsed using a default RtpHeaderParser object.
|
||||
// In particular, RTP header extensions won't be parsed.
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
PacketSource::PacketSource() : use_ssrc_filter_(false), ssrc_(0) {}
|
||||
PacketSource::PacketSource() = default;
|
||||
|
||||
PacketSource::~PacketSource() = default;
|
||||
|
||||
@ -21,10 +21,5 @@ void PacketSource::FilterOutPayloadType(uint8_t payload_type) {
|
||||
filter_.set(payload_type, true);
|
||||
}
|
||||
|
||||
void PacketSource::SelectSsrc(uint32_t ssrc) {
|
||||
use_ssrc_filter_ = true;
|
||||
ssrc_ = ssrc;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
@ -32,13 +32,8 @@ class PacketSource {
|
||||
|
||||
virtual void FilterOutPayloadType(uint8_t payload_type);
|
||||
|
||||
virtual void SelectSsrc(uint32_t ssrc);
|
||||
|
||||
protected:
|
||||
std::bitset<128> filter_; // Payload type is 7 bits in the RFC.
|
||||
// If SSRC filtering discards all packet that do not match the SSRC.
|
||||
bool use_ssrc_filter_; // True when SSRC filtering is active.
|
||||
uint32_t ssrc_; // The selected SSRC. All other SSRCs will be discarded.
|
||||
|
||||
private:
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(PacketSource);
|
||||
|
||||
@ -13,94 +13,105 @@
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
#include "logging/rtc_event_log/rtc_event_processor.h"
|
||||
#include "modules/audio_coding/neteq/tools/packet.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_header_parser.h"
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
RtcEventLogSource* RtcEventLogSource::Create(const std::string& file_name) {
|
||||
namespace {
|
||||
bool ShouldSkipStream(ParsedRtcEventLogNew::MediaType media_type,
|
||||
uint32_t ssrc,
|
||||
absl::optional<uint32_t> ssrc_filter) {
|
||||
if (media_type != ParsedRtcEventLogNew::MediaType::AUDIO)
|
||||
return true;
|
||||
if (ssrc_filter.has_value() && ssrc != *ssrc_filter)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
RtcEventLogSource* RtcEventLogSource::Create(
|
||||
const std::string& file_name,
|
||||
absl::optional<uint32_t> ssrc_filter) {
|
||||
RtcEventLogSource* source = new RtcEventLogSource();
|
||||
RTC_CHECK(source->OpenFile(file_name));
|
||||
RTC_CHECK(source->OpenFile(file_name, ssrc_filter));
|
||||
return source;
|
||||
}
|
||||
|
||||
RtcEventLogSource::~RtcEventLogSource() {}
|
||||
|
||||
bool RtcEventLogSource::RegisterRtpHeaderExtension(RTPExtensionType type,
|
||||
uint8_t id) {
|
||||
RTC_CHECK(parser_.get());
|
||||
return parser_->RegisterRtpHeaderExtension(type, id);
|
||||
}
|
||||
|
||||
std::unique_ptr<Packet> RtcEventLogSource::NextPacket() {
|
||||
for (; rtp_packet_index_ < parsed_stream_.GetNumberOfEvents();
|
||||
rtp_packet_index_++) {
|
||||
if (parsed_stream_.GetEventType(rtp_packet_index_) ==
|
||||
ParsedRtcEventLogNew::EventType::RTP_EVENT) {
|
||||
PacketDirection direction;
|
||||
size_t header_length;
|
||||
size_t packet_length;
|
||||
uint64_t timestamp_us = parsed_stream_.GetTimestamp(rtp_packet_index_);
|
||||
parsed_stream_.GetRtpHeader(rtp_packet_index_, &direction, nullptr,
|
||||
&header_length, &packet_length, nullptr);
|
||||
if (rtp_packet_index_ >= rtp_packets_.size())
|
||||
return nullptr;
|
||||
|
||||
if (direction != kIncomingPacket) {
|
||||
continue;
|
||||
}
|
||||
|
||||
uint8_t* packet_header = new uint8_t[header_length];
|
||||
parsed_stream_.GetRtpHeader(rtp_packet_index_, nullptr, packet_header,
|
||||
nullptr, nullptr, nullptr);
|
||||
std::unique_ptr<Packet> packet(
|
||||
new Packet(packet_header, header_length, packet_length,
|
||||
static_cast<double>(timestamp_us) / 1000, *parser_.get()));
|
||||
|
||||
if (!packet->valid_header()) {
|
||||
std::cout << "Warning: Packet with index " << rtp_packet_index_
|
||||
<< " has an invalid header and will be ignored." << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parsed_stream_.GetMediaType(packet->header().ssrc, direction) !=
|
||||
ParsedRtcEventLogNew::MediaType::AUDIO) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the packet should not be filtered out.
|
||||
if (!filter_.test(packet->header().payloadType) &&
|
||||
!(use_ssrc_filter_ && packet->header().ssrc != ssrc_)) {
|
||||
++rtp_packet_index_;
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
std::unique_ptr<Packet> packet = std::move(rtp_packets_[rtp_packet_index_++]);
|
||||
return packet;
|
||||
}
|
||||
|
||||
int64_t RtcEventLogSource::NextAudioOutputEventMs() {
|
||||
while (audio_output_index_ < parsed_stream_.GetNumberOfEvents()) {
|
||||
if (parsed_stream_.GetEventType(audio_output_index_) ==
|
||||
ParsedRtcEventLogNew::EventType::AUDIO_PLAYOUT_EVENT) {
|
||||
LoggedAudioPlayoutEvent playout_event =
|
||||
parsed_stream_.GetAudioPlayout(audio_output_index_);
|
||||
if (!(use_ssrc_filter_ && playout_event.ssrc != ssrc_)) {
|
||||
audio_output_index_++;
|
||||
return playout_event.timestamp_us / 1000;
|
||||
}
|
||||
}
|
||||
audio_output_index_++;
|
||||
}
|
||||
return std::numeric_limits<int64_t>::max();
|
||||
if (audio_output_index_ >= audio_outputs_.size())
|
||||
return std::numeric_limits<int64_t>::max();
|
||||
|
||||
int64_t output_time_ms = audio_outputs_[audio_output_index_++];
|
||||
return output_time_ms;
|
||||
}
|
||||
|
||||
RtcEventLogSource::RtcEventLogSource()
|
||||
: PacketSource(), parser_(RtpHeaderParser::Create()) {}
|
||||
RtcEventLogSource::RtcEventLogSource() : PacketSource() {}
|
||||
|
||||
bool RtcEventLogSource::OpenFile(const std::string& file_name) {
|
||||
return parsed_stream_.ParseFile(file_name);
|
||||
bool RtcEventLogSource::OpenFile(const std::string& file_name,
|
||||
absl::optional<uint32_t> ssrc_filter) {
|
||||
ParsedRtcEventLogNew parsed_log;
|
||||
if (!parsed_log.ParseFile(file_name))
|
||||
return false;
|
||||
|
||||
auto handle_rtp_packet =
|
||||
[this](const webrtc::LoggedRtpPacketIncoming& incoming) {
|
||||
if (!filter_.test(incoming.rtp.header.payloadType)) {
|
||||
rtp_packets_.emplace_back(absl::make_unique<Packet>(
|
||||
incoming.rtp.header, incoming.rtp.total_length,
|
||||
incoming.rtp.total_length - incoming.rtp.header_length,
|
||||
static_cast<double>(incoming.log_time_ms())));
|
||||
}
|
||||
};
|
||||
|
||||
auto handle_audio_playout =
|
||||
[this](const webrtc::LoggedAudioPlayoutEvent& audio_playout) {
|
||||
audio_outputs_.emplace_back(audio_playout.log_time_ms());
|
||||
};
|
||||
|
||||
// This wouldn't be needed if we knew that there was at most one audio stream.
|
||||
webrtc::RtcEventProcessor event_processor;
|
||||
for (const auto& rtp_packets : parsed_log.incoming_rtp_packets_by_ssrc()) {
|
||||
ParsedRtcEventLogNew::MediaType media_type =
|
||||
parsed_log.GetMediaType(rtp_packets.ssrc, webrtc::kIncomingPacket);
|
||||
if (ShouldSkipStream(media_type, rtp_packets.ssrc, ssrc_filter)) {
|
||||
continue;
|
||||
}
|
||||
auto rtp_view = absl::make_unique<
|
||||
webrtc::ProcessableEventList<webrtc::LoggedRtpPacketIncoming>>(
|
||||
rtp_packets.incoming_packets.begin(),
|
||||
rtp_packets.incoming_packets.end(), handle_rtp_packet);
|
||||
event_processor.AddEvents(std::move(rtp_view));
|
||||
}
|
||||
|
||||
for (const auto& audio_playouts : parsed_log.audio_playout_events()) {
|
||||
if (ssrc_filter.has_value() && audio_playouts.first != *ssrc_filter)
|
||||
continue;
|
||||
auto audio_view = absl::make_unique<
|
||||
webrtc::ProcessableEventList<webrtc::LoggedAudioPlayoutEvent>>(
|
||||
audio_playouts.second.begin(), audio_playouts.second.end(),
|
||||
handle_audio_playout);
|
||||
event_processor.AddEvents(std::move(audio_view));
|
||||
}
|
||||
|
||||
// Fills in rtp_packets_ and audio_outputs_.
|
||||
event_processor.ProcessEventsInOrder();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
||||
@ -13,7 +13,9 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "logging/rtc_event_log/rtc_event_log_parser_new.h"
|
||||
#include "modules/audio_coding/neteq/tools/packet_source.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
@ -31,13 +33,11 @@ class RtcEventLogSource : public PacketSource {
|
||||
public:
|
||||
// Creates an RtcEventLogSource reading from |file_name|. If the file cannot
|
||||
// be opened, or has the wrong format, NULL will be returned.
|
||||
static RtcEventLogSource* Create(const std::string& file_name);
|
||||
static RtcEventLogSource* Create(const std::string& file_name,
|
||||
absl::optional<uint32_t> ssrc_filter);
|
||||
|
||||
virtual ~RtcEventLogSource();
|
||||
|
||||
// Registers an RTP header extension and binds it to |id|.
|
||||
virtual bool RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id);
|
||||
|
||||
std::unique_ptr<Packet> NextPacket() override;
|
||||
|
||||
// Returns the timestamp of the next audio output event, in milliseconds. The
|
||||
@ -48,14 +48,14 @@ class RtcEventLogSource : public PacketSource {
|
||||
private:
|
||||
RtcEventLogSource();
|
||||
|
||||
bool OpenFile(const std::string& file_name);
|
||||
bool OpenFile(const std::string& file_name,
|
||||
absl::optional<uint32_t> ssrc_filter);
|
||||
|
||||
std::vector<std::unique_ptr<Packet>> rtp_packets_;
|
||||
size_t rtp_packet_index_ = 0;
|
||||
std::vector<int64_t> audio_outputs_;
|
||||
size_t audio_output_index_ = 0;
|
||||
|
||||
ParsedRtcEventLogNew parsed_stream_;
|
||||
std::unique_ptr<RtpHeaderParser> parser_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(RtcEventLogSource);
|
||||
};
|
||||
|
||||
|
||||
@ -26,8 +26,9 @@
|
||||
namespace webrtc {
|
||||
namespace test {
|
||||
|
||||
RtpFileSource* RtpFileSource::Create(const std::string& file_name) {
|
||||
RtpFileSource* source = new RtpFileSource();
|
||||
RtpFileSource* RtpFileSource::Create(const std::string& file_name,
|
||||
absl::optional<uint32_t> ssrc_filter) {
|
||||
RtpFileSource* source = new RtpFileSource(ssrc_filter);
|
||||
RTC_CHECK(source->OpenFile(file_name));
|
||||
return source;
|
||||
}
|
||||
@ -72,7 +73,7 @@ std::unique_ptr<Packet> RtpFileSource::NextPacket() {
|
||||
continue;
|
||||
}
|
||||
if (filter_.test(packet->header().payloadType) ||
|
||||
(use_ssrc_filter_ && packet->header().ssrc != ssrc_)) {
|
||||
(ssrc_filter_ && packet->header().ssrc != *ssrc_filter_)) {
|
||||
// This payload type should be filtered out. Continue to the next packet.
|
||||
continue;
|
||||
}
|
||||
@ -80,8 +81,10 @@ std::unique_ptr<Packet> RtpFileSource::NextPacket() {
|
||||
}
|
||||
}
|
||||
|
||||
RtpFileSource::RtpFileSource()
|
||||
: PacketSource(), parser_(RtpHeaderParser::Create()) {}
|
||||
RtpFileSource::RtpFileSource(absl::optional<uint32_t> ssrc_filter)
|
||||
: PacketSource(),
|
||||
parser_(RtpHeaderParser::Create()),
|
||||
ssrc_filter_(ssrc_filter) {}
|
||||
|
||||
bool RtpFileSource::OpenFile(const std::string& file_name) {
|
||||
rtp_reader_.reset(RtpFileReader::Create(RtpFileReader::kRtpDump, file_name));
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/types/optional.h"
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "modules/audio_coding/neteq/tools/packet_source.h"
|
||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||
@ -33,7 +34,9 @@ class RtpFileSource : public PacketSource {
|
||||
public:
|
||||
// Creates an RtpFileSource reading from |file_name|. If the file cannot be
|
||||
// opened, or has the wrong format, NULL will be returned.
|
||||
static RtpFileSource* Create(const std::string& file_name);
|
||||
static RtpFileSource* Create(
|
||||
const std::string& file_name,
|
||||
absl::optional<uint32_t> ssrc_filter = absl::nullopt);
|
||||
|
||||
// Checks whether a files is a valid RTP dump or PCAP (Wireshark) file.
|
||||
static bool ValidRtpDump(const std::string& file_name);
|
||||
@ -51,12 +54,13 @@ class RtpFileSource : public PacketSource {
|
||||
static const int kRtpFileHeaderSize = 4 + 4 + 4 + 2 + 2;
|
||||
static const size_t kPacketHeaderSize = 8;
|
||||
|
||||
RtpFileSource();
|
||||
explicit RtpFileSource(absl::optional<uint32_t> ssrc_filter);
|
||||
|
||||
bool OpenFile(const std::string& file_name);
|
||||
|
||||
std::unique_ptr<RtpFileReader> rtp_reader_;
|
||||
std::unique_ptr<RtpHeaderParser> parser_;
|
||||
const absl::optional<uint32_t> ssrc_filter_;
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(RtpFileSource);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user