2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
11 #include "webrtc/video/video_receive_stream.h"
18 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
19 #include "webrtc/system_wrappers/interface/clock.h"
20 #include "webrtc/video_engine/include/vie_base.h"
21 #include "webrtc/video_engine/include/vie_capture.h"
22 #include "webrtc/video_engine/include/vie_codec.h"
23 #include "webrtc/video_engine/include/vie_external_codec.h"
24 #include "webrtc/video_engine/include/vie_image_process.h"
25 #include "webrtc/video_engine/include/vie_network.h"
26 #include "webrtc/video_engine/include/vie_render.h"
27 #include "webrtc/video_engine/include/vie_rtp_rtcp.h"
28 #include "webrtc/video_receive_stream.h"
33 VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine,
34 const VideoReceiveStream::Config& config,
35 newapi::Transport* transport,
36 webrtc::VoiceEngine* voice_engine,
38 : transport_adapter_(transport),
39 encoded_frame_proxy_(config.pre_decode_callback),
42 video_engine_base_ = ViEBase::GetInterface(video_engine);
43 video_engine_base_->CreateReceiveChannel(channel_, base_channel);
44 assert(channel_ != -1);
46 rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine);
47 assert(rtp_rtcp_ != NULL);
49 // TODO(pbos): This is not fine grained enough...
50 rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0);
51 rtp_rtcp_->SetKeyFrameRequestMethod(channel_, kViEKeyFrameRequestPliRtcp);
52 switch (config_.rtp.rtcp_mode) {
53 case newapi::kRtcpCompound:
54 rtp_rtcp_->SetRTCPStatus(channel_, kRtcpCompound_RFC4585);
56 case newapi::kRtcpReducedSize:
57 rtp_rtcp_->SetRTCPStatus(channel_, kRtcpNonCompound_RFC5506);
61 assert(config_.rtp.remote_ssrc != 0);
62 assert(config_.rtp.local_ssrc != 0);
63 assert(config_.rtp.remote_ssrc != config_.rtp.local_ssrc);
65 rtp_rtcp_->SetLocalSSRC(channel_, config_.rtp.local_ssrc);
66 rtp_rtcp_->SetRembStatus(channel_, false, config_.rtp.remb);
68 for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) {
69 const std::string& extension = config_.rtp.extensions[i].name;
70 int id = config_.rtp.extensions[i].id;
71 if (extension == RtpExtension::kTOffset) {
72 if (rtp_rtcp_->SetReceiveTimestampOffsetStatus(channel_, true, id) != 0)
74 } else if (extension == RtpExtension::kAbsSendTime) {
75 if (rtp_rtcp_->SetReceiveAbsoluteSendTimeStatus(channel_, true, id) != 0)
78 abort(); // Unsupported extension.
82 network_ = ViENetwork::GetInterface(video_engine);
83 assert(network_ != NULL);
85 network_->RegisterSendTransport(channel_, transport_adapter_);
87 codec_ = ViECodec::GetInterface(video_engine);
89 for (size_t i = 0; i < config_.codecs.size(); ++i) {
90 if (codec_->SetReceiveCodec(channel_, config_.codecs[i]) != 0) {
91 // TODO(pbos): Abort gracefully, this can be a runtime error.
92 // Factor out to an Init() method.
97 external_codec_ = ViEExternalCodec::GetInterface(video_engine);
98 for (size_t i = 0; i < config_.external_decoders.size(); ++i) {
99 ExternalVideoDecoder* decoder = &config_.external_decoders[i];
100 if (external_codec_->RegisterExternalReceiveCodec(
102 decoder->payload_type,
105 decoder->expected_delay_ms) !=
107 // TODO(pbos): Abort gracefully? Can this be a runtime error?
112 render_ = ViERender::GetInterface(video_engine);
113 assert(render_ != NULL);
115 render_->AddRenderCallback(channel_, this);
118 video_engine_base_->SetVoiceEngine(voice_engine);
119 video_engine_base_->ConnectAudioChannel(channel_, config_.audio_channel_id);
122 image_process_ = ViEImageProcess::GetInterface(video_engine);
123 if (config.pre_decode_callback) {
124 image_process_->RegisterPreDecodeImageCallback(channel_,
125 &encoded_frame_proxy_);
127 image_process_->RegisterPreRenderCallback(channel_,
128 config_.pre_render_callback);
130 if (config.rtp.rtcp_xr.receiver_reference_time_report) {
131 rtp_rtcp_->SetRtcpXrRrtrStatus(channel_, true);
134 clock_ = Clock::GetRealTimeClock();
137 VideoReceiveStream::~VideoReceiveStream() {
138 image_process_->DeRegisterPreRenderCallback(channel_);
139 image_process_->DeRegisterPreDecodeCallback(channel_);
141 render_->RemoveRenderer(channel_);
143 for (size_t i = 0; i < config_.external_decoders.size(); ++i) {
144 external_codec_->DeRegisterExternalReceiveCodec(
145 channel_, config_.external_decoders[i].payload_type);
148 network_->DeregisterSendTransport(channel_);
150 video_engine_base_->SetVoiceEngine(NULL);
151 image_process_->Release();
152 video_engine_base_->Release();
153 external_codec_->Release();
157 rtp_rtcp_->Release();
160 void VideoReceiveStream::StartReceiving() {
161 if (render_->StartRender(channel_) != 0)
163 if (video_engine_base_->StartReceive(channel_) != 0)
167 void VideoReceiveStream::StopReceiving() {
168 if (render_->StopRender(channel_) != 0)
170 if (video_engine_base_->StopReceive(channel_) != 0)
174 void VideoReceiveStream::GetCurrentReceiveCodec(VideoCodec* receive_codec) {
175 // TODO(pbos): Implement
178 bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
179 return network_->ReceivedRTCPPacket(
180 channel_, packet, static_cast<int>(length)) == 0;
183 bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, size_t length) {
184 return network_->ReceivedRTPPacket(
185 channel_, packet, static_cast<int>(length),
189 int32_t VideoReceiveStream::RenderFrame(const uint32_t stream_id,
190 I420VideoFrame& video_frame) {
191 if (config_.renderer == NULL)
194 config_.renderer->RenderFrame(
195 video_frame, video_frame.render_time_ms() - clock_->TimeInMilliseconds());
198 } // namespace internal
199 } // namespace webrtc