Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / video / video_send_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_send_stream.h"
12
13 #include <string>
14 #include <vector>
15
16 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
17 #include "webrtc/video_engine/include/vie_base.h"
18 #include "webrtc/video_engine/include/vie_capture.h"
19 #include "webrtc/video_engine/include/vie_codec.h"
20 #include "webrtc/video_engine/include/vie_external_codec.h"
21 #include "webrtc/video_engine/include/vie_image_process.h"
22 #include "webrtc/video_engine/include/vie_network.h"
23 #include "webrtc/video_engine/include/vie_rtp_rtcp.h"
24 #include "webrtc/video_engine/vie_defines.h"
25 #include "webrtc/video_send_stream.h"
26
27 namespace webrtc {
28 namespace internal {
29
30 VideoSendStream::VideoSendStream(newapi::Transport* transport,
31                                  CpuOveruseObserver* overuse_observer,
32                                  webrtc::VideoEngine* video_engine,
33                                  const VideoSendStream::Config& config,
34                                  int base_channel)
35     : transport_adapter_(transport),
36       encoded_frame_proxy_(config.post_encode_callback),
37       codec_lock_(CriticalSectionWrapper::CreateCriticalSection()),
38       config_(config),
39       external_codec_(NULL),
40       channel_(-1),
41       stats_proxy_(new SendStatisticsProxy(config, this)) {
42   video_engine_base_ = ViEBase::GetInterface(video_engine);
43   video_engine_base_->CreateChannel(channel_, base_channel);
44   assert(channel_ != -1);
45
46   rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine);
47   assert(rtp_rtcp_ != NULL);
48
49   assert(config_.rtp.ssrcs.size() > 0);
50   if (config_.suspend_below_min_bitrate)
51     config_.pacing = true;
52   rtp_rtcp_->SetTransmissionSmoothingStatus(channel_, config_.pacing);
53
54   assert(config_.rtp.min_transmit_bitrate_bps >= 0);
55   rtp_rtcp_->SetMinTransmitBitrate(channel_,
56                                    config_.rtp.min_transmit_bitrate_bps / 1000);
57
58   for (size_t i = 0; i < config_.rtp.extensions.size(); ++i) {
59     const std::string& extension = config_.rtp.extensions[i].name;
60     int id = config_.rtp.extensions[i].id;
61     if (extension == RtpExtension::kTOffset) {
62       if (rtp_rtcp_->SetSendTimestampOffsetStatus(channel_, true, id) != 0)
63         abort();
64     } else if (extension == RtpExtension::kAbsSendTime) {
65       if (rtp_rtcp_->SetSendAbsoluteSendTimeStatus(channel_, true, id) != 0)
66         abort();
67     } else {
68       abort();  // Unsupported extension.
69     }
70   }
71
72   rtp_rtcp_->SetRembStatus(channel_, true, false);
73
74   // Enable NACK, FEC or both.
75   if (config_.rtp.fec.red_payload_type != -1) {
76     assert(config_.rtp.fec.ulpfec_payload_type != -1);
77     if (config_.rtp.nack.rtp_history_ms > 0) {
78       rtp_rtcp_->SetHybridNACKFECStatus(
79           channel_,
80           true,
81           static_cast<unsigned char>(config_.rtp.fec.red_payload_type),
82           static_cast<unsigned char>(config_.rtp.fec.ulpfec_payload_type));
83     } else {
84       rtp_rtcp_->SetFECStatus(
85           channel_,
86           true,
87           static_cast<unsigned char>(config_.rtp.fec.red_payload_type),
88           static_cast<unsigned char>(config_.rtp.fec.ulpfec_payload_type));
89     }
90   } else {
91     rtp_rtcp_->SetNACKStatus(channel_, config_.rtp.nack.rtp_history_ms > 0);
92   }
93
94   char rtcp_cname[ViERTP_RTCP::KMaxRTCPCNameLength];
95   assert(config_.rtp.c_name.length() < ViERTP_RTCP::KMaxRTCPCNameLength);
96   strncpy(rtcp_cname, config_.rtp.c_name.c_str(), sizeof(rtcp_cname) - 1);
97   rtcp_cname[sizeof(rtcp_cname) - 1] = '\0';
98
99   rtp_rtcp_->SetRTCPCName(channel_, rtcp_cname);
100
101   capture_ = ViECapture::GetInterface(video_engine);
102   capture_->AllocateExternalCaptureDevice(capture_id_, external_capture_);
103   capture_->ConnectCaptureDevice(capture_id_, channel_);
104
105   network_ = ViENetwork::GetInterface(video_engine);
106   assert(network_ != NULL);
107
108   network_->RegisterSendTransport(channel_, transport_adapter_);
109   // 28 to match packet overhead in ModuleRtpRtcpImpl.
110   network_->SetMTU(channel_,
111                    static_cast<unsigned int>(config_.rtp.max_packet_size + 28));
112
113   assert(config.encoder_settings.encoder != NULL);
114   assert(config.encoder_settings.payload_type >= 0);
115   assert(config.encoder_settings.payload_type <= 127);
116   external_codec_ = ViEExternalCodec::GetInterface(video_engine);
117   if (external_codec_->RegisterExternalSendCodec(
118           channel_,
119           config.encoder_settings.payload_type,
120           config.encoder_settings.encoder,
121           false) != 0) {
122     abort();
123   }
124
125   codec_ = ViECodec::GetInterface(video_engine);
126   if (!ReconfigureVideoEncoder(config_.encoder_settings.streams,
127                                config_.encoder_settings.encoder_settings)) {
128     abort();
129   }
130
131   if (overuse_observer)
132     video_engine_base_->RegisterCpuOveruseObserver(channel_, overuse_observer);
133
134   image_process_ = ViEImageProcess::GetInterface(video_engine);
135   image_process_->RegisterPreEncodeCallback(channel_,
136                                             config_.pre_encode_callback);
137   if (config_.post_encode_callback) {
138     image_process_->RegisterPostEncodeImageCallback(channel_,
139                                                     &encoded_frame_proxy_);
140   }
141
142   if (config_.suspend_below_min_bitrate) {
143     codec_->SuspendBelowMinBitrate(channel_);
144   }
145
146   rtp_rtcp_->RegisterSendChannelRtcpStatisticsCallback(channel_,
147                                                        stats_proxy_.get());
148   rtp_rtcp_->RegisterSendChannelRtpStatisticsCallback(channel_,
149                                                       stats_proxy_.get());
150   rtp_rtcp_->RegisterSendBitrateObserver(channel_, stats_proxy_.get());
151   rtp_rtcp_->RegisterSendFrameCountObserver(channel_, stats_proxy_.get());
152
153   codec_->RegisterEncoderObserver(channel_, *stats_proxy_);
154   capture_->RegisterObserver(capture_id_, *stats_proxy_);
155 }
156
157 VideoSendStream::~VideoSendStream() {
158   capture_->DeregisterObserver(capture_id_);
159   codec_->DeregisterEncoderObserver(channel_);
160
161   rtp_rtcp_->DeregisterSendFrameCountObserver(channel_, stats_proxy_.get());
162   rtp_rtcp_->DeregisterSendBitrateObserver(channel_, stats_proxy_.get());
163   rtp_rtcp_->DeregisterSendChannelRtpStatisticsCallback(channel_,
164                                                         stats_proxy_.get());
165   rtp_rtcp_->DeregisterSendChannelRtcpStatisticsCallback(channel_,
166                                                          stats_proxy_.get());
167
168   image_process_->DeRegisterPreEncodeCallback(channel_);
169
170   network_->DeregisterSendTransport(channel_);
171
172   capture_->DisconnectCaptureDevice(channel_);
173   capture_->ReleaseCaptureDevice(capture_id_);
174
175   external_codec_->DeRegisterExternalSendCodec(
176       channel_, config_.encoder_settings.payload_type);
177
178   video_engine_base_->DeleteChannel(channel_);
179
180   image_process_->Release();
181   video_engine_base_->Release();
182   capture_->Release();
183   codec_->Release();
184   if (external_codec_)
185     external_codec_->Release();
186   network_->Release();
187   rtp_rtcp_->Release();
188 }
189
190 void VideoSendStream::PutFrame(const I420VideoFrame& frame) {
191   input_frame_.CopyFrame(frame);
192   SwapFrame(&input_frame_);
193 }
194
195 void VideoSendStream::SwapFrame(I420VideoFrame* frame) {
196   // TODO(pbos): Warn if frame is "too far" into the future, or too old. This
197   //             would help detect if frame's being used without NTP.
198   //             TO REVIEWER: Is there any good check for this? Should it be
199   //             skipped?
200   if (frame != &input_frame_)
201     input_frame_.SwapFrame(frame);
202
203   // TODO(pbos): Local rendering should not be done on the capture thread.
204   if (config_.local_renderer != NULL)
205     config_.local_renderer->RenderFrame(input_frame_, 0);
206
207   external_capture_->SwapFrame(&input_frame_);
208 }
209
210 VideoSendStreamInput* VideoSendStream::Input() { return this; }
211
212 void VideoSendStream::Start() {
213   transport_adapter_.Enable();
214   video_engine_base_->StartSend(channel_);
215   video_engine_base_->StartReceive(channel_);
216 }
217
218 void VideoSendStream::Stop() {
219   video_engine_base_->StopSend(channel_);
220   video_engine_base_->StopReceive(channel_);
221   transport_adapter_.Disable();
222 }
223
224 bool VideoSendStream::ReconfigureVideoEncoder(
225     const std::vector<VideoStream>& streams,
226     void* encoder_settings) {
227   assert(!streams.empty());
228   assert(config_.rtp.ssrcs.size() >= streams.size());
229   // TODO(pbos): Wire encoder_settings.
230   assert(encoder_settings == NULL);
231
232   // VideoStreams in config_.encoder_settings need to be locked.
233   CriticalSectionScoped crit(codec_lock_.get());
234
235   VideoCodec video_codec;
236   memset(&video_codec, 0, sizeof(video_codec));
237   video_codec.codecType =
238       (config_.encoder_settings.payload_name == "VP8" ? kVideoCodecVP8
239                                                       : kVideoCodecGeneric);
240
241   if (video_codec.codecType == kVideoCodecVP8) {
242     video_codec.codecSpecific.VP8.resilience = kResilientStream;
243     video_codec.codecSpecific.VP8.numberOfTemporalLayers = 1;
244     video_codec.codecSpecific.VP8.denoisingOn = true;
245     video_codec.codecSpecific.VP8.errorConcealmentOn = false;
246     video_codec.codecSpecific.VP8.automaticResizeOn = false;
247     video_codec.codecSpecific.VP8.frameDroppingOn = true;
248     video_codec.codecSpecific.VP8.keyFrameInterval = 3000;
249   }
250
251   strncpy(video_codec.plName,
252           config_.encoder_settings.payload_name.c_str(),
253           kPayloadNameSize - 1);
254   video_codec.plName[kPayloadNameSize - 1] = '\0';
255   video_codec.plType = config_.encoder_settings.payload_type;
256   video_codec.numberOfSimulcastStreams =
257       static_cast<unsigned char>(streams.size());
258   video_codec.minBitrate = streams[0].min_bitrate_bps / 1000;
259   assert(streams.size() <= kMaxSimulcastStreams);
260   for (size_t i = 0; i < streams.size(); ++i) {
261     SimulcastStream* sim_stream = &video_codec.simulcastStream[i];
262     assert(streams[i].width > 0);
263     assert(streams[i].height > 0);
264     assert(streams[i].max_framerate > 0);
265     // Different framerates not supported per stream at the moment.
266     assert(streams[i].max_framerate == streams[0].max_framerate);
267     assert(streams[i].min_bitrate_bps >= 0);
268     assert(streams[i].target_bitrate_bps >= streams[i].min_bitrate_bps);
269     assert(streams[i].max_bitrate_bps >= streams[i].target_bitrate_bps);
270     assert(streams[i].max_qp >= 0);
271
272     sim_stream->width = static_cast<unsigned short>(streams[i].width);
273     sim_stream->height = static_cast<unsigned short>(streams[i].height);
274     sim_stream->minBitrate = streams[i].min_bitrate_bps / 1000;
275     sim_stream->targetBitrate = streams[i].target_bitrate_bps / 1000;
276     sim_stream->maxBitrate = streams[i].max_bitrate_bps / 1000;
277     sim_stream->qpMax = streams[i].max_qp;
278     // TODO(pbos): Implement mapping for temporal layers.
279     assert(streams[i].temporal_layers.empty());
280
281     video_codec.width = std::max(video_codec.width,
282                                  static_cast<unsigned short>(streams[i].width));
283     video_codec.height = std::max(
284         video_codec.height, static_cast<unsigned short>(streams[i].height));
285     video_codec.minBitrate =
286         std::min(video_codec.minBitrate,
287                  static_cast<unsigned int>(streams[i].min_bitrate_bps / 1000));
288     video_codec.maxBitrate += streams[i].max_bitrate_bps / 1000;
289     video_codec.qpMax = std::max(video_codec.qpMax,
290                                  static_cast<unsigned int>(streams[i].max_qp));
291   }
292
293   if (video_codec.minBitrate < kViEMinCodecBitrate)
294     video_codec.minBitrate = kViEMinCodecBitrate;
295   if (video_codec.maxBitrate < kViEMinCodecBitrate)
296     video_codec.maxBitrate = kViEMinCodecBitrate;
297
298   video_codec.startBitrate = 300;
299
300   if (video_codec.startBitrate < video_codec.minBitrate)
301     video_codec.startBitrate = video_codec.minBitrate;
302   if (video_codec.startBitrate > video_codec.maxBitrate)
303     video_codec.startBitrate = video_codec.maxBitrate;
304
305   assert(config_.encoder_settings.streams[0].max_framerate > 0);
306   video_codec.maxFramerate = config_.encoder_settings.streams[0].max_framerate;
307
308   if (codec_->SetSendCodec(channel_, video_codec) != 0)
309     return false;
310
311   for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
312     rtp_rtcp_->SetLocalSSRC(channel_,
313                             config_.rtp.ssrcs[i],
314                             kViEStreamTypeNormal,
315                             static_cast<unsigned char>(i));
316   }
317
318   config_.encoder_settings.streams = streams;
319   config_.encoder_settings.encoder_settings = encoder_settings;
320
321   if (config_.rtp.rtx.ssrcs.empty())
322     return true;
323
324   // Set up RTX.
325   assert(config_.rtp.rtx.ssrcs.size() == config_.rtp.ssrcs.size());
326   for (size_t i = 0; i < config_.rtp.ssrcs.size(); ++i) {
327     rtp_rtcp_->SetLocalSSRC(channel_,
328                             config_.rtp.rtx.ssrcs[i],
329                             kViEStreamTypeRtx,
330                             static_cast<unsigned char>(i));
331   }
332
333   if (config_.rtp.rtx.payload_type != 0)
334     rtp_rtcp_->SetRtxSendPayloadType(channel_, config_.rtp.rtx.payload_type);
335
336   return true;
337 }
338
339 bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
340   return network_->ReceivedRTCPPacket(
341              channel_, packet, static_cast<int>(length)) == 0;
342 }
343
344 VideoSendStream::Stats VideoSendStream::GetStats() const {
345   return stats_proxy_->GetStats();
346 }
347
348 bool VideoSendStream::GetSendSideDelay(VideoSendStream::Stats* stats) {
349   return codec_->GetSendSideDelay(
350       channel_, &stats->avg_delay_ms, &stats->max_delay_ms);
351 }
352
353 std::string VideoSendStream::GetCName() {
354   char rtcp_cname[ViERTP_RTCP::KMaxRTCPCNameLength];
355   rtp_rtcp_->GetRTCPCName(channel_, rtcp_cname);
356   return rtcp_cname;
357 }
358
359 }  // namespace internal
360 }  // namespace webrtc