Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / video / video_receive_stream.cc
1 /*
2  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3  *
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.
9  */
10
11 #include "webrtc/video/video_receive_stream.h"
12
13 #include <assert.h>
14 #include <stdlib.h>
15
16 #include <string>
17
18 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
19 #include "webrtc/system_wrappers/interface/clock.h"
20 #include "webrtc/video/receive_statistics_proxy.h"
21 #include "webrtc/video_engine/include/vie_base.h"
22 #include "webrtc/video_engine/include/vie_capture.h"
23 #include "webrtc/video_engine/include/vie_codec.h"
24 #include "webrtc/video_engine/include/vie_external_codec.h"
25 #include "webrtc/video_engine/include/vie_image_process.h"
26 #include "webrtc/video_engine/include/vie_network.h"
27 #include "webrtc/video_engine/include/vie_render.h"
28 #include "webrtc/video_engine/include/vie_rtp_rtcp.h"
29 #include "webrtc/video_receive_stream.h"
30
31 namespace webrtc {
32 namespace internal {
33
34 VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine,
35                                        const VideoReceiveStream::Config& config,
36                                        newapi::Transport* transport,
37                                        webrtc::VoiceEngine* voice_engine,
38                                        int base_channel)
39     : transport_adapter_(transport),
40       encoded_frame_proxy_(config.pre_decode_callback),
41       config_(config),
42       clock_(Clock::GetRealTimeClock()),
43       channel_(-1) {
44   video_engine_base_ = ViEBase::GetInterface(video_engine);
45   video_engine_base_->CreateReceiveChannel(channel_, base_channel);
46   assert(channel_ != -1);
47
48   rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine);
49   assert(rtp_rtcp_ != NULL);
50
51   // TODO(pbos): This is not fine grained enough...
52   rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0);
53   rtp_rtcp_->SetKeyFrameRequestMethod(channel_, kViEKeyFrameRequestPliRtcp);
54   switch (config_.rtp.rtcp_mode) {
55     case newapi::kRtcpCompound:
56       rtp_rtcp_->SetRTCPStatus(channel_, kRtcpCompound_RFC4585);
57       break;
58     case newapi::kRtcpReducedSize:
59       rtp_rtcp_->SetRTCPStatus(channel_, kRtcpNonCompound_RFC5506);
60       break;
61   }
62
63   assert(config_.rtp.remote_ssrc != 0);
64   // TODO(pbos): What's an appropriate local_ssrc for receive-only streams?
65   assert(config_.rtp.local_ssrc != 0);
66   assert(config_.rtp.remote_ssrc != config_.rtp.local_ssrc);
67
68   rtp_rtcp_->SetLocalSSRC(channel_, config_.rtp.local_ssrc);
69   // TODO(pbos): Support multiple RTX, per video payload.
70   Config::Rtp::RtxMap::const_iterator it = config_.rtp.rtx.begin();
71   if (it != config_.rtp.rtx.end()) {
72     assert(it->second.ssrc != 0);
73     assert(it->second.payload_type != 0);
74
75     rtp_rtcp_->SetRemoteSSRCType(channel_, kViEStreamTypeRtx, it->second.ssrc);
76     rtp_rtcp_->SetRtxReceivePayloadType(channel_, it->second.payload_type);
77   }
78
79   rtp_rtcp_->SetRembStatus(channel_, false, config_.rtp.remb);
80
81   for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) {
82     const std::string& extension = config_.rtp.extensions[i].name;
83     int id = config_.rtp.extensions[i].id;
84     if (extension == RtpExtension::kTOffset) {
85       if (rtp_rtcp_->SetReceiveTimestampOffsetStatus(channel_, true, id) != 0)
86         abort();
87     } else if (extension == RtpExtension::kAbsSendTime) {
88       if (rtp_rtcp_->SetReceiveAbsoluteSendTimeStatus(channel_, true, id) != 0)
89         abort();
90     } else {
91       abort();  // Unsupported extension.
92     }
93   }
94
95   network_ = ViENetwork::GetInterface(video_engine);
96   assert(network_ != NULL);
97
98   network_->RegisterSendTransport(channel_, transport_adapter_);
99
100   codec_ = ViECodec::GetInterface(video_engine);
101
102   for (size_t i = 0; i < config_.codecs.size(); ++i) {
103     if (codec_->SetReceiveCodec(channel_, config_.codecs[i]) != 0) {
104       // TODO(pbos): Abort gracefully, this can be a runtime error.
105       //             Factor out to an Init() method.
106       abort();
107     }
108   }
109
110   stats_proxy_.reset(new ReceiveStatisticsProxy(
111       config_.rtp.local_ssrc, clock_, rtp_rtcp_, codec_, channel_));
112
113   if (rtp_rtcp_->RegisterReceiveChannelRtcpStatisticsCallback(
114           channel_, stats_proxy_.get()) != 0)
115     abort();
116
117   if (rtp_rtcp_->RegisterReceiveChannelRtpStatisticsCallback(
118           channel_, stats_proxy_.get()) != 0)
119     abort();
120
121   if (codec_->RegisterDecoderObserver(channel_, *stats_proxy_) != 0)
122     abort();
123
124   external_codec_ = ViEExternalCodec::GetInterface(video_engine);
125   for (size_t i = 0; i < config_.external_decoders.size(); ++i) {
126     ExternalVideoDecoder* decoder = &config_.external_decoders[i];
127     if (external_codec_->RegisterExternalReceiveCodec(
128             channel_,
129             decoder->payload_type,
130             decoder->decoder,
131             decoder->renderer,
132             decoder->expected_delay_ms) != 0) {
133       // TODO(pbos): Abort gracefully? Can this be a runtime error?
134       abort();
135     }
136   }
137
138   render_ = ViERender::GetInterface(video_engine);
139   assert(render_ != NULL);
140
141   render_->AddRenderCallback(channel_, this);
142
143   if (voice_engine) {
144     video_engine_base_->SetVoiceEngine(voice_engine);
145     video_engine_base_->ConnectAudioChannel(channel_, config_.audio_channel_id);
146   }
147
148   image_process_ = ViEImageProcess::GetInterface(video_engine);
149   if (config.pre_decode_callback) {
150     image_process_->RegisterPreDecodeImageCallback(channel_,
151                                                    &encoded_frame_proxy_);
152   }
153   image_process_->RegisterPreRenderCallback(channel_, this);
154
155   if (config.rtp.rtcp_xr.receiver_reference_time_report) {
156     rtp_rtcp_->SetRtcpXrRrtrStatus(channel_, true);
157   }
158 }
159
160 VideoReceiveStream::~VideoReceiveStream() {
161   image_process_->DeRegisterPreRenderCallback(channel_);
162   image_process_->DeRegisterPreDecodeCallback(channel_);
163
164   render_->RemoveRenderer(channel_);
165
166   for (size_t i = 0; i < config_.external_decoders.size(); ++i) {
167     external_codec_->DeRegisterExternalReceiveCodec(
168         channel_, config_.external_decoders[i].payload_type);
169   }
170
171   network_->DeregisterSendTransport(channel_);
172
173   video_engine_base_->SetVoiceEngine(NULL);
174   image_process_->Release();
175   video_engine_base_->Release();
176   external_codec_->Release();
177   codec_->DeregisterDecoderObserver(channel_);
178   rtp_rtcp_->DeregisterReceiveChannelRtpStatisticsCallback(channel_,
179                                                            stats_proxy_.get());
180   rtp_rtcp_->DeregisterReceiveChannelRtcpStatisticsCallback(channel_,
181                                                             stats_proxy_.get());
182   codec_->Release();
183   network_->Release();
184   render_->Release();
185   rtp_rtcp_->Release();
186 }
187
188 void VideoReceiveStream::StartReceiving() {
189   transport_adapter_.Enable();
190   if (render_->StartRender(channel_) != 0)
191     abort();
192   if (video_engine_base_->StartReceive(channel_) != 0)
193     abort();
194 }
195
196 void VideoReceiveStream::StopReceiving() {
197   if (render_->StopRender(channel_) != 0)
198     abort();
199   if (video_engine_base_->StopReceive(channel_) != 0)
200     abort();
201   transport_adapter_.Disable();
202 }
203
204 VideoReceiveStream::Stats VideoReceiveStream::GetStats() const {
205   return stats_proxy_->GetStats();
206 }
207
208 void VideoReceiveStream::GetCurrentReceiveCodec(VideoCodec* receive_codec) {
209   // TODO(pbos): Implement
210 }
211
212 bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
213   return network_->ReceivedRTCPPacket(
214              channel_, packet, static_cast<int>(length)) == 0;
215 }
216
217 bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, size_t length) {
218   return network_->ReceivedRTPPacket(
219              channel_, packet, static_cast<int>(length), PacketTime()) == 0;
220 }
221
222 void VideoReceiveStream::FrameCallback(I420VideoFrame* video_frame) {
223   stats_proxy_->OnDecodedFrame();
224
225   if (config_.pre_render_callback)
226     config_.pre_render_callback->FrameCallback(video_frame);
227 }
228
229 int32_t VideoReceiveStream::RenderFrame(const uint32_t stream_id,
230                                         I420VideoFrame& video_frame) {
231   if (config_.renderer != NULL)
232     config_.renderer->RenderFrame(
233         video_frame,
234         video_frame.render_time_ms() - clock_->TimeInMilliseconds());
235
236   stats_proxy_->OnRenderedFrame();
237
238   return 0;
239 }
240 }  // namespace internal
241 }  // namespace webrtc