Upstream version 5.34.92.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_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"
29
30 namespace webrtc {
31 namespace internal {
32
33 VideoReceiveStream::VideoReceiveStream(webrtc::VideoEngine* video_engine,
34                                        const VideoReceiveStream::Config& config,
35                                        newapi::Transport* transport,
36                                        webrtc::VoiceEngine* voice_engine,
37                                        int base_channel)
38     : transport_adapter_(transport),
39       encoded_frame_proxy_(config.pre_decode_callback),
40       config_(config),
41       channel_(-1) {
42   video_engine_base_ = ViEBase::GetInterface(video_engine);
43   video_engine_base_->CreateReceiveChannel(channel_, base_channel);
44   assert(channel_ != -1);
45
46   rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine);
47   assert(rtp_rtcp_ != NULL);
48
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);
55       break;
56     case newapi::kRtcpReducedSize:
57       rtp_rtcp_->SetRTCPStatus(channel_, kRtcpNonCompound_RFC5506);
58       break;
59   }
60
61   assert(config_.rtp.remote_ssrc != 0);
62   assert(config_.rtp.local_ssrc != 0);
63   assert(config_.rtp.remote_ssrc != config_.rtp.local_ssrc);
64
65   rtp_rtcp_->SetLocalSSRC(channel_, config_.rtp.local_ssrc);
66   rtp_rtcp_->SetRembStatus(channel_, false, config_.rtp.remb);
67
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)
73         abort();
74     } else if (extension == RtpExtension::kAbsSendTime) {
75       if (rtp_rtcp_->SetReceiveAbsoluteSendTimeStatus(channel_, true, id) != 0)
76         abort();
77     } else {
78       abort();  // Unsupported extension.
79     }
80   }
81
82   network_ = ViENetwork::GetInterface(video_engine);
83   assert(network_ != NULL);
84
85   network_->RegisterSendTransport(channel_, transport_adapter_);
86
87   codec_ = ViECodec::GetInterface(video_engine);
88
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.
93       abort();
94     }
95   }
96
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(
101             channel_,
102             decoder->payload_type,
103             decoder->decoder,
104             decoder->renderer,
105             decoder->expected_delay_ms) !=
106         0) {
107       // TODO(pbos): Abort gracefully? Can this be a runtime error?
108       abort();
109     }
110   }
111
112   render_ = ViERender::GetInterface(video_engine);
113   assert(render_ != NULL);
114
115   render_->AddRenderCallback(channel_, this);
116
117   if (voice_engine) {
118     video_engine_base_->SetVoiceEngine(voice_engine);
119     video_engine_base_->ConnectAudioChannel(channel_, config_.audio_channel_id);
120   }
121
122   image_process_ = ViEImageProcess::GetInterface(video_engine);
123   if (config.pre_decode_callback) {
124     image_process_->RegisterPreDecodeImageCallback(channel_,
125                                                    &encoded_frame_proxy_);
126   }
127   image_process_->RegisterPreRenderCallback(channel_,
128                                             config_.pre_render_callback);
129
130   if (config.rtp.rtcp_xr.receiver_reference_time_report) {
131     rtp_rtcp_->SetRtcpXrRrtrStatus(channel_, true);
132   }
133
134   clock_ = Clock::GetRealTimeClock();
135 }
136
137 VideoReceiveStream::~VideoReceiveStream() {
138   image_process_->DeRegisterPreRenderCallback(channel_);
139   image_process_->DeRegisterPreDecodeCallback(channel_);
140
141   render_->RemoveRenderer(channel_);
142
143   for (size_t i = 0; i < config_.external_decoders.size(); ++i) {
144     external_codec_->DeRegisterExternalReceiveCodec(
145         channel_, config_.external_decoders[i].payload_type);
146   }
147
148   network_->DeregisterSendTransport(channel_);
149
150   video_engine_base_->SetVoiceEngine(NULL);
151   image_process_->Release();
152   video_engine_base_->Release();
153   external_codec_->Release();
154   codec_->Release();
155   network_->Release();
156   render_->Release();
157   rtp_rtcp_->Release();
158 }
159
160 void VideoReceiveStream::StartReceiving() {
161   if (render_->StartRender(channel_) != 0)
162     abort();
163   if (video_engine_base_->StartReceive(channel_) != 0)
164     abort();
165 }
166
167 void VideoReceiveStream::StopReceiving() {
168   if (render_->StopRender(channel_) != 0)
169     abort();
170   if (video_engine_base_->StopReceive(channel_) != 0)
171     abort();
172 }
173
174 void VideoReceiveStream::GetCurrentReceiveCodec(VideoCodec* receive_codec) {
175   // TODO(pbos): Implement
176 }
177
178 bool VideoReceiveStream::DeliverRtcp(const uint8_t* packet, size_t length) {
179   return network_->ReceivedRTCPPacket(
180              channel_, packet, static_cast<int>(length)) == 0;
181 }
182
183 bool VideoReceiveStream::DeliverRtp(const uint8_t* packet, size_t length) {
184   return network_->ReceivedRTPPacket(
185              channel_, packet, static_cast<int>(length),
186              PacketTime()) == 0;
187 }
188
189 int32_t VideoReceiveStream::RenderFrame(const uint32_t stream_id,
190                                         I420VideoFrame& video_frame) {
191   if (config_.renderer == NULL)
192     return 0;
193
194   config_.renderer->RenderFrame(
195       video_frame, video_frame.render_time_ms() - clock_->TimeInMilliseconds());
196   return 0;
197 }
198 }  // namespace internal
199 }  // namespace webrtc