#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
#include "webrtc/system_wrappers/interface/clock.h"
+#include "webrtc/video/receive_statistics_proxy.h"
#include "webrtc/video_engine/include/vie_base.h"
#include "webrtc/video_engine/include/vie_capture.h"
#include "webrtc/video_engine/include/vie_codec.h"
: transport_adapter_(transport),
encoded_frame_proxy_(config.pre_decode_callback),
config_(config),
+ clock_(Clock::GetRealTimeClock()),
channel_(-1) {
video_engine_base_ = ViEBase::GetInterface(video_engine);
video_engine_base_->CreateReceiveChannel(channel_, base_channel);
}
assert(config_.rtp.remote_ssrc != 0);
+ // TODO(pbos): What's an appropriate local_ssrc for receive-only streams?
assert(config_.rtp.local_ssrc != 0);
assert(config_.rtp.remote_ssrc != config_.rtp.local_ssrc);
rtp_rtcp_->SetLocalSSRC(channel_, config_.rtp.local_ssrc);
+ // TODO(pbos): Support multiple RTX, per video payload.
+ Config::Rtp::RtxMap::const_iterator it = config_.rtp.rtx.begin();
+ if (it != config_.rtp.rtx.end()) {
+ assert(it->second.ssrc != 0);
+ assert(it->second.payload_type != 0);
+
+ rtp_rtcp_->SetRemoteSSRCType(channel_, kViEStreamTypeRtx, it->second.ssrc);
+ rtp_rtcp_->SetRtxReceivePayloadType(channel_, it->second.payload_type);
+ }
+
rtp_rtcp_->SetRembStatus(channel_, false, config_.rtp.remb);
for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) {
}
}
+ stats_proxy_.reset(new ReceiveStatisticsProxy(
+ config_.rtp.local_ssrc, clock_, rtp_rtcp_, codec_, channel_));
+
+ if (rtp_rtcp_->RegisterReceiveChannelRtcpStatisticsCallback(
+ channel_, stats_proxy_.get()) != 0)
+ abort();
+
+ if (rtp_rtcp_->RegisterReceiveChannelRtpStatisticsCallback(
+ channel_, stats_proxy_.get()) != 0)
+ abort();
+
+ if (codec_->RegisterDecoderObserver(channel_, *stats_proxy_) != 0)
+ abort();
+
external_codec_ = ViEExternalCodec::GetInterface(video_engine);
for (size_t i = 0; i < config_.external_decoders.size(); ++i) {
ExternalVideoDecoder* decoder = &config_.external_decoders[i];
decoder->payload_type,
decoder->decoder,
decoder->renderer,
- decoder->expected_delay_ms) !=
- 0) {
+ decoder->expected_delay_ms) != 0) {
// TODO(pbos): Abort gracefully? Can this be a runtime error?
abort();
}
image_process_->RegisterPreDecodeImageCallback(channel_,
&encoded_frame_proxy_);
}
- image_process_->RegisterPreRenderCallback(channel_,
- config_.pre_render_callback);
+ image_process_->RegisterPreRenderCallback(channel_, this);
if (config.rtp.rtcp_xr.receiver_reference_time_report) {
rtp_rtcp_->SetRtcpXrRrtrStatus(channel_, true);
}
-
- clock_ = Clock::GetRealTimeClock();
}
VideoReceiveStream::~VideoReceiveStream() {
image_process_->Release();
video_engine_base_->Release();
external_codec_->Release();
+ codec_->DeregisterDecoderObserver(channel_);
+ rtp_rtcp_->DeregisterReceiveChannelRtpStatisticsCallback(channel_,
+ stats_proxy_.get());
+ rtp_rtcp_->DeregisterReceiveChannelRtcpStatisticsCallback(channel_,
+ stats_proxy_.get());
codec_->Release();
network_->Release();
render_->Release();
}
void VideoReceiveStream::StartReceiving() {
+ transport_adapter_.Enable();
if (render_->StartRender(channel_) != 0)
abort();
if (video_engine_base_->StartReceive(channel_) != 0)
abort();
if (video_engine_base_->StopReceive(channel_) != 0)
abort();
+ transport_adapter_.Disable();
+}
+
+VideoReceiveStream::Stats VideoReceiveStream::GetStats() const {
+ return stats_proxy_->GetStats();
}
void VideoReceiveStream::GetCurrentReceiveCodec(VideoCodec* receive_codec) {
bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, size_t length) {
return network_->ReceivedRTPPacket(
- channel_, packet, static_cast<int>(length),
- PacketTime()) == 0;
+ channel_, packet, static_cast<int>(length), PacketTime()) == 0;
+}
+
+void VideoReceiveStream::FrameCallback(I420VideoFrame* video_frame) {
+ stats_proxy_->OnDecodedFrame();
+
+ if (config_.pre_render_callback)
+ config_.pre_render_callback->FrameCallback(video_frame);
}
int32_t VideoReceiveStream::RenderFrame(const uint32_t stream_id,
I420VideoFrame& video_frame) {
- if (config_.renderer == NULL)
- return 0;
+ if (config_.renderer != NULL)
+ config_.renderer->RenderFrame(
+ video_frame,
+ video_frame.render_time_ms() - clock_->TimeInMilliseconds());
+
+ stats_proxy_->OnRenderedFrame();
- config_.renderer->RenderFrame(
- video_frame, video_frame.render_time_ms() - clock_->TimeInMilliseconds());
return 0;
}
} // namespace internal