diff --git a/webrtc/common_types.h b/webrtc/common_types.h index 7138b05319..a45cf069d2 100644 --- a/webrtc/common_types.h +++ b/webrtc/common_types.h @@ -138,7 +138,6 @@ enum FileFormats kFileFormatPcm32kHzFile = 9 }; - enum ProcessingTypes { kPlaybackPerChannel = 0, @@ -148,6 +147,15 @@ enum ProcessingTypes kRecordingPreprocessing }; +enum FrameType +{ + kFrameEmpty = 0, + kAudioFrameSpeech = 1, + kAudioFrameCN = 2, + kVideoFrameKey = 3, // independent frame + kVideoFrameDelta = 4, // depends on the previus frame +}; + // Interface for encrypting and decrypting regular data and rtp/rtcp packets. // Implement this interface if you wish to provide an encryption scheme to // the voice or video engines. @@ -302,9 +310,9 @@ class BitrateStatisticsObserver { class FrameCountObserver { public: virtual ~FrameCountObserver() {} - virtual void Notify(const unsigned int key_frames, - const unsigned int delta_frames, - const unsigned int ssrc) = 0; + virtual void FrameCountUpdated(FrameType frame_type, + uint32_t frame_count, + const unsigned int ssrc) = 0; }; // ================================================================== @@ -322,17 +330,6 @@ struct CodecInst int rate; // bits/sec unlike {start,min,max}Bitrate elsewhere in this file! }; -enum FrameType -{ - kFrameEmpty = 0, - kAudioFrameSpeech = 1, - kAudioFrameCN = 2, - kVideoFrameKey = 3, // independent frame - kVideoFrameDelta = 4, // depends on the previus frame - kVideoFrameGolden = 5, // depends on a old known previus frame - kVideoFrameAltRef = 6 -}; - // RTP enum {kRtpCsrcSize = 15}; // RFC 3550 page 13 diff --git a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h index 28ee0f568d..9fb8199ade 100644 --- a/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h +++ b/webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h @@ -331,6 +331,10 @@ class RtpRtcp : public Module { virtual int TimeToSendPadding(int bytes) = 0; + virtual void RegisterSendFrameCountObserver( + FrameCountObserver* observer) = 0; + virtual FrameCountObserver* GetSendFrameCountObserver() const = 0; + /************************************************************************** * * RTCP diff --git a/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h b/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h index 472683e886..93230da101 100644 --- a/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h +++ b/webrtc/modules/rtp_rtcp/mocks/mock_rtp_rtcp.h @@ -240,7 +240,10 @@ class MockRtpRtcp : public RtpRtcp { int32_t()); MOCK_METHOD0(Process, int32_t()); - + MOCK_METHOD1(RegisterSendFrameCountObserver, + void(FrameCountObserver*)); + MOCK_CONST_METHOD0(GetSendFrameCountObserver, + FrameCountObserver*(void)); // Members. unsigned int remote_ssrc_; }; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc index 44dcb8604c..027d17d28d 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.cc @@ -1645,4 +1645,13 @@ uint32_t ModuleRtpRtcpImpl::rtt_ms() const { return rtt_ms_; } +void ModuleRtpRtcpImpl::RegisterSendFrameCountObserver( + FrameCountObserver* observer) { + rtp_sender_.RegisterFrameCountObserver(observer); +} + +FrameCountObserver* ModuleRtpRtcpImpl::GetSendFrameCountObserver() const { + return rtp_sender_.GetFrameCountObserver(); +} + } // Namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h index 1fdec2845b..c8ab063e06 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h @@ -363,6 +363,10 @@ class ModuleRtpRtcpImpl : public RtpRtcp { void OnRequestSendReport(); + virtual void RegisterSendFrameCountObserver( + FrameCountObserver* observer) OVERRIDE; + virtual FrameCountObserver* GetSendFrameCountObserver() const OVERRIDE; + protected: void RegisterChildModule(RtpRtcp* module); diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc index 0f08573efd..c7179646b5 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc @@ -32,8 +32,6 @@ const char* FrameTypeToString(const FrameType frame_type) { case kAudioFrameCN: return "audio_cn"; case kVideoFrameKey: return "video_key"; case kVideoFrameDelta: return "video_delta"; - case kVideoFrameGolden: return "video_golden"; - case kVideoFrameAltRef: return "video_altref"; } return ""; } @@ -61,7 +59,8 @@ RTPSender::RTPSender(const int32_t id, const bool audio, Clock *clock, remote_ssrc_(0), sequence_number_forced_(false), ssrc_forced_(false), timestamp_(0), capture_time_ms_(0), last_timestamp_time_ms_(0), last_packet_marker_bit_(false), num_csrcs_(0), csrcs_(), - include_csrcs_(true), rtx_(kRtxOff), payload_type_rtx_(-1) { + include_csrcs_(true), rtx_(kRtxOff), payload_type_rtx_(-1), + frame_counts_(), frame_count_observer_(NULL) { memset(nack_byte_count_times_, 0, sizeof(nack_byte_count_times_)); memset(nack_byte_count_, 0, sizeof(nack_byte_count_)); memset(csrcs_, 0, sizeof(csrcs_)); @@ -359,14 +358,15 @@ int32_t RTPSender::SendOutgoingData( return -1; } + uint32_t ret_val; if (audio_configured_) { TRACE_EVENT_ASYNC_STEP1("webrtc", "Audio", capture_timestamp, "Send", "type", FrameTypeToString(frame_type)); assert(frame_type == kAudioFrameSpeech || frame_type == kAudioFrameCN || frame_type == kFrameEmpty); - return audio_->SendAudio(frame_type, payload_type, capture_timestamp, - payload_data, payload_size, fragmentation); + ret_val = audio_->SendAudio(frame_type, payload_type, capture_timestamp, + payload_data, payload_size, fragmentation); } else { TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", capture_time_ms, "Send", "type", FrameTypeToString(frame_type)); @@ -380,11 +380,23 @@ int32_t RTPSender::SendOutgoingData( return SendPaddingAccordingToBitrate(payload_type, capture_timestamp, capture_time_ms) ? 0 : -1; } - return video_->SendVideo(video_type, frame_type, payload_type, - capture_timestamp, capture_time_ms, payload_data, - payload_size, fragmentation, codec_info, - rtp_type_hdr); + ret_val = video_->SendVideo(video_type, frame_type, payload_type, + capture_timestamp, capture_time_ms, + payload_data, payload_size, + fragmentation, codec_info, + rtp_type_hdr); + } + + CriticalSectionScoped cs(statistics_crit_.get()); + uint32_t frame_count = ++frame_counts_[frame_type]; + if (frame_count_observer_) { + frame_count_observer_->FrameCountUpdated(frame_type, + frame_count, + ssrc_); + } + + return ret_val; } int RTPSender::SendRedundantPayloads(int payload_type, int bytes_to_send) { @@ -1478,4 +1490,16 @@ void RTPSender::BuildRtxPacket(uint8_t* buffer, uint16_t* length, *length += 2; } +void RTPSender::RegisterFrameCountObserver(FrameCountObserver* observer) { + CriticalSectionScoped cs(statistics_crit_.get()); + if (observer != NULL) + assert(frame_count_observer_ == NULL); + frame_count_observer_ = observer; +} + +FrameCountObserver* RTPSender::GetFrameCountObserver() const { + CriticalSectionScoped cs(statistics_crit_.get()); + return frame_count_observer_; +} + } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.h b/webrtc/modules/rtp_rtcp/source/rtp_sender.h index c78af28e85..7b7967ef7c 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.h @@ -260,6 +260,9 @@ class RTPSender : public Bitrate, public RTPSenderInterface { int32_t SetFecParameters(const FecProtectionParams *delta_params, const FecProtectionParams *key_params); + virtual void RegisterFrameCountObserver(FrameCountObserver* observer); + virtual FrameCountObserver* GetFrameCountObserver() const; + protected: int32_t CheckPayloadType(const int8_t payload_type, RtpVideoCodecTypes *video_type); @@ -346,6 +349,8 @@ class RTPSender : public Bitrate, public RTPSenderInterface { int rtx_; uint32_t ssrc_rtx_; int payload_type_rtx_; + std::map frame_counts_; + FrameCountObserver* frame_count_observer_; }; } // namespace webrtc diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc index ed4aa823ad..0bb752f0cb 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_unittest.cc @@ -717,6 +717,68 @@ TEST_F(RtpSenderTest, SendGenericVideo) { EXPECT_EQ(0, memcmp(payload, payload_data, sizeof(payload))); } +TEST_F(RtpSenderTest, FrameCountCallbacks) { + class TestCallback : public FrameCountObserver { + public: + TestCallback() + : FrameCountObserver(), num_calls_(0), ssrc_(0), + key_frames_(0), delta_frames_(0) {} + virtual ~TestCallback() {} + + virtual void FrameCountUpdated(FrameType frame_type, + uint32_t frame_count, + const unsigned int ssrc) { + ++num_calls_; + ssrc_ = ssrc; + switch (frame_type) { + case kVideoFrameDelta: + delta_frames_ = frame_count; + break; + case kVideoFrameKey: + key_frames_ = frame_count; + break; + default: + break; + } + } + + uint32_t num_calls_; + uint32_t ssrc_; + uint32_t key_frames_; + uint32_t delta_frames_; + } callback; + + char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC"; + const uint8_t payload_type = 127; + ASSERT_EQ(0, rtp_sender_->RegisterPayload(payload_name, payload_type, 90000, + 0, 1500)); + uint8_t payload[] = {47, 11, 32, 93, 89}; + rtp_sender_->SetStorePacketsStatus(true, 1); + uint32_t ssrc = rtp_sender_->SSRC(); + + rtp_sender_->RegisterFrameCountObserver(&callback); + + ASSERT_EQ(0, rtp_sender_->SendOutgoingData(kVideoFrameKey, payload_type, 1234, + 4321, payload, sizeof(payload), + NULL)); + + EXPECT_EQ(1U, callback.num_calls_); + EXPECT_EQ(ssrc, callback.ssrc_); + EXPECT_EQ(1U, callback.key_frames_); + EXPECT_EQ(0U, callback.delta_frames_); + + ASSERT_EQ(0, rtp_sender_->SendOutgoingData(kVideoFrameDelta, + payload_type, 1234, 4321, payload, + sizeof(payload), NULL)); + + EXPECT_EQ(2U, callback.num_calls_); + EXPECT_EQ(ssrc, callback.ssrc_); + EXPECT_EQ(1U, callback.key_frames_); + EXPECT_EQ(1U, callback.delta_frames_); + + rtp_sender_->RegisterFrameCountObserver(NULL); +} + class RtpSenderAudioTest : public RtpSenderTest { protected: RtpSenderAudioTest() {} diff --git a/webrtc/modules/video_coding/main/source/encoded_frame.cc b/webrtc/modules/video_coding/main/source/encoded_frame.cc index 62744500e2..6760762c9a 100644 --- a/webrtc/modules/video_coding/main/source/encoded_frame.cc +++ b/webrtc/modules/video_coding/main/source/encoded_frame.cc @@ -174,33 +174,16 @@ VCMEncodedFrame::VerifyAndAllocate(const uint32_t minimumSize) webrtc::FrameType VCMEncodedFrame::ConvertFrameType(VideoFrameType frameType) { - switch(frameType) - { + switch(frameType) { case kKeyFrame: - { - return kVideoFrameKey; - } + return kVideoFrameKey; case kDeltaFrame: - { - return kVideoFrameDelta; - } - case kGoldenFrame: - { - return kVideoFrameGolden; - } - case kAltRefFrame: - { - return kVideoFrameAltRef; - } + return kVideoFrameDelta; case kSkipFrame: - { - return kFrameEmpty; - } + return kFrameEmpty; default: - { - return kVideoFrameDelta; - } - } + return kVideoFrameDelta; + } } VideoFrameType VCMEncodedFrame::ConvertFrameType(webrtc::FrameType frame_type) { @@ -209,10 +192,6 @@ VideoFrameType VCMEncodedFrame::ConvertFrameType(webrtc::FrameType frame_type) { return kKeyFrame; case kVideoFrameDelta: return kDeltaFrame; - case kVideoFrameGolden: - return kGoldenFrame; - case kVideoFrameAltRef: - return kAltRefFrame; default: assert(false); return kDeltaFrame; diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer.cc b/webrtc/modules/video_coding/main/source/jitter_buffer.cc index 56282000b4..f11f81b46f 100644 --- a/webrtc/modules/video_coding/main/source/jitter_buffer.cc +++ b/webrtc/modules/video_coding/main/source/jitter_buffer.cc @@ -147,7 +147,6 @@ VCMJitterBuffer::VCMJitterBuffer(Clock* clock, incomplete_frames_(), last_decoded_state_(), first_packet_since_reset_(true), - receive_statistics_(), incoming_frame_rate_(0), incoming_frame_count_(0), time_last_incoming_frame_count_(0), @@ -172,7 +171,6 @@ VCMJitterBuffer::VCMJitterBuffer(Clock* clock, average_packets_per_frame_(0.0f), frame_counter_(0) { memset(frame_buffers_, 0, sizeof(frame_buffers_)); - memset(receive_statistics_, 0, sizeof(receive_statistics_)); for (int i = 0; i < kStartNumberOfFrames; i++) { frame_buffers_[i] = new VCMFrameBuffer(); @@ -218,8 +216,7 @@ void VCMJitterBuffer::CopyFrom(const VCMJitterBuffer& rhs) { assert(max_nack_list_size_ == rhs.max_nack_list_size_); assert(max_packet_age_to_nack_ == rhs.max_packet_age_to_nack_); assert(max_incomplete_time_ms_ == rhs.max_incomplete_time_ms_); - memcpy(receive_statistics_, rhs.receive_statistics_, - sizeof(receive_statistics_)); + receive_statistics_ = rhs.receive_statistics_; nack_seq_nums_.resize(rhs.nack_seq_nums_.size()); missing_sequence_numbers_ = rhs.missing_sequence_numbers_; latest_received_sequence_number_ = rhs.latest_received_sequence_number_; @@ -264,7 +261,7 @@ void VCMJitterBuffer::Start() { incoming_bit_count_ = 0; incoming_bit_rate_ = 0; time_last_incoming_frame_count_ = clock_->TimeInMilliseconds(); - memset(receive_statistics_, 0, sizeof(receive_statistics_)); + receive_statistics_.clear(); num_consecutive_old_frames_ = 0; num_consecutive_old_packets_ = 0; @@ -336,13 +333,9 @@ void VCMJitterBuffer::Flush() { } // Get received key and delta frames -void VCMJitterBuffer::FrameStatistics(uint32_t* received_delta_frames, - uint32_t* received_key_frames) const { - assert(received_delta_frames); - assert(received_key_frames); +std::map VCMJitterBuffer::FrameStatistics() const { CriticalSectionScoped cs(crit_sect_); - *received_delta_frames = receive_statistics_[1] + receive_statistics_[3]; - *received_key_frames = receive_statistics_[0] + receive_statistics_[2]; + return receive_statistics_; } int VCMJitterBuffer::num_discarded_packets() const { @@ -1206,26 +1199,7 @@ void VCMJitterBuffer::CountFrame(const VCMFrameBuffer& frame) { // Update receive statistics. We count all layers, thus when you use layers // adding all key and delta frames might differ from frame count. if (frame.IsSessionComplete()) { - switch (frame.FrameType()) { - case kVideoFrameKey: { - receive_statistics_[0]++; - break; - } - case kVideoFrameDelta: { - receive_statistics_[1]++; - break; - } - case kVideoFrameGolden: { - receive_statistics_[2]++; - break; - } - case kVideoFrameAltRef: { - receive_statistics_[3]++; - break; - } - default: - assert(false); - } + ++receive_statistics_[frame.FrameType()]; } } diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer.h b/webrtc/modules/video_coding/main/source/jitter_buffer.h index 3716a41202..8586f115f8 100644 --- a/webrtc/modules/video_coding/main/source/jitter_buffer.h +++ b/webrtc/modules/video_coding/main/source/jitter_buffer.h @@ -98,10 +98,9 @@ class VCMJitterBuffer { // Empty the jitter buffer of all its data. void Flush(); - // Get the number of received key and delta frames since the jitter buffer + // Get the number of received frames, by type, since the jitter buffer // was started. - void FrameStatistics(uint32_t* received_delta_frames, - uint32_t* received_key_frames) const; + std::map FrameStatistics() const; // The number of packets discarded by the jitter buffer because the decoder // won't be able to decode them. @@ -297,8 +296,8 @@ class VCMJitterBuffer { bool first_packet_since_reset_; // Statistics. - // Frame counter for each type (key, delta, golden, key-delta). - unsigned int receive_statistics_[4]; + // Frame counts for each type (key, delta, ...) + std::map receive_statistics_; // Latest calculated frame rates of incoming stream. unsigned int incoming_frame_rate_; unsigned int incoming_frame_count_; diff --git a/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc b/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc index f596d68002..e535a8a404 100644 --- a/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc +++ b/webrtc/modules/video_coding/main/source/jitter_buffer_unittest.cc @@ -1632,11 +1632,9 @@ TEST_F(TestRunningJitterBuffer, EmptyPackets) { } TEST_F(TestRunningJitterBuffer, StatisticsTest) { - uint32_t num_delta_frames = 0; - uint32_t num_key_frames = 0; - jitter_buffer_->FrameStatistics(&num_delta_frames, &num_key_frames); - EXPECT_EQ(0u, num_delta_frames); - EXPECT_EQ(0u, num_key_frames); + std::map frame_stats(jitter_buffer_->FrameStatistics()); + EXPECT_EQ(0u, frame_stats[kVideoFrameDelta]); + EXPECT_EQ(0u, frame_stats[kVideoFrameKey]); uint32_t framerate = 0; uint32_t bitrate = 0; @@ -1654,9 +1652,9 @@ TEST_F(TestRunningJitterBuffer, StatisticsTest) { // being decoded. EXPECT_TRUE(DecodeCompleteFrame()); EXPECT_TRUE(DecodeCompleteFrame()); - jitter_buffer_->FrameStatistics(&num_delta_frames, &num_key_frames); - EXPECT_EQ(3u, num_delta_frames); - EXPECT_EQ(2u, num_key_frames); + frame_stats = jitter_buffer_->FrameStatistics(); + EXPECT_EQ(3u, frame_stats[kVideoFrameDelta]); + EXPECT_EQ(2u, frame_stats[kVideoFrameKey]); // Insert 20 more frames to get estimates of bitrate and framerate over // 1 second. diff --git a/webrtc/modules/video_coding/main/source/media_optimization.cc b/webrtc/modules/video_coding/main/source/media_optimization.cc index 37dff6c7f1..27fa681933 100644 --- a/webrtc/modules/video_coding/main/source/media_optimization.cc +++ b/webrtc/modules/video_coding/main/source/media_optimization.cc @@ -291,8 +291,7 @@ int32_t MediaOptimization::UpdateWithEncodedData(int encoded_length, UpdateSentBitrate(now_ms); UpdateSentFramerate(); if (encoded_length > 0) { - const bool delta_frame = (encoded_frame_type != kVideoFrameKey && - encoded_frame_type != kVideoFrameGolden); + const bool delta_frame = (encoded_frame_type != kVideoFrameKey); frame_dropper_->Fill(encoded_length, delta_frame); if (max_payload_size_ > 0 && encoded_length > 0) { diff --git a/webrtc/modules/video_coding/main/source/receiver.cc b/webrtc/modules/video_coding/main/source/receiver.cc index e0969ef5a0..ae13ddd421 100644 --- a/webrtc/modules/video_coding/main/source/receiver.cc +++ b/webrtc/modules/video_coding/main/source/receiver.cc @@ -238,8 +238,9 @@ void VCMReceiver::ReceiveStatistics(uint32_t* bitrate, void VCMReceiver::ReceivedFrameCount(VCMFrameCount* frame_count) const { assert(frame_count); - jitter_buffer_.FrameStatistics(&frame_count->numDeltaFrames, - &frame_count->numKeyFrames); + std::map counts(jitter_buffer_.FrameStatistics()); + frame_count->numDeltaFrames = counts[kVideoFrameDelta]; + frame_count->numKeyFrames = counts[kVideoFrameKey]; } uint32_t VCMReceiver::DiscardedPackets() const { diff --git a/webrtc/video_engine/vie_channel.cc b/webrtc/video_engine/vie_channel.cc index 3a0cb74ac6..59c628edcf 100644 --- a/webrtc/video_engine/vie_channel.cc +++ b/webrtc/video_engine/vie_channel.cc @@ -356,6 +356,7 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec, module_process_thread_.DeRegisterModule(rtp_rtcp); rtp_rtcp->SetSendingStatus(false); rtp_rtcp->SetSendingMediaStatus(false); + rtp_rtcp->RegisterSendFrameCountObserver(NULL); simulcast_rtp_rtcp_.pop_back(); removed_rtp_rtcp_.push_front(rtp_rtcp); } @@ -410,6 +411,8 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec, kRtpExtensionAbsoluteSendTime); } rtp_rtcp->SetRtcpXrRrtrStatus(rtp_rtcp_->RtcpXrRrtrStatus()); + rtp_rtcp->RegisterSendFrameCountObserver( + rtp_rtcp_->GetSendFrameCountObserver()); } // |RegisterSimulcastRtpRtcpModules| resets all old weak pointers and old // modules can be deleted after this step. @@ -420,6 +423,7 @@ int32_t ViEChannel::SetSendCodec(const VideoCodec& video_codec, module_process_thread_.DeRegisterModule(rtp_rtcp); rtp_rtcp->SetSendingStatus(false); rtp_rtcp->SetSendingMediaStatus(false); + rtp_rtcp->RegisterSendFrameCountObserver(NULL); simulcast_rtp_rtcp_.pop_back(); removed_rtp_rtcp_.push_front(rtp_rtcp); } @@ -1971,4 +1975,15 @@ void ViEChannel::ResetStatistics(uint32_t ssrc) { statistician->ResetStatistics(); } +void ViEChannel::RegisterSendFrameCountObserver( + FrameCountObserver* observer) { + rtp_rtcp_->RegisterSendFrameCountObserver(observer); + CriticalSectionScoped cs(rtp_rtcp_cs_.get()); + for (std::list::iterator it = simulcast_rtp_rtcp_.begin(); + it != simulcast_rtp_rtcp_.end(); + it++) { + (*it)->RegisterSendFrameCountObserver(observer); + } +} + } // namespace webrtc diff --git a/webrtc/video_engine/vie_channel.h b/webrtc/video_engine/vie_channel.h index c9536f16e6..a16a65d513 100644 --- a/webrtc/video_engine/vie_channel.h +++ b/webrtc/video_engine/vie_channel.h @@ -326,6 +326,8 @@ class ViEChannel void RegisterPreDecodeImageCallback( EncodedImageCallback* pre_decode_callback); + void RegisterSendFrameCountObserver(FrameCountObserver* observer); + protected: static bool ChannelDecodeThreadFunction(void* obj); bool ChannelDecodeProcess(); diff --git a/webrtc/video_engine/vie_rtp_rtcp_impl.cc b/webrtc/video_engine/vie_rtp_rtcp_impl.cc index 7d3c8ad252..edad270be5 100644 --- a/webrtc/video_engine/vie_rtp_rtcp_impl.cc +++ b/webrtc/video_engine/vie_rtp_rtcp_impl.cc @@ -1178,16 +1178,39 @@ int ViERTP_RTCPImpl::DeregisterSendBitrateObserver( } int ViERTP_RTCPImpl::RegisterSendFrameCountObserver( - int channel, FrameCountObserver* callback) { - // TODO(sprang): Implement - return -1; + int video_channel, FrameCountObserver* callback) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d)", __FUNCTION__, video_channel); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); + shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); + return -1; + } + vie_channel->RegisterSendFrameCountObserver(callback); + return 0; } int ViERTP_RTCPImpl::DeregisterSendFrameCountObserver( - int channel, FrameCountObserver* callback) { - // TODO(sprang): Implement - return -1; + int video_channel, FrameCountObserver* callback) { + WEBRTC_TRACE(kTraceApiCall, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s(channel: %d)", __FUNCTION__, video_channel); + ViEChannelManagerScoped cs(*(shared_data_->channel_manager())); + ViEChannel* vie_channel = cs.Channel(video_channel); + if (!vie_channel) { + WEBRTC_TRACE(kTraceError, kTraceVideo, + ViEId(shared_data_->instance_id(), video_channel), + "%s: Channel %d doesn't exist", __FUNCTION__, video_channel); + shared_data_->SetLastError(kViERtpRtcpInvalidChannelId); + return -1; + } + vie_channel->RegisterSendFrameCountObserver(NULL); + return 0; } - } // namespace webrtc