blob: e0df6fe1ecd7f5dba52fe6bdc095edcb70dc6009 [file] [log] [blame]
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001/*
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
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000011#include <assert.h>
12#include <string.h>
13
pbos@webrtc.org29d58392013-05-16 12:08:03 +000014#include <map>
15#include <vector>
16
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000017#include "webrtc/call.h"
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +000018#include "webrtc/common.h"
pbos@webrtc.orgc49d5b72013-12-05 12:11:47 +000019#include "webrtc/config.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000020#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
pbos@webrtc.orgde74b642013-10-02 13:36:09 +000021#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000022#include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
pbos@webrtc.orgde74b642013-10-02 13:36:09 +000023#include "webrtc/system_wrappers/interface/scoped_ptr.h"
24#include "webrtc/system_wrappers/interface/trace.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000025#include "webrtc/video/video_receive_stream.h"
26#include "webrtc/video/video_send_stream.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000027#include "webrtc/video_engine/include/vie_base.h"
28#include "webrtc/video_engine/include/vie_codec.h"
29#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000030
31namespace webrtc {
pbos@webrtc.orgc49d5b72013-12-05 12:11:47 +000032const char* RtpExtension::kTOffset = "urn:ietf:params:rtp-hdrext:toffset";
33const char* RtpExtension::kAbsSendTime =
34 "http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time";
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000035namespace internal {
36class Call : public webrtc::Call, public PacketReceiver {
37 public:
38 Call(webrtc::VideoEngine* video_engine, const Call::Config& config);
39 virtual ~Call();
40
41 virtual PacketReceiver* Receiver() OVERRIDE;
42 virtual std::vector<VideoCodec> GetVideoCodecs() OVERRIDE;
43
44 virtual VideoSendStream::Config GetDefaultSendConfig() OVERRIDE;
45
pbos@webrtc.org5a636552013-11-20 10:40:25 +000046 virtual VideoSendStream* CreateVideoSendStream(
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000047 const VideoSendStream::Config& config) OVERRIDE;
48
pbos@webrtc.org2c46f8d2013-11-21 13:49:43 +000049 virtual void DestroyVideoSendStream(webrtc::VideoSendStream* send_stream)
50 OVERRIDE;
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000051
52 virtual VideoReceiveStream::Config GetDefaultReceiveConfig() OVERRIDE;
53
pbos@webrtc.org5a636552013-11-20 10:40:25 +000054 virtual VideoReceiveStream* CreateVideoReceiveStream(
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000055 const VideoReceiveStream::Config& config) OVERRIDE;
56
pbos@webrtc.org2c46f8d2013-11-21 13:49:43 +000057 virtual void DestroyVideoReceiveStream(
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000058 webrtc::VideoReceiveStream* receive_stream) OVERRIDE;
59
60 virtual uint32_t SendBitrateEstimate() OVERRIDE;
61 virtual uint32_t ReceiveBitrateEstimate() OVERRIDE;
62
63 virtual bool DeliverPacket(const uint8_t* packet, size_t length) OVERRIDE;
64
65 private:
66 bool DeliverRtcp(const uint8_t* packet, size_t length);
67 bool DeliverRtp(const RTPHeader& header,
68 const uint8_t* packet,
69 size_t length);
70
71 Call::Config config_;
72
73 std::map<uint32_t, VideoReceiveStream*> receive_ssrcs_;
74 scoped_ptr<RWLockWrapper> receive_lock_;
75
76 std::map<uint32_t, VideoSendStream*> send_ssrcs_;
77 scoped_ptr<RWLockWrapper> send_lock_;
78
79 scoped_ptr<RtpHeaderParser> rtp_header_parser_;
80
81 webrtc::VideoEngine* video_engine_;
82 ViERTP_RTCP* rtp_rtcp_;
83 ViECodec* codec_;
84
85 DISALLOW_COPY_AND_ASSIGN(Call);
86};
pbos@webrtc.orgc49d5b72013-12-05 12:11:47 +000087} // namespace internal
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +000088
pbos@webrtc.orgde74b642013-10-02 13:36:09 +000089class TraceDispatcher : public TraceCallback {
90 public:
91 TraceDispatcher()
92 : crit_(CriticalSectionWrapper::CreateCriticalSection()),
pbos@webrtc.org9b5c8072013-10-02 16:22:18 +000093 initialized_(false),
pbos@webrtc.orgde74b642013-10-02 13:36:09 +000094 filter_(kTraceNone) {}
95
pbos@webrtc.org9b5c8072013-10-02 16:22:18 +000096 ~TraceDispatcher() {
97 if (initialized_) {
98 Trace::ReturnTrace();
99 VideoEngine::SetTraceCallback(NULL);
100 }
101 }
102
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000103 virtual void Print(TraceLevel level,
104 const char* message,
105 int length) OVERRIDE {
106 CriticalSectionScoped lock(crit_.get());
107 for (std::map<Call*, Call::Config*>::iterator it = callbacks_.begin();
108 it != callbacks_.end();
109 ++it) {
110 if ((level & it->second->trace_filter) != kTraceNone)
111 it->second->trace_callback->Print(level, message, length);
112 }
113 }
114
115 void RegisterCallback(Call* call, Call::Config* config) {
116 if (config->trace_callback == NULL)
117 return;
118
119 CriticalSectionScoped lock(crit_.get());
120 callbacks_[call] = config;
121
pbos@webrtc.org9b5c8072013-10-02 16:22:18 +0000122 filter_ |= config->trace_filter;
123 if (filter_ != kTraceNone && !initialized_) {
124 initialized_ = true;
125 Trace::CreateTrace();
126 VideoEngine::SetTraceCallback(this);
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000127 }
pbos@webrtc.org9b5c8072013-10-02 16:22:18 +0000128 VideoEngine::SetTraceFilter(filter_);
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000129 }
130
131 void DeregisterCallback(Call* call) {
132 CriticalSectionScoped lock(crit_.get());
133 callbacks_.erase(call);
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000134
135 filter_ = kTraceNone;
136 for (std::map<Call*, Call::Config*>::iterator it = callbacks_.begin();
137 it != callbacks_.end();
138 ++it) {
139 filter_ |= it->second->trace_filter;
140 }
141
142 VideoEngine::SetTraceFilter(filter_);
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000143 }
144
145 private:
146 scoped_ptr<CriticalSectionWrapper> crit_;
pbos@webrtc.org9b5c8072013-10-02 16:22:18 +0000147 bool initialized_;
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000148 unsigned int filter_;
149 std::map<Call*, Call::Config*> callbacks_;
150};
151
152namespace internal {
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000153TraceDispatcher* global_trace_dispatcher = NULL;
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000154} // internal
155
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000156void CreateTraceDispatcher() {
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000157 if (internal::global_trace_dispatcher == NULL) {
158 TraceDispatcher* dispatcher = new TraceDispatcher();
159 // TODO(pbos): Atomic compare and exchange.
160 if (internal::global_trace_dispatcher == NULL) {
161 internal::global_trace_dispatcher = dispatcher;
162 } else {
163 delete dispatcher;
164 }
165 }
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000166}
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000167
stefan@webrtc.org7e9315b2013-12-04 10:24:26 +0000168Call* Call::Create(const Call::Config& config) {
169 CreateTraceDispatcher();
170
171 VideoEngine* video_engine = config.webrtc_config != NULL ?
172 VideoEngine::Create(*config.webrtc_config) : VideoEngine::Create();
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +0000173 assert(video_engine != NULL);
174
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000175 return new internal::Call(video_engine, config);
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +0000176}
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +0000177
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000178namespace internal {
179
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000180Call::Call(webrtc::VideoEngine* video_engine, const Call::Config& config)
mflodman@webrtc.org6879c8a2013-07-23 11:35:00 +0000181 : config_(config),
pbos@webrtc.org1819fd72013-06-10 13:48:26 +0000182 receive_lock_(RWLockWrapper::CreateRWLock()),
183 send_lock_(RWLockWrapper::CreateRWLock()),
pbos@webrtc.org40523702013-08-05 12:49:22 +0000184 rtp_header_parser_(RtpHeaderParser::Create()),
pbos@webrtc.org1819fd72013-06-10 13:48:26 +0000185 video_engine_(video_engine) {
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000186 assert(video_engine != NULL);
mflodman@webrtc.org6879c8a2013-07-23 11:35:00 +0000187 assert(config.send_transport != NULL);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000188
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000189 global_trace_dispatcher->RegisterCallback(this, &config_);
190
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000191 rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine_);
192 assert(rtp_rtcp_ != NULL);
193
194 codec_ = ViECodec::GetInterface(video_engine_);
195 assert(codec_ != NULL);
196}
197
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000198Call::~Call() {
pbos@webrtc.orgde74b642013-10-02 13:36:09 +0000199 global_trace_dispatcher->DeregisterCallback(this);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000200 codec_->Release();
pbos@webrtc.orgfd39e132013-08-14 13:52:52 +0000201 rtp_rtcp_->Release();
202 webrtc::VideoEngine::Delete(video_engine_);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000203}
204
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000205PacketReceiver* Call::Receiver() { return this; }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000206
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000207std::vector<VideoCodec> Call::GetVideoCodecs() {
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000208 std::vector<VideoCodec> codecs;
209
210 VideoCodec codec;
211 for (size_t i = 0; i < static_cast<size_t>(codec_->NumberOfCodecs()); ++i) {
pbos@webrtc.org16e03b72013-10-28 16:32:01 +0000212 if (codec_->GetCodec(static_cast<unsigned char>(i), codec) == 0) {
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000213 codecs.push_back(codec);
214 }
215 }
216 return codecs;
217}
218
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000219VideoSendStream::Config Call::GetDefaultSendConfig() {
pbos@webrtc.org025f4f12013-06-05 11:33:21 +0000220 VideoSendStream::Config config;
221 codec_->GetCodec(0, config.codec);
222 return config;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000223}
224
pbos@webrtc.org5a636552013-11-20 10:40:25 +0000225VideoSendStream* Call::CreateVideoSendStream(
226 const VideoSendStream::Config& config) {
pbos@webrtc.org1819fd72013-06-10 13:48:26 +0000227 assert(config.rtp.ssrcs.size() > 0);
pbos@webrtc.org13d38a12013-11-28 11:59:31 +0000228 assert(config.rtp.ssrcs.size() >= config.codec.numberOfSimulcastStreams);
pbos@webrtc.org1819fd72013-06-10 13:48:26 +0000229
pbos@webrtc.org40523702013-08-05 12:49:22 +0000230 VideoSendStream* send_stream = new VideoSendStream(
231 config_.send_transport, config_.overuse_detection, video_engine_, config);
pbos@webrtc.org1819fd72013-06-10 13:48:26 +0000232
233 WriteLockScoped write_lock(*send_lock_);
234 for (size_t i = 0; i < config.rtp.ssrcs.size(); ++i) {
235 assert(send_ssrcs_.find(config.rtp.ssrcs[i]) == send_ssrcs_.end());
236 send_ssrcs_[config.rtp.ssrcs[i]] = send_stream;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000237 }
238 return send_stream;
239}
240
pbos@webrtc.org2c46f8d2013-11-21 13:49:43 +0000241void Call::DestroyVideoSendStream(webrtc::VideoSendStream* send_stream) {
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000242 assert(send_stream != NULL);
243
244 VideoSendStream* send_stream_impl = NULL;
245 {
246 WriteLockScoped write_lock(*send_lock_);
247 for (std::map<uint32_t, VideoSendStream*>::iterator it =
248 send_ssrcs_.begin();
249 it != send_ssrcs_.end();
250 ++it) {
251 if (it->second == static_cast<VideoSendStream*>(send_stream)) {
252 send_stream_impl = it->second;
253 send_ssrcs_.erase(it);
254 break;
255 }
256 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000257 }
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000258
259 assert(send_stream_impl != NULL);
260 delete send_stream_impl;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000261}
262
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000263VideoReceiveStream::Config Call::GetDefaultReceiveConfig() {
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000264 return VideoReceiveStream::Config();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000265}
266
pbos@webrtc.org5a636552013-11-20 10:40:25 +0000267VideoReceiveStream* Call::CreateVideoReceiveStream(
pbos@webrtc.org74fa4892013-08-23 09:19:30 +0000268 const VideoReceiveStream::Config& config) {
stefan@webrtc.orgb082ade2013-11-18 11:45:11 +0000269 VideoReceiveStream* receive_stream = new VideoReceiveStream(
270 video_engine_, config, config_.send_transport, config_.voice_engine);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000271
pbos@webrtc.org1819fd72013-06-10 13:48:26 +0000272 WriteLockScoped write_lock(*receive_lock_);
pbos@webrtc.orgb613b5a2013-12-03 10:13:04 +0000273 assert(receive_ssrcs_.find(config.rtp.remote_ssrc) == receive_ssrcs_.end());
274 receive_ssrcs_[config.rtp.remote_ssrc] = receive_stream;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000275 return receive_stream;
276}
277
pbos@webrtc.org2c46f8d2013-11-21 13:49:43 +0000278void Call::DestroyVideoReceiveStream(
279 webrtc::VideoReceiveStream* receive_stream) {
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000280 assert(receive_stream != NULL);
281
282 VideoReceiveStream* receive_stream_impl = NULL;
283 {
284 WriteLockScoped write_lock(*receive_lock_);
285 for (std::map<uint32_t, VideoReceiveStream*>::iterator it =
286 receive_ssrcs_.begin();
287 it != receive_ssrcs_.end();
288 ++it) {
289 if (it->second == static_cast<VideoReceiveStream*>(receive_stream)) {
290 receive_stream_impl = it->second;
291 receive_ssrcs_.erase(it);
292 break;
293 }
294 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000295 }
pbos@webrtc.org95e51f52013-09-05 12:38:54 +0000296
297 assert(receive_stream_impl != NULL);
298 delete receive_stream_impl;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000299}
300
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000301uint32_t Call::SendBitrateEstimate() {
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000302 // TODO(pbos): Return send-bitrate estimate
303 return 0;
304}
305
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000306uint32_t Call::ReceiveBitrateEstimate() {
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000307 // TODO(pbos): Return receive-bitrate estimate
308 return 0;
309}
310
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000311bool Call::DeliverRtcp(const uint8_t* packet, size_t length) {
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000312 // TODO(pbos): Figure out what channel needs it actually.
313 // Do NOT broadcast! Also make sure it's a valid packet.
314 bool rtcp_delivered = false;
pbos@webrtc.org40523702013-08-05 12:49:22 +0000315 {
316 ReadLockScoped read_lock(*receive_lock_);
317 for (std::map<uint32_t, VideoReceiveStream*>::iterator it =
318 receive_ssrcs_.begin();
319 it != receive_ssrcs_.end();
320 ++it) {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000321 if (it->second->DeliverRtcp(packet, length))
pbos@webrtc.org40523702013-08-05 12:49:22 +0000322 rtcp_delivered = true;
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000323 }
324 }
325
pbos@webrtc.org40523702013-08-05 12:49:22 +0000326 {
327 ReadLockScoped read_lock(*send_lock_);
328 for (std::map<uint32_t, VideoSendStream*>::iterator it =
329 send_ssrcs_.begin();
330 it != send_ssrcs_.end();
331 ++it) {
pbos@webrtc.org0e63e762013-09-20 11:56:26 +0000332 if (it->second->DeliverRtcp(packet, length))
pbos@webrtc.org40523702013-08-05 12:49:22 +0000333 rtcp_delivered = true;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000334 }
335 }
336 return rtcp_delivered;
337}
338
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000339bool Call::DeliverRtp(const RTPHeader& header,
340 const uint8_t* packet,
341 size_t length) {
pbos@webrtc.org40523702013-08-05 12:49:22 +0000342 VideoReceiveStream* receiver;
343 {
344 ReadLockScoped read_lock(*receive_lock_);
345 std::map<uint32_t, VideoReceiveStream*>::iterator it =
346 receive_ssrcs_.find(header.ssrc);
347 if (it == receive_ssrcs_.end()) {
348 // TODO(pbos): Log some warning, SSRC without receiver.
349 return false;
350 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000351
pbos@webrtc.org40523702013-08-05 12:49:22 +0000352 receiver = it->second;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000353 }
pbos@webrtc.orgbbb07e62013-08-05 12:01:36 +0000354 return receiver->DeliverRtp(static_cast<const uint8_t*>(packet), length);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000355}
356
pbos@webrtc.org841c8a42013-09-09 15:04:25 +0000357bool Call::DeliverPacket(const uint8_t* packet, size_t length) {
pbos@webrtc.org40523702013-08-05 12:49:22 +0000358 // TODO(pbos): ExtensionMap if there are extensions.
359 if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length)))
360 return DeliverRtcp(packet, length);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000361
pbos@webrtc.org40523702013-08-05 12:49:22 +0000362 RTPHeader rtp_header;
363 if (!rtp_header_parser_->Parse(packet, static_cast<int>(length), &rtp_header))
364 return false;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000365
pbos@webrtc.org40523702013-08-05 12:49:22 +0000366 return DeliverRtp(rtp_header, packet, length);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000367}
368
369} // namespace internal
370} // namespace webrtc