blob: c3780fdc48435387f99fe5c5a257306df820e52b [file] [log] [blame]
pbos@webrtc.org2a9108f2013-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.orgbf6d5722013-09-09 15:04:25 +000011#include "webrtc/video_engine/internal/call.h"
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +000012
pbos@webrtc.org3f45c2e2013-08-05 16:22:53 +000013#include <assert.h>
14#include <string.h>
15
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +000016#include <map>
17#include <vector>
18
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +000019#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
20#include "webrtc/system_wrappers/interface/scoped_ptr.h"
21#include "webrtc/system_wrappers/interface/trace.h"
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +000022#include "webrtc/video_engine/include/vie_base.h"
23#include "webrtc/video_engine/include/vie_codec.h"
24#include "webrtc/video_engine/include/vie_rtp_rtcp.h"
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +000025#include "webrtc/video_engine/internal/video_receive_stream.h"
26#include "webrtc/video_engine/internal/video_send_stream.h"
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +000027
28namespace webrtc {
pbos@webrtc.orgc2014fd2013-08-14 13:52:52 +000029
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +000030class TraceDispatcher : public TraceCallback {
31 public:
32 TraceDispatcher()
33 : crit_(CriticalSectionWrapper::CreateCriticalSection()),
34 filter_(kTraceNone) {}
35
36 virtual void Print(TraceLevel level,
37 const char* message,
38 int length) OVERRIDE {
39 CriticalSectionScoped lock(crit_.get());
40 for (std::map<Call*, Call::Config*>::iterator it = callbacks_.begin();
41 it != callbacks_.end();
42 ++it) {
43 if ((level & it->second->trace_filter) != kTraceNone)
44 it->second->trace_callback->Print(level, message, length);
45 }
46 }
47
48 void RegisterCallback(Call* call, Call::Config* config) {
49 if (config->trace_callback == NULL)
50 return;
51
52 CriticalSectionScoped lock(crit_.get());
53 callbacks_[call] = config;
54
55 if ((filter_ | config->trace_filter) != filter_) {
56 if (filter_ == kTraceNone) {
57 Trace::CreateTrace();
58 VideoEngine::SetTraceCallback(this);
59 }
60 filter_ |= config->trace_filter;
61 VideoEngine::SetTraceFilter(filter_);
62 }
63 }
64
65 void DeregisterCallback(Call* call) {
66 CriticalSectionScoped lock(crit_.get());
67 callbacks_.erase(call);
68 // Return early if there was no filter, this is required to prevent
69 // returning the Trace handle more than once.
70 if (filter_ == kTraceNone)
71 return;
72
73 filter_ = kTraceNone;
74 for (std::map<Call*, Call::Config*>::iterator it = callbacks_.begin();
75 it != callbacks_.end();
76 ++it) {
77 filter_ |= it->second->trace_filter;
78 }
79
80 VideoEngine::SetTraceFilter(filter_);
81 if (filter_ == kTraceNone) {
82 VideoEngine::SetTraceCallback(NULL);
83 Trace::ReturnTrace();
84 }
85 }
86
87 private:
88 scoped_ptr<CriticalSectionWrapper> crit_;
89 unsigned int filter_;
90 std::map<Call*, Call::Config*> callbacks_;
91};
92
93namespace internal {
94 TraceDispatcher* global_trace_dispatcher = NULL;
95} // internal
96
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +000097Call* Call::Create(const Call::Config& config) {
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +000098 if (internal::global_trace_dispatcher == NULL) {
99 TraceDispatcher* dispatcher = new TraceDispatcher();
100 // TODO(pbos): Atomic compare and exchange.
101 if (internal::global_trace_dispatcher == NULL) {
102 internal::global_trace_dispatcher = dispatcher;
103 } else {
104 delete dispatcher;
105 }
106 }
107
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000108 VideoEngine* video_engine = VideoEngine::Create();
pbos@webrtc.orgc2014fd2013-08-14 13:52:52 +0000109 assert(video_engine != NULL);
110
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000111 return new internal::Call(video_engine, config);
pbos@webrtc.orgc2014fd2013-08-14 13:52:52 +0000112}
pbos@webrtc.orgc2014fd2013-08-14 13:52:52 +0000113
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000114namespace internal {
115
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000116Call::Call(webrtc::VideoEngine* video_engine, const Call::Config& config)
mflodman@webrtc.orgbf76ae22013-07-23 11:35:00 +0000117 : config_(config),
pbos@webrtc.org63988b22013-06-10 13:48:26 +0000118 receive_lock_(RWLockWrapper::CreateRWLock()),
119 send_lock_(RWLockWrapper::CreateRWLock()),
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000120 rtp_header_parser_(RtpHeaderParser::Create()),
pbos@webrtc.org63988b22013-06-10 13:48:26 +0000121 video_engine_(video_engine) {
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000122 assert(video_engine != NULL);
mflodman@webrtc.orgbf76ae22013-07-23 11:35:00 +0000123 assert(config.send_transport != NULL);
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000124
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000125 global_trace_dispatcher->RegisterCallback(this, &config_);
126
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000127 rtp_rtcp_ = ViERTP_RTCP::GetInterface(video_engine_);
128 assert(rtp_rtcp_ != NULL);
129
130 codec_ = ViECodec::GetInterface(video_engine_);
131 assert(codec_ != NULL);
132}
133
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000134Call::~Call() {
pbos@webrtc.orgb5d2d162013-10-02 13:36:09 +0000135 global_trace_dispatcher->DeregisterCallback(this);
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000136 codec_->Release();
pbos@webrtc.orgc2014fd2013-08-14 13:52:52 +0000137 rtp_rtcp_->Release();
138 webrtc::VideoEngine::Delete(video_engine_);
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000139}
140
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000141PacketReceiver* Call::Receiver() { return this; }
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000142
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000143std::vector<VideoCodec> Call::GetVideoCodecs() {
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000144 std::vector<VideoCodec> codecs;
145
146 VideoCodec codec;
147 for (size_t i = 0; i < static_cast<size_t>(codec_->NumberOfCodecs()); ++i) {
148 if (codec_->GetCodec(i, codec) == 0) {
149 codecs.push_back(codec);
150 }
151 }
152 return codecs;
153}
154
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000155VideoSendStream::Config Call::GetDefaultSendConfig() {
pbos@webrtc.org6f1c3ef2013-06-05 11:33:21 +0000156 VideoSendStream::Config config;
157 codec_->GetCodec(0, config.codec);
158 return config;
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000159}
160
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000161VideoSendStream* Call::CreateSendStream(const VideoSendStream::Config& config) {
pbos@webrtc.org63988b22013-06-10 13:48:26 +0000162 assert(config.rtp.ssrcs.size() > 0);
163 assert(config.codec.numberOfSimulcastStreams == 0 ||
164 config.codec.numberOfSimulcastStreams == config.rtp.ssrcs.size());
165
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000166 VideoSendStream* send_stream = new VideoSendStream(
167 config_.send_transport, config_.overuse_detection, video_engine_, config);
pbos@webrtc.org63988b22013-06-10 13:48:26 +0000168
169 WriteLockScoped write_lock(*send_lock_);
170 for (size_t i = 0; i < config.rtp.ssrcs.size(); ++i) {
171 assert(send_ssrcs_.find(config.rtp.ssrcs[i]) == send_ssrcs_.end());
172 send_ssrcs_[config.rtp.ssrcs[i]] = send_stream;
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000173 }
174 return send_stream;
175}
176
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000177SendStreamState* Call::DestroySendStream(webrtc::VideoSendStream* send_stream) {
pbos@webrtc.org00208582013-09-05 12:38:54 +0000178 assert(send_stream != NULL);
179
180 VideoSendStream* send_stream_impl = NULL;
181 {
182 WriteLockScoped write_lock(*send_lock_);
183 for (std::map<uint32_t, VideoSendStream*>::iterator it =
184 send_ssrcs_.begin();
185 it != send_ssrcs_.end();
186 ++it) {
187 if (it->second == static_cast<VideoSendStream*>(send_stream)) {
188 send_stream_impl = it->second;
189 send_ssrcs_.erase(it);
190 break;
191 }
192 }
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000193 }
pbos@webrtc.org00208582013-09-05 12:38:54 +0000194
195 assert(send_stream_impl != NULL);
196 delete send_stream_impl;
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000197
198 // TODO(pbos): Return its previous state
199 return NULL;
200}
201
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000202VideoReceiveStream::Config Call::GetDefaultReceiveConfig() {
pbos@webrtc.orgc1797062013-08-23 09:19:30 +0000203 return VideoReceiveStream::Config();
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000204}
205
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000206VideoReceiveStream* Call::CreateReceiveStream(
pbos@webrtc.orgc1797062013-08-23 09:19:30 +0000207 const VideoReceiveStream::Config& config) {
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000208 VideoReceiveStream* receive_stream =
209 new VideoReceiveStream(video_engine_, config, config_.send_transport);
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000210
pbos@webrtc.org63988b22013-06-10 13:48:26 +0000211 WriteLockScoped write_lock(*receive_lock_);
212 assert(receive_ssrcs_.find(config.rtp.ssrc) == receive_ssrcs_.end());
213 receive_ssrcs_[config.rtp.ssrc] = receive_stream;
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000214 return receive_stream;
215}
216
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000217void Call::DestroyReceiveStream(webrtc::VideoReceiveStream* receive_stream) {
pbos@webrtc.org00208582013-09-05 12:38:54 +0000218 assert(receive_stream != NULL);
219
220 VideoReceiveStream* receive_stream_impl = NULL;
221 {
222 WriteLockScoped write_lock(*receive_lock_);
223 for (std::map<uint32_t, VideoReceiveStream*>::iterator it =
224 receive_ssrcs_.begin();
225 it != receive_ssrcs_.end();
226 ++it) {
227 if (it->second == static_cast<VideoReceiveStream*>(receive_stream)) {
228 receive_stream_impl = it->second;
229 receive_ssrcs_.erase(it);
230 break;
231 }
232 }
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000233 }
pbos@webrtc.org00208582013-09-05 12:38:54 +0000234
235 assert(receive_stream_impl != NULL);
236 delete receive_stream_impl;
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000237}
238
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000239uint32_t Call::SendBitrateEstimate() {
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000240 // TODO(pbos): Return send-bitrate estimate
241 return 0;
242}
243
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000244uint32_t Call::ReceiveBitrateEstimate() {
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000245 // TODO(pbos): Return receive-bitrate estimate
246 return 0;
247}
248
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000249bool Call::DeliverRtcp(const uint8_t* packet, size_t length) {
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000250 // TODO(pbos): Figure out what channel needs it actually.
251 // Do NOT broadcast! Also make sure it's a valid packet.
252 bool rtcp_delivered = false;
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000253 {
254 ReadLockScoped read_lock(*receive_lock_);
255 for (std::map<uint32_t, VideoReceiveStream*>::iterator it =
256 receive_ssrcs_.begin();
257 it != receive_ssrcs_.end();
258 ++it) {
pbos@webrtc.org00112522013-09-20 11:56:26 +0000259 if (it->second->DeliverRtcp(packet, length))
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000260 rtcp_delivered = true;
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000261 }
262 }
263
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000264 {
265 ReadLockScoped read_lock(*send_lock_);
266 for (std::map<uint32_t, VideoSendStream*>::iterator it =
267 send_ssrcs_.begin();
268 it != send_ssrcs_.end();
269 ++it) {
pbos@webrtc.org00112522013-09-20 11:56:26 +0000270 if (it->second->DeliverRtcp(packet, length))
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000271 rtcp_delivered = true;
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000272 }
273 }
274 return rtcp_delivered;
275}
276
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000277bool Call::DeliverRtp(const RTPHeader& header,
278 const uint8_t* packet,
279 size_t length) {
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000280 VideoReceiveStream* receiver;
281 {
282 ReadLockScoped read_lock(*receive_lock_);
283 std::map<uint32_t, VideoReceiveStream*>::iterator it =
284 receive_ssrcs_.find(header.ssrc);
285 if (it == receive_ssrcs_.end()) {
286 // TODO(pbos): Log some warning, SSRC without receiver.
287 return false;
288 }
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000289
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000290 receiver = it->second;
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000291 }
pbos@webrtc.orgce851092013-08-05 12:01:36 +0000292 return receiver->DeliverRtp(static_cast<const uint8_t*>(packet), length);
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000293}
294
pbos@webrtc.orgbf6d5722013-09-09 15:04:25 +0000295bool Call::DeliverPacket(const uint8_t* packet, size_t length) {
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000296 // TODO(pbos): ExtensionMap if there are extensions.
297 if (RtpHeaderParser::IsRtcp(packet, static_cast<int>(length)))
298 return DeliverRtcp(packet, length);
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000299
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000300 RTPHeader rtp_header;
301 if (!rtp_header_parser_->Parse(packet, static_cast<int>(length), &rtp_header))
302 return false;
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000303
pbos@webrtc.org78ab5112013-08-05 12:49:22 +0000304 return DeliverRtp(rtp_header, packet, length);
pbos@webrtc.org2a9108f2013-05-16 12:08:03 +0000305}
306
307} // namespace internal
308} // namespace webrtc