/* * Copyright (c) 2015 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 "webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h" #include #include #include #include #include "webrtc/base/checks.h" #include "webrtc/call/rtc_event_log.h" #include "webrtc/modules/audio_coding/neteq/tools/packet.h" #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" // Files generated at build-time by the protobuf compiler. #ifdef WEBRTC_ANDROID_PLATFORM_BUILD #include "external/webrtc/webrtc/call/rtc_event_log.pb.h" #else #include "webrtc/call/rtc_event_log.pb.h" #endif namespace webrtc { namespace test { namespace { const rtclog::RtpPacket* GetRtpPacket(const rtclog::Event& event) { if (!event.has_type() || event.type() != rtclog::Event::RTP_EVENT) return nullptr; if (!event.has_timestamp_us() || !event.has_rtp_packet()) return nullptr; const rtclog::RtpPacket& rtp_packet = event.rtp_packet(); if (!rtp_packet.has_type() || rtp_packet.type() != rtclog::AUDIO || !rtp_packet.has_incoming() || !rtp_packet.incoming() || !rtp_packet.has_packet_length() || rtp_packet.packet_length() == 0 || !rtp_packet.has_header() || rtp_packet.header().size() == 0 || rtp_packet.packet_length() < rtp_packet.header().size()) return nullptr; return &rtp_packet; } const rtclog::AudioPlayoutEvent* GetAudioPlayoutEvent( const rtclog::Event& event) { if (!event.has_type() || event.type() != rtclog::Event::AUDIO_PLAYOUT_EVENT) return nullptr; if (!event.has_timestamp_us() || !event.has_audio_playout_event()) return nullptr; const rtclog::AudioPlayoutEvent& playout_event = event.audio_playout_event(); if (!playout_event.has_local_ssrc()) return nullptr; return &playout_event; } } // namespace RtcEventLogSource* RtcEventLogSource::Create(const std::string& file_name) { RtcEventLogSource* source = new RtcEventLogSource(); RTC_CHECK(source->OpenFile(file_name)); return source; } RtcEventLogSource::~RtcEventLogSource() {} bool RtcEventLogSource::RegisterRtpHeaderExtension(RTPExtensionType type, uint8_t id) { RTC_CHECK(parser_.get()); return parser_->RegisterRtpHeaderExtension(type, id); } Packet* RtcEventLogSource::NextPacket() { while (rtp_packet_index_ < event_log_->stream_size()) { const rtclog::Event& event = event_log_->stream(rtp_packet_index_); const rtclog::RtpPacket* rtp_packet = GetRtpPacket(event); rtp_packet_index_++; if (rtp_packet) { uint8_t* packet_header = new uint8_t[rtp_packet->header().size()]; memcpy(packet_header, rtp_packet->header().data(), rtp_packet->header().size()); Packet* packet = new Packet(packet_header, rtp_packet->header().size(), rtp_packet->packet_length(), event.timestamp_us() / 1000, *parser_.get()); if (packet->valid_header()) { // Check if the packet should not be filtered out. if (!filter_.test(packet->header().payloadType) && !(use_ssrc_filter_ && packet->header().ssrc != ssrc_)) return packet; } else { std::cout << "Warning: Packet with index " << (rtp_packet_index_ - 1) << " has an invalid header and will be ignored." << std::endl; } // The packet has either an invalid header or needs to be filtered out, so // it can be deleted. delete packet; } } return nullptr; } int64_t RtcEventLogSource::NextAudioOutputEventMs() { while (audio_output_index_ < event_log_->stream_size()) { const rtclog::Event& event = event_log_->stream(audio_output_index_); const rtclog::AudioPlayoutEvent* playout_event = GetAudioPlayoutEvent(event); audio_output_index_++; if (playout_event) return event.timestamp_us() / 1000; } return std::numeric_limits::max(); } RtcEventLogSource::RtcEventLogSource() : PacketSource(), parser_(RtpHeaderParser::Create()) {} bool RtcEventLogSource::OpenFile(const std::string& file_name) { event_log_.reset(new rtclog::EventStream()); return RtcEventLog::ParseRtcEventLog(file_name, event_log_.get()); } } // namespace test } // namespace webrtc